2 * Copyright (c) 2007-2008, Novell Inc.
4 * This program is licensed under the BSD license, read LICENSE.BSD
5 * for further information
11 * SAT based dependency solver
21 #include "solver_private.h"
27 #include "solverdebug.h"
29 #include "linkedpkg.h"
31 #define RULES_BLOCK 63
34 /********************************************************************
36 * dependency check helpers
40 /*-------------------------------------------------------------------
41 * handle split provides
43 * a splitprovides dep looks like
44 * namespace:splitprovides(pkg REL_WITH path)
45 * and is only true if pkg is installed and contains the specified path.
46 * we also make sure that pkg is selected for an update, otherwise the
47 * update would always be forced onto the user.
48 * Map m is the map used when called from dep_possible.
52 solver_is_updating(Solver *solv, Id p)
54 /* check if the update rule is true */
55 Pool *pool = solv->pool;
58 if (solv->decisionmap[p] >= 0)
59 return 0; /* old package stayed */
60 r = solv->rules + solv->updaterules + (p - solv->installed->start);
61 FOR_RULELITERALS(l, pp, r)
62 if (l > 0 && l != p && solv->decisionmap[l] > 0)
68 solver_splitprovides(Solver *solv, Id dep, Map *m)
70 Pool *pool = solv->pool;
75 if (!solv->dosplitprovides || !solv->installed)
79 rd = GETRELDEP(pool, dep);
80 if (rd->flags != REL_WITH)
83 * things are a bit tricky here if pool->addedprovides == 1, because most split-provides are in
84 * a non-standard location. If we simply call pool_whatprovides, we'll drag in the complete
85 * file list. Instead we rely on pool_addfileprovides ignoring the addfileprovidesfiltered flag
86 * for installed packages and check the lazywhatprovidesq (ignoring the REL_WITH part, but
87 * we filter the package name further down anyway).
89 if (pool->addedfileprovides == 1 && !ISRELDEP(rd->evr) && !pool->whatprovides[rd->evr])
90 pp = pool_searchlazywhatprovidesq(pool, rd->evr);
92 pp = pool_whatprovides(pool, dep);
93 while ((p = pool->whatprovidesdata[pp++]) != 0)
95 /* here we have packages that provide the correct name and contain the path,
96 * now do extra filtering */
97 s = pool->solvables + p;
98 if (s->repo != solv->installed || s->name != rd->name)
100 /* check if the package is updated. if m is set, we're called from dep_possible */
101 if (m || solver_is_updating(solv, p))
108 /* mirrors solver_dep_fulfilled, but returns 2 if a new package
111 solver_dep_fulfilled_alreadyinstalled(Solver *solv, Id dep)
113 Pool *pool = solv->pool;
119 Reldep *rd = GETRELDEP(pool, dep);
120 if (rd->flags == REL_AND)
122 int r2, r1 = solver_dep_fulfilled_alreadyinstalled(solv, rd->name);
125 r2 = solver_dep_fulfilled_alreadyinstalled(solv, rd->evr);
128 return r1 == 2 || r2 == 2 ? 2 : 1;
130 if (rd->flags == REL_OR)
132 int r2, r1 = solver_dep_fulfilled_alreadyinstalled(solv, rd->name);
133 r2 = solver_dep_fulfilled_alreadyinstalled(solv, rd->evr);
136 return r1 == 2 || r2 == 2 ? 2 : 1;
138 if (rd->flags == REL_NAMESPACE && rd->name == NAMESPACE_SPLITPROVIDES)
139 return solver_splitprovides(solv, rd->evr, 0);
140 if (rd->flags == REL_NAMESPACE && solv->installsuppdepq)
142 Queue *q = solv->installsuppdepq;
144 for (i = 0; i < q->count; i++)
145 if (q->elements[i] == dep || q->elements[i] == rd->name)
150 FOR_PROVIDES(p, pp, dep)
151 if (solv->decisionmap[p] > 0)
153 Solvable *s = pool->solvables + p;
154 if (s->repo && s->repo != solv->installed)
162 solver_is_supplementing_alreadyinstalled(Solver *solv, Solvable *s)
165 supp = s->repo->idarraydata + s->supplements;
166 while ((sup = *supp++) != 0)
167 if (solver_dep_fulfilled_alreadyinstalled(solv, sup) == 2)
173 autouninstall(Solver *solv, Id *problem)
175 Pool *pool = solv->pool;
177 int lastfeature = 0, lastupdate = 0;
181 for (i = 0; (v = problem[i]) != 0; i++)
184 extraflags &= solv->job.elements[-v - 1];
185 if (v >= solv->updaterules && v < solv->updaterules_end)
187 /* check if identical to feature rule, we don't like that */
188 Rule *r = solv->rules + solv->featurerules + (v - solv->updaterules);
191 /* update rule == feature rule */
200 if (!lastupdate && !lastfeature)
202 v = lastupdate ? lastupdate : lastfeature;
203 POOL_DEBUG(SOLV_DEBUG_UNSOLVABLE, "allowuninstall disabling ");
204 solver_printruleclass(solv, SOLV_DEBUG_UNSOLVABLE, solv->rules + v);
205 solver_disableproblem(solv, v);
206 if (extraflags != -1 && (extraflags & SOLVER_CLEANDEPS) != 0 && solv->cleandepsmap.size)
208 /* add the package to the updatepkgs list, this will automatically turn
209 * on cleandeps mode */
210 Id p = solv->rules[v].p;
211 if (!solv->cleandeps_updatepkgs)
213 solv->cleandeps_updatepkgs = solv_calloc(1, sizeof(Queue));
214 queue_init(solv->cleandeps_updatepkgs);
218 int oldupdatepkgscnt = solv->cleandeps_updatepkgs->count;
219 queue_pushunique(solv->cleandeps_updatepkgs, p);
220 if (solv->cleandeps_updatepkgs->count != oldupdatepkgscnt)
221 solver_disablepolicyrules(solv);
227 /************************************************************************/
230 * enable/disable learnt rules
232 * we have enabled or disabled some of our rules. We now reenable all
233 * of our learnt rules except the ones that were learnt from rules that
237 enabledisablelearntrules(Solver *solv)
239 Pool *pool = solv->pool;
244 POOL_DEBUG(SOLV_DEBUG_SOLUTIONS, "enabledisablelearntrules called\n");
245 for (i = solv->learntrules, r = solv->rules + i; i < solv->nrules; i++, r++)
247 whyp = solv->learnt_pool.elements + solv->learnt_why.elements[i - solv->learntrules];
248 while ((why = *whyp++) != 0)
250 assert(why > 0 && why < i);
251 if (solv->rules[why].d < 0)
254 /* why != 0: we found a disabled rule, disable the learnt rule */
255 if (why && r->d >= 0)
257 IF_POOLDEBUG (SOLV_DEBUG_SOLUTIONS)
259 POOL_DEBUG(SOLV_DEBUG_SOLUTIONS, "disabling ");
260 solver_printruleclass(solv, SOLV_DEBUG_SOLUTIONS, r);
262 solver_disablerule(solv, r);
264 else if (!why && r->d < 0)
266 IF_POOLDEBUG (SOLV_DEBUG_SOLUTIONS)
268 POOL_DEBUG(SOLV_DEBUG_SOLUTIONS, "re-enabling ");
269 solver_printruleclass(solv, SOLV_DEBUG_SOLUTIONS, r);
271 solver_enablerule(solv, r);
278 * make assertion rules into decisions
280 * Go through rules and add direct assertions to the decisionqueue.
281 * If we find a conflict, disable rules and add them to problem queue.
285 makeruledecisions(Solver *solv)
287 Pool *pool = solv->pool;
292 int record_proof = 1;
294 int havedisabled = 0;
296 /* The system solvable is always installed first */
297 assert(solv->decisionq.count == 0);
298 queue_push(&solv->decisionq, SYSTEMSOLVABLE);
299 queue_push(&solv->decisionq_why, 0);
300 solv->decisionmap[SYSTEMSOLVABLE] = 1; /* installed at level '1' */
302 decisionstart = solv->decisionq.count;
305 /* if we needed to re-run, back up decisions to decisionstart */
306 while (solv->decisionq.count > decisionstart)
308 v = solv->decisionq.elements[--solv->decisionq.count];
309 --solv->decisionq_why.count;
311 solv->decisionmap[vv] = 0;
314 /* note that the ruleassertions queue is ordered */
315 for (ii = 0; ii < solv->ruleassertions.count; ii++)
317 ri = solv->ruleassertions.elements[ii];
318 r = solv->rules + ri;
320 if (havedisabled && ri >= solv->learntrules)
322 /* just started with learnt rule assertions. If we have disabled
323 * some rules, adapt the learnt rule status */
324 enabledisablelearntrules(solv);
328 if (r->d < 0 || !r->p || r->w2) /* disabled, dummy or no assertion */
331 /* do weak rules in phase 2 */
332 if (ri < solv->learntrules && solv->weakrulemap.size && MAPTST(&solv->weakrulemap, ri))
338 if (!solv->decisionmap[vv]) /* if not yet decided */
340 queue_push(&solv->decisionq, v);
341 queue_push(&solv->decisionq_why, r - solv->rules);
342 solv->decisionmap[vv] = v > 0 ? 1 : -1;
343 IF_POOLDEBUG (SOLV_DEBUG_PROPAGATE)
345 Solvable *s = solv->pool->solvables + vv;
347 POOL_DEBUG(SOLV_DEBUG_PROPAGATE, "conflicting %s (assertion)\n", pool_solvable2str(solv->pool, s));
349 POOL_DEBUG(SOLV_DEBUG_PROPAGATE, "installing %s (assertion)\n", pool_solvable2str(solv->pool, s));
354 /* check against previous decision: is there a conflict? */
355 if (v > 0 && solv->decisionmap[vv] > 0) /* ok to install */
357 if (v < 0 && solv->decisionmap[vv] < 0) /* ok to remove */
363 * The rule (r) we're currently processing says something
364 * different (v = r->p) than a previous decision (decisionmap[abs(v)])
368 if (ri >= solv->learntrules)
370 /* conflict with a learnt rule */
371 /* can happen when packages cannot be installed for multiple reasons. */
372 /* we disable the learnt rule in this case */
373 /* (XXX: we should really call analyze_unsolvable_rule here!) */
374 solver_disablerule(solv, r);
379 * find the decision which is the "opposite" of the rule
381 for (i = 0; i < solv->decisionq.count; i++)
382 if (solv->decisionq.elements[i] == -v)
384 assert(i < solv->decisionq.count); /* assert that we found it */
385 oldproblemcount = solv->problems.count;
388 * conflict with system solvable ?
390 if (v == -SYSTEMSOLVABLE)
394 queue_push(&solv->problems, solv->learnt_pool.count);
395 queue_push(&solv->learnt_pool, ri);
396 queue_push(&solv->learnt_pool, 0);
399 queue_push(&solv->problems, 0);
400 POOL_DEBUG(SOLV_DEBUG_UNSOLVABLE, "conflict with system solvable, disabling rule #%d\n", ri);
401 if (ri >= solv->jobrules && ri < solv->jobrules_end)
402 v = -(solv->ruletojob.elements[ri - solv->jobrules] + 1);
405 queue_push(&solv->problems, v);
406 queue_push(&solv->problems, 0);
407 if (solv->allowuninstall && v >= solv->featurerules && v < solv->updaterules_end)
408 solv->problems.count = oldproblemcount;
409 solver_disableproblem(solv, v);
411 break; /* start over */
414 assert(solv->decisionq_why.elements[i] > 0);
417 * conflict with a pkg rule ?
419 if (solv->decisionq_why.elements[i] < solv->pkgrules_end)
423 queue_push(&solv->problems, solv->learnt_pool.count);
424 queue_push(&solv->learnt_pool, ri);
425 queue_push(&solv->learnt_pool, solv->decisionq_why.elements[i]);
426 queue_push(&solv->learnt_pool, 0);
429 queue_push(&solv->problems, 0);
430 assert(v > 0 || v == -SYSTEMSOLVABLE);
431 POOL_DEBUG(SOLV_DEBUG_UNSOLVABLE, "conflict with pkg rule, disabling rule #%d\n", ri);
432 if (ri >= solv->jobrules && ri < solv->jobrules_end)
433 v = -(solv->ruletojob.elements[ri - solv->jobrules] + 1);
436 queue_push(&solv->problems, v);
437 queue_push(&solv->problems, 0);
438 if (solv->allowuninstall && v >= solv->featurerules && v < solv->updaterules_end)
439 solv->problems.count = oldproblemcount;
440 solver_disableproblem(solv, v);
442 break; /* start over */
446 * conflict with another job or update/feature rule
452 queue_push(&solv->problems, solv->learnt_pool.count);
453 queue_push(&solv->learnt_pool, ri);
454 queue_push(&solv->learnt_pool, solv->decisionq_why.elements[i]);
455 queue_push(&solv->learnt_pool, 0);
458 queue_push(&solv->problems, 0);
460 POOL_DEBUG(SOLV_DEBUG_UNSOLVABLE, "conflicting update/job assertions over literal %d\n", vv);
463 * push all of our rules (can only be feature or job rules)
464 * asserting this literal on the problem stack
466 for (i = solv->featurerules, rr = solv->rules + i; i < solv->learntrules; i++, rr++)
468 if (rr->d < 0 /* disabled */
469 || rr->w2) /* or no assertion */
471 if (rr->p != vv /* not affecting the literal */
474 if (solv->weakrulemap.size && MAPTST(&solv->weakrulemap, i)) /* weak: silently ignore */
477 POOL_DEBUG(SOLV_DEBUG_UNSOLVABLE, " - disabling rule #%d\n", i);
478 solver_printruleclass(solv, SOLV_DEBUG_UNSOLVABLE, solv->rules + i);
481 if (i >= solv->jobrules && i < solv->jobrules_end)
482 v = -(solv->ruletojob.elements[i - solv->jobrules] + 1);
483 queue_push(&solv->problems, v);
485 queue_push(&solv->problems, 0);
487 if (solv->allowuninstall && (v = autouninstall(solv, solv->problems.elements + oldproblemcount + 1)) != 0)
488 solv->problems.count = oldproblemcount;
490 for (i = oldproblemcount + 1; i < solv->problems.count - 1; i++)
491 solver_disableproblem(solv, solv->problems.elements[i]);
493 break; /* start over */
495 if (ii < solv->ruleassertions.count)
499 * phase 2: now do the weak assertions
501 if (!solv->weakrulemap.size)
502 break; /* no weak rules, no phase 2 */
503 for (ii = 0; ii < solv->ruleassertions.count; ii++)
505 ri = solv->ruleassertions.elements[ii];
506 r = solv->rules + ri;
507 if (r->d < 0 || r->w2) /* disabled or no assertion */
509 if (ri >= solv->learntrules || !MAPTST(&solv->weakrulemap, ri)) /* skip non-weak */
514 if (!solv->decisionmap[vv]) /* if not yet decided */
516 queue_push(&solv->decisionq, v);
517 queue_push(&solv->decisionq_why, r - solv->rules);
518 solv->decisionmap[vv] = v > 0 ? 1 : -1;
519 IF_POOLDEBUG (SOLV_DEBUG_PROPAGATE)
521 Solvable *s = solv->pool->solvables + vv;
523 POOL_DEBUG(SOLV_DEBUG_PROPAGATE, "conflicting %s (weak assertion)\n", pool_solvable2str(solv->pool, s));
525 POOL_DEBUG(SOLV_DEBUG_PROPAGATE, "installing %s (weak assertion)\n", pool_solvable2str(solv->pool, s));
529 /* check against previous decision: is there a conflict? */
530 if (v > 0 && solv->decisionmap[vv] > 0)
532 if (v < 0 && solv->decisionmap[vv] < 0)
535 POOL_DEBUG(SOLV_DEBUG_UNSOLVABLE, "assertion conflict, but I am weak, disabling ");
536 solver_printrule(solv, SOLV_DEBUG_UNSOLVABLE, r);
538 if (ri >= solv->jobrules && ri < solv->jobrules_end)
539 v = -(solv->ruletojob.elements[ri - solv->jobrules] + 1);
542 solver_disableproblem(solv, v);
544 solver_reenablepolicyrules(solv, -v);
546 break; /* start over */
548 if (ii == solv->ruleassertions.count)
549 break; /* finished! */
554 /********************************************************************/
558 /*-------------------------------------------------------------------
561 * initial setup for all watches
565 makewatches(Solver *solv)
569 int nsolvables = solv->pool->nsolvables;
571 solv_free(solv->watches);
572 /* lower half for removals, upper half for installs */
573 solv->watches = solv_calloc(2 * nsolvables, sizeof(Id));
574 for (i = 1, r = solv->rules + solv->nrules - 1; i < solv->nrules; i++, r--)
576 if (!r->w2) /* assertions do not need watches */
579 /* see addwatches_rule(solv, r) */
580 r->n1 = solv->watches[nsolvables + r->w1];
581 solv->watches[nsolvables + r->w1] = r - solv->rules;
583 r->n2 = solv->watches[nsolvables + r->w2];
584 solv->watches[nsolvables + r->w2] = r - solv->rules;
589 /*-------------------------------------------------------------------
591 * add watches (for a new learned rule)
592 * sets up watches for a single rule
594 * see also makewatches() above.
598 addwatches_rule(Solver *solv, Rule *r)
600 int nsolvables = solv->pool->nsolvables;
602 r->n1 = solv->watches[nsolvables + r->w1];
603 solv->watches[nsolvables + r->w1] = r - solv->rules;
605 r->n2 = solv->watches[nsolvables + r->w2];
606 solv->watches[nsolvables + r->w2] = r - solv->rules;
610 /********************************************************************/
616 /* shortcuts to check if a literal (positive or negative) assignment
617 * evaluates to 'true' or 'false'
619 #define DECISIONMAP_TRUE(p) ((p) > 0 ? (decisionmap[p] > 0) : (decisionmap[-p] < 0))
620 #define DECISIONMAP_FALSE(p) ((p) > 0 ? (decisionmap[p] < 0) : (decisionmap[-p] > 0))
621 #define DECISIONMAP_UNDEF(p) (decisionmap[(p) > 0 ? (p) : -(p)] == 0)
623 /*-------------------------------------------------------------------
627 * make decision and propagate to all rules
629 * Evaluate each term affected by the decision (linked through watches).
630 * If we find unit rules we make new decisions based on them.
632 * return : 0 = everything is OK
633 * rule = conflict found in this rule
637 propagate(Solver *solv, int level)
639 Pool *pool = solv->pool;
640 Id *rp, *next_rp; /* rule pointer, next rule pointer in linked list */
642 Id p, pkg, other_watch;
644 Id *decisionmap = solv->decisionmap;
645 Id *watches = solv->watches + pool->nsolvables; /* place ptr in middle */
647 POOL_DEBUG(SOLV_DEBUG_PROPAGATE, "----- propagate -----\n");
649 /* foreach non-propagated decision */
650 while (solv->propagate_index < solv->decisionq.count)
653 * 'pkg' was just decided
654 * negate because our watches trigger if literal goes FALSE
656 pkg = -solv->decisionq.elements[solv->propagate_index++];
658 IF_POOLDEBUG (SOLV_DEBUG_PROPAGATE)
660 POOL_DEBUG(SOLV_DEBUG_PROPAGATE, "propagate for decision %d level %d\n", -pkg, level);
661 solver_printruleelement(solv, SOLV_DEBUG_PROPAGATE, 0, -pkg);
664 /* foreach rule where 'pkg' is now FALSE */
665 for (rp = watches + pkg; *rp; rp = next_rp)
667 r = solv->rules + *rp;
670 /* rule is disabled, goto next */
678 IF_POOLDEBUG (SOLV_DEBUG_PROPAGATE)
680 POOL_DEBUG(SOLV_DEBUG_PROPAGATE," watch triggered ");
681 solver_printrule(solv, SOLV_DEBUG_PROPAGATE, r);
685 * 'pkg' was just decided (was set to FALSE), so this rule
688 /* find the other watch */
701 * if the other watch is true we have nothing to do
703 if (DECISIONMAP_TRUE(other_watch))
707 * The other literal is FALSE or UNDEF
713 /* Not a binary clause, try to move our watch.
715 * Go over all literals and find one that is
719 * (TRUE is also ok, in that case the rule is fulfilled)
720 * As speed matters here we do not use the FOR_RULELITERALS
723 if (r->p /* we have a 'p' */
724 && r->p != other_watch /* which is not watched */
725 && !DECISIONMAP_FALSE(r->p)) /* and not FALSE */
729 else /* go find a 'd' to make 'true' */
732 we just iterate sequentially, doing it in another order just changes the order of decisions, not the decisions itself
734 for (dp = pool->whatprovidesdata + r->d; (p = *dp++) != 0;)
736 if (p != other_watch /* which is not watched */
737 && !DECISIONMAP_FALSE(p)) /* and not FALSE */
745 * if we found some p that is UNDEF or TRUE, move
748 IF_POOLDEBUG (SOLV_DEBUG_PROPAGATE)
751 POOL_DEBUG(SOLV_DEBUG_PROPAGATE, " -> move w%d to %s\n", (pkg == r->w1 ? 1 : 2), pool_solvid2str(pool, p));
753 POOL_DEBUG(SOLV_DEBUG_PROPAGATE, " -> move w%d to !%s\n", (pkg == r->w1 ? 1 : 2), pool_solvid2str(pool, -p));
769 watches[p] = r - solv->rules;
772 /* search failed, thus all unwatched literals are FALSE */
777 * unit clause found, set literal other_watch to TRUE
780 if (DECISIONMAP_FALSE(other_watch)) /* check if literal is FALSE */
781 return r; /* eek, a conflict! */
783 IF_POOLDEBUG (SOLV_DEBUG_PROPAGATE)
785 POOL_DEBUG(SOLV_DEBUG_PROPAGATE, " unit ");
786 solver_printrule(solv, SOLV_DEBUG_PROPAGATE, r);
790 decisionmap[other_watch] = level; /* install! */
792 decisionmap[-other_watch] = -level; /* remove! */
794 queue_push(&solv->decisionq, other_watch);
795 queue_push(&solv->decisionq_why, r - solv->rules);
797 IF_POOLDEBUG (SOLV_DEBUG_PROPAGATE)
800 POOL_DEBUG(SOLV_DEBUG_PROPAGATE, " -> decided to install %s\n", pool_solvid2str(pool, other_watch));
802 POOL_DEBUG(SOLV_DEBUG_PROPAGATE, " -> decided to conflict %s\n", pool_solvid2str(pool, -other_watch));
805 } /* foreach rule involving 'pkg' */
807 } /* while we have non-decided decisions */
809 POOL_DEBUG(SOLV_DEBUG_PROPAGATE, "----- propagate end-----\n");
811 return 0; /* all is well */
815 /********************************************************************/
818 /*-------------------------------------------------------------------
821 * revert decisionq to a level
825 revert(Solver *solv, int level)
827 Pool *pool = solv->pool;
829 while (solv->decisionq.count)
831 v = solv->decisionq.elements[solv->decisionq.count - 1];
833 if (solv->decisionmap[vv] <= level && solv->decisionmap[vv] >= -level)
835 POOL_DEBUG(SOLV_DEBUG_PROPAGATE, "reverting decision %d at %d\n", v, solv->decisionmap[vv]);
836 solv->decisionmap[vv] = 0;
837 solv->decisionq.count--;
838 solv->decisionq_why.count--;
839 solv->propagate_index = solv->decisionq.count;
841 while (solv->branches.count && solv->branches.elements[solv->branches.count - 1] >= level)
842 solv->branches.count -= solv->branches.elements[solv->branches.count - 2];
843 if (solv->recommends_index > solv->decisionq.count)
844 solv->recommends_index = -1; /* rebuild recommends/suggests maps */
845 if (solv->decisionq.count < solv->decisioncnt_jobs)
846 solv->decisioncnt_jobs = 0;
847 if (solv->decisionq.count < solv->decisioncnt_update)
848 solv->decisioncnt_update = 0;
849 if (solv->decisionq.count < solv->decisioncnt_keep)
850 solv->decisioncnt_keep = 0;
851 if (solv->decisionq.count < solv->decisioncnt_resolve)
852 solv->decisioncnt_resolve = 0;
853 if (solv->decisionq.count < solv->decisioncnt_weak)
854 solv->decisioncnt_weak= 0;
855 if (solv->decisionq.count < solv->decisioncnt_orphan)
856 solv->decisioncnt_orphan = 0;
859 /*-------------------------------------------------------------------
861 * watch2onhighest - put watch2 on literal with highest level
865 watch2onhighest(Solver *solv, Rule *r)
870 d = r->d < 0 ? -r->d - 1 : r->d;
872 return; /* binary rule, both watches are set */
873 dp = solv->pool->whatprovidesdata + d;
874 while ((v = *dp++) != 0)
876 l = solv->decisionmap[v < 0 ? -v : v];
888 /*-------------------------------------------------------------------
895 analyze(Solver *solv, int level, Rule *c, Rule **lrp)
897 Pool *pool = solv->pool;
902 Map seen; /* global? */
903 Id p = 0, pp, v, vv, why;
905 int num = 0, l1num = 0;
906 int learnt_why = solv->learnt_pool.count;
907 Id *decisionmap = solv->decisionmap;
909 queue_init_buffer(&q, q_buf, sizeof(q_buf)/sizeof(*q_buf));
911 POOL_DEBUG(SOLV_DEBUG_ANALYZE, "ANALYZE at %d ----------------------\n", level);
912 map_init(&seen, pool->nsolvables);
913 idx = solv->decisionq.count;
916 IF_POOLDEBUG (SOLV_DEBUG_ANALYZE)
917 solver_printruleclass(solv, SOLV_DEBUG_ANALYZE, c);
918 queue_push(&solv->learnt_pool, c - solv->rules);
919 FOR_RULELITERALS(v, pp, c)
921 if (DECISIONMAP_TRUE(v)) /* the one true literal */
924 if (MAPTST(&seen, vv))
926 MAPSET(&seen, vv); /* mark that we also need to look at this literal */
927 l = solv->decisionmap[vv];
931 l1num++; /* need to do this one in level1 pass */
933 num++; /* need to do this one as well */
936 queue_push(&q, v); /* not level1 or conflict level, add to new rule */
942 if (!num && !--l1num)
943 break; /* all literals done */
945 /* find the next literal to investigate */
946 /* (as num + l1num > 0, we know that we'll always find one) */
950 v = solv->decisionq.elements[--idx];
952 if (MAPTST(&seen, vv))
957 if (num && --num == 0)
959 /* done with normal literals, now start level 1 literal processing */
960 p = -v; /* so that v doesn't get lost */
963 POOL_DEBUG(SOLV_DEBUG_ANALYZE, "got %d involved level 1 decisions\n", l1num);
964 /* clear non-l1 bits from seen map */
965 for (i = 0; i < q.count; i++)
968 MAPCLR(&seen, v > 0 ? v : -v);
970 /* only level 1 marks left in seen map */
971 l1num++; /* as l1retry decrements it */
975 why = solv->decisionq_why.elements[idx];
976 if (why <= 0) /* just in case, maybe for SYSTEMSOLVABLE */
978 c = solv->rules + why;
982 assert(rlevel > 0 && rlevel < level);
983 IF_POOLDEBUG (SOLV_DEBUG_ANALYZE)
985 POOL_DEBUG(SOLV_DEBUG_ANALYZE, "learned rule for level %d (am %d)\n", rlevel, level);
986 solver_printruleelement(solv, SOLV_DEBUG_ANALYZE, 0, p);
987 for (i = 0; i < q.count; i++)
988 solver_printruleelement(solv, SOLV_DEBUG_ANALYZE, 0, q.elements[i]);
990 /* push end marker on learnt reasons stack */
991 queue_push(&solv->learnt_pool, 0);
992 solv->stats_learned++;
994 POOL_DEBUG(SOLV_DEBUG_ANALYZE, "reverting decisions (level %d -> %d)\n", level, rlevel);
999 Id d = q.count ? q.elements[0] : 0;
1001 r = solver_addrule(solv, p, d, 0);
1005 Id d = pool_queuetowhatprovides(pool, &q);
1007 r = solver_addrule(solv, p, 0, d);
1009 assert(solv->learnt_why.count == (r - solv->rules) - solv->learntrules);
1010 queue_push(&solv->learnt_why, learnt_why);
1014 watch2onhighest(solv, r);
1015 addwatches_rule(solv, r);
1019 /* rule is an assertion */
1020 queue_push(&solv->ruleassertions, r - solv->rules);
1027 /*-------------------------------------------------------------------
1031 * reset all solver decisions
1032 * called after rules have been enabled/disabled
1036 solver_reset(Solver *solv)
1041 /* rewind all decisions */
1042 for (i = solv->decisionq.count - 1; i >= 0; i--)
1044 v = solv->decisionq.elements[i];
1045 solv->decisionmap[v > 0 ? v : -v] = 0;
1047 queue_empty(&solv->decisionq_why);
1048 queue_empty(&solv->decisionq);
1049 solv->recommends_index = -1;
1050 solv->propagate_index = 0;
1051 solv->decisioncnt_update = solv->decisioncnt_keep = solv->decisioncnt_resolve = solv->decisioncnt_weak = solv->decisioncnt_orphan = 0;
1052 queue_empty(&solv->branches);
1054 /* adapt learnt rule status to new set of enabled/disabled rules */
1055 enabledisablelearntrules(solv);
1059 /*-------------------------------------------------------------------
1061 * analyze_unsolvable_rule
1063 * recursion helper used by analyze_unsolvable
1067 analyze_unsolvable_rule(Solver *solv, Rule *r, Id *lastweakp, Map *rseen)
1069 Pool *pool = solv->pool;
1071 Id why = r - solv->rules;
1073 IF_POOLDEBUG (SOLV_DEBUG_UNSOLVABLE)
1074 solver_printruleclass(solv, SOLV_DEBUG_UNSOLVABLE, r);
1075 if (solv->learntrules && why >= solv->learntrules)
1077 if (MAPTST(rseen, why - solv->learntrules))
1079 MAPSET(rseen, why - solv->learntrules);
1080 for (i = solv->learnt_why.elements[why - solv->learntrules]; solv->learnt_pool.elements[i]; i++)
1081 if (solv->learnt_pool.elements[i] > 0)
1082 analyze_unsolvable_rule(solv, solv->rules + solv->learnt_pool.elements[i], lastweakp, rseen);
1085 if (solv->weakrulemap.size && MAPTST(&solv->weakrulemap, why))
1086 if (!*lastweakp || why > *lastweakp)
1088 /* do not add pkg rules to problem */
1089 if (why < solv->pkgrules_end)
1091 /* turn rule into problem */
1092 if (why >= solv->jobrules && why < solv->jobrules_end)
1093 why = -(solv->ruletojob.elements[why - solv->jobrules] + 1);
1094 /* normalize dup/infarch rules */
1095 if (why > solv->infarchrules && why < solv->infarchrules_end)
1097 Id name = pool->solvables[-solv->rules[why].p].name;
1098 while (why > solv->infarchrules && pool->solvables[-solv->rules[why - 1].p].name == name)
1101 if (why > solv->duprules && why < solv->duprules_end)
1103 Id name = pool->solvables[-solv->rules[why].p].name;
1104 while (why > solv->duprules && pool->solvables[-solv->rules[why - 1].p].name == name)
1108 /* return if problem already countains our rule */
1109 if (solv->problems.count)
1111 for (i = solv->problems.count - 1; i >= 0; i--)
1112 if (solv->problems.elements[i] == 0) /* end of last problem reached? */
1114 else if (solv->problems.elements[i] == why)
1117 queue_push(&solv->problems, why);
1121 /*-------------------------------------------------------------------
1123 * analyze_unsolvable (called from setpropagatelearn)
1125 * We know that the problem is not solvable. Record all involved
1126 * rules (i.e. the "proof") into solv->learnt_pool.
1127 * Record the learnt pool index and all non-pkg rules into
1128 * solv->problems. (Our solutions to fix the problems are to
1129 * disable those rules.)
1131 * If the proof contains at least one weak rule, we disable the
1134 * Otherwise we return -1 if disablerules is not set or disable
1135 * _all_ of the problem rules and return 0.
1137 * return: 0 - disabled some rules, try again
1142 analyze_unsolvable(Solver *solv, Rule *cr, int disablerules)
1144 Pool *pool = solv->pool;
1146 Map involved; /* global to speed things up? */
1150 Id *decisionmap = solv->decisionmap;
1151 int oldproblemcount;
1152 int oldlearntpoolcount;
1154 int record_proof = 1;
1156 POOL_DEBUG(SOLV_DEBUG_UNSOLVABLE, "ANALYZE UNSOLVABLE ----------------------\n");
1157 solv->stats_unsolvable++;
1158 oldproblemcount = solv->problems.count;
1159 oldlearntpoolcount = solv->learnt_pool.count;
1161 /* make room for proof index */
1162 /* must update it later, as analyze_unsolvable_rule would confuse
1163 * it with a rule index if we put the real value in already */
1164 queue_push(&solv->problems, 0);
1167 map_init(&involved, pool->nsolvables);
1168 map_init(&rseen, solv->learntrules ? solv->nrules - solv->learntrules : 0);
1170 queue_push(&solv->learnt_pool, r - solv->rules);
1172 analyze_unsolvable_rule(solv, r, &lastweak, &rseen);
1173 FOR_RULELITERALS(v, pp, r)
1175 if (DECISIONMAP_TRUE(v)) /* the one true literal */
1177 vv = v > 0 ? v : -v;
1178 MAPSET(&involved, vv);
1180 idx = solv->decisionq.count;
1183 v = solv->decisionq.elements[--idx];
1184 vv = v > 0 ? v : -v;
1185 if (!MAPTST(&involved, vv) || vv == SYSTEMSOLVABLE)
1187 why = solv->decisionq_why.elements[idx];
1190 queue_push(&solv->learnt_pool, why);
1191 r = solv->rules + why;
1192 analyze_unsolvable_rule(solv, r, &lastweak, &rseen);
1193 FOR_RULELITERALS(v, pp, r)
1195 if (DECISIONMAP_TRUE(v)) /* the one true literal */
1197 vv = v > 0 ? v : -v;
1198 MAPSET(&involved, vv);
1201 map_free(&involved);
1203 queue_push(&solv->problems, 0); /* mark end of this problem */
1207 /* disable last weak rule */
1208 solv->problems.count = oldproblemcount;
1209 solv->learnt_pool.count = oldlearntpoolcount;
1210 if (lastweak >= solv->jobrules && lastweak < solv->jobrules_end)
1211 v = -(solv->ruletojob.elements[lastweak - solv->jobrules] + 1);
1214 POOL_DEBUG(SOLV_DEBUG_UNSOLVABLE, "disabling ");
1215 solver_printruleclass(solv, SOLV_DEBUG_UNSOLVABLE, solv->rules + lastweak);
1216 if (lastweak >= solv->choicerules && lastweak < solv->choicerules_end)
1217 solver_disablechoicerules(solv, solv->rules + lastweak);
1218 solver_disableproblem(solv, v);
1220 solver_reenablepolicyrules(solv, -v);
1225 if (solv->allowuninstall && (v = autouninstall(solv, solv->problems.elements + oldproblemcount + 1)) != 0)
1227 solv->problems.count = oldproblemcount;
1228 solv->learnt_pool.count = oldlearntpoolcount;
1236 queue_push(&solv->learnt_pool, 0);
1237 solv->problems.elements[oldproblemcount] = oldlearntpoolcount;
1240 /* + 2: index + trailing zero */
1241 if (disablerules && oldproblemcount + 2 < solv->problems.count)
1243 for (i = oldproblemcount + 1; i < solv->problems.count - 1; i++)
1244 solver_disableproblem(solv, solv->problems.elements[i]);
1245 /* XXX: might want to enable all weak rules again */
1249 POOL_DEBUG(SOLV_DEBUG_UNSOLVABLE, "UNSOLVABLE\n");
1254 /*-------------------------------------------------------------------
1258 * add free decision (solvable to install) to decisionq
1259 * increase level and propagate decision
1260 * return if no conflict.
1262 * in conflict case, analyze conflict rule, add resulting
1263 * rule to learnt rule set, make decision from learnt
1264 * rule (always unit) and re-propagate.
1266 * returns the new solver level or -1 if unsolvable
1271 setpropagatelearn(Solver *solv, int level, Id decision, int disablerules, Id ruleid)
1273 Pool *pool = solv->pool;
1280 solv->decisionmap[decision] = level;
1282 solv->decisionmap[-decision] = -level;
1283 queue_push(&solv->decisionq, decision);
1284 queue_push(&solv->decisionq_why, -ruleid); /* <= 0 -> free decision */
1286 assert(ruleid >= 0 && level > 0);
1289 r = propagate(solv, level);
1293 return analyze_unsolvable(solv, r, disablerules);
1294 POOL_DEBUG(SOLV_DEBUG_ANALYZE, "conflict with rule #%d\n", (int)(r - solv->rules));
1295 level = analyze(solv, level, r, &lr);
1296 /* the new rule is unit by design */
1298 solv->decisionmap[decision > 0 ? decision : -decision] = decision > 0 ? level : -level;
1299 queue_push(&solv->decisionq, decision);
1300 queue_push(&solv->decisionq_why, lr - solv->rules);
1301 IF_POOLDEBUG (SOLV_DEBUG_ANALYZE)
1303 POOL_DEBUG(SOLV_DEBUG_ANALYZE, "decision: ");
1304 solver_printruleelement(solv, SOLV_DEBUG_ANALYZE, 0, decision);
1305 POOL_DEBUG(SOLV_DEBUG_ANALYZE, "new rule: ");
1306 solver_printrule(solv, SOLV_DEBUG_ANALYZE, lr);
1313 reorder_dq_for_jobrules(Solver *solv, int level, Queue *dq)
1315 Pool *pool = solv->pool;
1316 int i, j, haveone = 0, dqcount = dq->count;
1317 int decisionqcount = solv->decisionq.count;
1321 /* at the time we process jobrules the installed packages are not kept yet */
1322 /* reorder so that "future-supplemented" packages come first */
1323 FOR_REPO_SOLVABLES(solv->installed, p, s)
1325 if (MAPTST(&solv->noupdate, p - solv->installed->start))
1327 if (solv->decisionmap[p] == 0)
1329 if (s->recommends || s->suggests)
1330 queue_push(&solv->decisionq, p);
1331 solv->decisionmap[p] = level + 1;
1337 policy_update_recommendsmap(solv);
1338 for (i = 0; i < dqcount; i++)
1340 p = dq->elements[i];
1341 if (!(pool->solvables[p].repo == solv->installed || MAPTST(&solv->suggestsmap, p) || solver_is_enhancing(solv, pool->solvables + p)))
1344 dq->elements[i] = 0;
1347 dqcount = dq->count;
1348 for (i = 0; i < dqcount; i++)
1350 p = dq->elements[i];
1351 if (p && !(pool->solvables[p].repo == solv->installed || MAPTST(&solv->recommendsmap, p) || solver_is_supplementing(solv, pool->solvables + p)))
1354 dq->elements[i] = 0;
1357 for (i = j = 0; i < dq->count; i++)
1358 if (dq->elements[i])
1359 dq->elements[j++] = dq->elements[i];
1360 queue_truncate(dq, j);
1361 FOR_REPO_SOLVABLES(solv->installed, p, s)
1362 if (solv->decisionmap[p] == level + 1)
1363 solv->decisionmap[p] = 0;
1364 if (solv->decisionq.count != decisionqcount)
1366 solv->recommends_index = -1;
1367 queue_truncate(&solv->decisionq, decisionqcount);
1371 /*-------------------------------------------------------------------
1377 createbranch(Solver *solv, int level, Queue *dq, Id p, Id data)
1379 Pool *pool = solv->pool;
1381 IF_POOLDEBUG (SOLV_DEBUG_POLICY)
1383 POOL_DEBUG (SOLV_DEBUG_POLICY, "creating a branch:\n");
1384 for (i = 0; i < dq->count; i++)
1385 POOL_DEBUG (SOLV_DEBUG_POLICY, " - %s\n", pool_solvid2str(pool, dq->elements[i]));
1387 queue_push(&solv->branches, -dq->elements[0]);
1388 for (i = 1; i < dq->count; i++)
1389 queue_push(&solv->branches, dq->elements[i]);
1390 queue_push2(&solv->branches, p, data);
1391 queue_push2(&solv->branches, dq->count + 4, level);
1395 takebranch(Solver *solv, int pos, int end, const char *msg, int disablerules)
1397 Pool *pool = solv->pool;
1403 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]);
1404 for (i = end - solv->branches.elements[end - 2]; i < end - 4; i++)
1405 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]));
1408 level = solv->branches.elements[end - 1];
1409 p = solv->branches.elements[pos];
1410 solv->branches.elements[pos] = -p;
1411 POOL_DEBUG(SOLV_DEBUG_SOLVER, "%s %d -> %d with %s\n", msg, solv->decisionmap[p], level, pool_solvid2str(pool, p));
1412 /* hack: set level to zero so that revert does not remove the branch */
1413 solv->branches.elements[end - 1] = 0;
1414 revert(solv, level);
1415 solv->branches.elements[end - 1] = level;
1416 /* hack: revert simply sets the count, so we can still access the reverted elements */
1417 why = -solv->decisionq_why.elements[solv->decisionq_why.count];
1419 return setpropagatelearn(solv, level, p, disablerules, why);
1422 /*-------------------------------------------------------------------
1424 * select and install
1426 * install best package from the queue. We add an extra package, inst, if
1427 * provided. See comment in weak install section.
1429 * returns the new solver level or -1 if unsolvable
1434 selectandinstall(Solver *solv, int level, Queue *dq, int disablerules, Id ruleid)
1436 Pool *pool = solv->pool;
1440 policy_filter_unwanted(solv, dq, POLICY_MODE_CHOOSE);
1441 /* if we're resolving job rules and didn't resolve the installed packages yet,
1442 * do some special supplements ordering */
1443 if (dq->count > 1 && ruleid >= solv->jobrules && ruleid < solv->jobrules_end && solv->installed && !solv->focus_installed)
1444 reorder_dq_for_jobrules(solv, level, dq);
1445 /* if we have multiple candidates we open a branch */
1447 createbranch(solv, level, dq, 0, ruleid);
1448 p = dq->elements[0];
1449 POOL_DEBUG(SOLV_DEBUG_POLICY, "installing %s\n", pool_solvid2str(pool, p));
1450 return setpropagatelearn(solv, level, p, disablerules, ruleid);
1454 /********************************************************************/
1455 /* Main solver interface */
1458 /*-------------------------------------------------------------------
1461 * create solver structure
1463 * pool: all available solvables
1464 * installed: installed Solvables
1467 * Upon solving, rules are created to flag the Solvables
1468 * of the 'installed' Repo as installed.
1472 solver_create(Pool *pool)
1475 solv = (Solver *)solv_calloc(1, sizeof(Solver));
1477 solv->installed = pool->installed;
1479 solv->allownamechange = 1;
1481 solv->dup_allowdowngrade = 1;
1482 solv->dup_allownamechange = 1;
1483 solv->dup_allowarchchange = 1;
1484 solv->dup_allowvendorchange = 1;
1486 solv->keepexplicitobsoletes = pool->noobsoletesmultiversion ? 0 : 1;
1488 queue_init(&solv->ruletojob);
1489 queue_init(&solv->decisionq);
1490 queue_init(&solv->decisionq_why);
1491 queue_init(&solv->problems);
1492 queue_init(&solv->orphaned);
1493 queue_init(&solv->learnt_why);
1494 queue_init(&solv->learnt_pool);
1495 queue_init(&solv->branches);
1496 queue_init(&solv->weakruleq);
1497 queue_init(&solv->ruleassertions);
1498 queue_init(&solv->addedmap_deduceq);
1500 queue_push(&solv->learnt_pool, 0); /* so that 0 does not describe a proof */
1502 map_init(&solv->recommendsmap, pool->nsolvables);
1503 map_init(&solv->suggestsmap, pool->nsolvables);
1504 map_init(&solv->noupdate, solv->installed ? solv->installed->end - solv->installed->start : 0);
1505 solv->recommends_index = 0;
1507 solv->decisionmap = (Id *)solv_calloc(pool->nsolvables, sizeof(Id));
1509 solv->rules = solv_extend_resize(solv->rules, solv->nrules, sizeof(Rule), RULES_BLOCK);
1510 memset(solv->rules, 0, sizeof(Rule));
1517 resolve_jobrules(Solver *solv, int level, int disablerules, Queue *dq)
1519 Pool *pool = solv->pool;
1520 int oldlevel = level;
1524 POOL_DEBUG(SOLV_DEBUG_SOLVER, "resolving job rules\n");
1525 if (!solv->decisioncnt_jobs)
1526 solv->decisioncnt_jobs = solv->decisionq.count;
1527 for (i = solv->jobrules, r = solv->rules + i; i < solv->jobrules_end; i++, r++)
1530 if (r->d < 0) /* ignore disabled rules */
1533 FOR_RULELITERALS(l, pp, r)
1537 if (solv->decisionmap[-l] <= 0)
1542 if (solv->decisionmap[l] > 0)
1544 if (solv->decisionmap[l] == 0)
1548 if (l || !dq->count)
1550 /* prune to installed if not updating */
1551 if (dq->count > 1 && solv->installed && !solv->updatemap_all &&
1552 !(solv->job.elements[solv->ruletojob.elements[i - solv->jobrules]] & SOLVER_ORUPDATE))
1555 for (j = k = 0; j < dq->count; j++)
1557 Solvable *s = pool->solvables + dq->elements[j];
1558 if (s->repo == solv->installed)
1560 dq->elements[k++] = dq->elements[j];
1561 if (solv->updatemap.size && MAPTST(&solv->updatemap, dq->elements[j] - solv->installed->start))
1563 k = 0; /* package wants to be updated, do not prune */
1572 level = selectandinstall(solv, level, dq, disablerules, i);
1573 if (level <= olevel)
1575 if (level == olevel)
1579 continue; /* try something else */
1581 if (level < oldlevel)
1583 /* redo from start of jobrules */
1584 i = solv->jobrules - 1;
1585 r = solv->rules + i;
1591 /*-------------------------------------------------------------------
1597 queuep_free(Queue **qp)
1602 *qp = solv_free(*qp);
1606 map_zerosize(Map *m)
1616 solver_free(Solver *solv)
1618 queue_free(&solv->job);
1619 queue_free(&solv->ruletojob);
1620 queue_free(&solv->decisionq);
1621 queue_free(&solv->decisionq_why);
1622 queue_free(&solv->learnt_why);
1623 queue_free(&solv->learnt_pool);
1624 queue_free(&solv->problems);
1625 queue_free(&solv->solutions);
1626 queue_free(&solv->orphaned);
1627 queue_free(&solv->branches);
1628 queue_free(&solv->weakruleq);
1629 queue_free(&solv->ruleassertions);
1630 queue_free(&solv->addedmap_deduceq);
1631 queuep_free(&solv->cleandeps_updatepkgs);
1632 queuep_free(&solv->cleandeps_mistakes);
1633 queuep_free(&solv->update_targets);
1634 queuep_free(&solv->installsuppdepq);
1635 queuep_free(&solv->recommendscplxq);
1636 queuep_free(&solv->suggestscplxq);
1637 queuep_free(&solv->brokenorphanrules);
1639 map_free(&solv->recommendsmap);
1640 map_free(&solv->suggestsmap);
1641 map_free(&solv->noupdate);
1642 map_free(&solv->weakrulemap);
1643 map_free(&solv->multiversion);
1645 map_free(&solv->updatemap);
1646 map_free(&solv->bestupdatemap);
1647 map_free(&solv->fixmap);
1648 map_free(&solv->dupmap);
1649 map_free(&solv->dupinvolvedmap);
1650 map_free(&solv->droporphanedmap);
1651 map_free(&solv->cleandepsmap);
1653 solv_free(solv->decisionmap);
1654 solv_free(solv->rules);
1655 solv_free(solv->watches);
1656 solv_free(solv->obsoletes);
1657 solv_free(solv->obsoletes_data);
1658 solv_free(solv->specialupdaters);
1659 solv_free(solv->choicerules_ref);
1660 solv_free(solv->bestrules_pkg);
1661 solv_free(solv->yumobsrules_info);
1662 solv_free(solv->instbuddy);
1667 solver_get_flag(Solver *solv, int flag)
1671 case SOLVER_FLAG_ALLOW_DOWNGRADE:
1672 return solv->allowdowngrade;
1673 case SOLVER_FLAG_ALLOW_NAMECHANGE:
1674 return solv->allownamechange;
1675 case SOLVER_FLAG_ALLOW_ARCHCHANGE:
1676 return solv->allowarchchange;
1677 case SOLVER_FLAG_ALLOW_VENDORCHANGE:
1678 return solv->allowvendorchange;
1679 case SOLVER_FLAG_ALLOW_UNINSTALL:
1680 return solv->allowuninstall;
1681 case SOLVER_FLAG_NO_UPDATEPROVIDE:
1682 return solv->noupdateprovide;
1683 case SOLVER_FLAG_SPLITPROVIDES:
1684 return solv->dosplitprovides;
1685 case SOLVER_FLAG_IGNORE_RECOMMENDED:
1686 return solv->dontinstallrecommended;
1687 case SOLVER_FLAG_ADD_ALREADY_RECOMMENDED:
1688 return solv->addalreadyrecommended;
1689 case SOLVER_FLAG_NO_INFARCHCHECK:
1690 return solv->noinfarchcheck;
1691 case SOLVER_FLAG_KEEP_EXPLICIT_OBSOLETES:
1692 return solv->keepexplicitobsoletes;
1693 case SOLVER_FLAG_BEST_OBEY_POLICY:
1694 return solv->bestobeypolicy;
1695 case SOLVER_FLAG_NO_AUTOTARGET:
1696 return solv->noautotarget;
1697 case SOLVER_FLAG_DUP_ALLOW_DOWNGRADE:
1698 return solv->dup_allowdowngrade;
1699 case SOLVER_FLAG_DUP_ALLOW_NAMECHANGE:
1700 return solv->dup_allownamechange;
1701 case SOLVER_FLAG_DUP_ALLOW_ARCHCHANGE:
1702 return solv->dup_allowarchchange;
1703 case SOLVER_FLAG_DUP_ALLOW_VENDORCHANGE:
1704 return solv->dup_allowvendorchange;
1705 case SOLVER_FLAG_KEEP_ORPHANS:
1706 return solv->keep_orphans;
1707 case SOLVER_FLAG_BREAK_ORPHANS:
1708 return solv->break_orphans;
1709 case SOLVER_FLAG_FOCUS_INSTALLED:
1710 return solv->focus_installed;
1711 case SOLVER_FLAG_YUM_OBSOLETES:
1712 return solv->do_yum_obsoletes;
1713 case SOLVER_FLAG_NEED_UPDATEPROVIDE:
1714 return solv->needupdateprovide;
1722 solver_set_flag(Solver *solv, int flag, int value)
1724 int old = solver_get_flag(solv, flag);
1727 case SOLVER_FLAG_ALLOW_DOWNGRADE:
1728 solv->allowdowngrade = value;
1730 case SOLVER_FLAG_ALLOW_NAMECHANGE:
1731 solv->allownamechange = value;
1733 case SOLVER_FLAG_ALLOW_ARCHCHANGE:
1734 solv->allowarchchange = value;
1736 case SOLVER_FLAG_ALLOW_VENDORCHANGE:
1737 solv->allowvendorchange = value;
1739 case SOLVER_FLAG_ALLOW_UNINSTALL:
1740 solv->allowuninstall = value;
1742 case SOLVER_FLAG_NO_UPDATEPROVIDE:
1743 solv->noupdateprovide = value;
1745 case SOLVER_FLAG_SPLITPROVIDES:
1746 solv->dosplitprovides = value;
1748 case SOLVER_FLAG_IGNORE_RECOMMENDED:
1749 solv->dontinstallrecommended = value;
1751 case SOLVER_FLAG_ADD_ALREADY_RECOMMENDED:
1752 solv->addalreadyrecommended = value;
1754 case SOLVER_FLAG_NO_INFARCHCHECK:
1755 solv->noinfarchcheck = value;
1757 case SOLVER_FLAG_KEEP_EXPLICIT_OBSOLETES:
1758 solv->keepexplicitobsoletes = value;
1760 case SOLVER_FLAG_BEST_OBEY_POLICY:
1761 solv->bestobeypolicy = value;
1763 case SOLVER_FLAG_NO_AUTOTARGET:
1764 solv->noautotarget = value;
1766 case SOLVER_FLAG_DUP_ALLOW_DOWNGRADE:
1767 solv->dup_allowdowngrade = value;
1769 case SOLVER_FLAG_DUP_ALLOW_NAMECHANGE:
1770 solv->dup_allownamechange = value;
1772 case SOLVER_FLAG_DUP_ALLOW_ARCHCHANGE:
1773 solv->dup_allowarchchange = value;
1775 case SOLVER_FLAG_DUP_ALLOW_VENDORCHANGE:
1776 solv->dup_allowvendorchange = value;
1778 case SOLVER_FLAG_KEEP_ORPHANS:
1779 solv->keep_orphans = value;
1781 case SOLVER_FLAG_BREAK_ORPHANS:
1782 solv->break_orphans = value;
1784 case SOLVER_FLAG_FOCUS_INSTALLED:
1785 solv->focus_installed = value;
1787 case SOLVER_FLAG_YUM_OBSOLETES:
1788 solv->do_yum_obsoletes = value;
1790 case SOLVER_FLAG_NEED_UPDATEPROVIDE:
1791 solv->needupdateprovide = value;
1800 cleandeps_check_mistakes(Solver *solv)
1802 Pool *pool = solv->pool;
1806 int mademistake = 0;
1808 if (!solv->cleandepsmap.size)
1810 /* check for mistakes */
1811 for (i = solv->installed->start; i < solv->installed->end; i++)
1813 if (!MAPTST(&solv->cleandepsmap, i - solv->installed->start))
1815 r = solv->rules + solv->featurerules + (i - solv->installed->start);
1816 /* a mistake is when the featurerule is true but the updaterule is false */
1819 FOR_RULELITERALS(p, pp, r)
1820 if (p > 0 && solv->decisionmap[p] > 0)
1823 continue; /* feature rule is not true */
1824 r = solv->rules + solv->updaterules + (i - solv->installed->start);
1827 FOR_RULELITERALS(p, pp, r)
1828 if (p > 0 && solv->decisionmap[p] > 0)
1831 continue; /* update rule is true */
1832 POOL_DEBUG(SOLV_DEBUG_SOLVER, "cleandeps mistake: ");
1833 solver_printruleclass(solv, SOLV_DEBUG_SOLVER, r);
1834 POOL_DEBUG(SOLV_DEBUG_SOLVER, "feature rule: ");
1835 solver_printruleclass(solv, SOLV_DEBUG_SOLVER, solv->rules + solv->featurerules + (i - solv->installed->start));
1836 if (!solv->cleandeps_mistakes)
1838 solv->cleandeps_mistakes = solv_calloc(1, sizeof(Queue));
1839 queue_init(solv->cleandeps_mistakes);
1841 queue_push(solv->cleandeps_mistakes, i);
1842 MAPCLR(&solv->cleandepsmap, i - solv->installed->start);
1843 solver_reenablepolicyrules_cleandeps(solv, i);
1850 prune_to_update_targets(Solver *solv, Id *cp, Queue *q)
1854 for (i = j = 0; i < q->count; i++)
1857 for (cp2 = cp; *cp2; cp2++)
1860 q->elements[j++] = p;
1864 queue_truncate(q, j);
1867 #ifdef ENABLE_COMPLEX_DEPS
1870 add_complex_recommends(Solver *solv, Id rec, Queue *dq, Map *dqmap)
1872 Pool *pool = solv->pool;
1873 int oldcnt = dq->count;
1879 printf("ADD_COMPLEX_RECOMMENDS %s\n", pool_dep2str(pool, rec));
1881 i = pool_normalize_complex_dep(pool, rec, dq, CPLXDEPS_EXPAND);
1882 if (i == 0 || i == 1)
1885 for (i = oldcnt; i < cutcnt; i++)
1888 for (; (p = dq->elements[i]) != 0; i++)
1892 if (solv->decisionmap[-p] <= 0)
1896 if (solv->decisionmap[p] > 0)
1898 queue_truncate(dq, blkcnt);
1903 if (!MAPTST(dqmap, p))
1908 if (solv->decisionmap[p] < 0)
1910 if (solv->dupmap_all && solv->installed && pool->solvables[p].repo == solv->installed && (solv->droporphanedmap_all || (solv->droporphanedmap.size && MAPTST(&solv->droporphanedmap, p - solv->installed->start))))
1915 while (dq->elements[i])
1918 queue_deleten(dq, oldcnt, cutcnt - oldcnt);
1920 if (dq->count != oldcnt)
1922 for (j = oldcnt; j < dq->count; j++)
1924 p = dq->elements[j];
1925 for (i = 0; i < j; i++)
1926 if (dq->elements[i] == p)
1928 dq->elements[j] = 0;
1932 for (i = j = oldcnt; j < dq->count; j++)
1933 if (dq->elements[j])
1934 dq->elements[i++] = dq->elements[j];
1935 queue_truncate(dq, i);
1938 printf("RETURN:\n");
1939 for (i = oldcnt; i < dq->count; i++)
1940 printf(" - %s\n", pool_solvid2str(pool, dq->elements[i]));
1945 do_complex_recommendations(Solver *solv, Id rec, Map *m, int noselected)
1947 Pool *pool = solv->pool;
1953 printf("DO_COMPLEX_RECOMMENDATIONS %s\n", pool_dep2str(pool, rec));
1956 i = pool_normalize_complex_dep(pool, rec, &dq, CPLXDEPS_EXPAND);
1957 if (i == 0 || i == 1)
1962 for (i = 0; i < dq.count; i++)
1965 for (; (p = dq.elements[i]) != 0; i++)
1969 if (solv->decisionmap[-p] <= 0)
1973 if (solv->decisionmap[p] > 0)
1978 for (i++; (p = dq.elements[i]) != 0; i++)
1979 if (p > 0 && solv->decisionmap[p] > 0)
1987 for (i = blk; (p = dq.elements[i]) != 0; i++)
1991 while (dq.elements[i])
1999 /*-------------------------------------------------------------------
2003 * all rules have been set up, now actually run the solver
2008 solver_run_sat(Solver *solv, int disablerules, int doweak)
2010 Queue dq; /* local decisionqueue */
2011 Queue dqs; /* local decisionqueue for supplements */
2017 Pool *pool = solv->pool;
2018 Id p, pp, *dp, postponed;
2019 int minimizationsteps;
2020 int installedpos = solv->installed ? solv->installed->start : 0;
2022 IF_POOLDEBUG (SOLV_DEBUG_RULE_CREATION)
2024 POOL_DEBUG (SOLV_DEBUG_RULE_CREATION, "number of rules: %d\n", solv->nrules);
2025 for (i = 1; i < solv->nrules; i++)
2026 solver_printruleclass(solv, SOLV_DEBUG_RULE_CREATION, solv->rules + i);
2029 /* start SAT algorithm */
2031 systemlevel = level + 1;
2032 POOL_DEBUG(SOLV_DEBUG_SOLVER, "solving...\n");
2038 * here's the main loop:
2039 * 1) decide assertion rules and propagate
2041 * 3) try to keep installed packages
2042 * 4) fulfill all unresolved rules
2043 * 5) install recommended packages
2044 * 6) minimalize solution if we had choices
2045 * if we encounter a problem, we rewind to a safe level and restart
2049 minimizationsteps = 0;
2053 * initial propagation of the assertions
2059 makeruledecisions(solv);
2061 if (!disablerules && solv->problems.count)
2066 POOL_DEBUG(SOLV_DEBUG_PROPAGATE, "initial propagate (propagate_index: %d; size decisionq: %d)...\n", solv->propagate_index, solv->decisionq.count);
2067 if ((r = propagate(solv, level)) != 0)
2069 level = analyze_unsolvable(solv, r, disablerules);
2072 systemlevel = level + 1;
2076 * resolve jobs first (unless focus_installed is set)
2078 if (level < systemlevel && !solv->focus_installed)
2081 level = resolve_jobrules(solv, level, disablerules, &dq);
2084 systemlevel = level + 1;
2089 * installed packages
2091 if (!solv->decisioncnt_update)
2092 solv->decisioncnt_update = solv->decisionq.count;
2093 if (level < systemlevel && solv->installed && solv->installed->nsolvables && !solv->installed->disabled)
2095 Repo *installed = solv->installed;
2098 POOL_DEBUG(SOLV_DEBUG_SOLVER, "resolving installed packages\n");
2099 /* we use two passes if we need to update packages
2100 * to create a better user experience */
2101 for (pass = solv->updatemap.size ? 0 : 1; pass < 2; pass++)
2103 int passlevel = level;
2104 Id *specialupdaters = solv->specialupdaters;
2105 if (pass == 1 && !solv->decisioncnt_keep)
2106 solv->decisioncnt_keep = solv->decisionq.count;
2107 /* start with installedpos, the position that gave us problems the last time */
2108 for (i = installedpos, n = installed->start; n < installed->end; i++, n++)
2113 if (i == installed->end)
2114 i = installed->start;
2115 s = pool->solvables + i;
2116 if (s->repo != installed)
2119 if (solv->decisionmap[i] > 0 && (!specialupdaters || !specialupdaters[i - installed->start]))
2120 continue; /* already decided */
2121 if (!pass && solv->updatemap.size && !MAPTST(&solv->updatemap, i - installed->start))
2122 continue; /* updates first */
2123 r = solv->rules + solv->updaterules + (i - installed->start);
2125 if (!rr->p || rr->d < 0) /* disabled -> look at feature rule */
2126 rr -= solv->installed->end - solv->installed->start;
2127 if (!rr->p) /* identical to update rule? */
2129 if (!rr->p && !(specialupdaters && specialupdaters[i - installed->start]))
2130 continue; /* orpaned package */
2132 /* check if we should update this package to the latest version
2133 * noupdate is set for erase jobs, in that case we want to deinstall
2134 * the installed package and not replace it with a newer version
2135 * rr->p != i is for dup jobs where the installed package cannot be kept */
2137 if (!MAPTST(&solv->noupdate, i - installed->start) && (solv->decisionmap[i] < 0 || solv->updatemap_all || (solv->updatemap.size && MAPTST(&solv->updatemap, i - installed->start)) || (rr->p && rr->p != i)))
2141 /* specialupdater with no update/feature rule */
2142 for (d = specialupdaters[i - installed->start]; (p = pool->whatprovidesdata[d++]) != 0; )
2144 if (solv->decisionmap[p] > 0)
2149 if (!solv->decisionmap[p])
2153 else if (specialupdaters && (d = specialupdaters[i - installed->start]) != 0)
2155 /* special multiversion handling, make sure best version is chosen */
2156 if (rr->p == i && solv->decisionmap[i] >= 0)
2158 while ((p = pool->whatprovidesdata[d++]) != 0)
2159 if (solv->decisionmap[p] >= 0)
2161 if (dq.count && solv->update_targets && solv->update_targets->elements[i - installed->start])
2162 prune_to_update_targets(solv, solv->update_targets->elements + solv->update_targets->elements[i - installed->start], &dq);
2165 policy_filter_unwanted(solv, &dq, POLICY_MODE_CHOOSE);
2167 if (p != i && solv->decisionmap[p] == 0)
2169 rr = solv->rules + solv->featurerules + (i - solv->installed->start);
2170 if (!rr->p) /* update rule == feature rule? */
2171 rr = rr - solv->featurerules + solv->updaterules;
2180 /* update to best package of the update rule */
2181 FOR_RULELITERALS(p, pp, rr)
2183 if (solv->decisionmap[p] > 0)
2185 dq.count = 0; /* already fulfilled */
2188 if (!solv->decisionmap[p])
2193 if (dq.count && solv->update_targets && solv->update_targets->elements[i - installed->start])
2194 prune_to_update_targets(solv, solv->update_targets->elements + solv->update_targets->elements[i - installed->start], &dq);
2195 /* install best version */
2199 level = selectandinstall(solv, level, &dq, disablerules, rr - solv->rules);
2200 if (level <= olevel)
2202 if (level < passlevel)
2203 break; /* trouble */
2205 n = installed->start; /* redo all */
2211 /* if still undecided keep package */
2212 if (solv->decisionmap[i] == 0)
2215 if (solv->cleandepsmap.size && MAPTST(&solv->cleandepsmap, i - installed->start))
2218 POOL_DEBUG(SOLV_DEBUG_POLICY, "cleandeps erasing %s\n", pool_solvid2str(pool, i));
2219 level = setpropagatelearn(solv, level, -i, disablerules, 0);
2226 POOL_DEBUG(SOLV_DEBUG_POLICY, "keeping %s\n", pool_solvid2str(pool, i));
2227 level = setpropagatelearn(solv, level, i, disablerules, r - solv->rules);
2229 if (level <= olevel)
2231 if (level < passlevel)
2232 break; /* trouble */
2234 n = installed->start; /* redo all */
2237 continue; /* retry with learnt rule */
2241 if (n < installed->end)
2243 installedpos = i; /* retry problem solvable next time */
2244 break; /* ran into trouble */
2246 installedpos = installed->start; /* reset installedpos */
2248 systemlevel = level + 1;
2250 continue; /* had trouble, retry */
2252 if (!solv->decisioncnt_keep)
2253 solv->decisioncnt_keep = solv->decisionq.count;
2255 if (level < systemlevel && solv->focus_installed)
2258 level = resolve_jobrules(solv, level, disablerules, &dq);
2261 systemlevel = level + 1;
2264 if (level < systemlevel)
2265 systemlevel = level;
2270 if (!solv->decisioncnt_resolve)
2271 solv->decisioncnt_resolve = solv->decisionq.count;
2272 POOL_DEBUG(SOLV_DEBUG_POLICY, "deciding unresolved rules\n");
2274 for (i = 1, n = 1; ; i++, n++)
2276 if (n >= solv->nrules)
2284 if (i == solv->nrules)
2286 r = solv->rules + i;
2287 if (r->d < 0) /* ignore disabled rules */
2289 if (r->p < 0) /* most common cases first */
2291 if (r->d == 0 || solv->decisionmap[-r->p] <= 0)
2298 /* binary or unary rule */
2299 /* need two positive undecided literals, r->p already checked above */
2302 if (solv->decisionmap[r->p] || solv->decisionmap[r->w2])
2304 queue_push(&dq, r->p);
2305 queue_push(&dq, r->w2);
2310 * all negative literals are installed
2311 * no positive literal is installed
2312 * i.e. the rule is not fulfilled and we
2313 * just need to decide on the positive literals
2314 * (decisionmap[-r->p] for the r->p < 0 case is already checked above)
2318 if (solv->decisionmap[r->p] > 0)
2320 if (solv->decisionmap[r->p] == 0)
2321 queue_push(&dq, r->p);
2323 dp = pool->whatprovidesdata + r->d;
2324 while ((p = *dp++) != 0)
2328 if (solv->decisionmap[-p] <= 0)
2333 if (solv->decisionmap[p] > 0)
2335 if (solv->decisionmap[p] == 0)
2342 IF_POOLDEBUG (SOLV_DEBUG_PROPAGATE)
2344 POOL_DEBUG(SOLV_DEBUG_PROPAGATE, "unfulfilled ");
2345 solver_printruleclass(solv, SOLV_DEBUG_PROPAGATE, r);
2347 /* dq.count < 2 cannot happen as this means that
2348 * the rule is unit */
2349 assert(dq.count > 1);
2351 /* prune to cleandeps packages */
2352 if (solv->cleandepsmap.size && solv->installed)
2354 Repo *installed = solv->installed;
2355 for (j = 0; j < dq.count; j++)
2356 if (pool->solvables[dq.elements[j]].repo == installed && MAPTST(&solv->cleandepsmap, dq.elements[j] - installed->start))
2360 dq.elements[0] = dq.elements[j];
2361 queue_truncate(&dq, 1);
2365 if (dq.count > 1 && postponed >= 0)
2367 policy_filter_unwanted(solv, &dq, POLICY_MODE_CHOOSE_NOREORDER);
2377 level = selectandinstall(solv, level, &dq, disablerules, r - solv->rules);
2378 if (level < systemlevel)
2379 break; /* trouble */
2380 /* something changed, so look at all rules again */
2384 if (n < solv->nrules) /* ran into trouble? */
2385 continue; /* start over */
2387 /* decide leftover cleandeps packages */
2388 if (solv->cleandepsmap.size && solv->installed)
2390 for (p = solv->installed->start; p < solv->installed->end; p++)
2392 s = pool->solvables + p;
2393 if (s->repo != solv->installed)
2395 if (solv->decisionmap[p] == 0 && MAPTST(&solv->cleandepsmap, p - solv->installed->start))
2397 POOL_DEBUG(SOLV_DEBUG_POLICY, "cleandeps erasing %s\n", pool_solvid2str(pool, p));
2399 level = setpropagatelearn(solv, level, -p, 0, 0);
2404 if (p < solv->installed->end)
2408 /* at this point we have a consistent system. now do the extras... */
2410 if (!solv->decisioncnt_weak)
2411 solv->decisioncnt_weak = solv->decisionq.count;
2416 POOL_DEBUG(SOLV_DEBUG_POLICY, "installing recommended packages\n");
2417 queue_empty(&dq); /* recommended packages */
2418 queue_empty(&dqs); /* supplemented packages */
2419 for (i = 1; i < pool->nsolvables; i++)
2421 if (solv->decisionmap[i] < 0)
2423 if (solv->decisionmap[i] > 0)
2425 /* installed, check for recommends */
2426 Id *recp, rec, pp, p;
2427 s = pool->solvables + i;
2428 if (!solv->addalreadyrecommended && s->repo == solv->installed)
2430 /* XXX need to special case AND ? */
2433 recp = s->repo->idarraydata + s->recommends;
2434 while ((rec = *recp++) != 0)
2436 #ifdef ENABLE_COMPLEX_DEPS
2437 if (pool_is_complex_dep(pool, rec))
2439 add_complex_recommends(solv, rec, &dq, 0);
2444 FOR_PROVIDES(p, pp, rec)
2446 if (solv->decisionmap[p] > 0)
2451 else if (solv->decisionmap[p] == 0)
2453 if (solv->dupmap_all && solv->installed && pool->solvables[p].repo == solv->installed && (solv->droporphanedmap_all || (solv->droporphanedmap.size && MAPTST(&solv->droporphanedmap, p - solv->installed->start))))
2455 queue_pushunique(&dq, p);
2463 s = pool->solvables + i;
2464 if (!s->supplements)
2466 if (!pool_installable(pool, s))
2468 if (!solver_is_supplementing(solv, s))
2470 if (solv->dupmap_all && solv->installed && s->repo == solv->installed && (solv->droporphanedmap_all || (solv->droporphanedmap.size && MAPTST(&solv->droporphanedmap, i - solv->installed->start))))
2472 queue_push(&dqs, i);
2476 /* filter out all packages obsoleted by installed packages */
2477 /* this is no longer needed if we have reverse obsoletes */
2478 if ((dqs.count || dq.count) && solv->installed)
2481 Id obs, *obsp, po, ppo;
2483 map_init(&obsmap, pool->nsolvables);
2484 for (p = solv->installed->start; p < solv->installed->end; p++)
2486 s = pool->solvables + p;
2487 if (s->repo != solv->installed || !s->obsoletes)
2489 if (solv->decisionmap[p] <= 0)
2491 if (solv->multiversion.size && MAPTST(&solv->multiversion, p))
2493 obsp = s->repo->idarraydata + s->obsoletes;
2494 /* foreach obsoletes */
2495 while ((obs = *obsp++) != 0)
2496 FOR_PROVIDES(po, ppo, obs)
2497 MAPSET(&obsmap, po);
2499 for (i = j = 0; i < dqs.count; i++)
2500 if (!MAPTST(&obsmap, dqs.elements[i]))
2501 dqs.elements[j++] = dqs.elements[i];
2503 for (i = j = 0; i < dq.count; i++)
2504 if (!MAPTST(&obsmap, dq.elements[i]))
2505 dq.elements[j++] = dq.elements[i];
2510 /* filter out all already supplemented packages if requested */
2511 if (!solv->addalreadyrecommended && dqs.count)
2513 /* filter out old supplements */
2514 for (i = j = 0; i < dqs.count; i++)
2516 p = dqs.elements[i];
2517 s = pool->solvables + p;
2518 if (s->supplements && solver_is_supplementing_alreadyinstalled(solv, s))
2519 dqs.elements[j++] = p;
2524 /* multiversion doesn't mix well with supplements.
2525 * filter supplemented packages where we already decided
2526 * to install a different version (see bnc#501088) */
2527 if (dqs.count && solv->multiversion.size)
2529 for (i = j = 0; i < dqs.count; i++)
2531 p = dqs.elements[i];
2532 if (MAPTST(&solv->multiversion, p))
2535 s = pool->solvables + p;
2536 FOR_PROVIDES(p2, pp2, s->name)
2537 if (solv->decisionmap[p2] > 0 && pool->solvables[p2].name == s->name)
2540 continue; /* ignore this package */
2542 dqs.elements[j++] = p;
2547 /* make dq contain both recommended and supplemented pkgs */
2550 for (i = 0; i < dqs.count; i++)
2551 queue_pushunique(&dq, dqs.elements[i]);
2557 int decisioncount = solv->decisionq.count;
2561 /* simple case, just one package. no need to choose to best version */
2564 POOL_DEBUG(SOLV_DEBUG_POLICY, "installing supplemented %s\n", pool_solvid2str(pool, p));
2566 POOL_DEBUG(SOLV_DEBUG_POLICY, "installing recommended %s\n", pool_solvid2str(pool, p));
2567 level = setpropagatelearn(solv, level, p, 0, 0);
2568 continue; /* back to main loop */
2571 /* filter packages, this gives us the best versions */
2572 policy_filter_unwanted(solv, &dq, POLICY_MODE_RECOMMEND);
2574 /* create map of result */
2575 map_init(&dqmap, pool->nsolvables);
2576 for (i = 0; i < dq.count; i++)
2577 MAPSET(&dqmap, dq.elements[i]);
2579 /* install all supplemented packages */
2580 for (i = 0; i < dqs.count; i++)
2582 p = dqs.elements[i];
2583 if (solv->decisionmap[p] || !MAPTST(&dqmap, p))
2585 POOL_DEBUG(SOLV_DEBUG_POLICY, "installing supplemented %s\n", pool_solvid2str(pool, p));
2587 level = setpropagatelearn(solv, level, p, 0, 0);
2588 if (level <= olevel)
2591 if (i < dqs.count || solv->decisionq.count < decisioncount)
2597 /* install all recommended packages */
2598 /* more work as we want to created branches if multiple
2599 * choices are valid */
2600 for (i = 0; i < decisioncount; i++)
2603 p = solv->decisionq.elements[i];
2606 s = pool->solvables + p;
2607 if (!s->repo || (!solv->addalreadyrecommended && s->repo == solv->installed))
2611 recp = s->repo->idarraydata + s->recommends;
2612 while ((rec = *recp++) != 0)
2615 #ifdef ENABLE_COMPLEX_DEPS
2616 if (pool_is_complex_dep(pool, rec))
2617 add_complex_recommends(solv, rec, &dq, &dqmap);
2620 FOR_PROVIDES(p, pp, rec)
2622 if (solv->decisionmap[p] > 0)
2627 else if (solv->decisionmap[p] == 0 && MAPTST(&dqmap, p))
2633 policy_filter_unwanted(solv, &dq, POLICY_MODE_CHOOSE);
2634 /* if we have multiple candidates we open a branch */
2636 createbranch(solv, level, &dq, s - pool->solvables, rec);
2638 POOL_DEBUG(SOLV_DEBUG_POLICY, "installing recommended %s\n", pool_solvid2str(pool, p));
2640 level = setpropagatelearn(solv, level, p, 0, 0);
2641 if (level <= olevel || solv->decisionq.count < decisioncount)
2642 break; /* we had to revert some decisions */
2645 break; /* had a problem above, quit loop */
2648 continue; /* back to main loop so that all deps are checked */
2652 if (!solv->decisioncnt_orphan)
2653 solv->decisioncnt_orphan = solv->decisionq.count;
2654 if (solv->dupmap_all && solv->installed)
2656 int installedone = 0;
2658 /* let's see if we can install some unsupported package */
2659 POOL_DEBUG(SOLV_DEBUG_SOLVER, "deciding orphaned packages\n");
2660 for (i = 0; i < solv->orphaned.count; i++)
2662 p = solv->orphaned.elements[i];
2663 if (solv->decisionmap[p])
2664 continue; /* already decided */
2665 if (solv->droporphanedmap_all)
2667 if (solv->droporphanedmap.size && MAPTST(&solv->droporphanedmap, p - solv->installed->start))
2669 POOL_DEBUG(SOLV_DEBUG_SOLVER, "keeping orphaned %s\n", pool_solvid2str(pool, p));
2671 level = setpropagatelearn(solv, level, p, 0, 0);
2676 if (installedone || i < solv->orphaned.count)
2677 continue; /* back to main loop */
2678 for (i = 0; i < solv->orphaned.count; i++)
2680 p = solv->orphaned.elements[i];
2681 if (solv->decisionmap[p])
2682 continue; /* already decided */
2683 POOL_DEBUG(SOLV_DEBUG_SOLVER, "removing orphaned %s\n", pool_solvid2str(pool, p));
2685 level = setpropagatelearn(solv, level, -p, 0, 0);
2689 if (i < solv->orphaned.count)
2690 continue; /* back to main loop */
2691 if (solv->brokenorphanrules)
2693 solver_check_brokenorphanrules(solv, &dq);
2696 policy_filter_unwanted(solv, &dq, POLICY_MODE_CHOOSE);
2697 for (i = 0; i < dq.count; i++)
2700 POOL_DEBUG(SOLV_DEBUG_POLICY, "installing orphaned dep %s\n", pool_solvid2str(pool, p));
2702 level = setpropagatelearn(solv, level, p, 0, 0);
2711 /* one final pass to make sure we decided all installed packages */
2712 if (solv->installed)
2714 for (p = solv->installed->start; p < solv->installed->end; p++)
2716 if (solv->decisionmap[p])
2717 continue; /* already decided */
2718 s = pool->solvables + p;
2719 if (s->repo != solv->installed)
2721 POOL_DEBUG(SOLV_DEBUG_SOLVER, "removing unwanted %s\n", pool_solvid2str(pool, p));
2723 level = setpropagatelearn(solv, level, -p, 0, 0);
2727 if (p < solv->installed->end)
2728 continue; /* back to main loop */
2731 if (solv->installed && solv->cleandepsmap.size && cleandeps_check_mistakes(solv))
2734 level = 0; /* restart from scratch */
2738 if (solv->solution_callback)
2740 solv->solution_callback(solv, solv->solution_callback_data);
2741 if (solv->branches.count)
2745 for (i = solv->branches.count - 1; i >= 0; i--)
2747 p = solv->branches.elements[i];
2752 i -= 3; /* skip: p data count */
2761 while (i > 0 && solv->branches.elements[i - 1] > 0)
2763 level = takebranch(solv, i, endi, "branching", disablerules);
2767 /* all branches done, we're finally finished */
2771 /* auto-minimization step */
2772 if (solv->branches.count)
2774 int endi, lasti = -1, lastiend = -1;
2775 if (solv->recommends_index < solv->decisionq.count)
2776 policy_update_recommendsmap(solv);
2777 for (endi = solv->branches.count; endi > 0;)
2779 int l, lastsi = -1, starti = endi - solv->branches.elements[endi - 2];
2780 l = solv->branches.elements[endi - 1];
2781 for (i = starti; i < endi - 4; i++)
2783 p = solv->branches.elements[i];
2786 if (solv->decisionmap[p] > l)
2793 if (lastsi < 0 && (MAPTST(&solv->recommendsmap, p) || solver_is_supplementing(solv, pool->solvables + p)))
2798 /* we have a recommended package that could not be installed */
2799 /* take it if our current selection is not recommended */
2800 for (i = starti; i < endi - 4; i++)
2802 p = -solv->branches.elements[i];
2803 if (p <= 0 || solv->decisionmap[p] != l + 1)
2805 if (!(MAPTST(&solv->recommendsmap, p) || solver_is_supplementing(solv, pool->solvables + p)))
2817 minimizationsteps++;
2818 level = takebranch(solv, lasti, lastiend, "minimizing", disablerules);
2819 continue; /* back to main loop */
2822 /* no minimization found, we're finally finished! */
2826 POOL_DEBUG(SOLV_DEBUG_STATS, "solver statistics: %d learned rules, %d unsolvable, %d minimization steps\n", solv->stats_learned, solv->stats_unsolvable, minimizationsteps);
2828 POOL_DEBUG(SOLV_DEBUG_STATS, "done solving.\n\n");
2834 solv->decisioncnt_jobs = solv->decisionq.count;
2835 solv->decisioncnt_update = solv->decisionq.count;
2836 solv->decisioncnt_keep = solv->decisionq.count;
2837 solv->decisioncnt_resolve = solv->decisionq.count;
2838 solv->decisioncnt_weak = solv->decisionq.count;
2839 solv->decisioncnt_orphan = solv->decisionq.count;
2842 solver_printdecisionq(solv, SOLV_DEBUG_RESULT);
2847 /*-------------------------------------------------------------------
2849 * remove disabled conflicts
2851 * purpose: update the decisionmap after some rules were disabled.
2852 * this is used to calculate the suggested/recommended package list.
2853 * Also returns a "removed" list to undo the discisionmap changes.
2857 removedisabledconflicts(Solver *solv, Queue *removed)
2859 Pool *pool = solv->pool;
2864 Id *decisionmap = solv->decisionmap;
2866 queue_empty(removed);
2867 for (i = 0; i < solv->decisionq.count; i++)
2869 p = solv->decisionq.elements[i];
2871 continue; /* conflicts only, please */
2872 why = solv->decisionq_why.elements[i];
2875 /* no rule involved, must be a orphan package drop */
2878 /* we never do conflicts on free decisions, so there
2879 * must have been an unit rule */
2881 r = solv->rules + why;
2882 if (r->d < 0 && decisionmap[-p])
2884 /* rule is now disabled, remove from decisionmap */
2885 POOL_DEBUG(SOLV_DEBUG_SOLVER, "removing conflict for package %s[%d]\n", pool_solvid2str(pool, -p), -p);
2886 queue_push(removed, -p);
2887 queue_push(removed, decisionmap[-p]);
2888 decisionmap[-p] = 0;
2891 if (!removed->count)
2893 /* we removed some confliced packages. some of them might still
2894 * be in conflict, so search for unit rules and re-conflict */
2896 for (i = n = 1, r = solv->rules + i; n < solv->nrules; i++, r++, n++)
2898 if (i == solv->nrules)
2901 r = solv->rules + i;
2907 if (r->p < 0 && !decisionmap[-r->p])
2913 if (r->p < 0 && decisionmap[-r->p] == 0 && DECISIONMAP_FALSE(r->w2))
2915 else if (r->w2 < 0 && decisionmap[-r->w2] == 0 && DECISIONMAP_FALSE(r->p))
2920 if (r->p < 0 && decisionmap[-r->p] == 0)
2922 if (new || DECISIONMAP_FALSE(r->p))
2924 dp = pool->whatprovidesdata + r->d;
2925 while ((p = *dp++) != 0)
2927 if (new && p == new)
2929 if (p < 0 && decisionmap[-p] == 0)
2938 else if (!DECISIONMAP_FALSE(p))
2948 POOL_DEBUG(SOLV_DEBUG_SOLVER, "re-conflicting package %s[%d]\n", pool_solvid2str(pool, -new), -new);
2949 decisionmap[-new] = -1;
2951 n = 0; /* redo all rules */
2957 undo_removedisabledconflicts(Solver *solv, Queue *removed)
2960 for (i = 0; i < removed->count; i += 2)
2961 solv->decisionmap[removed->elements[i]] = removed->elements[i + 1];
2965 /*-------------------------------------------------------------------
2967 * weaken solvable dependencies
2971 weaken_solvable_deps(Solver *solv, Id p)
2976 for (i = 1, r = solv->rules + i; i < solv->pkgrules_end; i++, r++)
2980 if ((r->d == 0 || r->d == -1) && r->w2 < 0)
2981 continue; /* conflict */
2982 queue_push(&solv->weakruleq, i);
2987 /********************************************************************/
2992 solver_calculate_multiversionmap(Pool *pool, Queue *job, Map *multiversionmap)
2995 Id how, what, select;
2997 for (i = 0; i < job->count; i += 2)
2999 how = job->elements[i];
3000 if ((how & SOLVER_JOBMASK) != SOLVER_MULTIVERSION)
3002 what = job->elements[i + 1];
3003 select = how & SOLVER_SELECTMASK;
3004 if (!multiversionmap->size)
3005 map_grow(multiversionmap, pool->nsolvables);
3006 if (select == SOLVER_SOLVABLE_ALL)
3008 FOR_POOL_SOLVABLES(p)
3009 MAPSET(multiversionmap, p);
3011 else if (select == SOLVER_SOLVABLE_REPO)
3014 Repo *repo = pool_id2repo(pool, what);
3016 FOR_REPO_SOLVABLES(repo, p, s)
3017 MAPSET(multiversionmap, p);
3019 FOR_JOB_SELECT(p, pp, select, what)
3020 MAPSET(multiversionmap, p);
3025 solver_calculate_noobsmap(Pool *pool, Queue *job, Map *multiversionmap)
3027 solver_calculate_multiversionmap(pool, job, multiversionmap);
3031 * add a rule created by a job, record job number and weak flag
3034 solver_addjobrule(Solver *solv, Id p, Id p2, Id d, Id job, int weak)
3036 solver_addrule(solv, p, p2, d);
3037 queue_push(&solv->ruletojob, job);
3039 queue_push(&solv->weakruleq, solv->nrules - 1);
3043 add_cleandeps_package(Solver *solv, Id p)
3045 if (!solv->cleandeps_updatepkgs)
3047 solv->cleandeps_updatepkgs = solv_calloc(1, sizeof(Queue));
3048 queue_init(solv->cleandeps_updatepkgs);
3050 queue_pushunique(solv->cleandeps_updatepkgs, p);
3054 add_update_target(Solver *solv, Id p, Id how)
3056 Pool *pool = solv->pool;
3057 Solvable *s = pool->solvables + p;
3058 Repo *installed = solv->installed;
3060 if (!solv->update_targets)
3062 solv->update_targets = solv_calloc(1, sizeof(Queue));
3063 queue_init(solv->update_targets);
3065 if (s->repo == installed)
3067 queue_push2(solv->update_targets, p, p);
3070 FOR_PROVIDES(pi, pip, s->name)
3072 Solvable *si = pool->solvables + pi;
3073 if (si->repo != installed || si->name != s->name)
3075 if (how & SOLVER_FORCEBEST)
3077 if (!solv->bestupdatemap.size)
3078 map_grow(&solv->bestupdatemap, installed->end - installed->start);
3079 MAPSET(&solv->bestupdatemap, pi - installed->start);
3081 if (how & SOLVER_CLEANDEPS)
3082 add_cleandeps_package(solv, pi);
3083 queue_push2(solv->update_targets, pi, p);
3084 /* check if it's ok to keep the installed package */
3085 if (s->evr == si->evr && solvable_identical(s, si))
3086 queue_push2(solv->update_targets, pi, pi);
3090 Id obs, *obsp = s->repo->idarraydata + s->obsoletes;
3091 while ((obs = *obsp++) != 0)
3093 FOR_PROVIDES(pi, pip, obs)
3095 Solvable *si = pool->solvables + pi;
3096 if (si->repo != installed)
3098 if (si->name == s->name)
3099 continue; /* already handled above */
3100 if (!pool->obsoleteusesprovides && !pool_match_nevr(pool, si, obs))
3102 if (pool->obsoleteusescolors && !pool_colormatch(pool, s, si))
3104 if (how & SOLVER_FORCEBEST)
3106 if (!solv->bestupdatemap.size)
3107 map_grow(&solv->bestupdatemap, installed->end - installed->start);
3108 MAPSET(&solv->bestupdatemap, pi - installed->start);
3110 if (how & SOLVER_CLEANDEPS)
3111 add_cleandeps_package(solv, pi);
3112 queue_push2(solv->update_targets, pi, p);
3119 transform_update_targets_sortfn(const void *ap, const void *bp, void *dp)
3129 transform_update_targets(Solver *solv)
3131 Repo *installed = solv->installed;
3132 Queue *update_targets = solv->update_targets;
3134 Id p, q, lastp, lastq;
3136 if (!update_targets->count)
3138 queue_free(update_targets);
3139 solv->update_targets = solv_free(update_targets);
3142 if (update_targets->count > 2)
3143 solv_sort(update_targets->elements, update_targets->count >> 1, 2 * sizeof(Id), transform_update_targets_sortfn, solv);
3144 queue_insertn(update_targets, 0, installed->end - installed->start, 0);
3146 for (i = j = installed->end - installed->start; i < update_targets->count; i += 2)
3148 if ((p = update_targets->elements[i]) != lastp)
3150 if (!solv->updatemap.size)
3151 map_grow(&solv->updatemap, installed->end - installed->start);
3152 MAPSET(&solv->updatemap, p - installed->start);
3153 update_targets->elements[j++] = 0; /* finish old set */
3154 update_targets->elements[p - installed->start] = j; /* start new set */
3158 if ((q = update_targets->elements[i + 1]) != lastq)
3160 update_targets->elements[j++] = q;
3164 queue_truncate(update_targets, j);
3165 queue_push(update_targets, 0); /* finish last set */
3170 addedmap2deduceq(Solver *solv, Map *addedmap)
3172 Pool *pool = solv->pool;
3177 queue_empty(&solv->addedmap_deduceq);
3178 for (i = 2, j = solv->pkgrules_end - 1; i < pool->nsolvables && j > 0; j--)
3180 r = solv->rules + j;
3183 if ((r->d == 0 || r->d == -1) && r->w2 < 0)
3186 if (!MAPTST(addedmap, p))
3188 /* should never happen, but... */
3189 if (!solv->addedmap_deduceq.count || solv->addedmap_deduceq.elements[solv->addedmap_deduceq.count - 1] != -p)
3190 queue_push(&solv->addedmap_deduceq, -p);
3194 if (MAPTST(addedmap, i))
3195 queue_push(&solv->addedmap_deduceq, i);
3199 for (; i < pool->nsolvables; i++)
3200 if (MAPTST(addedmap, i))
3201 queue_push(&solv->addedmap_deduceq, i);
3203 for (i = 2; i < pool->nsolvables; i++)
3204 if (MAPTST(addedmap, i))
3209 deduceq2addedmap(Solver *solv, Map *addedmap)
3214 for (j = solv->pkgrules_end - 1; j > 0; j--)
3216 r = solv->rules + j;
3217 if (r->d < 0 && r->p)
3218 solver_enablerule(solv, r);
3221 if ((r->d == 0 || r->d == -1) && r->w2 < 0)
3224 MAPSET(addedmap, p);
3226 for (j = 0; j < solv->addedmap_deduceq.count; j++)
3228 p = solv->addedmap_deduceq.elements[j];
3230 MAPSET(addedmap, p);
3232 MAPCLR(addedmap, p);
3236 #ifdef ENABLE_COMPLEX_DEPS
3238 add_complex_jobrules(Solver *solv, Id dep, int flags, int jobidx, int weak)
3240 Pool *pool = solv->pool;
3245 i = pool_normalize_complex_dep(pool, dep, &bq, flags | CPLXDEPS_EXPAND);
3246 if (i == 0 || i == 1)
3250 solver_addjobrule(solv, -SYSTEMSOLVABLE, 0, 0, jobidx, weak);
3253 for (i = 0; i < bq.count; i++)
3255 if (!bq.elements[i])
3257 for (j = 0; bq.elements[i + j + 1]; j++)
3260 solver_addjobrule(solv, bq.elements[i], 0, pool_ids2whatprovides(pool, bq.elements + i + 1, j), jobidx, weak);
3262 solver_addjobrule(solv, bq.elements[i], bq.elements[i + 1], 0, jobidx, weak);
3277 solver_solve(Solver *solv, Queue *job)
3279 Pool *pool = solv->pool;
3280 Repo *installed = solv->installed;
3282 int oldnrules, initialnrules;
3283 Map addedmap; /* '1' == have pkg-rules for solvable */
3284 Map installcandidatemap;
3285 Id how, what, select, name, weak, p, pp, d;
3289 int now, solve_start;
3291 int hasbestinstalljob = 0;
3293 solve_start = solv_timems(0);
3295 /* log solver options */
3296 POOL_DEBUG(SOLV_DEBUG_STATS, "solver started\n");
3297 POOL_DEBUG(SOLV_DEBUG_STATS, "dosplitprovides=%d, noupdateprovide=%d, noinfarchcheck=%d\n", solv->dosplitprovides, solv->noupdateprovide, solv->noinfarchcheck);
3298 POOL_DEBUG(SOLV_DEBUG_STATS, "allowuninstall=%d, allowdowngrade=%d, allownamechange=%d, allowarchchange=%d, allowvendorchange=%d\n", solv->allowuninstall, solv->allowdowngrade, solv->allownamechange, solv->allowarchchange, solv->allowvendorchange);
3299 POOL_DEBUG(SOLV_DEBUG_STATS, "promoteepoch=%d, forbidselfconflicts=%d\n", pool->promoteepoch, pool->forbidselfconflicts);
3300 POOL_DEBUG(SOLV_DEBUG_STATS, "obsoleteusesprovides=%d, implicitobsoleteusesprovides=%d, obsoleteusescolors=%d, implicitobsoleteusescolors=%d\n", pool->obsoleteusesprovides, pool->implicitobsoleteusesprovides, pool->obsoleteusescolors, pool->implicitobsoleteusescolors);
3301 POOL_DEBUG(SOLV_DEBUG_STATS, "dontinstallrecommended=%d, addalreadyrecommended=%d\n", solv->dontinstallrecommended, solv->addalreadyrecommended);
3303 /* create whatprovides if not already there */
3304 if (!pool->whatprovides)
3305 pool_createwhatprovides(pool);
3307 /* create obsolete index */
3308 policy_create_obsolete_index(solv);
3311 queue_free(&solv->job);
3312 queue_init_clone(&solv->job, job);
3313 solv->pooljobcnt = pool->pooljobs.count;
3314 if (pool->pooljobs.count)
3315 queue_insertn(&solv->job, 0, pool->pooljobs.count, pool->pooljobs.elements);
3318 /* free old stuff in jase we re-run a solver */
3319 queuep_free(&solv->update_targets);
3320 queuep_free(&solv->cleandeps_updatepkgs);
3321 queue_empty(&solv->ruleassertions);
3322 solv->bestrules_pkg = solv_free(solv->bestrules_pkg);
3323 solv->yumobsrules_info = solv_free(solv->yumobsrules_info);
3324 solv->choicerules_ref = solv_free(solv->choicerules_ref);
3325 if (solv->noupdate.size)
3326 map_empty(&solv->noupdate);
3327 map_zerosize(&solv->multiversion);
3328 solv->updatemap_all = 0;
3329 map_zerosize(&solv->updatemap);
3330 solv->bestupdatemap_all = 0;
3331 map_zerosize(&solv->bestupdatemap);
3332 solv->fixmap_all = 0;
3333 map_zerosize(&solv->fixmap);
3334 solv->dupmap_all = 0;
3335 map_zerosize(&solv->dupmap);
3336 map_zerosize(&solv->dupinvolvedmap);
3337 solv->droporphanedmap_all = 0;
3338 map_zerosize(&solv->droporphanedmap);
3339 map_zerosize(&solv->cleandepsmap);
3340 map_zerosize(&solv->weakrulemap);
3341 queue_empty(&solv->weakruleq);
3342 solv->watches = solv_free(solv->watches);
3343 queue_empty(&solv->ruletojob);
3344 if (solv->decisionq.count)
3345 memset(solv->decisionmap, 0, pool->nsolvables * sizeof(Id));
3346 queue_empty(&solv->decisionq);
3347 queue_empty(&solv->decisionq_why);
3348 solv->decisioncnt_jobs = solv->decisioncnt_update = solv->decisioncnt_keep = solv->decisioncnt_resolve = solv->decisioncnt_weak = solv->decisioncnt_orphan = 0;
3349 queue_empty(&solv->learnt_why);
3350 queue_empty(&solv->learnt_pool);
3351 queue_empty(&solv->branches);
3352 solv->propagate_index = 0;
3353 queue_empty(&solv->problems);
3354 queue_empty(&solv->solutions);
3355 queue_empty(&solv->orphaned);
3356 solv->stats_learned = solv->stats_unsolvable = 0;
3357 if (solv->recommends_index)
3359 map_empty(&solv->recommendsmap);
3360 map_empty(&solv->suggestsmap);
3361 queuep_free(&solv->recommendscplxq);
3362 queuep_free(&solv->suggestscplxq);
3363 solv->recommends_index = 0;
3365 queuep_free(&solv->brokenorphanrules);
3366 solv->specialupdaters = solv_free(solv->specialupdaters);
3370 * create basic rule set of all involved packages
3371 * use addedmap bitmap to make sure we don't create rules twice
3374 /* create multiversion map if needed */
3375 solver_calculate_multiversionmap(pool, job, &solv->multiversion);
3377 map_init(&addedmap, pool->nsolvables);
3378 MAPSET(&addedmap, SYSTEMSOLVABLE);
3380 map_init(&installcandidatemap, pool->nsolvables);
3383 now = solv_timems(0);
3385 * create rules for all package that could be involved with the solving
3386 * so called: pkg rules
3389 initialnrules = solv->pkgrules_end ? solv->pkgrules_end : 1;
3390 if (initialnrules > 1)
3391 deduceq2addedmap(solv, &addedmap);
3392 if (solv->nrules != initialnrules)
3393 solver_shrinkrules(solv, initialnrules);
3394 solv->nrules = initialnrules;
3395 solv->pkgrules_end = 0;
3399 /* check for update/verify jobs as they need to be known early */
3400 /* also setup the droporphaned map, we need it when creating update rules */
3401 for (i = 0; i < job->count; i += 2)
3403 how = job->elements[i];
3404 what = job->elements[i + 1];
3405 select = how & SOLVER_SELECTMASK;
3406 switch (how & SOLVER_JOBMASK)
3409 if (select == SOLVER_SOLVABLE_ALL || (select == SOLVER_SOLVABLE_REPO && installed && what == installed->repoid))
3410 solv->fixmap_all = 1;
3411 FOR_JOB_SELECT(p, pp, select, what)
3413 s = pool->solvables + p;
3414 if (s->repo != installed)
3416 if (!solv->fixmap.size)
3417 map_grow(&solv->fixmap, installed->end - installed->start);
3418 MAPSET(&solv->fixmap, p - installed->start);
3422 if (select == SOLVER_SOLVABLE_ALL)
3424 solv->updatemap_all = 1;
3425 if (how & SOLVER_FORCEBEST)
3426 solv->bestupdatemap_all = 1;
3427 if (how & SOLVER_CLEANDEPS)
3429 FOR_REPO_SOLVABLES(installed, p, s)
3430 add_cleandeps_package(solv, p);
3433 else if (select == SOLVER_SOLVABLE_REPO)
3435 Repo *repo = pool_id2repo(pool, what);
3438 if (repo == installed && !(how & SOLVER_TARGETED))
3440 solv->updatemap_all = 1;
3441 if (how & SOLVER_FORCEBEST)
3442 solv->bestupdatemap_all = 1;
3443 if (how & SOLVER_CLEANDEPS)
3445 FOR_REPO_SOLVABLES(installed, p, s)
3446 add_cleandeps_package(solv, p);
3450 if (solv->noautotarget && !(how & SOLVER_TARGETED))
3452 /* targeted update */
3453 FOR_REPO_SOLVABLES(repo, p, s)
3454 add_update_target(solv, p, how);
3458 if (!(how & SOLVER_TARGETED))
3461 FOR_JOB_SELECT(p, pp, select, what)
3463 s = pool->solvables + p;
3464 if (s->repo != installed)
3466 if (!solv->updatemap.size)
3467 map_grow(&solv->updatemap, installed->end - installed->start);
3468 MAPSET(&solv->updatemap, p - installed->start);
3469 if (how & SOLVER_FORCEBEST)
3471 if (!solv->bestupdatemap.size)
3472 map_grow(&solv->bestupdatemap, installed->end - installed->start);
3473 MAPSET(&solv->bestupdatemap, p - installed->start);
3475 if (how & SOLVER_CLEANDEPS)
3476 add_cleandeps_package(solv, p);
3479 if (!targeted || solv->noautotarget)
3482 FOR_JOB_SELECT(p, pp, select, what)
3483 add_update_target(solv, p, how);
3486 case SOLVER_DROP_ORPHANED:
3487 if (select == SOLVER_SOLVABLE_ALL || (select == SOLVER_SOLVABLE_REPO && what == installed->repoid))
3488 solv->droporphanedmap_all = 1;
3489 FOR_JOB_SELECT(p, pp, select, what)
3491 s = pool->solvables + p;
3492 if (s->repo != installed)
3494 if (!solv->droporphanedmap.size)
3495 map_grow(&solv->droporphanedmap, installed->end - installed->start);
3496 MAPSET(&solv->droporphanedmap, p - installed->start);
3504 if (solv->update_targets)
3505 transform_update_targets(solv);
3507 oldnrules = solv->nrules;
3508 FOR_REPO_SOLVABLES(installed, p, s)
3509 solver_addpkgrulesforsolvable(solv, s, &addedmap);
3510 POOL_DEBUG(SOLV_DEBUG_STATS, "added %d pkg rules for installed solvables\n", solv->nrules - oldnrules);
3511 oldnrules = solv->nrules;
3512 FOR_REPO_SOLVABLES(installed, p, s)
3513 solver_addpkgrulesforupdaters(solv, s, &addedmap, 1);
3514 POOL_DEBUG(SOLV_DEBUG_STATS, "added %d pkg rules for updaters of installed solvables\n", solv->nrules - oldnrules);
3518 * create rules for all packages involved in the job
3519 * (to be installed or removed)
3522 oldnrules = solv->nrules;
3523 for (i = 0; i < job->count; i += 2)
3525 how = job->elements[i];
3526 what = job->elements[i + 1];
3527 select = how & SOLVER_SELECTMASK;
3529 switch (how & SOLVER_JOBMASK)
3531 case SOLVER_INSTALL:
3532 FOR_JOB_SELECT(p, pp, select, what)
3534 MAPSET(&installcandidatemap, p);
3535 solver_addpkgrulesforsolvable(solv, pool->solvables + p, &addedmap);
3538 case SOLVER_DISTUPGRADE:
3539 if (select == SOLVER_SOLVABLE_ALL)
3541 solv->dupmap_all = 1;
3542 solv->updatemap_all = 1;
3543 if (how & SOLVER_FORCEBEST)
3544 solv->bestupdatemap_all = 1;
3546 if (!solv->dupmap_all || solv->allowuninstall)
3553 POOL_DEBUG(SOLV_DEBUG_STATS, "added %d pkg rules for packages involved in a job\n", solv->nrules - oldnrules);
3557 * add rules for suggests, enhances
3559 oldnrules = solv->nrules;
3560 solver_addpkgrulesforweak(solv, &addedmap);
3561 POOL_DEBUG(SOLV_DEBUG_STATS, "added %d pkg rules because of weak dependencies\n", solv->nrules - oldnrules);
3563 #ifdef ENABLE_LINKED_PKGS
3564 oldnrules = solv->nrules;
3565 solver_addpkgrulesforlinked(solv, &addedmap);
3566 POOL_DEBUG(SOLV_DEBUG_STATS, "added %d pkg rules because of linked packages\n", solv->nrules - oldnrules);
3570 * first pass done, we now have all the pkg rules we need.
3571 * unify existing rules before going over all job rules and
3573 * at this point the system is always solvable,
3574 * as an empty system (remove all packages) is a valid solution
3577 IF_POOLDEBUG (SOLV_DEBUG_STATS)
3579 int possible = 0, installable = 0;
3580 for (i = 1; i < pool->nsolvables; i++)
3582 if (pool_installable(pool, pool->solvables + i))
3584 if (MAPTST(&addedmap, i))
3587 POOL_DEBUG(SOLV_DEBUG_STATS, "%d of %d installable solvables considered for solving\n", possible, installable);
3590 if (solv->nrules > initialnrules)
3591 solver_unifyrules(solv); /* remove duplicate pkg rules */
3592 solv->pkgrules_end = solv->nrules; /* mark end of pkg rules */
3594 if (solv->nrules > initialnrules)
3595 addedmap2deduceq(solv, &addedmap); /* so that we can recreate the addedmap */
3597 POOL_DEBUG(SOLV_DEBUG_STATS, "pkg rule memory used: %d K\n", solv->nrules * (int)sizeof(Rule) / 1024);
3598 POOL_DEBUG(SOLV_DEBUG_STATS, "pkg rule creation took %d ms\n", solv_timems(now));
3600 /* create dup maps if needed. We need the maps early to create our
3603 solver_createdupmaps(solv);
3606 * create feature rules
3608 * foreach installed:
3609 * create assertion (keep installed, if no update available)
3611 * create update rule (A|update1(A)|update2(A)|...)
3613 * those are used later on to keep a version of the installed packages in
3617 solv->featurerules = solv->nrules; /* mark start of feature rules */
3620 /* foreach possibly installed solvable */
3621 for (i = installed->start, s = pool->solvables + i; i < installed->end; i++, s++)
3623 if (s->repo != installed)
3625 solver_addrule(solv, 0, 0, 0); /* create dummy rule */
3628 solver_addupdaterule(solv, s, 1); /* allow s to be updated */
3630 /* make sure we accounted for all rules */
3631 assert(solv->nrules - solv->featurerules == installed->end - installed->start);
3633 solv->featurerules_end = solv->nrules;
3636 * Add update rules for installed solvables
3638 * almost identical to feature rules
3639 * except that downgrades/archchanges/vendorchanges are not allowed
3642 solv->updaterules = solv->nrules;
3645 { /* foreach installed solvables */
3646 /* we create all update rules, but disable some later on depending on the job */
3647 for (i = installed->start, s = pool->solvables + i; i < installed->end; i++, s++)
3651 if (s->repo != installed)
3653 solver_addrule(solv, 0, 0, 0); /* create dummy rule */
3656 solver_addupdaterule(solv, s, 0); /* allowall = 0: downgrades not allowed */
3658 * check for and remove duplicate
3660 r = solv->rules + solv->nrules - 1; /* r: update rule */
3663 sr = r - (installed->end - installed->start); /* sr: feature rule */
3664 /* it's also orphaned if the feature rule consists just of the installed package */
3665 if (!solv->dupmap_all && sr->p == i && !sr->d && !sr->w2)
3666 queue_push(&solv->orphaned, i);
3667 if (!solver_rulecmp(solv, r, sr))
3668 memset(sr, 0, sizeof(*sr)); /* delete unneeded feature rule */
3670 solver_disablerule(solv, sr); /* disable feature rule for now */
3672 /* consistency check: we added a rule for _every_ installed solvable */
3673 assert(solv->nrules - solv->updaterules == installed->end - installed->start);
3675 solv->updaterules_end = solv->nrules;
3679 * now add all job rules
3682 solv->jobrules = solv->nrules;
3683 for (i = 0; i < job->count; i += 2)
3685 oldnrules = solv->nrules;
3687 if (i && i == solv->pooljobcnt)
3688 POOL_DEBUG(SOLV_DEBUG_JOB, "end of pool jobs\n");
3689 how = job->elements[i];
3690 what = job->elements[i + 1];
3691 weak = how & SOLVER_WEAK;
3692 select = how & SOLVER_SELECTMASK;
3693 switch (how & SOLVER_JOBMASK)
3695 case SOLVER_INSTALL:
3696 POOL_DEBUG(SOLV_DEBUG_JOB, "job: %sinstall %s\n", weak ? "weak " : "", solver_select2str(pool, select, what));
3697 if ((how & SOLVER_CLEANDEPS) != 0 && !solv->cleandepsmap.size && installed)
3698 map_grow(&solv->cleandepsmap, installed->end - installed->start);
3699 if (select == SOLVER_SOLVABLE)
3704 #ifdef ENABLE_COMPLEX_DEPS
3705 else if ((select == SOLVER_SOLVABLE_PROVIDES || select == SOLVER_SOLVABLE_NAME) && pool_is_complex_dep(pool, what))
3707 if (add_complex_jobrules(solv, what, select == SOLVER_SOLVABLE_NAME ? CPLXDEPS_NAME : 0, i, weak))
3708 if (how & SOLVER_FORCEBEST)
3709 hasbestinstalljob = 1;
3716 FOR_JOB_SELECT(p, pp, select, what)
3720 if (select == SOLVER_SOLVABLE_ONE_OF)
3721 break; /* ignore empty installs */
3722 /* no candidate found or unsupported, make this an impossible rule */
3723 queue_push(&q, -SYSTEMSOLVABLE);
3725 p = queue_shift(&q); /* get first candidate */
3726 d = !q.count ? 0 : pool_queuetowhatprovides(pool, &q); /* internalize */
3728 /* force install of namespace supplements hack */
3729 if (select == SOLVER_SOLVABLE_PROVIDES && !d && (p == SYSTEMSOLVABLE || p == -SYSTEMSOLVABLE) && ISRELDEP(what))
3731 Reldep *rd = GETRELDEP(pool, what);
3732 if (rd->flags == REL_NAMESPACE)
3735 if (!solv->installsuppdepq)
3737 solv->installsuppdepq = solv_calloc(1, sizeof(Queue));
3738 queue_init(solv->installsuppdepq);
3740 queue_pushunique(solv->installsuppdepq, rd->evr == 0 ? rd->name : what);
3743 solver_addjobrule(solv, p, 0, d, i, weak);
3744 if (how & SOLVER_FORCEBEST)
3745 hasbestinstalljob = 1;
3748 POOL_DEBUG(SOLV_DEBUG_JOB, "job: %s%serase %s\n", weak ? "weak " : "", how & SOLVER_CLEANDEPS ? "clean deps " : "", solver_select2str(pool, select, what));
3749 if ((how & SOLVER_CLEANDEPS) != 0 && !solv->cleandepsmap.size && installed)
3750 map_grow(&solv->cleandepsmap, installed->end - installed->start);
3751 /* specific solvable: by id or by nevra */
3752 name = (select == SOLVER_SOLVABLE || (select == SOLVER_SOLVABLE_NAME && ISRELDEP(what))) ? 0 : -1;
3753 if (select == SOLVER_SOLVABLE_ALL) /* hmmm ;) */
3755 FOR_POOL_SOLVABLES(p)
3756 solver_addjobrule(solv, -p, 0, 0, i, weak);
3758 else if (select == SOLVER_SOLVABLE_REPO)
3760 Repo *repo = pool_id2repo(pool, what);
3762 FOR_REPO_SOLVABLES(repo, p, s)
3763 solver_addjobrule(solv, -p, 0, 0, i, weak);
3765 #ifdef ENABLE_COMPLEX_DEPS
3766 else if ((select == SOLVER_SOLVABLE_PROVIDES || select == SOLVER_SOLVABLE_NAME) && pool_is_complex_dep(pool, what))
3768 /* no special "erase a specific solvable" handling? */
3769 add_complex_jobrules(solv, what, select == SOLVER_SOLVABLE_NAME ? (CPLXDEPS_NAME | CPLXDEPS_TODNF | CPLXDEPS_INVERT) : (CPLXDEPS_TODNF | CPLXDEPS_INVERT), i, weak);
3773 FOR_JOB_SELECT(p, pp, select, what)
3775 s = pool->solvables + p;
3776 if (installed && s->repo == installed)
3777 name = !name ? s->name : -1;
3778 solver_addjobrule(solv, -p, 0, 0, i, weak);
3780 /* special case for "erase a specific solvable": we also
3781 * erase all other solvables with that name, so that they
3782 * don't get picked up as replacement.
3783 * name is > 0 if exactly one installed solvable matched.
3785 /* XXX: look also at packages that obsolete this package? */
3790 FOR_PROVIDES(p, pp, name)
3792 s = pool->solvables + p;
3793 if (s->name != name)
3795 /* keep other versions installed */
3796 if (s->repo == installed)
3798 /* keep installcandidates of other jobs */
3799 if (MAPTST(&installcandidatemap, p))
3801 /* don't add the same rule twice */
3802 for (j = oldnrules; j < k; j++)
3803 if (solv->rules[j].p == -p)
3806 solver_addjobrule(solv, -p, 0, 0, i, weak); /* remove by id */
3812 POOL_DEBUG(SOLV_DEBUG_JOB, "job: %supdate %s\n", weak ? "weak " : "", solver_select2str(pool, select, what));
3815 POOL_DEBUG(SOLV_DEBUG_JOB, "job: %sverify %s\n", weak ? "weak " : "", solver_select2str(pool, select, what));
3817 case SOLVER_WEAKENDEPS:
3818 POOL_DEBUG(SOLV_DEBUG_JOB, "job: %sweaken deps %s\n", weak ? "weak " : "", solver_select2str(pool, select, what));
3819 if (select != SOLVER_SOLVABLE)
3821 s = pool->solvables + what;
3822 weaken_solvable_deps(solv, what);
3824 case SOLVER_MULTIVERSION:
3825 POOL_DEBUG(SOLV_DEBUG_JOB, "job: %smultiversion %s\n", weak ? "weak " : "", solver_select2str(pool, select, what));
3828 POOL_DEBUG(SOLV_DEBUG_JOB, "job: %slock %s\n", weak ? "weak " : "", solver_select2str(pool, select, what));
3829 if (select == SOLVER_SOLVABLE_ALL)
3831 FOR_POOL_SOLVABLES(p)
3832 solver_addjobrule(solv, installed && pool->solvables[p].repo == installed ? p : -p, 0, 0, i, weak);
3834 else if (select == SOLVER_SOLVABLE_REPO)
3836 Repo *repo = pool_id2repo(pool, what);
3838 FOR_REPO_SOLVABLES(repo, p, s)
3839 solver_addjobrule(solv, installed && pool->solvables[p].repo == installed ? p : -p, 0, 0, i, weak);
3841 FOR_JOB_SELECT(p, pp, select, what)
3842 solver_addjobrule(solv, installed && pool->solvables[p].repo == installed ? p : -p, 0, 0, i, weak);
3844 case SOLVER_DISTUPGRADE:
3845 POOL_DEBUG(SOLV_DEBUG_JOB, "job: distupgrade %s\n", solver_select2str(pool, select, what));
3847 case SOLVER_DROP_ORPHANED:
3848 POOL_DEBUG(SOLV_DEBUG_JOB, "job: drop orphaned %s\n", solver_select2str(pool, select, what));
3850 case SOLVER_USERINSTALLED:
3851 POOL_DEBUG(SOLV_DEBUG_JOB, "job: user installed %s\n", solver_select2str(pool, select, what));
3854 POOL_DEBUG(SOLV_DEBUG_JOB, "job: unknown job\n");
3858 IF_POOLDEBUG (SOLV_DEBUG_JOB)
3861 if (solv->nrules == oldnrules)
3862 POOL_DEBUG(SOLV_DEBUG_JOB, " - no rule created\n");
3863 for (j = oldnrules; j < solv->nrules; j++)
3865 POOL_DEBUG(SOLV_DEBUG_JOB, " - job ");
3866 solver_printrule(solv, SOLV_DEBUG_JOB, solv->rules + j);
3870 assert(solv->ruletojob.count == solv->nrules - solv->jobrules);
3871 solv->jobrules_end = solv->nrules;
3873 /* now create infarch and dup rules */
3874 if (!solv->noinfarchcheck)
3876 solver_addinfarchrules(solv, &addedmap);
3878 if (pool->implicitobsoleteusescolors)
3880 /* currently doesn't work well with infarch rules, so make
3882 for (i = solv->infarchrules; i < solv->infarchrules_end; i++)
3883 queue_push(&solv->weakruleq, i);
3888 solv->infarchrules = solv->infarchrules_end = solv->nrules;
3891 solver_addduprules(solv, &addedmap);
3893 solv->duprules = solv->duprules_end = solv->nrules;
3895 if (solv->bestupdatemap_all || solv->bestupdatemap.size || hasbestinstalljob)
3896 solver_addbestrules(solv, hasbestinstalljob);
3898 solv->bestrules = solv->bestrules_end = solv->nrules;
3901 solver_freedupmaps(solv); /* no longer needed */
3903 if (solv->do_yum_obsoletes)
3904 solver_addyumobsrules(solv);
3906 solv->yumobsrules = solv->yumobsrules_end = solv->nrules;
3909 solver_addchoicerules(solv);
3911 solv->choicerules = solv->choicerules_end = solv->nrules;
3915 for (i = solv->featurerules; i < solv->nrules; i++)
3916 solver_printruleclass(solv, SOLV_DEBUG_RESULT, solv->rules + i);
3918 /* all rules created
3919 * --------------------------------------------------------------
3920 * prepare for solving
3923 /* free unneeded memory */
3924 map_free(&addedmap);
3925 map_free(&installcandidatemap);
3928 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\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);
3929 POOL_DEBUG(SOLV_DEBUG_STATS, "overall rule memory used: %d K\n", solv->nrules * (int)sizeof(Rule) / 1024);
3931 /* create weak map */
3932 if (solv->weakruleq.count)
3934 map_grow(&solv->weakrulemap, solv->nrules);
3935 for (i = 0; i < solv->weakruleq.count; i++)
3937 p = solv->weakruleq.elements[i];
3938 MAPSET(&solv->weakrulemap, p);
3942 /* enable cleandepsmap creation if we have updatepkgs */
3943 if (solv->cleandeps_updatepkgs && !solv->cleandepsmap.size)
3944 map_grow(&solv->cleandepsmap, installed->end - installed->start);
3946 if (solv->cleandeps_mistakes)
3948 queue_free(solv->cleandeps_mistakes);
3949 solv->cleandeps_mistakes = solv_free(solv->cleandeps_mistakes);
3952 /* all new rules are learnt after this point */
3953 solv->learntrules = solv->nrules;
3955 /* create watches chains */
3958 /* create assertion index. it is only used to speed up
3959 * makeruledecsions() a bit */
3960 for (i = 1, r = solv->rules + i; i < solv->nrules; i++, r++)
3961 if (r->p && !r->w2 && (r->d == 0 || r->d == -1))
3962 queue_push(&solv->ruleassertions, i);
3964 /* disable update rules that conflict with our job */
3965 solver_disablepolicyrules(solv);
3967 /* break orphans if requested */
3968 if (solv->dupmap_all && solv->orphaned.count && solv->break_orphans)
3969 solver_breakorphans(solv);
3972 * ********************************************
3974 * ********************************************
3977 now = solv_timems(0);
3978 solver_run_sat(solv, 1, solv->dontinstallrecommended ? 0 : 1);
3979 POOL_DEBUG(SOLV_DEBUG_STATS, "solver took %d ms\n", solv_timems(now));
3982 * prepare solution queue if there were problems
3984 solver_prepare_solutions(solv);
3986 POOL_DEBUG(SOLV_DEBUG_STATS, "final solver statistics: %d problems, %d learned rules, %d unsolvable\n", solv->problems.count / 2, solv->stats_learned, solv->stats_unsolvable);
3987 POOL_DEBUG(SOLV_DEBUG_STATS, "solver_solve took %d ms\n", solv_timems(solve_start));
3989 /* return number of problems */
3990 return solv->problems.count ? solv->problems.count / 2 : 0;
3994 solver_create_transaction(Solver *solv)
3996 return transaction_create_decisionq(solv->pool, &solv->decisionq, &solv->multiversion);
3999 void solver_get_orphaned(Solver *solv, Queue *orphanedq)
4001 queue_free(orphanedq);
4002 queue_init_clone(orphanedq, &solv->orphaned);
4005 void solver_get_recommendations(Solver *solv, Queue *recommendationsq, Queue *suggestionsq, int noselected)
4007 Pool *pool = solv->pool;
4008 Queue redoq, disabledq;
4014 if (!recommendationsq && !suggestionsq)
4017 map_init(&obsmap, pool->nsolvables);
4018 if (solv->installed)
4020 Id obs, *obsp, p, po, ppo;
4021 for (p = solv->installed->start; p < solv->installed->end; p++)
4023 s = pool->solvables + p;
4024 if (s->repo != solv->installed || !s->obsoletes)
4026 if (solv->decisionmap[p] <= 0)
4028 if (solv->multiversion.size && MAPTST(&solv->multiversion, p))
4030 obsp = s->repo->idarraydata + s->obsoletes;
4031 /* foreach obsoletes */
4032 while ((obs = *obsp++) != 0)
4033 FOR_PROVIDES(po, ppo, obs)
4034 MAPSET(&obsmap, po);
4039 queue_init(&disabledq);
4041 /* disable all erase jobs (including weak "keep uninstalled" rules) */
4042 for (i = solv->jobrules, r = solv->rules + i; i < solv->jobrules_end; i++, r++)
4044 if (r->d < 0) /* disabled ? */
4046 if (r->p >= 0) /* install job? */
4048 queue_push(&disabledq, i);
4049 solver_disablerule(solv, r);
4055 enabledisablelearntrules(solv);
4056 removedisabledconflicts(solv, &redoq);
4060 * find recommended packages
4062 if (recommendationsq)
4064 Id rec, *recp, p, pp;
4066 queue_empty(recommendationsq);
4067 /* create map of all recommened packages */
4068 solv->recommends_index = -1;
4069 MAPZERO(&solv->recommendsmap);
4071 /* put all packages the solver already chose in the map */
4072 if (solv->decisioncnt_weak)
4074 for (i = solv->decisioncnt_weak; i < solv->decisioncnt_orphan; i++)
4077 why = solv->decisionq_why.elements[i];
4079 continue; /* forced by unit rule or dep resolving */
4080 p = solv->decisionq.elements[i];
4083 MAPSET(&solv->recommendsmap, p);
4087 for (i = 0; i < solv->decisionq.count; i++)
4089 p = solv->decisionq.elements[i];
4092 s = pool->solvables + p;
4095 recp = s->repo->idarraydata + s->recommends;
4096 while ((rec = *recp++) != 0)
4098 #ifdef ENABLE_COMPLEX_DEPS
4099 if (pool_is_complex_dep(pool, rec))
4101 do_complex_recommendations(solv, rec, &solv->recommendsmap, noselected);
4105 FOR_PROVIDES(p, pp, rec)
4106 if (solv->decisionmap[p] > 0)
4112 FOR_PROVIDES(p, pp, rec)
4113 if (solv->decisionmap[p] > 0)
4114 MAPSET(&solv->recommendsmap, p);
4116 continue; /* p != 0: already fulfilled */
4118 FOR_PROVIDES(p, pp, rec)
4119 MAPSET(&solv->recommendsmap, p);
4123 for (i = 1; i < pool->nsolvables; i++)
4125 if (solv->decisionmap[i] < 0)
4127 if (solv->decisionmap[i] > 0 && noselected)
4129 if (MAPTST(&obsmap, i))
4131 s = pool->solvables + i;
4132 if (!MAPTST(&solv->recommendsmap, i))
4134 if (!s->supplements)
4136 if (!pool_installable(pool, s))
4138 if (!solver_is_supplementing(solv, s))
4141 queue_push(recommendationsq, i);
4143 /* we use MODE_SUGGEST here so that repo prio is ignored */
4144 policy_filter_unwanted(solv, recommendationsq, POLICY_MODE_SUGGEST);
4148 * find suggested packages
4153 Id sug, *sugp, p, pp;
4155 queue_empty(suggestionsq);
4156 /* create map of all suggests that are still open */
4157 solv->recommends_index = -1;
4158 MAPZERO(&solv->suggestsmap);
4159 for (i = 0; i < solv->decisionq.count; i++)
4161 p = solv->decisionq.elements[i];
4164 s = pool->solvables + p;
4167 sugp = s->repo->idarraydata + s->suggests;
4168 while ((sug = *sugp++) != 0)
4170 #ifdef ENABLE_COMPLEX_DEPS
4171 if (pool_is_complex_dep(pool, sug))
4173 do_complex_recommendations(solv, sug, &solv->suggestsmap, noselected);
4177 FOR_PROVIDES(p, pp, sug)
4178 if (solv->decisionmap[p] > 0)
4184 FOR_PROVIDES(p, pp, sug)
4185 if (solv->decisionmap[p] > 0)
4186 MAPSET(&solv->suggestsmap, p);
4188 continue; /* already fulfilled */
4190 FOR_PROVIDES(p, pp, sug)
4191 MAPSET(&solv->suggestsmap, p);
4195 for (i = 1; i < pool->nsolvables; i++)
4197 if (solv->decisionmap[i] < 0)
4199 if (solv->decisionmap[i] > 0 && noselected)
4201 if (MAPTST(&obsmap, i))
4203 s = pool->solvables + i;
4204 if (!MAPTST(&solv->suggestsmap, i))
4208 if (!pool_installable(pool, s))
4210 if (!solver_is_enhancing(solv, s))
4213 queue_push(suggestionsq, i);
4215 policy_filter_unwanted(solv, suggestionsq, POLICY_MODE_SUGGEST);
4218 /* undo removedisabledconflicts */
4220 undo_removedisabledconflicts(solv, &redoq);
4223 /* undo job rule disabling */
4224 for (i = 0; i < disabledq.count; i++)
4225 solver_enablerule(solv, solv->rules + disabledq.elements[i]);
4226 queue_free(&disabledq);
4231 /***********************************************************************/
4232 /* disk usage computations */
4234 /*-------------------------------------------------------------------
4236 * calculate DU changes
4240 solver_calc_duchanges(Solver *solv, DUChanges *mps, int nmps)
4244 solver_create_state_maps(solv, &installedmap, 0);
4245 pool_calc_duchanges(solv->pool, &installedmap, mps, nmps);
4246 map_free(&installedmap);
4250 /*-------------------------------------------------------------------
4252 * calculate changes in install size
4256 solver_calc_installsizechange(Solver *solv)
4261 solver_create_state_maps(solv, &installedmap, 0);
4262 change = pool_calc_installsizechange(solv->pool, &installedmap);
4263 map_free(&installedmap);
4268 solver_create_state_maps(Solver *solv, Map *installedmap, Map *conflictsmap)
4270 pool_create_state_maps(solv->pool, &solv->decisionq, installedmap, conflictsmap);
4274 solver_trivial_installable(Solver *solv, Queue *pkgs, Queue *res)
4276 Pool *pool = solv->pool;
4279 pool_create_state_maps(pool, &solv->decisionq, &installedmap, 0);
4280 pool_trivial_installable_multiversionmap(pool, &installedmap, pkgs, res, solv->multiversion.size ? &solv->multiversion : 0);
4281 for (i = 0; i < res->count; i++)
4282 if (res->elements[i] != -1)
4284 Solvable *s = pool->solvables + pkgs->elements[i];
4285 if (!strncmp("patch:", pool_id2str(pool, s->name), 6) && solvable_is_irrelevant_patch(s, &installedmap))
4286 res->elements[i] = -1;
4288 map_free(&installedmap);
4291 /*-------------------------------------------------------------------
4293 * decision introspection
4297 solver_get_decisionlevel(Solver *solv, Id p)
4299 return solv->decisionmap[p];
4303 solver_get_decisionqueue(Solver *solv, Queue *decisionq)
4305 queue_free(decisionq);
4306 queue_init_clone(decisionq, &solv->decisionq);
4310 solver_get_lastdecisionblocklevel(Solver *solv)
4313 if (solv->decisionq.count == 0)
4315 p = solv->decisionq.elements[solv->decisionq.count - 1];
4318 return solv->decisionmap[p] < 0 ? -solv->decisionmap[p] : solv->decisionmap[p];
4322 solver_get_decisionblock(Solver *solv, int level, Queue *decisionq)
4327 queue_empty(decisionq);
4328 for (i = 0; i < solv->decisionq.count; i++)
4330 p = solv->decisionq.elements[i];
4333 if (solv->decisionmap[p] == level || solv->decisionmap[p] == -level)
4336 if (i == solv->decisionq.count)
4338 for (i = 0; i < solv->decisionq.count; i++)
4340 p = solv->decisionq.elements[i];
4343 if (solv->decisionmap[p] == level || solv->decisionmap[p] == -level)
4344 queue_push(decisionq, p);
4351 solver_describe_decision(Solver *solv, Id p, Id *infop)
4358 if (!solv->decisionmap[p])
4359 return SOLVER_REASON_UNRELATED;
4360 pp = solv->decisionmap[p] < 0 ? -p : p;
4361 for (i = 0; i < solv->decisionq.count; i++)
4362 if (solv->decisionq.elements[i] == pp)
4364 if (i == solv->decisionq.count) /* just in case... */
4365 return SOLVER_REASON_UNRELATED;
4366 why = solv->decisionq_why.elements[i];
4368 *infop = why > 0 ? why : -why;
4370 return SOLVER_REASON_UNIT_RULE;
4373 return SOLVER_REASON_KEEP_INSTALLED; /* the systemsolvable */
4374 if (i < solv->decisioncnt_update)
4375 return SOLVER_REASON_RESOLVE_JOB;
4376 if (i < solv->decisioncnt_keep)
4378 if (why == 0 && pp < 0)
4379 return SOLVER_REASON_CLEANDEPS_ERASE;
4380 return SOLVER_REASON_UPDATE_INSTALLED;
4382 if (i < solv->decisioncnt_resolve)
4384 if (solv->focus_installed && i >= solv->decisioncnt_jobs)
4385 return SOLVER_REASON_RESOLVE_JOB;
4386 if (why == 0 && pp < 0)
4387 return SOLVER_REASON_CLEANDEPS_ERASE;
4388 return SOLVER_REASON_KEEP_INSTALLED;
4391 return SOLVER_REASON_RESOLVE;
4392 /* weak or orphaned */
4393 if (i < solv->decisioncnt_orphan)
4394 return SOLVER_REASON_WEAKDEP;
4395 return SOLVER_REASON_RESOLVE_ORPHAN;
4400 solver_describe_weakdep_decision(Solver *solv, Id p, Queue *whyq)
4402 Pool *pool = solv->pool;
4404 int level = solv->decisionmap[p];
4411 for (decisionno = 0; decisionno < solv->decisionq.count; decisionno++)
4412 if (solv->decisionq.elements[decisionno] == p)
4414 if (decisionno == solv->decisionq.count)
4416 if (decisionno < solv->decisioncnt_weak || decisionno >= solv->decisioncnt_orphan)
4419 /* 1) list all packages that recommend us */
4420 for (i = 1; i < pool->nsolvables; i++)
4422 Id *recp, rec, pp2, p2;
4423 if (solv->decisionmap[i] < 0 || solv->decisionmap[i] >= level)
4425 s = pool->solvables + i;
4428 if (!solv->addalreadyrecommended && s->repo == solv->installed)
4430 recp = s->repo->idarraydata + s->recommends;
4431 while ((rec = *recp++) != 0)
4434 FOR_PROVIDES(p2, pp2, rec)
4440 /* if p2 is already installed, this recommends is ignored */
4441 if (solv->decisionmap[p2] > 0 && solv->decisionmap[p2] < level)
4447 queue_push(whyq, SOLVER_REASON_RECOMMENDED);
4448 queue_push2(whyq, i, rec);
4452 /* 2) list all supplements */
4453 s = pool->solvables + p;
4454 if (s->supplements && level > 0)
4456 Id *supp, sup, pp2, p2;
4457 /* this is a hack. to use solver_dep_fulfilled we temporarily clear
4458 * everything above our level in the decisionmap */
4459 for (i = decisionno; i < solv->decisionq.count; i++ )
4461 p2 = solv->decisionq.elements[i];
4463 solv->decisionmap[p2] = -solv->decisionmap[p2];
4465 supp = s->repo->idarraydata + s->supplements;
4466 while ((sup = *supp++) != 0)
4467 if (solver_dep_fulfilled(solv, sup))
4470 /* let's see if this is an easy supp */
4471 FOR_PROVIDES(p2, pp2, sup)
4473 if (!solv->addalreadyrecommended && solv->installed)
4475 if (pool->solvables[p2].repo == solv->installed)
4478 if (solv->decisionmap[p2] > 0 && solv->decisionmap[p2] < level)
4480 queue_push(whyq, SOLVER_REASON_SUPPLEMENTED);
4481 queue_push2(whyq, p2, sup);
4487 /* hard case, just note dependency with no package */
4488 queue_push(whyq, SOLVER_REASON_SUPPLEMENTED);
4489 queue_push2(whyq, 0, sup);
4492 for (i = decisionno; i < solv->decisionq.count; i++)
4494 p2 = solv->decisionq.elements[i];
4496 solv->decisionmap[p2] = -solv->decisionmap[p2];
4502 pool_job2solvables(Pool *pool, Queue *pkgs, Id how, Id what)
4505 how &= SOLVER_SELECTMASK;
4507 if (how == SOLVER_SOLVABLE_ALL)
4509 FOR_POOL_SOLVABLES(p)
4510 queue_push(pkgs, p);
4512 else if (how == SOLVER_SOLVABLE_REPO)
4514 Repo *repo = pool_id2repo(pool, what);
4517 FOR_REPO_SOLVABLES(repo, p, s)
4518 queue_push(pkgs, p);
4522 FOR_JOB_SELECT(p, pp, how, what)
4523 queue_push(pkgs, p);
4528 pool_isemptyupdatejob(Pool *pool, Id how, Id what)
4531 Id select = how & SOLVER_SELECTMASK;
4532 if ((how & SOLVER_JOBMASK) != SOLVER_UPDATE)
4534 if (select == SOLVER_SOLVABLE_ALL || select == SOLVER_SOLVABLE_REPO)
4536 if (!pool->installed)
4538 FOR_JOB_SELECT(p, pp, select, what)
4539 if (pool->solvables[p].repo == pool->installed)
4542 FOR_JOB_SELECT(p, pp, select, what)
4544 Solvable *s = pool->solvables + p;
4545 FOR_PROVIDES(pi, pip, s->name)
4547 Solvable *si = pool->solvables + pi;
4548 if (si->repo != pool->installed || si->name != s->name)
4554 Id obs, *obsp = s->repo->idarraydata + s->obsoletes;
4555 while ((obs = *obsp++) != 0)
4557 FOR_PROVIDES(pi, pip, obs)
4559 Solvable *si = pool->solvables + pi;
4560 if (si->repo != pool->installed)
4562 if (!pool->obsoleteusesprovides && !pool_match_nevr(pool, si, obs))
4564 if (pool->obsoleteusescolors && !pool_colormatch(pool, s, si))
4575 get_userinstalled_cmp(const void *ap, const void *bp, void *dp)
4577 return *(Id *)ap - *(Id *)bp;
4581 get_userinstalled_cmp_names(const void *ap, const void *bp, void *dp)
4584 return strcmp(pool_id2str(pool, *(Id *)ap), pool_id2str(pool, *(Id *)bp));
4588 get_userinstalled_cmp_namearch(const void *ap, const void *bp, void *dp)
4592 r = strcmp(pool_id2str(pool, ((Id *)ap)[0]), pool_id2str(pool, ((Id *)bp)[0]));
4595 return strcmp(pool_id2str(pool, ((Id *)ap)[1]), pool_id2str(pool, ((Id *)bp)[1]));
4599 get_userinstalled_sort_uniq(Pool *pool, Queue *q, int flags)
4601 Id lastp = -1, lasta = -1;
4603 if (q->count < ((flags & GET_USERINSTALLED_NAMEARCH) ? 4 : 2))
4605 if ((flags & GET_USERINSTALLED_NAMEARCH) != 0)
4606 solv_sort(q->elements, q->count / 2, 2 * sizeof(Id), get_userinstalled_cmp_namearch, pool);
4607 else if ((flags & GET_USERINSTALLED_NAMES) != 0)
4608 solv_sort(q->elements, q->count, sizeof(Id), get_userinstalled_cmp_names, pool);
4610 solv_sort(q->elements, q->count, sizeof(Id), get_userinstalled_cmp, 0);
4611 if ((flags & GET_USERINSTALLED_NAMEARCH) != 0)
4613 for (i = j = 0; i < q->count; i += 2)
4614 if (q->elements[i] != lastp || q->elements[i + 1] != lasta)
4616 q->elements[j++] = lastp = q->elements[i];
4617 q->elements[j++] = lasta = q->elements[i + 1];
4622 for (i = j = 0; i < q->count; i++)
4623 if (q->elements[i] != lastp)
4624 q->elements[j++] = lastp = q->elements[i];
4626 queue_truncate(q, j);
4630 namearch2solvables(Pool *pool, Queue *q, Queue *qout, int job)
4633 if (!pool->installed)
4635 for (i = 0; i < q->count; i += 2)
4637 Id p, pp, name = q->elements[i], arch = q->elements[i + 1];
4638 FOR_PROVIDES(p, pp, name)
4640 Solvable *s = pool->solvables + p;
4641 if (s->repo != pool->installed || s->name != name || (arch && s->arch != arch))
4644 queue_push(qout, job);
4645 queue_push(qout, p);
4651 solver_get_userinstalled(Solver *solv, Queue *q, int flags)
4653 Pool *pool = solv->pool;
4656 Repo *installed = solv->installed;
4660 map_init(&userinstalled, 0);
4662 /* first process jobs */
4663 for (i = 0; i < solv->job.count; i += 2)
4665 Id how = solv->job.elements[i];
4667 if (installed && (how & SOLVER_JOBMASK) == SOLVER_USERINSTALLED)
4669 if (!userinstalled.size)
4670 map_grow(&userinstalled, installed->end - installed->start);
4671 what = solv->job.elements[i + 1];
4672 select = how & SOLVER_SELECTMASK;
4673 if (select == SOLVER_SOLVABLE_ALL || (select == SOLVER_SOLVABLE_REPO && what == installed->repoid))
4674 FOR_REPO_SOLVABLES(installed, p, s)
4675 MAPSET(&userinstalled, p - installed->start);
4676 FOR_JOB_SELECT(p, pp, select, what)
4677 if (pool->solvables[p].repo == installed)
4678 MAPSET(&userinstalled, p - installed->start);
4681 if ((how & SOLVER_JOBMASK) != SOLVER_INSTALL)
4683 if ((how & SOLVER_NOTBYUSER) != 0)
4685 what = solv->job.elements[i + 1];
4686 select = how & SOLVER_SELECTMASK;
4687 FOR_JOB_SELECT(p, pp, select, what)
4688 if (solv->decisionmap[p] > 0)
4691 #ifdef ENABLE_LINKED_PKGS
4692 if (has_package_link(pool, pool->solvables + p))
4697 find_package_link(pool, pool->solvables + p, 0, &lq, 0, 0);
4698 for (j = 0; j < lq.count; j++)
4699 if (solv->decisionmap[lq.elements[j]] > 0)
4700 queue_push(q, lq.elements[j]);
4705 /* now process updates of userinstalled packages */
4706 if (installed && userinstalled.size)
4708 for (i = 1; i < solv->decisionq.count; i++)
4710 p = solv->decisionq.elements[i];
4713 s = pool->solvables + p;
4716 if (s->repo == installed)
4718 if (MAPTST(&userinstalled, p - installed->start))
4722 /* new package, check if we replace a userinstalled one */
4723 FOR_PROVIDES(p2, pp, s->name)
4725 Solvable *ps = pool->solvables + p2;
4726 if (p2 == p || ps->repo != installed || !MAPTST(&userinstalled, p2 - installed->start))
4728 if (!pool->implicitobsoleteusesprovides && s->name != ps->name)
4730 if (pool->implicitobsoleteusescolors && !pool_colormatch(pool, s, ps))
4735 if (!p2 && s->repo != installed && s->obsoletes)
4737 Id obs, *obsp = s->repo->idarraydata + s->obsoletes;
4738 while ((obs = *obsp++) != 0)
4740 FOR_PROVIDES(p2, pp, obs)
4742 Solvable *ps = pool->solvables + p2;
4743 if (p2 == p || ps->repo != installed || !MAPTST(&userinstalled, p2 - installed->start))
4745 if (!pool->obsoleteusesprovides && !pool_match_nevr(pool, ps, obs))
4747 if (pool->obsoleteusescolors && !pool_colormatch(pool, s, ps))
4758 map_free(&userinstalled);
4760 /* convert to desired output format */
4761 if ((flags & GET_USERINSTALLED_NAMEARCH) != 0)
4763 int qcount = q->count;
4764 queue_insertn(q, 0, qcount, 0);
4765 for (i = j = 0; i < qcount; i++)
4767 s = pool->solvables + q->elements[i + qcount];
4768 q->elements[j++] = s->name;
4769 q->elements[j++] = s->arch;
4772 else if ((flags & GET_USERINSTALLED_NAMES) != 0)
4774 for (i = 0; i < q->count; i++)
4776 s = pool->solvables + q->elements[i];
4777 q->elements[i] = s->name;
4780 /* sort and unify */
4781 get_userinstalled_sort_uniq(pool, q, flags);
4783 /* invert if asked for */
4784 if ((flags & GET_USERINSTALLED_INVERTED) != 0)
4786 /* first generate queue with all installed packages */
4789 for (i = 1; i < solv->decisionq.count; i++)
4791 p = solv->decisionq.elements[i];
4794 s = pool->solvables + p;
4797 if ((flags & GET_USERINSTALLED_NAMEARCH) != 0)
4798 queue_push2(&invq, s->name, s->arch);
4799 else if ((flags & GET_USERINSTALLED_NAMES) != 0)
4800 queue_push(&invq, s->name);
4802 queue_push(&invq, p);
4804 /* push q on invq, just in case... */
4805 queue_insertn(&invq, invq.count, q->count, q->elements);
4806 get_userinstalled_sort_uniq(pool, &invq, flags);
4807 /* subtract queues (easy as they are sorted and invq is a superset of q) */
4808 if ((flags & GET_USERINSTALLED_NAMEARCH) != 0)
4812 for (i = j = 0; i < invq.count; i += 2)
4813 if (invq.elements[i] == q->elements[j] && invq.elements[i + 1] == q->elements[j + 1])
4815 invq.elements[i] = invq.elements[i + 1] = 0;
4822 for (i = 0; i < invq.count; i += 2)
4823 if (invq.elements[i])
4824 queue_push2(q, invq.elements[i], invq.elements[i + 1]);
4830 for (i = j = 0; i < invq.count; i++)
4831 if (invq.elements[i] == q->elements[j])
4833 invq.elements[i] = 0;
4834 if (++j >= q->count)
4839 for (i = 0; i < invq.count; i++)
4840 if (invq.elements[i])
4841 queue_push(q, invq.elements[i]);
4848 pool_add_userinstalled_jobs(Pool *pool, Queue *q, Queue *job, int flags)
4852 if ((flags & GET_USERINSTALLED_INVERTED) != 0)
4858 if (!pool->installed)
4861 if ((flags & GET_USERINSTALLED_NAMEARCH) != 0)
4862 flags &= ~GET_USERINSTALLED_NAMES; /* just in case */
4863 FOR_REPO_SOLVABLES(pool->installed, p, s)
4864 queue_push(&invq, flags & GET_USERINSTALLED_NAMES ? s->name : p);
4865 if ((flags & GET_USERINSTALLED_NAMEARCH) != 0)
4867 /* for namearch we convert to packages */
4868 namearch2solvables(pool, q, &invq, 0);
4869 get_userinstalled_sort_uniq(pool, &invq, flags);
4870 namearch2solvables(pool, q, &invq, 0);
4875 queue_insertn(&invq, invq.count, q->count, q->elements);
4876 get_userinstalled_sort_uniq(pool, &invq, flags);
4877 /* now the fun part, add q again, sort, and remove all dups */
4878 queue_insertn(&invq, invq.count, q->count, q->elements);
4882 if ((flags & GET_USERINSTALLED_NAMES) != 0)
4883 solv_sort(invq.elements, invq.count, sizeof(Id), get_userinstalled_cmp_names, pool);
4885 solv_sort(invq.elements, invq.count, sizeof(Id), get_userinstalled_cmp, 0);
4889 for (i = 0; i < invq.count; i++)
4891 if (invq.elements[i] == lastid)
4897 queue_push2(job, SOLVER_USERINSTALLED | (flags & GET_USERINSTALLED_NAMES ? SOLVER_SOLVABLE_NAME : SOLVER_SOLVABLE), lastid);
4899 lastid = invq.elements[i];
4902 queue_push2(job, SOLVER_USERINSTALLED | (flags & GET_USERINSTALLED_NAMES ? SOLVER_SOLVABLE_NAME : SOLVER_SOLVABLE), lastid);
4907 if (flags & GET_USERINSTALLED_NAMEARCH)
4908 namearch2solvables(pool, q, job, SOLVER_USERINSTALLED | SOLVER_SOLVABLE);
4911 for (i = 0; i < q->count; i++)
4912 queue_push2(job, SOLVER_USERINSTALLED | (flags & GET_USERINSTALLED_NAMES ? SOLVER_SOLVABLE_NAME : SOLVER_SOLVABLE), q->elements[i]);
4918 solver_alternatives_count(Solver *solv)
4920 Id *elements = solv->branches.elements;
4922 for (res = 0, count = solv->branches.count; count; res++)
4923 count -= elements[count - 2];
4928 solver_get_alternative(Solver *solv, Id alternative, Id *idp, Id *fromp, Id *chosenp, Queue *choices, int *levelp)
4930 int cnt = solver_alternatives_count(solv);
4931 int count = solv->branches.count;
4932 Id *elements = solv->branches.elements;
4934 queue_empty(choices);
4935 if (alternative <= 0 || alternative > cnt)
4938 for (; cnt > alternative; cnt--)
4939 elements -= elements[-2];
4941 *levelp = elements[-1];
4943 *fromp = elements[-4];
4945 *idp = elements[-3];
4950 for (i = elements[-2]; i > 4; i--)
4952 Id p = -elements[-i];
4953 if (p > 0 && solv->decisionmap[p] == elements[-1] + 1)
4961 queue_insertn(choices, 0, elements[-2] - 4, elements - elements[-2]);
4962 return elements[-4] ? SOLVER_ALTERNATIVE_TYPE_RECOMMENDS : SOLVER_ALTERNATIVE_TYPE_RULE;
4966 solver_select2str(Pool *pool, Id select, Id what)
4970 select &= SOLVER_SELECTMASK;
4971 if (select == SOLVER_SOLVABLE)
4972 return pool_solvid2str(pool, what);
4973 if (select == SOLVER_SOLVABLE_NAME)
4974 return pool_dep2str(pool, what);
4975 if (select == SOLVER_SOLVABLE_PROVIDES)
4977 s = pool_dep2str(pool, what);
4978 b = pool_alloctmpspace(pool, 11 + strlen(s));
4979 sprintf(b, "providing %s", s);
4982 if (select == SOLVER_SOLVABLE_ONE_OF)
4986 while ((p = pool->whatprovidesdata[what++]) != 0)
4988 s = pool_solvid2str(pool, p);
4990 b = pool_tmpappend(pool, b, ", ", s);
4992 b = pool_tmpjoin(pool, s, 0, 0);
4993 pool_freetmpspace(pool, s);
4995 return b ? b : "nothing";
4997 if (select == SOLVER_SOLVABLE_REPO)
4999 b = pool_alloctmpspace(pool, 20);
5000 sprintf(b, "repo #%d", what);
5003 if (select == SOLVER_SOLVABLE_ALL)
5004 return "all packages";
5005 return "unknown job select";
5009 pool_job2str(Pool *pool, Id how, Id what, Id flagmask)
5011 Id select = how & SOLVER_SELECTMASK;
5012 const char *strstart = 0, *strend = 0;
5016 switch (how & SOLVER_JOBMASK)
5019 return "do nothing";
5020 case SOLVER_INSTALL:
5021 if (select == SOLVER_SOLVABLE && pool->installed && pool->solvables[what].repo == pool->installed)
5022 strstart = "keep ", strend = " installed";
5023 else if (select == SOLVER_SOLVABLE || select == SOLVER_SOLVABLE_NAME)
5024 strstart = "install ";
5025 else if (select == SOLVER_SOLVABLE_PROVIDES)
5026 strstart = "install a package ";
5028 strstart = "install one of ";
5031 if (select == SOLVER_SOLVABLE && !(pool->installed && pool->solvables[what].repo == pool->installed))
5032 strstart = "keep ", strend = " uninstalled";
5033 else if (select == SOLVER_SOLVABLE_PROVIDES)
5034 strstart = "deinstall all packages ";
5036 strstart = "deinstall ";
5039 strstart = "update ";
5041 case SOLVER_WEAKENDEPS:
5042 strstart = "weaken deps of ";
5044 case SOLVER_MULTIVERSION:
5045 strstart = "multi version ";
5050 case SOLVER_DISTUPGRADE:
5051 strstart = "dist upgrade ";
5054 strstart = "verify ";
5056 case SOLVER_DROP_ORPHANED:
5057 strstart = "deinstall ", strend = " if orphaned";
5059 case SOLVER_USERINSTALLED:
5060 strstart = "regard ", strend = " as userinstalled";
5063 strstart = "unknown job ";
5066 s = pool_tmpjoin(pool, strstart, solver_select2str(pool, select, what), strend);
5068 if ((how & ~(SOLVER_SELECTMASK|SOLVER_JOBMASK)) == 0)
5071 s = pool_tmpappend(pool, s, " ", 0);
5072 if (how & SOLVER_WEAK)
5073 s = pool_tmpappend(pool, s, ",weak", 0);
5074 if (how & SOLVER_ESSENTIAL)
5075 s = pool_tmpappend(pool, s, ",essential", 0);
5076 if (how & SOLVER_CLEANDEPS)
5077 s = pool_tmpappend(pool, s, ",cleandeps", 0);
5078 if (how & SOLVER_ORUPDATE)
5079 s = pool_tmpappend(pool, s, ",orupdate", 0);
5080 if (how & SOLVER_FORCEBEST)
5081 s = pool_tmpappend(pool, s, ",forcebest", 0);
5082 if (how & SOLVER_TARGETED)
5083 s = pool_tmpappend(pool, s, ",targeted", 0);
5084 if (how & SOLVER_SETEV)
5085 s = pool_tmpappend(pool, s, ",setev", 0);
5086 if (how & SOLVER_SETEVR)
5087 s = pool_tmpappend(pool, s, ",setevr", 0);
5088 if (how & SOLVER_SETARCH)
5089 s = pool_tmpappend(pool, s, ",setarch", 0);
5090 if (how & SOLVER_SETVENDOR)
5091 s = pool_tmpappend(pool, s, ",setvendor", 0);
5092 if (how & SOLVER_SETREPO)
5093 s = pool_tmpappend(pool, s, ",setrepo", 0);
5094 if (how & SOLVER_SETNAME)
5095 s = pool_tmpappend(pool, s, ",setname", 0);
5096 if (how & SOLVER_NOAUTOSET)
5097 s = pool_tmpappend(pool, s, ",noautoset", 0);
5098 if (s[o + 1] != ',')
5099 s = pool_tmpappend(pool, s, ",?", 0);
5101 return pool_tmpappend(pool, s, "]", 0);
5105 solver_alternative2str(Solver *solv, int type, Id id, Id from)
5107 Pool *pool = solv->pool;
5108 if (type == SOLVER_ALTERNATIVE_TYPE_RECOMMENDS)
5110 const char *s = pool_dep2str(pool, id);
5111 return pool_tmpappend(pool, s, ", recommended by ", pool_solvid2str(pool, from));
5113 if (type == SOLVER_ALTERNATIVE_TYPE_RULE)
5116 Id depfrom, depto, dep;
5118 if (solver_ruleclass(solv, id) == SOLVER_RULE_CHOICE)
5119 id = solver_rule2pkgrule(solv, id);
5120 rtype = solver_ruleinfo(solv, id, &depfrom, &depto, &dep);
5121 if ((rtype & SOLVER_RULE_TYPEMASK) == SOLVER_RULE_JOB)
5123 if ((depto & SOLVER_SELECTMASK) == SOLVER_SOLVABLE_PROVIDES)
5124 return pool_dep2str(pool, dep);
5125 return solver_select2str(pool, depto & SOLVER_SELECTMASK, dep);
5127 if (rtype == SOLVER_RULE_PKG_REQUIRES)
5129 const char *s = pool_dep2str(pool, dep);
5130 return pool_tmpappend(pool, s, ", required by ", pool_solvid2str(pool, depfrom));
5132 sprintf(buf, "Rule #%d", id);
5133 return pool_tmpjoin(pool, buf, 0, 0);
5135 return "unknown alternative type";