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