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