00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014 #include <stdio.h>
00015 #include <stdlib.h>
00016 #include <unistd.h>
00017 #include <string.h>
00018 #include <assert.h>
00019
00020 #include "solver.h"
00021 #include "bitmap.h"
00022 #include "pool.h"
00023 #include "poolarch.h"
00024 #include "util.h"
00025 #include "policy.h"
00026 #include "solverdebug.h"
00027
00028 #define RULES_BLOCK 63
00029
00030 static void addrpmruleinfo(Solver *solv, Id p, Id d, int type, Id dep);
00031
00032
00033
00034
00035
00036
00037
00038 static inline int
00039 dep_possible(Solver *solv, Id dep, Map *m)
00040 {
00041 Pool *pool = solv->pool;
00042 Id p, pp;
00043
00044 if (ISRELDEP(dep))
00045 {
00046 Reldep *rd = GETRELDEP(pool, dep);
00047 if (rd->flags == REL_AND)
00048 {
00049 if (!dep_possible(solv, rd->name, m))
00050 return 0;
00051 return dep_possible(solv, rd->evr, m);
00052 }
00053 if (rd->flags == REL_NAMESPACE && rd->name == NAMESPACE_SPLITPROVIDES)
00054 return solver_splitprovides(solv, rd->evr);
00055 if (rd->flags == REL_NAMESPACE && rd->name == NAMESPACE_INSTALLED)
00056 return solver_dep_installed(solv, rd->evr);
00057 }
00058 FOR_PROVIDES(p, pp, dep)
00059 {
00060 if (MAPTST(m, p))
00061 return 1;
00062 }
00063 return 0;
00064 }
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079 static int
00080 unifyrules_sortcmp(const void *ap, const void *bp, void *dp)
00081 {
00082 Pool *pool = dp;
00083 Rule *a = (Rule *)ap;
00084 Rule *b = (Rule *)bp;
00085 Id *ad, *bd;
00086 int x;
00087
00088 x = a->p - b->p;
00089 if (x)
00090 return x;
00091
00092
00093 if (a->d == 0 && b->d == 0)
00094 return a->w2 - b->w2;
00095
00096 if (a->d == 0)
00097 {
00098 x = a->w2 - pool->whatprovidesdata[b->d];
00099 return x ? x : -1;
00100 }
00101
00102 if (b->d == 0)
00103 {
00104 x = pool->whatprovidesdata[a->d] - b->w2;
00105 return x ? x : 1;
00106 }
00107
00108
00109 ad = pool->whatprovidesdata + a->d;
00110 bd = pool->whatprovidesdata + b->d;
00111 while (*bd)
00112 if ((x = *ad++ - *bd++) != 0)
00113 return x;
00114 return *ad;
00115 }
00116
00117 int
00118 solver_samerule(Solver *solv, Rule *r1, Rule *r2)
00119 {
00120 return unifyrules_sortcmp(r1, r2, solv->pool);
00121 }
00122
00123
00124
00125
00126
00127
00128
00129
00130 void
00131 solver_unifyrules(Solver *solv)
00132 {
00133 Pool *pool = solv->pool;
00134 int i, j;
00135 Rule *ir, *jr;
00136
00137 if (solv->nrules <= 1)
00138 return;
00139
00140 POOL_DEBUG(SAT_DEBUG_SCHUBI, "----- unifyrules -----\n");
00141
00142
00143 sat_sort(solv->rules + 1, solv->nrules - 1, sizeof(Rule), unifyrules_sortcmp, solv->pool);
00144
00145
00146
00147
00148
00149 jr = 0;
00150 for (i = j = 1, ir = solv->rules + i; i < solv->nrules; i++, ir++)
00151 {
00152 if (jr && !unifyrules_sortcmp(ir, jr, pool))
00153 continue;
00154 jr = solv->rules + j++;
00155 if (ir != jr)
00156 *jr = *ir;
00157 }
00158
00159
00160 POOL_DEBUG(SAT_DEBUG_STATS, "pruned rules from %d to %d\n", solv->nrules, j);
00161
00162
00163 solv->nrules = j;
00164 solv->rules = sat_extend_resize(solv->rules, solv->nrules, sizeof(Rule), RULES_BLOCK);
00165
00166
00167
00168
00169 IF_POOLDEBUG (SAT_DEBUG_STATS)
00170 {
00171 int binr = 0;
00172 int lits = 0;
00173 Id *dp;
00174 Rule *r;
00175
00176 for (i = 1; i < solv->nrules; i++)
00177 {
00178 r = solv->rules + i;
00179 if (r->d == 0)
00180 binr++;
00181 else
00182 {
00183 dp = solv->pool->whatprovidesdata + r->d;
00184 while (*dp++)
00185 lits++;
00186 }
00187 }
00188 POOL_DEBUG(SAT_DEBUG_STATS, " binary: %d\n", binr);
00189 POOL_DEBUG(SAT_DEBUG_STATS, " normal: %d, %d literals\n", solv->nrules - 1 - binr, lits);
00190 }
00191 POOL_DEBUG(SAT_DEBUG_SCHUBI, "----- unifyrules end -----\n");
00192 }
00193
00194 #if 0
00195
00196
00197
00198
00199
00200 static Hashval
00201 hashrule(Solver *solv, Id p, Id d, int n)
00202 {
00203 unsigned int x = (unsigned int)p;
00204 int *dp;
00205
00206 if (n <= 1)
00207 return (x * 37) ^ (unsigned int)d;
00208 dp = solv->pool->whatprovidesdata + d;
00209 while (*dp)
00210 x = (x * 37) ^ (unsigned int)*dp++;
00211 return x;
00212 }
00213 #endif
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256 Rule *
00257 solver_addrule(Solver *solv, Id p, Id d)
00258 {
00259 Pool *pool = solv->pool;
00260 Rule *r = 0;
00261 Id *dp = 0;
00262
00263 int n = 0;
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273 if (solv->nrules
00274 && !solv->rpmrules_end)
00275 {
00276 r = solv->rules + solv->nrules - 1;
00277 if (r->p == p && r->d == d && d != 0)
00278 return r;
00279 }
00280
00281
00282
00283
00284
00285 if (d < 0)
00286 {
00287
00288 if (p == d)
00289 return 0;
00290 n = 1;
00291 }
00292 else if (d > 0)
00293 {
00294 for (dp = pool->whatprovidesdata + d; *dp; dp++, n++)
00295 if (*dp == -p)
00296 return 0;
00297
00298 if (n == 1)
00299 d = dp[-1];
00300 }
00301
00302 if (n == 1 && p > d && !solv->rpmrules_end)
00303 {
00304
00305 n = p; p = d; d = n;
00306 n = 1;
00307 }
00308
00309
00310
00311
00312
00313
00314 if (r && n == 1 && !r->d && r->p == p && r->w2 == d)
00315 return r;
00316
00317
00318 if (r && n > 1 && r->d && r->p == p)
00319 {
00320
00321 Id *dp2;
00322 if (d == r->d)
00323 return r;
00324 dp2 = pool->whatprovidesdata + r->d;
00325 for (dp = pool->whatprovidesdata + d; *dp; dp++, dp2++)
00326 if (*dp != *dp2)
00327 break;
00328 if (*dp == *dp2)
00329 return r;
00330 }
00331
00332
00333
00334
00335
00336
00337 solv->rules = sat_extend(solv->rules, solv->nrules, 1, sizeof(Rule), RULES_BLOCK);
00338 r = solv->rules + solv->nrules++;
00339
00340
00341
00342
00343
00344 r->p = p;
00345 if (n == 0)
00346 {
00347
00348 r->d = 0;
00349 r->w1 = p;
00350 r->w2 = 0;
00351 }
00352 else if (n == 1)
00353 {
00354
00355 r->d = 0;
00356 r->w1 = p;
00357 r->w2 = d;
00358 }
00359 else
00360 {
00361 r->d = d;
00362 r->w1 = p;
00363 r->w2 = pool->whatprovidesdata[d];
00364 }
00365 r->n1 = 0;
00366 r->n2 = 0;
00367
00368 IF_POOLDEBUG (SAT_DEBUG_RULE_CREATION)
00369 {
00370 POOL_DEBUG(SAT_DEBUG_RULE_CREATION, " Add rule: ");
00371 solver_printrule(solv, SAT_DEBUG_RULE_CREATION, r);
00372 }
00373
00374 return r;
00375 }
00376
00377
00378
00379
00380
00381
00382
00383
00384
00385
00386
00387
00388
00389
00390
00391 static Id
00392 makemultiversionconflict(Solver *solv, Id n, Id con)
00393 {
00394 Pool *pool = solv->pool;
00395 Solvable *s, *sn;
00396 Queue q;
00397 Id p, pp, qbuf[64];
00398
00399 sn = pool->solvables + n;
00400 queue_init_buffer(&q, qbuf, sizeof(qbuf)/sizeof(*qbuf));
00401 queue_push(&q, -n);
00402 FOR_PROVIDES(p, pp, sn->name)
00403 {
00404 s = pool->solvables + p;
00405 if (s->name != sn->name || s->arch != sn->arch)
00406 continue;
00407 if (!MAPTST(&solv->noobsoletes, p))
00408 continue;
00409 if (pool_match_nevr(pool, pool->solvables + p, con))
00410 continue;
00411
00412
00413 queue_push(&q, p);
00414 }
00415 if (q.count == 1)
00416 return -n;
00417 return pool_queuetowhatprovides(pool, &q);
00418 }
00419
00420 static inline void
00421 addrpmrule(Solver *solv, Id p, Id d, int type, Id dep)
00422 {
00423 if (!solv->ruleinfoq)
00424 solver_addrule(solv, p, d);
00425 else
00426 addrpmruleinfo(solv, p, d, type, dep);
00427 }
00428
00429
00430
00431
00432
00433
00434
00435
00436
00437
00438
00439
00440
00441
00442
00443
00444
00445
00446
00447
00448
00449 void
00450 solver_addrpmrulesforsolvable(Solver *solv, Solvable *s, Map *m)
00451 {
00452 Pool *pool = solv->pool;
00453 Repo *installed = solv->installed;
00454
00455
00456
00457 Queue workq;
00458 Id workqbuf[64];
00459
00460 int i;
00461
00462
00463
00464 int dontfix;
00465
00466
00467
00468 Id req, *reqp;
00469 Id con, *conp;
00470 Id obs, *obsp;
00471 Id rec, *recp;
00472 Id sug, *sugp;
00473 Id p, pp;
00474 Id *dp;
00475 Id n;
00476
00477 POOL_DEBUG(SAT_DEBUG_SCHUBI, "----- addrpmrulesforsolvable -----\n");
00478
00479 queue_init_buffer(&workq, workqbuf, sizeof(workqbuf)/sizeof(*workqbuf));
00480 queue_push(&workq, s - pool->solvables);
00481
00482
00483 while (workq.count)
00484 {
00485
00486
00487
00488
00489
00490 n = queue_shift(&workq);
00491 if (m)
00492 {
00493 if (MAPTST(m, n))
00494 continue;
00495 MAPSET(m, n);
00496 }
00497
00498 s = pool->solvables + n;
00499
00500 dontfix = 0;
00501 if (installed
00502 && !solv->fixsystem
00503 && s->repo == installed
00504 && (!solv->fixmap.size || !MAPTST(&solv->fixmap, n - installed->start)))
00505 {
00506 dontfix = 1;
00507 }
00508
00509 if (!dontfix
00510 && s->arch != ARCH_SRC
00511 && s->arch != ARCH_NOSRC
00512 && !pool_installable(pool, s))
00513 {
00514 POOL_DEBUG(SAT_DEBUG_RULE_CREATION, "package %s [%d] is not installable\n", solvable2str(pool, s), (Id)(s - pool->solvables));
00515 addrpmrule(solv, -n, 0, SOLVER_RULE_RPM_NOT_INSTALLABLE, 0);
00516 }
00517
00518
00519 if (pool->nscallback && !strncmp("product:", id2str(pool, s->name), 8))
00520 {
00521 Id buddy = pool->nscallback(pool, pool->nscallbackdata, NAMESPACE_PRODUCTBUDDY, n);
00522 if (buddy > 0 && buddy != SYSTEMSOLVABLE && buddy != n && buddy < pool->nsolvables)
00523 {
00524 addrpmrule(solv, n, -buddy, SOLVER_RULE_RPM_PACKAGE_REQUIRES, solvable_selfprovidedep(pool->solvables + n));
00525 addrpmrule(solv, buddy, -n, SOLVER_RULE_RPM_PACKAGE_REQUIRES, solvable_selfprovidedep(pool->solvables + buddy));
00526 if (m && !MAPTST(m, buddy))
00527 queue_push(&workq, buddy);
00528 }
00529 }
00530
00531
00532
00533
00534
00535 if (s->requires)
00536 {
00537 reqp = s->repo->idarraydata + s->requires;
00538 while ((req = *reqp++) != 0)
00539 {
00540 if (req == SOLVABLE_PREREQMARKER)
00541 continue;
00542
00543
00544 dp = pool_whatprovides_ptr(pool, req);
00545
00546 if (*dp == SYSTEMSOLVABLE)
00547 continue;
00548
00549 if (dontfix)
00550 {
00551
00552
00553
00554
00555
00556
00557 for (i = 0; (p = dp[i]) != 0; i++)
00558 {
00559 if (pool->solvables[p].repo == installed)
00560 break;
00561 }
00562
00563 if (!p)
00564 {
00565 POOL_DEBUG(SAT_DEBUG_RULE_CREATION, "ignoring broken requires %s of installed package %s\n", dep2str(pool, req), solvable2str(pool, s));
00566 continue;
00567 }
00568 }
00569
00570 if (!*dp)
00571 {
00572
00573 POOL_DEBUG(SAT_DEBUG_RULE_CREATION, "package %s [%d] is not installable (%s)\n", solvable2str(pool, s), (Id)(s - pool->solvables), dep2str(pool, req));
00574 addrpmrule(solv, -n, 0, SOLVER_RULE_RPM_NOTHING_PROVIDES_DEP, req);
00575 continue;
00576 }
00577
00578 IF_POOLDEBUG (SAT_DEBUG_RULE_CREATION)
00579 {
00580 POOL_DEBUG(SAT_DEBUG_RULE_CREATION," %s requires %s\n", solvable2str(pool, s), dep2str(pool, req));
00581 for (i = 0; dp[i]; i++)
00582 POOL_DEBUG(SAT_DEBUG_RULE_CREATION, " provided by %s\n", solvid2str(pool, dp[i]));
00583 }
00584
00585
00586
00587 addrpmrule(solv, -n, dp - pool->whatprovidesdata, SOLVER_RULE_RPM_PACKAGE_REQUIRES, req);
00588
00589
00590
00591 if (m)
00592 {
00593 for (; *dp; dp++)
00594 {
00595 if (!MAPTST(m, *dp))
00596 queue_push(&workq, *dp);
00597 }
00598 }
00599
00600 }
00601
00602 }
00603
00604
00605 if (s->arch == ARCH_SRC || s->arch == ARCH_NOSRC)
00606 continue;
00607
00608
00609
00610
00611
00612 if (s->conflicts)
00613 {
00614 int ispatch = 0;
00615
00616
00617
00618
00619
00620
00621
00622 if (!strncmp("patch:", id2str(pool, s->name), 6))
00623 ispatch = 1;
00624 conp = s->repo->idarraydata + s->conflicts;
00625
00626 while ((con = *conp++) != 0)
00627 {
00628
00629 FOR_PROVIDES(p, pp, con)
00630 {
00631 if (ispatch && !pool_match_nevr(pool, pool->solvables + p, con))
00632 continue;
00633
00634 if (dontfix && pool->solvables[p].repo == installed)
00635 continue;
00636
00637 if (p == n && !pool->allowselfconflicts)
00638 {
00639 if (ISRELDEP(con))
00640 {
00641 Reldep *rd = GETRELDEP(pool, con);
00642 if (rd->flags == REL_NAMESPACE && rd->name == NAMESPACE_OTHERPROVIDERS)
00643 continue;
00644 }
00645 p = 0;
00646 }
00647 if (p && ispatch && solv->noobsoletes.size && MAPTST(&solv->noobsoletes, p) && ISRELDEP(con))
00648 {
00649
00650 p = -makemultiversionconflict(solv, p, con);
00651 }
00652
00653 addrpmrule(solv, -n, -p, p ? SOLVER_RULE_RPM_PACKAGE_CONFLICT : SOLVER_RULE_RPM_SELF_CONFLICT, con);
00654 }
00655 }
00656 }
00657
00658
00659
00660
00661
00662 if (!installed || pool->solvables[n].repo != installed)
00663 {
00664 int noobs = solv->noobsoletes.size && MAPTST(&solv->noobsoletes, n);
00665 if (s->obsoletes && !noobs)
00666 {
00667 obsp = s->repo->idarraydata + s->obsoletes;
00668
00669 while ((obs = *obsp++) != 0)
00670 {
00671
00672 FOR_PROVIDES(p, pp, obs)
00673 {
00674 Solvable *ps = pool->solvables + p;
00675 if (!pool->obsoleteusesprovides
00676 && !pool_match_nevr(pool, ps, obs))
00677 continue;
00678 if (pool->obsoleteusescolors && !pool_colormatch(pool, s, ps))
00679 continue;
00680 addrpmrule(solv, -n, -p, SOLVER_RULE_RPM_PACKAGE_OBSOLETES, obs);
00681 }
00682 }
00683 }
00684 FOR_PROVIDES(p, pp, s->name)
00685 {
00686 Solvable *ps = pool->solvables + p;
00687
00688
00689 if (noobs && (s->name != ps->name || s->evr != ps->evr || s->arch != ps->arch))
00690 continue;
00691 if (!pool->implicitobsoleteusesprovides && s->name != ps->name)
00692 continue;
00693 if (pool->obsoleteusescolors && !pool_colormatch(pool, s, ps))
00694 continue;
00695 if (s->name == ps->name)
00696 addrpmrule(solv, -n, -p, SOLVER_RULE_RPM_SAME_NAME, 0);
00697 else
00698 addrpmrule(solv, -n, -p, SOLVER_RULE_RPM_IMPLICIT_OBSOLETES, s->name);
00699 }
00700 }
00701
00702
00703
00704
00705 if (s->recommends && m)
00706 {
00707 recp = s->repo->idarraydata + s->recommends;
00708 while ((rec = *recp++) != 0)
00709 {
00710 FOR_PROVIDES(p, pp, rec)
00711 if (!MAPTST(m, p))
00712 queue_push(&workq, p);
00713 }
00714 }
00715 if (s->suggests && m)
00716 {
00717 sugp = s->repo->idarraydata + s->suggests;
00718 while ((sug = *sugp++) != 0)
00719 {
00720 FOR_PROVIDES(p, pp, sug)
00721 if (!MAPTST(m, p))
00722 queue_push(&workq, p);
00723 }
00724 }
00725 }
00726 queue_free(&workq);
00727 POOL_DEBUG(SAT_DEBUG_SCHUBI, "----- addrpmrulesforsolvable end -----\n");
00728 }
00729
00730
00731
00732
00733
00734
00735
00736
00737
00738 void
00739 solver_addrpmrulesforweak(Solver *solv, Map *m)
00740 {
00741 Pool *pool = solv->pool;
00742 Solvable *s;
00743 Id sup, *supp;
00744 int i, n;
00745
00746 POOL_DEBUG(SAT_DEBUG_SCHUBI, "----- addrpmrulesforweak -----\n");
00747
00748 for (i = n = 1; n < pool->nsolvables; i++, n++)
00749 {
00750 if (i == pool->nsolvables)
00751 i = 1;
00752 if (MAPTST(m, i))
00753 continue;
00754
00755 s = pool->solvables + i;
00756 if (!pool_installable(pool, s))
00757 continue;
00758
00759 sup = 0;
00760 if (s->supplements)
00761 {
00762
00763 supp = s->repo->idarraydata + s->supplements;
00764 while ((sup = *supp++) != ID_NULL)
00765 if (dep_possible(solv, sup, m))
00766 break;
00767 }
00768
00769
00770 if (!sup && s->enhances)
00771 {
00772 supp = s->repo->idarraydata + s->enhances;
00773 while ((sup = *supp++) != ID_NULL)
00774 if (dep_possible(solv, sup, m))
00775 break;
00776 }
00777
00778 if (!sup)
00779 continue;
00780 solver_addrpmrulesforsolvable(solv, s, m);
00781 n = 0;
00782 }
00783 POOL_DEBUG(SAT_DEBUG_SCHUBI, "----- addrpmrulesforweak end -----\n");
00784 }
00785
00786
00787
00788
00789
00790
00791
00792
00793
00794
00795
00796 void
00797 solver_addrpmrulesforupdaters(Solver *solv, Solvable *s, Map *m, int allow_all)
00798 {
00799 Pool *pool = solv->pool;
00800 int i;
00801
00802 Queue qs;
00803 Id qsbuf[64];
00804
00805 POOL_DEBUG(SAT_DEBUG_SCHUBI, "----- addrpmrulesforupdaters -----\n");
00806
00807 queue_init_buffer(&qs, qsbuf, sizeof(qsbuf)/sizeof(*qsbuf));
00808
00809 policy_findupdatepackages(solv, s, &qs, allow_all);
00810
00811 if (!MAPTST(m, s - pool->solvables))
00812 solver_addrpmrulesforsolvable(solv, s, m);
00813
00814 for (i = 0; i < qs.count; i++)
00815 if (!MAPTST(m, qs.elements[i]))
00816 solver_addrpmrulesforsolvable(solv, pool->solvables + qs.elements[i], m);
00817 queue_free(&qs);
00818
00819 POOL_DEBUG(SAT_DEBUG_SCHUBI, "----- addrpmrulesforupdaters -----\n");
00820 }
00821
00822
00823
00824
00825
00826
00827
00828
00829
00830
00831 static Id
00832 finddistupgradepackages(Solver *solv, Solvable *s, Queue *qs, int allow_all)
00833 {
00834 Pool *pool = solv->pool;
00835 int i;
00836
00837 policy_findupdatepackages(solv, s, qs, allow_all);
00838 if (!qs->count)
00839 {
00840 if (allow_all)
00841 return 0;
00842
00843 policy_findupdatepackages(solv, s, qs, 1);
00844 if (!qs->count)
00845 return 0;
00846 qs->count = 0;
00847 return -SYSTEMSOLVABLE;
00848 }
00849 if (allow_all)
00850 return s - pool->solvables;
00851
00852 for (i = 0; i < qs->count; i++)
00853 {
00854 Solvable *ns = pool->solvables + qs->elements[i];
00855 if (s->evr == ns->evr && solvable_identical(s, ns))
00856 return s - pool->solvables;
00857 }
00858
00859 return -SYSTEMSOLVABLE;
00860 }
00861
00862
00863
00864
00865 static void
00866 addduppackages(Solver *solv, Solvable *s, Queue *qs)
00867 {
00868 Queue dupqs;
00869 Id p, dupqsbuf[64];
00870 int i;
00871 int oldnoupdateprovide = solv->noupdateprovide;
00872
00873 queue_init_buffer(&dupqs, dupqsbuf, sizeof(dupqsbuf)/sizeof(*dupqsbuf));
00874 solv->noupdateprovide = 1;
00875 policy_findupdatepackages(solv, s, &dupqs, 2);
00876 solv->noupdateprovide = oldnoupdateprovide;
00877 for (i = 0; i < dupqs.count; i++)
00878 {
00879 p = dupqs.elements[i];
00880 if (MAPTST(&solv->dupmap, p))
00881 queue_pushunique(qs, p);
00882 }
00883 queue_free(&dupqs);
00884 }
00885
00886
00887
00888
00889
00890
00891
00892
00893
00894 void
00895 solver_addupdaterule(Solver *solv, Solvable *s, int allow_all)
00896 {
00897
00898 Pool *pool = solv->pool;
00899 Id p, d;
00900 Queue qs;
00901 Id qsbuf[64];
00902
00903 POOL_DEBUG(SAT_DEBUG_SCHUBI, "----- addupdaterule -----\n");
00904 queue_init_buffer(&qs, qsbuf, sizeof(qsbuf)/sizeof(*qsbuf));
00905 p = s - pool->solvables;
00906
00907 if (solv->distupgrade)
00908 p = finddistupgradepackages(solv, s, &qs, allow_all);
00909 else
00910 policy_findupdatepackages(solv, s, &qs, allow_all);
00911 if (!allow_all && !solv->distupgrade && solv->dupinvolvedmap.size && MAPTST(&solv->dupinvolvedmap, p))
00912 addduppackages(solv, s, &qs);
00913
00914 if (!allow_all && qs.count && solv->noobsoletes.size)
00915 {
00916 int i, j;
00917
00918 d = pool_queuetowhatprovides(pool, &qs);
00919
00920 for (i = j = 0; i < qs.count; i++)
00921 {
00922 if (MAPTST(&solv->noobsoletes, qs.elements[i]))
00923 {
00924
00925 Solvable *ps = pool->solvables + qs.elements[i];
00926 if (ps->name != s->name || ps->evr != s->evr || ps->arch != s->arch)
00927 continue;
00928 }
00929 qs.elements[j++] = qs.elements[i];
00930 }
00931 if (j < qs.count)
00932 {
00933 if (d && solv->updatesystem && solv->installed && s->repo == solv->installed)
00934 {
00935 if (!solv->multiversionupdaters)
00936 solv->multiversionupdaters = sat_calloc(solv->installed->end - solv->installed->start, sizeof(Id));
00937 solv->multiversionupdaters[s - pool->solvables - solv->installed->start] = d;
00938 }
00939 if (j == 0 && p == -SYSTEMSOLVABLE && solv->distupgrade)
00940 {
00941 queue_push(&solv->orphaned, s - pool->solvables);
00942 j = qs.count;
00943 }
00944 qs.count = j;
00945 }
00946 }
00947 if (qs.count && p == -SYSTEMSOLVABLE)
00948 p = queue_shift(&qs);
00949 d = qs.count ? pool_queuetowhatprovides(pool, &qs) : 0;
00950 queue_free(&qs);
00951 solver_addrule(solv, p, d);
00952 POOL_DEBUG(SAT_DEBUG_SCHUBI, "----- addupdaterule end -----\n");
00953 }
00954
00955 static inline void
00956 disableupdaterule(Solver *solv, Id p)
00957 {
00958 Rule *r;
00959
00960 MAPSET(&solv->noupdate, p - solv->installed->start);
00961 r = solv->rules + solv->updaterules + (p - solv->installed->start);
00962 if (r->p && r->d >= 0)
00963 solver_disablerule(solv, r);
00964 r = solv->rules + solv->featurerules + (p - solv->installed->start);
00965 if (r->p && r->d >= 0)
00966 solver_disablerule(solv, r);
00967 }
00968
00969 static inline void
00970 reenableupdaterule(Solver *solv, Id p)
00971 {
00972 Pool *pool = solv->pool;
00973 Rule *r;
00974
00975 MAPCLR(&solv->noupdate, p - solv->installed->start);
00976 r = solv->rules + solv->updaterules + (p - solv->installed->start);
00977 if (r->p)
00978 {
00979 if (r->d >= 0)
00980 return;
00981 solver_enablerule(solv, r);
00982 IF_POOLDEBUG (SAT_DEBUG_SOLUTIONS)
00983 {
00984 POOL_DEBUG(SAT_DEBUG_SOLUTIONS, "@@@ re-enabling ");
00985 solver_printruleclass(solv, SAT_DEBUG_SOLUTIONS, r);
00986 }
00987 return;
00988 }
00989 r = solv->rules + solv->featurerules + (p - solv->installed->start);
00990 if (r->p && r->d < 0)
00991 {
00992 solver_enablerule(solv, r);
00993 IF_POOLDEBUG (SAT_DEBUG_SOLUTIONS)
00994 {
00995 POOL_DEBUG(SAT_DEBUG_SOLUTIONS, "@@@ re-enabling ");
00996 solver_printruleclass(solv, SAT_DEBUG_SOLUTIONS, r);
00997 }
00998 }
00999 }
01000
01001
01002
01003
01004
01005
01006
01007
01008
01009
01010
01011 void
01012 solver_addinfarchrules(Solver *solv, Map *addedmap)
01013 {
01014 Pool *pool = solv->pool;
01015 int first, i, j;
01016 Id p, pp, a, aa, bestarch;
01017 Solvable *s, *ps, *bests;
01018 Queue badq, allowedarchs;
01019
01020 queue_init(&badq);
01021 queue_init(&allowedarchs);
01022 solv->infarchrules = solv->nrules;
01023 for (i = 1; i < pool->nsolvables; i++)
01024 {
01025 if (i == SYSTEMSOLVABLE || !MAPTST(addedmap, i))
01026 continue;
01027 s = pool->solvables + i;
01028 first = i;
01029 bestarch = 0;
01030 bests = 0;
01031 queue_empty(&allowedarchs);
01032 FOR_PROVIDES(p, pp, s->name)
01033 {
01034 ps = pool->solvables + p;
01035 if (ps->name != s->name || !MAPTST(addedmap, p))
01036 continue;
01037 if (p == i)
01038 first = 0;
01039 if (first)
01040 break;
01041 a = ps->arch;
01042 a = (a <= pool->lastarch) ? pool->id2arch[a] : 0;
01043 if (a != 1 && pool->installed && ps->repo == pool->installed)
01044 {
01045 if (!solv->distupgrade)
01046 queue_pushunique(&allowedarchs, ps->arch);
01047 continue;
01048 }
01049 if (a && a != 1 && (!bestarch || a < bestarch))
01050 {
01051 bestarch = a;
01052 bests = ps;
01053 }
01054 }
01055 if (first)
01056 continue;
01057
01058 if (allowedarchs.count == 1 && bests && allowedarchs.elements[0] == bests->arch)
01059 allowedarchs.count--;
01060 queue_empty(&badq);
01061 FOR_PROVIDES(p, pp, s->name)
01062 {
01063 ps = pool->solvables + p;
01064 if (ps->name != s->name || !MAPTST(addedmap, p))
01065 continue;
01066 a = ps->arch;
01067 a = (a <= pool->lastarch) ? pool->id2arch[a] : 0;
01068 if (a != 1 && bestarch && ((a ^ bestarch) & 0xffff0000) != 0)
01069 {
01070 if (pool->installed && ps->repo == pool->installed)
01071 continue;
01072 for (j = 0; j < allowedarchs.count; j++)
01073 {
01074 aa = allowedarchs.elements[j];
01075 if (ps->arch == aa)
01076 break;
01077 aa = (aa <= pool->lastarch) ? pool->id2arch[aa] : 0;
01078 if (aa && ((a ^ aa) & 0xffff0000) == 0)
01079 break;
01080 }
01081 if (j == allowedarchs.count)
01082 queue_push(&badq, p);
01083 }
01084 }
01085 if (!badq.count)
01086 continue;
01087
01088 for (j = 0; j < badq.count; j++)
01089 {
01090 p = badq.elements[j];
01091 solver_addrule(solv, -p, 0);
01092 }
01093 }
01094 queue_free(&badq);
01095 queue_free(&allowedarchs);
01096 solv->infarchrules_end = solv->nrules;
01097 }
01098
01099 static inline void
01100 disableinfarchrule(Solver *solv, Id name)
01101 {
01102 Pool *pool = solv->pool;
01103 Rule *r;
01104 int i;
01105 for (i = solv->infarchrules, r = solv->rules + i; i < solv->infarchrules_end; i++, r++)
01106 {
01107 if (r->p < 0 && r->d >= 0 && pool->solvables[-r->p].name == name)
01108 solver_disablerule(solv, r);
01109 }
01110 }
01111
01112 static inline void
01113 reenableinfarchrule(Solver *solv, Id name)
01114 {
01115 Pool *pool = solv->pool;
01116 Rule *r;
01117 int i;
01118 for (i = solv->infarchrules, r = solv->rules + i; i < solv->infarchrules_end; i++, r++)
01119 {
01120 if (r->p < 0 && r->d < 0 && pool->solvables[-r->p].name == name)
01121 {
01122 solver_enablerule(solv, r);
01123 IF_POOLDEBUG (SAT_DEBUG_SOLUTIONS)
01124 {
01125 POOL_DEBUG(SAT_DEBUG_SOLUTIONS, "@@@ re-enabling ");
01126 solver_printruleclass(solv, SAT_DEBUG_SOLUTIONS, r);
01127 }
01128 }
01129 }
01130 }
01131
01132
01133
01134
01135
01136
01137
01138
01139
01140
01141
01142 void
01143 solver_createdupmaps(Solver *solv)
01144 {
01145 Queue *job = &solv->job;
01146 Pool *pool = solv->pool;
01147 Repo *repo;
01148 Id how, what, p, pi, pp, obs, *obsp;
01149 Solvable *s, *ps;
01150 int i;
01151
01152 map_init(&solv->dupmap, pool->nsolvables);
01153 map_init(&solv->dupinvolvedmap, pool->nsolvables);
01154 for (i = 0; i < job->count; i += 2)
01155 {
01156 how = job->elements[i];
01157 what = job->elements[i + 1];
01158 switch (how & SOLVER_JOBMASK)
01159 {
01160 case SOLVER_DISTUPGRADE:
01161 if ((how & SOLVER_SELECTMASK) != SOLVER_SOLVABLE_REPO)
01162 break;
01163 if (what <= 0 || what > pool->nrepos)
01164 break;
01165 repo = pool_id2repo(pool, what);
01166 FOR_REPO_SOLVABLES(repo, p, s)
01167 {
01168 if (repo != solv->installed && !pool_installable(pool, s))
01169 continue;
01170 MAPSET(&solv->dupmap, p);
01171 FOR_PROVIDES(pi, pp, s->name)
01172 {
01173 ps = pool->solvables + pi;
01174 if (ps->name != s->name)
01175 continue;
01176 MAPSET(&solv->dupinvolvedmap, pi);
01177 }
01178 if (s->obsoletes)
01179 {
01180
01181 obsp = s->repo->idarraydata + s->obsoletes;
01182 while ((obs = *obsp++) != 0)
01183 {
01184 FOR_PROVIDES(pi, pp, obs)
01185 {
01186 Solvable *pis = pool->solvables + pi;
01187 if (!pool->obsoleteusesprovides && !pool_match_nevr(pool, pis, obs))
01188 continue;
01189 if (pool->obsoleteusescolors && !pool_colormatch(pool, s, pis))
01190 continue;
01191 MAPSET(&solv->dupinvolvedmap, pi);
01192 }
01193 }
01194 }
01195 }
01196 break;
01197 default:
01198 break;
01199 }
01200 }
01201 MAPCLR(&solv->dupinvolvedmap, SYSTEMSOLVABLE);
01202 }
01203
01204 void
01205 solver_freedupmaps(Solver *solv)
01206 {
01207 map_free(&solv->dupmap);
01208 map_free(&solv->dupinvolvedmap);
01209 }
01210
01211 void
01212 solver_addduprules(Solver *solv, Map *addedmap)
01213 {
01214 Pool *pool = solv->pool;
01215 Id p, pp;
01216 Solvable *s, *ps;
01217 int first, i;
01218
01219 solv->duprules = solv->nrules;
01220 for (i = 1; i < pool->nsolvables; i++)
01221 {
01222 if (i == SYSTEMSOLVABLE || !MAPTST(addedmap, i))
01223 continue;
01224 s = pool->solvables + i;
01225 first = i;
01226 FOR_PROVIDES(p, pp, s->name)
01227 {
01228 ps = pool->solvables + p;
01229 if (ps->name != s->name || !MAPTST(addedmap, p))
01230 continue;
01231 if (p == i)
01232 first = 0;
01233 if (first)
01234 break;
01235 if (!MAPTST(&solv->dupinvolvedmap, p))
01236 continue;
01237 if (solv->installed && ps->repo == solv->installed)
01238 {
01239 if (!solv->updatemap.size)
01240 map_grow(&solv->updatemap, solv->installed->end - solv->installed->start);
01241 MAPSET(&solv->updatemap, p - solv->installed->start);
01242 if (!MAPTST(&solv->dupmap, p))
01243 {
01244 Id ip, ipp;
01245
01246 FOR_PROVIDES(ip, ipp, ps->name)
01247 {
01248 Solvable *is = pool->solvables + ip;
01249 if (!MAPTST(&solv->dupmap, ip))
01250 continue;
01251 if (is->evr == ps->evr && solvable_identical(ps, is))
01252 break;
01253 }
01254 if (!ip)
01255 solver_addrule(solv, -p, 0);
01256 }
01257 }
01258 else if (!MAPTST(&solv->dupmap, p))
01259 solver_addrule(solv, -p, 0);
01260 }
01261 }
01262 solv->duprules_end = solv->nrules;
01263 }
01264
01265
01266 static inline void
01267 disableduprule(Solver *solv, Id name)
01268 {
01269 Pool *pool = solv->pool;
01270 Rule *r;
01271 int i;
01272 for (i = solv->duprules, r = solv->rules + i; i < solv->duprules_end; i++, r++)
01273 {
01274 if (r->p < 0 && r->d >= 0 && pool->solvables[-r->p].name == name)
01275 solver_disablerule(solv, r);
01276 }
01277 }
01278
01279 static inline void
01280 reenableduprule(Solver *solv, Id name)
01281 {
01282 Pool *pool = solv->pool;
01283 Rule *r;
01284 int i;
01285 for (i = solv->duprules, r = solv->rules + i; i < solv->duprules_end; i++, r++)
01286 {
01287 if (r->p < 0 && r->d < 0 && pool->solvables[-r->p].name == name)
01288 {
01289 solver_enablerule(solv, r);
01290 IF_POOLDEBUG (SAT_DEBUG_SOLUTIONS)
01291 {
01292 POOL_DEBUG(SAT_DEBUG_SOLUTIONS, "@@@ re-enabling ");
01293 solver_printruleclass(solv, SAT_DEBUG_SOLUTIONS, r);
01294 }
01295 }
01296 }
01297 }
01298
01299
01300
01301
01302
01303
01304
01305
01306
01307
01308
01309 #define DISABLE_UPDATE 1
01310 #define DISABLE_INFARCH 2
01311 #define DISABLE_DUP 3
01312
01313 static void
01314 jobtodisablelist(Solver *solv, Id how, Id what, Queue *q)
01315 {
01316 Pool *pool = solv->pool;
01317 Id select, p, pp;
01318 Repo *installed;
01319 Solvable *s;
01320 int i;
01321
01322 installed = solv->installed;
01323 select = how & SOLVER_SELECTMASK;
01324 switch (how & SOLVER_JOBMASK)
01325 {
01326 case SOLVER_INSTALL:
01327 if ((select == SOLVER_SOLVABLE_NAME || select == SOLVER_SOLVABLE_PROVIDES) && solv->infarchrules != solv->infarchrules_end && ISRELDEP(what))
01328 {
01329 Reldep *rd = GETRELDEP(pool, what);
01330 if (rd->flags == REL_ARCH)
01331 {
01332 int qcnt = q->count;
01333 FOR_JOB_SELECT(p, pp, select, what)
01334 {
01335 s = pool->solvables + p;
01336
01337 for (i = qcnt; i < q->count; i += 2)
01338 if (q->elements[i + 1] == s->name)
01339 break;
01340 if (i < q->count)
01341 continue;
01342 queue_push(q, DISABLE_INFARCH);
01343 queue_push(q, s->name);
01344 }
01345 }
01346 }
01347 if (select != SOLVER_SOLVABLE)
01348 break;
01349 s = pool->solvables + what;
01350 if (solv->infarchrules != solv->infarchrules_end)
01351 {
01352 queue_push(q, DISABLE_INFARCH);
01353 queue_push(q, s->name);
01354 }
01355 if (solv->duprules != solv->duprules_end)
01356 {
01357 queue_push(q, DISABLE_DUP);
01358 queue_push(q, s->name);
01359 }
01360 if (!installed)
01361 return;
01362 if (solv->noobsoletes.size && MAPTST(&solv->noobsoletes, what))
01363 {
01364
01365 if (solv->distupgrade && s->repo == installed)
01366 {
01367 queue_push(q, DISABLE_UPDATE);
01368 queue_push(q, what);
01369 return;
01370 }
01371 return;
01372 }
01373 if (s->repo == installed)
01374 {
01375 queue_push(q, DISABLE_UPDATE);
01376 queue_push(q, what);
01377 return;
01378 }
01379 if (s->obsoletes)
01380 {
01381 Id obs, *obsp;
01382 obsp = s->repo->idarraydata + s->obsoletes;
01383 while ((obs = *obsp++) != 0)
01384 FOR_PROVIDES(p, pp, obs)
01385 {
01386 Solvable *ps = pool->solvables + p;
01387 if (ps->repo != installed)
01388 continue;
01389 if (!pool->obsoleteusesprovides && !pool_match_nevr(pool, ps, obs))
01390 continue;
01391 if (pool->obsoleteusescolors && !pool_colormatch(pool, s, ps))
01392 continue;
01393 queue_push(q, DISABLE_UPDATE);
01394 queue_push(q, p);
01395 }
01396 }
01397 FOR_PROVIDES(p, pp, s->name)
01398 {
01399 Solvable *ps = pool->solvables + p;
01400 if (ps->repo != installed)
01401 continue;
01402 if (!pool->implicitobsoleteusesprovides && ps->name != s->name)
01403 continue;
01404 if (pool->obsoleteusescolors && !pool_colormatch(pool, s, ps))
01405 continue;
01406 queue_push(q, DISABLE_UPDATE);
01407 queue_push(q, p);
01408 }
01409 return;
01410 case SOLVER_ERASE:
01411 if (!installed)
01412 break;
01413 FOR_JOB_SELECT(p, pp, select, what)
01414 if (pool->solvables[p].repo == installed)
01415 {
01416 queue_push(q, DISABLE_UPDATE);
01417 queue_push(q, p);
01418 }
01419 return;
01420 default:
01421 return;
01422 }
01423 }
01424
01425
01426 void
01427 solver_disablepolicyrules(Solver *solv)
01428 {
01429 Queue *job = &solv->job;
01430 int i, j;
01431 Queue allq;
01432 Rule *r;
01433 Id lastjob = -1;
01434 Id allqbuf[128];
01435
01436 queue_init_buffer(&allq, allqbuf, sizeof(allqbuf)/sizeof(*allqbuf));
01437
01438 for (i = solv->jobrules; i < solv->jobrules_end; i++)
01439 {
01440 r = solv->rules + i;
01441 if (r->d < 0)
01442 continue;
01443 j = solv->ruletojob.elements[i - solv->jobrules];
01444 if (j == lastjob)
01445 continue;
01446 lastjob = j;
01447 jobtodisablelist(solv, job->elements[j], job->elements[j + 1], &allq);
01448 }
01449 MAPZERO(&solv->noupdate);
01450 for (i = 0; i < allq.count; i += 2)
01451 {
01452 Id type = allq.elements[i], arg = allq.elements[i + 1];
01453 switch(type)
01454 {
01455 case DISABLE_UPDATE:
01456 disableupdaterule(solv, arg);
01457 break;
01458 case DISABLE_INFARCH:
01459 disableinfarchrule(solv, arg);
01460 break;
01461 case DISABLE_DUP:
01462 disableduprule(solv, arg);
01463 break;
01464 default:
01465 break;
01466 }
01467 }
01468 queue_free(&allq);
01469 }
01470
01471
01472
01473 void
01474 solver_reenablepolicyrules(Solver *solv, int jobidx)
01475 {
01476 Queue *job = &solv->job;
01477 int i, j;
01478 Queue q, allq;
01479 Rule *r;
01480 Id lastjob = -1;
01481 Id qbuf[32], allqbuf[128];
01482
01483 queue_init_buffer(&q, qbuf, sizeof(qbuf)/sizeof(*qbuf));
01484 queue_init_buffer(&allq, allqbuf, sizeof(allqbuf)/sizeof(*allqbuf));
01485 jobtodisablelist(solv, job->elements[jobidx], job->elements[jobidx + 1], &q);
01486 if (!q.count)
01487 return;
01488 for (i = solv->jobrules; i < solv->jobrules_end; i++)
01489 {
01490 r = solv->rules + i;
01491 if (r->d < 0)
01492 continue;
01493 j = solv->ruletojob.elements[i - solv->jobrules];
01494 if (j == lastjob)
01495 continue;
01496 lastjob = j;
01497 jobtodisablelist(solv, job->elements[j], job->elements[j + 1], &allq);
01498 }
01499 for (j = 0; j < q.count; j += 2)
01500 {
01501 Id type = q.elements[j], arg = q.elements[j + 1];
01502 for (i = 0; i < allq.count; i += 2)
01503 if (allq.elements[i] == type && allq.elements[i + 1] == arg)
01504 break;
01505 if (i < allq.count)
01506 continue;
01507 switch(type)
01508 {
01509 case DISABLE_UPDATE:
01510 reenableupdaterule(solv, arg);
01511 break;
01512 case DISABLE_INFARCH:
01513 reenableinfarchrule(solv, arg);
01514 break;
01515 case DISABLE_DUP:
01516 reenableduprule(solv, arg);
01517 break;
01518 }
01519 }
01520 queue_free(&allq);
01521 queue_free(&q);
01522 }
01523
01524
01525
01526
01527
01528
01529
01530
01531 static void
01532 addrpmruleinfo(Solver *solv, Id p, Id d, int type, Id dep)
01533 {
01534 Pool *pool = solv->pool;
01535 Rule *r;
01536 Id w2, op, od, ow2;
01537
01538
01539 r = solv->rules + solv->ruleinfoq->elements[0];
01540 op = r->p;
01541 od = r->d < 0 ? -r->d - 1 : r->d;
01542 ow2 = 0;
01543
01544
01545 w2 = d > 0 ? 0 : d;
01546 if (p < 0 && d > 0 && (!pool->whatprovidesdata[d] || !pool->whatprovidesdata[d + 1]))
01547 {
01548 w2 = pool->whatprovidesdata[d];
01549 d = 0;
01550
01551 }
01552 if (p > 0 && d < 0)
01553 {
01554 w2 = p;
01555 p = d;
01556 }
01557
01558 if (d > 0)
01559 {
01560 if (p != op && !od)
01561 return;
01562 if (d != od)
01563 {
01564 Id *dp = pool->whatprovidesdata + d;
01565 Id *odp = pool->whatprovidesdata + od;
01566 while (*dp)
01567 if (*dp++ != *odp++)
01568 return;
01569 if (*odp)
01570 return;
01571 }
01572 w2 = 0;
01573
01574 if (p < 0 && pool->whatprovidesdata[d] < 0)
01575 {
01576 w2 = pool->whatprovidesdata[d];
01577
01578 }
01579 }
01580 else
01581 {
01582 if (od)
01583 return;
01584 ow2 = r->w2;
01585 if (p > w2)
01586 {
01587 if (w2 != op || p != ow2)
01588 return;
01589 }
01590 else
01591 {
01592 if (p != op || w2 != ow2)
01593 return;
01594 }
01595 }
01596
01597 queue_push(solv->ruleinfoq, type);
01598 if (type == SOLVER_RULE_RPM_SAME_NAME)
01599 {
01600
01601 queue_push(solv->ruleinfoq, op < 0 ? -op : 0);
01602 queue_push(solv->ruleinfoq, ow2 < 0 ? -ow2 : 0);
01603 }
01604 else
01605 {
01606 queue_push(solv->ruleinfoq, p < 0 ? -p : 0);
01607 queue_push(solv->ruleinfoq, w2 < 0 ? -w2 : 0);
01608 }
01609 queue_push(solv->ruleinfoq, dep);
01610 }
01611
01612 static int
01613 solver_allruleinfos_cmp(const void *ap, const void *bp, void *dp)
01614 {
01615 const Id *a = ap, *b = bp;
01616 int r;
01617
01618 r = a[0] - b[0];
01619 if (r)
01620 return r;
01621 r = a[1] - b[1];
01622 if (r)
01623 return r;
01624 r = a[2] - b[2];
01625 if (r)
01626 return r;
01627 r = a[3] - b[3];
01628 if (r)
01629 return r;
01630 return 0;
01631 }
01632
01633 int
01634 solver_allruleinfos(Solver *solv, Id rid, Queue *rq)
01635 {
01636 Pool *pool = solv->pool;
01637 Rule *r = solv->rules + rid;
01638 int i, j;
01639
01640 queue_empty(rq);
01641 if (rid <= 0 || rid >= solv->rpmrules_end)
01642 {
01643 Id type, from, to, dep;
01644 type = solver_ruleinfo(solv, rid, &from, &to, &dep);
01645 queue_push(rq, type);
01646 queue_push(rq, from);
01647 queue_push(rq, to);
01648 queue_push(rq, dep);
01649 return 1;
01650 }
01651 if (r->p >= 0)
01652 return 0;
01653 queue_push(rq, rid);
01654 solv->ruleinfoq = rq;
01655 solver_addrpmrulesforsolvable(solv, pool->solvables - r->p, 0);
01656
01657 if ((r->d == 0 || r->d == -1) && r->w2 < 0)
01658 solver_addrpmrulesforsolvable(solv, pool->solvables - r->w2, 0);
01659 solv->ruleinfoq = 0;
01660 queue_shift(rq);
01661
01662 if (!rq->count)
01663 return 0;
01664 sat_sort(rq->elements, rq->count / 4, 4 * sizeof(Id), solver_allruleinfos_cmp, 0);
01665
01666 for (i = j = 0; i < rq->count; i += 4)
01667 {
01668 if (j)
01669 {
01670 if (rq->elements[i] == rq->elements[j - 4] &&
01671 rq->elements[i + 1] == rq->elements[j - 3] &&
01672 rq->elements[i + 2] == rq->elements[j - 2] &&
01673 rq->elements[i + 3] == rq->elements[j - 1])
01674 continue;
01675 }
01676 rq->elements[j++] = rq->elements[i];
01677 rq->elements[j++] = rq->elements[i + 1];
01678 rq->elements[j++] = rq->elements[i + 2];
01679 rq->elements[j++] = rq->elements[i + 3];
01680 }
01681 rq->count = j;
01682 return j / 4;
01683 }
01684
01685 SolverRuleinfo
01686 solver_ruleinfo(Solver *solv, Id rid, Id *fromp, Id *top, Id *depp)
01687 {
01688 Pool *pool = solv->pool;
01689 Rule *r = solv->rules + rid;
01690 SolverRuleinfo type = SOLVER_RULE_UNKNOWN;
01691
01692 if (fromp)
01693 *fromp = 0;
01694 if (top)
01695 *top = 0;
01696 if (depp)
01697 *depp = 0;
01698 if (rid > 0 && rid < solv->rpmrules_end)
01699 {
01700 Queue rq;
01701 int i;
01702
01703 if (r->p >= 0)
01704 return SOLVER_RULE_RPM;
01705 if (fromp)
01706 *fromp = -r->p;
01707 queue_init(&rq);
01708 queue_push(&rq, rid);
01709 solv->ruleinfoq = &rq;
01710 solver_addrpmrulesforsolvable(solv, pool->solvables - r->p, 0);
01711
01712 if ((r->d == 0 || r->d == -1) && r->w2 < 0)
01713 solver_addrpmrulesforsolvable(solv, pool->solvables - r->w2, 0);
01714 solv->ruleinfoq = 0;
01715 type = SOLVER_RULE_RPM;
01716 for (i = 1; i < rq.count; i += 4)
01717 {
01718 Id qt, qo, qp, qd;
01719 qt = rq.elements[i];
01720 qp = rq.elements[i + 1];
01721 qo = rq.elements[i + 2];
01722 qd = rq.elements[i + 3];
01723 if (type == SOLVER_RULE_RPM || type > qt)
01724 {
01725 type = qt;
01726 if (fromp)
01727 *fromp = qp;
01728 if (top)
01729 *top = qo;
01730 if (depp)
01731 *depp = qd;
01732 }
01733 }
01734 queue_free(&rq);
01735 return type;
01736 }
01737 if (rid >= solv->jobrules && rid < solv->jobrules_end)
01738 {
01739 Id jidx = solv->ruletojob.elements[rid - solv->jobrules];
01740 if (fromp)
01741 *fromp = jidx;
01742 if (top)
01743 *top = solv->job.elements[jidx];
01744 if (depp)
01745 *depp = solv->job.elements[jidx + 1];
01746 if ((r->d == 0 || r->d == -1) && r->w2 == 0 && r->p == -SYSTEMSOLVABLE && (solv->job.elements[jidx] & SOLVER_SELECTMASK) != SOLVER_SOLVABLE_ONE_OF)
01747 return SOLVER_RULE_JOB_NOTHING_PROVIDES_DEP;
01748 return SOLVER_RULE_JOB;
01749 }
01750 if (rid >= solv->updaterules && rid < solv->updaterules_end)
01751 {
01752 if (fromp)
01753 *fromp = solv->installed->start + (rid - solv->updaterules);
01754 return SOLVER_RULE_UPDATE;
01755 }
01756 if (rid >= solv->featurerules && rid < solv->featurerules_end)
01757 {
01758 if (fromp)
01759 *fromp = solv->installed->start + (rid - solv->featurerules);
01760 return SOLVER_RULE_FEATURE;
01761 }
01762 if (rid >= solv->duprules && rid < solv->duprules_end)
01763 {
01764 if (fromp)
01765 *fromp = -r->p;
01766 if (depp)
01767 *depp = pool->solvables[-r->p].name;
01768 return SOLVER_RULE_DISTUPGRADE;
01769 }
01770 if (rid >= solv->infarchrules && rid < solv->infarchrules_end)
01771 {
01772 if (fromp)
01773 *fromp = -r->p;
01774 if (depp)
01775 *depp = pool->solvables[-r->p].name;
01776 return SOLVER_RULE_INFARCH;
01777 }
01778 if (rid >= solv->choicerules && rid < solv->choicerules_end)
01779 {
01780 return SOLVER_RULE_CHOICE;
01781 }
01782 if (rid >= solv->learntrules)
01783 {
01784 return SOLVER_RULE_LEARNT;
01785 }
01786 return SOLVER_RULE_UNKNOWN;
01787 }
01788
01789 void
01790 addchoicerules(Solver *solv)
01791 {
01792 Pool *pool = solv->pool;
01793 Map m, mneg;
01794 Rule *r;
01795 Queue q, qi;
01796 int i, j, rid, havechoice;
01797 Id p, d, *pp;
01798 Id p2, pp2;
01799 Solvable *s, *s2;
01800
01801 solv->choicerules = solv->nrules;
01802 if (!pool->installed)
01803 {
01804 solv->choicerules_end = solv->nrules;
01805 return;
01806 }
01807 solv->choicerules_ref = sat_calloc(solv->rpmrules_end, sizeof(Id));
01808 queue_init(&q);
01809 queue_init(&qi);
01810 map_init(&m, pool->nsolvables);
01811 map_init(&mneg, pool->nsolvables);
01812
01813 for (rid = solv->infarchrules, r = solv->rules + rid; rid < solv->infarchrules_end; rid++, r++)
01814 if (r->p < 0 && !r->w2 && (r->d == 0 || r->d == -1))
01815 MAPSET(&mneg, -r->p);
01816 for (rid = solv->duprules, r = solv->rules + rid; rid < solv->duprules_end; rid++, r++)
01817 if (r->p < 0 && !r->w2 && (r->d == 0 || r->d == -1))
01818 MAPSET(&mneg, -r->p);
01819 for (rid = 1; rid < solv->rpmrules_end ; rid++)
01820 {
01821 r = solv->rules + rid;
01822 if (r->p >= 0 || ((r->d == 0 || r->d == -1) && r->w2 < 0))
01823 continue;
01824
01825 queue_empty(&q);
01826 queue_empty(&qi);
01827 havechoice = 0;
01828 FOR_RULELITERALS(p, pp, r)
01829 {
01830 if (p < 0)
01831 continue;
01832 s = pool->solvables + p;
01833 if (!s->repo)
01834 continue;
01835 if (s->repo == pool->installed)
01836 {
01837 queue_push(&q, p);
01838 continue;
01839 }
01840
01841 s2 = 0;
01842 FOR_PROVIDES(p2, pp2, s->name)
01843 {
01844 s2 = pool->solvables + p2;
01845 if (s2->repo != pool->installed)
01846 continue;
01847 if (!pool->implicitobsoleteusesprovides && s->name != s2->name)
01848 continue;
01849 if (pool->obsoleteusescolors && !pool_colormatch(pool, s, s2))
01850 continue;
01851 break;
01852 }
01853 if (p2)
01854 {
01855
01856 if (!solv->allowarchchange && s->arch != s2->arch && policy_illegal_archchange(solv, s, s2))
01857 continue;
01858 if (!solv->allowvendorchange && s->vendor != s2->vendor && policy_illegal_vendorchange(solv, s, s2))
01859 continue;
01860 if (MAPTST(&mneg, p))
01861 continue;
01862 queue_push(&qi, p2);
01863 queue_push(&q, p);
01864 continue;
01865 }
01866 if (s->obsoletes)
01867 {
01868 Id obs, *obsp = s->repo->idarraydata + s->obsoletes;
01869 s2 = 0;
01870 while ((obs = *obsp++) != 0)
01871 {
01872 FOR_PROVIDES(p2, pp2, obs)
01873 {
01874 s2 = pool->solvables + p2;
01875 if (s2->repo != pool->installed)
01876 continue;
01877 if (!pool->obsoleteusesprovides && !pool_match_nevr(pool, pool->solvables + p2, obs))
01878 continue;
01879 if (pool->obsoleteusescolors && !pool_colormatch(pool, s, s2))
01880 continue;
01881 break;
01882 }
01883 if (p2)
01884 break;
01885 }
01886 if (obs)
01887 {
01888
01889 if (!solv->allowarchchange && s->arch != s2->arch && policy_illegal_archchange(solv, s, s2))
01890 continue;
01891 if (!solv->allowvendorchange && s->vendor != s2->vendor && policy_illegal_vendorchange(solv, s, s2))
01892 continue;
01893 if (MAPTST(&mneg, p))
01894 continue;
01895 queue_push(&qi, p2);
01896 queue_push(&q, p);
01897 continue;
01898 }
01899 }
01900
01901 havechoice = 1;
01902 }
01903 if (!havechoice || !q.count)
01904 continue;
01905
01906
01907
01908
01909 map_empty(&m);
01910 FOR_RULELITERALS(p, pp, r)
01911 if (p > 0)
01912 MAPSET(&m, p);
01913 for (i = 0; i < qi.count; i++)
01914 {
01915 if (!qi.elements[i])
01916 continue;
01917 Rule *ur = solv->rules + solv->updaterules + (qi.elements[i] - pool->installed->start);
01918 if (!ur->p)
01919 ur = solv->rules + solv->featurerules + (qi.elements[i] - pool->installed->start);
01920 if (!ur->p)
01921 continue;
01922 FOR_RULELITERALS(p, pp, ur)
01923 if (!MAPTST(&m, p))
01924 break;
01925 if (p)
01926 break;
01927 for (j = i + 1; j < qi.count; j++)
01928 if (qi.elements[i] == qi.elements[j])
01929 qi.elements[j] = 0;
01930 }
01931 if (i == qi.count)
01932 {
01933 #if 0
01934 printf("skipping choice ");
01935 solver_printrule(solv, SAT_DEBUG_RESULT, solv->rules + rid);
01936 #endif
01937 continue;
01938 }
01939 d = q.count ? pool_queuetowhatprovides(pool, &q) : 0;
01940 solver_addrule(solv, r->p, d);
01941 queue_push(&solv->weakruleq, solv->nrules - 1);
01942 solv->choicerules_ref[solv->nrules - 1 - solv->choicerules] = rid;
01943 #if 0
01944 printf("OLD ");
01945 solver_printrule(solv, SAT_DEBUG_RESULT, solv->rules + rid);
01946 printf("WEAK CHOICE ");
01947 solver_printrule(solv, SAT_DEBUG_RESULT, solv->rules + solv->nrules - 1);
01948 #endif
01949 }
01950 queue_free(&q);
01951 queue_free(&qi);
01952 map_free(&m);
01953 map_free(&mneg);
01954 solv->choicerules_end = solv->nrules;
01955 }
01956
01957
01958
01959
01960
01961 void
01962 disablechoicerules(Solver *solv, Rule *r)
01963 {
01964 Id rid, p, *pp;
01965 Pool *pool = solv->pool;
01966 Map m;
01967 Rule *or;
01968
01969 or = solv->rules + solv->choicerules_ref[(r - solv->rules) - solv->choicerules];
01970 map_init(&m, pool->nsolvables);
01971 FOR_RULELITERALS(p, pp, or)
01972 if (p > 0)
01973 MAPSET(&m, p);
01974 FOR_RULELITERALS(p, pp, r)
01975 if (p > 0)
01976 MAPCLR(&m, p);
01977 for (rid = solv->choicerules; rid < solv->choicerules_end; rid++)
01978 {
01979 r = solv->rules + rid;
01980 if (r->d < 0)
01981 continue;
01982 or = solv->rules + solv->choicerules_ref[(r - solv->rules) - solv->choicerules];
01983 FOR_RULELITERALS(p, pp, or)
01984 if (p > 0 && MAPTST(&m, p))
01985 break;
01986 if (p)
01987 solver_disablerule(solv, r);
01988 }
01989 }
01990
01991