satsolver 0.16.3
|
00001 /* 00002 * Copyright (c) 2007, Novell Inc. 00003 * 00004 * This program is licensed under the BSD license, read LICENSE.BSD 00005 * for further information 00006 */ 00007 00008 /* 00009 * Generic policy interface for SAT solver 00010 * 00011 */ 00012 00013 #include <stdio.h> 00014 #include <stdlib.h> 00015 #include <unistd.h> 00016 #include <string.h> 00017 00018 #include "solver.h" 00019 #include "evr.h" 00020 #include "policy.h" 00021 #include "poolvendor.h" 00022 #include "poolarch.h" 00023 00024 00025 /*-----------------------------------------------------------------*/ 00026 00027 /* 00028 * prep for prune_best_version 00029 * sort by name 00030 */ 00031 00032 static int 00033 prune_to_best_version_sortcmp(const void *ap, const void *bp, void *dp) 00034 { 00035 Pool *pool = dp; 00036 int r; 00037 Id a = *(Id *)ap; 00038 Id b = *(Id *)bp; 00039 Solvable *sa, *sb; 00040 00041 sa = pool->solvables + a; 00042 sb = pool->solvables + b; 00043 r = sa->name - sb->name; 00044 if (r) 00045 { 00046 const char *na, *nb; 00047 /* different names. We use real strcmp here so that the result 00048 * is not depending on some random solvable order */ 00049 na = id2str(pool, sa->name); 00050 nb = id2str(pool, sb->name); 00051 return strcmp(na, nb); 00052 } 00053 /* the same name, bring installed solvables to the front */ 00054 if (pool->installed) 00055 { 00056 if (sa->repo == pool->installed) 00057 { 00058 if (sb->repo != pool->installed) 00059 return -1; 00060 } 00061 else if (sb->repo == pool->installed) 00062 return 1; 00063 } 00064 /* sort by repository sub-prio (installed repo handled above) */ 00065 r = (sb->repo ? sb->repo->subpriority : 0) - (sa->repo ? sa->repo->subpriority : 0); 00066 if (r) 00067 return r; 00068 /* no idea about the order, sort by id */ 00069 return a - b; 00070 } 00071 00072 00073 /* 00074 * prune to repository with highest priority. 00075 * does not prune installed solvables. 00076 */ 00077 00078 static void 00079 prune_to_highest_prio(Pool *pool, Queue *plist) 00080 { 00081 int i, j; 00082 Solvable *s; 00083 int bestprio = 0, bestprioset = 0; 00084 00085 /* prune to highest priority */ 00086 for (i = 0; i < plist->count; i++) /* find highest prio in queue */ 00087 { 00088 s = pool->solvables + plist->elements[i]; 00089 if (pool->installed && s->repo == pool->installed) 00090 continue; 00091 if (!bestprioset || s->repo->priority > bestprio) 00092 { 00093 bestprio = s->repo->priority; 00094 bestprioset = 1; 00095 } 00096 } 00097 if (!bestprioset) 00098 return; 00099 for (i = j = 0; i < plist->count; i++) /* remove all with lower prio */ 00100 { 00101 s = pool->solvables + plist->elements[i]; 00102 if (s->repo->priority == bestprio || (pool->installed && s->repo == pool->installed)) 00103 plist->elements[j++] = plist->elements[i]; 00104 } 00105 plist->count = j; 00106 } 00107 00108 static void 00109 prune_to_highest_prio_per_name(Pool *pool, Queue *plist) 00110 { 00111 Queue pq; 00112 int i, j, k; 00113 Id name; 00114 00115 queue_init(&pq); 00116 sat_sort(plist->elements, plist->count, sizeof(Id), prune_to_best_version_sortcmp, pool); 00117 queue_push(&pq, plist->elements[0]); 00118 name = pool->solvables[pq.elements[0]].name; 00119 for (i = 1, j = 0; i < plist->count; i++) 00120 { 00121 if (pool->solvables[plist->elements[i]].name != name) 00122 { 00123 if (pq.count > 2) 00124 prune_to_highest_prio(pool, &pq); 00125 for (k = 0; k < pq.count; k++) 00126 plist->elements[j++] = pq.elements[k]; 00127 queue_empty(&pq); 00128 queue_push(&pq, plist->elements[i]); 00129 name = pool->solvables[pq.elements[0]].name; 00130 } 00131 } 00132 if (pq.count > 2) 00133 prune_to_highest_prio(pool, &pq); 00134 for (k = 0; k < pq.count; k++) 00135 plist->elements[j++] = pq.elements[k]; 00136 queue_free(&pq); 00137 plist->count = j; 00138 } 00139 00140 00141 /* 00142 * prune to recommended/suggested packages. 00143 * does not prune installed packages (they are also somewhat recommended). 00144 */ 00145 00146 static void 00147 prune_to_recommended(Solver *solv, Queue *plist) 00148 { 00149 Pool *pool = solv->pool; 00150 int i, j, k, ninst; 00151 Solvable *s; 00152 Id p, pp, rec, *recp, sug, *sugp; 00153 00154 ninst = 0; 00155 if (pool->installed) 00156 { 00157 for (i = 0; i < plist->count; i++) 00158 { 00159 p = plist->elements[i]; 00160 s = pool->solvables + p; 00161 if (pool->installed && s->repo == pool->installed) 00162 ninst++; 00163 } 00164 } 00165 if (plist->count - ninst < 2) 00166 return; 00167 00168 /* update our recommendsmap/suggestsmap */ 00169 if (solv->recommends_index < 0) 00170 { 00171 MAPZERO(&solv->recommendsmap); 00172 MAPZERO(&solv->suggestsmap); 00173 solv->recommends_index = 0; 00174 } 00175 while (solv->recommends_index < solv->decisionq.count) 00176 { 00177 p = solv->decisionq.elements[solv->recommends_index++]; 00178 if (p < 0) 00179 continue; 00180 s = pool->solvables + p; 00181 if (s->recommends) 00182 { 00183 recp = s->repo->idarraydata + s->recommends; 00184 while ((rec = *recp++) != 0) 00185 FOR_PROVIDES(p, pp, rec) 00186 MAPSET(&solv->recommendsmap, p); 00187 } 00188 if (s->suggests) 00189 { 00190 sugp = s->repo->idarraydata + s->suggests; 00191 while ((sug = *sugp++) != 0) 00192 FOR_PROVIDES(p, pp, sug) 00193 MAPSET(&solv->suggestsmap, p); 00194 } 00195 } 00196 00197 /* prune to recommended/supplemented */ 00198 ninst = 0; 00199 for (i = j = 0; i < plist->count; i++) 00200 { 00201 p = plist->elements[i]; 00202 s = pool->solvables + p; 00203 if (pool->installed && s->repo == pool->installed) 00204 { 00205 ninst++; 00206 if (j) 00207 plist->elements[j++] = p; 00208 continue; 00209 } 00210 if (!MAPTST(&solv->recommendsmap, p)) 00211 if (!solver_is_supplementing(solv, s)) 00212 continue; 00213 if (!j && ninst) 00214 { 00215 for (k = 0; j < ninst; k++) 00216 { 00217 s = pool->solvables + plist->elements[k]; 00218 if (pool->installed && s->repo == pool->installed) 00219 plist->elements[j++] = plist->elements[k]; 00220 } 00221 } 00222 plist->elements[j++] = p; 00223 } 00224 if (j) 00225 plist->count = j; 00226 00227 /* anything left to prune? */ 00228 if (plist->count - ninst < 2) 00229 return; 00230 00231 /* prune to suggested/enhanced*/ 00232 ninst = 0; 00233 for (i = j = 0; i < plist->count; i++) 00234 { 00235 p = plist->elements[i]; 00236 s = pool->solvables + p; 00237 if (pool->installed && s->repo == pool->installed) 00238 { 00239 ninst++; 00240 if (j) 00241 plist->elements[j++] = p; 00242 continue; 00243 } 00244 if (!MAPTST(&solv->suggestsmap, p)) 00245 if (!solver_is_enhancing(solv, s)) 00246 continue; 00247 if (!j && ninst) 00248 { 00249 for (k = 0; j < ninst; k++) 00250 { 00251 s = pool->solvables + plist->elements[k]; 00252 if (pool->installed && s->repo == pool->installed) 00253 plist->elements[j++] = plist->elements[k]; 00254 } 00255 } 00256 plist->elements[j++] = p; 00257 } 00258 if (j) 00259 plist->count = j; 00260 } 00261 00262 void 00263 prune_to_best_arch(const Pool *pool, Queue *plist) 00264 { 00265 Id a, bestscore; 00266 Solvable *s; 00267 int i, j; 00268 00269 if (!pool->id2arch || plist->count < 2) 00270 return; 00271 bestscore = 0; 00272 for (i = 0; i < plist->count; i++) 00273 { 00274 s = pool->solvables + plist->elements[i]; 00275 a = s->arch; 00276 a = (a <= pool->lastarch) ? pool->id2arch[a] : 0; 00277 if (a && a != 1 && (!bestscore || a < bestscore)) 00278 bestscore = a; 00279 } 00280 for (i = j = 0; i < plist->count; i++) 00281 { 00282 s = pool->solvables + plist->elements[i]; 00283 a = s->arch; 00284 if (a > pool->lastarch) 00285 continue; 00286 a = pool->id2arch[a]; 00287 /* a == 1 -> noarch */ 00288 if (a != 1 && ((a ^ bestscore) & 0xffff0000) != 0) 00289 continue; 00290 plist->elements[j++] = plist->elements[i]; 00291 } 00292 if (j) 00293 plist->count = j; 00294 } 00295 00296 /* 00297 * remove entries from plist that are obsoleted by other entries 00298 * with different name. 00299 * plist should be sorted in some way. 00300 */ 00301 static void 00302 prune_obsoleted(Pool *pool, Queue *plist) 00303 { 00304 int i, j; 00305 Solvable *s; 00306 00307 /* FIXME maybe also check provides depending on noupdateprovide? */ 00308 /* FIXME do not prune cycles */ 00309 for (i = 0; i < plist->count; i++) 00310 { 00311 Id p, pp, obs, *obsp; 00312 s = pool->solvables + plist->elements[i]; 00313 if (!s->obsoletes) 00314 continue; 00315 obsp = s->repo->idarraydata + s->obsoletes; 00316 while ((obs = *obsp++) != 0) 00317 { 00318 FOR_PROVIDES(p, pp, obs) 00319 { 00320 Solvable *ps = pool->solvables + p; 00321 if (ps->name == s->name) 00322 continue; 00323 if (!pool->obsoleteusesprovides && !pool_match_nevr(pool, ps, obs)) 00324 continue; 00325 if (pool->obsoleteusescolors && !pool_colormatch(pool, s, ps)) 00326 continue; 00327 /* hmm, expensive. should use hash if plist is big */ 00328 for (j = 0; j < plist->count; j++) 00329 { 00330 if (i == j) 00331 continue; 00332 if (plist->elements[j] == p) 00333 plist->elements[j] = 0; 00334 } 00335 } 00336 } 00337 } 00338 /* delete zeroed out queue entries */ 00339 for (i = j = 0; i < plist->count; i++) 00340 if (plist->elements[i]) 00341 plist->elements[j++] = plist->elements[i]; 00342 plist->count = j; 00343 } 00344 00345 /* 00346 * prune_to_best_version 00347 * 00348 * sort list of packages (given through plist) by name and evr 00349 * return result through plist 00350 */ 00351 void 00352 prune_to_best_version(Pool *pool, Queue *plist) 00353 { 00354 int i, j; 00355 Solvable *s, *best; 00356 00357 if (plist->count < 2) /* no need to prune for a single entry */ 00358 return; 00359 POOL_DEBUG(SAT_DEBUG_POLICY, "prune_to_best_version %d\n", plist->count); 00360 00361 /* sort by name first, prefer installed */ 00362 sat_sort(plist->elements, plist->count, sizeof(Id), prune_to_best_version_sortcmp, pool); 00363 00364 /* now find best 'per name' */ 00365 best = 0; 00366 for (i = j = 0; i < plist->count; i++) 00367 { 00368 s = pool->solvables + plist->elements[i]; 00369 00370 POOL_DEBUG(SAT_DEBUG_POLICY, "- %s[%s]\n", 00371 solvable2str(pool, s), 00372 (pool->installed && s->repo == pool->installed) ? "installed" : "not installed"); 00373 00374 if (!best) /* if no best yet, the current is best */ 00375 { 00376 best = s; 00377 continue; 00378 } 00379 00380 /* name switch: finish group, re-init */ 00381 if (best->name != s->name) /* new name */ 00382 { 00383 plist->elements[j++] = best - pool->solvables; /* move old best to front */ 00384 best = s; /* take current as new best */ 00385 continue; 00386 } 00387 00388 if (best->evr != s->evr) /* compare evr */ 00389 { 00390 if (evrcmp(pool, best->evr, s->evr, EVRCMP_COMPARE) < 0) 00391 best = s; 00392 } 00393 } 00394 plist->elements[j++] = best - pool->solvables; /* finish last group */ 00395 plist->count = j; 00396 00397 /* we reduced the list to one package per name, now look at 00398 * package obsoletes */ 00399 if (plist->count > 1) 00400 prune_obsoleted(pool, plist); 00401 } 00402 00403 00404 /* legacy, do not use anymore! 00405 * (rates arch higher than version, but thats a policy) 00406 */ 00407 00408 void 00409 prune_best_arch_name_version(const Solver *solv, Pool *pool, Queue *plist) 00410 { 00411 if (solv && solv->bestSolvableCb) 00412 { /* The application is responsible for */ 00413 return solv->bestSolvableCb(solv->pool, plist); 00414 } 00415 00416 if (plist->count > 1) 00417 prune_to_best_arch(pool, plist); 00418 if (plist->count > 1) 00419 prune_to_best_version(pool, plist); 00420 } 00421 00422 /* installed packages involed in a dup operation can only be kept 00423 * if they are identical to a non-installed one */ 00424 static void 00425 prune_installed_dup_packages(Solver *solv, Queue *plist) 00426 { 00427 Pool *pool = solv->pool; 00428 int i, j, k; 00429 00430 for (i = j = 0; i < plist->count; i++) 00431 { 00432 Id p = plist->elements[i]; 00433 Solvable *s = pool->solvables + p; 00434 if (s->repo == pool->installed && (solv->dupmap_all || (solv->dupinvolvedmap.size && MAPTST(&solv->dupinvolvedmap, p)))) 00435 { 00436 for (k = 0; k < plist->count; k++) 00437 { 00438 Solvable *s2 = pool->solvables + plist->elements[k]; 00439 if (s2->repo != pool->installed && solvable_identical(s, s2)) 00440 break; 00441 } 00442 if (k == plist->count) 00443 continue; /* no identical package found, ignore installed package */ 00444 } 00445 plist->elements[j++] = p; 00446 } 00447 if (j) 00448 plist->count = j; 00449 } 00450 00451 /* 00452 * POLICY_MODE_CHOOSE: default, do all pruning steps 00453 * POLICY_MODE_RECOMMEND: leave out prune_to_recommended 00454 * POLICY_MODE_SUGGEST: leave out prune_to_recommended, do prio pruning just per name 00455 */ 00456 void 00457 policy_filter_unwanted(Solver *solv, Queue *plist, int mode) 00458 { 00459 Pool *pool = solv->pool; 00460 if (plist->count > 1) 00461 { 00462 if (mode != POLICY_MODE_SUGGEST) 00463 prune_to_highest_prio(pool, plist); 00464 else 00465 prune_to_highest_prio_per_name(pool, plist); 00466 /* installed dup packages need special treatment as prio pruning 00467 * does not prune installed packages */ 00468 if (plist->count > 1 && pool->installed && (solv->dupmap_all || solv->dupinvolvedmap.size)) 00469 prune_installed_dup_packages(solv, plist); 00470 } 00471 if (plist->count > 1 && mode == POLICY_MODE_CHOOSE) 00472 prune_to_recommended(solv, plist); 00473 prune_best_arch_name_version(solv, pool, plist); 00474 } 00475 00476 00477 int 00478 policy_illegal_archchange(Solver *solv, Solvable *s1, Solvable *s2) 00479 { 00480 Pool *pool = solv->pool; 00481 Id a1 = s1->arch, a2 = s2->arch; 00482 00483 if (solv && solv->archCheckCb) 00484 { /* The application is responsible for */ 00485 return solv->archCheckCb(solv->pool, s1, s2); 00486 } 00487 00488 /* we allow changes to/from noarch */ 00489 #ifndef DEBIAN_SEMANTICS 00490 if (a1 == a2 || a1 == ARCH_NOARCH || a2 == ARCH_NOARCH) 00491 return 0; 00492 #else 00493 if (a1 == a2 || a1 == ARCH_ALL || a2 == ARCH_ALL) 00494 return 0; 00495 #endif 00496 if (!pool->id2arch) 00497 return 0; 00498 a1 = a1 <= pool->lastarch ? pool->id2arch[a1] : 0; 00499 a2 = a2 <= pool->lastarch ? pool->id2arch[a2] : 0; 00500 if (((a1 ^ a2) & 0xffff0000) != 0) 00501 return 1; 00502 return 0; 00503 } 00504 00505 int 00506 policy_illegal_vendorchange(Solver *solv, Solvable *s1, Solvable *s2) 00507 { 00508 Pool *pool = solv->pool; 00509 Id v1, v2; 00510 Id vendormask1, vendormask2; 00511 00512 if (solv->vendorCheckCb) 00513 { /* The application is responsible for */ 00514 return solv->vendorCheckCb(pool, s1, s2); 00515 } 00516 /* treat a missing vendor as empty string */ 00517 v1 = s1->vendor ? s1->vendor : ID_EMPTY; 00518 v2 = s2->vendor ? s2->vendor : ID_EMPTY; 00519 if (v1 == v2) 00520 return 0; 00521 vendormask1 = pool_vendor2mask(pool, v1); 00522 if (!vendormask1) 00523 return 1; /* can't match */ 00524 vendormask2 = pool_vendor2mask(pool, v2); 00525 if ((vendormask1 & vendormask2) != 0) 00526 return 0; 00527 return 1; /* no class matches */ 00528 } 00529 00530 /* check if it is illegal to replace installed 00531 * package "is" with package "s" (which must obsolete "is") 00532 */ 00533 int 00534 policy_is_illegal(Solver *solv, Solvable *is, Solvable *s, int ignore) 00535 { 00536 Pool *pool = solv->pool; 00537 int ret = 0; 00538 if (!(ignore & POLICY_ILLEGAL_DOWNGRADE) && !solv->allowdowngrade) 00539 { 00540 if (is->name == s->name && evrcmp(pool, is->evr, s->evr, EVRCMP_COMPARE) > 0) 00541 ret |= POLICY_ILLEGAL_DOWNGRADE; 00542 } 00543 if (!(ignore & POLICY_ILLEGAL_ARCHCHANGE) && !solv->allowarchchange) 00544 { 00545 if (is->arch != s->arch && policy_illegal_archchange(solv, s, is)) 00546 ret |= POLICY_ILLEGAL_ARCHCHANGE; 00547 } 00548 if (!(ignore & POLICY_ILLEGAL_VENDORCHANGE) && !solv->allowvendorchange) 00549 { 00550 if (is->vendor != s->vendor && policy_illegal_vendorchange(solv, s, is)) 00551 ret |= POLICY_ILLEGAL_VENDORCHANGE; 00552 } 00553 return ret; 00554 } 00555 00556 /*------------------------------------------------------------------- 00557 * 00558 * create reverse obsoletes map for installed solvables 00559 * 00560 * For each installed solvable find which packages with *different* names 00561 * obsolete the solvable. 00562 * This index is used in policy_findupdatepackages() below. 00563 */ 00564 void 00565 policy_create_obsolete_index(Solver *solv) 00566 { 00567 Pool *pool = solv->pool; 00568 Solvable *s; 00569 Repo *installed = solv->installed; 00570 Id p, pp, obs, *obsp, *obsoletes, *obsoletes_data; 00571 int i, n, cnt; 00572 00573 if (!installed || installed->start == installed->end) 00574 return; 00575 cnt = installed->end - installed->start; 00576 solv->obsoletes = obsoletes = sat_calloc(cnt, sizeof(Id)); 00577 for (i = 1; i < pool->nsolvables; i++) 00578 { 00579 s = pool->solvables + i; 00580 if (!s->obsoletes) 00581 continue; 00582 if (!pool_installable(pool, s)) 00583 continue; 00584 obsp = s->repo->idarraydata + s->obsoletes; 00585 while ((obs = *obsp++) != 0) 00586 { 00587 FOR_PROVIDES(p, pp, obs) 00588 { 00589 Solvable *ps = pool->solvables + p;; 00590 if (ps->repo != installed) 00591 continue; 00592 if (ps->name == s->name) 00593 continue; 00594 if (!pool->obsoleteusesprovides && !pool_match_nevr(pool, ps, obs)) 00595 continue; 00596 if (pool->obsoleteusescolors && !pool_colormatch(pool, s, ps)) 00597 continue; 00598 obsoletes[p - installed->start]++; 00599 } 00600 } 00601 } 00602 n = 0; 00603 for (i = 0; i < cnt; i++) 00604 if (obsoletes[i]) 00605 { 00606 n += obsoletes[i] + 1; 00607 obsoletes[i] = n; 00608 } 00609 solv->obsoletes_data = obsoletes_data = sat_calloc(n + 1, sizeof(Id)); 00610 POOL_DEBUG(SAT_DEBUG_STATS, "obsoletes data: %d entries\n", n + 1); 00611 for (i = pool->nsolvables - 1; i > 0; i--) 00612 { 00613 s = pool->solvables + i; 00614 if (!s->obsoletes) 00615 continue; 00616 if (!pool_installable(pool, s)) 00617 continue; 00618 obsp = s->repo->idarraydata + s->obsoletes; 00619 while ((obs = *obsp++) != 0) 00620 { 00621 FOR_PROVIDES(p, pp, obs) 00622 { 00623 Solvable *ps = pool->solvables + p;; 00624 if (ps->repo != installed) 00625 continue; 00626 if (ps->name == s->name) 00627 continue; 00628 if (!pool->obsoleteusesprovides && !pool_match_nevr(pool, ps, obs)) 00629 continue; 00630 if (pool->obsoleteusescolors && !pool_colormatch(pool, s, ps)) 00631 continue; 00632 if (obsoletes_data[obsoletes[p - installed->start]] != i) 00633 obsoletes_data[--obsoletes[p - installed->start]] = i; 00634 } 00635 } 00636 } 00637 } 00638 00639 00640 /* 00641 * find update candidates 00642 * 00643 * s: solvable to be updated 00644 * qs: [out] queue to hold Ids of candidates 00645 * allow_all: 0 = dont allow downgrades, 1 = allow all candidates 00646 * 00647 */ 00648 void 00649 policy_findupdatepackages(Solver *solv, Solvable *s, Queue *qs, int allow_all) 00650 { 00651 /* installed packages get a special upgrade allowed rule */ 00652 Pool *pool = solv->pool; 00653 Id p, pp, n, p2, pp2; 00654 Id obs, *obsp; 00655 Solvable *ps; 00656 int haveprovobs = 0; 00657 00658 queue_empty(qs); 00659 00660 if (solv && solv->updateCandidateCb) 00661 { /* The application is responsible for */ 00662 return solv->updateCandidateCb(solv->pool, s, qs); 00663 } 00664 00665 /* 00666 * s = solvable ptr 00667 * n = solvable Id 00668 */ 00669 n = s - pool->solvables; 00670 00671 /* 00672 * look for updates for s 00673 */ 00674 FOR_PROVIDES(p, pp, s->name) /* every provider of s' name */ 00675 { 00676 if (p == n) /* skip itself */ 00677 continue; 00678 00679 ps = pool->solvables + p; 00680 if (s->name == ps->name) /* name match */ 00681 { 00682 if (!allow_all && !solv->allowdowngrade && evrcmp(pool, s->evr, ps->evr, EVRCMP_COMPARE) > 0) 00683 continue; 00684 } 00685 else if (!solv->noupdateprovide && ps->obsoletes) /* provides/obsoletes combination ? */ 00686 { 00687 obsp = ps->repo->idarraydata + ps->obsoletes; 00688 while ((obs = *obsp++) != 0) /* for all obsoletes */ 00689 { 00690 FOR_PROVIDES(p2, pp2, obs) /* and all matching providers of the obsoletes */ 00691 { 00692 Solvable *ps2 = pool->solvables + p2; 00693 if (!pool->obsoleteusesprovides && !pool_match_nevr(pool, ps2, obs)) 00694 continue; 00695 if (pool->obsoleteusescolors && !pool_colormatch(pool, s, ps2)) 00696 continue; 00697 if (p2 == n) /* match ! */ 00698 break; 00699 } 00700 if (p2) /* match! */ 00701 break; 00702 } 00703 if (!obs) /* continue if no match */ 00704 continue; 00705 /* here we have 'p' with a matching provides/obsoletes combination 00706 * thus flagging p as a valid update candidate for s 00707 */ 00708 haveprovobs = 1; 00709 } 00710 else 00711 continue; 00712 if (!allow_all && !solv->allowarchchange && s->arch != ps->arch && policy_illegal_archchange(solv, s, ps)) 00713 continue; 00714 if (!allow_all && !solv->allowvendorchange && s->vendor != ps->vendor && policy_illegal_vendorchange(solv, s, ps)) 00715 continue; 00716 queue_push(qs, p); 00717 } 00718 /* if we have found some valid candidates and noupdateprovide is not set, we're 00719 done. otherwise we fallback to all obsoletes */ 00720 if (!solv->noupdateprovide && haveprovobs) 00721 return; 00722 if (solv->obsoletes && solv->obsoletes[n - solv->installed->start]) 00723 { 00724 Id *opp; 00725 for (opp = solv->obsoletes_data + solv->obsoletes[n - solv->installed->start]; (p = *opp++) != 0;) 00726 { 00727 ps = pool->solvables + p; 00728 if (!allow_all && !solv->allowarchchange && s->arch != ps->arch && policy_illegal_archchange(solv, s, ps)) 00729 continue; 00730 if (!allow_all && !solv->allowvendorchange && s->vendor != ps->vendor && policy_illegal_vendorchange(solv, s, ps)) 00731 continue; 00732 queue_push(qs, p); 00733 } 00734 } 00735 } 00736