4 * SAT based dependency solver
17 #include "poolvendor.h"
21 #define RULES_BLOCK 63
23 static Pool *prune_best_version_arch_sortcmp_data;
25 /*-----------------------------------------------------------------*/
28 * prep for prune_best_version_arch
33 prune_best_version_arch_sortcmp(const void *ap, const void *bp)
35 Pool *pool = prune_best_version_arch_sortcmp_data;
39 r = pool->solvables[a].name - pool->solvables[b].name;
43 /* different names. We use real strcmp here so that the result
44 * is not depending on some random solvable order */
45 na = id2str(pool, pool->solvables[a].name);
46 nb = id2str(pool, pool->solvables[b].name);
47 /* bring selections and patterns to the front */
48 if (!strncmp(na, "pattern:", 8))
50 if (strncmp(nb, "pattern:", 8))
53 else if (!strncmp(nb, "pattern:", 8))
55 if (strncmp(na, "pattern:", 8))
58 if (!strncmp(na, "selection:", 10))
60 if (strncmp(nb, "selection:", 10))
63 else if (!strncmp(nb, "selection:", 10))
65 if (strncmp(na, "selection:", 10))
68 return strcmp(na, nb);
76 replaces_installed(Solver *solv, Id id)
78 Pool *pool = solv->pool;
79 Repo *installed = solv->installed;
80 Id *name = pool->solvables[id].name;
82 FOR_PROVIDES(p, pp, id)
84 s = pool->solvables + p;
87 if (p >= installed->start && p < installed->start + installed->nsolvables)
94 dep_installed(Solver *solv, Id dep)
96 /* disable for now, splitprovides don't work anyway and it breaks
99 Pool *pool = solv->pool;
104 Reldep *rd = GETRELDEP(pool, dep);
105 if (rd->flags == REL_AND)
107 if (!dep_installed(solv, rd->name))
109 return dep_installed(solv, rd->evr);
111 if (rd->flags == REL_NAMESPACE && rd->name == NAMESPACE_INSTALLED)
112 return dep_installed(solv, rd->evr);
114 FOR_PROVIDES(p, pp, dep)
116 if (p >= solv->installed->start && p < solv->installed->start + solv->installed->nsolvables)
124 dep_fulfilled(Solver *solv, Id dep)
126 Pool *pool = solv->pool;
131 Reldep *rd = GETRELDEP(pool, dep);
132 if (rd->flags == REL_AND)
134 if (!dep_fulfilled(solv, rd->name))
136 return dep_fulfilled(solv, rd->evr);
138 if (rd->flags == REL_NAMESPACE && rd->name == NAMESPACE_INSTALLED)
139 return dep_installed(solv, rd->evr);
141 FOR_PROVIDES(p, pp, dep)
143 if (solv->decisionmap[p] > 0)
150 dep_possible(Solver *solv, Id dep, Map *m)
152 Pool *pool = solv->pool;
157 Reldep *rd = GETRELDEP(pool, dep);
158 if (rd->flags == REL_AND)
160 if (!dep_possible(solv, rd->name, m))
162 return dep_possible(solv, rd->evr, m);
164 if (rd->flags == REL_NAMESPACE && rd->name == NAMESPACE_INSTALLED)
165 return dep_installed(solv, rd->evr);
167 FOR_PROVIDES(p, pp, dep)
176 prune_to_highest_prio(Pool *pool, Queue *plist)
182 /* prune to highest priority */
183 for (i = 0; i < plist->count; i++)
185 s = pool->solvables + plist->elements[i];
186 if (i == 0 || s->repo->priority > bestprio)
187 bestprio = s->repo->priority;
189 for (i = j = 0; i < plist->count; i++)
191 s = pool->solvables + plist->elements[i];
192 if (s->repo->priority == bestprio)
193 plist->elements[j++] = plist->elements[i];
199 * prune_to_recommended
201 * XXX: should we prune to requires/suggests that are already
202 * fulfilled by other packages?
205 prune_to_recommended(Solver *solv, Queue *plist)
207 Pool *pool = solv->pool;
210 Id p, *pp, sup, *supp, rec, *recp, sug, *sugp, enh, *enhp;
212 if (solv->recommends_index < 0)
214 MAPZERO(&solv->recommendsmap);
215 MAPZERO(&solv->suggestsmap);
216 solv->recommends_index = 0;
218 while (solv->recommends_index < solv->decisionq.count)
220 p = solv->decisionq.elements[solv->recommends_index++];
223 s = pool->solvables + p;
226 recp = s->repo->idarraydata + s->recommends;
227 while ((rec = *recp++) != 0)
228 FOR_PROVIDES(p, pp, rec)
229 MAPSET(&solv->recommendsmap, p);
233 sugp = s->repo->idarraydata + s->suggests;
234 while ((sug = *sugp++) != 0)
235 FOR_PROVIDES(p, pp, sug)
236 MAPSET(&solv->suggestsmap, p);
239 /* prune to recommended/supplemented */
240 for (i = j = 0; i < plist->count; i++)
242 p = plist->elements[i];
243 if (MAPTST(&solv->recommendsmap, p))
245 plist->elements[j++] = p;
248 s = pool->solvables + p;
249 if (!s->supplements && !s->freshens)
253 supp = s->repo->idarraydata + s->supplements;
254 while ((sup = *supp++) != 0)
255 if (dep_fulfilled(solv, sup))
262 supp = s->repo->idarraydata + s->freshens;
263 while ((sup = *supp++) != 0)
264 if (dep_fulfilled(solv, sup))
269 plist->elements[j++] = s - pool->solvables;
274 /* prune to suggested/enhanced*/
275 if (plist->count < 2)
277 for (i = j = 0; i < plist->count; i++)
279 p = plist->elements[i];
280 if (MAPTST(&solv->suggestsmap, p))
282 plist->elements[j++] = p;
285 s = pool->solvables + p;
288 enhp = s->repo->idarraydata + s->enhances;
289 while ((enh = *enhp++) != 0)
290 if (dep_fulfilled(solv, enh))
294 plist->elements[j++] = s - pool->solvables;
301 * prune_best_version_arch
303 * sort list of packages (given through plist) by name and evr
304 * return result through plist
308 /* FIXME: should prefer installed if identical version */
311 prune_best_version_arch(Pool *pool, Queue *plist)
318 if (plist->count < 2) /* no need to prune for a single entry */
320 if (pool->verbose > 1) printf("prune_best_version_arch %d\n", plist->count);
322 /* prune to best architecture */
326 for (i = 0; i < plist->count; i++)
328 s = pool->solvables + plist->elements[i];
330 a = a <= pool->lastarch ? pool->id2arch[a] : 0;
331 if (a && a != 1 && (!bestscore || a < bestscore))
334 for (i = j = 0; i < plist->count; i++)
336 s = pool->solvables + plist->elements[i];
338 if (a > pool->lastarch)
340 a = pool->id2arch[a];
341 /* a == 1 -> noarch */
342 if (a != 1 && ((a ^ bestscore) & 0xffff0000) != 0)
344 plist->elements[j++] = plist->elements[i];
350 prune_best_version_arch_sortcmp_data = pool;
351 /* sort by name first */
352 qsort(plist->elements, plist->count, sizeof(Id), prune_best_version_arch_sortcmp);
354 /* delete obsoleted. hmm, looks expensive! */
355 /* FIXME maybe also check provides depending on noupdateprovide? */
356 /* FIXME do not prune cycles */
357 for (i = 0; i < plist->count; i++)
359 Id p, *pp, obs, *obsp;
360 s = pool->solvables + plist->elements[i];
363 obsp = s->repo->idarraydata + s->obsoletes;
364 while ((obs = *obsp++) != 0)
366 FOR_PROVIDES(p, pp, obs)
368 if (pool->solvables[p].name == s->name)
370 for (j = 0; j < plist->count; j++)
374 if (plist->elements[j] == p)
375 plist->elements[j] = 0;
380 for (i = j = 0; i < plist->count; i++)
381 if (plist->elements[i])
382 plist->elements[j++] = plist->elements[i];
385 /* now find best 'per name' */
386 for (i = j = 0; i < plist->count; i++)
388 s = pool->solvables + plist->elements[i];
390 if (pool->verbose > 1) printf("- %s-%s.%s\n", id2str(pool, s->name), id2str(pool, s->evr), id2str(pool, s->arch));
392 if (!best) /* if no best yet, the current is best */
394 best = plist->elements[i];
398 /* name switch: re-init */
399 if (pool->solvables[best].name != s->name) /* new name */
401 plist->elements[j++] = best; /* move old best to front */
402 best = plist->elements[i]; /* take current as new best */
406 if (pool->solvables[best].evr != s->evr) /* compare evr */
408 if (evrcmp(pool, pool->solvables[best].evr, s->evr) < 0)
409 best = plist->elements[i];
414 best = plist->elements[0];
416 plist->elements[j++] = best;
421 /*-----------------------------------------------------------------*/
428 printruleelement(Solver *solv, Rule *r, Id v)
430 Pool *pool = solv->pool;
434 s = pool->solvables + -v;
435 printf(" !%s-%s.%s [%d]", id2str(pool, s->name), id2str(pool, s->evr), id2str(pool, s->arch), -v);
439 s = pool->solvables + v;
440 printf(" %s-%s.%s [%d]", id2str(pool, s->name), id2str(pool, s->evr), id2str(pool, s->arch), v);
449 if (solv->decisionmap[s - pool->solvables] > 0)
450 printf(" I.%d", solv->decisionmap[s - pool->solvables]);
451 if (solv->decisionmap[s - pool->solvables] < 0)
452 printf(" C.%d", -solv->decisionmap[s - pool->solvables]);
462 printrule(Solver *solv, Rule *r)
467 if (r >= solv->rules && r < solv->rules + solv->nrules) /* r is a solver rule */
468 printf("Rule #%d:\n", (int)(r - solv->rules));
470 printf("Rule:\n"); /* r is any rule */
475 else if (r->d == ID_NULL)
482 v = solv->pool->whatprovidesdata[r->d + i - 1];
485 printruleelement(solv, r, v);
487 printf(" next: %d %d\n", r->n1, r->n2);
491 /*-----------------------------------------------------------------*/
497 static Pool *unifyrules_sortcmp_data;
500 * compare rules for unification sort
504 unifyrules_sortcmp(const void *ap, const void *bp)
506 Pool *pool = unifyrules_sortcmp_data;
507 Rule *a = (Rule *)ap;
508 Rule *b = (Rule *)bp;
514 return x; /* p differs */
517 if (a->d == 0 && b->d == 0)
518 return a->w2 - b->w2; /* assertion: return w2 diff */
520 if (a->d == 0) /* a is assertion, b not */
522 x = a->w2 - pool->whatprovidesdata[b->d];
526 if (b->d == 0) /* b is assertion, a not */
528 x = pool->whatprovidesdata[a->d] - b->w2;
532 /* compare whatprovidesdata */
533 ad = pool->whatprovidesdata + a->d;
534 bd = pool->whatprovidesdata + b->d;
536 if ((x = *ad++ - *bd++) != 0)
547 unifyrules(Solver *solv)
552 if (solv->nrules <= 1) /* nothing to unify */
555 /* sort rules first */
556 unifyrules_sortcmp_data = solv->pool;
557 qsort(solv->rules + 1, solv->nrules - 1, sizeof(Rule), unifyrules_sortcmp);
564 for (i = j = 1, ir = solv->rules + 1; i < solv->nrules; i++, ir++)
566 if (jr && !unifyrules_sortcmp(ir, jr))
567 continue; /* prune! */
568 jr = solv->rules + j++; /* keep! */
573 /* reduced count from nrules to j rules */
574 if (solv->pool->verbose) printf("pruned rules from %d to %d\n", solv->nrules, j);
576 /* adapt rule buffer */
577 solv->rules = (Rule *)xrealloc(solv->rules, ((solv->nrules + RULES_BLOCK) & ~RULES_BLOCK) * sizeof(Rule));
580 if (solv->pool->verbose)
587 for (i = 1; i < solv->nrules; i++)
594 dp = solv->pool->whatprovidesdata + r->d;
599 printf(" binary: %d\n", binr);
600 printf(" normal: %d, %d literals\n", solv->nrules - 1 - binr, lits);
612 hashrule(Solver *solv, Id p, Id d, int n)
614 unsigned int x = (unsigned int)p;
618 return (x * 37) ^ (unsigned int)d;
619 dp = solv->pool->whatprovidesdata + d;
621 x = (x * 37) ^ (unsigned int)*dp++;
629 * p = direct literal; > 0 for learnt, < 0 for installed pkg (rpm)
630 * d, if < 0 direct literal, if > 0 offset into whatprovides, if == 0 rule is assertion (look at p only)
633 * A requires b, b provided by B1,B2,B3 => (-A|B1|B2|B3)
635 * p < 0 : rule from rpm (installed pkg)
636 * d > 0 : Offset in whatprovidesdata (list of providers)
638 * A conflicts b, b provided by B1,B2,B3 => (-A|-B1), (-A|-B2), (-A|-B3)
639 * d < 0: Id of solvable (e.g. B1)
641 * d == 0: unary rule, assertion => (A) or (-A)
643 * Install: p > 0, d = 0 (A) user requested install
644 * Remove: p < 0, d = 0 (-A) user requested remove
645 * Requires: p < 0, d > 0 (-A|B1|B2|...) d: <list of providers for requirement of p>
646 * Updates: p > 0, d > 0 (A|B1|B2|...) d: <list of updates for solvable p>
647 * Conflicts: p < 0, d < 0 (-A|-B) either p (conflict issuer) or d (conflict provider)
648 * ? p > 0, d < 0 (A|-B)
649 * No-op ?: p = 0, d = 0 (null) (used as policy rule placeholder)
653 addrule(Solver *solv, Id p, Id d)
658 int n = 0; /* number of literals in rule - 1
659 0 = direct assertion (single literal)
663 /* it often happenes that requires lead to adding the same rpm rule
664 * multiple times, so we prune those duplicates right away to make
665 * the work for unifyrules a bit easier */
667 if (solv->nrules && !solv->jobrules)
669 r = solv->rules + solv->nrules - 1; /* get the last added rule */
670 if (r->p == p && r->d == d && d != 0) /* identical and not user requested */
677 return 0; /* ignore self conflict */
680 else if (d == 0) /* user requested */
684 for (dp = solv->pool->whatprovidesdata + d; *dp; dp++, n++)
686 return 0; /* rule is self-fulfilling */
691 if (n == 0) /* direct assertion */
695 /* this is a rpm rule assertion, we do not have to allocate it */
696 /* it can be identified by a level of 1 and a zero reason */
697 /* we must not drop those rules from the decisionq when rewinding! */
700 if (solv->decisionmap[-p] > 0 || solv->decisionmap[-p] < -1)
702 if (solv->decisionmap[-p])
704 queue_push(&solv->decisionq, p);
705 queue_push(&solv->decisionq_why, 0);
706 solv->decisionmap[-p] = -1;
710 else if (n == 1 && p > d)
712 /* smallest literal first so we can find dups */
716 n = 1; /* re-set n, was used as temp var */
719 /* check if the last added rule is exactly the same as what we're looking for. */
720 if (r && n == 1 && !r->d && r->p == p && r->w2 == d)
723 if (r && n > 1 && r->d && r->p == p)
728 dp2 = solv->pool->whatprovidesdata + r->d;
729 for (dp = solv->pool->whatprovidesdata + d; *dp; dp++, dp2++)
740 /* check and extend rule buffer */
741 if ((solv->nrules & RULES_BLOCK) == 0)
743 solv->rules = (Rule *)xrealloc(solv->rules, (solv->nrules + (RULES_BLOCK + 1)) * sizeof(Rule));
746 r = solv->rules + solv->nrules++; /* point to rule space */
751 /* direct assertion, no watch needed */
767 r->w2 = solv->pool->whatprovidesdata[d];
775 /* go through system and job rules and add direct assertions
776 * to the decisionqueue. If we find a conflict, disable rules and
777 * add them to problem queue.
780 makeruledecisions(Solver *solv)
786 /* no learnt rules for now */
787 if (solv->learntrules && solv->learntrules != solv->nrules)
790 for (ri = solv->jobrules, r = solv->rules + ri; ri < solv->nrules; ri++, r++)
796 if (solv->decisionmap[vv] == 0)
798 queue_push(&solv->decisionq, v);
799 queue_push(&solv->decisionq_why, r - solv->rules);
800 solv->decisionmap[vv] = v > 0 ? 1 : -1;
803 if (v > 0 && solv->decisionmap[vv] > 0)
805 if (v < 0 && solv->decisionmap[vv] < 0)
807 /* found a conflict! */
808 /* if we are weak, just disable ourself */
809 if (ri >= solv->weakrules)
811 printf("conflict, but I am weak, disabling ");
816 for (i = 0; i < solv->decisionq.count; i++)
817 if (solv->decisionq.elements[i] == -v)
819 if (i == solv->decisionq.count)
821 if (solv->decisionq_why.elements[i] == 0)
823 /* conflict with rpm rule, need only disable our rule */
824 printf("conflict with rpm rule, disabling rule #%d\n", ri);
825 queue_push(&solv->problems, r - solv->rules);
826 queue_push(&solv->problems, 0);
827 r->w1 = 0; /* disable */
830 /* conflict with another job or system rule */
831 /* remove old decision */
832 printf("conflicting system/job rules over literal %d\n", vv);
833 solv->decisionmap[vv] = 0;
834 for (; i + 1 < solv->decisionq.count; i++)
836 solv->decisionq.elements[i] = solv->decisionq.elements[i + 1];
837 solv->decisionq_why.elements[i] = solv->decisionq_why.elements[i + 1];
839 solv->decisionq.count--;
840 solv->decisionq_why.count--;
841 /* push all of our rules asserting this literal on the problem stack */
842 for (i = solv->jobrules, rr = solv->rules + i; i < solv->nrules; i++, rr++)
844 if (!rr->w1 || rr->w2)
846 if (rr->p != v && rr->p != -v)
848 printf(" - disabling rule #%d\n", i);
849 queue_push(&solv->problems, i);
850 rr->w1 = 0; /* disable */
852 queue_push(&solv->problems, 0);
858 * add (install) rules for solvable
863 addrulesforsolvable(Solver *solv, Solvable *s, Map *m)
865 Pool *pool = solv->pool;
866 Repo *installed = solv->installed;
880 queue_init_buffer(&q, qbuf, sizeof(qbuf)/sizeof(*qbuf));
881 queue_push(&q, s - pool->solvables); /* push solvable Id */
887 * s: Pointer to solvable
891 if (MAPTST(m, n)) /* continue if already done */
895 s = pool->solvables + n; /* s = Solvable in question */
900 && n >= installed->start /* is it installed? */
901 && n < installed->start + installed->nsolvables)
903 dontfix = 1; /* dont care about broken rpm deps */
906 /*-----------------------------------------
907 * check requires of s
912 reqp = s->repo->idarraydata + s->requires;
913 while ((req = *reqp++) != 0)
915 if (req == SOLVABLE_PREREQMARKER) /* skip the marker */
918 dp = GET_PROVIDESP(req, p); /* get providers of req */
920 if (*dp == SYSTEMSOLVABLE) /* always installed */
925 /* the strategy here is to not insist on dependencies
926 * that are already broken. so if we find one provider
927 * that was already installed, we know that the
928 * dependency was not broken before so we enforce it */
929 for (i = 0; dp[i]; i++) /* for all providers */
931 if (dp[i] >= installed->start && dp[i] < installed->start + installed->nsolvables)
932 break; /* provider was installed */
934 if (!dp[i]) /* previously broken dependency */
936 if (pool->verbose) printf("ignoring broken requires %s of installed package %s-%s.%s\n", dep2str(pool, req), id2str(pool, s->name), id2str(pool, s->evr), id2str(pool, s->arch));
943 /* nothing provides req! */
945 if (pool->verbose) printf("package %s-%s.%s [%ld] is not installable (%s)\n", id2str(pool, s->name), id2str(pool, s->evr), id2str(pool, s->arch), (long int)(s - pool->solvables), dep2str(pool, req));
947 addrule(solv, -n, 0); /* mark requestor as uninstallable */
949 printf(">!> !unflag %s-%s.%s[%s]\n", id2str(pool, s->name), id2str(pool, s->evr), id2str(pool, s->arch), repo_name(s->repo));
954 printf("addrule %s-%s.%s %s %d %d\n", id2str(pool, s->name), id2str(pool, s->evr), id2str(pool, s->arch), dep2str(pool, req), -n, dp - pool->whatprovidesdata);
955 for (i = 0; dp[i]; i++)
956 printf(" %s-%s.%s\n", id2str(pool, pool->solvables[dp[i]].name), id2str(pool, pool->solvables[dp[i]].evr), id2str(pool, pool->solvables[dp[i]].arch));
958 /* add 'requires' dependency */
959 /* rule: (-requestor|provider1|provider2|...|providerN) */
960 addrule(solv, -n, dp - pool->whatprovidesdata);
962 /* descend the dependency tree */
963 for (; *dp; dp++) /* loop through all providers */
969 } /* while, requirements of n */
971 } /* if, requirements */
974 /*-----------------------------------------
975 * check conflicts of s
980 conp = s->repo->idarraydata + s->conflicts;
981 while ((con = *conp++) != 0)
983 FOR_PROVIDES(p, pp, con)
985 /* dontfix: dont care about conflicts with already installed packs */
986 if (dontfix && p >= installed->start && p < installed->start + installed->nsolvables)
988 /* rule: -n|-p: either solvable _or_ provider of conflict */
989 addrule(solv, -n, -p);
994 /*-----------------------------------------
995 * check obsoletes if not installed
997 if (!installed || n < installed->start || n >= (installed->start + installed->nsolvables))
998 { /* not installed */
1001 obsp = s->repo->idarraydata + s->obsoletes;
1002 while ((obs = *obsp++) != 0)
1004 FOR_PROVIDES(p, pp, obs)
1005 addrule(solv, -n, -p);
1008 FOR_PROVIDES(p, pp, s->name)
1010 if (s->name == pool->solvables[p].name)
1011 addrule(solv, -n, -p);
1015 /*-----------------------------------------
1016 * add recommends to the rule list
1020 recp = s->repo->idarraydata + s->recommends;
1021 while ((rec = *recp++) != 0)
1023 FOR_PROVIDES(p, pp, rec)
1030 sugp = s->repo->idarraydata + s->suggests;
1031 while ((sug = *sugp++) != 0)
1033 FOR_PROVIDES(p, pp, sug)
1043 addrulesforweak(Solver *solv, Map *m)
1045 Pool *pool = solv->pool;
1050 if (pool->verbose) printf("addrulesforweak... (%d)\n", solv->nrules);
1051 for (i = n = 1; n < pool->nsolvables; i++, n++)
1053 if (i == pool->nsolvables)
1057 s = pool->solvables + i;
1058 if (!pool_installable(pool, s))
1063 supp = s->repo->idarraydata + s->supplements;
1064 while ((sup = *supp++) != ID_NULL)
1065 if (dep_possible(solv, sup, m))
1068 if (!sup && s->freshens)
1070 supp = s->repo->idarraydata + s->freshens;
1071 while ((sup = *supp++) != ID_NULL)
1072 if (dep_possible(solv, sup, m))
1075 if (!sup && s->enhances)
1077 supp = s->repo->idarraydata + s->enhances;
1078 while ((sup = *supp++) != ID_NULL)
1079 if (dep_possible(solv, sup, m))
1084 addrulesforsolvable(solv, s, m);
1087 if (pool->verbose) printf("done. (%d)\n", solv->nrules);
1091 archchanges(Pool *pool, Solvable *s1, Solvable *s2)
1093 Id a1 = s1->arch, a2 = s2->arch;
1095 /* we allow changes to/from noarch */
1096 if (a1 == a2 || a1 == ARCH_NOARCH || a2 == ARCH_NOARCH)
1100 a1 = a1 <= pool->lastarch ? pool->id2arch[a1] : 0;
1101 a2 = a2 <= pool->lastarch ? pool->id2arch[a2] : 0;
1102 if (((a1 ^ a2) & 0xffff0000) != 0)
1108 findupdatepackages(Solver *solv, Solvable *s, Queue *qs, Map *m, int allowdowngrade, int allowarchchange, int allowvendorchange)
1110 /* installed packages get a special upgrade allowed rule */
1111 Pool *pool = solv->pool;
1112 Id p, *pp, n, p2, *pp2;
1122 n = s - pool->solvables;
1123 vendormask = pool_vendor2mask(pool, s->vendor);
1125 if (m && !MAPTST(m, n)) /* add rule for s if not already done */
1126 addrulesforsolvable(solv, s, m);
1129 * look for updates for s
1131 FOR_PROVIDES(p, pp, s->name) /* every provider of s' name */
1133 if (p == n) /* skip itself */
1136 ps = pool->solvables + p;
1137 if (s->name == ps->name) /* name match */
1139 if (!allowdowngrade /* consider downgrades ? */
1140 && evrcmp(pool, s->evr, ps->evr) > 0)
1143 if (!allowarchchange && archchanges(pool, s, ps))
1145 if (!allowvendorchange && s->vendor != ps->vendor && vendormask && (vendormask & pool_vendor2mask(pool, ps->vendor)) == 0)
1148 else if (!solv->noupdateprovide && ps->obsoletes) /* provides/obsoletes combination ? */
1150 obsp = ps->repo->idarraydata + ps->obsoletes;
1151 while ((obs = *obsp++) != 0) /* for all obsoletes */
1153 FOR_PROVIDES(p2, pp2, obs) /* and all matching providers of the obsoletes */
1155 if (p2 == n) /* match ! */
1158 if (p2) /* match! */
1161 if (!obs) /* continue if no match */
1163 /* here we have 'p' with a matching provides/obsoletes combination
1164 * thus flagging p as a valid update candidate for s
1171 if (m && !MAPTST(m, p)) /* mark p for install if not already done */
1172 addrulesforsolvable(solv, pool->solvables + p, m);
1174 if (solv->noupdateprovide && solv->obsoletes && solv->obsoletes[n - solv->installed->start])
1176 for (pp = solv->obsoletes_data + solv->obsoletes[n - solv->installed->start]; (p = *pp++) != 0;)
1179 if (m && !MAPTST(m, p)) /* mark p for install if not already done */
1180 addrulesforsolvable(solv, pool->solvables + p, m);
1186 * add rule for update
1187 * (A|A1|A2|A3...) An = update candidates for A
1189 * s = (installed) solvable
1190 * m = 'addedmap', bit set if 'install' rule for solvable exists
1194 addupdaterule(Solver *solv, Solvable *s, Map *m, int allowdowngrade, int allowarchchange, int allowvendorchange, int dontaddrule)
1196 /* installed packages get a special upgrade allowed rule */
1197 Pool *pool = solv->pool;
1203 queue_init_buffer(&qs, qsbuf, sizeof(qsbuf)/sizeof(*qsbuf));
1204 findupdatepackages(solv, s, &qs, m, allowdowngrade, allowarchchange, allowvendorchange);
1205 p = s - pool->solvables;
1206 if (dontaddrule) /* we consider update candidates but dont force them */
1212 if (qs.count == 0) /* no updates found */
1215 printf("new update rule: must keep %s-%s.%s\n", id2str(pool, s->name), id2str(pool, s->evr), id2str(pool, s->arch));
1217 addrule(solv, p, 0); /* request 'install' of s */
1222 d = pool_queuetowhatprovides(pool, &qs); /* intern computed provider queue */
1224 r = addrule(solv, p, d); /* allow update of s */
1226 printf("new update rule ");
1233 /*-----------------------------------------------------------------*/
1240 * initial setup for all watches
1244 makewatches(Solver *solv)
1248 int nsolvables = solv->pool->nsolvables;
1250 xfree(solv->watches);
1251 /* lower half for removals, upper half for installs */
1252 solv->watches = (Id *)xcalloc(2 * nsolvables, sizeof(Id));
1254 /* do it reverse so rpm rules get triggered first */
1255 for (i = 1, r = solv->rules + solv->nrules - 1; i < solv->nrules; i++, r--)
1257 for (i = 1, r = solv->rules + 1; i < solv->nrules; i++, r++)
1260 if (!r->w1 /* rule is disabled */
1261 || !r->w2) /* rule is assertion */
1264 /* see addwatches(solv, r) */
1265 r->n1 = solv->watches[nsolvables + r->w1];
1266 solv->watches[nsolvables + r->w1] = r - solv->rules;
1268 r->n2 = solv->watches[nsolvables + r->w2];
1269 solv->watches[nsolvables + r->w2] = r - solv->rules;
1275 * add watches (for rule)
1279 addwatches(Solver *solv, Rule *r)
1281 int nsolvables = solv->pool->nsolvables;
1283 r->n1 = solv->watches[nsolvables + r->w1];
1284 solv->watches[nsolvables + r->w1] = r - solv->rules;
1286 r->n2 = solv->watches[nsolvables + r->w2];
1287 solv->watches[nsolvables + r->w2] = r - solv->rules;
1291 /*-----------------------------------------------------------------*/
1292 /* rule propagation */
1294 #define DECISIONMAP_TRUE(p) ((p) > 0 ? (decisionmap[p] > 0) : (decisionmap[-p] < 0))
1299 * propagate decision to all rules
1303 propagate(Solver *solv, int level)
1305 Pool *pool = solv->pool;
1310 Id *decisionmap = solv->decisionmap;
1311 Id *watches = solv->watches + pool->nsolvables;
1313 while (solv->propagate_index < solv->decisionq.count)
1315 /* negative because our watches trigger if literal goes FALSE */
1316 pkg = -solv->decisionq.elements[solv->propagate_index++];
1318 printf("popagate for decision %d level %d\n", -pkg, level);
1319 printruleelement(solv, 0, -pkg);
1321 for (rp = watches + pkg; *rp; rp = nrp)
1323 r = solv->rules + *rp;
1325 printf(" watch triggered ");
1338 /* if clause is TRUE, nothing to do */
1339 if (DECISIONMAP_TRUE(ow))
1344 /* not a binary clause, check if we need to move our watch */
1345 if (r->p && r->p != ow && !DECISIONMAP_TRUE(-r->p))
1348 for (dp = pool->whatprovidesdata + r->d; (p = *dp++) != 0;)
1349 if (p != ow && !DECISIONMAP_TRUE(-p))
1353 /* p is free to watch, move watch to p */
1356 printf(" -> move w%d to %s-%s.%s\n", (pkg == r->w1 ? 1 : 2), id2str(pool, pool->solvables[p].name), id2str(pool, pool->solvables[p].evr), id2str(pool, pool->solvables[p].arch));
1358 printf(" -> move w%d to !%s-%s.%s\n", (pkg == r->w1 ? 1 : 2), id2str(pool, pool->solvables[-p].name), id2str(pool, pool->solvables[-p].evr), id2str(pool, pool->solvables[-p].arch));
1372 watches[p] = r - solv->rules;
1376 /* unit clause found, set other watch to TRUE */
1377 if (DECISIONMAP_TRUE(-ow))
1378 return r; /* eek, a conflict! */
1379 if (pool->verbose > 2)
1385 decisionmap[ow] = level;
1387 decisionmap[-ow] = -level;
1388 queue_push(&solv->decisionq, ow);
1389 queue_push(&solv->decisionq_why, r - solv->rules);
1392 Solvable *s = pool->solvables + (ow > 0 ? ow : -ow);
1394 printf(" -> decided to install %s-%s.%s\n", id2str(pool, s->name), id2str(pool, s->evr), id2str(pool, s->arch));
1396 printf(" -> decided to conflict %s-%s.%s\n", id2str(pool, s->name), id2str(pool, s->evr), id2str(pool, s->arch));
1401 return 0; /* all is well */
1405 /*-----------------------------------------------------------------*/
1414 analyze(Solver *solv, int level, Rule *c, int *pr, int *dr, int *why)
1416 Pool *pool = solv->pool;
1419 Map seen; /* global? */
1423 int learnt_why = solv->learnt_pool.count;
1424 Id *decisionmap = solv->decisionmap;
1428 if (pool->verbose > 1) printf("ANALYZE at %d ----------------------\n", level);
1429 map_init(&seen, pool->nsolvables);
1430 idx = solv->decisionq.count;
1433 if (pool->verbose > 1) printrule(solv, c);
1434 queue_push(&solv->learnt_pool, c - solv->rules);
1435 dp = c->d ? pool->whatprovidesdata + c->d : 0;
1446 if (DECISIONMAP_TRUE(v)) /* the one true literal */
1448 vv = v > 0 ? v : -v;
1449 if (MAPTST(&seen, vv))
1451 l = solv->decisionmap[vv];
1458 for (j = 0; j < solv->decisionq.count; j++)
1459 if (solv->decisionq.elements[j] == v)
1461 if (j == solv->decisionq.count)
1463 queue_push(&rulq, -(j + 1));
1465 continue; /* initial setting */
1469 num++; /* need to do this one as well */
1474 printf("PUSH %d ", v);
1475 printruleelement(solv, 0, v);
1482 printf("num = %d\n", num);
1488 v = solv->decisionq.elements[--idx];
1489 vv = v > 0 ? v : -v;
1490 if (MAPTST(&seen, vv))
1493 c = solv->rules + solv->decisionq_why.elements[idx];
1501 else if (r.count == 1 && r.elements[0] < 0)
1502 *dr = r.elements[0];
1504 *dr = pool_queuetowhatprovides(pool, &r);
1505 if (pool->verbose > 1)
1507 printf("learned rule for level %d (am %d)\n", rlevel, level);
1508 printruleelement(solv, 0, -v);
1509 for (i = 0; i < r.count; i++)
1512 printruleelement(solv, 0, v);
1516 queue_push(&solv->learnt_pool, 0);
1518 for (i = learnt_why; solv->learnt_pool.elements[i]; i++)
1520 printf("learnt_why ");
1521 printrule(solv, solv->rules + solv->learnt_pool.elements[i]);
1532 * reset the solver decisions to right after the rpm rules
1536 reset_solver(Solver *solv)
1541 /* delete all learnt rules */
1542 solv->nrules = solv->learntrules;
1543 queue_empty(&solv->learnt_why);
1544 queue_empty(&solv->learnt_pool);
1546 /* redo all direct rpm rule decisions */
1547 /* we break at the first decision with a why attached, this is
1548 * either a job/system rule decision of a propagated decision */
1549 for (i = 0; i < solv->decisionq.count; i++)
1551 v = solv->decisionq.elements[i];
1552 solv->decisionmap[v > 0 ? v : -v] = 0;
1554 for (i = 0; i < solv->decisionq_why.count; i++)
1555 if (solv->decisionq_why.elements[i])
1559 v = solv->decisionq.elements[i];
1560 solv->decisionmap[v > 0 ? v : -v] = v > 0 ? 1 : -1;
1563 if (solv->pool->verbose > 1)
1564 printf("decisions done reduced from %d to %d\n", solv->decisionq.count, i);
1566 solv->decisionq_why.count = i;
1567 solv->decisionq.count = i;
1568 solv->recommends_index = -1;
1569 solv->propagate_index = 0;
1571 /* redo all job/system decisions */
1572 makeruledecisions(solv);
1573 if (solv->pool->verbose > 1)
1574 printf("decisions after adding job and system rules: %d\n", solv->decisionq.count);
1575 /* recreate watches */
1581 * analyze_unsolvable_rule
1585 analyze_unsolvable_rule(Solver *solv, Rule *r)
1588 Id why = r - solv->rules;
1590 if (why >= solv->jobrules && why < solv->systemrules)
1592 if (why >= solv->systemrules && why < solv->weakrules)
1593 printf("SYSTEM %d ", why - solv->systemrules);
1594 if (why >= solv->weakrules && why < solv->learntrules)
1596 if (solv->learntrules && why >= solv->learntrules)
1600 if (solv->learntrules && why >= solv->learntrules)
1602 for (i = solv->learnt_why.elements[why - solv->learntrules]; solv->learnt_pool.elements[i]; i++)
1603 analyze_unsolvable_rule(solv, solv->rules + solv->learnt_pool.elements[i]);
1606 /* do not add rpm rules to problem */
1607 if (why < solv->jobrules)
1609 /* return if problem already countains the rule */
1610 if (solv->problems.count)
1612 for (i = solv->problems.count - 1; i >= 0; i--)
1613 if (solv->problems.elements[i] == 0)
1615 else if (solv->problems.elements[i] == why)
1618 queue_push(&solv->problems, why);
1623 * analyze_unsolvable
1625 * return: 1 - disabled some rules, try again
1630 analyze_unsolvable(Solver *solv, Rule *r, int disablerules)
1632 Pool *pool = solv->pool;
1633 Map seen; /* global? */
1636 Id *decisionmap = solv->decisionmap;
1637 int oldproblemcount;
1641 printf("ANALYZE UNSOLVABLE ----------------------\n");
1643 oldproblemcount = solv->problems.count;
1644 map_init(&seen, pool->nsolvables);
1645 analyze_unsolvable_rule(solv, r);
1646 dp = r->d ? pool->whatprovidesdata + r->d : 0;
1657 if (DECISIONMAP_TRUE(v)) /* the one true literal */
1659 vv = v > 0 ? v : -v;
1660 l = solv->decisionmap[vv];
1665 idx = solv->decisionq.count;
1668 v = solv->decisionq.elements[--idx];
1669 vv = v > 0 ? v : -v;
1670 if (!MAPTST(&seen, vv))
1672 why = solv->decisionq_why.elements[idx];
1677 printruleelement(solv, 0, v);
1681 r = solv->rules + why;
1682 analyze_unsolvable_rule(solv, r);
1683 dp = r->d ? pool->whatprovidesdata + r->d : 0;
1694 if (DECISIONMAP_TRUE(v)) /* the one true literal */
1696 vv = v > 0 ? v : -v;
1697 l = solv->decisionmap[vv];
1704 queue_push(&solv->problems, 0); /* mark end of this problem */
1707 if (solv->weakrules != solv->learntrules)
1709 for (i = oldproblemcount; i < solv->problems.count - 1; i++)
1711 why = solv->problems.elements[i];
1712 if (why < solv->weakrules || why >= solv->learntrules)
1714 if (!lastweak || lastweak < why)
1720 /* disable last weak rule */
1721 solv->problems.count = oldproblemcount;
1722 r = solv->rules + lastweak;
1723 printf("disabling weak ");
1729 else if (disablerules)
1731 for (i = oldproblemcount; i < solv->problems.count - 1; i++)
1733 r = solv->rules + solv->problems.elements[i];
1743 /*-----------------------------------------------------------------*/
1744 /* Decision revert */
1748 * revert decision at level
1752 revert(Solver *solv, int level)
1755 while (solv->decisionq.count)
1757 v = solv->decisionq.elements[solv->decisionq.count - 1];
1758 vv = v > 0 ? v : -v;
1759 if (solv->decisionmap[vv] <= level && solv->decisionmap[vv] >= -level)
1762 printf("reverting decision %d at %d\n", v, solv->decisionmap[vv]);
1764 solv->decisionmap[vv] = 0;
1765 solv->decisionq.count--;
1766 solv->decisionq_why.count--;
1767 solv->propagate_index = solv->decisionq.count;
1769 while (solv->minimize.count && solv->minimize.elements[solv->minimize.count - 1] < -level)
1771 solv->minimize.count--;
1772 while (solv->minimize.count && solv->minimize.elements[solv->minimize.count - 1] >= 0)
1773 solv->minimize.count--;
1775 solv->recommends_index = -1;
1780 * watch2onhighest - put watch2 on literal with highest level
1784 watch2onhighest(Solver *solv, Rule *r)
1790 return; /* binary rule, both watches are set */
1791 dp = solv->pool->whatprovidesdata + r->d;
1792 while ((v = *dp++) != 0)
1794 l = solv->decisionmap[v < 0 ? -v : v];
1811 setpropagatelearn(Solver *solv, int level, Id decision, int disablerules)
1821 solv->decisionmap[decision] = level;
1823 solv->decisionmap[-decision] = -level;
1824 queue_push(&solv->decisionq, decision);
1825 queue_push(&solv->decisionq_why, 0);
1829 r = propagate(solv, level);
1833 return analyze_unsolvable(solv, r, disablerules);
1834 printf("conflict with rule #%d\n", (int)(r - solv->rules));
1835 l = analyze(solv, level, r, &p, &d, &why);
1836 if (l >= level || l <= 0)
1838 printf("reverting decisions (level %d -> %d)\n", level, l);
1840 revert(solv, level);
1841 r = addrule(solv, p, d); /* p requires d */
1844 if (solv->learnt_why.count != (r - solv->rules) - solv->learntrules)
1846 printf("%d %d\n", solv->learnt_why.count, (int)(r - solv->rules) - solv->learntrules);
1849 queue_push(&solv->learnt_why, why);
1852 /* at least 2 literals, needs watches */
1853 watch2onhighest(solv, r);
1854 addwatches(solv, r);
1856 solv->decisionmap[p > 0 ? p : -p] = p > 0 ? level : -level;
1857 queue_push(&solv->decisionq, p);
1858 queue_push(&solv->decisionq_why, r - solv->rules);
1859 if (solv->pool->verbose > 1)
1861 printf("decision: ");
1862 printruleelement(solv, 0, p);
1863 printf("new rule: ");
1870 /*-----------------------------------------------------------------*/
1871 /* Main solver interface */
1876 * create solver structure
1878 * pool: all available solvables
1879 * installed: installed Solvables
1882 * Upon solving, rules are created to flag the Solvables
1883 * of the 'installed' Repo as installed.
1887 solver_create(Pool *pool, Repo *installed)
1890 solv = (Solver *)xcalloc(1, sizeof(Solver));
1892 solv->installed = installed;
1895 queue_init(&solv->ruletojob);
1896 queue_init(&solv->decisionq);
1897 queue_init(&solv->decisionq_why);
1898 queue_init(&solv->problems);
1899 queue_init(&solv->suggestions);
1900 queue_init(&solv->learnt_why);
1901 queue_init(&solv->learnt_pool);
1902 queue_init(&solv->minimize);
1904 map_init(&solv->recommendsmap, pool->nsolvables);
1905 map_init(&solv->suggestsmap, pool->nsolvables);
1906 solv->recommends_index = 0;
1908 solv->decisionmap = (Id *)xcalloc(pool->nsolvables, sizeof(Id));
1909 solv->rules = (Rule *)xmalloc((solv->nrules + (RULES_BLOCK + 1)) * sizeof(Rule));
1910 memset(solv->rules, 0, sizeof(Rule));
1922 solver_free(Solver *solv)
1924 queue_free(&solv->ruletojob);
1925 queue_free(&solv->decisionq);
1926 queue_free(&solv->decisionq_why);
1927 queue_free(&solv->learnt_why);
1928 queue_free(&solv->learnt_pool);
1929 queue_free(&solv->problems);
1930 queue_free(&solv->suggestions);
1931 queue_free(&solv->minimize);
1933 map_free(&solv->recommendsmap);
1934 map_free(&solv->suggestsmap);
1935 xfree(solv->decisionmap);
1937 xfree(solv->watches);
1938 xfree(solv->weaksystemrules);
1939 xfree(solv->obsoletes);
1940 xfree(solv->obsoletes_data);
1945 /*-------------------------------------------------------*/
1950 * all rules have been set up, now actually run the solver
1955 run_solver(Solver *solv, int disablerules, int doweak)
1963 Pool *pool = solv->pool;
1967 printf("number of rules: %d\n", solv->nrules);
1968 for (i = 0; i < solv->nrules; i++)
1969 printrule(solv, solv->rules + i);
1972 /* all new rules are learnt after this point */
1973 solv->learntrules = solv->nrules;
1974 /* crate watches lists */
1977 if (pool->verbose) printf("initial decisions: %d\n", solv->decisionq.count);
1979 /* start SAT algorithm */
1981 systemlevel = level + 1;
1982 if (pool->verbose) printf("solving...\n");
1993 if (pool->verbose) printf("propagating (%d %d)...\n", solv->propagate_index, solv->decisionq.count);
1994 if ((r = propagate(solv, level)) != 0)
1996 if (analyze_unsolvable(solv, r, disablerules))
1998 printf("UNSOLVABLE\n");
2005 * installed packages
2008 if (level < systemlevel && solv->installed->nsolvables)
2010 if (!solv->updatesystem)
2012 /* try to keep as many packages as possible */
2013 if (pool->verbose) printf("installing system packages\n");
2014 for (i = solv->installed->start, n = 0; ; i++, n++)
2016 if (n == solv->installed->nsolvables)
2018 if (i == solv->installed->start + solv->installed->nsolvables)
2019 i = solv->installed->start;
2020 s = pool->solvables + i;
2021 if (solv->decisionmap[i] != 0)
2024 printf("keeping %s-%s.%s\n", id2str(pool, s->name), id2str(pool, s->evr), id2str(pool, s->arch));
2027 level = setpropagatelearn(solv, level, i, disablerules);
2030 printf("UNSOLVABLE\n");
2034 if (level <= olevel)
2038 if (solv->weaksystemrules)
2040 if (pool->verbose) printf("installing weak system packages\n");
2041 for (i = solv->installed->start, n = 0; ; i++, n++)
2043 if (n == solv->installed->nsolvables)
2045 if (solv->decisionmap[i] > 0 || (solv->decisionmap[i] < 0 && solv->weaksystemrules[i - solv->installed->start] == 0))
2048 if (solv->weaksystemrules[i - solv->installed->start])
2050 dp = pool->whatprovidesdata + solv->weaksystemrules[i - solv->installed->start];
2051 while ((p = *dp++) != 0)
2053 if (solv->decisionmap[p] > 0)
2055 if (solv->decisionmap[p] == 0)
2059 continue; /* rule is already true */
2061 if (!dq.count && solv->decisionmap[i] != 0)
2065 prune_to_highest_prio(pool, &dq);
2067 prune_to_recommended(solv, &dq);
2068 /* FIXME we push it that late so that it doesn't get
2069 * pruned. should do things a bit different instead! */
2070 if (solv->decisionmap[i] == 0)
2073 prune_best_version_arch(pool, &dq);
2075 s = pool->solvables + dq.elements[0];
2076 printf("weak system installing %s-%s.%s\n", id2str(pool, s->name), id2str(pool, s->evr), id2str(pool, s->arch));
2079 level = setpropagatelearn(solv, level, dq.elements[0], disablerules);
2082 printf("UNSOLVABLE\n");
2086 if (level <= olevel)
2092 if (n != solv->installed->nsolvables)
2095 systemlevel = level;
2102 if (pool->verbose) printf("deciding unresolved rules\n");
2103 for (i = 1, n = 1; ; i++, n++)
2105 if (n == solv->nrules)
2107 if (i == solv->nrules)
2109 r = solv->rules + i;
2115 /* binary or unary rule */
2116 /* need two positive undecided literals */
2117 if (r->p < 0 || r->w2 <= 0)
2119 if (solv->decisionmap[r->p] || solv->decisionmap[r->w2])
2121 queue_push(&dq, r->p);
2122 queue_push(&dq, r->w2);
2127 * all negative literals are installed
2128 * no positive literal is installed
2129 * i.e. the rule is not fulfilled and we
2130 * just need to decide on the positive literals
2134 if (solv->decisionmap[-r->p] <= 0)
2139 if (solv->decisionmap[r->p] > 0)
2141 if (solv->decisionmap[r->p] == 0)
2142 queue_push(&dq, r->p);
2144 dp = pool->whatprovidesdata + r->d;
2145 while ((p = *dp++) != 0)
2149 if (solv->decisionmap[-p] <= 0)
2154 if (solv->decisionmap[p] > 0)
2156 if (solv->decisionmap[p] == 0)
2165 /* cannot happen as this means that
2166 * the rule is unit */
2170 if (pool->verbose > 2)
2172 prune_to_highest_prio(pool, &dq);
2174 prune_to_recommended(solv, &dq);
2176 prune_best_version_arch(pool, &dq);
2180 for (j = 1; j < dq.count; j++)
2181 queue_push(&solv->minimize, dq.elements[j]);
2182 queue_push(&solv->minimize, -level);
2185 s = pool->solvables + p;
2187 printf("installing %s-%s.%s\n", id2str(pool, s->name), id2str(pool, s->evr), id2str(pool, s->arch));
2190 level = setpropagatelearn(solv, level, p, disablerules);
2193 printf("UNSOLVABLE\n");
2197 if (level < systemlevel)
2200 } /* for(), decide */
2202 if (n != solv->nrules) /* continue if level < systemlevel */
2205 if (doweak && !solv->problems.count)
2209 if (pool->verbose) printf("installing recommended packages\n");
2211 for (i = 1; i < pool->nsolvables; i++)
2213 if (solv->decisionmap[i] < 0)
2215 if (solv->decisionmap[i] > 0)
2217 Id *recp, rec, *pp, p;
2218 s = pool->solvables + i;
2219 /* installed, check for recommends */
2220 /* XXX need to special case AND ? */
2223 recp = s->repo->idarraydata + s->recommends;
2224 while ((rec = *recp++) != 0)
2227 FOR_PROVIDES(p, pp, rec)
2229 if (solv->decisionmap[p] > 0)
2234 else if (solv->decisionmap[p] == 0)
2236 queue_pushunique(&dq, p);
2245 s = pool->solvables + i;
2246 if (!s->supplements && !s->freshens)
2248 if (!pool_installable(pool, s))
2252 supp = s->repo->idarraydata + s->supplements;
2253 while ((sup = *supp++) != 0)
2254 if (dep_fulfilled(solv, sup))
2261 supp = s->repo->idarraydata + s->freshens;
2262 while ((sup = *supp++) != 0)
2263 if (dep_fulfilled(solv, sup))
2268 queue_pushunique(&dq, i);
2274 prune_to_highest_prio(pool, &dq);
2276 prune_best_version_arch(pool, &dq);
2278 s = pool->solvables + p;
2280 printf("installing recommended %s-%s.%s\n", id2str(pool, s->name), id2str(pool, s->evr), id2str(pool, s->arch));
2282 level = setpropagatelearn(solv, level, p, 0);
2286 /* minimization step */
2287 if (solv->minimize.count)
2289 int l = 0, lasti = -1, lastl = -1;
2291 for (i = solv->minimize.count - 1; i >= 0; i--)
2293 p = solv->minimize.elements[i];
2296 else if (p > 0 && solv->decisionmap[p] > l + 1)
2304 /* kill old solvable so that we do not loop */
2305 p = solv->minimize.elements[lasti];
2306 solv->minimize.elements[lasti] = 0;
2307 s = pool->solvables + p;
2309 printf("minimizing %d -> %d with %s-%s.%s\n", solv->decisionmap[p], l, id2str(pool, s->name), id2str(pool, s->evr), id2str(pool, s->arch));
2312 revert(solv, level);
2314 level = setpropagatelearn(solv, level, p, disablerules);
2317 printf("UNSOLVABLE\n");
2335 refine_suggestion(Solver *solv, Id *problem, Id sug, Queue *refined)
2338 int i, j, sugseen, sugjob = -1;
2343 printf("refine_suggestion start\n");
2345 if (sug >= solv->jobrules && sug < solv->systemrules)
2346 sugjob = solv->ruletojob.elements[sug - solv->jobrules];
2348 queue_init(&disabled);
2349 queue_empty(refined);
2350 queue_push(refined, sug);
2352 /* re-enable all rules but rule "sug" of the problem */
2358 r = solv->rules + sug;
2362 for (i = 0; problem[i]; i++)
2364 if (problem[i] == sug)
2369 if (sugjob >= 0 && problem[i] >= solv->jobrules && problem[i] < solv->systemrules && sugjob == solv->ruletojob.elements[problem[i] - solv->jobrules])
2371 /* rule belongs to same job */
2374 r = solv->rules + problem[i];
2381 /* direct assertion */
2382 if (r->p == sugassert && sugseen)
2384 /* also leave this assertion disabled */
2387 v = r->p > 0 ? r->p : -r->p;
2388 if (solv->decisionmap[v])
2390 if ((solv->decisionmap[v] > 0 && r->p < 0) ||
2391 (solv->decisionmap[v] < 0 && r->p > 0))
2393 printf("direct assertion failure, no solution found!\n");
2396 r = solv->rules + problem[i];
2403 if (r->d == 0 || r->w2 != r->p)
2406 r->w1 = solv->pool->whatprovidesdata[r->d];
2410 /* re-enable as many weak rules as possible */
2411 for (i = solv->weakrules; i < solv->learntrules; i++)
2413 r = solv->rules + i;
2416 if (r->d == 0 || r->w2 != r->p)
2419 r->w1 = solv->pool->whatprovidesdata[r->d];
2422 queue_empty(&solv->problems);
2423 revert(solv, 1); /* XXX move to reset_solver? */
2425 run_solver(solv, 0, 0);
2426 if (!solv->problems.count)
2428 printf("no more problems!\n");
2430 printdecisions(solv);
2432 break; /* great, no more problems */
2434 disabledcnt = disabled.count;
2435 for (i = 0; i < solv->problems.elements[i]; i++)
2437 /* ignore solutions in refined */
2438 v = solv->problems.elements[i];
2439 for (j = 0; problem[j]; j++)
2440 if (problem[j] != sug && problem[j] == v)
2444 queue_push(&disabled, v);
2445 queue_push(&disabled, 0); /* room for watch */
2447 if (disabled.count == disabledcnt)
2449 /* no solution found, this was an invalid suggestion! */
2450 printf("no solution found!\n");
2454 if (disabled.count == disabledcnt + 2)
2456 /* just one suggestion, add it to refined list */
2457 queue_push(refined, disabled.elements[disabledcnt]);
2462 printf("############################################## more than one solution found.\n");
2463 for (i = 0; i < solv->problems.elements[i]; i++)
2464 printrule(solv, solv->rules + solv->problems.elements[i]);
2465 printf("##############################################\n");
2467 /* more than one solution, keep all disabled */
2469 for (i = disabledcnt; i < disabled.count; i += 2)
2472 r = solv->rules + disabled.elements[i];
2473 disabled.elements[i + 1] = r->w1;
2481 /* enable refined rules again */
2482 for (i = 0; i < disabled.count; i += 2)
2484 r = solv->rules + disabled.elements[i];
2485 r->w1 = disabled.elements[i + 1];
2487 /* disable problem rules again so that we are in the same state as before */
2488 for (i = 0; problem[i]; i++)
2490 r = solv->rules + problem[i];
2493 printf("refine_suggestion end\n");
2502 id2rc(Solver *solv, Id id)
2505 if (solv->rc_output != 2)
2507 evr = id2str(solv->pool, id);
2508 if (*evr < '0' || *evr > '9')
2510 while (*evr >= '0' && *evr <= '9')
2518 printdecisions(Solver *solv)
2520 Pool *pool = solv->pool;
2521 Id p, *obsoletesmap;
2525 obsoletesmap = (Id *)xcalloc(pool->nsolvables, sizeof(Id));
2526 for (i = 0; i < solv->decisionq.count; i++)
2530 n = solv->decisionq.elements[i];
2533 if (n == SYSTEMSOLVABLE)
2535 if (n >= solv->installed->start && n < solv->installed->start + solv->installed->nsolvables)
2537 s = pool->solvables + n;
2538 FOR_PROVIDES(p, pp, s->name)
2539 if (s->name == pool->solvables[p].name)
2541 if (p >= solv->installed->start && p < solv->installed->start + solv->installed->nsolvables && !obsoletesmap[p])
2543 obsoletesmap[p] = n;
2548 for (i = 0; i < solv->decisionq.count; i++)
2553 n = solv->decisionq.elements[i];
2556 if (n == SYSTEMSOLVABLE)
2558 if (n >= solv->installed->start && n < solv->installed->start + solv->installed->nsolvables)
2560 s = pool->solvables + n;
2563 obsp = s->repo->idarraydata + s->obsoletes;
2564 while ((obs = *obsp++) != 0)
2565 FOR_PROVIDES(p, pp, obs)
2567 if (p >= solv->installed->start && p < solv->installed->start + solv->installed->nsolvables && !obsoletesmap[p])
2569 obsoletesmap[p] = n;
2575 if (solv->rc_output)
2576 printf(">!> Solution #1:\n");
2578 int installs = 0, uninstalls = 0, upgrades = 0;
2580 /* print solvables to be erased */
2582 for (i = solv->installed->start; i < solv->installed->start + solv->installed->nsolvables; i++)
2584 if (solv->decisionmap[i] > 0)
2586 if (obsoletesmap[i])
2588 s = pool->solvables + i;
2589 if (solv->rc_output == 2)
2590 printf(">!> remove %s-%s%s\n", id2str(pool, s->name), id2rc(solv, s->evr), id2str(pool, s->evr));
2591 else if (solv->rc_output)
2592 printf(">!> remove %s-%s.%s\n", id2str(pool, s->name), id2str(pool, s->evr), id2str(pool, s->arch));
2594 printf("erase %s-%s.%s\n", id2str(pool, s->name), id2str(pool, s->evr), id2str(pool, s->arch));
2598 /* print solvables to be installed */
2600 for (i = 0; i < solv->decisionq.count; i++)
2603 p = solv->decisionq.elements[i];
2606 if (p == SYSTEMSOLVABLE)
2608 if (p >= solv->installed->start && p < solv->installed->start + solv->installed->nsolvables)
2610 s = pool->solvables + p;
2612 if (!obsoletesmap[p])
2614 if (solv->rc_output)
2616 printf("install %s-%s%s", id2str(pool, s->name), id2rc(solv, s->evr), id2str(pool, s->evr));
2617 if (solv->rc_output != 2)
2618 printf(".%s", id2str(pool, s->arch));
2621 else if (!solv->rc_output)
2623 printf("update %s-%s.%s (obsoletes", id2str(pool, s->name), id2str(pool, s->evr), id2str(pool, s->arch));
2624 for (j = solv->installed->start; j < solv->installed->start + solv->installed->nsolvables; j++)
2626 if (obsoletesmap[j] != p)
2628 s = pool->solvables + j;
2629 printf(" %s-%s.%s", id2str(pool, s->name), id2str(pool, s->evr), id2str(pool, s->arch));
2636 Solvable *f, *fn = 0;
2637 for (j = solv->installed->start; j < solv->installed->start + solv->installed->nsolvables; j++)
2639 if (obsoletesmap[j] != p)
2641 f = pool->solvables + j;
2642 if (fn || f->name != s->name)
2644 if (solv->rc_output == 2)
2645 printf(">!> remove %s-%s%s\n", id2str(pool, f->name), id2rc(solv, f->evr), id2str(pool, f->evr));
2646 else if (solv->rc_output)
2647 printf(">!> remove %s-%s.%s\n", id2str(pool, f->name), id2str(pool, f->evr), id2str(pool, f->arch));
2655 printf(">!> install %s-%s%s", id2str(pool, s->name), id2rc(solv, s->evr), id2str(pool, s->evr));
2656 if (solv->rc_output != 2)
2657 printf(".%s", id2str(pool, s->arch));
2662 if (solv->rc_output == 2)
2663 printf(">!> upgrade %s-%s => %s-%s%s", id2str(pool, fn->name), id2str(pool, fn->evr), id2str(pool, s->name), id2rc(solv, s->evr), id2str(pool, s->evr));
2665 printf(">!> upgrade %s-%s.%s => %s-%s.%s", id2str(pool, fn->name), id2str(pool, fn->evr), id2str(pool, fn->arch), id2str(pool, s->name), id2str(pool, s->evr), id2str(pool, s->arch));
2669 if (solv->rc_output)
2671 Repo *repo = s->repo;
2672 if (repo && strcmp(repo_name(repo), "locales"))
2673 printf("[%s]", repo_name(repo));
2678 if (solv->rc_output)
2679 printf(">!> installs=%d, upgrades=%d, uninstalls=%d\n", installs, upgrades, uninstalls);
2681 xfree(obsoletesmap);
2685 create_obsolete_index(Solver *solv)
2687 Pool *pool = solv->pool;
2689 Repo *installed = solv->installed;
2690 Id p, *pp, obs, *obsp, *obsoletes, *obsoletes_data;
2693 /* create reverse obsoletes map for installed solvables */
2694 solv->obsoletes = obsoletes = xcalloc(installed->nsolvables, sizeof(Id));
2695 for (i = 1; i < pool->nsolvables; i++)
2697 s = pool->solvables + i;
2700 if (!pool_installable(pool, s))
2702 obsp = s->repo->idarraydata + s->obsoletes;
2703 while ((obs = *obsp++) != 0)
2704 FOR_PROVIDES(p, pp, obs)
2706 if (p < installed->start || p >= installed->start + installed->nsolvables)
2708 if (pool->solvables[p].name == s->name)
2710 obsoletes[p - installed->start]++;
2714 for (i = 0; i < installed->nsolvables; i++)
2717 n += obsoletes[i] + 1;
2720 solv->obsoletes_data = obsoletes_data = xcalloc(n + 1, sizeof(Id));
2721 if (pool->verbose) printf("obsoletes data: %d entries\n", n + 1);
2722 for (i = pool->nsolvables - 1; i > 0; i--)
2724 s = pool->solvables + i;
2727 if (!pool_installable(pool, s))
2729 obsp = s->repo->idarraydata + s->obsoletes;
2730 while ((obs = *obsp++) != 0)
2731 FOR_PROVIDES(p, pp, obs)
2733 if (p < installed->start || p >= installed->start + installed->nsolvables)
2735 if (pool->solvables[p].name == s->name)
2737 p -= installed->start;
2738 if (obsoletes_data[obsoletes[p]] != i)
2739 obsoletes_data[--obsoletes[p]] = i;
2744 /*-----------------------------------------------------------------*/
2754 solve(Solver *solv, Queue *job)
2756 Pool *pool = solv->pool;
2758 Map addedmap; /* '1' == have rule for solvable */
2759 Map noupdaterule; /* '1' == don't update (scheduled for removal) */
2760 Id how, what, p, *pp, d;
2766 * create basic rule set of all involved packages
2771 map_init(&addedmap, pool->nsolvables);
2772 map_init(&noupdaterule, pool->nsolvables);
2777 * always install our system solvable
2779 MAPSET(&addedmap, SYSTEMSOLVABLE);
2780 queue_push(&solv->decisionq, SYSTEMSOLVABLE);
2781 queue_push(&solv->decisionq_why, 0);
2782 solv->decisionmap[SYSTEMSOLVABLE] = 1;
2785 * create rules for installed solvables -> keep them installed
2786 * so called: rpm rules
2790 for (i = solv->installed->start; i < solv->installed->start + solv->installed->nsolvables; i++)
2791 addrulesforsolvable(solv, pool->solvables + i, &addedmap);
2794 * create install rules
2796 * two passes, as we want to keep the rpm rules distinct from the job rules
2800 if (solv->noupdateprovide && solv->installed->nsolvables)
2801 create_obsolete_index(solv);
2805 * process job rules for solvables
2808 for (i = 0; i < job->count; i += 2)
2810 how = job->elements[i];
2811 what = job->elements[i + 1];
2815 case SOLVER_INSTALL_SOLVABLE:
2816 addrulesforsolvable(solv, pool->solvables + what, &addedmap);
2818 case SOLVER_INSTALL_SOLVABLE_NAME:
2819 case SOLVER_INSTALL_SOLVABLE_PROVIDES:
2821 FOR_PROVIDES(p, pp, what)
2823 /* if by name, ensure that the name matches */
2824 if (how == SOLVER_INSTALL_SOLVABLE_NAME && pool->solvables[p].name != what)
2826 addrulesforsolvable(solv, pool->solvables + p, &addedmap);
2829 case SOLVER_INSTALL_SOLVABLE_UPDATE:
2830 /* dont allow downgrade */
2831 addupdaterule(solv, pool->solvables + what, &addedmap, 0, 0, 0, 1);
2837 * if unstalls are disallowed, add update rules for every
2838 * installed solvables in the hope to circumvent uninstall
2844 if (!solv->allowuninstall)
2846 /* add update rule for every installed package */
2847 for (i = solv->installed->start; i < solv->installed->start + solv->installed->nsolvables; i++)
2848 addupdaterule(solv, pool->solvables + i, &addedmap, solv->allowdowngrade, solv->allowarchchange, solv->allowvendorchange, 1);
2850 #else /* this is just to add the needed rpm rules to our set */
2851 for (i = solv->installed->start; i < solv->installed->start + solv->installed->nsolvables; i++)
2852 addupdaterule(solv, pool->solvables + i, &addedmap, 1, 1, 1, 1);
2855 addrulesforweak(solv, &addedmap);
2859 int possible = 0, installable = 0;
2860 for (i = 1; i < pool->nsolvables; i++)
2862 if (pool_installable(pool, pool->solvables + i))
2864 if (MAPTST(&addedmap, i))
2867 printf("%d of %d installable solvables used for solving\n", possible, installable);
2874 * unify existing rules before going over all job rules
2878 unifyrules(solv); /* remove duplicate rpm rules */
2881 * at this point the system is always solvable,
2882 * as an empty system (remove all packages) is a valid solution
2884 if (pool->verbose) printf("decisions based on rpms: %d\n", solv->decisionq.count);
2887 * now add all job rules
2890 solv->jobrules = solv->nrules;
2892 for (i = 0; i < job->count; i += 2)
2894 how = job->elements[i];
2895 what = job->elements[i + 1];
2898 case SOLVER_INSTALL_SOLVABLE: /* install specific solvable */
2899 s = pool->solvables + what;
2900 if (solv->rc_output)
2902 printf(">!> Installing %s from channel %s\n", id2str(pool, s->name), repo_name(s->repo));
2905 printf("job: install solvable %s-%s.%s\n", id2str(pool, s->name), id2str(pool, s->evr), id2str(pool, s->arch));
2906 addrule(solv, what, 0); /* install by Id */
2907 queue_push(&solv->ruletojob, i);
2908 FOR_PROVIDES(p, pp, s->name)
2909 if (pool->solvables[p].name == s->name)
2910 MAPSET(&noupdaterule, p);
2912 case SOLVER_ERASE_SOLVABLE:
2913 s = pool->solvables + what;
2915 printf("job: erase solvable %s-%s.%s\n", id2str(pool, s->name), id2str(pool, s->evr), id2str(pool, s->arch));
2916 addrule(solv, -what, 0); /* remove by Id */
2917 queue_push(&solv->ruletojob, i);
2918 MAPSET(&noupdaterule, what);
2920 case SOLVER_INSTALL_SOLVABLE_NAME: /* install by capability */
2921 case SOLVER_INSTALL_SOLVABLE_PROVIDES:
2922 if (pool->verbose && how == SOLVER_INSTALL_SOLVABLE_NAME)
2923 printf("job: install name %s\n", id2str(pool, what));
2924 if (pool->verbose && how == SOLVER_INSTALL_SOLVABLE_PROVIDES)
2925 printf("job: install provides %s\n", dep2str(pool, what));
2927 FOR_PROVIDES(p, pp, what)
2929 /* if by name, ensure that the name matches */
2930 if (how == SOLVER_INSTALL_SOLVABLE_NAME && pool->solvables[p].name != what)
2936 /* no provider, make this an impossible rule */
2937 queue_push(&q, -SYSTEMSOLVABLE);
2940 p = queue_shift(&q); /* get first provider */
2942 d = 0; /* single provider ? -> make assertion */
2944 d = pool_queuetowhatprovides(pool, &q); /* get all providers */
2945 addrule(solv, p, d); /* add 'requires' rule */
2946 queue_push(&solv->ruletojob, i);
2948 case SOLVER_ERASE_SOLVABLE_NAME: /* remove by capability */
2949 case SOLVER_ERASE_SOLVABLE_PROVIDES:
2950 if (pool->verbose && how == SOLVER_ERASE_SOLVABLE_NAME)
2951 printf("job: erase name %s\n", id2str(pool, what));
2952 if (pool->verbose && how == SOLVER_ERASE_SOLVABLE_PROVIDES)
2953 printf("job: erase provides %s\n", dep2str(pool, what));
2954 FOR_PROVIDES(p, pp, what)
2956 /* if by name, ensure that the name matches */
2957 if (how == SOLVER_ERASE_SOLVABLE_NAME && pool->solvables[p].name != what)
2960 addrule(solv, -p, 0); /* add 'remove' rule */
2961 queue_push(&solv->ruletojob, i);
2962 MAPSET(&noupdaterule, p);
2965 case SOLVER_INSTALL_SOLVABLE_UPDATE: /* find update for solvable */
2966 s = pool->solvables + what;
2967 MAPSET(&noupdaterule, what);
2969 printf("job: update %s-%s.%s\n", id2str(pool, s->name), id2str(pool, s->evr), id2str(pool, s->arch));
2970 addupdaterule(solv, s, &addedmap, 0, 0, 0, 0);
2971 queue_push(&solv->ruletojob, i);
2976 if (solv->ruletojob.count != solv->nrules - solv->jobrules)
2979 if (pool->verbose) printf("problems so far: %d\n", solv->problems.count);
2982 * now add policy rules
2986 solv->systemrules = solv->nrules;
2989 * create rules for updating installed solvables
2995 if (!solv->allowuninstall)
2996 { /* loop over all installed solvables */
2997 for (i = solv->installed->start; i < solv->installed->start + solv->installed->nsolvables; i++)
2999 if (!MAPTST(&noupdaterule, i)) /* if not marked as 'noupdate' */
3000 addupdaterule(solv, pool->solvables + i, &addedmap, solv->allowdowngrade, solv->allowarchchange, solv->allowvendorchange, 0);
3002 addrule(solv, 0, 0); /* place holder */
3004 /* consistency check: we added a rule for _every_ system solvable */
3005 if (solv->nrules - solv->systemrules != solv->installed->nsolvables)
3009 if (pool->verbose) printf("problems so far: %d\n", solv->problems.count);
3011 /* create special weak system rules */
3012 if (solv->installed->nsolvables)
3014 solv->weaksystemrules = xcalloc(solv->installed->nsolvables, sizeof(Id));
3015 for (i = 0; i < solv->installed->nsolvables; i++)
3017 if (MAPTST(&noupdaterule, solv->installed->start + i))
3019 findupdatepackages(solv, pool->solvables + solv->installed->start + i, &q, (Map *)0, 1, 1, 1);
3021 solv->weaksystemrules[i] = pool_queuetowhatprovides(pool, &q);
3025 /* free unneeded memory */
3026 map_free(&addedmap);
3027 map_free(&noupdaterule);
3030 solv->weakrules = solv->nrules;
3032 /* try real hard to keep packages installed */
3035 for (i = 0; i < solv->installed->nsolvables; i++)
3037 d = solv->weaksystemrules[i];
3038 addrule(solv, solv->installed->start + i, d);
3047 makeruledecisions(solv);
3048 run_solver(solv, 1, 1);
3050 /* find suggested packages */
3051 if (!solv->problems.count)
3053 Id sug, *sugp, enh, *enhp, p, *pp;
3055 /* create map of all suggests that are still open */
3056 solv->recommends_index = -1;
3057 MAPZERO(&solv->suggestsmap);
3058 for (i = 0; i < solv->decisionq.count; i++)
3060 p = solv->decisionq.elements[i];
3063 s = pool->solvables + p;
3066 sugp = s->repo->idarraydata + s->suggests;
3067 while ((sug = *sugp++) != 0)
3069 FOR_PROVIDES(p, pp, sug)
3070 if (solv->decisionmap[p] > 0)
3073 continue; /* already fulfilled */
3074 FOR_PROVIDES(p, pp, sug)
3075 MAPSET(&solv->suggestsmap, p);
3079 for (i = 1; i < pool->nsolvables; i++)
3081 if (solv->decisionmap[i] != 0)
3083 s = pool->solvables + i;
3084 if (!MAPTST(&solv->suggestsmap, i))
3088 if (!pool_installable(pool, s))
3090 enhp = s->repo->idarraydata + s->enhances;
3091 while ((enh = *enhp++) != 0)
3092 if (dep_fulfilled(solv, enh))
3097 queue_push(&solv->suggestions, i);
3099 prune_best_version_arch(pool, &solv->suggestions);
3104 * print solver result
3108 if (pool->verbose) printf("-------------------------------------------------------------\n");
3110 if (solv->problems.count)
3120 queue_clone(&problems, &solv->problems);
3121 queue_init(&solution);
3122 printf("Encountered problems! Here are the solutions:\n");
3123 problem = problems.elements;
3126 printf("Problem %d:\n", pcnt);
3127 printf("====================================\n");
3128 for (i = 0; i < problems.count; i++)
3130 Id v = problems.elements[i];
3134 if (i + 1 == problems.count)
3136 printf("Problem %d:\n", ++pcnt);
3137 printf("====================================\n");
3138 problem = problems.elements + i + 1;
3141 if (v >= solv->jobrules && v < solv->systemrules)
3143 ji = solv->ruletojob.elements[v - solv->jobrules];
3146 if (problem[j] >= solv->jobrules && problem[j] < solv->systemrules && ji == solv->ruletojob.elements[problem[j] - solv->jobrules])
3149 if (problem + j < problems.elements + i)
3152 refine_suggestion(solv, problem, v, &solution);
3153 for (j = 0; j < solution.count; j++)
3155 r = solv->rules + solution.elements[j];
3156 why = solution.elements[j];
3160 if (why >= solv->jobrules && why < solv->systemrules)
3162 ji = solv->ruletojob.elements[why - solv->jobrules];
3163 what = job->elements[ji + 1];
3164 switch (job->elements[ji])
3166 case SOLVER_INSTALL_SOLVABLE:
3167 s = pool->solvables + what;
3168 if (what >= solv->installed->start && what < solv->installed->start + solv->installed->nsolvables)
3169 printf("- do not keep %s-%s.%s installed\n", id2str(pool, s->name), id2str(pool, s->evr), id2str(pool, s->arch));
3171 printf("- do not install %s-%s.%s\n", id2str(pool, s->name), id2str(pool, s->evr), id2str(pool, s->arch));
3173 case SOLVER_ERASE_SOLVABLE:
3174 s = pool->solvables + what;
3175 if (what >= solv->installed->start && what < solv->installed->start + solv->installed->nsolvables)
3176 printf("- do not deinstall %s-%s.%s\n", id2str(pool, s->name), id2str(pool, s->evr), id2str(pool, s->arch));
3178 printf("- do not forbid installation of %s-%s.%s\n", id2str(pool, s->name), id2str(pool, s->evr), id2str(pool, s->arch));
3180 case SOLVER_INSTALL_SOLVABLE_NAME:
3181 printf("- do not install %s\n", id2str(pool, what));
3183 case SOLVER_ERASE_SOLVABLE_NAME:
3184 printf("- do not deinstall %s\n", id2str(pool, what));
3186 case SOLVER_INSTALL_SOLVABLE_PROVIDES:
3187 printf("- do not install a solvable providing %s\n", dep2str(pool, what));
3189 case SOLVER_ERASE_SOLVABLE_PROVIDES:
3190 printf("- do not deinstall all solvables providing %s\n", dep2str(pool, what));
3192 case SOLVER_INSTALL_SOLVABLE_UPDATE:
3193 s = pool->solvables + what;
3194 printf("- do not install most recent version of %s-%s.%s\n", id2str(pool, s->name), id2str(pool, s->evr), id2str(pool, s->arch));
3197 printf("- do something different\n");
3201 else if (why >= solv->systemrules && why < solv->weakrules)
3204 s = pool->solvables + solv->installed->start + (why - solv->systemrules);
3205 if (solv->weaksystemrules && solv->weaksystemrules[why - solv->systemrules])
3207 Id *dp = pool->whatprovidesdata + solv->weaksystemrules[why - solv->systemrules];
3210 if (*dp >= solv->installed->start && *dp < solv->installed->start + solv->installed->nsolvables)
3212 if (solv->decisionmap[*dp] > 0)
3214 sd = pool->solvables + *dp;
3222 if (evrcmp(pool, sd->evr, s->evr) < 0)
3224 printf("- allow downgrade of %s-%s.%s to %s-%s.%s\n", id2str(pool, s->name), id2str(pool, s->evr), id2str(pool, s->arch), id2str(pool, sd->name), id2str(pool, sd->evr), id2str(pool, sd->arch));
3227 if (!solv->allowarchchange && s->name == sd->name && archchanges(pool, sd, s))
3229 printf("- allow architecture change of %s-%s.%s to %s-%s.%s\n", id2str(pool, s->name), id2str(pool, s->evr), id2str(pool, s->arch), id2str(pool, sd->name), id2str(pool, sd->evr), id2str(pool, sd->arch));
3232 if (!solv->allowvendorchange && s->name == sd->name && s->vendor != sd->vendor && pool_vendor2mask(pool, s->vendor) && (pool_vendor2mask(pool, s->vendor) & pool_vendor2mask(pool, sd->vendor)) == 0)
3235 printf("- allow vendor change from '%s' (%s-%s.%s) to '%s' (%s-%s.%s)\n", id2str(pool, s->vendor), id2str(pool, s->name), id2str(pool, s->evr), id2str(pool, s->arch), id2str(pool, sd->vendor), id2str(pool, sd->name), id2str(pool, sd->evr), id2str(pool, sd->arch));
3237 printf("- allow vendor change from '%s' (%s-%s.%s) to no vendor (%s-%s.%s)\n", id2str(pool, s->vendor), id2str(pool, s->name), id2str(pool, s->evr), id2str(pool, s->arch), id2str(pool, sd->name), id2str(pool, sd->evr), id2str(pool, sd->arch));
3241 printf("- allow replacement of %s-%s.%s with %s-%s.%s\n", id2str(pool, s->name), id2str(pool, s->evr), id2str(pool, s->arch), id2str(pool, sd->name), id2str(pool, sd->evr), id2str(pool, sd->arch));
3245 printf("- allow deinstallation of %s-%s.%s [%ld]\n", id2str(pool, s->name), id2str(pool, s->evr), id2str(pool, s->arch), (long int)(s - pool->solvables));
3253 printf("------------------------------------\n");
3255 queue_free(&solution);
3256 queue_free(&problems);
3260 printdecisions(solv);
3261 if (solv->suggestions.count)
3263 printf("\nsuggested packages:\n");
3264 for (i = 0; i < solv->suggestions.count; i++)
3266 s = pool->solvables + solv->suggestions.elements[i];
3267 printf("- %s-%s.%s\n", id2str(pool, s->name), id2str(pool, s->evr), id2str(pool, s->arch));