4 * SAT based dependency solver
18 #define RULES_BLOCK 63
20 static Pool *prune_best_version_arch_sortcmp_data;
22 /*-----------------------------------------------------------------*/
25 * prep for prune_best_version_arch
30 prune_best_version_arch_sortcmp(const void *ap, const void *bp)
32 Pool *pool = prune_best_version_arch_sortcmp_data;
35 return pool->solvables[a].name - pool->solvables[b].name;
41 replaces_system(Solver *solv, Id id)
43 Pool *pool = solv->pool;
44 Source *system = solv->system;
45 Id *name = pool->solvables[id].name;
47 FOR_PROVIDES(p, pp, id)
49 s = pool->solvables + p;
52 if (p >= system->start && p < system->start + system->nsolvables)
59 * prune_best_version_arch
61 * sort list of packages (given through plist) by name and evr
62 * return result through plist
66 /* FIXME: must also look at update packages */
69 prune_best_version_arch(Pool *pool, Queue *plist)
76 if (plist->count < 2) /* no need to prune for a single entry */
78 if (pool->verbose) printf("prune_best_version_arch %d\n", plist->count);
80 /* prune to best architecture */
84 for (i = 0; i < plist->count; i++)
86 s = pool->solvables + plist->elements[i];
88 if (a > pool->lastarch)
91 if ((a & 0xffff0000) > bestscore)
92 bestscore = a & 0xffff0000;
94 for (i = j = 0; i < plist->count; i++)
96 s = pool->solvables + plist->elements[i];
98 if (a > pool->lastarch)
100 a = pool->id2arch[a];
101 /* a == 1 -> noarch */
102 if (a != 1 && (a & 0xffff0000) != bestscore)
104 plist->elements[j++] = plist->elements[i];
111 prune_best_version_arch_sortcmp_data = pool;
112 /* sort by name first */
113 qsort(plist->elements, plist->count, sizeof(Id), prune_best_version_arch_sortcmp);
115 /* now find best 'per name' */
116 for (i = j = 0; i < plist->count; i++)
118 s = pool->solvables + plist->elements[i];
119 if (s->arch == ARCH_SRC || s->arch == ARCH_NOSRC)
122 if (pool->verbose) printf("- %s-%s.%s\n", id2str(pool, s->name), id2str(pool, s->evr), id2str(pool, s->arch));
124 if (!best) /* if no best yet, the current is best */
126 best = plist->elements[i];
130 /* name switch: re-init */
131 if (pool->solvables[best].name != s->name) /* new name */
133 if (pool->verbose) printf("BEST: %s-%s.%s\n", id2str(pool, pool->solvables[best].name), id2str(pool, pool->solvables[best].evr), id2str(pool, pool->solvables[best].arch));
134 plist->elements[j++] = best; /* move old best to front */
135 best = plist->elements[i]; /* take current as new best */
139 if (pool->solvables[best].evr != s->evr) /* compare evr */
141 if (evrcmp(pool, pool->solvables[best].evr, s->evr) < 0)
142 best = plist->elements[i];
147 best = plist->elements[0];
149 /* XXX also check obsoletes! */
150 if (pool->verbose) printf("BEST: %s-%s.%s\n", id2str(pool, pool->solvables[best].name), id2str(pool, pool->solvables[best].evr), id2str(pool, pool->solvables[best].arch));
152 plist->elements[j++] = best;
157 /*-----------------------------------------------------------------*/
164 printruleelement(Solver *solv, Rule *r, Id v)
166 Pool *pool = solv->pool;
170 s = pool->solvables + -v;
171 printf(" !%s-%s.%s [%d]", id2str(pool, s->name), id2str(pool, s->evr), id2str(pool, s->arch), -v);
175 s = pool->solvables + v;
176 printf(" %s-%s.%s [%d]", id2str(pool, s->name), id2str(pool, s->evr), id2str(pool, s->arch), v);
185 if (solv->decisionmap[s - pool->solvables] > 0)
186 printf(" I.%d", solv->decisionmap[s - pool->solvables]);
187 if (solv->decisionmap[s - pool->solvables] < 0)
188 printf(" C.%d", -solv->decisionmap[s - pool->solvables]);
198 printrule(Solver *solv, Rule *r)
203 if (r >= solv->rules && r < solv->rules + solv->nrules) /* r is a solver rule */
204 printf("Rule #%d:\n", (int)(r - solv->rules));
206 printf("Rule:\n"); /* r is any rule */
211 else if (r->d == ID_NULL)
218 v = solv->pool->whatprovidesdata[r->d + i - 1];
221 printruleelement(solv, r, v);
223 printf(" next: %d %d\n", r->n1, r->n2);
227 /*-----------------------------------------------------------------*/
233 static Pool *unifyrules_sortcmp_data;
236 * compare rules for unification sort
240 unifyrules_sortcmp(const void *ap, const void *bp)
242 Pool *pool = unifyrules_sortcmp_data;
243 Rule *a = (Rule *)ap;
244 Rule *b = (Rule *)bp;
250 return x; /* p differs */
253 if (a->d == 0 && b->d == 0)
254 return a->w2 - b->w2; /* assertion: return w2 diff */
256 if (a->d == 0) /* a is assertion, b not */
258 x = a->w2 - pool->whatprovidesdata[b->d];
262 if (b->d == 0) /* b is assertion, a not */
264 x = pool->whatprovidesdata[a->d] - b->w2;
268 /* compare whatprovidesdata */
269 ad = pool->whatprovidesdata + a->d;
270 bd = pool->whatprovidesdata + b->d;
271 for (; *ad && *ad == *bd; ad++, bd++)
282 unifyrules(Solver *solv)
287 if (solv->nrules <= 1) /* nothing to unify */
290 /* sort rules first */
291 unifyrules_sortcmp_data = solv->pool;
292 qsort(solv->rules + 1, solv->nrules - 1, sizeof(Rule), unifyrules_sortcmp);
299 for (i = j = 1, ir = solv->rules + 1; i < solv->nrules; i++, ir++)
301 if (jr && !unifyrules_sortcmp(ir, jr))
302 continue; /* prune! */
303 jr = solv->rules + j++; /* keep! */
308 /* reduced count from nrules to j rules */
309 if (solv->pool->verbose) printf("pruned rules from %d to %d\n", solv->nrules, j);
311 /* adapt rule buffer */
312 solv->rules = (Rule *)xrealloc(solv->rules, ((solv->nrules + RULES_BLOCK) & ~RULES_BLOCK) * sizeof(Rule));
321 for (i = 1; i < solv->nrules; i++)
324 if (r->d == 0) /* assertion */
329 dp = solv->pool->whatprovidesdata + r->d;
333 if (solv->pool->verbose)
335 printf(" binary: %d\n", binr);
336 printf(" normal: %d\n", solv->nrules - 1 - binr);
337 printf(" normal lits: %d\n", dc);
350 hashrule(Solver *solv, Id p, Id d, int n)
352 unsigned int x = (unsigned int)p;
356 return (x * 37) ^ (unsigned int)d;
357 dp = solv->pool->whatprovidesdata + d;
359 x = (x * 37) ^ (unsigned int)*dp++;
367 * p = direct literal; > 0 for learnt, < 0 for installed pkg (rpm)
368 * d, if < 0 direct literal, if > 0 offset into whatprovides, if == 0 rule is assertion (look at p only)
371 * A requires b, b provided by B1,B2,B3 => (-A|B1|B2|B3)
373 * p < 0 : rule from rpm (installed pkg)
374 * d > 0 : Offset in whatprovidesdata (list of providers)
376 * A conflicts b, b provided by B1,B2,B3 => (-A|-B1), (-A|-B2), (-A|-B3)
377 * d < 0: Id of solvable (e.g. B1)
379 * d == 0: unary rule, assertion => (A) or (-A)
381 * Install: p > 0, d = 0 (A) user requested install
382 * Remove: p < 0, d = 0 (-A) user requested remove
383 * Requires: p < 0, d > 0 (-A|B1|B2|...) d: <list of providers for requirement of p>
384 * Updates: p > 0, d > 0 (A|B1|B2|...) d: <list of updates for solvable p>
385 * Conflicts: p < 0, d < 0 (-A|-B) either p (conflict issuer) or d (conflict provider)
386 * ? p > 0, d < 0 (A|-B)
387 * No-op ?: p = 0, d = 0 (null) (used as policy rule placeholder)
391 addrule(Solver *solv, Id p, Id d)
396 int n = 0; /* number of literals in rule - 1
397 0 = direct assertion (single literal)
401 /* it often happenes that requires lead to adding the same rpm rule
402 * multiple times, so we prune those duplicates right away to make
403 * the work for unifyrules a bit easier */
405 if (solv->nrules && !solv->jobrules)
407 r = solv->rules + solv->nrules - 1; /* get the last added rule */
408 if (r->p == p && r->d == d && d != 0) /* identical and not user requested */
415 return NULL; /* ignore self conflict */
418 else if (d == 0) /* user requested */
422 for (dp = solv->pool->whatprovidesdata + d; *dp; dp++, n++)
424 return NULL; /* rule is self-fulfilling */
429 if (n == 0) /* direct assertion */
433 /* this is a rpm rule assertion, we do not have to allocate it */
434 /* we can identify it by looking at the decision level, it will be 1 */
437 if (solv->decisionmap[-p] > 0) /* */
439 if (solv->decisionmap[-p]) /* */
441 queuepush(&solv->decisionq, p);
442 queuepush(&solv->decisionq_why, 0);
443 solv->decisionmap[-p] = -1;
448 else if (n == 1 && p > d)
450 /* smallest literal first so we can find dups */
454 n = 1; /* re-set n, was used as temp var */
470 Id *dp2 = solv->pool->whatprovidesdata + r->d;
471 for (dp = solv->pool->whatprovidesdata + d; *dp; dp++, dp2++)
484 /* check and extend rule buffer */
485 if ((solv->nrules & RULES_BLOCK) == 0)
487 solv->rules = (Rule *)xrealloc(solv->rules, (solv->nrules + (RULES_BLOCK + 1)) * sizeof(Rule));
490 r = solv->rules + solv->nrules++; /* point to rule space */
495 /* direct assertion, no watch needed */
511 r->w2 = solv->pool->whatprovidesdata[d];
516 /* we don't add the decision for learnt rules, as the code does that
517 * right after calling addrule anyway */
520 && !solv->learntrules)
522 /* must be system or job rule, as there are only negative unary rpm rules */
523 Id vv = p > 0 ? p : -p;
524 if (solv->decisionmap[vv])
527 if (solv->decisionmap[vv] > 0 && p > 0)
529 if (solv->decisionmap[vv] < 0 && p < 0)
531 /* direct conflict! */
532 for (i = 0; i < solv->decisionq.count; i++)
534 if (solv->decisionq.elements[i] == -p)
537 if (i == solv->decisionq.count)
539 if (solv->decisionq_why.elements[i] == 0)
541 /* conflict with rpm rule */
542 queuepush(&solv->problems, r - solv->rules);
543 queuepush(&solv->problems, 0);
544 r->w1 = 0; /* disable */
547 /* conflict with other job or system rule */
548 queuepush(&solv->problems, solv->decisionq_why.elements[i]);
549 queuepush(&solv->problems, r - solv->rules);
550 queuepush(&solv->problems, 0);
551 r->w1 = 0; /* disable */
552 /* also disable conflicting rule */
553 solv->rules[solv->decisionq_why.elements[i]].w1 = 0;
554 /* XXX: remove from decisionq! */
555 printf("XXX remove from decisionq\n");
558 queuepush(&solv->decisionq, p);
559 queuepush(&solv->decisionq_why, r - solv->rules);
560 solv->decisionmap[p > 0 ? p : -p] = p > 0 ? 1 : -1;
567 * add (install) rules for solvable
572 addrulesforsolvable(Solver *solv, Solvable *s, Map *m)
574 Pool *pool = solv->pool;
575 Source *system = solv->system;
588 queuepush(&q, s - pool->solvables);/* push solvable Id */
594 * s: Pointer to solvable
598 if (MAPTST(m, n)) /* continue if already set in map */
602 s = pool->solvables + n; /* s = Solvable in question */
605 if (system /* have rpm */
607 && n >= system->start /* its an rpm rule */
608 && n < system->start + system->nsolvables)
610 dontfix = 1; /* dont care about broken rpm deps */
613 /*-----------------------------------------
614 * check requires of s
617 if ((reqp = s->requires) != ID_NULL)
619 while ((req = *reqp++) != ID_NULL)
621 if (req == SOLVABLE_PREREQMARKER) /* skip the marker */
624 dp = GET_PROVIDESP(req, p); /* get providers of req */
626 if (!*dp /* dont care if noone provides rpmlib() */
627 && !strncmp(id2str(pool, req), "rpmlib(", 7))
632 if (dontfix) /* rpm rule, dont care about breakage */
634 for (i = 0; dp[i]; i++)/* for all providers */
636 if (dp[i] >= system->start && dp[i] < system->start + system->nsolvables)
637 break; /* provider is installed */
639 if (!dp[i]) /* no provider found */
641 if (pool->verbose) printf("ignoring broken requires %s%s%s of system package %s-%s.%s\n", id2str(pool, req), id2rel(pool, req), id2evr(pool, req), id2str(pool, s->name), id2str(pool, s->evr), id2str(pool, s->arch));
648 /* nothing provides req! */
650 if (pool->verbose) printf("package %s-%s.%s is not installable (%s%s%s)\n", id2str(pool, s->name), id2str(pool, s->evr), id2str(pool, s->arch), id2str(pool, req), id2rel(pool, req), id2evr(pool, req));
652 addrule(solv, -n, 0); /* mark requestor as uninstallable */
654 printf(">!> !unflag %s-%s.%s[%s]\n", id2str(pool, s->name), id2str(pool, s->evr), id2str(pool, s->arch), source_name(pool_source(pool, s)));
658 printf("addrule %s-%s.%s %s%s%s %d %d\n", id2str(pool, s->name), id2str(pool, s->evr), id2str(pool, s->arch), id2str(pool, req), id2rel(pool, req), id2evr(pool, req), -n, dp - pool->whatprovidesdata);
659 for (i = 0; dp[i]; i++)
660 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));
662 /* add 'requires' dependency */
663 addrule(solv, -n, dp - pool->whatprovidesdata); /* rule: (-requestor|provider1|provider2|...|providerN) */
665 /* descend the dependency tree */
666 for (; *dp != ID_NULL; dp++) /* loop through all providers */
668 if (!MAPTST(m, *dp)) /* if not already marked */
669 queuepush(&q, *dp); /* queue for installation */
672 } /* while, requirements of n */
674 } /* if, requirements */
677 /*-----------------------------------------
678 * check conflicts of s
681 if ((conp = s->conflicts) != ID_NULL)
683 while ((con = *conp++) != ID_NULL)
685 FOR_PROVIDES(p, pp, con) /* loop through all providers of this conflict */
687 /* dontfix: dont care about conflicts with already installed packs */
688 if (dontfix && p >= system->start && p < system->start + system->nsolvables)
690 addrule(solv, -n, -p); /* rule: -n|-p: either solvable _or_ provider of conflict */
695 /*-----------------------------------------
696 * check obsoletes if not installed
698 if (!system || n < system->start || n >= (system->start + system->nsolvables))
699 { /* not installed */
700 if ((obsp = s->obsoletes) != ID_NULL)
702 while ((obs = *obsp++) != ID_NULL)
704 FOR_PROVIDES(p, pp, obs)
705 addrule(solv, -n, -p);
708 FOR_PROVIDES(p, pp, s->name)
710 if (s->name == pool->solvables[p].name)
711 addrule(solv, -n, -p);
715 /*-----------------------------------------
716 * add recommends to the rule list
718 if ((recp = s->recommends) != ID_NULL)
719 while ((rec = *recp++) != ID_NULL)
721 FOR_PROVIDES(p, pp, rec)
730 addrulesforsupplements(Solver *solv, Map *m)
732 Pool *pool = solv->pool;
738 if (pool->verbose) printf("addrulesforsupplements... (%d)\n", solv->nrules);
739 for (i = n = 1; n < pool->nsolvables; i++, n++)
741 if (i == pool->nsolvables)
745 s = pool->solvables + i;
746 if (!(supp = s->supplements))
748 while ((sup = *supp++) != ID_NULL)
750 FOR_PROVIDES(p, pp, sup)
758 addrulesforsolvable(solv, s, m);
761 if (pool->verbose) printf("done. (%d)\n", solv->nrules);
766 archchanges(Pool *pool, Solvable *s1, Solvable *s2)
768 Id a1 = s1->arch, a2 = s2->arch;
770 /* we allow changes to/from noarch */
771 if (a1 == a2 || a1 == ARCH_NOARCH || a2 == ARCH_NOARCH)
775 a1 = a1 <= pool->lastarch ? pool->id2arch[a1] : 0;
776 a2 = a2 <= pool->lastarch ? pool->id2arch[a2] : 0;
777 if (((a1 ^ a2) & 0xffff0000) != 0)
784 findupdatepackages(Solver *solv, Solvable *s, Queue *qs, Map *m, int allowdowngrade, int allowarchchange)
786 /* system packages get a special upgrade allowed rule */
787 Pool *pool = solv->pool;
788 Id p, *pp, n, p2, *pp2;
796 n = s - pool->solvables;
797 if (m && !MAPTST(m, n)) /* add rule for s if not already done */
798 addrulesforsolvable(solv, s, m);
801 * look for updates for s
803 FOR_PROVIDES(p, pp, s->name) /* every provider of s' name */
805 if (p == n) /* skip itself */
808 if (s->name == pool->solvables[p].name) /* name match */
810 if (!allowdowngrade /* consider downgrades ? */
811 && evrcmp(pool, s->evr, pool->solvables[p].evr) > 0)
814 if (!allowarchchange && archchanges(pool, s, pool->solvables + p))
817 else if ((obsp = pool->solvables[p].obsoletes) != 0) /* provides/obsoletes combination ? */
819 while ((obs = *obsp++) != 0) /* for all obsoletes */
821 FOR_PROVIDES(p2, pp2, obs) /* and all matching providers of the obsoletes */
823 if (p2 == n) /* match ! */
829 if (!obs) /* continue if no match */
831 /* here we have 'p' with a matching provides/obsoletes combination
832 * thus flagging p as a valid update candidate for s
837 if (m && !MAPTST(m, p)) /* mark p for install if not already done */
838 addrulesforsolvable(solv, pool->solvables + p, m);
843 * add rule for update
844 * (A|A1|A2|A3...) An = update candidates for A
846 * s = (installed) solvable
847 * m = 'addedmap', bit set if 'install' rule for solvable exists
851 addupdaterule(Solver *solv, Solvable *s, Map *m, int allowdowngrade, int allowarchchange, int dontaddrule)
853 /* system packages get a special upgrade allowed rule */
854 Pool *pool = solv->pool;
860 findupdatepackages(solv, s, &qs, m, allowdowngrade, allowarchchange);
861 n = s - pool->solvables;
862 if (dontaddrule) /* we consider update candidates but dont force them */
868 if (qs.count == 0) /* no updates found */
871 printf("new update rule: must keep %s-%s.%s\n", id2str(pool, s->name), id2str(pool, s->evr), id2str(pool, s->arch));
873 addrule(solv, n, 0); /* request 'install' of s */
878 d = pool_queuetowhatprovides(pool, &qs); /* intern computed provider queue */
880 r = addrule(solv, n, d); /* allow update of s */
882 printf("new update rule ");
889 /*-----------------------------------------------------------------*/
896 * initial setup for all watches
900 makewatches(Solver *solv)
904 int nsolvables = solv->pool->nsolvables;
906 xfree(solv->watches);
907 /* lower half for removals, upper half for installs */
908 solv->watches = (Id *)xcalloc(2 * nsolvables, sizeof(Id));
910 /* do it reverse so rpm rules get triggered first */
911 for (i = 1, r = solv->rules + solv->nrules - 1; i < solv->nrules; i++, r--)
913 for (i = 1, r = solv->rules + 1; i < solv->nrules; i++, r++)
916 if (!r->w1 /* rule is disabled */
917 || !r->w2) /* rule is assertion */
920 /* see addwatches(solv, r) */
921 r->n1 = solv->watches[nsolvables + r->w1];
922 solv->watches[nsolvables + r->w1] = r - solv->rules;
924 r->n2 = solv->watches[nsolvables + r->w2];
925 solv->watches[nsolvables + r->w2] = r - solv->rules;
931 * add watches (for rule)
935 addwatches(Solver *solv, Rule *r)
937 int nsolvables = solv->pool->nsolvables;
939 r->n1 = solv->watches[nsolvables + r->w1];
940 solv->watches[nsolvables + r->w1] = r - solv->rules;
942 r->n2 = solv->watches[nsolvables + r->w2];
943 solv->watches[nsolvables + r->w2] = r - solv->rules;
947 /*-----------------------------------------------------------------*/
948 /* rule propagation */
950 #define DECISIONMAP_TRUE(p) ((p) > 0 ? (decisionmap[p] > 0) : (decisionmap[-p] < 0))
955 * propagate decision to all rules
959 propagate(Solver *solv, int level)
961 Pool *pool = solv->pool;
966 Id *decisionmap = solv->decisionmap;
967 Id *watches = solv->watches + pool->nsolvables;
969 while (solv->propagate_index < solv->decisionq.count)
971 /* negative because our watches trigger if literal goes FALSE */
972 pkg = -solv->decisionq.elements[solv->propagate_index++];
974 printf("popagate for decision %d level %d\n", -pkg, level);
975 printruleelement(solv, 0, -pkg);
977 for (rp = watches + pkg; *rp; rp = nrp)
979 r = solv->rules + *rp;
981 printf(" watch triggered ");
994 /* if clause is TRUE, nothing to do */
995 if (DECISIONMAP_TRUE(ow))
1000 /* not a binary clause, check if we need to move our watch */
1001 if (r->p && r->p != ow && !DECISIONMAP_TRUE(-r->p))
1004 for (dp = pool->whatprovidesdata + r->d; (p = *dp++) != 0;)
1005 if (p != ow && !DECISIONMAP_TRUE(-p))
1009 /* p is free to watch, move watch to p */
1012 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));
1014 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));
1028 watches[p] = r - solv->rules;
1032 /* unit clause found, set other watch to TRUE */
1033 if (DECISIONMAP_TRUE(-ow))
1034 return r; /* eek, a conflict! */
1040 decisionmap[ow] = level;
1042 decisionmap[-ow] = -level;
1043 queuepush(&solv->decisionq, ow);
1044 queuepush(&solv->decisionq_why, r - solv->rules);
1047 Solvable *s = pool->solvables + (ow > 0 ? ow : -ow);
1049 printf(" -> decided to install %s-%s.%s\n", id2str(pool, s->name), id2str(pool, s->evr), id2str(pool, s->arch));
1051 printf(" -> decided to conflict %s-%s.%s\n", id2str(pool, s->name), id2str(pool, s->evr), id2str(pool, s->arch));
1056 return 0; /* all is well */
1060 /*-----------------------------------------------------------------*/
1069 analyze(Solver *solv, int level, Rule *c, int *pr, int *dr, int *why)
1071 Pool *pool = solv->pool;
1074 Map seen; /* global? */
1078 int learnt_why = solv->learnt_pool.count;
1079 Id *decisionmap = solv->decisionmap;
1083 if (pool->verbose) printf("ANALYZE at %d ----------------------\n", level);
1084 mapinit(&seen, pool->nsolvables);
1085 idx = solv->decisionq.count;
1089 queuepush(&solv->learnt_pool, c - solv->rules);
1090 dp = c->d ? pool->whatprovidesdata + c->d : 0;
1101 if (DECISIONMAP_TRUE(v)) /* the one true literal */
1103 vv = v > 0 ? v : -v;
1104 if (MAPTST(&seen, vv))
1106 l = solv->decisionmap[vv];
1113 for (j = 0; j < solv->decisionq.count; j++)
1114 if (solv->decisionq.elements[j] == v)
1116 if (j == solv->decisionq.count)
1118 queuepush(&rulq, -(j + 1));
1120 continue; /* initial setting */
1124 num++; /* need to do this one as well */
1129 printf("PUSH %d ", v);
1130 printruleelement(solv, 0, v);
1137 printf("num = %d\n", num);
1143 v = solv->decisionq.elements[--idx];
1144 vv = v > 0 ? v : -v;
1145 if (MAPTST(&seen, vv))
1148 c = solv->rules + solv->decisionq_why.elements[idx];
1156 else if (r.count == 1 && r.elements[0] < 0)
1157 *dr = r.elements[0];
1159 *dr = pool_queuetowhatprovides(pool, &r);
1162 printf("learned rule for level %d (am %d)\n", rlevel, level);
1163 printruleelement(solv, 0, -v);
1164 for (i = 0; i < r.count; i++)
1167 printruleelement(solv, 0, v);
1171 queuepush(&solv->learnt_pool, 0);
1173 for (i = learnt_why; solv->learnt_pool.elements[i]; i++)
1175 printf("learnt_why ");
1176 printrule(solv, solv->rules + solv->learnt_pool.elements[i]);
1187 * reset the solver decisions to right after the rpm rules
1191 reset_solver(Solver *solv)
1197 /* delete all learnt rules */
1198 solv->nrules = solv->learntrules;
1199 QUEUEEMPTY(&solv->learnt_why);
1200 QUEUEEMPTY(&solv->learnt_pool);
1202 /* redo all direct decision without the disabled rules */
1203 for (i = 0; i < solv->decisionq.count; i++)
1205 v = solv->decisionq.elements[i];
1206 solv->decisionmap[v > 0 ? v : -v] = 0;
1208 for (i = 0; i < solv->decisionq_why.count; i++)
1209 if (solv->decisionq_why.elements[i])
1213 v = solv->decisionq.elements[i];
1214 solv->decisionmap[v > 0 ? v : -v] = v > 0 ? 1 : -1;
1217 if (solv->pool->verbose)
1218 printf("decisions done reduced from %d to %d\n", solv->decisionq.count, i);
1220 solv->decisionq_why.count = i;
1221 solv->decisionq.count = i;
1222 if (i < solv->propagate_index)
1223 solv->propagate_index = i;
1224 /* make direct decisions from enabled unary rules */
1225 for (i = solv->jobrules, r = solv->rules + solv->jobrules; i < solv->nrules; i++, r++)
1227 if (!r->w1 || r->w2)
1233 queuepush(&solv->decisionq, v);
1234 queuepush(&solv->decisionq_why, r - solv->rules);
1235 solv->decisionmap[v > 0 ? v : -v] = v > 0 ? 1 : -1;
1237 if (solv->pool->verbose)
1238 printf("decisions after adding job and system rules: %d\n", solv->decisionq.count);
1239 /* recreate watches */
1245 * analyze_unsolvable_rule
1249 analyze_unsolvable_rule(Solver *solv, Rule *c, int disablerules)
1254 why = c - solv->rules;
1256 if (why >= solv->jobrules && why < solv->systemrules)
1258 if (why >= solv->systemrules && why < solv->learntrules)
1259 printf("SYSTEM %d ", why - solv->systemrules);
1260 if (solv->learntrules && why >= solv->learntrules)
1264 if (solv->learntrules && why >= solv->learntrules)
1266 for (i = solv->learnt_why.elements[why - solv->learntrules]; solv->learnt_pool.elements[i]; i++)
1267 analyze_unsolvable_rule(solv, solv->rules + solv->learnt_pool.elements[i], disablerules);
1270 if (why >= solv->jobrules && why < solv->learntrules)
1274 /* turn off rule for further analysis */
1278 if (solv->problems.count)
1280 for (i = solv->problems.count - 1; i >= 0; i--)
1281 if (solv->problems.elements[i] == 0)
1283 else if (solv->problems.elements[i] == why)
1286 queuepush(&solv->problems, why);
1292 * analyze_unsolvable
1296 analyze_unsolvable(Solver *solv, Rule *c, int disablerules)
1298 Pool *pool = solv->pool;
1299 Map seen; /* global? */
1302 Id *decisionmap = solv->decisionmap;
1305 printf("ANALYZE UNSOLVABLE ----------------------\n");
1307 mapinit(&seen, pool->nsolvables);
1308 analyze_unsolvable_rule(solv, c, disablerules);
1309 dp = c->d ? pool->whatprovidesdata + c->d : 0;
1320 if (DECISIONMAP_TRUE(v)) /* the one true literal */
1322 vv = v > 0 ? v : -v;
1323 l = solv->decisionmap[vv];
1328 idx = solv->decisionq.count;
1331 v = solv->decisionq.elements[--idx];
1332 vv = v > 0 ? v : -v;
1333 if (!MAPTST(&seen, vv))
1335 why = solv->decisionq_why.elements[idx];
1340 printruleelement(solv, 0, v);
1344 c = solv->rules + why;
1345 analyze_unsolvable_rule(solv, c, disablerules);
1346 dp = c->d ? pool->whatprovidesdata + c->d : 0;
1357 if (DECISIONMAP_TRUE(v)) /* the one true literal */
1359 vv = v > 0 ? v : -v;
1360 l = solv->decisionmap[vv];
1367 queuepush(&solv->problems, 0); /* mark end of this problem */
1371 printf("analyze_unsolvables done\n");
1376 /*-----------------------------------------------------------------*/
1377 /* Decision revert */
1381 * revert decision at level
1385 revert(Solver *solv, int level)
1388 while (solv->decisionq.count)
1390 v = solv->decisionq.elements[solv->decisionq.count - 1];
1391 vv = v > 0 ? v : -v;
1392 if (solv->decisionmap[vv] <= level && solv->decisionmap[vv] >= -level)
1395 printf("reverting decision %d at %d\n", v, solv->decisionmap[vv]);
1397 solv->decisionmap[vv] = 0;
1398 solv->decisionq.count--;
1399 solv->decisionq_why.count--;
1400 solv->propagate_index = solv->decisionq.count;
1410 watch2onhighest(Solver *solv, Rule *r)
1416 return; /* binary rule, both watches are set */
1417 dp = solv->pool->whatprovidesdata + r->d;
1418 while ((v = *dp++) != 0)
1420 l = solv->decisionmap[v < 0 ? -v : v];
1437 setpropagatelearn(Solver *solv, int level, Id decision, int disablerules)
1447 solv->decisionmap[decision] = level;
1449 solv->decisionmap[-decision] = -level;
1450 queuepush(&solv->decisionq, decision);
1451 queuepush(&solv->decisionq_why, 0);
1455 r = propagate(solv, level);
1460 analyze_unsolvable(solv, r, disablerules);
1465 printf("conflict with rule #%d\n", (int)(r - solv->rules));
1466 l = analyze(solv, level, r, &p, &d, &why);
1467 if (l >= level || l <= 0)
1469 printf("reverting decisions (level %d -> %d)\n", level, l);
1471 revert(solv, level);
1472 r = addrule(solv, p, d); /* p requires d */
1475 if (solv->learnt_why.count != (r - solv->rules) - solv->learntrules)
1477 printf("%d %d\n", solv->learnt_why.count, (int)(r - solv->rules) - solv->learntrules);
1480 queuepush(&solv->learnt_why, why);
1483 /* at least 2 literals, needs watches */
1484 watch2onhighest(solv, r);
1485 addwatches(solv, r);
1487 solv->decisionmap[p > 0 ? p : -p] = p > 0 ? level : -level;
1488 queuepush(&solv->decisionq, p);
1489 queuepush(&solv->decisionq_why, r - solv->rules);
1490 printf("decision: ");
1491 printruleelement(solv, 0, p);
1492 printf("new rule: ");
1498 /*-----------------------------------------------------------------*/
1499 /* Main solver interface */
1504 * create solver structure
1506 * pool: all available solvables
1507 * system: installed Solvables
1510 * Upon solving, rules are created to flag the Solvables
1511 * of the 'system' Source as installed.
1515 solver_create(Pool *pool, Source *system)
1518 solv = (Solver *)xcalloc(1, sizeof(Solver));
1520 solv->system = system;
1523 queueinit(&solv->decisionq);
1524 queueinit(&solv->decisionq_why);
1525 queueinit(&solv->problems);
1526 queueinit(&solv->learnt_why);
1527 queueinit(&solv->learnt_pool);
1529 solv->decisionmap = (Id *)xcalloc(pool->nsolvables, sizeof(Id));
1530 solv->rules = (Rule *)xmalloc((solv->nrules + (RULES_BLOCK + 1)) * sizeof(Rule));
1531 memset(solv->rules, 0, sizeof(Rule));
1544 solver_free(Solver *solv)
1546 queuefree(&solv->decisionq);
1547 queuefree(&solv->decisionq_why);
1548 queuefree(&solv->learnt_why);
1549 queuefree(&solv->learnt_pool);
1550 xfree(solv->decisionmap);
1552 xfree(solv->watches);
1553 xfree(solv->weaksystemrules);
1561 * r->w1 was set to 0, now find proper value for w1
1565 reenablerule(Solver *solv, Rule *r)
1570 if (!r->w2) /* not a rule, but an assertion */
1580 r->w2 = r->d; /* mls: shouldn't this be r->w1 ? */
1584 /* put it on the first not-false literal */
1590 v = solv->pool->whatprovidesdata[r->d + i];
1598 l = solv->decisionmap[v > 0 ? v : -v];
1599 if (!l || (v < 0 && l < 0) || (v > 0 && l > 0))
1606 /*-------------------------------------------------------*/
1611 * all rules have been set up, not actually run the solver
1616 run_solver(Solver *solv, int disablerules, int doweak)
1624 Pool *pool = solv->pool;
1628 printf("number of rules: %d\n", solv->nrules);
1631 for (i = 0; i < solv->nrules; i++)
1633 printrule(solv, solv->rules + i);
1638 /* all new rules are learnt after this point */
1639 solv->learntrules = solv->nrules;
1640 /* crate watches lists */
1643 if (pool->verbose) printf("initial decisions: %d\n", solv->decisionq.count);
1645 /* start SAT algorithm */
1647 if (!solv->updatesystem)
1651 if (pool->verbose) printf("solving...\n");
1662 if (pool->verbose) printf("propagating (%d %d)...\n", solv->propagate_index, solv->decisionq.count);
1663 if ((r = propagate(solv, level)) != 0)
1665 analyze_unsolvable(solv, r, disablerules);
1668 printf("UNSOLVABLE\n");
1678 if (level < systemlevel && solv->system->nsolvables)
1680 if (pool->verbose) printf("installing system packages\n");
1681 for (i = solv->system->start, n = 0; ; i++, n++)
1683 if (n == solv->system->nsolvables)
1685 if (i == solv->system->start + solv->system->nsolvables)
1686 i = solv->system->start;
1687 s = pool->solvables + i;
1689 if (solv->decisionmap[i] < 0)
1692 printf("system %s-%s.%s conflicts\n", id2str(pool, s->name), id2str(pool, s->evr), id2str(pool, s->arch));
1693 for (j = 0; j < solv->decisionq.count; j++)
1694 if (solv->decisionq.elements[j] == -i)
1696 if (solv->decisionq_why.elements[j])
1697 printrule(solv, solv->rules + solv->decisionq_why.elements[j]);
1700 if (solv->decisionmap[i] != 0)
1703 printf("system installing %s-%s.%s\n", id2str(pool, s->name), id2str(pool, s->evr), id2str(pool, s->arch));
1706 level = setpropagatelearn(solv, level, i, disablerules);
1709 printf("UNSOLVABLE\n");
1713 if (level <= olevel)
1716 if (solv->weaksystemrules)
1718 if (pool->verbose) printf("installing weak system packages\n");
1719 for (i = solv->system->start, n = 0; ; i++, n++)
1721 if (n == solv->system->nsolvables)
1723 if (solv->decisionmap[i] > 0 || solv->weaksystemrules[i - solv->system->start] == 0)
1726 dp = pool->whatprovidesdata + solv->weaksystemrules[i - solv->system->start];
1727 while ((p = *dp++) != 0)
1729 if (solv->decisionmap[p] > 0)
1731 if (solv->decisionmap[p] == 0)
1739 prune_best_version_arch(pool, &dq);
1741 s = pool->solvables + dq.elements[0];
1742 printf("weak system installing %s-%s.%s\n", id2str(pool, s->name), id2str(pool, s->evr), id2str(pool, s->arch));
1745 level = setpropagatelearn(solv, level, dq.elements[0], disablerules);
1748 printf("UNSOLVABLE\n");
1752 if (level <= olevel)
1758 if (n != solv->system->nsolvables)
1761 systemlevel = level;
1768 if (pool->verbose) printf("deciding unresolved rules\n");
1769 for (i = 1, n = 1; ; i++, n++)
1771 if (n == solv->nrules)
1773 if (i == solv->nrules)
1775 r = solv->rules + i;
1781 /* binary or unary rule */
1782 /* need two positive undecided literals */
1783 if (r->p < 0 || r->w2 <= 0)
1785 if (solv->decisionmap[r->p] || solv->decisionmap[r->w2])
1787 queuepush(&dq, r->p);
1788 queuepush(&dq, r->w2);
1793 * all negative literals are installed
1794 * no positive literal is installed
1795 * i.e. the rule is not fulfilled and we
1796 * just need to decide on the positive literals
1800 if (solv->decisionmap[-r->p] <= 0)
1805 if (solv->decisionmap[r->p] > 0)
1807 if (solv->decisionmap[r->p] == 0)
1808 queuepush(&dq, r->p);
1810 dp = pool->whatprovidesdata + r->d;
1811 while ((p = *dp++) != 0)
1815 if (solv->decisionmap[-p] <= 0)
1820 if (solv->decisionmap[p] > 0)
1822 if (solv->decisionmap[p] == 0)
1831 /* cannot happen as this means that
1832 * the rule is unit */
1836 prune_best_version_arch(pool, &dq);
1837 p = dq.elements[dq.count - 1];
1838 s = pool->solvables + p;
1840 printf("installing %s-%s.%s\n", id2str(pool, s->name), id2str(pool, s->evr), id2str(pool, s->arch));
1843 level = setpropagatelearn(solv, level, p, disablerules);
1846 printf("UNSOLVABLE\n");
1850 if (level < systemlevel)
1852 if (level <= olevel)
1854 } /* for(), decide */
1860 if (n != solv->nrules)
1862 if (doweak && !solv->problems.count)
1866 if (pool->verbose) printf("installing recommended packages\n");
1868 for (i = 1; i < pool->nsolvables; i++)
1870 if (solv->decisionmap[i] < 0)
1872 if (solv->decisionmap[i] > 0)
1874 Id *recp, rec, *pp, p;
1875 s = pool->solvables + i;
1876 /* installed, check for recommends */
1877 if ((recp = s->recommends) != 0)
1879 while ((rec = *recp++) != 0)
1882 FOR_PROVIDES(p, pp, rec)
1884 if (solv->decisionmap[p] > 0)
1886 else if (solv->decisionmap[p] == 0)
1887 queuepushunique(&dq, p);
1890 dq.count = qcount; /* already fulfilled */
1896 Id *supp, sup, *pp, p;
1897 s = pool->solvables + i;
1898 if ((supp = s->supplements) != 0)
1900 while ((sup = *supp++) != 0)
1902 FOR_PROVIDES(p, pp, sup)
1904 if (solv->decisionmap[p] > 0)
1908 queuepushunique(&dq, i);
1915 prune_best_version_arch(pool, &dq);
1916 p = dq.elements[dq.count - 1];
1917 s = pool->solvables + p;
1919 printf("weak installing %s-%s.%s\n", id2str(pool, s->name), id2str(pool, s->evr), id2str(pool, s->arch));
1921 level = setpropagatelearn(solv, level, p, 0);
1936 refine_suggestion(Solver *solv, Id *problem, Id sug, Queue *refined)
1944 printf("refine_suggestion start\n");
1945 queueinit(&disabled);
1946 QUEUEEMPTY(refined);
1947 queuepush(refined, sug);
1949 /* re-enable all rules but rule "sug" of the problem */
1950 for (i = 0; problem[i]; i++)
1952 if (problem[i] == sug)
1954 r = solv->rules + problem[i];
1959 reenablerule(solv, r);
1965 QUEUEEMPTY(&solv->problems);
1966 run_solver(solv, 0, 0);
1967 if (!solv->problems.count)
1969 printf("no more problems!\n");
1971 printdecisions(solv);
1973 break; /* great, no more problems */
1975 disabledcnt = disabled.count;
1976 for (i = 0; i < solv->problems.elements[i]; i++)
1978 /* ignore solutions in refined */
1979 v = solv->problems.elements[i];
1980 for (j = 0; problem[j]; j++)
1981 if (problem[j] != sug && problem[j] == v)
1985 queuepush(&disabled, v);
1987 if (disabled.count == disabledcnt)
1989 /* no solution found, this was an invalid suggestion! */
1990 printf("no solution found!\n");
1991 for (i = 0; i < refined->count; i++)
1992 reenablerule(solv, solv->rules + refined->elements[i]);
1996 if (disabled.count == disabledcnt + 1)
1998 /* just one solution, add it to refined list */
1999 queuepush(refined, disabled.elements[disabledcnt]);
2003 printf("############################################## more than one solution found.\n");
2005 for (i = 0; i < solv->problems.elements[i]; i++)
2007 printrule(solv, solv->rules + solv->problems.elements[i]);
2009 printf("##############################################\n");
2011 /* more than one solution */
2012 /* for now return */
2014 for (i = disabledcnt; i < disabled.count; i++)
2016 r = solv->rules + disabled.elements[i];;
2025 /* enable refined rules again */
2027 for (i = 0; i < disabled.count; i++)
2028 reenablerule(solv, solv->rules + disabled.elements[i]);
2029 /* disable problem rules again so that we are in the same state as before */
2030 for (i = 0; problem[i]; i++)
2032 r = solv->rules + problem[i];
2035 printf("refine_suggestion end\n");
2044 id2rc(Solver *solv, Id id)
2047 if (solv->rc_output != 2)
2049 evr = id2str(solv->pool, id);
2050 if (*evr < '0' || *evr > '9')
2052 while (*evr >= '0' && *evr <= '9')
2060 printdecisions(Solver *solv)
2062 Pool *pool = solv->pool;
2063 Id p, *obsoletesmap;
2067 obsoletesmap = (Id *)xcalloc(pool->nsolvables, sizeof(Id));
2068 for (i = 0; i < solv->decisionq.count; i++)
2073 n = solv->decisionq.elements[i];
2076 if (n >= solv->system->start && n < solv->system->start + solv->system->nsolvables)
2078 s = pool->solvables + n;
2079 if ((obsp = s->obsoletes) != 0)
2080 while ((obs = *obsp++) != 0)
2081 FOR_PROVIDES(p, pp, obs)
2083 if (p >= solv->system->start && p < solv->system->start + solv->system->nsolvables)
2085 obsoletesmap[p] = n;
2089 FOR_PROVIDES(p, pp, s->name)
2090 if (s->name == pool->solvables[p].name)
2092 if (p >= solv->system->start && p < solv->system->start + solv->system->nsolvables)
2094 obsoletesmap[p] = n;
2100 if (solv->rc_output)
2101 printf(">!> Solution #1:\n");
2103 int installs = 0, uninstalls = 0, upgrades = 0;
2105 /* print solvables to be erased */
2107 for (i = solv->system->start; i < solv->system->start + solv->system->nsolvables; i++)
2109 if (solv->decisionmap[i] > 0)
2111 if (obsoletesmap[i])
2113 s = pool->solvables + i;
2114 if (solv->rc_output)
2117 if (solv->rc_output == 2)
2120 printf(" %s-%s%s", id2str(pool, s->name), id2rc(solv, s->evr), id2str(pool, s->evr));
2124 printf("remove %s-%s.%s", id2str(pool, s->name), id2str(pool, s->evr), id2str(pool, s->arch));
2129 printf("erase %s-%s.%s", id2str(pool, s->name), id2str(pool, s->evr), id2str(pool, s->arch));
2135 /* print solvables to be installed */
2137 for (i = 0; i < solv->decisionq.count; i++)
2139 p = solv->decisionq.elements[i];
2142 if (p >= solv->system->start && p < solv->system->start + solv->system->nsolvables)
2144 s = pool->solvables + p;
2146 if (solv->rc_output)
2149 if (!obsoletesmap[p])
2151 printf("install %s-%s%s", id2str(pool, s->name), id2rc(solv, s->evr), id2str(pool, s->evr));
2152 if (solv->rc_output != 2)
2153 printf(".%s", id2str(pool, s->arch));
2159 Solvable *from = NULL, *to = NULL;
2160 if (solv->rc_output)
2163 printf("update %s-%s.%s (obsoletes", id2str(pool, s->name), id2str(pool, s->evr), id2str(pool, s->arch));
2165 for (j = solv->system->start; j < solv->system->start + solv->system->nsolvables; j++)
2167 if (obsoletesmap[j] == p)
2169 s = pool->solvables + j;
2170 if (solv->rc_output)
2173 printf(" %s-%s.%s", id2str(pool, s->name), id2str(pool, s->evr), id2str(pool, s->arch));
2176 if (solv->rc_output)
2178 if (solv->rc_output == 2)
2179 printf("upgrade %s-%s => %s-%s%s", id2str(pool, from->name), id2str(pool, from->evr), id2str(pool, to->name), id2rc(solv, to->evr), id2str(pool, to->evr));
2181 printf("upgrade %s-%s.%s => %s-%s.%s", id2str(pool, from->name), id2str(pool, from->evr), id2str(pool, from->arch), id2str(pool, to->name), id2str(pool, to->evr), id2str(pool, to->arch));
2182 s = to; /* for final source name */
2187 if (solv->rc_output)
2189 Source *source = pool_source(pool, s);
2191 printf("[%s]", source_name(source));
2196 if (solv->rc_output)
2197 printf(">!> installs=%d, upgrades=%d, uninstalls=%d\n", installs, upgrades, uninstalls);
2199 xfree(obsoletesmap);
2203 /*-----------------------------------------------------------------*/
2213 solve(Solver *solv, Queue *job)
2215 Pool *pool = solv->pool;
2217 Map addedmap; /* '1' == have rule for solvable */
2218 Map noupdaterule; /* '1' == don't update (scheduled for removal) */
2219 Id how, what, p, *pp, d;
2225 * create basic rule set of all involved packages
2230 mapinit(&addedmap, pool->nsolvables);
2231 mapinit(&noupdaterule, pool->nsolvables);
2236 * create rules for installed solvables -> keep them installed
2237 * so called: rpm rules
2241 for (i = solv->system->start; i < solv->system->start + solv->system->nsolvables; i++)
2242 addrulesforsolvable(solv, pool->solvables + i, &addedmap);
2245 * create install rules
2247 * two passes, as we want to keep the rpm rules distinct from the job rules
2253 * process job rules for solvables
2256 for (i = 0; i < job->count; i += 2)
2258 how = job->elements[i];
2259 what = job->elements[i + 1];
2263 case SOLVER_INSTALL_SOLVABLE:
2264 addrulesforsolvable(solv, pool->solvables + what, &addedmap);
2266 case SOLVER_INSTALL_SOLVABLE_NAME:
2267 case SOLVER_INSTALL_SOLVABLE_PROVIDES:
2269 FOR_PROVIDES(p, pp, what)
2271 /* if by name, ensure that the name matches */
2272 if (how == SOLVER_INSTALL_SOLVABLE_NAME && pool->solvables[p].name != what)
2274 addrulesforsolvable(solv, pool->solvables + p, &addedmap);
2277 case SOLVER_INSTALL_SOLVABLE_UPDATE:
2278 /* dont allow downgrade */
2279 addupdaterule(solv, pool->solvables + what, &addedmap, 0, 0, 1);
2285 * if unstalls are disallowed, add update rules for every
2286 * installed solvables in the hope to circumvent uninstall
2292 if (!solv->allowuninstall)
2294 /* add update rule for every installed package */
2295 for (i = solv->system->start; i < solv->system->start + solv->system->nsolvables; i++)
2296 addupdaterule(solv, pool->solvables + i, &addedmap, solv->allowdowngrade, solv->allowarchchange, 1);
2298 #else /* this is just to add the needed rpm rules to our set */
2299 for (i = solv->system->start; i < solv->system->start + solv->system->nsolvables; i++)
2300 addupdaterule(solv, pool->solvables + i, &addedmap, 1, 1, 1);
2306 * unify existing rules before going over all job rules
2310 addrulesforsupplements(solv, &addedmap);
2312 unifyrules(solv); /* remove duplicate rpm rules */
2315 * at this point the system is always solvable,
2316 * as an empty system (remove all packages) is a valid solution
2318 if (pool->verbose) printf("decisions based on rpms: %d\n", solv->decisionq.count);
2321 * now add all job rules
2324 solv->jobrules = solv->nrules;
2326 for (i = 0; i < job->count; i += 2)
2328 how = job->elements[i];
2329 what = job->elements[i + 1];
2332 case SOLVER_INSTALL_SOLVABLE: /* install specific solvable */
2333 if (solv->rc_output) {
2334 Solvable *s = pool->solvables + what;
2335 printf(">!> Installing %s from channel %s\n", id2str(pool, s->name), source_name(pool_source(pool, s)));
2337 addrule(solv, what, 0); /* install by Id */
2339 case SOLVER_ERASE_SOLVABLE:
2340 addrule(solv, -what, 0); /* remove by Id */
2341 MAPSET(&noupdaterule, what);
2343 case SOLVER_INSTALL_SOLVABLE_NAME: /* install by capability */
2344 case SOLVER_INSTALL_SOLVABLE_PROVIDES:
2346 FOR_PROVIDES(p, pp, what) /* check all providers */
2348 /* if by name, ensure that the name matches */
2349 if (how == SOLVER_INSTALL_SOLVABLE_NAME && pool->solvables[p].name != what)
2353 if (!q.count) { /* no provider found -> abort */
2354 fprintf(stderr, "Nothing provides '%s'\n", id2str(pool, what));
2355 /* XXX make this a problem! */
2360 p = queueshift(&q); /* get first provider */
2362 d = 0; /* single provider ? -> make assertion */
2364 d = pool_queuetowhatprovides(pool, &q); /* get all providers */
2365 addrule(solv, p, d); /* add 'requires' rule */
2367 case SOLVER_ERASE_SOLVABLE_NAME: /* remove by capability */
2368 case SOLVER_ERASE_SOLVABLE_PROVIDES:
2369 FOR_PROVIDES(p, pp, what)
2371 /* if by name, ensure that the name matches */
2372 if (how == SOLVER_ERASE_SOLVABLE_NAME && pool->solvables[p].name != what)
2375 addrule(solv, -p, 0); /* add 'remove' rule */
2376 MAPSET(&noupdaterule, p);
2379 case SOLVER_INSTALL_SOLVABLE_UPDATE: /* find update for solvable */
2380 addupdaterule(solv, pool->solvables + what, &addedmap, 0, 0, 0);
2385 if (pool->verbose) printf("problems so far: %d\n", solv->problems.count);
2388 * now add policy rules
2392 solv->systemrules = solv->nrules;
2395 * create rules for updating installed solvables
2401 if (!solv->allowuninstall)
2402 { /* loop over all installed solvables */
2403 for (i = solv->system->start; i < solv->system->start + solv->system->nsolvables; i++)
2405 if (!MAPTST(&noupdaterule, i)) /* if not marked as 'noupdate' */
2406 addupdaterule(solv, pool->solvables + i, &addedmap, solv->allowdowngrade, solv->allowarchchange, 0);
2408 addrule(solv, 0, 0); /* place holder */
2410 /* consistency check: we added a rule for _every_ system solvable */
2411 if (solv->nrules - solv->systemrules != solv->system->nsolvables)
2415 if (pool->verbose) printf("problems so far: %d\n", solv->problems.count);
2417 /* create special weak system rules */
2418 if (solv->system->nsolvables)
2420 solv->weaksystemrules = xcalloc(solv->system->nsolvables, sizeof(Id));
2421 for (i = 0; i < solv->system->nsolvables; i++)
2423 findupdatepackages(solv, pool->solvables + solv->system->start + i, &q, (Map *)0, 1, 1);
2425 solv->weaksystemrules[i] = pool_queuetowhatprovides(pool, &q);
2429 /* free unneeded memory */
2431 mapfree(&noupdaterule);
2439 run_solver(solv, 1, 1);
2443 * print solver result
2447 if (pool->verbose) printf("-------------------------------------------------------------\n");
2449 if (solv->problems.count)
2459 clonequeue(&problems, &solv->problems);
2460 queueinit(&solution);
2461 printf("Encountered problems! Here are the solutions:\n");
2462 problem = problems.elements;
2463 for (i = 0; i < problems.count; i++)
2465 Id v = problems.elements[i];
2468 printf("====================================\n");
2469 problem = problems.elements + i + 1;
2472 refine_suggestion(solv, problem, v, &solution);
2473 for (j = 0; j < solution.count; j++)
2475 r = solv->rules + solution.elements[j];
2476 why = solution.elements[j];
2480 if (why >= solv->jobrules && why < solv->systemrules)
2482 /* do a sloppy job of analyzing the job rule */
2485 s = pool->solvables + r->p;
2486 printf("- do not install %s-%s.%s\n", id2str(pool, s->name), id2str(pool, s->evr), id2str(pool, s->arch));
2490 s = pool->solvables - r->p;
2491 printf("- do not erase %s-%s.%s\n", id2str(pool, s->name), id2str(pool, s->evr), id2str(pool, s->arch));
2494 else if (why >= solv->systemrules && why < solv->learntrules)
2496 s = pool->solvables + solv->system->start + (why - solv->systemrules);
2497 printf("- allow deinstallation/downgrade of %s-%s.%s [%d]\n", id2str(pool, s->name), id2str(pool, s->evr), id2str(pool, s->arch), why);
2504 printf("------------------------------------\n");
2509 printdecisions(solv);