]>
Commit | Line | Data |
---|---|---|
77c11828 | 1 | /* |
0cac083d | 2 | * Copyright (c) 2007-2017, SUSE Inc. |
77c11828 MS |
3 | * |
4 | * This program is licensed under the BSD license, read LICENSE.BSD | |
5 | * for further information | |
6 | */ | |
7 | ||
8 | /* | |
9 | * rules.c | |
10 | * | |
11 | * SAT based dependency solver | |
12 | */ | |
13 | ||
14 | #include <stdio.h> | |
15 | #include <stdlib.h> | |
16 | #include <unistd.h> | |
17 | #include <string.h> | |
18 | #include <assert.h> | |
19 | ||
20 | #include "solver.h" | |
66e7a252 | 21 | #include "solver_private.h" |
77c11828 MS |
22 | #include "bitmap.h" |
23 | #include "pool.h" | |
539bae90 | 24 | #include "poolarch.h" |
77c11828 | 25 | #include "util.h" |
7a6a10a3 | 26 | #include "evr.h" |
77c11828 MS |
27 | #include "policy.h" |
28 | #include "solverdebug.h" | |
cd702d8a | 29 | #include "linkedpkg.h" |
e67081ca | 30 | #include "cplxdeps.h" |
77c11828 MS |
31 | |
32 | #define RULES_BLOCK 63 | |
33 | ||
ea3d1f2e | 34 | static void addpkgruleinfo(Solver *solv, Id p, Id p2, Id d, int type, Id dep); |
77c11828 | 35 | |
5b07accd MS |
36 | static inline int |
37 | is_otherproviders_dep(Pool *pool, Id dep) | |
38 | { | |
39 | if (ISRELDEP(dep)) | |
40 | { | |
41 | Reldep *rd = GETRELDEP(pool, dep); | |
42 | if (rd->flags == REL_NAMESPACE && rd->name == NAMESPACE_OTHERPROVIDERS) | |
43 | return 1; | |
44 | } | |
45 | return 0; | |
46 | } | |
47 | ||
77c11828 MS |
48 | /******************************************************************** |
49 | * | |
50 | * Rule handling | |
51 | * | |
52 | * - unify rules, remove duplicates | |
53 | */ | |
54 | ||
55 | /*------------------------------------------------------------------- | |
56 | * | |
57 | * compare rules for unification sort | |
58 | * | |
59 | */ | |
60 | ||
61 | static int | |
62 | unifyrules_sortcmp(const void *ap, const void *bp, void *dp) | |
63 | { | |
64 | Pool *pool = dp; | |
65 | Rule *a = (Rule *)ap; | |
66 | Rule *b = (Rule *)bp; | |
67 | Id *ad, *bd; | |
68 | int x; | |
69 | ||
70 | x = a->p - b->p; | |
71 | if (x) | |
55f5574a | 72 | return x; /* p differs */ |
77c11828 MS |
73 | |
74 | /* identical p */ | |
55f5574a MS |
75 | if (a->d == 0 && b->d == 0) /* both assertions or binary */ |
76 | return a->w2 - b->w2; | |
77c11828 | 77 | |
55f5574a | 78 | if (a->d == 0) /* a is assertion or binary, b not */ |
77c11828 MS |
79 | { |
80 | x = a->w2 - pool->whatprovidesdata[b->d]; | |
81 | return x ? x : -1; | |
82 | } | |
83 | ||
55f5574a | 84 | if (b->d == 0) /* b is assertion or binary, a not */ |
77c11828 MS |
85 | { |
86 | x = pool->whatprovidesdata[a->d] - b->w2; | |
87 | return x ? x : 1; | |
88 | } | |
89 | ||
55f5574a MS |
90 | if (a->d == b->d) |
91 | return 0; | |
92 | ||
77c11828 MS |
93 | /* compare whatprovidesdata */ |
94 | ad = pool->whatprovidesdata + a->d; | |
95 | bd = pool->whatprovidesdata + b->d; | |
96 | while (*bd) | |
97 | if ((x = *ad++ - *bd++) != 0) | |
98 | return x; | |
99 | return *ad; | |
100 | } | |
101 | ||
102 | int | |
78bc17cb | 103 | solver_rulecmp(Solver *solv, Rule *r1, Rule *r2) |
77c11828 MS |
104 | { |
105 | return unifyrules_sortcmp(r1, r2, solv->pool); | |
106 | } | |
107 | ||
108 | ||
109 | /*------------------------------------------------------------------- | |
110 | * | |
111 | * unify rules | |
112 | * go over all rules and remove duplicates | |
113 | */ | |
114 | ||
115 | void | |
116 | solver_unifyrules(Solver *solv) | |
117 | { | |
118 | Pool *pool = solv->pool; | |
119 | int i, j; | |
120 | Rule *ir, *jr; | |
121 | ||
55f5574a | 122 | if (solv->nrules <= 2) /* nothing to unify */ |
77c11828 MS |
123 | return; |
124 | ||
55f5574a MS |
125 | if (solv->recommendsruleq) |
126 | { | |
127 | /* mis-use n2 as recommends rule marker */ | |
128 | for (i = 1, ir = solv->rules + i; i < solv->nrules; i++, ir++) | |
129 | ir->n2 = 0; | |
130 | for (i = 0; i < solv->recommendsruleq->count; i++) | |
131 | solv->rules[solv->recommendsruleq->elements[i]].n2 = 1; | |
132 | } | |
133 | ||
77c11828 | 134 | /* sort rules first */ |
09f29f70 | 135 | solv_sort(solv->rules + 1, solv->nrules - 1, sizeof(Rule), unifyrules_sortcmp, solv->pool); |
77c11828 | 136 | |
55f5574a | 137 | /* prune rules */ |
77c11828 MS |
138 | jr = 0; |
139 | for (i = j = 1, ir = solv->rules + i; i < solv->nrules; i++, ir++) | |
140 | { | |
141 | if (jr && !unifyrules_sortcmp(ir, jr, pool)) | |
55f5574a MS |
142 | { |
143 | jr->n2 &= ir->n2; /* bitwise-and recommends marker */ | |
144 | continue; /* prune! */ | |
145 | } | |
146 | jr = solv->rules + j++; /* keep! */ | |
77c11828 MS |
147 | if (ir != jr) |
148 | *jr = *ir; | |
149 | } | |
150 | ||
151 | /* reduced count from nrules to j rules */ | |
09f29f70 | 152 | POOL_DEBUG(SOLV_DEBUG_STATS, "pruned rules from %d to %d\n", solv->nrules, j); |
77c11828 MS |
153 | |
154 | /* adapt rule buffer */ | |
55f5574a MS |
155 | solver_shrinkrules(solv, j); |
156 | ||
157 | if (solv->recommendsruleq) | |
158 | { | |
159 | /* rebuild recommendsruleq */ | |
160 | queue_empty(solv->recommendsruleq); | |
161 | for (i = 1, ir = solv->rules + i; i < solv->nrules; i++, ir++) | |
162 | if (ir->n2) | |
163 | { | |
164 | ir->n2 = 0; | |
165 | queue_push(solv->recommendsruleq, i); | |
166 | } | |
167 | } | |
ee15afaf MS |
168 | |
169 | /* | |
170 | * debug: log rule statistics | |
171 | */ | |
09f29f70 | 172 | IF_POOLDEBUG (SOLV_DEBUG_STATS) |
77c11828 MS |
173 | { |
174 | int binr = 0; | |
175 | int lits = 0; | |
176 | Id *dp; | |
177 | Rule *r; | |
178 | ||
179 | for (i = 1; i < solv->nrules; i++) | |
180 | { | |
181 | r = solv->rules + i; | |
182 | if (r->d == 0) | |
183 | binr++; | |
184 | else | |
185 | { | |
c4552628 | 186 | dp = pool->whatprovidesdata + r->d; |
77c11828 MS |
187 | while (*dp++) |
188 | lits++; | |
189 | } | |
190 | } | |
09f29f70 MS |
191 | POOL_DEBUG(SOLV_DEBUG_STATS, " binary: %d\n", binr); |
192 | POOL_DEBUG(SOLV_DEBUG_STATS, " normal: %d, %d literals\n", solv->nrules - 1 - binr, lits); | |
77c11828 | 193 | } |
77c11828 MS |
194 | } |
195 | ||
196 | #if 0 | |
197 | ||
198 | /* | |
199 | * hash rule | |
200 | */ | |
201 | ||
202 | static Hashval | |
203 | hashrule(Solver *solv, Id p, Id d, int n) | |
204 | { | |
205 | unsigned int x = (unsigned int)p; | |
206 | int *dp; | |
207 | ||
208 | if (n <= 1) | |
209 | return (x * 37) ^ (unsigned int)d; | |
210 | dp = solv->pool->whatprovidesdata + d; | |
211 | while (*dp) | |
212 | x = (x * 37) ^ (unsigned int)*dp++; | |
213 | return x; | |
214 | } | |
215 | #endif | |
216 | ||
217 | ||
218 | /*------------------------------------------------------------------- | |
2581c2d3 | 219 | * |
77c11828 MS |
220 | */ |
221 | ||
222 | /* | |
223 | * add rule | |
77c11828 MS |
224 | * |
225 | * A requires b, b provided by B1,B2,B3 => (-A|B1|B2|B3) | |
226 | * | |
ea3d1f2e MS |
227 | * p < 0 : pkg id of A |
228 | * d > 0 : Offset in whatprovidesdata (list of providers of b) | |
77c11828 MS |
229 | * |
230 | * A conflicts b, b provided by B1,B2,B3 => (-A|-B1), (-A|-B2), (-A|-B3) | |
ea3d1f2e MS |
231 | * p < 0 : pkg id of A |
232 | * p2 < 0 : Id of solvable (e.g. B1) | |
77c11828 | 233 | * |
ea3d1f2e | 234 | * d == 0, p2 == 0: unary rule, assertion => (A) or (-A) |
77c11828 MS |
235 | * |
236 | * Install: p > 0, d = 0 (A) user requested install | |
237 | * Remove: p < 0, d = 0 (-A) user requested remove (also: uninstallable) | |
238 | * Requires: p < 0, d > 0 (-A|B1|B2|...) d: <list of providers for requirement of p> | |
239 | * Updates: p > 0, d > 0 (A|B1|B2|...) d: <list of updates for solvable p> | |
ea3d1f2e | 240 | * Conflicts: p < 0, p2 < 0 (-A|-B) either p (conflict issuer) or d (conflict provider) (binary rule) |
77c11828 | 241 | * also used for obsoletes |
06024bfd | 242 | * No-op ?: p = 0, d = 0 (null) (used as placeholder in update/feature rules) |
77c11828 MS |
243 | * |
244 | * resulting watches: | |
245 | * ------------------ | |
8e6473a7 | 246 | * Direct assertion (no watch needed) --> d = 0, w1 = p, w2 = 0 |
77c11828 MS |
247 | * Binary rule: p = first literal, d = 0, w2 = second literal, w1 = p |
248 | * every other : w1 = p, w2 = whatprovidesdata[d]; | |
77c11828 | 249 | * |
2b48a178 | 250 | * always returns a rule for non-pkg rules |
77c11828 MS |
251 | */ |
252 | ||
253 | Rule * | |
ea3d1f2e | 254 | solver_addrule(Solver *solv, Id p, Id p2, Id d) |
77c11828 MS |
255 | { |
256 | Pool *pool = solv->pool; | |
b0dda2ba | 257 | Rule *r; |
ea3d1f2e MS |
258 | |
259 | if (d) | |
77c11828 | 260 | { |
ea3d1f2e MS |
261 | assert(!p2 && d > 0); |
262 | if (!pool->whatprovidesdata[d]) | |
263 | d = 0; | |
264 | else if (!pool->whatprovidesdata[d + 1]) | |
b0dda2ba | 265 | { |
ea3d1f2e MS |
266 | p2 = pool->whatprovidesdata[d]; |
267 | d = 0; | |
b0dda2ba | 268 | } |
77c11828 MS |
269 | } |
270 | ||
ea3d1f2e MS |
271 | /* now we have two cases: |
272 | * 1 or 2 literals: d = 0, p, p2 contain the literals | |
273 | * 3 or more literals: d > 0, p2 == 0, d is offset into whatprovidesdata | |
274 | */ | |
b0dda2ba MS |
275 | |
276 | /* it often happenes that requires lead to adding the same pkg rule | |
277 | * multiple times, so we prune those duplicates right away to make | |
278 | * the work for unifyrules a bit easier */ | |
279 | if (!solv->pkgrules_end) /* we add pkg rules */ | |
77c11828 | 280 | { |
55f5574a | 281 | r = solv->rules + solv->lastpkgrule; |
ea3d1f2e | 282 | if (d) |
06024bfd | 283 | { |
ea3d1f2e MS |
284 | Id *dp; |
285 | /* check if rule is identical */ | |
286 | if (r->p == p) | |
287 | { | |
288 | Id *dp2; | |
289 | if (r->d == d) | |
290 | return r; | |
291 | dp2 = pool->whatprovidesdata + r->d; | |
292 | for (dp = pool->whatprovidesdata + d; *dp; dp++, dp2++) | |
293 | if (*dp != *dp2) | |
294 | break; | |
295 | if (*dp == *dp2) | |
296 | return r; | |
297 | } | |
298 | /* check if rule is self-fulfilling */ | |
299 | for (dp = pool->whatprovidesdata + d; *dp; dp++) | |
300 | if (*dp == -p) | |
301 | return 0; /* rule is self-fulfilling */ | |
302 | } | |
303 | else | |
304 | { | |
305 | if (p2 && p > p2) | |
306 | { | |
307 | Id o = p; /* switch p1 and p2 */ | |
308 | p = p2; | |
309 | p2 = o; | |
310 | } | |
311 | if (r->p == p && !r->d && r->w2 == p2) | |
06024bfd | 312 | return r; |
ea3d1f2e MS |
313 | if (p == -p2) |
314 | return 0; /* rule is self-fulfilling */ | |
06024bfd | 315 | } |
55f5574a | 316 | solv->lastpkgrule = solv->nrules; |
06024bfd | 317 | } |
77c11828 | 318 | |
09f29f70 | 319 | solv->rules = solv_extend(solv->rules, solv->nrules, 1, sizeof(Rule), RULES_BLOCK); |
77c11828 | 320 | r = solv->rules + solv->nrules++; /* point to rule space */ |
77c11828 | 321 | r->p = p; |
b0dda2ba MS |
322 | r->d = d; |
323 | r->w1 = p; | |
ea3d1f2e | 324 | r->w2 = d ? pool->whatprovidesdata[d] : p2; |
77c11828 MS |
325 | r->n1 = 0; |
326 | r->n2 = 0; | |
09f29f70 | 327 | IF_POOLDEBUG (SOLV_DEBUG_RULE_CREATION) |
77c11828 | 328 | { |
09f29f70 MS |
329 | POOL_DEBUG(SOLV_DEBUG_RULE_CREATION, " Add rule: "); |
330 | solver_printrule(solv, SOLV_DEBUG_RULE_CREATION, r); | |
77c11828 | 331 | } |
77c11828 MS |
332 | return r; |
333 | } | |
334 | ||
ea3d1f2e | 335 | |
41c5eb1c MS |
336 | void |
337 | solver_shrinkrules(Solver *solv, int nrules) | |
338 | { | |
339 | solv->nrules = nrules; | |
340 | solv->rules = solv_extend_resize(solv->rules, solv->nrules, sizeof(Rule), RULES_BLOCK); | |
55f5574a | 341 | solv->lastpkgrule = 0; |
41c5eb1c | 342 | } |
77c11828 | 343 | |
ee15afaf MS |
344 | /****************************************************************************** |
345 | *** | |
2b48a178 | 346 | *** pkg rule part: create rules representing the package dependencies |
ee15afaf MS |
347 | *** |
348 | ***/ | |
77c11828 MS |
349 | |
350 | /* | |
351 | * special multiversion patch conflict handling: | |
395b1102 | 352 | * a patch conflict is also satisfied if some other |
77c11828 | 353 | * version with the same name/arch that doesn't conflict |
395b1102 | 354 | * gets installed. The generated rule is thus: |
77c11828 MS |
355 | * -patch|-cpack|opack1|opack2|... |
356 | */ | |
357 | static Id | |
358 | makemultiversionconflict(Solver *solv, Id n, Id con) | |
359 | { | |
360 | Pool *pool = solv->pool; | |
361 | Solvable *s, *sn; | |
362 | Queue q; | |
363 | Id p, pp, qbuf[64]; | |
364 | ||
365 | sn = pool->solvables + n; | |
366 | queue_init_buffer(&q, qbuf, sizeof(qbuf)/sizeof(*qbuf)); | |
367 | queue_push(&q, -n); | |
368 | FOR_PROVIDES(p, pp, sn->name) | |
369 | { | |
370 | s = pool->solvables + p; | |
371 | if (s->name != sn->name || s->arch != sn->arch) | |
372 | continue; | |
646a92ed | 373 | if (!MAPTST(&solv->multiversion, p)) |
77c11828 MS |
374 | continue; |
375 | if (pool_match_nevr(pool, pool->solvables + p, con)) | |
376 | continue; | |
377 | /* here we have a multiversion solvable that doesn't conflict */ | |
378 | /* thus we're not in conflict if it is installed */ | |
379 | queue_push(&q, p); | |
380 | } | |
381 | if (q.count == 1) | |
b0dda2ba | 382 | n = 0; /* no other package found, normal conflict handling */ |
4ffaa58a MS |
383 | else |
384 | n = pool_queuetowhatprovides(pool, &q); | |
385 | queue_free(&q); | |
386 | return n; | |
77c11828 MS |
387 | } |
388 | ||
389 | static inline void | |
ea3d1f2e | 390 | addpkgrule(Solver *solv, Id p, Id p2, Id d, int type, Id dep) |
b0dda2ba MS |
391 | { |
392 | if (!solv->ruleinfoq) | |
ea3d1f2e | 393 | solver_addrule(solv, p, p2, d); |
b0dda2ba | 394 | else |
ea3d1f2e | 395 | addpkgruleinfo(solv, p, p2, d, type, dep); |
77c11828 MS |
396 | } |
397 | ||
e5fff4bc MS |
398 | #ifdef ENABLE_LINKED_PKGS |
399 | ||
a2a85109 MS |
400 | static int |
401 | addlinks_cmp(const void *ap, const void *bp, void *dp) | |
402 | { | |
403 | Pool *pool = dp; | |
404 | Id a = *(Id *)ap; | |
405 | Id b = *(Id *)bp; | |
406 | Solvable *sa = pool->solvables + a; | |
407 | Solvable *sb = pool->solvables + b; | |
408 | if (sa->name != sb->name) | |
409 | return sa->name - sb->name; | |
410 | return sa - sb; | |
411 | } | |
412 | ||
f09c993f MS |
413 | static void |
414 | addlinks(Solver *solv, Solvable *s, Id req, Queue *qr, Id prv, Queue *qp, Map *m, Queue *workq) | |
415 | { | |
416 | Pool *pool = solv->pool; | |
417 | int i; | |
418 | if (!qr->count) | |
419 | return; | |
a2a85109 MS |
420 | if (qp->count > 1) |
421 | solv_sort(qp->elements, qp->count, sizeof(Id), addlinks_cmp, pool); | |
f09c993f MS |
422 | #if 0 |
423 | printf("ADDLINKS %s\n -> %s\n", pool_solvable2str(pool, s), pool_dep2str(pool, req)); | |
424 | for (i = 0; i < qr->count; i++) | |
425 | printf(" - %s\n", pool_solvid2str(pool, qr->elements[i])); | |
426 | printf(" <- %s\n", pool_dep2str(pool, prv)); | |
427 | for (i = 0; i < qp->count; i++) | |
428 | printf(" - %s\n", pool_solvid2str(pool, qp->elements[i])); | |
429 | #endif | |
430 | ||
431 | if (qr->count == 1) | |
ea3d1f2e | 432 | addpkgrule(solv, -(s - pool->solvables), qr->elements[0], 0, SOLVER_RULE_PKG_REQUIRES, req); |
f09c993f | 433 | else |
ea3d1f2e | 434 | addpkgrule(solv, -(s - pool->solvables), 0, pool_queuetowhatprovides(pool, qr), SOLVER_RULE_PKG_REQUIRES, req); |
f09c993f MS |
435 | if (qp->count > 1) |
436 | { | |
a2a85109 MS |
437 | int j; |
438 | for (i = j = 0; i < qp->count; i = j) | |
439 | { | |
440 | Id d = pool->solvables[qp->elements[i]].name; | |
441 | for (j = i + 1; j < qp->count; j++) | |
442 | if (d != pool->solvables[qp->elements[j]].name) | |
443 | break; | |
444 | d = pool_ids2whatprovides(pool, qp->elements + i, j - i); | |
445 | for (i = 0; i < qr->count; i++) | |
446 | addpkgrule(solv, -qr->elements[i], 0, d, SOLVER_RULE_PKG_REQUIRES, prv); | |
447 | } | |
f09c993f MS |
448 | } |
449 | else if (qp->count) | |
450 | { | |
451 | for (i = 0; i < qr->count; i++) | |
ea3d1f2e | 452 | addpkgrule(solv, -qr->elements[i], qp->elements[0], 0, SOLVER_RULE_PKG_REQUIRES, prv); |
f09c993f MS |
453 | } |
454 | if (!m) | |
2b48a178 | 455 | return; /* nothing more to do if called from getpkgruleinfos() */ |
f09c993f | 456 | for (i = 0; i < qr->count; i++) |
1fe6dc5d | 457 | if (!MAPTST(m, qr->elements[i])) |
f09c993f MS |
458 | queue_push(workq, qr->elements[i]); |
459 | for (i = 0; i < qp->count; i++) | |
1fe6dc5d | 460 | if (!MAPTST(m, qp->elements[i])) |
f09c993f MS |
461 | queue_push(workq, qp->elements[i]); |
462 | if (solv->installed && s->repo == solv->installed) | |
463 | { | |
464 | Repo *installed = solv->installed; | |
465 | /* record installed buddies */ | |
466 | if (!solv->instbuddy) | |
467 | solv->instbuddy = solv_calloc(installed->end - installed->start, sizeof(Id)); | |
468 | if (qr->count == 1) | |
469 | solv->instbuddy[s - pool->solvables - installed->start] = qr->elements[0]; | |
c50b6829 | 470 | for (i = 0; i < qr->count; i++) |
f09c993f | 471 | { |
c50b6829 | 472 | Id p = qr->elements[i]; |
f09c993f MS |
473 | if (pool->solvables[p].repo != installed) |
474 | continue; /* huh? */ | |
475 | if (qp->count > 1 || (solv->instbuddy[p - installed->start] != 0 && solv->instbuddy[p - installed->start] != s - pool->solvables)) | |
476 | solv->instbuddy[p - installed->start] = 1; /* 1: ambiguous buddy */ | |
477 | else | |
478 | solv->instbuddy[p - installed->start] = s - pool->solvables; | |
479 | } | |
480 | } | |
481 | } | |
482 | ||
483 | static void | |
cd702d8a | 484 | add_package_link(Solver *solv, Solvable *s, Map *m, Queue *workq) |
f09c993f | 485 | { |
f09c993f | 486 | Queue qr, qp; |
cd702d8a | 487 | Id req = 0, prv = 0; |
f09c993f MS |
488 | queue_init(&qr); |
489 | queue_init(&qp); | |
cd702d8a MS |
490 | find_package_link(solv->pool, s, &req, &qr, &prv, &qp); |
491 | if (qr.count) | |
492 | addlinks(solv, s, req, &qr, prv, &qp, m, workq); | |
f09c993f MS |
493 | queue_free(&qr); |
494 | queue_free(&qp); | |
495 | } | |
496 | ||
e5fff4bc MS |
497 | #endif |
498 | ||
e67081ca MS |
499 | #ifdef ENABLE_COMPLEX_DEPS |
500 | ||
b8c3b209 MS |
501 | #ifdef SUSE |
502 | static inline int | |
503 | suse_isptf(Pool *pool, Solvable *s) | |
504 | { | |
505 | if (!strncmp("ptf-", pool_id2str(pool, s->name), 4)) | |
506 | return 1; | |
507 | return 0; | |
508 | } | |
509 | #endif | |
510 | ||
e67081ca MS |
511 | static void |
512 | add_complex_deprules(Solver *solv, Id p, Id dep, int type, int dontfix, Queue *workq, Map *m) | |
513 | { | |
514 | Pool *pool = solv->pool; | |
515 | Repo *installed = solv->installed; | |
1eb60cf9 | 516 | int i, j, flags; |
e67081ca MS |
517 | Queue bq; |
518 | ||
519 | queue_init(&bq); | |
1eb60cf9 | 520 | flags = dontfix ? CPLXDEPS_DONTFIX : 0; |
e67081ca | 521 | /* CNF expansion for requires, DNF + INVERT expansion for conflicts */ |
1eb60cf9 MS |
522 | if (type == SOLVER_RULE_PKG_CONFLICTS) |
523 | flags |= CPLXDEPS_TODNF | CPLXDEPS_EXPAND | CPLXDEPS_INVERT; | |
b8c3b209 MS |
524 | #ifdef SUSE |
525 | if (type == SOLVER_RULE_PKG_REQUIRES && suse_isptf(pool, pool->solvables + p)) | |
526 | flags |= CPLXDEPS_NAME; /* do not match provides */ | |
527 | #endif | |
1eb60cf9 MS |
528 | |
529 | i = pool_normalize_complex_dep(pool, dep, &bq, flags); | |
e67081ca MS |
530 | /* handle special cases */ |
531 | if (i == 0) | |
532 | { | |
533 | if (dontfix) | |
534 | { | |
535 | POOL_DEBUG(SOLV_DEBUG_RULE_CREATION, "ignoring broken dependency %s of installed package %s\n", pool_dep2str(pool, dep), pool_solvid2str(pool, p)); | |
536 | } | |
537 | else | |
538 | { | |
539 | POOL_DEBUG(SOLV_DEBUG_RULE_CREATION, "package %s [%d] is not installable (%s)\n", pool_solvid2str(pool, p), p, pool_dep2str(pool, dep)); | |
ea3d1f2e | 540 | addpkgrule(solv, -p, 0, 0, type == SOLVER_RULE_PKG_REQUIRES ? SOLVER_RULE_PKG_NOTHING_PROVIDES_DEP : type, dep); |
e67081ca MS |
541 | } |
542 | queue_free(&bq); | |
543 | return; | |
544 | } | |
545 | if (i == 1) | |
546 | { | |
547 | queue_free(&bq); | |
548 | return; | |
549 | } | |
550 | ||
551 | /* go through all blocks and add a rule for each block */ | |
552 | for (i = 0; i < bq.count; i++) | |
553 | { | |
554 | if (!bq.elements[i]) | |
555 | continue; /* huh? */ | |
556 | if (bq.elements[i] == pool->nsolvables) | |
557 | { | |
558 | /* conventional requires (cannot be a conflicts as they have been expanded) */ | |
559 | Id *dp = pool->whatprovidesdata + bq.elements[i + 1]; | |
560 | i += 2; | |
561 | if (dontfix) | |
562 | { | |
563 | for (j = 0; dp[j] != 0; j++) | |
564 | if (pool->solvables[dp[j]].repo == installed) | |
565 | break; /* provider was installed */ | |
566 | if (!dp[j]) | |
f80abd37 | 567 | continue; |
e67081ca | 568 | } |
55f5574a MS |
569 | if (type == SOLVER_RULE_PKG_RECOMMENDS && !*dp) |
570 | continue; | |
f80abd37 MS |
571 | /* check if the rule contains both p and -p */ |
572 | for (j = 0; dp[j] != 0; j++) | |
573 | if (dp[j] == p) | |
574 | break; | |
575 | if (dp[j]) | |
576 | continue; | |
55f5574a | 577 | addpkgrule(solv, -p, 0, dp - pool->whatprovidesdata, type, dep); |
e67081ca MS |
578 | /* push all non-visited providers on the work queue */ |
579 | if (m) | |
580 | for (; *dp; dp++) | |
581 | if (!MAPTST(m, *dp)) | |
582 | queue_push(workq, *dp); | |
583 | continue; | |
584 | } | |
585 | if (!bq.elements[i + 1]) | |
586 | { | |
f80abd37 MS |
587 | Id p2 = bq.elements[i++]; |
588 | /* simple rule with just two literals, we'll add a (-p, p2) rule */ | |
589 | if (dontfix) | |
590 | { | |
591 | if (p2 < 0 && pool->solvables[-p2].repo == installed) | |
592 | continue; | |
593 | if (p2 > 0 && pool->solvables[p2].repo != installed) | |
594 | continue; | |
595 | } | |
e67081ca MS |
596 | if (-p == p2) |
597 | { | |
2b48a178 | 598 | if (type == SOLVER_RULE_PKG_CONFLICTS) |
e67081ca MS |
599 | { |
600 | if (pool->forbidselfconflicts && !is_otherproviders_dep(pool, dep)) | |
ea3d1f2e | 601 | addpkgrule(solv, -p, 0, 0, SOLVER_RULE_PKG_SELF_CONFLICT, dep); |
e67081ca MS |
602 | continue; |
603 | } | |
ea3d1f2e | 604 | addpkgrule(solv, -p, 0, 0, type, dep); |
e67081ca MS |
605 | continue; |
606 | } | |
f80abd37 MS |
607 | /* check if the rule contains both p and -p */ |
608 | if (p == p2) | |
609 | continue; | |
ea3d1f2e | 610 | addpkgrule(solv, -p, p2, 0, type, dep); |
e67081ca MS |
611 | if (m && p2 > 0 && !MAPTST(m, p2)) |
612 | queue_push(workq, p2); | |
613 | } | |
614 | else | |
615 | { | |
98446739 | 616 | Id *qele, d; |
e67081ca MS |
617 | int qcnt; |
618 | ||
619 | qele = bq.elements + i; | |
620 | qcnt = i; | |
621 | while (bq.elements[i]) | |
622 | i++; | |
623 | qcnt = i - qcnt; | |
624 | if (dontfix) | |
625 | { | |
626 | for (j = 0; j < qcnt; j++) | |
627 | { | |
628 | if (qele[j] > 0 && pool->solvables[qele[j]].repo == installed) | |
629 | break; | |
630 | if (qele[j] < 0 && pool->solvables[-qele[j]].repo != installed) | |
631 | break; | |
632 | } | |
633 | if (j == qcnt) | |
634 | continue; | |
635 | } | |
636 | /* add -p to (ordered) rule (overwriting the trailing zero) */ | |
637 | for (j = 0; ; j++) | |
638 | { | |
639 | if (j == qcnt || qele[j] > -p) | |
640 | { | |
641 | if (j < qcnt) | |
642 | memmove(qele + j + 1, qele + j, (qcnt - j) * sizeof(Id)); | |
643 | qele[j] = -p; | |
644 | qcnt++; | |
645 | break; | |
646 | } | |
647 | if (qele[j] == -p) | |
648 | break; | |
649 | } | |
650 | /* check if the rule contains both p and -p */ | |
651 | for (j = 0; j < qcnt; j++) | |
652 | if (qele[j] == p) | |
653 | break; | |
f80abd37 MS |
654 | if (j < qcnt) |
655 | continue; | |
98446739 MS |
656 | d = pool_ids2whatprovides(pool, qele + 1, qcnt - 1); |
657 | if (solv->ruleinfoq && qele[0] != p) | |
658 | { | |
659 | int oldcount = solv->ruleinfoq->count; | |
660 | addpkgrule(solv, qele[0], 0, d, type, dep); | |
661 | /* fixup from element of ruleinfo */ | |
c6c3088d MS |
662 | if (solv->ruleinfoq->count > oldcount && solv->ruleinfoq->elements[oldcount + 1] != p) |
663 | { | |
664 | if (solv->ruleinfoq->elements[oldcount + 2]) | |
665 | solv->ruleinfoq->elements[oldcount + 2] = solv->ruleinfoq->elements[oldcount + 1]; | |
666 | solv->ruleinfoq->elements[oldcount + 1] = p; | |
667 | } | |
98446739 MS |
668 | } |
669 | else | |
670 | addpkgrule(solv, qele[0], 0, d, type, dep); | |
f80abd37 MS |
671 | if (m) |
672 | for (j = 0; j < qcnt; j++) | |
673 | if (qele[j] > 0 && !MAPTST(m, qele[j])) | |
674 | queue_push(workq, qele[j]); | |
e67081ca MS |
675 | } |
676 | } | |
677 | queue_free(&bq); | |
678 | } | |
679 | ||
680 | #endif | |
681 | ||
6adcbee1 MS |
682 | #ifdef ENABLE_CONDA |
683 | void | |
3f5e35a1 | 684 | add_conda_constrains_rule(Solver *solv, Id n, Id dep, int dontfix) |
6adcbee1 MS |
685 | { |
686 | Pool *pool = solv->pool; | |
687 | Reldep *rd; | |
688 | Id p, pp, pdep; | |
689 | if (!ISRELDEP(dep)) | |
690 | return; | |
691 | rd = GETRELDEP(pool, dep); | |
692 | pdep = pool_whatprovides(pool, dep); | |
693 | FOR_PROVIDES(p, pp, rd->name) | |
694 | { | |
695 | Id p2; | |
8f3aed5f MS |
696 | if (p == n) |
697 | continue; | |
3f5e35a1 MS |
698 | if (dontfix && pool->solvables[p].repo == solv->installed) |
699 | continue; | |
6adcbee1 MS |
700 | while ((p2 = pool->whatprovidesdata[pdep]) != 0 && p2 < p) |
701 | pdep++; | |
702 | if (p == p2) | |
703 | pdep++; | |
704 | else | |
705 | addpkgrule(solv, -n, -p, 0, SOLVER_RULE_PKG_CONSTRAINS, dep); | |
706 | } | |
707 | } | |
708 | #endif | |
709 | ||
77c11828 | 710 | /*------------------------------------------------------------------- |
2581c2d3 | 711 | * |
6afc1750 | 712 | * add dependency rules for solvable |
2581c2d3 | 713 | * |
77c11828 MS |
714 | * s: Solvable for which to add rules |
715 | * m: m[s] = 1 for solvables which have rules, prevent rule duplication | |
2581c2d3 | 716 | * |
77c11828 MS |
717 | * Algorithm: 'visit all nodes of a graph'. The graph nodes are |
718 | * solvables, the edges their dependencies. | |
719 | * Starting from an installed solvable, this will create all rules | |
720 | * representing the graph created by the solvables dependencies. | |
2581c2d3 | 721 | * |
77c11828 MS |
722 | * for unfulfilled requirements, conflicts, obsoletes,.... |
723 | * add a negative assertion for solvables that are not installable | |
2581c2d3 | 724 | * |
77c11828 MS |
725 | * It will also create rules for all solvables referenced by 's' |
726 | * i.e. descend to all providers of requirements of 's' | |
727 | * | |
728 | */ | |
729 | ||
730 | void | |
2b48a178 | 731 | solver_addpkgrulesforsolvable(Solver *solv, Solvable *s, Map *m) |
77c11828 MS |
732 | { |
733 | Pool *pool = solv->pool; | |
734 | Repo *installed = solv->installed; | |
735 | ||
5b07accd | 736 | Queue workq; /* list of solvables we still have to work on */ |
77c11828 | 737 | Id workqbuf[64]; |
6b414e99 MS |
738 | Queue depq; /* list of pre-req ids to ignore */ |
739 | Id depqbuf[16]; | |
2581c2d3 | 740 | |
77c11828 | 741 | int i; |
5b07accd | 742 | int dontfix; /* ignore dependency errors for installed solvables */ |
77c11828 MS |
743 | Id req, *reqp; |
744 | Id con, *conp; | |
745 | Id obs, *obsp; | |
746 | Id rec, *recp; | |
747 | Id sug, *sugp; | |
748 | Id p, pp; /* whatprovides loops */ | |
749 | Id *dp; /* ptr to 'whatprovides' */ | |
750 | Id n; /* Id for current solvable 's' */ | |
751 | ||
77c11828 MS |
752 | queue_init_buffer(&workq, workqbuf, sizeof(workqbuf)/sizeof(*workqbuf)); |
753 | queue_push(&workq, s - pool->solvables); /* push solvable Id to work queue */ | |
754 | ||
6b414e99 | 755 | queue_init_buffer(&depq, depqbuf, sizeof(depqbuf)/sizeof(*depqbuf)); |
6afc1750 | 756 | |
77c11828 MS |
757 | /* loop until there's no more work left */ |
758 | while (workq.count) | |
759 | { | |
760 | /* | |
761 | * n: Id of solvable | |
762 | * s: Pointer to solvable | |
763 | */ | |
764 | ||
765 | n = queue_shift(&workq); /* 'pop' next solvable to work on from queue */ | |
766 | if (m) | |
767 | { | |
768 | if (MAPTST(m, n)) /* continue if already visited */ | |
769 | continue; | |
770 | MAPSET(m, n); /* mark as visited */ | |
771 | } | |
772 | ||
5b07accd | 773 | s = pool->solvables + n; |
77c11828 MS |
774 | |
775 | dontfix = 0; | |
776 | if (installed /* Installed system available */ | |
0686141a | 777 | && s->repo == installed /* solvable is installed */ |
2b48a178 | 778 | && !solv->fixmap_all /* NOT repair errors in dependency graph */ |
bd9afae6 | 779 | && !(solv->fixmap.size && MAPTST(&solv->fixmap, n - installed->start))) |
77c11828 | 780 | { |
2b48a178 | 781 | dontfix = 1; /* dont care about broken deps */ |
77c11828 MS |
782 | } |
783 | ||
1e554802 | 784 | if (!dontfix) |
77c11828 | 785 | { |
1e554802 | 786 | if (s->arch == ARCH_SRC || s->arch == ARCH_NOSRC |
2581c2d3 | 787 | ? pool_disabled_solvable(pool, s) |
1e554802 MS |
788 | : !pool_installable(pool, s)) |
789 | { | |
5b07accd | 790 | POOL_DEBUG(SOLV_DEBUG_RULE_CREATION, "package %s [%d] is not installable\n", pool_solvid2str(pool, n), n); |
ea3d1f2e | 791 | addpkgrule(solv, -n, 0, 0, SOLVER_RULE_PKG_NOT_INSTALLABLE, 0); |
1e554802 | 792 | } |
77c11828 MS |
793 | } |
794 | ||
e5fff4bc | 795 | #ifdef ENABLE_LINKED_PKGS |
f09c993f | 796 | /* add pseudo-package <-> real-package links */ |
cd702d8a MS |
797 | if (has_package_link(pool, s)) |
798 | add_package_link(solv, s, m, &workq); | |
e5fff4bc | 799 | #endif |
77c11828 MS |
800 | |
801 | /*----------------------------------------- | |
802 | * check requires of s | |
803 | */ | |
804 | ||
805 | if (s->requires) | |
806 | { | |
6afc1750 | 807 | int filterpre = 0; |
77c11828 MS |
808 | reqp = s->repo->idarraydata + s->requires; |
809 | while ((req = *reqp++) != 0) /* go through all requires */ | |
810 | { | |
811 | if (req == SOLVABLE_PREREQMARKER) /* skip the marker */ | |
6afc1750 MS |
812 | { |
813 | if (installed && s->repo == installed) | |
814 | { | |
6b414e99 MS |
815 | solvable_lookup_idarray(s, SOLVABLE_PREREQ_IGNOREINST, &depq); |
816 | filterpre = depq.count; | |
6afc1750 MS |
817 | } |
818 | continue; | |
819 | } | |
820 | if (filterpre) | |
821 | { | |
6b414e99 MS |
822 | /* check if this id is filtered. assumes that depq.count is small */ |
823 | for (i = 0; i < depq.count; i++) | |
824 | if (req == depq.elements[i]) | |
6afc1750 | 825 | break; |
6b414e99 | 826 | if (i < depq.count) |
6afc1750 MS |
827 | { |
828 | POOL_DEBUG(SOLV_DEBUG_RULE_CREATION, "package %s: ignoring filtered pre-req dependency %s\n", pool_solvable2str(pool, s), pool_dep2str(pool, req)); | |
829 | continue; | |
830 | } | |
831 | } | |
77c11828 | 832 | |
e67081ca MS |
833 | #ifdef ENABLE_COMPLEX_DEPS |
834 | if (pool_is_complex_dep(pool, req)) | |
835 | { | |
836 | /* we have AND/COND deps, normalize */ | |
2b48a178 | 837 | add_complex_deprules(solv, n, req, SOLVER_RULE_PKG_REQUIRES, dontfix, &workq, m); |
e67081ca MS |
838 | continue; |
839 | } | |
840 | #endif | |
841 | ||
77c11828 MS |
842 | /* find list of solvables providing 'req' */ |
843 | dp = pool_whatprovides_ptr(pool, req); | |
844 | ||
845 | if (*dp == SYSTEMSOLVABLE) /* always installed */ | |
846 | continue; | |
847 | ||
848 | if (dontfix) | |
849 | { | |
850 | /* the strategy here is to not insist on dependencies | |
851 | * that are already broken. so if we find one provider | |
852 | * that was already installed, we know that the | |
853 | * dependency was not broken before so we enforce it */ | |
77c11828 | 854 | for (i = 0; (p = dp[i]) != 0; i++) |
5b07accd MS |
855 | if (pool->solvables[p].repo == installed) |
856 | break; /* found installed provider */ | |
77c11828 MS |
857 | if (!p) |
858 | { | |
5b07accd | 859 | /* didn't find an installed provider: previously broken dependency */ |
09f29f70 | 860 | POOL_DEBUG(SOLV_DEBUG_RULE_CREATION, "ignoring broken requires %s of installed package %s\n", pool_dep2str(pool, req), pool_solvable2str(pool, s)); |
77c11828 MS |
861 | continue; |
862 | } | |
863 | } | |
864 | ||
865 | if (!*dp) | |
866 | { | |
5b07accd | 867 | POOL_DEBUG(SOLV_DEBUG_RULE_CREATION, "package %s [%d] is not installable (%s)\n", pool_solvid2str(pool, n), n, pool_dep2str(pool, req)); |
ea3d1f2e | 868 | addpkgrule(solv, -n, 0, 0, SOLVER_RULE_PKG_NOTHING_PROVIDES_DEP, req); |
77c11828 MS |
869 | continue; |
870 | } | |
871 | ||
f80abd37 MS |
872 | for (i = 0; dp[i] != 0; i++) |
873 | if (n == dp[i]) | |
874 | break; | |
875 | if (dp[i]) | |
876 | continue; /* provided by itself, no need to add rule */ | |
877 | ||
09f29f70 | 878 | IF_POOLDEBUG (SOLV_DEBUG_RULE_CREATION) |
77c11828 | 879 | { |
09f29f70 | 880 | POOL_DEBUG(SOLV_DEBUG_RULE_CREATION," %s requires %s\n", pool_solvable2str(pool, s), pool_dep2str(pool, req)); |
77c11828 | 881 | for (i = 0; dp[i]; i++) |
09f29f70 | 882 | POOL_DEBUG(SOLV_DEBUG_RULE_CREATION, " provided by %s\n", pool_solvid2str(pool, dp[i])); |
77c11828 MS |
883 | } |
884 | ||
885 | /* add 'requires' dependency */ | |
886 | /* rule: (-requestor|provider1|provider2|...|providerN) */ | |
ea3d1f2e | 887 | addpkgrule(solv, -n, 0, dp - pool->whatprovidesdata, SOLVER_RULE_PKG_REQUIRES, req); |
77c11828 | 888 | |
5b07accd | 889 | /* push all non-visited providers on the work queue */ |
77c11828 | 890 | if (m) |
5b07accd MS |
891 | for (; *dp; dp++) |
892 | if (!MAPTST(m, *dp)) | |
893 | queue_push(&workq, *dp); | |
894 | } | |
895 | } | |
77c11828 | 896 | |
55f5574a MS |
897 | if (s->recommends && solv->strongrecommends) |
898 | { | |
899 | int start = solv->nrules; | |
900 | solv->lastpkgrule = 0; | |
901 | reqp = s->repo->idarraydata + s->recommends; | |
902 | while ((req = *reqp++) != 0) /* go through all recommends */ | |
903 | { | |
904 | #ifdef ENABLE_COMPLEX_DEPS | |
905 | if (pool_is_complex_dep(pool, req)) | |
906 | { | |
907 | /* we have AND/COND deps, normalize */ | |
908 | add_complex_deprules(solv, n, req, SOLVER_RULE_PKG_RECOMMENDS, dontfix, &workq, m); | |
909 | continue; | |
910 | } | |
911 | #endif | |
912 | dp = pool_whatprovides_ptr(pool, req); | |
913 | if (*dp == SYSTEMSOLVABLE || !*dp) /* always installed or not installable */ | |
914 | continue; | |
915 | for (i = 0; dp[i] != 0; i++) | |
916 | if (n == dp[i]) | |
917 | break; | |
918 | if (dp[i]) | |
919 | continue; /* provided by itself, no need to add rule */ | |
920 | addpkgrule(solv, -n, 0, dp - pool->whatprovidesdata, SOLVER_RULE_PKG_RECOMMENDS, req); | |
921 | if (m) | |
922 | for (; *dp; dp++) | |
923 | if (!MAPTST(m, *dp)) | |
924 | queue_push(&workq, *dp); | |
925 | } | |
926 | if (!solv->ruleinfoq && start < solv->nrules) | |
927 | { | |
928 | if (!solv->recommendsruleq) | |
929 | { | |
930 | solv->recommendsruleq = solv_calloc(1, sizeof(Queue)); | |
931 | queue_init(solv->recommendsruleq); | |
932 | } | |
933 | for (i = start; i < solv->nrules; i++) | |
934 | queue_push(solv->recommendsruleq, i); | |
935 | solv->lastpkgrule = 0; | |
936 | } | |
937 | } | |
938 | ||
6adcbee1 MS |
939 | #ifdef ENABLE_CONDA |
940 | if (pool->disttype == DISTTYPE_CONDA) | |
941 | { | |
6b414e99 MS |
942 | solvable_lookup_idarray(s, SOLVABLE_CONSTRAINS, &depq); |
943 | for (i = 0; i < depq.count; i++) | |
3f5e35a1 | 944 | add_conda_constrains_rule(solv, n, depq.elements[i], dontfix); |
6adcbee1 MS |
945 | } |
946 | #endif | |
947 | ||
77c11828 MS |
948 | /* that's all we check for src packages */ |
949 | if (s->arch == ARCH_SRC || s->arch == ARCH_NOSRC) | |
950 | continue; | |
951 | ||
952 | /*----------------------------------------- | |
953 | * check conflicts of s | |
954 | */ | |
955 | ||
956 | if (s->conflicts) | |
957 | { | |
958 | int ispatch = 0; | |
959 | ||
960 | /* we treat conflicts in patches a bit differen: | |
961 | * - nevr matching | |
962 | * - multiversion handling | |
963 | * XXX: we should really handle this different, looking | |
964 | * at the name is a bad hack | |
965 | */ | |
e2a47f38 | 966 | if (!strncmp("patch:", pool_id2str(pool, s->name), 6)) |
77c11828 MS |
967 | ispatch = 1; |
968 | conp = s->repo->idarraydata + s->conflicts; | |
969 | /* foreach conflicts of 's' */ | |
970 | while ((con = *conp++) != 0) | |
971 | { | |
e67081ca MS |
972 | #ifdef ENABLE_COMPLEX_DEPS |
973 | if (!ispatch && pool_is_complex_dep(pool, con)) | |
974 | { | |
975 | /* we have AND/COND deps, normalize */ | |
2b48a178 | 976 | add_complex_deprules(solv, n, con, SOLVER_RULE_PKG_CONFLICTS, dontfix, &workq, m); |
e67081ca MS |
977 | continue; |
978 | } | |
979 | #endif | |
77c11828 MS |
980 | /* foreach providers of a conflict of 's' */ |
981 | FOR_PROVIDES(p, pp, con) | |
982 | { | |
983 | if (ispatch && !pool_match_nevr(pool, pool->solvables + p, con)) | |
984 | continue; | |
985 | /* dontfix: dont care about conflicts with already installed packs */ | |
986 | if (dontfix && pool->solvables[p].repo == installed) | |
987 | continue; | |
5b07accd | 988 | if (p == n) /* p == n: self conflict */ |
77c11828 | 989 | { |
5b07accd MS |
990 | if (!pool->forbidselfconflicts || is_otherproviders_dep(pool, con)) |
991 | continue; | |
ea3d1f2e | 992 | addpkgrule(solv, -n, 0, 0, SOLVER_RULE_PKG_SELF_CONFLICT, con); |
5b07accd | 993 | continue; |
77c11828 | 994 | } |
5b07accd | 995 | if (ispatch && solv->multiversion.size && MAPTST(&solv->multiversion, p) && ISRELDEP(con)) |
77c11828 | 996 | { |
646a92ed | 997 | /* our patch conflicts with a multiversion package */ |
b0dda2ba MS |
998 | Id d = makemultiversionconflict(solv, p, con); |
999 | if (d) | |
1000 | { | |
ea3d1f2e | 1001 | addpkgrule(solv, -n, 0, d, SOLVER_RULE_PKG_CONFLICTS, con); |
b0dda2ba MS |
1002 | continue; |
1003 | } | |
77c11828 | 1004 | } |
b0dda2ba MS |
1005 | if (p == SYSTEMSOLVABLE) |
1006 | p = 0; | |
5b07accd | 1007 | /* rule: -n|-p: either solvable _or_ provider of conflict */ |
ea3d1f2e | 1008 | addpkgrule(solv, -n, -p, 0, SOLVER_RULE_PKG_CONFLICTS, con); |
77c11828 MS |
1009 | } |
1010 | } | |
1011 | } | |
1012 | ||
1013 | /*----------------------------------------- | |
395b1102 MS |
1014 | * check obsoletes and implicit obsoletes of a package |
1015 | * if ignoreinstalledsobsoletes is not set, we're also checking | |
1016 | * obsoletes of installed packages (like newer rpm versions) | |
77c11828 | 1017 | */ |
395b1102 MS |
1018 | if ((!installed || s->repo != installed) || !pool->noinstalledobsoletes) |
1019 | { | |
646a92ed | 1020 | int multi = solv->multiversion.size && MAPTST(&solv->multiversion, n); |
395b1102 | 1021 | int isinstalled = (installed && s->repo == installed); |
646a92ed | 1022 | if (s->obsoletes && (!multi || solv->keepexplicitobsoletes)) |
77c11828 MS |
1023 | { |
1024 | obsp = s->repo->idarraydata + s->obsoletes; | |
1025 | /* foreach obsoletes */ | |
1026 | while ((obs = *obsp++) != 0) | |
1027 | { | |
2581c2d3 | 1028 | /* foreach provider of an obsoletes of 's' */ |
77c11828 MS |
1029 | FOR_PROVIDES(p, pp, obs) |
1030 | { | |
539bae90 | 1031 | Solvable *ps = pool->solvables + p; |
395b1102 MS |
1032 | if (p == n) |
1033 | continue; | |
1034 | if (isinstalled && dontfix && ps->repo == installed) | |
1035 | continue; /* don't repair installed/installed problems */ | |
bef8a9bb | 1036 | if (!pool->obsoleteusesprovides /* obsoletes are matched names, not provides */ |
539bae90 MS |
1037 | && !pool_match_nevr(pool, ps, obs)) |
1038 | continue; | |
1039 | if (pool->obsoleteusescolors && !pool_colormatch(pool, s, ps)) | |
77c11828 | 1040 | continue; |
b0dda2ba MS |
1041 | if (p == SYSTEMSOLVABLE) |
1042 | p = 0; | |
395b1102 | 1043 | if (!isinstalled) |
ea3d1f2e | 1044 | addpkgrule(solv, -n, -p, 0, SOLVER_RULE_PKG_OBSOLETES, obs); |
395b1102 | 1045 | else |
ea3d1f2e | 1046 | addpkgrule(solv, -n, -p, 0, SOLVER_RULE_PKG_INSTALLED_OBSOLETES, obs); |
77c11828 MS |
1047 | } |
1048 | } | |
1049 | } | |
395b1102 MS |
1050 | /* check implicit obsoletes |
1051 | * for installed packages we only need to check installed/installed problems (and | |
1052 | * only when dontfix is not set), as the others are picked up when looking at the | |
1053 | * uninstalled package. | |
1054 | */ | |
1055 | if (!isinstalled || !dontfix) | |
77c11828 | 1056 | { |
395b1102 MS |
1057 | FOR_PROVIDES(p, pp, s->name) |
1058 | { | |
1059 | Solvable *ps = pool->solvables + p; | |
1060 | if (p == n) | |
1061 | continue; | |
1062 | if (isinstalled && ps->repo != installed) | |
1063 | continue; | |
1064 | /* we still obsolete packages with same nevra, like rpm does */ | |
1065 | /* (actually, rpm mixes those packages. yuck...) */ | |
646a92ed | 1066 | if (multi && (s->name != ps->name || s->evr != ps->evr || s->arch != ps->arch)) |
18627d1c MS |
1067 | { |
1068 | if (isinstalled || ps->repo != installed) | |
1069 | continue; | |
1070 | /* also check the installed package for multi-ness */ | |
1071 | if (MAPTST(&solv->multiversion, p)) | |
1072 | continue; | |
1073 | } | |
395b1102 MS |
1074 | if (!pool->implicitobsoleteusesprovides && s->name != ps->name) |
1075 | continue; | |
ee3a248c | 1076 | if (pool->implicitobsoleteusescolors && !pool_colormatch(pool, s, ps)) |
395b1102 | 1077 | continue; |
b0dda2ba MS |
1078 | if (p == SYSTEMSOLVABLE) |
1079 | p = 0; | |
395b1102 | 1080 | if (s->name == ps->name) |
2bbeceaa MS |
1081 | { |
1082 | /* optimization: do not add the same-name conflict rule if it was | |
18627d1c | 1083 | * already added when we looked at the other package. |
2bbeceaa MS |
1084 | * (this assumes pool_colormatch is symmetric) */ |
1085 | if (p && m && ps->repo != installed && MAPTST(m, p) && | |
1086 | (ps->arch != ARCH_SRC && ps->arch != ARCH_NOSRC) && | |
1087 | !(solv->multiversion.size && MAPTST(&solv->multiversion, p))) | |
1088 | continue; | |
1089 | addpkgrule(solv, -n, -p, 0, SOLVER_RULE_PKG_SAME_NAME, 0); | |
1090 | } | |
395b1102 | 1091 | else |
ea3d1f2e | 1092 | addpkgrule(solv, -n, -p, 0, SOLVER_RULE_PKG_IMPLICIT_OBSOLETES, s->name); |
395b1102 | 1093 | } |
77c11828 MS |
1094 | } |
1095 | } | |
1096 | ||
965e0a76 | 1097 | if (m && pool->implicitobsoleteusescolors && pool_arch2score(pool, s->arch) > 1) |
f190dfed | 1098 | { |
e02692e2 | 1099 | unsigned int pa, a = pool_arch2score(pool, s->arch); |
f190dfed MS |
1100 | /* check lock-step candidates */ |
1101 | FOR_PROVIDES(p, pp, s->name) | |
1102 | { | |
1103 | Solvable *ps = pool->solvables + p; | |
1104 | if (s->name != ps->name || s->evr != ps->evr || MAPTST(m, p)) | |
1105 | continue; | |
965e0a76 MS |
1106 | pa = pool_arch2score(pool, ps->arch); |
1107 | if (!pa || pa == 1 || pa >= a) | |
f190dfed MS |
1108 | continue; |
1109 | queue_push(&workq, p); | |
1110 | } | |
1111 | } | |
1112 | ||
77c11828 | 1113 | /*----------------------------------------- |
348e68e3 | 1114 | * add recommends/suggests to the work queue |
77c11828 MS |
1115 | */ |
1116 | if (s->recommends && m) | |
1117 | { | |
1118 | recp = s->repo->idarraydata + s->recommends; | |
1119 | while ((rec = *recp++) != 0) | |
1120 | { | |
348e68e3 MS |
1121 | #ifdef ENABLE_COMPLEX_DEPS |
1122 | if (pool_is_complex_dep(pool, rec)) | |
1123 | { | |
1124 | pool_add_pos_literals_complex_dep(pool, rec, &workq, m, 0); | |
6713cd45 | 1125 | continue; |
348e68e3 MS |
1126 | } |
1127 | #endif | |
77c11828 MS |
1128 | FOR_PROVIDES(p, pp, rec) |
1129 | if (!MAPTST(m, p)) | |
1130 | queue_push(&workq, p); | |
1131 | } | |
1132 | } | |
1133 | if (s->suggests && m) | |
1134 | { | |
1135 | sugp = s->repo->idarraydata + s->suggests; | |
1136 | while ((sug = *sugp++) != 0) | |
1137 | { | |
348e68e3 MS |
1138 | #ifdef ENABLE_COMPLEX_DEPS |
1139 | if (pool_is_complex_dep(pool, sug)) | |
1140 | { | |
1141 | pool_add_pos_literals_complex_dep(pool, sug, &workq, m, 0); | |
6713cd45 | 1142 | continue; |
348e68e3 MS |
1143 | } |
1144 | #endif | |
77c11828 MS |
1145 | FOR_PROVIDES(p, pp, sug) |
1146 | if (!MAPTST(m, p)) | |
1147 | queue_push(&workq, p); | |
1148 | } | |
1149 | } | |
1150 | } | |
6b414e99 | 1151 | queue_free(&depq); |
77c11828 | 1152 | queue_free(&workq); |
77c11828 MS |
1153 | } |
1154 | ||
e5fff4bc | 1155 | #ifdef ENABLE_LINKED_PKGS |
f09c993f | 1156 | void |
2b48a178 | 1157 | solver_addpkgrulesforlinked(Solver *solv, Map *m) |
f09c993f MS |
1158 | { |
1159 | Pool *pool = solv->pool; | |
1160 | Solvable *s; | |
1fe6dc5d MS |
1161 | int i, j; |
1162 | Queue qr; | |
f09c993f | 1163 | |
1fe6dc5d | 1164 | queue_init(&qr); |
f09c993f MS |
1165 | for (i = 1; i < pool->nsolvables; i++) |
1166 | { | |
1167 | if (MAPTST(m, i)) | |
1168 | continue; | |
1169 | s = pool->solvables + i; | |
1170 | if (!s->repo || s->repo == solv->installed) | |
1171 | continue; | |
1fe6dc5d | 1172 | if (!strchr(pool_id2str(pool, s->name), ':')) |
f09c993f MS |
1173 | continue; |
1174 | if (!pool_installable(pool, s)) | |
1175 | continue; | |
1fe6dc5d MS |
1176 | find_package_link(pool, s, 0, &qr, 0, 0); |
1177 | if (qr.count) | |
f09c993f | 1178 | { |
1fe6dc5d MS |
1179 | for (j = 0; j < qr.count; j++) |
1180 | if (MAPTST(m, qr.elements[j])) | |
1181 | { | |
2b48a178 | 1182 | solver_addpkgrulesforsolvable(solv, s, m); |
1fe6dc5d MS |
1183 | break; |
1184 | } | |
1185 | queue_empty(&qr); | |
f09c993f MS |
1186 | } |
1187 | } | |
1fe6dc5d | 1188 | queue_free(&qr); |
f09c993f | 1189 | } |
e5fff4bc | 1190 | #endif |
77c11828 MS |
1191 | |
1192 | /*------------------------------------------------------------------- | |
2581c2d3 | 1193 | * |
8e6473a7 | 1194 | * Add rules for packages possibly selected in by weak dependencies |
77c11828 | 1195 | * |
8e6473a7 | 1196 | * m: already added solvables |
77c11828 MS |
1197 | */ |
1198 | ||
1199 | void | |
2b48a178 | 1200 | solver_addpkgrulesforweak(Solver *solv, Map *m) |
77c11828 MS |
1201 | { |
1202 | Pool *pool = solv->pool; | |
1203 | Solvable *s; | |
1204 | Id sup, *supp; | |
1205 | int i, n; | |
1206 | ||
8e6473a7 | 1207 | /* foreach solvable in pool */ |
77c11828 MS |
1208 | for (i = n = 1; n < pool->nsolvables; i++, n++) |
1209 | { | |
1210 | if (i == pool->nsolvables) /* wrap i */ | |
1211 | i = 1; | |
8e6473a7 | 1212 | if (MAPTST(m, i)) /* already added that one */ |
77c11828 MS |
1213 | continue; |
1214 | ||
1215 | s = pool->solvables + i; | |
86328583 | 1216 | if (!s->repo) |
77c11828 | 1217 | continue; |
86328583 MS |
1218 | if (s->repo != pool->installed && !pool_installable(pool, s)) |
1219 | continue; /* only look at installable ones */ | |
77c11828 MS |
1220 | |
1221 | sup = 0; | |
1222 | if (s->supplements) | |
1223 | { | |
1224 | /* find possible supplements */ | |
1225 | supp = s->repo->idarraydata + s->supplements; | |
8e6473a7 | 1226 | while ((sup = *supp++) != 0) |
b414e484 | 1227 | if (solver_dep_possible(solv, sup, m)) |
77c11828 MS |
1228 | break; |
1229 | } | |
1230 | ||
1231 | /* if nothing found, check for enhances */ | |
1232 | if (!sup && s->enhances) | |
1233 | { | |
1234 | supp = s->repo->idarraydata + s->enhances; | |
8e6473a7 | 1235 | while ((sup = *supp++) != 0) |
b414e484 | 1236 | if (solver_dep_possible(solv, sup, m)) |
77c11828 MS |
1237 | break; |
1238 | } | |
1239 | /* if nothing found, goto next solvables */ | |
1240 | if (!sup) | |
1241 | continue; | |
2b48a178 | 1242 | solver_addpkgrulesforsolvable(solv, s, m); |
8e6473a7 | 1243 | n = 0; /* check all solvables again because we added solvables to m */ |
77c11828 | 1244 | } |
77c11828 MS |
1245 | } |
1246 | ||
1247 | ||
1248 | /*------------------------------------------------------------------- | |
2581c2d3 | 1249 | * |
77c11828 | 1250 | * add package rules for possible updates |
2581c2d3 | 1251 | * |
77c11828 MS |
1252 | * s: solvable |
1253 | * m: map of already visited solvables | |
1254 | * allow_all: 0 = dont allow downgrades, 1 = allow all candidates | |
1255 | */ | |
1256 | ||
1257 | void | |
2b48a178 | 1258 | solver_addpkgrulesforupdaters(Solver *solv, Solvable *s, Map *m, int allow_all) |
77c11828 MS |
1259 | { |
1260 | Pool *pool = solv->pool; | |
1261 | int i; | |
1262 | /* queue and buffer for it */ | |
1263 | Queue qs; | |
1264 | Id qsbuf[64]; | |
1265 | ||
77c11828 MS |
1266 | queue_init_buffer(&qs, qsbuf, sizeof(qsbuf)/sizeof(*qsbuf)); |
1267 | /* find update candidates for 's' */ | |
1268 | policy_findupdatepackages(solv, s, &qs, allow_all); | |
1269 | /* add rule for 's' if not already done */ | |
1270 | if (!MAPTST(m, s - pool->solvables)) | |
2b48a178 | 1271 | solver_addpkgrulesforsolvable(solv, s, m); |
77c11828 MS |
1272 | /* foreach update candidate, add rule if not already done */ |
1273 | for (i = 0; i < qs.count; i++) | |
1274 | if (!MAPTST(m, qs.elements[i])) | |
2b48a178 | 1275 | solver_addpkgrulesforsolvable(solv, pool->solvables + qs.elements[i], m); |
77c11828 | 1276 | queue_free(&qs); |
77c11828 MS |
1277 | } |
1278 | ||
1279 | ||
ee15afaf MS |
1280 | /*********************************************************************** |
1281 | *** | |
1282 | *** Update/Feature rule part | |
1283 | *** | |
1284 | *** Those rules make sure an installed package isn't silently deleted | |
1285 | *** | |
1286 | ***/ | |
1287 | ||
6c9cef4e MS |
1288 | static int |
1289 | dup_maykeepinstalled(Solver *solv, Solvable *s) | |
1290 | { | |
1291 | Pool *pool = solv->pool; | |
1292 | Id ip, pp; | |
1293 | ||
1294 | if (solv->dupmap.size && MAPTST(&solv->dupmap, s - pool->solvables)) | |
1295 | return 1; | |
1296 | /* is installed identical to a good one? */ | |
1297 | FOR_PROVIDES(ip, pp, s->name) | |
1298 | { | |
1299 | Solvable *is = pool->solvables + ip; | |
1300 | if (is->evr != s->evr) | |
1301 | continue; | |
1302 | if (solv->dupmap.size) | |
1303 | { | |
1304 | if (!MAPTST(&solv->dupmap, ip)) | |
1305 | continue; | |
1306 | } | |
1307 | else if (is->repo == pool->installed) | |
1308 | continue; | |
1309 | if (solvable_identical(s, is)) | |
1310 | return 1; | |
1311 | } | |
1312 | return 0; | |
1313 | } | |
1314 | ||
1315 | ||
9762f8b8 MS |
1316 | /* stash away the original updaters for multiversion packages. We do this so that |
1317 | * we can update the package later */ | |
1318 | static inline void | |
1319 | set_specialupdaters(Solver *solv, Solvable *s, Id d) | |
1320 | { | |
1321 | Repo *installed = solv->installed; | |
1322 | if (!solv->specialupdaters) | |
1323 | solv->specialupdaters = solv_calloc(installed->end - installed->start, sizeof(Id)); | |
1324 | solv->specialupdaters[s - solv->pool->solvables - installed->start] = d; | |
1325 | } | |
1326 | ||
6c9cef4e MS |
1327 | #ifdef ENABLE_LINKED_PKGS |
1328 | /* Check if this is a linked pseudo package. As it is linked, we do not need an update/feature rule */ | |
1329 | static inline int | |
1330 | is_linked_pseudo_package(Solver *solv, Solvable *s) | |
1331 | { | |
1332 | Pool *pool = solv->pool; | |
1333 | if (solv->instbuddy && solv->instbuddy[s - pool->solvables - solv->installed->start]) | |
1334 | { | |
1335 | const char *name = pool_id2str(pool, s->name); | |
1336 | if (strncmp(name, "pattern:", 8) == 0 || strncmp(name, "application:", 12) == 0) | |
1337 | return 1; | |
1338 | } | |
1339 | return 0; | |
1340 | } | |
1341 | #endif | |
1342 | ||
1343 | void | |
1344 | solver_addfeaturerule(Solver *solv, Solvable *s) | |
1345 | { | |
1346 | Pool *pool = solv->pool; | |
1347 | int i; | |
1348 | Id p; | |
1349 | Queue qs; | |
1350 | Id qsbuf[64]; | |
1351 | ||
1352 | #ifdef ENABLE_LINKED_PKGS | |
1353 | if (is_linked_pseudo_package(solv, s)) | |
1354 | { | |
1355 | solver_addrule(solv, 0, 0, 0); /* no feature rules for those */ | |
1356 | return; | |
1357 | } | |
1358 | #endif | |
1359 | queue_init_buffer(&qs, qsbuf, sizeof(qsbuf)/sizeof(*qsbuf)); | |
1360 | p = s - pool->solvables; | |
1361 | policy_findupdatepackages(solv, s, &qs, 1); | |
0d625aa6 | 1362 | if (solv->dupinvolvedmap_all || (solv->dupinvolvedmap.size && MAPTST(&solv->dupinvolvedmap, p))) |
6c9cef4e MS |
1363 | { |
1364 | if (!dup_maykeepinstalled(solv, s)) | |
1365 | { | |
1366 | for (i = 0; i < qs.count; i++) | |
1367 | { | |
1368 | Solvable *ns = pool->solvables + qs.elements[i]; | |
1369 | if (ns->repo != pool->installed || dup_maykeepinstalled(solv, ns)) | |
1370 | break; | |
1371 | } | |
1372 | if (i == qs.count) | |
1373 | { | |
1374 | solver_addrule(solv, 0, 0, 0); /* this is an orphan */ | |
1375 | queue_free(&qs); | |
1376 | return; | |
1377 | } | |
1378 | } | |
1379 | } | |
1380 | if (qs.count > 1) | |
1381 | { | |
1382 | Id d = pool_queuetowhatprovides(pool, &qs); | |
1383 | queue_free(&qs); | |
1384 | solver_addrule(solv, p, 0, d); /* allow update of s */ | |
1385 | } | |
1386 | else | |
1387 | { | |
1388 | Id d = qs.count ? qs.elements[0] : 0; | |
1389 | queue_free(&qs); | |
1390 | solver_addrule(solv, p, d, 0); /* allow update of s */ | |
1391 | } | |
1392 | } | |
1393 | ||
4975df65 MS |
1394 | /* check if multiversion solvable s2 has an obsoletes for installed solvable s */ |
1395 | static int | |
1396 | is_multiversion_obsoleteed(Pool *pool, Solvable *s, Solvable *s2) | |
1397 | { | |
1398 | Id *wp, obs, *obsp; | |
1399 | ||
1400 | if (pool->obsoleteusescolors && !pool_colormatch(pool, s, s2)) | |
1401 | return 0; | |
1402 | obsp = s2->repo->idarraydata + s2->obsoletes; | |
1403 | if (!pool->obsoleteusesprovides) | |
1404 | { | |
1405 | while ((obs = *obsp++) != 0) | |
1406 | if (pool_match_nevr(pool, s, obs)) | |
1407 | return 1; | |
1408 | } | |
1409 | else | |
1410 | { | |
1411 | while ((obs = *obsp++) != 0) | |
1412 | for (wp = pool_whatprovides_ptr(pool, obs); *wp; wp++) | |
1413 | if (pool->solvables + *wp == s) | |
1414 | return 1; | |
1415 | } | |
1416 | return 0; | |
1417 | } | |
1418 | ||
ee15afaf | 1419 | /*------------------------------------------------------------------- |
2581c2d3 | 1420 | * |
ee15afaf MS |
1421 | * add rule for update |
1422 | * (A|A1|A2|A3...) An = update candidates for A | |
1423 | * | |
1424 | * s = (installed) solvable | |
1425 | */ | |
1426 | ||
1427 | void | |
6c9cef4e | 1428 | solver_addupdaterule(Solver *solv, Solvable *s) |
ee15afaf MS |
1429 | { |
1430 | /* installed packages get a special upgrade allowed rule */ | |
1431 | Pool *pool = solv->pool; | |
1432 | Id p, d; | |
1433 | Queue qs; | |
1434 | Id qsbuf[64]; | |
6c9cef4e | 1435 | Rule *r; |
80bce710 | 1436 | int dupinvolved = 0; |
ee15afaf | 1437 | |
ee15afaf | 1438 | p = s - pool->solvables; |
95486231 MS |
1439 | |
1440 | if (pool->considered && pool_disabled_solvable(pool, s)) | |
1441 | { | |
1442 | /* disabled installed solvables must stay installed */ | |
1443 | solver_addrule(solv, p, 0, 0); | |
1444 | return; | |
1445 | } | |
1446 | ||
6c9cef4e MS |
1447 | /* Orphan detection. We cheat by looking at the feature rule, which |
1448 | * we already calculated */ | |
1449 | r = solv->rules + solv->featurerules + (p - solv->installed->start); | |
15873527 | 1450 | if (!r->p) |
6c9cef4e | 1451 | { |
15873527 MS |
1452 | #ifdef ENABLE_LINKED_PKGS |
1453 | if (is_linked_pseudo_package(solv, s)) | |
1454 | { | |
1455 | solver_addrule(solv, 0, 0, 0); | |
1456 | return; | |
1457 | } | |
1458 | #endif | |
6c9cef4e MS |
1459 | p = 0; |
1460 | queue_push(&solv->orphaned, s - pool->solvables); /* an orphaned package */ | |
1461 | if (solv->keep_orphans && !(solv->droporphanedmap_all || (solv->droporphanedmap.size && MAPTST(&solv->droporphanedmap, s - pool->solvables - solv->installed->start)))) | |
1462 | p = s - pool->solvables; /* keep this orphaned package installed */ | |
1463 | solver_addrule(solv, p, 0, 0); | |
1464 | return; | |
1465 | } | |
1466 | ||
ee15afaf | 1467 | /* find update candidates for 's' */ |
80bce710 MS |
1468 | queue_init_buffer(&qs, qsbuf, sizeof(qsbuf)/sizeof(*qsbuf)); |
1469 | dupinvolved = solv->dupinvolvedmap_all || (solv->dupinvolvedmap.size && MAPTST(&solv->dupinvolvedmap, p)); | |
1470 | policy_findupdatepackages(solv, s, &qs, dupinvolved ? 2 : 0); | |
ee15afaf | 1471 | |
6c9cef4e | 1472 | if (qs.count && solv->multiversion.size) |
ee15afaf MS |
1473 | { |
1474 | int i, j; | |
1475 | ||
457c61a3 MS |
1476 | for (i = 0; i < qs.count; i++) |
1477 | if (MAPTST(&solv->multiversion, qs.elements[i])) | |
1478 | break; | |
1479 | if (i < qs.count) | |
ee15afaf | 1480 | { |
457c61a3 | 1481 | /* filter out all multiversion packages as they don't update */ |
98352a50 | 1482 | d = pool_queuetowhatprovides(pool, &qs); /* save qs away */ |
457c61a3 MS |
1483 | for (j = i; i < qs.count; i++) |
1484 | { | |
1485 | if (MAPTST(&solv->multiversion, qs.elements[i])) | |
b2ed4571 | 1486 | { |
457c61a3 | 1487 | Solvable *ps = pool->solvables + qs.elements[i]; |
4975df65 MS |
1488 | /* check if there is an explicit obsoletes */ |
1489 | if (solv->keepexplicitobsoletes && ps->obsoletes && is_multiversion_obsoleteed(pool, s, ps)) | |
457c61a3 MS |
1490 | { |
1491 | qs.elements[j++] = qs.elements[i]; | |
1492 | continue; | |
1493 | } | |
1494 | /* it's ok if they have same nevra */ | |
1495 | if (ps->name != s->name || ps->evr != s->evr || ps->arch != s->arch) | |
1496 | continue; | |
b2ed4571 | 1497 | } |
457c61a3 | 1498 | qs.elements[j++] = qs.elements[i]; |
ee15afaf | 1499 | } |
80bce710 MS |
1500 | |
1501 | if (j == 0 && dupinvolved && !dup_maykeepinstalled(solv, s)) | |
ee15afaf | 1502 | { |
80bce710 MS |
1503 | /* this is a multiversion orphan */ |
1504 | queue_push(&solv->orphaned, p); | |
1505 | set_specialupdaters(solv, s, d); | |
1506 | if (solv->keep_orphans && !(solv->droporphanedmap_all || (solv->droporphanedmap.size && MAPTST(&solv->droporphanedmap, p - solv->installed->start)))) | |
457c61a3 | 1507 | { |
80bce710 MS |
1508 | /* we need to keep the orphan */ |
1509 | queue_free(&qs); | |
1510 | solver_addrule(solv, p, 0, 0); | |
1511 | return; | |
457c61a3 | 1512 | } |
80bce710 MS |
1513 | /* we can drop it as long as we update */ |
1514 | j = qs.count; | |
1515 | } | |
1516 | ||
1517 | if (j < qs.count) /* filtered at least one package? */ | |
1518 | { | |
1519 | if (d && (solv->updatemap_all || (solv->updatemap.size && MAPTST(&solv->updatemap, p - solv->installed->start)))) | |
9762f8b8 MS |
1520 | { |
1521 | /* non-orphan multiversion package, set special updaters if we want an update */ | |
1522 | set_specialupdaters(solv, s, d); | |
1523 | } | |
457c61a3 | 1524 | qs.count = j; |
ee15afaf | 1525 | } |
80bce710 | 1526 | else |
d1e903af | 1527 | { |
457c61a3 MS |
1528 | /* could fallthrough, but then we would do pool_queuetowhatprovides twice */ |
1529 | queue_free(&qs); | |
80bce710 | 1530 | solver_addrule(solv, p, 0, d); /* allow update of s */ |
457c61a3 | 1531 | return; |
d1e903af | 1532 | } |
96275a1c | 1533 | } |
ee15afaf | 1534 | } |
b0dda2ba MS |
1535 | if (qs.count > 1) |
1536 | { | |
1537 | d = pool_queuetowhatprovides(pool, &qs); | |
1538 | queue_free(&qs); | |
ea3d1f2e | 1539 | solver_addrule(solv, p, 0, d); /* allow update of s */ |
b0dda2ba MS |
1540 | } |
1541 | else | |
1542 | { | |
1543 | d = qs.count ? qs.elements[0] : 0; | |
1544 | queue_free(&qs); | |
ea3d1f2e | 1545 | solver_addrule(solv, p, d, 0); /* allow update of s */ |
b0dda2ba | 1546 | } |
ee15afaf MS |
1547 | } |
1548 | ||
2581c2d3 | 1549 | static inline void |
ee15afaf MS |
1550 | disableupdaterule(Solver *solv, Id p) |
1551 | { | |
1552 | Rule *r; | |
1553 | ||
1554 | MAPSET(&solv->noupdate, p - solv->installed->start); | |
1555 | r = solv->rules + solv->updaterules + (p - solv->installed->start); | |
1556 | if (r->p && r->d >= 0) | |
1557 | solver_disablerule(solv, r); | |
1558 | r = solv->rules + solv->featurerules + (p - solv->installed->start); | |
1559 | if (r->p && r->d >= 0) | |
1560 | solver_disablerule(solv, r); | |
178203fe | 1561 | if (solv->bestrules_info) |
96275a1c MS |
1562 | { |
1563 | int i, ni; | |
1564 | ni = solv->bestrules_end - solv->bestrules; | |
1fda7cd6 | 1565 | for (i = solv->bestrules_up - solv->bestrules; i < ni; i++) |
178203fe | 1566 | if (solv->bestrules_info[i] == p) |
96275a1c MS |
1567 | solver_disablerule(solv, solv->rules + solv->bestrules + i); |
1568 | } | |
ee15afaf MS |
1569 | } |
1570 | ||
2581c2d3 | 1571 | static inline void |
ee15afaf MS |
1572 | reenableupdaterule(Solver *solv, Id p) |
1573 | { | |
1574 | Pool *pool = solv->pool; | |
1575 | Rule *r; | |
1576 | ||
1577 | MAPCLR(&solv->noupdate, p - solv->installed->start); | |
1578 | r = solv->rules + solv->updaterules + (p - solv->installed->start); | |
1579 | if (r->p) | |
2581c2d3 | 1580 | { |
3c0edb72 | 1581 | if (r->d < 0) |
ee15afaf | 1582 | { |
96275a1c MS |
1583 | solver_enablerule(solv, r); |
1584 | IF_POOLDEBUG (SOLV_DEBUG_SOLUTIONS) | |
1585 | { | |
1586 | POOL_DEBUG(SOLV_DEBUG_SOLUTIONS, "@@@ re-enabling "); | |
1587 | solver_printruleclass(solv, SOLV_DEBUG_SOLUTIONS, r); | |
1588 | } | |
ee15afaf | 1589 | } |
ee15afaf | 1590 | } |
96275a1c | 1591 | else |
ee15afaf | 1592 | { |
96275a1c MS |
1593 | r = solv->rules + solv->featurerules + (p - solv->installed->start); |
1594 | if (r->p && r->d < 0) | |
ee15afaf | 1595 | { |
96275a1c MS |
1596 | solver_enablerule(solv, r); |
1597 | IF_POOLDEBUG (SOLV_DEBUG_SOLUTIONS) | |
1598 | { | |
1599 | POOL_DEBUG(SOLV_DEBUG_SOLUTIONS, "@@@ re-enabling "); | |
1600 | solver_printruleclass(solv, SOLV_DEBUG_SOLUTIONS, r); | |
1601 | } | |
ee15afaf MS |
1602 | } |
1603 | } | |
178203fe | 1604 | if (solv->bestrules_info) |
96275a1c MS |
1605 | { |
1606 | int i, ni; | |
1607 | ni = solv->bestrules_end - solv->bestrules; | |
1fda7cd6 | 1608 | for (i = solv->bestrules_up - solv->bestrules; i < ni; i++) |
178203fe | 1609 | if (solv->bestrules_info[i] == p) |
96275a1c MS |
1610 | solver_enablerule(solv, solv->rules + solv->bestrules + i); |
1611 | } | |
ee15afaf MS |
1612 | } |
1613 | ||
1614 | ||
1615 | /*********************************************************************** | |
1616 | *** | |
1617 | *** Infarch rule part | |
1618 | *** | |
1619 | *** Infarch rules make sure the solver uses the best architecture of | |
1620 | *** a package if multiple archetectures are available | |
1621 | *** | |
1622 | ***/ | |
1623 | ||
1624 | void | |
1625 | solver_addinfarchrules(Solver *solv, Map *addedmap) | |
1626 | { | |
1627 | Pool *pool = solv->pool; | |
f190dfed | 1628 | Repo *installed = pool->installed; |
ee15afaf | 1629 | int first, i, j; |
e02692e2 MS |
1630 | Id p, pp, aa; |
1631 | unsigned int a, bestscore; | |
ee15afaf MS |
1632 | Solvable *s, *ps, *bests; |
1633 | Queue badq, allowedarchs; | |
047a5a57 | 1634 | Queue lsq; |
ee15afaf MS |
1635 | |
1636 | queue_init(&badq); | |
1637 | queue_init(&allowedarchs); | |
047a5a57 | 1638 | queue_init(&lsq); |
ee15afaf MS |
1639 | solv->infarchrules = solv->nrules; |
1640 | for (i = 1; i < pool->nsolvables; i++) | |
1641 | { | |
1642 | if (i == SYSTEMSOLVABLE || !MAPTST(addedmap, i)) | |
1643 | continue; | |
1644 | s = pool->solvables + i; | |
1645 | first = i; | |
e02692e2 | 1646 | bestscore = 0; |
ee15afaf MS |
1647 | bests = 0; |
1648 | queue_empty(&allowedarchs); | |
1649 | FOR_PROVIDES(p, pp, s->name) | |
1650 | { | |
1651 | ps = pool->solvables + p; | |
1652 | if (ps->name != s->name || !MAPTST(addedmap, p)) | |
1653 | continue; | |
1654 | if (p == i) | |
1655 | first = 0; | |
1656 | if (first) | |
1657 | break; | |
965e0a76 | 1658 | a = pool_arch2score(pool, ps->arch); |
f190dfed | 1659 | if (a != 1 && installed && ps->repo == installed) |
ee15afaf | 1660 | { |
0d625aa6 MS |
1661 | if (solv->dupinvolvedmap_all || (solv->dupinvolvedmap.size && MAPTST(&solv->dupinvolvedmap, p))) |
1662 | continue; | |
1663 | queue_pushunique(&allowedarchs, ps->arch); /* also ok to keep this architecture */ | |
1664 | continue; /* but ignore installed solvables when calculating the best arch */ | |
ee15afaf | 1665 | } |
e02692e2 | 1666 | if (a && a != 1 && (!bestscore || a < bestscore)) |
ee15afaf | 1667 | { |
e02692e2 | 1668 | bestscore = a; |
ee15afaf MS |
1669 | bests = ps; |
1670 | } | |
1671 | } | |
1672 | if (first) | |
90fed1ef MS |
1673 | continue; /* not the first in the group */ |
1674 | ||
634371f1 MS |
1675 | if (!bestscore && allowedarchs.count > 1 && pool->implicitobsoleteusescolors) |
1676 | { | |
1677 | for (j = 0; j < allowedarchs.count; j++) | |
1678 | { | |
1679 | a = pool_arch2score(pool, allowedarchs.elements[j]); | |
1680 | if (a && a != 1 && (!bestscore || a < bestscore)) | |
1681 | bestscore = a; | |
1682 | } | |
1683 | } | |
1684 | ||
90fed1ef MS |
1685 | if (!bestscore) |
1686 | continue; /* did not find a score for this group */ | |
f190dfed | 1687 | |
ee15afaf MS |
1688 | /* speed up common case where installed package already has best arch */ |
1689 | if (allowedarchs.count == 1 && bests && allowedarchs.elements[0] == bests->arch) | |
1690 | allowedarchs.count--; /* installed arch is best */ | |
f190dfed | 1691 | |
90fed1ef | 1692 | if (allowedarchs.count && pool->implicitobsoleteusescolors && installed) |
f190dfed MS |
1693 | { |
1694 | /* need an extra pass for lockstep checking: we only allow to keep an inferior arch | |
1695 | * if the corresponding installed package is not lock-stepped */ | |
1696 | queue_empty(&allowedarchs); | |
1697 | FOR_PROVIDES(p, pp, s->name) | |
1698 | { | |
1699 | Id p2, pp2; | |
1700 | ps = pool->solvables + p; | |
1701 | if (ps->name != s->name || ps->repo != installed || !MAPTST(addedmap, p)) | |
1702 | continue; | |
0d625aa6 | 1703 | if (solv->dupinvolvedmap_all || (solv->dupinvolvedmap.size && MAPTST(&solv->dupinvolvedmap, p))) |
f190dfed | 1704 | continue; |
965e0a76 | 1705 | a = pool_arch2score(pool, ps->arch); |
f190dfed MS |
1706 | if (!a) |
1707 | { | |
1708 | queue_pushunique(&allowedarchs, ps->arch); /* strange arch, allow */ | |
1709 | continue; | |
1710 | } | |
e02692e2 | 1711 | if (a == 1 || ((a ^ bestscore) & 0xffff0000) == 0) |
f190dfed MS |
1712 | continue; |
1713 | /* have installed package with inferior arch, check if lock-stepped */ | |
1714 | FOR_PROVIDES(p2, pp2, s->name) | |
1715 | { | |
1716 | Solvable *s2 = pool->solvables + p2; | |
e02692e2 | 1717 | unsigned int a2; |
f190dfed MS |
1718 | if (p2 == p || s2->name != s->name || s2->evr != pool->solvables[p].evr || s2->arch == pool->solvables[p].arch) |
1719 | continue; | |
965e0a76 | 1720 | a2 = pool_arch2score(pool, s2->arch); |
e02692e2 | 1721 | if (a2 && (a2 == 1 || ((a2 ^ bestscore) & 0xffff0000) == 0)) |
f190dfed MS |
1722 | break; |
1723 | } | |
1724 | if (!p2) | |
1725 | queue_pushunique(&allowedarchs, ps->arch); | |
1726 | } | |
1727 | } | |
1728 | ||
1729 | /* find all bad packages */ | |
ee15afaf MS |
1730 | queue_empty(&badq); |
1731 | FOR_PROVIDES(p, pp, s->name) | |
1732 | { | |
1733 | ps = pool->solvables + p; | |
1734 | if (ps->name != s->name || !MAPTST(addedmap, p)) | |
1735 | continue; | |
965e0a76 | 1736 | a = pool_arch2score(pool, ps->arch); |
90fed1ef | 1737 | if (a != 1 && ((a ^ bestscore) & 0xffff0000) != 0) |
ee15afaf | 1738 | { |
f190dfed MS |
1739 | if (installed && ps->repo == installed) |
1740 | { | |
1741 | if (pool->implicitobsoleteusescolors) | |
1742 | queue_push(&badq, p); /* special lock-step handling, see below */ | |
1743 | continue; /* always ok to keep an installed package */ | |
1744 | } | |
ee15afaf MS |
1745 | for (j = 0; j < allowedarchs.count; j++) |
1746 | { | |
e02692e2 | 1747 | unsigned int aas; |
ee15afaf MS |
1748 | aa = allowedarchs.elements[j]; |
1749 | if (ps->arch == aa) | |
1750 | break; | |
e02692e2 MS |
1751 | aas = pool_arch2score(pool, aa); |
1752 | if (aas && ((a ^ aas) & 0xffff0000) == 0) | |
ee15afaf MS |
1753 | break; /* compatible */ |
1754 | } | |
1755 | if (j == allowedarchs.count) | |
1756 | queue_push(&badq, p); | |
1757 | } | |
1758 | } | |
f190dfed | 1759 | |
ee15afaf MS |
1760 | /* block all solvables in the badq! */ |
1761 | for (j = 0; j < badq.count; j++) | |
1762 | { | |
1763 | p = badq.elements[j]; | |
e02692e2 | 1764 | /* special lock-step handling */ |
047a5a57 MS |
1765 | if (pool->implicitobsoleteusescolors) |
1766 | { | |
1767 | Id p2; | |
f190dfed | 1768 | int haveinstalled = 0; |
047a5a57 MS |
1769 | queue_empty(&lsq); |
1770 | FOR_PROVIDES(p2, pp, s->name) | |
1771 | { | |
1772 | Solvable *s2 = pool->solvables + p2; | |
1773 | if (p2 == p || s2->name != s->name || s2->evr != pool->solvables[p].evr || s2->arch == pool->solvables[p].arch) | |
1774 | continue; | |
965e0a76 | 1775 | a = pool_arch2score(pool, s2->arch); |
e02692e2 | 1776 | if (a && (a == 1 || ((a ^ bestscore) & 0xffff000) == 0)) |
f190dfed MS |
1777 | { |
1778 | queue_push(&lsq, p2); | |
1779 | if (installed && s2->repo == installed) | |
1780 | haveinstalled = 1; | |
1781 | } | |
047a5a57 | 1782 | } |
f190dfed MS |
1783 | if (installed && pool->solvables[p].repo == installed && !haveinstalled) |
1784 | continue; /* installed package not in lock-step */ | |
4c28f90f MS |
1785 | if (lsq.count < 2) |
1786 | solver_addrule(solv, -p, lsq.count ? lsq.elements[0] : 0, 0); | |
1787 | else | |
1788 | solver_addrule(solv, -p, 0, pool_queuetowhatprovides(pool, &lsq)); | |
047a5a57 | 1789 | } |
b0dda2ba | 1790 | else |
4c28f90f MS |
1791 | { |
1792 | solver_addrule(solv, -p, 0, 0); | |
1793 | } | |
ee15afaf MS |
1794 | } |
1795 | } | |
047a5a57 | 1796 | queue_free(&lsq); |
ee15afaf MS |
1797 | queue_free(&badq); |
1798 | queue_free(&allowedarchs); | |
1799 | solv->infarchrules_end = solv->nrules; | |
1800 | } | |
1801 | ||
1802 | static inline void | |
1803 | disableinfarchrule(Solver *solv, Id name) | |
1804 | { | |
1805 | Pool *pool = solv->pool; | |
1806 | Rule *r; | |
1807 | int i; | |
1808 | for (i = solv->infarchrules, r = solv->rules + i; i < solv->infarchrules_end; i++, r++) | |
1809 | { | |
1810 | if (r->p < 0 && r->d >= 0 && pool->solvables[-r->p].name == name) | |
1811 | solver_disablerule(solv, r); | |
1812 | } | |
1813 | } | |
1814 | ||
1815 | static inline void | |
1816 | reenableinfarchrule(Solver *solv, Id name) | |
1817 | { | |
1818 | Pool *pool = solv->pool; | |
1819 | Rule *r; | |
1820 | int i; | |
1821 | for (i = solv->infarchrules, r = solv->rules + i; i < solv->infarchrules_end; i++, r++) | |
1822 | { | |
1823 | if (r->p < 0 && r->d < 0 && pool->solvables[-r->p].name == name) | |
1824 | { | |
1825 | solver_enablerule(solv, r); | |
09f29f70 | 1826 | IF_POOLDEBUG (SOLV_DEBUG_SOLUTIONS) |
ee15afaf | 1827 | { |
09f29f70 MS |
1828 | POOL_DEBUG(SOLV_DEBUG_SOLUTIONS, "@@@ re-enabling "); |
1829 | solver_printruleclass(solv, SOLV_DEBUG_SOLUTIONS, r); | |
ee15afaf MS |
1830 | } |
1831 | } | |
1832 | } | |
1833 | } | |
1834 | ||
1835 | ||
1836 | /*********************************************************************** | |
1837 | *** | |
1838 | *** Dup rule part | |
1839 | *** | |
1840 | *** Dup rules make sure a package is selected from the specified dup | |
1841 | *** repositories if an update candidate is included in one of them. | |
1842 | *** | |
1843 | ***/ | |
1844 | ||
2581c2d3 | 1845 | static inline void |
0cac083d | 1846 | add_cleandeps_updatepkg(Solver *solv, Id p) |
3e809fce MS |
1847 | { |
1848 | if (!solv->cleandeps_updatepkgs) | |
2581c2d3 | 1849 | { |
3e809fce MS |
1850 | solv->cleandeps_updatepkgs = solv_calloc(1, sizeof(Queue)); |
1851 | queue_init(solv->cleandeps_updatepkgs); | |
2581c2d3 MS |
1852 | } |
1853 | queue_pushunique(solv->cleandeps_updatepkgs, p); | |
3e809fce MS |
1854 | } |
1855 | ||
03d4ab0d | 1856 | static void |
b3b6c172 MS |
1857 | solver_addtodupmaps(Solver *solv, Id p, Id how, int targeted) |
1858 | { | |
1859 | Pool *pool = solv->pool; | |
1860 | Solvable *ps, *s = pool->solvables + p; | |
1861 | Repo *installed = solv->installed; | |
1862 | Id pi, pip, obs, *obsp; | |
1863 | ||
0d625aa6 MS |
1864 | if (!solv->dupinvolvedmap.size) |
1865 | map_grow(&solv->dupinvolvedmap, pool->nsolvables); | |
1866 | ||
b3b6c172 MS |
1867 | MAPSET(&solv->dupinvolvedmap, p); |
1868 | if (targeted) | |
1869 | MAPSET(&solv->dupmap, p); | |
1870 | FOR_PROVIDES(pi, pip, s->name) | |
1871 | { | |
1872 | ps = pool->solvables + pi; | |
1873 | if (ps->name != s->name) | |
1874 | continue; | |
1875 | MAPSET(&solv->dupinvolvedmap, pi); | |
ff65a849 | 1876 | if (targeted && ps->repo == installed && solv->obsoletes && solv->obsoletes[pi - installed->start]) |
b3b6c172 MS |
1877 | { |
1878 | Id *opp, pi2; | |
1879 | for (opp = solv->obsoletes_data + solv->obsoletes[pi - installed->start]; (pi2 = *opp++) != 0;) | |
1880 | if (pool->solvables[pi2].repo != installed) | |
1881 | MAPSET(&solv->dupinvolvedmap, pi2); | |
1882 | } | |
53ef5c8d | 1883 | if (ps->repo == installed && (how & SOLVER_FORCEBEST) != 0 && !solv->bestupdatemap_all) |
b3b6c172 MS |
1884 | { |
1885 | if (!solv->bestupdatemap.size) | |
1886 | map_grow(&solv->bestupdatemap, installed->end - installed->start); | |
1887 | MAPSET(&solv->bestupdatemap, pi - installed->start); | |
1888 | } | |
3e809fce | 1889 | if (ps->repo == installed && (how & SOLVER_CLEANDEPS) != 0) |
0cac083d | 1890 | add_cleandeps_updatepkg(solv, pi); |
b3b6c172 MS |
1891 | if (!targeted && ps->repo != installed) |
1892 | MAPSET(&solv->dupmap, pi); | |
1893 | } | |
1894 | if (s->repo == installed && solv->obsoletes && solv->obsoletes[p - installed->start]) | |
1895 | { | |
1896 | Id *opp; | |
1897 | for (opp = solv->obsoletes_data + solv->obsoletes[p - installed->start]; (pi = *opp++) != 0;) | |
1898 | { | |
1899 | ps = pool->solvables + pi; | |
1900 | if (ps->repo == installed) | |
1901 | continue; | |
1902 | MAPSET(&solv->dupinvolvedmap, pi); | |
1903 | if (!targeted) | |
1904 | MAPSET(&solv->dupmap, pi); | |
1905 | } | |
1906 | } | |
1907 | if (targeted && s->repo != installed && s->obsoletes) | |
1908 | { | |
1909 | /* XXX: check obsoletes/provides combination */ | |
1910 | obsp = s->repo->idarraydata + s->obsoletes; | |
1911 | while ((obs = *obsp++) != 0) | |
1912 | { | |
1913 | FOR_PROVIDES(pi, pip, obs) | |
1914 | { | |
1915 | Solvable *ps = pool->solvables + pi; | |
1916 | if (!pool->obsoleteusesprovides && !pool_match_nevr(pool, ps, obs)) | |
1917 | continue; | |
1918 | if (pool->obsoleteusescolors && !pool_colormatch(pool, s, ps)) | |
1919 | continue; | |
1920 | MAPSET(&solv->dupinvolvedmap, pi); | |
ff65a849 | 1921 | if (targeted && ps->repo == installed && solv->obsoletes && solv->obsoletes[pi - installed->start]) |
b3b6c172 MS |
1922 | { |
1923 | Id *opp, pi2; | |
1924 | for (opp = solv->obsoletes_data + solv->obsoletes[pi - installed->start]; (pi2 = *opp++) != 0;) | |
1925 | if (pool->solvables[pi2].repo != installed) | |
1926 | MAPSET(&solv->dupinvolvedmap, pi2); | |
1927 | } | |
53ef5c8d | 1928 | if (ps->repo == installed && (how & SOLVER_FORCEBEST) != 0 && !solv->bestupdatemap_all) |
b3b6c172 MS |
1929 | { |
1930 | if (!solv->bestupdatemap.size) | |
1931 | map_grow(&solv->bestupdatemap, installed->end - installed->start); | |
1932 | MAPSET(&solv->bestupdatemap, pi - installed->start); | |
1933 | } | |
3e809fce | 1934 | if (ps->repo == installed && (how & SOLVER_CLEANDEPS) != 0) |
0cac083d | 1935 | add_cleandeps_updatepkg(solv, pi); |
b3b6c172 MS |
1936 | } |
1937 | } | |
1938 | } | |
1939 | } | |
1940 | ||
0d625aa6 MS |
1941 | /* create the two dupmaps: |
1942 | * - dupmap: packages in that map are good to install/keep | |
1943 | * - dupinvolvedmap: packages are subject to dup mode | |
1944 | */ | |
ee15afaf MS |
1945 | void |
1946 | solver_createdupmaps(Solver *solv) | |
1947 | { | |
ee15afaf | 1948 | Pool *pool = solv->pool; |
c4552628 | 1949 | Queue *job = &solv->job; |
96275a1c | 1950 | Repo *installed = solv->installed; |
b3b6c172 MS |
1951 | Id select, how, what, p, pp; |
1952 | Solvable *s; | |
022b394e | 1953 | int i, targeted; |
ee15afaf MS |
1954 | |
1955 | map_init(&solv->dupmap, pool->nsolvables); | |
0d625aa6 MS |
1956 | solv->dupinvolvedmap_all = 0; |
1957 | map_init(&solv->dupinvolvedmap, 0); | |
ee15afaf MS |
1958 | for (i = 0; i < job->count; i += 2) |
1959 | { | |
1960 | how = job->elements[i]; | |
c77a6330 | 1961 | select = job->elements[i] & SOLVER_SELECTMASK; |
ee15afaf MS |
1962 | what = job->elements[i + 1]; |
1963 | switch (how & SOLVER_JOBMASK) | |
1964 | { | |
1965 | case SOLVER_DISTUPGRADE: | |
b3b6c172 MS |
1966 | if (select == SOLVER_SOLVABLE_REPO) |
1967 | { | |
1968 | Repo *repo; | |
1969 | if (what <= 0 || what > pool->nrepos) | |
1970 | break; | |
1971 | repo = pool_id2repo(pool, what); | |
1972 | if (!repo) | |
1973 | break; | |
1974 | if (repo != installed && !(how & SOLVER_TARGETED) && solv->noautotarget) | |
1975 | break; | |
1976 | targeted = repo != installed || (how & SOLVER_TARGETED) != 0; | |
1977 | FOR_REPO_SOLVABLES(repo, p, s) | |
1978 | { | |
1979 | if (repo != installed && !pool_installable(pool, s)) | |
1980 | continue; | |
1981 | solver_addtodupmaps(solv, p, how, targeted); | |
1982 | } | |
1983 | } | |
65a81492 MS |
1984 | else if (select == SOLVER_SOLVABLE_ALL) |
1985 | { | |
0d625aa6 | 1986 | solv->dupinvolvedmap_all = 1; |
65a81492 MS |
1987 | FOR_POOL_SOLVABLES(p) |
1988 | { | |
322ce52d MS |
1989 | Solvable *s = pool->solvables + p; |
1990 | if (!s->repo || s->repo == installed) | |
1991 | continue; | |
1992 | if (!pool_installable(pool, s)) | |
1993 | continue; | |
1994 | MAPSET(&solv->dupmap, p); | |
65a81492 | 1995 | } |
322ce52d | 1996 | if ((how & SOLVER_FORCEBEST) != 0) |
0d625aa6 | 1997 | solv->bestupdatemap_all = 1; |
322ce52d | 1998 | if ((how & SOLVER_CLEANDEPS) != 0 && installed) |
53ef5c8d MS |
1999 | { |
2000 | FOR_REPO_SOLVABLES(installed, p, s) | |
2001 | add_cleandeps_updatepkg(solv, p); | |
2002 | } | |
65a81492 | 2003 | } |
b3b6c172 | 2004 | else |
c77a6330 | 2005 | { |
022b394e MS |
2006 | targeted = how & SOLVER_TARGETED ? 1 : 0; |
2007 | if (installed && !targeted && !solv->noautotarget) | |
c77a6330 MS |
2008 | { |
2009 | FOR_JOB_SELECT(p, pp, select, what) | |
96275a1c | 2010 | if (pool->solvables[p].repo == installed) |
c77a6330 | 2011 | break; |
022b394e | 2012 | targeted = p == 0; |
c77a6330 | 2013 | } |
022b394e MS |
2014 | else if (!installed && !solv->noautotarget) |
2015 | targeted = 1; | |
c77a6330 MS |
2016 | FOR_JOB_SELECT(p, pp, select, what) |
2017 | { | |
2018 | Solvable *s = pool->solvables + p; | |
2019 | if (!s->repo) | |
2020 | continue; | |
b3b6c172 | 2021 | if (s->repo != installed && !targeted) |
c77a6330 | 2022 | continue; |
96275a1c | 2023 | if (s->repo != installed && !pool_installable(pool, s)) |
c77a6330 | 2024 | continue; |
b3b6c172 | 2025 | solver_addtodupmaps(solv, p, how, targeted); |
ee15afaf MS |
2026 | } |
2027 | } | |
2028 | break; | |
2029 | default: | |
2030 | break; | |
2031 | } | |
2032 | } | |
0d625aa6 MS |
2033 | if (solv->dupinvolvedmap.size) |
2034 | MAPCLR(&solv->dupinvolvedmap, SYSTEMSOLVABLE); | |
ebd5f74d MS |
2035 | /* set update for all involved installed packages. We need to do |
2036 | * this before creating the update rules */ | |
2037 | if (solv->dupinvolvedmap_all) | |
2038 | solv->updatemap_all = 1; | |
1d8399a4 | 2039 | else if (installed && !solv->updatemap_all && solv->dupinvolvedmap.size) |
ebd5f74d MS |
2040 | { |
2041 | FOR_REPO_SOLVABLES(installed, p, s) | |
2042 | { | |
1d8399a4 | 2043 | if (!MAPTST(&solv->dupinvolvedmap, p)) |
ebd5f74d MS |
2044 | continue; |
2045 | if (!solv->updatemap.size) | |
2046 | map_grow(&solv->updatemap, installed->end - installed->start); | |
2047 | MAPSET(&solv->updatemap, p - installed->start); | |
2048 | } | |
2049 | } | |
ee15afaf MS |
2050 | } |
2051 | ||
2052 | void | |
2053 | solver_freedupmaps(Solver *solv) | |
2054 | { | |
2055 | map_free(&solv->dupmap); | |
d45a9363 | 2056 | /* we no longer free solv->dupinvolvedmap as we need it in |
67ba3106 | 2057 | * policy's priority pruning code. sigh. */ |
ee15afaf MS |
2058 | } |
2059 | ||
2060 | void | |
2061 | solver_addduprules(Solver *solv, Map *addedmap) | |
2062 | { | |
2063 | Pool *pool = solv->pool; | |
364c90b0 | 2064 | Repo *installed = solv->installed; |
ee15afaf MS |
2065 | Id p, pp; |
2066 | Solvable *s, *ps; | |
2067 | int first, i; | |
98352a50 | 2068 | Rule *r; |
ee15afaf MS |
2069 | |
2070 | solv->duprules = solv->nrules; | |
2071 | for (i = 1; i < pool->nsolvables; i++) | |
2072 | { | |
2073 | if (i == SYSTEMSOLVABLE || !MAPTST(addedmap, i)) | |
2074 | continue; | |
2075 | s = pool->solvables + i; | |
2076 | first = i; | |
2077 | FOR_PROVIDES(p, pp, s->name) | |
2078 | { | |
2079 | ps = pool->solvables + p; | |
2080 | if (ps->name != s->name || !MAPTST(addedmap, p)) | |
2081 | continue; | |
2082 | if (p == i) | |
2083 | first = 0; | |
2084 | if (first) | |
2085 | break; | |
0d625aa6 | 2086 | if (!solv->dupinvolvedmap_all && !MAPTST(&solv->dupinvolvedmap, p)) |
ee15afaf | 2087 | continue; |
364c90b0 | 2088 | if (installed && ps->repo == installed) |
ee15afaf | 2089 | { |
95486231 MS |
2090 | if (pool->considered && pool_disabled_solvable(pool, ps)) |
2091 | continue; /* always keep disabled installed packages */ | |
ee15afaf MS |
2092 | if (!MAPTST(&solv->dupmap, p)) |
2093 | { | |
2094 | Id ip, ipp; | |
2095 | /* is installed identical to a good one? */ | |
4ace9e91 | 2096 | FOR_PROVIDES(ip, ipp, ps->name) |
ee15afaf MS |
2097 | { |
2098 | Solvable *is = pool->solvables + ip; | |
2099 | if (!MAPTST(&solv->dupmap, ip)) | |
2100 | continue; | |
4ace9e91 | 2101 | if (is->evr == ps->evr && solvable_identical(ps, is)) |
ee15afaf MS |
2102 | break; |
2103 | } | |
98352a50 | 2104 | if (ip) |
d5af25c0 | 2105 | { |
0d625aa6 | 2106 | /* ok, identical to a good one. we may keep this package. */ |
98352a50 MS |
2107 | MAPSET(&solv->dupmap, p); /* for best rules processing */ |
2108 | continue; | |
d5af25c0 | 2109 | } |
0d625aa6 | 2110 | /* check if it's orphaned. If yes, we may keep it */ |
98352a50 MS |
2111 | r = solv->rules + solv->updaterules + (p - installed->start); |
2112 | if (!r->p) | |
0d625aa6 MS |
2113 | r = solv->rules + solv->featurerules + (p - installed->start); |
2114 | if (!r->p) | |
2115 | { | |
2116 | /* no update/feature rule, this is an orphan */ | |
2117 | MAPSET(&solv->dupmap, p); /* for best rules processing */ | |
2118 | continue; | |
2119 | } | |
2120 | if (solv->specialupdaters && solv->specialupdaters[p - installed->start]) | |
98352a50 MS |
2121 | { |
2122 | /* this is a multiversion orphan, we're good if an update is installed */ | |
2123 | solver_addrule(solv, -p, 0, solv->specialupdaters[p - installed->start]); | |
2124 | continue; | |
2125 | } | |
0d625aa6 | 2126 | if (r->p == p && !r->d && !r->w2) |
7fed3dde | 2127 | { |
0d625aa6 MS |
2128 | r = solv->rules + solv->featurerules + (p - installed->start); |
2129 | if (!r->p || (!r->d && !r->w2)) | |
2130 | { | |
2131 | /* this is an orphan */ | |
2132 | MAPSET(&solv->dupmap, p); /* for best rules processing */ | |
2133 | continue; | |
2134 | } | |
7fed3dde | 2135 | } |
98352a50 | 2136 | solver_addrule(solv, -p, 0, 0); /* no match, sorry */ |
ee15afaf MS |
2137 | } |
2138 | } | |
2139 | else if (!MAPTST(&solv->dupmap, p)) | |
ea3d1f2e | 2140 | solver_addrule(solv, -p, 0, 0); |
ee15afaf MS |
2141 | } |
2142 | } | |
2143 | solv->duprules_end = solv->nrules; | |
2144 | } | |
2145 | ||
2146 | ||
2147 | static inline void | |
2148 | disableduprule(Solver *solv, Id name) | |
2149 | { | |
2150 | Pool *pool = solv->pool; | |
2151 | Rule *r; | |
2152 | int i; | |
2581c2d3 MS |
2153 | for (i = solv->duprules, r = solv->rules + i; i < solv->duprules_end; i++, r++) |
2154 | { | |
ee15afaf MS |
2155 | if (r->p < 0 && r->d >= 0 && pool->solvables[-r->p].name == name) |
2156 | solver_disablerule(solv, r); | |
2581c2d3 | 2157 | } |
ee15afaf MS |
2158 | } |
2159 | ||
2581c2d3 | 2160 | static inline void |
ee15afaf MS |
2161 | reenableduprule(Solver *solv, Id name) |
2162 | { | |
2163 | Pool *pool = solv->pool; | |
2164 | Rule *r; | |
2165 | int i; | |
2581c2d3 MS |
2166 | for (i = solv->duprules, r = solv->rules + i; i < solv->duprules_end; i++, r++) |
2167 | { | |
ee15afaf MS |
2168 | if (r->p < 0 && r->d < 0 && pool->solvables[-r->p].name == name) |
2169 | { | |
2170 | solver_enablerule(solv, r); | |
09f29f70 | 2171 | IF_POOLDEBUG (SOLV_DEBUG_SOLUTIONS) |
ee15afaf | 2172 | { |
09f29f70 MS |
2173 | POOL_DEBUG(SOLV_DEBUG_SOLUTIONS, "@@@ re-enabling "); |
2174 | solver_printruleclass(solv, SOLV_DEBUG_SOLUTIONS, r); | |
ee15afaf MS |
2175 | } |
2176 | } | |
2177 | } | |
2178 | } | |
2179 | ||
4120051b MS |
2180 | /*********************************************************************** |
2181 | *** | |
2182 | *** Black rule part | |
2183 | ***/ | |
2184 | ||
2185 | static inline void | |
2186 | disableblackrule(Solver *solv, Id p) | |
2187 | { | |
2188 | Rule *r; | |
2189 | int i; | |
2190 | for (i = solv->blackrules, r = solv->rules + i; i < solv->blackrules_end; i++, r++) | |
2191 | if (r->p == -p) | |
2192 | solver_disablerule(solv, r); | |
2193 | } | |
2194 | ||
2195 | static inline void | |
2196 | reenableblackrule(Solver *solv, Id p) | |
2197 | { | |
2198 | Pool *pool = solv->pool; | |
2199 | Rule *r; | |
2200 | int i; | |
2201 | for (i = solv->blackrules, r = solv->rules + i; i < solv->blackrules_end; i++, r++) | |
2202 | if (r->p == -p) | |
2203 | { | |
2204 | solver_enablerule(solv, r); | |
2205 | IF_POOLDEBUG (SOLV_DEBUG_SOLUTIONS) | |
2206 | { | |
2207 | POOL_DEBUG(SOLV_DEBUG_SOLUTIONS, "@@@ re-enabling "); | |
2208 | solver_printruleclass(solv, SOLV_DEBUG_SOLUTIONS, r); | |
2209 | } | |
2210 | } | |
2211 | } | |
2212 | ||
2213 | void | |
2214 | solver_addblackrules(Solver *solv) | |
2215 | { | |
4120051b MS |
2216 | Pool *pool = solv->pool; |
2217 | Repo *installed = solv->installed; | |
c4552628 MS |
2218 | Id how, select, what, p, pp; |
2219 | Queue *job = &solv->job; | |
4120051b | 2220 | Map updatemap; |
c4552628 | 2221 | int i; |
4120051b MS |
2222 | |
2223 | map_init(&updatemap, 0); | |
2224 | solv->blackrules = solv->nrules; | |
2225 | if (installed) | |
2226 | { | |
2227 | for (i = 0; i < job->count; i += 2) | |
2228 | { | |
2229 | how = job->elements[i]; | |
2230 | select = job->elements[i] & SOLVER_SELECTMASK; | |
2231 | what = job->elements[i + 1]; | |
2232 | switch (how & SOLVER_JOBMASK) | |
2233 | { | |
2234 | case SOLVER_BLACKLIST: | |
2235 | FOR_JOB_SELECT(p, pp, select, what) | |
2236 | { | |
2237 | Solvable *s = pool->solvables + p; | |
2238 | if (s->repo != installed) | |
2239 | continue; | |
2240 | if (!updatemap.size) | |
2241 | map_grow(&updatemap, pool->ss.nstrings); | |
2242 | if (s->name > 0 && s->name < pool->ss.nstrings) | |
2243 | MAPSET(&updatemap, s->name); | |
2244 | } | |
2245 | } | |
2246 | } | |
2247 | } | |
2248 | for (i = 0; i < job->count; i += 2) | |
2249 | { | |
2250 | how = job->elements[i]; | |
2251 | select = job->elements[i] & SOLVER_SELECTMASK; | |
2252 | what = job->elements[i + 1]; | |
2253 | switch (how & SOLVER_JOBMASK) | |
2254 | { | |
2255 | case SOLVER_BLACKLIST: | |
2256 | FOR_JOB_SELECT(p, pp, select, what) | |
2257 | { | |
2258 | Solvable *s = pool->solvables + p; | |
2259 | if (s->repo == installed) | |
2260 | continue; | |
2261 | if (updatemap.size && s->name > 0 && s->name < pool->ss.nstrings && MAPTST(&updatemap, s->name)) | |
2262 | continue; /* installed package with same name is already blacklisted */ | |
2263 | solver_addrule(solv, -p, 0, 0); | |
2264 | } | |
2265 | break; | |
2266 | } | |
2267 | } | |
2268 | map_free(&updatemap); | |
2269 | solv->blackrules_end = solv->nrules; | |
2270 | } | |
ee15afaf | 2271 | |
e79734ab MS |
2272 | /*********************************************************************** |
2273 | *** | |
2274 | *** Strict repo prio rule part | |
2275 | ***/ | |
2276 | ||
2277 | /* add rules to exclude solvables provided by lower | |
2278 | * precedence repositories */ | |
2279 | void solver_addstrictrepopriorules(struct s_Solver *solv, Map *addedmap) | |
2280 | { | |
2281 | Pool *pool = solv->pool; | |
2282 | Solvable *s; | |
2283 | Id p, p2, pp2; | |
2284 | Map priomap; | |
2285 | int max_prio; | |
2286 | ||
2287 | map_init_clone(&priomap, addedmap); | |
2288 | solv->strictrepopriorules = solv->nrules; | |
2289 | ||
2290 | FOR_POOL_SOLVABLES(p) | |
2291 | { | |
2292 | if (!MAPTST(&priomap, p)) | |
2293 | continue; | |
2294 | ||
2295 | s = pool->solvables + p; | |
2296 | max_prio = s->repo->priority; | |
2297 | FOR_PROVIDES(p2, pp2, s->name) | |
2298 | { | |
2299 | Solvable *s2 = pool->solvables + p2; | |
2300 | if (s->name != s2->name) | |
2301 | continue; | |
2302 | if (s2->repo->priority > max_prio) | |
2303 | max_prio = s2->repo->priority; | |
2304 | } | |
2305 | ||
2306 | FOR_PROVIDES(p2, pp2, s->name) | |
2307 | { | |
2308 | Solvable *s2 = pool->solvables + p2; | |
2309 | if (s->name != s2->name || !MAPTST(&priomap, p2)) | |
2310 | continue; | |
2311 | MAPCLR(&priomap, p2); | |
2312 | if (pool->installed && s2->repo == pool->installed) | |
2313 | continue; | |
2314 | if (s2->repo->priority < max_prio) | |
2315 | solver_addrule(solv, -p2, 0, 0); | |
2316 | } | |
2317 | } | |
2318 | solv->strictrepopriorules_end = solv->nrules; | |
2319 | map_free(&priomap); | |
2320 | } | |
2321 | ||
2322 | static inline void | |
2323 | disablerepopriorule(Solver *solv, Id name) | |
2324 | { | |
2325 | Pool *pool = solv->pool; | |
2326 | Rule *r; | |
2327 | int i; | |
2328 | for (i = solv->strictrepopriorules, r = solv->rules + i; i < solv->strictrepopriorules_end; i++, r++) | |
2329 | { | |
2330 | if (r->p < 0 && r->d >= 0 && pool->solvables[-r->p].name == name) | |
2331 | solver_disablerule(solv, r); | |
2332 | } | |
2333 | } | |
2334 | ||
2335 | static inline void | |
2336 | reenablerepopriorule(Solver *solv, Id name) | |
2337 | { | |
2338 | Pool *pool = solv->pool; | |
2339 | Rule *r; | |
2340 | int i; | |
2341 | for (i = solv->strictrepopriorules, r = solv->rules + i; i < solv->strictrepopriorules_end; i++, r++) | |
2342 | { | |
2343 | if (r->p < 0 && r->d < 0 && pool->solvables[-r->p].name == name) | |
2344 | { | |
2345 | solver_enablerule(solv, r); | |
2346 | IF_POOLDEBUG (SOLV_DEBUG_SOLUTIONS) | |
2347 | { | |
2348 | POOL_DEBUG(SOLV_DEBUG_SOLUTIONS, "@@@ re-enabling "); | |
2349 | solver_printruleclass(solv, SOLV_DEBUG_SOLUTIONS, r); | |
2350 | } | |
2351 | } | |
2352 | } | |
2353 | } | |
2354 | ||
ee15afaf MS |
2355 | /*********************************************************************** |
2356 | *** | |
2357 | *** Policy rule disabling/reenabling | |
2358 | *** | |
2359 | *** Disable all policy rules that conflict with our jobs. If a job | |
2360 | *** gets disabled later on, reenable the involved policy rules again. | |
2361 | *** | |
2362 | ***/ | |
2363 | ||
e79734ab MS |
2364 | #define DISABLE_UPDATE 1 |
2365 | #define DISABLE_INFARCH 2 | |
2366 | #define DISABLE_DUP 3 | |
2367 | #define DISABLE_BLACK 4 | |
2368 | #define DISABLE_REPOPRIO 5 | |
ee15afaf | 2369 | |
5dc4f81f MS |
2370 | /* check if installed package p is in lock-step with another installed package */ |
2371 | static int | |
2372 | installed_is_in_lockstep(Solver *solv, Id p) | |
2373 | { | |
2374 | Pool *pool = solv->pool; | |
2375 | Repo *installed = solv->installed; | |
2376 | int rid; | |
2377 | Id pp, l; | |
2378 | Rule *r; | |
2379 | ||
2380 | if (!installed) | |
2381 | return 0; | |
2382 | for (rid = solv->infarchrules, r = solv->rules + rid; rid < solv->infarchrules_end; rid++, r++) | |
2383 | { | |
2384 | if (r->p >= 0) | |
2385 | continue; | |
2386 | if (pool->solvables[-r->p].repo != installed) | |
2387 | continue; | |
2388 | FOR_RULELITERALS(l, pp, r) | |
2389 | if (l == p) | |
2390 | return 1; | |
2391 | } | |
2392 | return 0; | |
2393 | } | |
2394 | ||
ee15afaf MS |
2395 | static void |
2396 | jobtodisablelist(Solver *solv, Id how, Id what, Queue *q) | |
2397 | { | |
2398 | Pool *pool = solv->pool; | |
2399 | Id select, p, pp; | |
2400 | Repo *installed; | |
2401 | Solvable *s; | |
ed477952 | 2402 | int i, j, set, qstart; |
7a6a10a3 | 2403 | Map omap; |
ee15afaf MS |
2404 | |
2405 | installed = solv->installed; | |
2406 | select = how & SOLVER_SELECTMASK; | |
2407 | switch (how & SOLVER_JOBMASK) | |
2408 | { | |
2409 | case SOLVER_INSTALL: | |
7a6a10a3 | 2410 | set = how & SOLVER_SETMASK; |
72812c71 | 2411 | if (!(set & SOLVER_NOAUTOSET)) |
ee15afaf | 2412 | { |
72812c71 | 2413 | /* automatically add set bits by analysing the job */ |
d4295440 MS |
2414 | if (select == SOLVER_SOLVABLE_NAME) |
2415 | set |= SOLVER_SETNAME; | |
72812c71 | 2416 | if (select == SOLVER_SOLVABLE) |
d4295440 | 2417 | set |= SOLVER_SETNAME | SOLVER_SETARCH | SOLVER_SETVENDOR | SOLVER_SETREPO | SOLVER_SETEVR; |
72812c71 | 2418 | else if ((select == SOLVER_SOLVABLE_NAME || select == SOLVER_SOLVABLE_PROVIDES) && ISRELDEP(what)) |
7a6a10a3 | 2419 | { |
72812c71 MS |
2420 | Reldep *rd = GETRELDEP(pool, what); |
2421 | if (rd->flags == REL_EQ && select == SOLVER_SOLVABLE_NAME) | |
2422 | { | |
17ea16d7 MS |
2423 | if (pool->disttype != DISTTYPE_DEB) |
2424 | { | |
f3deacb9 | 2425 | const char *rel = strrchr(pool_id2str(pool, rd->evr), '-'); |
68a1076f | 2426 | set |= rel ? SOLVER_SETEVR : SOLVER_SETEV; |
17ea16d7 | 2427 | } |
72812c71 | 2428 | else |
17ea16d7 | 2429 | set |= SOLVER_SETEVR; |
72812c71 MS |
2430 | } |
2431 | if (rd->flags <= 7 && ISRELDEP(rd->name)) | |
2432 | rd = GETRELDEP(pool, rd->name); | |
2433 | if (rd->flags == REL_ARCH) | |
2434 | set |= SOLVER_SETARCH; | |
7a6a10a3 | 2435 | } |
7a6a10a3 | 2436 | } |
72812c71 MS |
2437 | else |
2438 | set &= ~SOLVER_NOAUTOSET; | |
7a6a10a3 MS |
2439 | if (!set) |
2440 | return; | |
2441 | if ((set & SOLVER_SETARCH) != 0 && solv->infarchrules != solv->infarchrules_end) | |
2442 | { | |
2443 | if (select == SOLVER_SOLVABLE) | |
5323eb7e MS |
2444 | { |
2445 | for (i = solv->infarchrules; i < solv->infarchrules_end; i++) | |
2446 | if (solv->rules[i].p == -what) | |
2447 | break; | |
2448 | if (i < solv->infarchrules_end) | |
2449 | queue_push2(q, DISABLE_INFARCH, pool->solvables[what].name); | |
2450 | } | |
7a6a10a3 | 2451 | else |
ee15afaf MS |
2452 | { |
2453 | int qcnt = q->count; | |
cb28413d MS |
2454 | /* does not work for SOLVER_SOLVABLE_ALL and SOLVER_SOLVABLE_REPO, but |
2455 | they are not useful for SOLVER_INSTALL jobs anyway */ | |
ee15afaf MS |
2456 | FOR_JOB_SELECT(p, pp, select, what) |
2457 | { | |
2458 | s = pool->solvables + p; | |
2459 | /* unify names */ | |
2460 | for (i = qcnt; i < q->count; i += 2) | |
2461 | if (q->elements[i + 1] == s->name) | |
2462 | break; | |
2463 | if (i < q->count) | |
5323eb7e MS |
2464 | continue; /* already have that DISABLE_INFARCH element */ |
2465 | for (i = solv->infarchrules; i < solv->infarchrules_end; i++) | |
2466 | if (solv->rules[i].p == -p) | |
2467 | break; | |
2468 | if (i < solv->infarchrules_end) | |
2469 | queue_push2(q, DISABLE_INFARCH, s->name); | |
ee15afaf MS |
2470 | } |
2471 | } | |
2472 | } | |
7a6a10a3 | 2473 | if ((set & SOLVER_SETREPO) != 0 && solv->duprules != solv->duprules_end) |
d1e903af | 2474 | { |
7a6a10a3 MS |
2475 | if (select == SOLVER_SOLVABLE) |
2476 | queue_push2(q, DISABLE_DUP, pool->solvables[what].name); | |
2477 | else | |
2478 | { | |
2479 | int qcnt = q->count; | |
2480 | FOR_JOB_SELECT(p, pp, select, what) | |
2481 | { | |
2482 | s = pool->solvables + p; | |
2483 | /* unify names */ | |
2484 | for (i = qcnt; i < q->count; i += 2) | |
2485 | if (q->elements[i + 1] == s->name) | |
2486 | break; | |
2487 | if (i < q->count) | |
2488 | continue; | |
2489 | queue_push2(q, DISABLE_DUP, s->name); | |
2490 | } | |
2491 | } | |
d1e903af | 2492 | } |
e79734ab MS |
2493 | if ((set & SOLVER_SETREPO) != 0 && solv->strictrepopriorules != solv->strictrepopriorules_end) |
2494 | { | |
2495 | if (select == SOLVER_SOLVABLE) | |
2496 | queue_push2(q, DISABLE_REPOPRIO, pool->solvables[what].name); | |
2497 | else | |
2498 | { | |
2499 | int qcnt = q->count; | |
2500 | FOR_JOB_SELECT(p, pp, select, what) | |
2501 | { | |
2502 | s = pool->solvables + p; | |
2503 | /* unify names */ | |
2504 | for (i = qcnt; i < q->count; i += 2) | |
2505 | if (q->elements[i + 1] == s->name) | |
2506 | break; | |
2507 | if (i < q->count) | |
2508 | continue; | |
2509 | queue_push2(q, DISABLE_REPOPRIO, s->name); | |
2510 | } | |
2511 | } | |
2512 | } | |
4120051b MS |
2513 | if ((set & SOLVER_SETEVR) != 0 && solv->blackrules != solv->blackrules_end) |
2514 | { | |
2515 | if (select == SOLVER_SOLVABLE) | |
2516 | queue_push2(q, DISABLE_BLACK, what); | |
2517 | else | |
2518 | { | |
2519 | FOR_JOB_SELECT(p, pp, select, what) | |
2520 | queue_push2(q, DISABLE_BLACK, p); | |
2521 | } | |
2522 | } | |
ed477952 | 2523 | if (!installed || installed->end == installed->start) |
7a6a10a3 MS |
2524 | return; |
2525 | /* now the hard part: disable some update rules */ | |
2526 | ||
73415322 MS |
2527 | /* if the job asks for a single solvable to stay, disable the update rule */ |
2528 | if (select == SOLVER_SOLVABLE && pool->solvables[what].repo == installed && solv->bestrules_info) | |
2529 | if ((set & (SOLVER_SETEVR | SOLVER_SETARCH | SOLVER_SETVENDOR)) == (SOLVER_SETEVR | SOLVER_SETARCH | SOLVER_SETVENDOR)) | |
2530 | { | |
2531 | int ni = solv->bestrules_end - solv->bestrules; | |
2532 | for (i = solv->bestrules_up - solv->bestrules; i < ni; i++) | |
2533 | if (solv->bestrules_info[i] == what) | |
2534 | { | |
2535 | queue_push2(q, DISABLE_UPDATE, what); /* will also disable the best rule */ | |
2536 | break; | |
2537 | } | |
2538 | return; | |
2539 | } | |
2540 | ||
11c885e5 | 2541 | /* first check if we have installed or multiversion packages in the job */ |
7a6a10a3 | 2542 | FOR_JOB_SELECT(p, pp, select, what) |
ee15afaf | 2543 | { |
7a6a10a3 | 2544 | if (pool->solvables[p].repo == installed) |
7a6a10a3 | 2545 | return; |
11c885e5 | 2546 | if (solv->multiversion.size && MAPTST(&solv->multiversion, p) && !solv->keepexplicitobsoletes) |
4975df65 | 2547 | return; /* will not obsolete anything, so just return */ |
ee15afaf | 2548 | } |
ed477952 | 2549 | omap.size = 0; |
7a6a10a3 | 2550 | qstart = q->count; |
7a6a10a3 | 2551 | FOR_JOB_SELECT(p, pp, select, what) |
ee15afaf | 2552 | { |
b414e484 | 2553 | solver_intersect_obsoleted(solv, p, q, qstart, &omap); |
7a6a10a3 MS |
2554 | if (q->count == qstart) |
2555 | break; | |
ee15afaf | 2556 | } |
7a6a10a3 MS |
2557 | if (omap.size) |
2558 | map_free(&omap); | |
72812c71 MS |
2559 | |
2560 | if (qstart == q->count) | |
2561 | return; /* nothing to prune */ | |
ed477952 MS |
2562 | |
2563 | /* convert result to (DISABLE_UPDATE, p) pairs */ | |
2564 | i = q->count; | |
2565 | for (j = qstart; j < i; j++) | |
2566 | queue_push(q, q->elements[j]); | |
2567 | for (j = qstart; j < q->count; j += 2) | |
2568 | { | |
2569 | q->elements[j] = DISABLE_UPDATE; | |
2570 | q->elements[j + 1] = q->elements[i++]; | |
2571 | } | |
7a6a10a3 MS |
2572 | |
2573 | /* now that we know which installed packages are obsoleted check each of them */ | |
ed477952 MS |
2574 | if ((set & (SOLVER_SETEVR | SOLVER_SETARCH | SOLVER_SETVENDOR)) == (SOLVER_SETEVR | SOLVER_SETARCH | SOLVER_SETVENDOR)) |
2575 | return; /* all is set, nothing to do */ | |
2576 | ||
7a6a10a3 | 2577 | for (i = j = qstart; i < q->count; i += 2) |
ee15afaf | 2578 | { |
7a6a10a3 MS |
2579 | Solvable *is = pool->solvables + q->elements[i + 1]; |
2580 | FOR_JOB_SELECT(p, pp, select, what) | |
2581 | { | |
2582 | int illegal = 0; | |
2583 | s = pool->solvables + p; | |
2584 | if ((set & SOLVER_SETEVR) != 0) | |
2585 | illegal |= POLICY_ILLEGAL_DOWNGRADE; /* ignore */ | |
d4295440 MS |
2586 | if ((set & SOLVER_SETNAME) != 0) |
2587 | illegal |= POLICY_ILLEGAL_NAMECHANGE; /* ignore */ | |
7a6a10a3 MS |
2588 | if ((set & SOLVER_SETARCH) != 0) |
2589 | illegal |= POLICY_ILLEGAL_ARCHCHANGE; /* ignore */ | |
2590 | if ((set & SOLVER_SETVENDOR) != 0) | |
2591 | illegal |= POLICY_ILLEGAL_VENDORCHANGE; /* ignore */ | |
2592 | illegal = policy_is_illegal(solv, is, s, illegal); | |
2593 | if (illegal && illegal == POLICY_ILLEGAL_DOWNGRADE && (set & SOLVER_SETEV) != 0) | |
2594 | { | |
2595 | /* it's ok if the EV is different */ | |
e2a47f38 | 2596 | if (pool_evrcmp(pool, is->evr, s->evr, EVRCMP_COMPARE_EVONLY) != 0) |
7a6a10a3 MS |
2597 | illegal = 0; |
2598 | } | |
2599 | if (illegal) | |
2600 | break; | |
2601 | } | |
2602 | if (!p) | |
2603 | { | |
2604 | /* no package conflicts with the update rule */ | |
2605 | /* thus keep the DISABLE_UPDATE */ | |
2606 | q->elements[j + 1] = q->elements[i + 1]; | |
2607 | j += 2; | |
2608 | } | |
ee15afaf | 2609 | } |
7a6a10a3 | 2610 | queue_truncate(q, j); |
ee15afaf | 2611 | return; |
72812c71 | 2612 | |
ee15afaf MS |
2613 | case SOLVER_ERASE: |
2614 | if (!installed) | |
2615 | break; | |
634371f1 MS |
2616 | set = how & SOLVER_SETMASK; |
2617 | if (!(set & (SOLVER_NOAUTOSET | SOLVER_SETARCH)) && pool->implicitobsoleteusescolors && solv->infarchrules != solv->infarchrules_end) | |
2618 | { | |
2619 | if (select == SOLVER_SOLVABLE) | |
2620 | set |= SOLVER_SETARCH; | |
2621 | else if ((select == SOLVER_SOLVABLE_NAME || select == SOLVER_SOLVABLE_PROVIDES) && ISRELDEP(what)) | |
2622 | { | |
2623 | Reldep *rd = GETRELDEP(pool, what); | |
2624 | if (rd->flags <= 7 && ISRELDEP(rd->name)) | |
2625 | rd = GETRELDEP(pool, rd->name); | |
2626 | if (rd->flags == REL_ARCH) | |
2627 | set |= SOLVER_SETARCH; | |
2628 | } | |
2629 | } | |
cb28413d | 2630 | if (select == SOLVER_SOLVABLE_ALL || (select == SOLVER_SOLVABLE_REPO && what == installed->repoid)) |
d7a25c06 MS |
2631 | { |
2632 | FOR_REPO_SOLVABLES(installed, p, s) | |
2633 | queue_push2(q, DISABLE_UPDATE, p); | |
2634 | } | |
ee15afaf MS |
2635 | FOR_JOB_SELECT(p, pp, select, what) |
2636 | if (pool->solvables[p].repo == installed) | |
f09c993f MS |
2637 | { |
2638 | queue_push2(q, DISABLE_UPDATE, p); | |
634371f1 | 2639 | if ((set & SOLVER_SETARCH) != 0 && pool->implicitobsoleteusescolors && solv->infarchrules != solv->infarchrules_end) |
5dc4f81f MS |
2640 | if (installed_is_in_lockstep(solv, p)) |
2641 | queue_push2(q, DISABLE_INFARCH, pool->solvables[p].name); /* allow to break the lock-step */ | |
8c000d8c | 2642 | #ifdef ENABLE_LINKED_PKGS |
f09c993f MS |
2643 | if (solv->instbuddy && solv->instbuddy[p - installed->start] > 1) |
2644 | queue_push2(q, DISABLE_UPDATE, solv->instbuddy[p - installed->start]); | |
8c000d8c | 2645 | #endif |
f09c993f | 2646 | } |
ee15afaf | 2647 | return; |
b717d12a MS |
2648 | |
2649 | case SOLVER_LOCK: | |
2650 | if (!installed) | |
2651 | break; | |
2652 | qstart = q->count; | |
2653 | if (select == SOLVER_SOLVABLE_ALL || (select == SOLVER_SOLVABLE_REPO && what == installed->repoid)) | |
2654 | { | |
2655 | FOR_REPO_SOLVABLES(installed, p, s) | |
2656 | { | |
2657 | for (i = qstart; i < q->count; i += 2) | |
2658 | if (q->elements[i] == DISABLE_DUP && q->elements[i + 1] == pool->solvables[p].name) | |
2659 | break; | |
2660 | if (i == q->count) | |
2661 | queue_push2(q, DISABLE_DUP, pool->solvables[p].name); | |
2662 | } | |
2663 | } | |
2664 | FOR_JOB_SELECT(p, pp, select, what) | |
2665 | { | |
2666 | if (pool->solvables[p].repo != installed) | |
2667 | continue; | |
2668 | for (i = qstart; i < q->count; i += 2) | |
2669 | if (q->elements[i] == DISABLE_DUP && q->elements[i + 1] == pool->solvables[p].name) | |
2670 | break; | |
2671 | if (i == q->count) | |
2672 | queue_push2(q, DISABLE_DUP, pool->solvables[p].name); | |
2673 | } | |
2674 | break; | |
2675 | ||
ee15afaf MS |
2676 | default: |
2677 | return; | |
2678 | } | |
2679 | } | |
2680 | ||
2681 | /* disable all policy rules that are in conflict with our job list */ | |
2682 | void | |
2683 | solver_disablepolicyrules(Solver *solv) | |
2684 | { | |
2685 | Queue *job = &solv->job; | |
2686 | int i, j; | |
2687 | Queue allq; | |
2688 | Rule *r; | |
2689 | Id lastjob = -1; | |
2690 | Id allqbuf[128]; | |
2691 | ||
2692 | queue_init_buffer(&allq, allqbuf, sizeof(allqbuf)/sizeof(*allqbuf)); | |
2693 | ||
2694 | for (i = solv->jobrules; i < solv->jobrules_end; i++) | |
2695 | { | |
2696 | r = solv->rules + i; | |
2697 | if (r->d < 0) /* disabled? */ | |
2698 | continue; | |
2699 | j = solv->ruletojob.elements[i - solv->jobrules]; | |
2700 | if (j == lastjob) | |
2701 | continue; | |
2702 | lastjob = j; | |
2703 | jobtodisablelist(solv, job->elements[j], job->elements[j + 1], &allq); | |
2704 | } | |
b6e6a93a MS |
2705 | if (solv->cleandepsmap.size) |
2706 | { | |
b86e5e1a | 2707 | solver_createcleandepsmap(solv, &solv->cleandepsmap, 0); |
b6e6a93a MS |
2708 | for (i = solv->installed->start; i < solv->installed->end; i++) |
2709 | if (MAPTST(&solv->cleandepsmap, i - solv->installed->start)) | |
2710 | queue_push2(&allq, DISABLE_UPDATE, i); | |
2711 | } | |
ee15afaf MS |
2712 | MAPZERO(&solv->noupdate); |
2713 | for (i = 0; i < allq.count; i += 2) | |
2714 | { | |
2715 | Id type = allq.elements[i], arg = allq.elements[i + 1]; | |
2716 | switch(type) | |
2717 | { | |
2718 | case DISABLE_UPDATE: | |
2719 | disableupdaterule(solv, arg); | |
2720 | break; | |
2721 | case DISABLE_INFARCH: | |
2722 | disableinfarchrule(solv, arg); | |
2723 | break; | |
2724 | case DISABLE_DUP: | |
2725 | disableduprule(solv, arg); | |
2726 | break; | |
4120051b MS |
2727 | case DISABLE_BLACK: |
2728 | disableblackrule(solv, arg); | |
2729 | break; | |
e79734ab MS |
2730 | case DISABLE_REPOPRIO: |
2731 | disablerepopriorule(solv, arg); | |
2732 | break; | |
ee15afaf MS |
2733 | default: |
2734 | break; | |
2735 | } | |
2736 | } | |
2737 | queue_free(&allq); | |
2738 | } | |
2739 | ||
2740 | /* we just disabled job #jobidx, now reenable all policy rules that were | |
2741 | * disabled because of this job */ | |
2742 | void | |
2743 | solver_reenablepolicyrules(Solver *solv, int jobidx) | |
2744 | { | |
2745 | Queue *job = &solv->job; | |
e1802029 | 2746 | int i, j, k, ai; |
ee15afaf MS |
2747 | Queue q, allq; |
2748 | Rule *r; | |
2749 | Id lastjob = -1; | |
e1802029 | 2750 | Id qbuf[32], allqbuf[32]; |
ee15afaf MS |
2751 | |
2752 | queue_init_buffer(&q, qbuf, sizeof(qbuf)/sizeof(*qbuf)); | |
76fb56c0 | 2753 | jobtodisablelist(solv, job->elements[jobidx - 1], job->elements[jobidx], &q); |
ee15afaf | 2754 | if (!q.count) |
e1802029 MS |
2755 | { |
2756 | queue_free(&q); | |
2757 | return; | |
2758 | } | |
2759 | /* now remove everything from q that is disabled by other jobs */ | |
2760 | ||
2761 | /* first remove cleandeps packages, they count as DISABLE_UPDATE */ | |
2762 | if (solv->cleandepsmap.size) | |
2763 | { | |
2764 | solver_createcleandepsmap(solv, &solv->cleandepsmap, 0); | |
2765 | for (j = k = 0; j < q.count; j += 2) | |
2766 | { | |
2767 | if (q.elements[j] == DISABLE_UPDATE) | |
2768 | { | |
2769 | Id p = q.elements[j + 1]; | |
2770 | if (p >= solv->installed->start && p < solv->installed->end && MAPTST(&solv->cleandepsmap, p - solv->installed->start)) | |
2771 | continue; /* remove element from q */ | |
2772 | } | |
2773 | q.elements[k++] = q.elements[j]; | |
2774 | q.elements[k++] = q.elements[j + 1]; | |
2775 | } | |
2776 | q.count = k; | |
2777 | if (!q.count) | |
2778 | { | |
2779 | queue_free(&q); | |
2780 | return; | |
2781 | } | |
2782 | } | |
2783 | ||
2784 | /* now go through the disable list of all other jobs */ | |
2785 | queue_init_buffer(&allq, allqbuf, sizeof(allqbuf)/sizeof(*allqbuf)); | |
ee15afaf MS |
2786 | for (i = solv->jobrules; i < solv->jobrules_end; i++) |
2787 | { | |
2788 | r = solv->rules + i; | |
2789 | if (r->d < 0) /* disabled? */ | |
2790 | continue; | |
2791 | j = solv->ruletojob.elements[i - solv->jobrules]; | |
2792 | if (j == lastjob) | |
2793 | continue; | |
2794 | lastjob = j; | |
2795 | jobtodisablelist(solv, job->elements[j], job->elements[j + 1], &allq); | |
e1802029 MS |
2796 | if (!allq.count) |
2797 | continue; | |
2798 | /* remove all elements in allq from q */ | |
2799 | for (j = k = 0; j < q.count; j += 2) | |
2800 | { | |
2801 | Id type = q.elements[j], arg = q.elements[j + 1]; | |
2802 | for (ai = 0; ai < allq.count; ai += 2) | |
2803 | if (allq.elements[ai] == type && allq.elements[ai + 1] == arg) | |
2804 | break; | |
2805 | if (ai < allq.count) | |
2806 | continue; /* found it in allq, remove element from q */ | |
2807 | q.elements[k++] = q.elements[j]; | |
2808 | q.elements[k++] = q.elements[j + 1]; | |
2809 | } | |
2810 | q.count = k; | |
2811 | if (!q.count) | |
2812 | { | |
2813 | queue_free(&q); | |
2814 | queue_free(&allq); | |
2815 | return; | |
2816 | } | |
2817 | queue_empty(&allq); | |
ee15afaf | 2818 | } |
e1802029 MS |
2819 | queue_free(&allq); |
2820 | ||
2821 | /* now re-enable anything that's left in q */ | |
ee15afaf MS |
2822 | for (j = 0; j < q.count; j += 2) |
2823 | { | |
2824 | Id type = q.elements[j], arg = q.elements[j + 1]; | |
ee15afaf MS |
2825 | switch(type) |
2826 | { | |
2827 | case DISABLE_UPDATE: | |
2828 | reenableupdaterule(solv, arg); | |
2829 | break; | |
2830 | case DISABLE_INFARCH: | |
2831 | reenableinfarchrule(solv, arg); | |
2832 | break; | |
2833 | case DISABLE_DUP: | |
2834 | reenableduprule(solv, arg); | |
2835 | break; | |
4120051b MS |
2836 | case DISABLE_BLACK: |
2837 | reenableblackrule(solv, arg); | |
2838 | break; | |
e79734ab MS |
2839 | case DISABLE_REPOPRIO: |
2840 | reenablerepopriorule(solv, arg); | |
2841 | break; | |
ee15afaf MS |
2842 | } |
2843 | } | |
ee15afaf MS |
2844 | queue_free(&q); |
2845 | } | |
2846 | ||
baca23f1 MS |
2847 | /* we just removed a package from the cleandeps map, now reenable all policy rules that were |
2848 | * disabled because of this */ | |
2849 | void | |
2850 | solver_reenablepolicyrules_cleandeps(Solver *solv, Id pkg) | |
2851 | { | |
2852 | Queue *job = &solv->job; | |
2853 | int i, j; | |
2854 | Queue allq; | |
2855 | Rule *r; | |
2856 | Id lastjob = -1; | |
2857 | Id allqbuf[128]; | |
2858 | ||
2859 | queue_init_buffer(&allq, allqbuf, sizeof(allqbuf)/sizeof(*allqbuf)); | |
2860 | for (i = solv->jobrules; i < solv->jobrules_end; i++) | |
2861 | { | |
2862 | r = solv->rules + i; | |
2863 | if (r->d < 0) /* disabled? */ | |
2864 | continue; | |
2865 | j = solv->ruletojob.elements[i - solv->jobrules]; | |
2866 | if (j == lastjob) | |
2867 | continue; | |
2868 | lastjob = j; | |
2869 | jobtodisablelist(solv, job->elements[j], job->elements[j + 1], &allq); | |
2870 | } | |
2871 | for (i = 0; i < allq.count; i += 2) | |
2872 | if (allq.elements[i] == DISABLE_UPDATE && allq.elements[i + 1] == pkg) | |
2873 | break; | |
2874 | if (i == allq.count) | |
2875 | reenableupdaterule(solv, pkg); | |
2876 | queue_free(&allq); | |
2877 | } | |
2878 | ||
ee15afaf MS |
2879 | |
2880 | /*********************************************************************** | |
2881 | *** | |
2882 | *** Rule info part, tell the user what the rule is about. | |
2883 | *** | |
2884 | ***/ | |
77c11828 MS |
2885 | |
2886 | static void | |
ea3d1f2e | 2887 | addpkgruleinfo(Solver *solv, Id p, Id p2, Id d, int type, Id dep) |
77c11828 MS |
2888 | { |
2889 | Pool *pool = solv->pool; | |
2890 | Rule *r; | |
b0dda2ba | 2891 | |
ea3d1f2e MS |
2892 | if (d) |
2893 | { | |
2894 | assert(!p2 && d > 0); | |
2895 | if (!pool->whatprovidesdata[d]) | |
2896 | d = 0; | |
2897 | else if (!pool->whatprovidesdata[d + 1]) | |
2898 | { | |
2899 | p2 = pool->whatprovidesdata[d]; | |
2900 | d = 0; | |
2901 | } | |
2902 | } | |
77c11828 MS |
2903 | |
2904 | /* check if this creates the rule we're searching for */ | |
2905 | r = solv->rules + solv->ruleinfoq->elements[0]; | |
ea3d1f2e | 2906 | if (d) |
77c11828 | 2907 | { |
ea3d1f2e MS |
2908 | /* three or more literals */ |
2909 | Id od = r->d < 0 ? -r->d - 1 : r->d; | |
2910 | if (p != r->p && !od) | |
77c11828 | 2911 | return; |
ea3d1f2e MS |
2912 | if (d != od) |
2913 | { | |
2914 | Id *dp = pool->whatprovidesdata + d; | |
2915 | Id *odp = pool->whatprovidesdata + od; | |
2916 | while (*dp) | |
2917 | if (*dp++ != *odp++) | |
2918 | return; | |
2919 | if (*odp) | |
2920 | return; | |
2921 | } | |
98446739 MS |
2922 | /* set p2 for multiversion conflicts */ |
2923 | if (p < 0 && pool->whatprovidesdata[d] < 0 && pool->whatprovidesdata[d + 1] >= 0 && type == SOLVER_RULE_PKG_CONFLICTS) | |
ea3d1f2e | 2924 | p2 = pool->whatprovidesdata[d]; |
77c11828 | 2925 | } |
ea3d1f2e | 2926 | else |
77c11828 | 2927 | { |
ea3d1f2e MS |
2928 | /* one or two literals */ |
2929 | Id op = p, op2 = p2; | |
2930 | if (op2 && op > op2) /* normalize */ | |
2931 | { | |
2932 | Id o = op; | |
2933 | op = op2; | |
2934 | op2 = o; | |
2935 | } | |
2936 | if (r->p != op || r->w2 != op2 || (r->d && r->d != -1)) | |
2937 | return; | |
b0dda2ba MS |
2938 | if (type == SOLVER_RULE_PKG_CONFLICTS && !p2) |
2939 | p2 = -SYSTEMSOLVABLE; | |
2940 | if (type == SOLVER_RULE_PKG_SAME_NAME) | |
2941 | { | |
ea3d1f2e | 2942 | p = op; /* we normalize same name order */ |
b0dda2ba MS |
2943 | p2 = op2; |
2944 | } | |
77c11828 | 2945 | } |
ea3d1f2e MS |
2946 | /* yep, rule matches. record info */ |
2947 | queue_push(solv->ruleinfoq, type); | |
2948 | queue_push(solv->ruleinfoq, p < 0 ? -p : 0); | |
2949 | queue_push(solv->ruleinfoq, p2 < 0 ? -p2 : 0); | |
2950 | queue_push(solv->ruleinfoq, dep); | |
77c11828 MS |
2951 | } |
2952 | ||
2953 | static int | |
2954 | solver_allruleinfos_cmp(const void *ap, const void *bp, void *dp) | |
2955 | { | |
2956 | const Id *a = ap, *b = bp; | |
2957 | int r; | |
2958 | ||
2959 | r = a[0] - b[0]; | |
2960 | if (r) | |
2961 | return r; | |
2962 | r = a[1] - b[1]; | |
2963 | if (r) | |
2964 | return r; | |
2965 | r = a[2] - b[2]; | |
2966 | if (r) | |
2967 | return r; | |
2968 | r = a[3] - b[3]; | |
2969 | if (r) | |
2970 | return r; | |
2971 | return 0; | |
2972 | } | |
2973 | ||
f09c993f | 2974 | static void |
2b48a178 | 2975 | getpkgruleinfos(Solver *solv, Rule *r, Queue *rq) |
f09c993f MS |
2976 | { |
2977 | Pool *pool = solv->pool; | |
5b07accd | 2978 | Id l, pp; |
f09c993f MS |
2979 | if (r->p >= 0) |
2980 | return; | |
2981 | queue_push(rq, r - solv->rules); /* push the rule we're interested in */ | |
2982 | solv->ruleinfoq = rq; | |
5b07accd | 2983 | FOR_RULELITERALS(l, pp, r) |
f09c993f | 2984 | { |
5b07accd MS |
2985 | if (l >= 0) |
2986 | break; | |
2b48a178 | 2987 | solver_addpkgrulesforsolvable(solv, pool->solvables - l, 0); |
f09c993f | 2988 | } |
5b07accd MS |
2989 | #ifdef ENABLE_LINKED_PKGS |
2990 | FOR_RULELITERALS(l, pp, r) | |
f09c993f | 2991 | { |
456e342d MS |
2992 | if (l < 0) |
2993 | { | |
2994 | if (l == r->p) | |
2995 | continue; | |
2996 | break; | |
2997 | } | |
5b07accd | 2998 | if (!strchr(pool_id2str(pool, pool->solvables[l].name), ':') || !has_package_link(pool, pool->solvables + l)) |
f09c993f | 2999 | break; |
5b07accd | 3000 | add_package_link(solv, pool->solvables + l, 0, 0); |
f09c993f | 3001 | } |
e5fff4bc | 3002 | #endif |
f09c993f MS |
3003 | solv->ruleinfoq = 0; |
3004 | queue_shift(rq); | |
3005 | } | |
3006 | ||
77c11828 MS |
3007 | int |
3008 | solver_allruleinfos(Solver *solv, Id rid, Queue *rq) | |
3009 | { | |
77c11828 MS |
3010 | Rule *r = solv->rules + rid; |
3011 | int i, j; | |
3012 | ||
3013 | queue_empty(rq); | |
2b48a178 | 3014 | if (rid <= 0 || rid >= solv->pkgrules_end) |
77c11828 MS |
3015 | { |
3016 | Id type, from, to, dep; | |
3017 | type = solver_ruleinfo(solv, rid, &from, &to, &dep); | |
3018 | queue_push(rq, type); | |
3019 | queue_push(rq, from); | |
3020 | queue_push(rq, to); | |
3021 | queue_push(rq, dep); | |
3022 | return 1; | |
3023 | } | |
2b48a178 | 3024 | getpkgruleinfos(solv, r, rq); |
77c11828 MS |
3025 | /* now sort & unify em */ |
3026 | if (!rq->count) | |
3027 | return 0; | |
09f29f70 | 3028 | solv_sort(rq->elements, rq->count / 4, 4 * sizeof(Id), solver_allruleinfos_cmp, 0); |
77c11828 MS |
3029 | /* throw out identical entries */ |
3030 | for (i = j = 0; i < rq->count; i += 4) | |
3031 | { | |
3032 | if (j) | |
3033 | { | |
2581c2d3 | 3034 | if (rq->elements[i] == rq->elements[j - 4] && |
77c11828 MS |
3035 | rq->elements[i + 1] == rq->elements[j - 3] && |
3036 | rq->elements[i + 2] == rq->elements[j - 2] && | |
3037 | rq->elements[i + 3] == rq->elements[j - 1]) | |
3038 | continue; | |
3039 | } | |
3040 | rq->elements[j++] = rq->elements[i]; | |
3041 | rq->elements[j++] = rq->elements[i + 1]; | |
3042 | rq->elements[j++] = rq->elements[i + 2]; | |
3043 | rq->elements[j++] = rq->elements[i + 3]; | |
3044 | } | |
3045 | rq->count = j; | |
3046 | return j / 4; | |
3047 | } | |
3048 | ||
3049 | SolverRuleinfo | |
3050 | solver_ruleinfo(Solver *solv, Id rid, Id *fromp, Id *top, Id *depp) | |
3051 | { | |
3052 | Pool *pool = solv->pool; | |
3053 | Rule *r = solv->rules + rid; | |
3054 | SolverRuleinfo type = SOLVER_RULE_UNKNOWN; | |
3055 | ||
3056 | if (fromp) | |
3057 | *fromp = 0; | |
3058 | if (top) | |
3059 | *top = 0; | |
3060 | if (depp) | |
3061 | *depp = 0; | |
2b48a178 | 3062 | if (rid > 0 && rid < solv->pkgrules_end) |
77c11828 MS |
3063 | { |
3064 | Queue rq; | |
3065 | int i; | |
3066 | ||
3067 | if (r->p >= 0) | |
2b48a178 | 3068 | return SOLVER_RULE_PKG; |
77c11828 MS |
3069 | if (fromp) |
3070 | *fromp = -r->p; | |
3071 | queue_init(&rq); | |
2b48a178 MS |
3072 | getpkgruleinfos(solv, r, &rq); |
3073 | type = SOLVER_RULE_PKG; | |
f09c993f | 3074 | for (i = 0; i < rq.count; i += 4) |
77c11828 MS |
3075 | { |
3076 | Id qt, qo, qp, qd; | |
3077 | qt = rq.elements[i]; | |
3078 | qp = rq.elements[i + 1]; | |
3079 | qo = rq.elements[i + 2]; | |
3080 | qd = rq.elements[i + 3]; | |
fc10f1d7 | 3081 | if (type == SOLVER_RULE_PKG || qt == SOLVER_RULE_PKG_SAME_NAME || type > qt) |
77c11828 MS |
3082 | { |
3083 | type = qt; | |
3084 | if (fromp) | |
3085 | *fromp = qp; | |
3086 | if (top) | |
3087 | *top = qo; | |
3088 | if (depp) | |
3089 | *depp = qd; | |
26fcfa71 MS |
3090 | if (qt == SOLVER_RULE_PKG_SAME_NAME) |
3091 | break; /* prefer SOLVER_RULE_PKG_SAME_NAME */ | |
77c11828 MS |
3092 | } |
3093 | } | |
3094 | queue_free(&rq); | |
3095 | return type; | |
3096 | } | |
3097 | if (rid >= solv->jobrules && rid < solv->jobrules_end) | |
3098 | { | |
3099 | Id jidx = solv->ruletojob.elements[rid - solv->jobrules]; | |
3100 | if (fromp) | |
3101 | *fromp = jidx; | |
3102 | if (top) | |
3103 | *top = solv->job.elements[jidx]; | |
3104 | if (depp) | |
3105 | *depp = solv->job.elements[jidx + 1]; | |
264d9fbb MS |
3106 | if ((r->d == 0 || r->d == -1) && r->w2 == 0 && r->p == -SYSTEMSOLVABLE) |
3107 | { | |
400d90ae MS |
3108 | Id how = solv->job.elements[jidx]; |
3109 | if ((how & (SOLVER_JOBMASK|SOLVER_SELECTMASK)) == (SOLVER_INSTALL|SOLVER_SOLVABLE_NAME)) | |
3110 | return SOLVER_RULE_JOB_UNKNOWN_PACKAGE; | |
3111 | if ((how & (SOLVER_JOBMASK|SOLVER_SELECTMASK)) == (SOLVER_INSTALL|SOLVER_SOLVABLE_PROVIDES)) | |
264d9fbb | 3112 | return SOLVER_RULE_JOB_NOTHING_PROVIDES_DEP; |
400d90ae | 3113 | if ((how & (SOLVER_JOBMASK|SOLVER_SELECTMASK)) == (SOLVER_ERASE|SOLVER_SOLVABLE_NAME)) |
6d567dae | 3114 | return SOLVER_RULE_JOB_PROVIDED_BY_SYSTEM; |
400d90ae | 3115 | if ((how & (SOLVER_JOBMASK|SOLVER_SELECTMASK)) == (SOLVER_ERASE|SOLVER_SOLVABLE_PROVIDES)) |
6d567dae | 3116 | return SOLVER_RULE_JOB_PROVIDED_BY_SYSTEM; |
400d90ae | 3117 | return SOLVER_RULE_JOB_UNSUPPORTED; |
264d9fbb | 3118 | } |
77c11828 MS |
3119 | return SOLVER_RULE_JOB; |
3120 | } | |
3121 | if (rid >= solv->updaterules && rid < solv->updaterules_end) | |
3122 | { | |
3123 | if (fromp) | |
3124 | *fromp = solv->installed->start + (rid - solv->updaterules); | |
3125 | return SOLVER_RULE_UPDATE; | |
3126 | } | |
3127 | if (rid >= solv->featurerules && rid < solv->featurerules_end) | |
3128 | { | |
3129 | if (fromp) | |
3130 | *fromp = solv->installed->start + (rid - solv->featurerules); | |
3131 | return SOLVER_RULE_FEATURE; | |
3132 | } | |
3133 | if (rid >= solv->duprules && rid < solv->duprules_end) | |
3134 | { | |
3135 | if (fromp) | |
3136 | *fromp = -r->p; | |
3137 | if (depp) | |
3138 | *depp = pool->solvables[-r->p].name; | |
3139 | return SOLVER_RULE_DISTUPGRADE; | |
3140 | } | |
3141 | if (rid >= solv->infarchrules && rid < solv->infarchrules_end) | |
3142 | { | |
3143 | if (fromp) | |
3144 | *fromp = -r->p; | |
3145 | if (depp) | |
3146 | *depp = pool->solvables[-r->p].name; | |
3147 | return SOLVER_RULE_INFARCH; | |
3148 | } | |
96275a1c MS |
3149 | if (rid >= solv->bestrules && rid < solv->bestrules_end) |
3150 | { | |
a3059b47 | 3151 | /* > 0: the package we are updating */ |
178203fe MS |
3152 | if (fromp && solv->bestrules_info[rid - solv->bestrules] > 0) |
3153 | *fromp = solv->bestrules_info[rid - solv->bestrules]; | |
a3059b47 MS |
3154 | /* < 0: the job rule */ |
3155 | if (top && solv->bestrules_info[rid - solv->bestrules] < 0) | |
3156 | *top = -solv->bestrules_info[rid - solv->bestrules]; | |
96275a1c MS |
3157 | return SOLVER_RULE_BEST; |
3158 | } | |
99e2d678 MS |
3159 | if (rid >= solv->yumobsrules && rid < solv->yumobsrules_end) |
3160 | { | |
3161 | if (fromp) | |
3162 | *fromp = -r->p; | |
3163 | if (top) | |
3164 | { | |
3165 | /* first solvable is enough, we just need it for the name */ | |
3166 | if (!r->d || r->d == -1) | |
3167 | *top = r->w2; | |
3168 | else | |
3169 | *top = pool->whatprovidesdata[r->d < 0 ? -r->d : r->d]; | |
3170 | } | |
3171 | if (depp) | |
3172 | *depp = solv->yumobsrules_info[rid - solv->yumobsrules]; | |
3173 | return SOLVER_RULE_YUMOBS; | |
3174 | } | |
4120051b MS |
3175 | if (rid >= solv->blackrules && rid < solv->blackrules_end) |
3176 | { | |
3177 | if (fromp) | |
3178 | *fromp = -r->p; | |
3179 | return SOLVER_RULE_BLACK; | |
3180 | } | |
91be77ea AD |
3181 | if (rid >= solv->strictrepopriorules && rid < solv->strictrepopriorules_end) |
3182 | { | |
3183 | if (fromp) | |
3184 | *fromp = -r->p; | |
3185 | return SOLVER_RULE_STRICT_REPO_PRIORITY; | |
3186 | } | |
cce95701 | 3187 | if (rid >= solv->choicerules && rid < solv->choicerules_end) |
a3059b47 MS |
3188 | { |
3189 | if (solv->choicerules_info && fromp) | |
3190 | *fromp = solv->choicerules_info[rid - solv->choicerules]; | |
3191 | return SOLVER_RULE_CHOICE; | |
3192 | } | |
841ea42d | 3193 | if (rid >= solv->recommendsrules && rid < solv->recommendsrules_end) |
a3059b47 | 3194 | { |
e10d75ee MS |
3195 | if (solv->recommendsrules_info && fromp) |
3196 | *fromp = solv->recommendsrules_info[rid - solv->recommendsrules]; | |
a3059b47 MS |
3197 | return SOLVER_RULE_RECOMMENDS; |
3198 | } | |
77c11828 | 3199 | if (rid >= solv->learntrules) |
841ea42d | 3200 | return SOLVER_RULE_LEARNT; |
77c11828 MS |
3201 | return SOLVER_RULE_UNKNOWN; |
3202 | } | |
3203 | ||
4c6908cd MS |
3204 | SolverRuleinfo |
3205 | solver_ruleclass(Solver *solv, Id rid) | |
3206 | { | |
3207 | if (rid <= 0) | |
3208 | return SOLVER_RULE_UNKNOWN; | |
2b48a178 MS |
3209 | if (rid > 0 && rid < solv->pkgrules_end) |
3210 | return SOLVER_RULE_PKG; | |
4c6908cd MS |
3211 | if (rid >= solv->jobrules && rid < solv->jobrules_end) |
3212 | return SOLVER_RULE_JOB; | |
3213 | if (rid >= solv->updaterules && rid < solv->updaterules_end) | |
3214 | return SOLVER_RULE_UPDATE; | |
3215 | if (rid >= solv->featurerules && rid < solv->featurerules_end) | |
3216 | return SOLVER_RULE_FEATURE; | |
3217 | if (rid >= solv->duprules && rid < solv->duprules_end) | |
3218 | return SOLVER_RULE_DISTUPGRADE; | |
3219 | if (rid >= solv->infarchrules && rid < solv->infarchrules_end) | |
3220 | return SOLVER_RULE_INFARCH; | |
96275a1c MS |
3221 | if (rid >= solv->bestrules && rid < solv->bestrules_end) |
3222 | return SOLVER_RULE_BEST; | |
99e2d678 MS |
3223 | if (rid >= solv->yumobsrules && rid < solv->yumobsrules_end) |
3224 | return SOLVER_RULE_YUMOBS; | |
4120051b MS |
3225 | if (rid >= solv->blackrules && rid < solv->blackrules_end) |
3226 | return SOLVER_RULE_BLACK; | |
4c6908cd MS |
3227 | if (rid >= solv->choicerules && rid < solv->choicerules_end) |
3228 | return SOLVER_RULE_CHOICE; | |
841ea42d MS |
3229 | if (rid >= solv->recommendsrules && rid < solv->recommendsrules_end) |
3230 | return SOLVER_RULE_RECOMMENDS; | |
91be77ea AD |
3231 | if (rid >= solv->strictrepopriorules && rid < solv->strictrepopriorules_end) |
3232 | return SOLVER_RULE_STRICT_REPO_PRIORITY; | |
c872fe4d | 3233 | if (rid >= solv->learntrules && rid < solv->nrules) |
4c6908cd MS |
3234 | return SOLVER_RULE_LEARNT; |
3235 | return SOLVER_RULE_UNKNOWN; | |
3236 | } | |
3237 | ||
76fb56c0 MS |
3238 | void |
3239 | solver_ruleliterals(Solver *solv, Id rid, Queue *q) | |
3240 | { | |
3241 | Pool *pool = solv->pool; | |
9eaaeb1e | 3242 | Id p, pp; |
76fb56c0 MS |
3243 | Rule *r; |
3244 | ||
3245 | queue_empty(q); | |
3246 | r = solv->rules + rid; | |
3247 | FOR_RULELITERALS(p, pp, r) | |
3248 | if (p != -SYSTEMSOLVABLE) | |
3249 | queue_push(q, p); | |
3250 | if (!q->count) | |
3251 | queue_push(q, -SYSTEMSOLVABLE); /* hmm, better to return an empty result? */ | |
3252 | } | |
3253 | ||
3254 | int | |
3255 | solver_rule2jobidx(Solver *solv, Id rid) | |
3256 | { | |
3257 | if (rid < solv->jobrules || rid >= solv->jobrules_end) | |
3258 | return 0; | |
3259 | return solv->ruletojob.elements[rid - solv->jobrules] + 1; | |
3260 | } | |
3261 | ||
b3ff8425 | 3262 | /* job rule introspection */ |
76fb56c0 MS |
3263 | Id |
3264 | solver_rule2job(Solver *solv, Id rid, Id *whatp) | |
3265 | { | |
3266 | int idx; | |
3267 | if (rid < solv->jobrules || rid >= solv->jobrules_end) | |
3268 | { | |
3269 | if (whatp) | |
3270 | *whatp = 0; | |
3271 | return 0; | |
3272 | } | |
3273 | idx = solv->ruletojob.elements[rid - solv->jobrules]; | |
3274 | if (whatp) | |
3275 | *whatp = solv->job.elements[idx + 1]; | |
3276 | return solv->job.elements[idx]; | |
3277 | } | |
3278 | ||
b3ff8425 | 3279 | /* update/feature rule introspection */ |
6861611d MS |
3280 | Id |
3281 | solver_rule2solvable(Solver *solv, Id rid) | |
3282 | { | |
d35c4524 MS |
3283 | if (rid >= solv->updaterules && rid < solv->updaterules_end && solv->installed) |
3284 | return solv->installed->start + (rid - solv->updaterules); | |
3285 | if (rid >= solv->featurerules && rid < solv->featurerules_end && solv->installed) | |
3286 | return solv->installed->start + (rid - solv->featurerules); | |
6861611d MS |
3287 | return 0; |
3288 | } | |
3289 | ||
f00efbde MS |
3290 | Id |
3291 | solver_rule2pkgrule(Solver *solv, Id rid) | |
3292 | { | |
3293 | if (rid >= solv->choicerules && rid < solv->choicerules_end) | |
178203fe | 3294 | return solv->choicerules_info[rid - solv->choicerules]; |
841ea42d MS |
3295 | if (rid >= solv->recommendsrules && rid < solv->recommendsrules_end) |
3296 | return solv->recommendsrules_info[rid - solv->recommendsrules]; | |
f00efbde MS |
3297 | return 0; |
3298 | } | |
3299 | ||
b3ff8425 MS |
3300 | static void |
3301 | solver_rule2rules_rec(Solver *solv, Id rid, Queue *q, Map *seen) | |
3302 | { | |
3303 | int i; | |
3304 | Id rid2; | |
3305 | ||
3306 | if (seen) | |
3307 | MAPSET(seen, rid); | |
3308 | for (i = solv->learnt_why.elements[rid - solv->learntrules]; (rid2 = solv->learnt_pool.elements[i]) != 0; i++) | |
3309 | { | |
3310 | if (seen) | |
3311 | { | |
3312 | if (MAPTST(seen, rid2)) | |
3313 | continue; | |
3314 | if (rid2 >= solv->learntrules) | |
3315 | solver_rule2rules_rec(solv, rid2, q, seen); | |
3316 | continue; | |
3317 | } | |
3318 | queue_push(q, rid2); | |
3319 | } | |
3320 | } | |
3321 | ||
3322 | /* learnt rule introspection */ | |
3323 | void | |
3324 | solver_rule2rules(Solver *solv, Id rid, Queue *q, int recursive) | |
3325 | { | |
3326 | queue_empty(q); | |
3327 | if (rid < solv->learntrules || rid >= solv->nrules) | |
3328 | return; | |
3329 | if (recursive) | |
3330 | { | |
3331 | Map seen; | |
3332 | map_init(&seen, solv->nrules); | |
3333 | solver_rule2rules_rec(solv, rid, q, &seen); | |
3334 | map_free(&seen); | |
3335 | } | |
3336 | else | |
3337 | solver_rule2rules_rec(solv, rid, q, 0); | |
3338 | } | |
3339 | ||
3340 | ||
0203da27 | 3341 | /* check if the newest versions of pi still provides the dependency we're looking for */ |
1da9bef8 MS |
3342 | /* pi: installed package |
3343 | * r: rule for the dependency | |
3344 | * m: map with all positive elements of r | |
3345 | * return 0: at least one provider | |
3346 | * return 1: the newest versions do not provide the dependency | |
3347 | */ | |
0203da27 | 3348 | static int |
ac0801c9 | 3349 | solver_choicerulecheck(Solver *solv, Id pi, Rule *r, Map *m, Queue *q) |
0203da27 MS |
3350 | { |
3351 | Pool *pool = solv->pool; | |
3352 | Rule *ur; | |
ac0801c9 | 3353 | Id p, pp; |
0203da27 MS |
3354 | int i; |
3355 | ||
ac0801c9 MS |
3356 | if (!q->count || q->elements[0] != pi) |
3357 | { | |
3358 | if (q->count) | |
3359 | queue_empty(q); | |
3360 | ur = solv->rules + solv->updaterules + (pi - pool->installed->start); | |
3361 | if (!ur->p) | |
3362 | ur = solv->rules + solv->featurerules + (pi - pool->installed->start); | |
3363 | if (!ur->p) | |
3364 | return 0; | |
3365 | queue_push2(q, pi, 0); | |
3366 | FOR_RULELITERALS(p, pp, ur) | |
3367 | if (p > 0) | |
3368 | queue_push(q, p); | |
3369 | } | |
3370 | if (q->count == 2) | |
3371 | return 1; | |
3372 | if (q->count == 3) | |
3373 | { | |
3374 | p = q->elements[2]; | |
3375 | return MAPTST(m, p) ? 0 : 1; | |
3376 | } | |
3377 | if (!q->elements[1]) | |
3378 | { | |
3379 | for (i = 2; i < q->count; i++) | |
3380 | if (!MAPTST(m, q->elements[i])) | |
3381 | break; | |
3382 | if (i == q->count) | |
3383 | return 0; /* all provide it, no need to filter */ | |
3384 | /* some don't provide it, have to filter */ | |
3385 | queue_deleten(q, 0, 2); | |
3386 | policy_filter_unwanted(solv, q, POLICY_MODE_CHOOSE); | |
3387 | queue_unshift(q, 1); /* filter mark */ | |
3388 | queue_unshift(q, pi); | |
3389 | } | |
3390 | for (i = 2; i < q->count; i++) | |
3391 | if (MAPTST(m, q->elements[i])) | |
3392 | return 0; /* at least one provides it */ | |
3393 | return 1; /* none of the new packages provided it */ | |
0203da27 MS |
3394 | } |
3395 | ||
fe06d76e MS |
3396 | static Id |
3397 | choicerule_find_installed(Pool *pool, Id p) | |
3398 | { | |
3399 | Solvable *s = pool->solvables + p; | |
3400 | Id p2, pp2; | |
3401 | ||
3402 | if (!s->repo) | |
3403 | return 0; | |
3404 | if (s->repo == pool->installed) | |
3405 | return p; | |
3406 | FOR_PROVIDES(p2, pp2, s->name) | |
3407 | { | |
3408 | Solvable *s2 = pool->solvables + p2; | |
3409 | if (s2->repo != pool->installed) | |
3410 | continue; | |
3411 | if (!pool->implicitobsoleteusesprovides && s->name != s2->name) | |
3412 | continue; | |
3413 | if (pool->implicitobsoleteusescolors && !pool_colormatch(pool, s, s2)) | |
3414 | continue; | |
3415 | return p2; | |
3416 | } | |
3417 | if (s->obsoletes) | |
3418 | { | |
3419 | Id obs, *obsp = s->repo->idarraydata + s->obsoletes; | |
3420 | while ((obs = *obsp++) != 0) | |
3421 | { | |
3422 | FOR_PROVIDES(p2, pp2, obs) | |
3423 | { | |
3424 | Solvable *s2 = pool->solvables + p2; | |
3425 | if (s2->repo != pool->installed) | |
3426 | continue; | |
3427 | if (!pool->obsoleteusesprovides && !pool_match_nevr(pool, pool->solvables + p2, obs)) | |
3428 | continue; | |
3429 | if (pool->obsoleteusescolors && !pool_colormatch(pool, s, s2)) | |
3430 | continue; | |
3431 | return p2; | |
3432 | } | |
3433 | } | |
3434 | } | |
3435 | return 0; | |
3436 | } | |
3437 | ||
cce95701 | 3438 | void |
6873aab5 | 3439 | solver_addchoicerules(Solver *solv) |
cce95701 MS |
3440 | { |
3441 | Pool *pool = solv->pool; | |
8dd1a068 | 3442 | Map m, mneg; |
cce95701 | 3443 | Rule *r; |
1da9bef8 | 3444 | Queue q, qi, qcheck, infoq; |
a32baa86 | 3445 | int i, j, rid, havechoice, negcnt; |
fe06d76e MS |
3446 | Id p, d, pp, p2; |
3447 | Solvable *s; | |
a68828a0 MS |
3448 | Id lastaddedp, lastaddedd; |
3449 | int lastaddedcnt; | |
0203da27 | 3450 | unsigned int now; |
1da9bef8 | 3451 | int isinstalled; |
cce95701 MS |
3452 | |
3453 | solv->choicerules = solv->nrules; | |
3454 | if (!pool->installed) | |
3455 | { | |
3456 | solv->choicerules_end = solv->nrules; | |
3457 | return; | |
3458 | } | |
0203da27 | 3459 | now = solv_timems(0); |
cce95701 | 3460 | queue_init(&q); |
38153ed6 | 3461 | queue_init(&qi); |
ac0801c9 | 3462 | queue_init(&qcheck); |
178203fe | 3463 | queue_init(&infoq); |
38153ed6 | 3464 | map_init(&m, pool->nsolvables); |
8dd1a068 MS |
3465 | map_init(&mneg, pool->nsolvables); |
3466 | /* set up negative assertion map from infarch and dup rules */ | |
3467 | for (rid = solv->infarchrules, r = solv->rules + rid; rid < solv->infarchrules_end; rid++, r++) | |
3468 | if (r->p < 0 && !r->w2 && (r->d == 0 || r->d == -1)) | |
3469 | MAPSET(&mneg, -r->p); | |
3470 | for (rid = solv->duprules, r = solv->rules + rid; rid < solv->duprules_end; rid++, r++) | |
3471 | if (r->p < 0 && !r->w2 && (r->d == 0 || r->d == -1)) | |
3472 | MAPSET(&mneg, -r->p); | |
a68828a0 MS |
3473 | lastaddedp = 0; |
3474 | lastaddedd = 0; | |
3475 | lastaddedcnt = 0; | |
2b48a178 | 3476 | for (rid = 1; rid < solv->pkgrules_end ; rid++) |
cce95701 MS |
3477 | { |
3478 | r = solv->rules + rid; | |
006013eb | 3479 | if (r->p >= 0 || ((r->d == 0 || r->d == -1) && r->w2 <= 0)) |
cce95701 | 3480 | continue; /* only look at requires rules */ |
34fd443d | 3481 | /* solver_printrule(solv, SOLV_DEBUG_RESULT, r); */ |
38153ed6 | 3482 | queue_empty(&qi); |
cce95701 | 3483 | havechoice = 0; |
1da9bef8 | 3484 | isinstalled = 0; |
cce95701 MS |
3485 | FOR_RULELITERALS(p, pp, r) |
3486 | { | |
3487 | if (p < 0) | |
1da9bef8 MS |
3488 | { |
3489 | Solvable *s = pool->solvables - p; | |
3490 | p2 = s->repo == pool->installed ? -p : 0; | |
3491 | if (p2) | |
3492 | { | |
3493 | if (!(solv->updatemap_all || (solv->updatemap.size && MAPTST(&solv->updatemap, p2 - solv->installed->start)))) | |
3494 | isinstalled = 1; | |
3495 | } | |
3496 | continue; | |
3497 | } | |
cce95701 MS |
3498 | s = pool->solvables + p; |
3499 | if (!s->repo) | |
3500 | continue; | |
3501 | if (s->repo == pool->installed) | |
3502 | { | |
894382f0 | 3503 | queue_push2(&qi, p, p); |
cce95701 MS |
3504 | continue; |
3505 | } | |
fe06d76e MS |
3506 | /* find an installed package p2 that we can update/downgrade to p */ |
3507 | p2 = choicerule_find_installed(pool, p); | |
cce95701 MS |
3508 | if (p2) |
3509 | { | |
efdbe25b | 3510 | if (MAPTST(&mneg, p)) |
8dd1a068 | 3511 | continue; |
fe06d76e | 3512 | if (policy_is_illegal(solv, pool->solvables + p2, s, 0)) |
0203da27 | 3513 | continue; |
0203da27 | 3514 | queue_push2(&qi, p2, p); |
cce95701 MS |
3515 | continue; |
3516 | } | |
efdbe25b | 3517 | /* package p is independent of the installed ones */ |
cce95701 MS |
3518 | havechoice = 1; |
3519 | } | |
894382f0 MS |
3520 | #if 0 |
3521 | printf("havechoice: %d qcount %d qicount %d\n", havechoice, q.count, qi.count); | |
3522 | #endif | |
1da9bef8 | 3523 | if (!havechoice || !qi.count) |
cce95701 | 3524 | continue; /* no choice */ |
38153ed6 | 3525 | |
38153ed6 MS |
3526 | FOR_RULELITERALS(p, pp, r) |
3527 | if (p > 0) | |
3528 | MAPSET(&m, p); | |
0203da27 | 3529 | |
1da9bef8 | 3530 | if (!isinstalled) |
894382f0 | 3531 | { |
1da9bef8 MS |
3532 | /* do extra checking for packages related to installed packages */ |
3533 | for (i = j = 0; i < qi.count; i += 2) | |
0203da27 | 3534 | { |
1da9bef8 MS |
3535 | p2 = qi.elements[i]; |
3536 | if (solv->updatemap_all || (solv->updatemap.size && MAPTST(&solv->updatemap, p2 - solv->installed->start))) | |
3537 | { | |
3538 | if (solver_choicerulecheck(solv, p2, r, &m, &qcheck)) | |
3539 | continue; | |
3540 | } | |
3541 | qi.elements[j++] = p2; | |
3542 | qi.elements[j++] = qi.elements[i + 1]; | |
0203da27 | 3543 | } |
1da9bef8 | 3544 | queue_truncate(&qi, j); |
0203da27 | 3545 | } |
ac0801c9 | 3546 | |
1da9bef8 | 3547 | if (!qi.count) |
0203da27 MS |
3548 | { |
3549 | FOR_RULELITERALS(p, pp, r) | |
3550 | if (p > 0) | |
3551 | MAPCLR(&m, p); | |
3552 | continue; | |
3553 | } | |
3554 | ||
1da9bef8 MS |
3555 | queue_empty(&q); |
3556 | /* split q from qi */ | |
3557 | for (i = j = 0; i < qi.count; i += 2) | |
3558 | { | |
3559 | queue_push(&q, qi.elements[i + 1]); | |
3560 | qi.elements[j++] = qi.elements[i]; | |
3561 | } | |
3562 | queue_truncate(&qi, j); | |
3563 | ||
0203da27 MS |
3564 | |
3565 | /* now check the update rules of the installed package. | |
3566 | * if all packages of the update rules are contained in | |
3567 | * the dependency rules, there's no need to set up the choice rule */ | |
38153ed6 MS |
3568 | for (i = 0; i < qi.count; i++) |
3569 | { | |
5b0d7883 | 3570 | Rule *ur; |
38153ed6 MS |
3571 | if (!qi.elements[i]) |
3572 | continue; | |
5b0d7883 | 3573 | ur = solv->rules + solv->updaterules + (qi.elements[i] - pool->installed->start); |
38153ed6 MS |
3574 | if (!ur->p) |
3575 | ur = solv->rules + solv->featurerules + (qi.elements[i] - pool->installed->start); | |
3576 | if (!ur->p) | |
3577 | continue; | |
3578 | FOR_RULELITERALS(p, pp, ur) | |
3579 | if (!MAPTST(&m, p)) | |
3580 | break; | |
3581 | if (p) | |
3582 | break; | |
1da9bef8 | 3583 | /* speed improvement: only check each package once */ |
38153ed6 MS |
3584 | for (j = i + 1; j < qi.count; j++) |
3585 | if (qi.elements[i] == qi.elements[j]) | |
3586 | qi.elements[j] = 0; | |
3587 | } | |
0203da27 | 3588 | /* empty map again */ |
a32baa86 | 3589 | negcnt = 0; |
0203da27 MS |
3590 | FOR_RULELITERALS(p, pp, r) |
3591 | if (p > 0) | |
3592 | MAPCLR(&m, p); | |
a32baa86 MS |
3593 | else |
3594 | negcnt++; | |
38153ed6 MS |
3595 | if (i == qi.count) |
3596 | { | |
3597 | #if 0 | |
3598 | printf("skipping choice "); | |
09f29f70 | 3599 | solver_printrule(solv, SOLV_DEBUG_RESULT, solv->rules + rid); |
38153ed6 MS |
3600 | #endif |
3601 | continue; | |
3602 | } | |
a32baa86 MS |
3603 | /* add neg elements to the front */ |
3604 | if (negcnt > 1) | |
3605 | { | |
3606 | i = 0; | |
3607 | FOR_RULELITERALS(p, pp, r) | |
3608 | if (p < 0 && p != r->p) | |
3609 | queue_insert(&q, i++, p); | |
3610 | } | |
a68828a0 MS |
3611 | /* don't add identical rules */ |
3612 | if (lastaddedp == r->p && lastaddedcnt == q.count) | |
3613 | { | |
3614 | for (i = 0; i < q.count; i++) | |
3615 | if (q.elements[i] != pool->whatprovidesdata[lastaddedd + i]) | |
3616 | break; | |
3617 | if (i == q.count) | |
3618 | continue; /* already added that one */ | |
3619 | } | |
cce95701 | 3620 | d = q.count ? pool_queuetowhatprovides(pool, &q) : 0; |
aa7796db | 3621 | |
a68828a0 MS |
3622 | lastaddedp = r->p; |
3623 | lastaddedd = d; | |
3624 | lastaddedcnt = q.count; | |
aa7796db | 3625 | |
ea3d1f2e | 3626 | solver_addrule(solv, r->p, 0, d); |
aa7796db | 3627 | queue_push(&solv->weakruleq, solv->nrules - 1); |
178203fe | 3628 | queue_push(&infoq, rid); |
39dfec97 MS |
3629 | #if 0 |
3630 | printf("OLD "); | |
09f29f70 | 3631 | solver_printrule(solv, SOLV_DEBUG_RESULT, solv->rules + rid); |
39dfec97 | 3632 | printf("WEAK CHOICE "); |
09f29f70 | 3633 | solver_printrule(solv, SOLV_DEBUG_RESULT, solv->rules + solv->nrules - 1); |
39dfec97 | 3634 | #endif |
cce95701 | 3635 | } |
178203fe MS |
3636 | if (infoq.count) |
3637 | solv->choicerules_info = solv_memdup2(infoq.elements, infoq.count, sizeof(Id)); | |
cce95701 | 3638 | queue_free(&q); |
38153ed6 | 3639 | queue_free(&qi); |
ac0801c9 | 3640 | queue_free(&qcheck); |
178203fe | 3641 | queue_free(&infoq); |
38153ed6 | 3642 | map_free(&m); |
8dd1a068 | 3643 | map_free(&mneg); |
cce95701 | 3644 | solv->choicerules_end = solv->nrules; |
0203da27 | 3645 | POOL_DEBUG(SOLV_DEBUG_STATS, "choice rule creation took %d ms\n", solv_timems(now)); |
cce95701 MS |
3646 | } |
3647 | ||
d39445e2 MS |
3648 | /* called when a choice rule needs to be disabled by analyze_unsolvable. |
3649 | * We also have to disable all other choice rules so that the best packages | |
3650 | * get picked */ | |
39dfec97 | 3651 | void |
b94940f4 | 3652 | solver_disablechoicerules(Solver *solv, Rule *r) |
39dfec97 | 3653 | { |
9eaaeb1e | 3654 | Id rid, p, pp; |
39dfec97 MS |
3655 | Pool *pool = solv->pool; |
3656 | Map m; | |
3657 | Rule *or; | |
3658 | ||
d39445e2 | 3659 | solver_disablerule(solv, r); |
178203fe | 3660 | or = solv->rules + solv->choicerules_info[(r - solv->rules) - solv->choicerules]; |
39dfec97 MS |
3661 | map_init(&m, pool->nsolvables); |
3662 | FOR_RULELITERALS(p, pp, or) | |
3663 | if (p > 0) | |
3664 | MAPSET(&m, p); | |
3665 | FOR_RULELITERALS(p, pp, r) | |
3666 | if (p > 0) | |
3667 | MAPCLR(&m, p); | |
3668 | for (rid = solv->choicerules; rid < solv->choicerules_end; rid++) | |
3669 | { | |
3670 | r = solv->rules + rid; | |
3671 | if (r->d < 0) | |
3672 | continue; | |
178203fe | 3673 | or = solv->rules + solv->choicerules_info[rid - solv->choicerules]; |
39dfec97 MS |
3674 | FOR_RULELITERALS(p, pp, or) |
3675 | if (p > 0 && MAPTST(&m, p)) | |
3676 | break; | |
3677 | if (p) | |
3678 | solver_disablerule(solv, r); | |
3679 | } | |
eb94d1c0 | 3680 | map_free(&m); |
39dfec97 MS |
3681 | } |
3682 | ||
6f46e0cf MS |
3683 | static void |
3684 | prune_to_update_targets(Solver *solv, Id *cp, Queue *q) | |
3685 | { | |
3686 | int i, j; | |
2581c2d3 | 3687 | Id p, *cp2; |
6f46e0cf | 3688 | for (i = j = 0; i < q->count; i++) |
2581c2d3 | 3689 | { |
6f46e0cf MS |
3690 | p = q->elements[i]; |
3691 | for (cp2 = cp; *cp2; cp2++) | |
3692 | if (*cp2 == p) | |
3693 | { | |
3694 | q->elements[j++] = p; | |
3695 | break; | |
3696 | } | |
3697 | } | |
3698 | queue_truncate(q, j); | |
3699 | } | |
3700 | ||
3701 | static void | |
3702 | prune_to_dup_packages(Solver *solv, Id p, Queue *q) | |
3703 | { | |
3704 | int i, j; | |
3705 | for (i = j = 0; i < q->count; i++) | |
3706 | { | |
3707 | Id p = q->elements[i]; | |
3708 | if (MAPTST(&solv->dupmap, p)) | |
3709 | q->elements[j++] = p; | |
3710 | } | |
3711 | queue_truncate(q, j); | |
3712 | } | |
3713 | ||
b717d12a MS |
3714 | static void |
3715 | prune_best_update(Solver *solv, Id p, Queue *q) | |
3716 | { | |
3717 | if (solv->update_targets && solv->update_targets->elements[p - solv->installed->start]) | |
3718 | prune_to_update_targets(solv, solv->update_targets->elements + solv->update_targets->elements[p - solv->installed->start], q); | |
3719 | if (solv->dupinvolvedmap.size && MAPTST(&solv->dupinvolvedmap, p)) | |
3720 | prune_to_dup_packages(solv, p, q); | |
3721 | /* select best packages, just look at prio and version */ | |
3722 | policy_filter_unwanted(solv, q, POLICY_MODE_RECOMMEND); | |
3723 | } | |
3724 | ||
bfdc347f MS |
3725 | static void |
3726 | prune_disabled(Pool *pool, Queue *q) | |
3727 | { | |
3728 | int i, j; | |
3729 | for (i = j = 0; i < q->count; i++) | |
3730 | { | |
3731 | Id p = q->elements[i]; | |
3732 | Solvable *s = pool->solvables + p; | |
3733 | if (s->repo && s->repo != pool->installed && !MAPTST(pool->considered, p)) | |
3734 | continue; | |
3735 | q->elements[j++] = p; | |
3736 | } | |
3737 | queue_truncate(q, j); | |
3738 | } | |
3739 | ||
96275a1c | 3740 | void |
b717d12a | 3741 | solver_addbestrules(Solver *solv, int havebestinstalljobs, int haslockjob) |
96275a1c MS |
3742 | { |
3743 | Pool *pool = solv->pool; | |
3744 | Id p; | |
3745 | Solvable *s; | |
3746 | Repo *installed = solv->installed; | |
3747 | Queue q, q2; | |
3748 | Rule *r; | |
178203fe | 3749 | Queue infoq; |
96275a1c | 3750 | int i, oldcnt; |
b717d12a | 3751 | Map *lockedmap = 0; |
96275a1c MS |
3752 | |
3753 | solv->bestrules = solv->nrules; | |
96275a1c MS |
3754 | queue_init(&q); |
3755 | queue_init(&q2); | |
178203fe | 3756 | queue_init(&infoq); |
96275a1c | 3757 | |
b717d12a MS |
3758 | if (haslockjob) |
3759 | { | |
3760 | int i; | |
3761 | lockedmap = solv_calloc(1, sizeof(Map)); | |
3762 | map_init(lockedmap, pool->nsolvables); | |
3763 | for (i = 0, r = solv->rules + solv->jobrules; i < solv->ruletojob.count; i++, r++) | |
3764 | { | |
3765 | if (r->w2 || (solv->job.elements[solv->ruletojob.elements[i]] & SOLVER_JOBMASK) != SOLVER_LOCK) | |
3766 | continue; | |
3767 | p = r->p > 0 ? r->p : -r->p; | |
3768 | MAPSET(lockedmap, p); | |
3769 | } | |
3770 | } | |
96275a1c MS |
3771 | if (havebestinstalljobs) |
3772 | { | |
3773 | for (i = 0; i < solv->job.count; i += 2) | |
3774 | { | |
1fda7cd6 MS |
3775 | Id how = solv->job.elements[i]; |
3776 | if ((how & (SOLVER_JOBMASK | SOLVER_FORCEBEST)) == (SOLVER_INSTALL | SOLVER_FORCEBEST)) | |
96275a1c | 3777 | { |
b717d12a | 3778 | int j, k; |
9eaaeb1e | 3779 | Id p2, pp2; |
96275a1c | 3780 | for (j = 0; j < solv->ruletojob.count; j++) |
1fda7cd6 MS |
3781 | { |
3782 | if (solv->ruletojob.elements[j] != i) | |
3783 | continue; | |
3784 | r = solv->rules + solv->jobrules + j; | |
3785 | queue_empty(&q); | |
3786 | queue_empty(&q2); | |
3787 | FOR_RULELITERALS(p2, pp2, r) | |
3788 | { | |
3789 | if (p2 > 0) | |
3790 | queue_push(&q, p2); | |
3791 | else if (p2 < 0) | |
3792 | queue_push(&q2, p2); | |
3793 | } | |
bfdc347f MS |
3794 | if (pool->considered && pool->whatprovideswithdisabled) |
3795 | prune_disabled(pool, &q); | |
1fda7cd6 MS |
3796 | if (!q.count) |
3797 | continue; /* orphaned */ | |
3798 | /* select best packages, just look at prio and version */ | |
3799 | oldcnt = q.count; | |
3800 | policy_filter_unwanted(solv, &q, POLICY_MODE_RECOMMEND); | |
3801 | if (q.count == oldcnt) | |
3802 | continue; /* nothing filtered */ | |
b717d12a MS |
3803 | if (lockedmap) |
3804 | { | |
bfdc347f MS |
3805 | queue_insertn(&q, 0, q2.count, q2.elements); |
3806 | queue_empty(&q2); | |
b717d12a MS |
3807 | FOR_RULELITERALS(p2, pp2, r) |
3808 | { | |
3809 | if (p2 <= 0) | |
3810 | continue; | |
3811 | if (installed && pool->solvables[p2].repo == installed) | |
3812 | { | |
3813 | if (MAPTST(lockedmap, p2)) | |
3814 | queue_pushunique(&q, p2); /* we always want that package */ | |
3815 | } | |
3816 | else if (MAPTST(lockedmap, p2)) | |
3817 | continue; | |
3818 | queue_push(&q2, p2); | |
3819 | } | |
bfdc347f MS |
3820 | if (pool->considered && pool->whatprovideswithdisabled) |
3821 | prune_disabled(pool, &q2); | |
b717d12a MS |
3822 | policy_filter_unwanted(solv, &q2, POLICY_MODE_RECOMMEND); |
3823 | for (k = 0; k < q2.count; k++) | |
3824 | queue_pushunique(&q, q2.elements[k]); | |
bfdc347f | 3825 | queue_empty(&q2); |
b717d12a | 3826 | } |
1fda7cd6 MS |
3827 | if (q2.count) |
3828 | queue_insertn(&q, 0, q2.count, q2.elements); | |
3829 | p2 = queue_shift(&q); | |
3830 | if (q.count < 2) | |
3831 | solver_addrule(solv, p2, q.count ? q.elements[0] : 0, 0); | |
3832 | else | |
3833 | solver_addrule(solv, p2, 0, pool_queuetowhatprovides(pool, &q)); | |
3834 | if ((how & SOLVER_WEAK) != 0) | |
3835 | queue_push(&solv->weakruleq, solv->nrules - 1); | |
178203fe | 3836 | queue_push(&infoq, -(solv->jobrules + j)); |
1fda7cd6 | 3837 | } |
96275a1c MS |
3838 | } |
3839 | } | |
3840 | } | |
1fda7cd6 | 3841 | solv->bestrules_up = solv->nrules; |
96275a1c | 3842 | |
d61d4df0 | 3843 | if (installed && (solv->bestupdatemap_all || solv->bestupdatemap.size)) |
96275a1c | 3844 | { |
22623468 MS |
3845 | Map m; |
3846 | ||
3847 | if (solv->allowuninstall || solv->allowuninstall_all || solv->allowuninstallmap.size) | |
3848 | map_init(&m, pool->nsolvables); | |
3849 | else | |
3850 | map_init(&m, 0); | |
96275a1c MS |
3851 | FOR_REPO_SOLVABLES(installed, p, s) |
3852 | { | |
9eaaeb1e | 3853 | Id d, p2, pp2; |
96275a1c MS |
3854 | if (!solv->updatemap_all && (!solv->updatemap.size || !MAPTST(&solv->updatemap, p - installed->start))) |
3855 | continue; | |
3856 | if (!solv->bestupdatemap_all && (!solv->bestupdatemap.size || !MAPTST(&solv->bestupdatemap, p - installed->start))) | |
3857 | continue; | |
3858 | queue_empty(&q); | |
3859 | if (solv->bestobeypolicy) | |
3860 | r = solv->rules + solv->updaterules + (p - installed->start); | |
3861 | else | |
3862 | { | |
3863 | r = solv->rules + solv->featurerules + (p - installed->start); | |
3864 | if (!r->p) /* identical to update rule? */ | |
3865 | r = solv->rules + solv->updaterules + (p - installed->start); | |
3866 | } | |
8c000d8c | 3867 | if (solv->specialupdaters && (d = solv->specialupdaters[p - installed->start]) != 0 && r == solv->rules + solv->updaterules + (p - installed->start)) |
96275a1c | 3868 | { |
8c000d8c | 3869 | /* need to check specialupdaters */ |
96275a1c MS |
3870 | if (r->p == p) /* be careful with the dup case */ |
3871 | queue_push(&q, p); | |
3872 | while ((p2 = pool->whatprovidesdata[d++]) != 0) | |
3873 | queue_push(&q, p2); | |
3874 | } | |
3875 | else | |
3876 | { | |
3877 | FOR_RULELITERALS(p2, pp2, r) | |
3878 | if (p2 > 0) | |
3879 | queue_push(&q, p2); | |
3880 | } | |
b717d12a MS |
3881 | if (lockedmap) |
3882 | { | |
3883 | queue_empty(&q2); | |
3884 | queue_insertn(&q2, 0, q.count, q.elements); | |
3885 | } | |
3886 | prune_best_update(solv, p, &q); | |
96275a1c MS |
3887 | if (!q.count) |
3888 | continue; /* orphaned */ | |
b717d12a MS |
3889 | if (lockedmap) |
3890 | { | |
3891 | int j; | |
3892 | /* always ok to keep installed locked packages */ | |
3893 | if (MAPTST(lockedmap, p)) | |
3894 | queue_pushunique(&q2, p); | |
3895 | for (j = 0; j < q2.count; j++) | |
3896 | { | |
3897 | Id p2 = q2.elements[j]; | |
3898 | if (pool->solvables[p2].repo == installed && MAPTST(lockedmap, p2)) | |
3899 | queue_pushunique(&q, p2); | |
3900 | } | |
3901 | /* filter out locked packages */ | |
3902 | for (i = j = 0; j < q2.count; j++) | |
3903 | { | |
3904 | Id p2 = q2.elements[j]; | |
3905 | if (pool->solvables[p2].repo == installed || !MAPTST(lockedmap, p2)) | |
3906 | q2.elements[i++] = p2; | |
3907 | } | |
3908 | queue_truncate(&q2, i); | |
3909 | prune_best_update(solv, p, &q2); | |
3910 | for (j = 0; j < q2.count; j++) | |
3911 | queue_pushunique(&q, q2.elements[j]); | |
3912 | } | |
96275a1c MS |
3913 | if (solv->bestobeypolicy) |
3914 | { | |
3915 | /* also filter the best of the feature rule packages and add them */ | |
3916 | r = solv->rules + solv->featurerules + (p - installed->start); | |
3917 | if (r->p) | |
3918 | { | |
3919 | int j; | |
3920 | queue_empty(&q2); | |
3921 | FOR_RULELITERALS(p2, pp2, r) | |
3922 | if (p2 > 0) | |
3923 | queue_push(&q2, p2); | |
b717d12a | 3924 | prune_best_update(solv, p, &q2); |
96275a1c MS |
3925 | for (j = 0; j < q2.count; j++) |
3926 | queue_pushunique(&q, q2.elements[j]); | |
b717d12a MS |
3927 | if (lockedmap) |
3928 | { | |
3929 | queue_empty(&q2); | |
3930 | FOR_RULELITERALS(p2, pp2, r) | |
3931 | if (p2 > 0) | |
3932 | if (pool->solvables[p2].repo == installed || !MAPTST(lockedmap, p2)) | |
3933 | queue_push(&q2, p2); | |
3934 | prune_best_update(solv, p, &q2); | |
3935 | for (j = 0; j < q2.count; j++) | |
3936 | queue_pushunique(&q, q2.elements[j]); | |
3937 | } | |
96275a1c MS |
3938 | } |
3939 | } | |
22623468 MS |
3940 | if (solv->allowuninstall || solv->allowuninstall_all || (solv->allowuninstallmap.size && MAPTST(&solv->allowuninstallmap, p - installed->start))) |
3941 | { | |
3942 | /* package is flagged both for allowuninstall and best, add negative rules */ | |
668e2495 | 3943 | d = q.count == 1 ? q.elements[0] : -pool_queuetowhatprovides(pool, &q); |
22623468 MS |
3944 | for (i = 0; i < q.count; i++) |
3945 | MAPSET(&m, q.elements[i]); | |
3946 | r = solv->rules + solv->featurerules + (p - installed->start); | |
3947 | if (!r->p) /* identical to update rule? */ | |
3948 | r = solv->rules + solv->updaterules + (p - installed->start); | |
3949 | FOR_RULELITERALS(p2, pp2, r) | |
3950 | { | |
3951 | if (MAPTST(&m, p2)) | |
3952 | continue; | |
668e2495 MS |
3953 | if (d >= 0) |
3954 | solver_addrule(solv, -p2, d, 0); | |
3955 | else | |
3956 | solver_addrule(solv, -p2, 0, -d); | |
178203fe | 3957 | queue_push(&infoq, p); |
22623468 MS |
3958 | } |
3959 | for (i = 0; i < q.count; i++) | |
3960 | MAPCLR(&m, q.elements[i]); | |
3961 | continue; | |
3962 | } | |
96275a1c | 3963 | p2 = queue_shift(&q); |
b0dda2ba | 3964 | if (q.count < 2) |
ea3d1f2e | 3965 | solver_addrule(solv, p2, q.count ? q.elements[0] : 0, 0); |
b0dda2ba | 3966 | else |
ea3d1f2e | 3967 | solver_addrule(solv, p2, 0, pool_queuetowhatprovides(pool, &q)); |
178203fe | 3968 | queue_push(&infoq, p); |
96275a1c | 3969 | } |
22623468 | 3970 | map_free(&m); |
96275a1c | 3971 | } |
178203fe MS |
3972 | if (infoq.count) |
3973 | solv->bestrules_info = solv_memdup2(infoq.elements, infoq.count, sizeof(Id)); | |
96275a1c MS |
3974 | solv->bestrules_end = solv->nrules; |
3975 | queue_free(&q); | |
3976 | queue_free(&q2); | |
178203fe | 3977 | queue_free(&infoq); |
b717d12a MS |
3978 | if (lockedmap) |
3979 | { | |
3980 | map_free(lockedmap); | |
3981 | solv_free(lockedmap); | |
3982 | } | |
96275a1c MS |
3983 | } |
3984 | ||
99e2d678 MS |
3985 | |
3986 | ||
3987 | ||
3988 | /* yumobs rule handling */ | |
a7101c56 MS |
3989 | /* note that we use pool->obsoleteusescolors || pool->implicitobsoleteusescolors |
3990 | * like in policy_findupdatepackages */ | |
99e2d678 MS |
3991 | |
3992 | static void | |
3993 | find_obsolete_group(Solver *solv, Id obs, Queue *q) | |
3994 | { | |
3995 | Pool *pool = solv->pool; | |
3996 | Queue qn; | |
3997 | Id p2, pp2, op, *opp, opp2; | |
3998 | int i, j, qnc, ncnt; | |
3999 | ||
4000 | queue_empty(q); | |
4001 | FOR_PROVIDES(p2, pp2, obs) | |
4002 | { | |
4003 | Solvable *s2 = pool->solvables + p2; | |
4004 | if (s2->repo != pool->installed) | |
4005 | continue; | |
4006 | if (!pool->obsoleteusesprovides && !pool_match_nevr(pool, pool->solvables + p2, obs)) | |
4007 | continue; | |
4008 | /* we obsolete installed package s2 with obs. now find all other packages that have the same dep */ | |
4009 | for (opp = solv->obsoletes_data + solv->obsoletes[p2 - solv->installed->start]; (op = *opp++) != 0;) | |
4010 | { | |
4011 | Solvable *os = pool->solvables + op; | |
4012 | Id obs2, *obsp2; | |
4013 | if (!os->obsoletes) | |
4014 | continue; | |
a7101c56 | 4015 | if ((pool->obsoleteusescolors || pool->implicitobsoleteusescolors) && !pool_colormatch(pool, s2, os)) |
99e2d678 | 4016 | continue; |
d39445e2 | 4017 | obsp2 = os->repo->idarraydata + os->obsoletes; |
99e2d678 MS |
4018 | while ((obs2 = *obsp2++) != 0) |
4019 | if (obs2 == obs) | |
4020 | break; | |
4021 | if (obs2) | |
4022 | queue_pushunique(q, op); | |
4023 | } | |
4024 | /* also search packages with the same name */ | |
4025 | FOR_PROVIDES(op, opp2, s2->name) | |
4026 | { | |
4027 | Solvable *os = pool->solvables + op; | |
4028 | Id obs2, *obsp2; | |
4029 | if (os->name != s2->name) | |
4030 | continue; | |
4031 | if (!os->obsoletes) | |
4032 | continue; | |
a7101c56 | 4033 | if ((pool->obsoleteusescolors || pool->implicitobsoleteusescolors) && !pool_colormatch(pool, s2, os)) |
99e2d678 | 4034 | continue; |
d39445e2 | 4035 | obsp2 = os->repo->idarraydata + os->obsoletes; |
99e2d678 MS |
4036 | while ((obs2 = *obsp2++) != 0) |
4037 | if (obs2 == obs) | |
4038 | break; | |
4039 | if (obs2) | |
4040 | queue_pushunique(q, op); | |
4041 | } | |
4042 | } | |
4043 | /* find names so that we can build groups */ | |
4044 | queue_init_clone(&qn, q); | |
c4552628 | 4045 | prune_to_best_version(pool, &qn); |
99e2d678 MS |
4046 | #if 0 |
4047 | { | |
4048 | for (i = 0; i < qn.count; i++) | |
4049 | printf(" + %s\n", pool_solvid2str(pool, qn.elements[i])); | |
4050 | } | |
4051 | #endif | |
4052 | /* filter into name groups */ | |
4053 | qnc = qn.count; | |
4054 | if (qnc == 1) | |
4055 | { | |
4056 | queue_free(&qn); | |
4057 | queue_empty(q); | |
4058 | return; | |
4059 | } | |
4060 | ncnt = 0; | |
4061 | for (i = 0; i < qnc; i++) | |
4062 | { | |
4063 | Id n = pool->solvables[qn.elements[i]].name; | |
4064 | int got = 0; | |
4065 | for (j = 0; j < q->count; j++) | |
4066 | { | |
4067 | Id p = q->elements[j]; | |
4068 | if (pool->solvables[p].name == n) | |
4069 | { | |
4070 | queue_push(&qn, p); | |
4071 | got = 1; | |
4072 | } | |
4073 | } | |
4074 | if (got) | |
4075 | { | |
4076 | queue_push(&qn, 0); | |
4077 | ncnt++; | |
4078 | } | |
4079 | } | |
4080 | if (ncnt <= 1) | |
4081 | { | |
4082 | queue_empty(q); | |
4083 | } | |
4084 | else | |
4085 | { | |
4086 | queue_empty(q); | |
4087 | queue_insertn(q, 0, qn.count - qnc, qn.elements + qnc); | |
4088 | } | |
4089 | queue_free(&qn); | |
4090 | } | |
4091 | ||
4092 | void | |
4093 | solver_addyumobsrules(Solver *solv) | |
4094 | { | |
4095 | Pool *pool = solv->pool; | |
4096 | Repo *installed = solv->installed; | |
4097 | Id p, op, *opp; | |
4098 | Solvable *s; | |
178203fe | 4099 | Queue qo, qq, infoq; |
99e2d678 MS |
4100 | int i, j, k; |
4101 | unsigned int now; | |
4102 | ||
4103 | solv->yumobsrules = solv->nrules; | |
4104 | if (!installed || !solv->obsoletes) | |
4105 | { | |
4106 | solv->yumobsrules_end = solv->nrules; | |
4107 | return; | |
4108 | } | |
4109 | now = solv_timems(0); | |
4110 | queue_init(&qo); | |
4111 | FOR_REPO_SOLVABLES(installed, p, s) | |
4112 | { | |
4113 | if (!solv->obsoletes[p - installed->start]) | |
4114 | continue; | |
4115 | #if 0 | |
4116 | printf("checking yumobs for %s\n", pool_solvable2str(pool, s)); | |
4117 | #endif | |
99e2d678 MS |
4118 | for (opp = solv->obsoletes_data + solv->obsoletes[p - installed->start]; (op = *opp++) != 0;) |
4119 | { | |
4120 | Solvable *os = pool->solvables + op; | |
4121 | Id obs, *obsp = os->repo->idarraydata + os->obsoletes; | |
4122 | Id p2, pp2; | |
4123 | while ((obs = *obsp++) != 0) | |
4124 | { | |
4125 | FOR_PROVIDES(p2, pp2, obs) | |
4126 | { | |
4127 | Solvable *s2 = pool->solvables + p2; | |
4128 | if (s2->repo != installed) | |
4129 | continue; | |
4130 | if (!pool->obsoleteusesprovides && !pool_match_nevr(pool, pool->solvables + p2, obs)) | |
4131 | continue; | |
a7101c56 | 4132 | if ((pool->obsoleteusescolors || pool->implicitobsoleteusescolors) && !pool_colormatch(pool, s, s2)) |
99e2d678 MS |
4133 | continue; |
4134 | queue_pushunique(&qo, obs); | |
4135 | break; | |
4136 | } | |
4137 | } | |
4138 | } | |
4139 | } | |
4140 | if (!qo.count) | |
4141 | { | |
4142 | queue_free(&qo); | |
4143 | return; | |
4144 | } | |
178203fe | 4145 | queue_init(&infoq); |
99e2d678 MS |
4146 | queue_init(&qq); |
4147 | for (i = 0; i < qo.count; i++) | |
4148 | { | |
4149 | int group, groupk, groupstart; | |
4150 | queue_empty(&qq); | |
4151 | #if 0 | |
4152 | printf("investigating %s\n", pool_dep2str(pool, qo.elements[i])); | |
4153 | #endif | |
4154 | find_obsolete_group(solv, qo.elements[i], &qq); | |
4155 | #if 0 | |
4156 | printf("result:\n"); | |
4157 | for (j = 0; j < qq.count; j++) | |
4158 | if (qq.elements[j] == 0) | |
4159 | printf("---\n"); | |
4160 | else | |
4161 | printf("%s\n", pool_solvid2str(pool, qq.elements[j])); | |
4162 | #endif | |
d39445e2 | 4163 | |
99e2d678 MS |
4164 | if (!qq.count) |
4165 | continue; | |
e31dfa02 | 4166 | /* at least two groups, build rules */ |
99e2d678 MS |
4167 | group = 0; |
4168 | for (j = 0; j < qq.count; j++) | |
4169 | { | |
4170 | p = qq.elements[j]; | |
4171 | if (!p) | |
4172 | { | |
4173 | group++; | |
4174 | continue; | |
4175 | } | |
4176 | if (pool->solvables[p].repo == installed) | |
4177 | continue; | |
4178 | groupk = 0; | |
4179 | groupstart = 0; | |
4180 | for (k = 0; k < qq.count; k++) | |
4181 | { | |
4182 | Id pk = qq.elements[k]; | |
4183 | if (pk) | |
4184 | continue; | |
4185 | if (group != groupk && k > groupstart) | |
4186 | { | |
4187 | /* add the rule */ | |
b0dda2ba | 4188 | if (k - groupstart == 1) |
ea3d1f2e | 4189 | solver_addrule(solv, -p, qq.elements[groupstart], 0); |
b0dda2ba | 4190 | else |
ea3d1f2e | 4191 | solver_addrule(solv, -p, 0, pool_ids2whatprovides(pool, qq.elements + groupstart, k - groupstart)); |
178203fe | 4192 | queue_push(&infoq, qo.elements[i]); |
99e2d678 MS |
4193 | } |
4194 | groupstart = k + 1; | |
4195 | groupk++; | |
4196 | } | |
4197 | } | |
4198 | } | |
178203fe MS |
4199 | if (infoq.count) |
4200 | solv->yumobsrules_info = solv_memdup2(infoq.elements, infoq.count, sizeof(Id)); | |
4201 | queue_free(&infoq); | |
99e2d678 | 4202 | queue_free(&qq); |
d9727c22 | 4203 | queue_free(&qo); |
99e2d678 MS |
4204 | solv->yumobsrules_end = solv->nrules; |
4205 | POOL_DEBUG(SOLV_DEBUG_STATS, "yumobs rule creation took %d ms\n", solv_timems(now)); | |
4206 | } | |
4207 | ||
841ea42d MS |
4208 | /* recommendsrules are a copy of some recommends package rule but |
4209 | * with some disfavored literals removed */ | |
4210 | void | |
4211 | solver_addrecommendsrules(Solver *solv) | |
4212 | { | |
4213 | Pool *pool = solv->pool; | |
4214 | int i, havedis, havepos; | |
4215 | Id p, pp; | |
4216 | Queue q, infoq; | |
4217 | ||
4218 | solv->recommendsrules = solv->nrules; | |
4219 | queue_init(&q); | |
4220 | queue_init(&infoq); | |
4221 | for (i = 0; i < solv->recommendsruleq->count; i++) | |
4222 | { | |
4223 | int rid = solv->recommendsruleq->elements[i]; | |
4224 | Rule *r = solv->rules + rid; | |
4225 | queue_empty(&q); | |
4226 | havedis = havepos = 0; | |
4227 | FOR_RULELITERALS(p, pp, r) | |
4228 | { | |
4229 | if (p > 0 && solv->favormap[p] < 0) | |
4230 | havedis = 1; | |
4231 | else | |
4232 | { | |
4233 | if (p > 0) | |
4234 | havepos = 1; | |
4235 | queue_push(&q, p); | |
4236 | } | |
4237 | } | |
4238 | if (!havedis) | |
4239 | continue; | |
4240 | solver_disablerule(solv, r); | |
4241 | if (!havepos || q.count < 2) | |
4242 | continue; | |
4243 | if (q.count == 2) | |
4244 | solver_addrule(solv, q.elements[0], q.elements[1], 0); | |
4245 | else | |
4246 | solver_addrule(solv, q.elements[0], 0, pool_ids2whatprovides(pool, q.elements + 1, q.count - 1)); | |
4247 | queue_push(&infoq, rid); | |
4248 | } | |
4249 | if (infoq.count) | |
4250 | solv->recommendsrules_info = solv_memdup2(infoq.elements, infoq.count, sizeof(Id)); | |
4251 | queue_free(&infoq); | |
4252 | queue_free(&q); | |
4253 | solv->recommendsrules_end = solv->nrules; | |
4254 | } | |
4255 | ||
3ef3b1fc MS |
4256 | void |
4257 | solver_breakorphans(Solver *solv) | |
4258 | { | |
4259 | Pool *pool = solv->pool; | |
4260 | Repo *installed = solv->installed; | |
4261 | int i, rid; | |
4262 | Map m; | |
4263 | ||
4264 | if (!installed || solv->droporphanedmap_all) | |
4265 | return; | |
4266 | solv->brokenorphanrules = solv_calloc(1, sizeof(Queue)); | |
4267 | queue_init(solv->brokenorphanrules); | |
4268 | map_init(&m, installed->end - installed->start); | |
4269 | for (i = 0; i < solv->orphaned.count; i++) | |
4270 | { | |
4271 | Id p = solv->orphaned.elements[i]; | |
4272 | if (pool->solvables[p].repo != installed) | |
4273 | continue; | |
4274 | if (solv->droporphanedmap.size && MAPTST(&solv->droporphanedmap, p - installed->start)) | |
4275 | continue; | |
4276 | MAPSET(&m, p - installed->start); | |
4277 | } | |
2b48a178 | 4278 | for (rid = 1; rid < solv->pkgrules_end ; rid++) |
3ef3b1fc MS |
4279 | { |
4280 | Id p, *dp; | |
4281 | Rule *r = solv->rules + rid; | |
4282 | /* ignore non-deps and simple conflicts */ | |
4283 | if (r->p >= 0 || ((r->d == 0 || r->d == -1) && r->w2 < 0)) | |
4284 | continue; | |
4285 | p = -r->p; | |
4286 | if (p < installed->start || p >= installed->end || !MAPTST(&m, p - installed->start)) | |
4287 | { | |
4288 | /* need to check other literals */ | |
4289 | if (r->d == 0 || r->d == -1) | |
4290 | continue; | |
4291 | for (dp = pool->whatprovidesdata + (r->d < 0 ? -r->d - 1 : r->d); *dp < 0; dp++) | |
4292 | { | |
4293 | p = -*dp; | |
4294 | if (p >= installed->start && p < installed->end && MAPTST(&m, p - installed->start)) | |
4295 | break; | |
4296 | } | |
4297 | if (*dp >= 0) | |
4298 | continue; | |
4299 | } | |
4300 | /* ok, disable this rule */ | |
4301 | queue_push(solv->brokenorphanrules, rid); | |
4302 | if (r->d >= 0) | |
4303 | solver_disablerule(solv, r); | |
4304 | } | |
4305 | map_free(&m); | |
4306 | if (!solv->brokenorphanrules->count) | |
4307 | { | |
4308 | queue_free(solv->brokenorphanrules); | |
4309 | solv->brokenorphanrules = solv_free(solv->brokenorphanrules); | |
4310 | } | |
4311 | } | |
4312 | ||
4313 | void | |
4314 | solver_check_brokenorphanrules(Solver *solv, Queue *dq) | |
4315 | { | |
4316 | Pool *pool = solv->pool; | |
4317 | int i; | |
4318 | Id l, pp; | |
d39445e2 | 4319 | |
3ef3b1fc MS |
4320 | queue_empty(dq); |
4321 | if (!solv->brokenorphanrules) | |
4322 | return; | |
4323 | for (i = 0; i < solv->brokenorphanrules->count; i++) | |
4324 | { | |
4325 | int rid = solv->brokenorphanrules->elements[i]; | |
4326 | Rule *r = solv->rules + rid; | |
4327 | FOR_RULELITERALS(l, pp, r) | |
4328 | { | |
4329 | if (l < 0) | |
4330 | { | |
4331 | if (solv->decisionmap[-l] <= 0) | |
4332 | break; | |
4333 | } | |
4334 | else | |
4335 | { | |
4336 | if (solv->decisionmap[l] > 0 && pool->solvables[l].repo != solv->installed) | |
4337 | break; | |
4338 | } | |
4339 | } | |
4340 | if (l) | |
4341 | continue; | |
4342 | FOR_RULELITERALS(l, pp, r) | |
4343 | if (l > 0 && solv->decisionmap[l] == 0 && pool->solvables[l].repo != solv->installed) | |
4344 | queue_pushunique(dq, l); | |
4345 | } | |
4346 | } | |
4347 | ||
4d14c809 MS |
4348 | const char * |
4349 | solver_ruleinfo2str(Solver *solv, SolverRuleinfo type, Id source, Id target, Id dep) | |
4350 | { | |
4351 | Pool *pool = solv->pool; | |
4352 | char *s; | |
4353 | Solvable *ss; | |
4354 | switch (type) | |
4355 | { | |
4356 | case SOLVER_RULE_DISTUPGRADE: | |
4357 | return pool_tmpjoin(pool, pool_solvid2str(pool, source), " does not belong to a distupgrade repository", 0); | |
4358 | case SOLVER_RULE_INFARCH: | |
4359 | return pool_tmpjoin(pool, pool_solvid2str(pool, source), " has inferior architecture", 0); | |
4360 | case SOLVER_RULE_UPDATE: | |
4361 | return pool_tmpjoin(pool, pool_solvid2str(pool, source), " needs to stay installed or be updated", 0); | |
a3059b47 MS |
4362 | case SOLVER_RULE_FEATURE: |
4363 | return pool_tmpjoin(pool, pool_solvid2str(pool, source), " needs to stay installed or be updated/downgraded", 0); | |
4d14c809 MS |
4364 | case SOLVER_RULE_JOB: |
4365 | return pool_tmpjoin(pool, "job ", pool_job2str(pool, target, dep, 0), 0); | |
4366 | case SOLVER_RULE_JOB_UNSUPPORTED: | |
4367 | return pool_tmpjoin(pool, "unsupported job ", pool_job2str(pool, target, dep, 0), 0); | |
4368 | case SOLVER_RULE_JOB_NOTHING_PROVIDES_DEP: | |
4369 | return pool_tmpjoin(pool, "nothing provides requested ", pool_dep2str(pool, dep), 0); | |
4370 | case SOLVER_RULE_JOB_UNKNOWN_PACKAGE: | |
4371 | return pool_tmpjoin(pool, "requested package ", pool_dep2str(pool, dep), " does not exist"); | |
4372 | case SOLVER_RULE_JOB_PROVIDED_BY_SYSTEM: | |
4373 | return pool_tmpjoin(pool, "requested ", pool_dep2str(pool, dep), " is provided by the system"); | |
4d14c809 MS |
4374 | case SOLVER_RULE_BEST: |
4375 | if (source > 0) | |
843076b1 | 4376 | return pool_tmpjoin(pool, "install best update candidate for ", pool_solvid2str(pool, source), 0); |
a3059b47 MS |
4377 | if (target > 0) |
4378 | { | |
4379 | target = solver_rule2job(solv, target, &dep); | |
4380 | return pool_tmpjoin(pool, "best package for job ", pool_job2str(pool, target, dep, 0), 0); | |
4381 | } | |
4382 | return "best rule"; | |
4383 | case SOLVER_RULE_PKG: | |
4384 | return "bad pkg rule type"; | |
4d14c809 MS |
4385 | case SOLVER_RULE_PKG_NOT_INSTALLABLE: |
4386 | ss = pool->solvables + source; | |
4387 | if (pool_disabled_solvable(pool, ss)) | |
843076b1 | 4388 | return pool_tmpjoin(pool, pool_solvid2str(pool, source), " is disabled", 0); |
4d14c809 MS |
4389 | if (ss->arch && ss->arch != ARCH_SRC && ss->arch != ARCH_NOSRC && |
4390 | pool->id2arch && pool_arch2score(pool, ss->arch) == 0) | |
843076b1 MS |
4391 | return pool_tmpjoin(pool, pool_solvid2str(pool, source), " does not have a compatible architecture", 0); |
4392 | return pool_tmpjoin(pool, pool_solvid2str(pool, source), " is not installable", 0); | |
4d14c809 MS |
4393 | case SOLVER_RULE_PKG_NOTHING_PROVIDES_DEP: |
4394 | s = pool_tmpjoin(pool, "nothing provides ", pool_dep2str(pool, dep), 0); | |
4395 | return pool_tmpappend(pool, s, " needed by ", pool_solvid2str(pool, source)); | |
4396 | case SOLVER_RULE_PKG_SAME_NAME: | |
4397 | s = pool_tmpjoin(pool, "cannot install both ", pool_solvid2str(pool, source), 0); | |
4398 | return pool_tmpappend(pool, s, " and ", pool_solvid2str(pool, target)); | |
4399 | case SOLVER_RULE_PKG_CONFLICTS: | |
843076b1 MS |
4400 | s = pool_tmpappend(pool, pool_solvid2str(pool, source), " conflicts with ", pool_dep2str(pool, dep)); |
4401 | if (target) | |
4402 | s = pool_tmpappend(pool, s, " provided by ", pool_solvid2str(pool, target)); | |
4403 | return s; | |
a3059b47 | 4404 | case SOLVER_RULE_PKG_SELF_CONFLICT: |
843076b1 | 4405 | s = pool_tmpjoin(pool, pool_solvid2str(pool, source), " conflicts with ", 0); |
a3059b47 | 4406 | return pool_tmpappend(pool, s, pool_dep2str(pool, dep), " provided by itself"); |
4d14c809 | 4407 | case SOLVER_RULE_PKG_OBSOLETES: |
843076b1 MS |
4408 | s = pool_tmpappend(pool, pool_solvid2str(pool, source), " obsoletes ", pool_dep2str(pool, dep)); |
4409 | if (target) | |
4410 | s = pool_tmpappend(pool, s, " provided by ", pool_solvid2str(pool, target)); | |
4411 | return s; | |
4d14c809 | 4412 | case SOLVER_RULE_PKG_INSTALLED_OBSOLETES: |
843076b1 | 4413 | s = pool_tmpjoin(pool, "installed ", pool_solvid2str(pool, source), 0); |
4d14c809 | 4414 | s = pool_tmpappend(pool, s, " obsoletes ", pool_dep2str(pool, dep)); |
843076b1 MS |
4415 | if (target) |
4416 | s = pool_tmpappend(pool, s, " provided by ", pool_solvid2str(pool, target)); | |
4417 | return s; | |
4d14c809 | 4418 | case SOLVER_RULE_PKG_IMPLICIT_OBSOLETES: |
843076b1 MS |
4419 | s = pool_tmpappend(pool, pool_solvid2str(pool, source), " implicitly obsoletes ", pool_dep2str(pool, dep)); |
4420 | if (target) | |
4421 | s = pool_tmpappend(pool, s, " provided by ", pool_solvid2str(pool, target)); | |
4422 | return s; | |
4d14c809 | 4423 | case SOLVER_RULE_PKG_REQUIRES: |
843076b1 | 4424 | return pool_tmpjoin(pool, pool_solvid2str(pool, source), " requires ", pool_dep2str(pool, dep)); |
a3059b47 | 4425 | case SOLVER_RULE_PKG_RECOMMENDS: |
843076b1 | 4426 | return pool_tmpjoin(pool, pool_solvid2str(pool, source), " recommends ", pool_dep2str(pool, dep)); |
a3059b47 | 4427 | case SOLVER_RULE_PKG_CONSTRAINS: |
843076b1 | 4428 | s = pool_tmpappend(pool, pool_solvid2str(pool, source), " has constraint ", pool_dep2str(pool, dep)); |
a3059b47 | 4429 | return pool_tmpappend(pool, s, " conflicting with ", pool_solvid2str(pool, target)); |
60751187 MS |
4430 | case SOLVER_RULE_PKG_SUPPLEMENTS: |
4431 | s = pool_tmpjoin(pool, pool_solvid2str(pool, source), " supplements ", pool_dep2str(pool, dep)); | |
4432 | if (target) | |
4433 | s = pool_tmpappend(pool, s, " provided by ", pool_solvid2str(pool, target)); | |
4434 | return s; | |
4d14c809 | 4435 | case SOLVER_RULE_YUMOBS: |
843076b1 | 4436 | s = pool_tmpjoin(pool, "both ", pool_solvid2str(pool, source), " and "); |
4d14c809 MS |
4437 | s = pool_tmpjoin(pool, s, pool_solvid2str(pool, target), " obsolete "); |
4438 | return pool_tmpappend(pool, s, pool_dep2str(pool, dep), 0); | |
4439 | case SOLVER_RULE_BLACK: | |
843076b1 | 4440 | return pool_tmpjoin(pool, pool_solvid2str(pool, source), " can only be installed by a direct request", 0); |
4d14c809 | 4441 | case SOLVER_RULE_STRICT_REPO_PRIORITY: |
843076b1 | 4442 | return pool_tmpjoin(pool, pool_solvid2str(pool, source), " is excluded by strict repo priority", 0); |
4d14c809 MS |
4443 | case SOLVER_RULE_LEARNT: |
4444 | return "learnt rule"; | |
a3059b47 MS |
4445 | case SOLVER_RULE_CHOICE: |
4446 | if (source > 0) | |
4447 | { | |
4448 | const char *s2; | |
4449 | type = solver_ruleinfo(solv, source, &source, &target, &dep); | |
4450 | s2 = solver_ruleinfo2str(solv, type, source, target, dep); | |
e10d75ee | 4451 | return pool_tmpjoin(pool, s2, " (limited version)", 0); |
a3059b47 MS |
4452 | } |
4453 | return "choice rule"; | |
e10d75ee MS |
4454 | case SOLVER_RULE_RECOMMENDS: |
4455 | if (source > 0) | |
4456 | { | |
4457 | const char *s2; | |
4458 | type = solver_ruleinfo(solv, source, &source, &target, &dep); | |
4459 | s2 = solver_ruleinfo2str(solv, type, source, target, dep); | |
4460 | return pool_tmpjoin(pool, s2, " (limited version)", 0); | |
4461 | } | |
4462 | return "recommends rule"; | |
4d14c809 | 4463 | default: |
e10d75ee | 4464 | return "bad rule type"; |
4d14c809 MS |
4465 | } |
4466 | } |