2 * Copyright (c) 2007-2017, SUSE Inc.
4 * This program is licensed under the BSD license, read LICENSE.BSD
5 * for further information
11 * SAT based dependency solver
21 #include "solver_private.h"
28 #include "solverdebug.h"
29 #include "linkedpkg.h"
32 #define RULES_BLOCK 63
34 static void addpkgruleinfo(Solver
*solv
, Id p
, Id p2
, Id d
, int type
, Id dep
);
37 is_otherproviders_dep(Pool
*pool
, Id dep
)
41 Reldep
*rd
= GETRELDEP(pool
, dep
);
42 if (rd
->flags
== REL_NAMESPACE
&& rd
->name
== NAMESPACE_OTHERPROVIDERS
)
48 /********************************************************************
52 * - unify rules, remove duplicates
55 /*-------------------------------------------------------------------
57 * compare rules for unification sort
62 unifyrules_sortcmp(const void *ap
, const void *bp
, void *dp
)
72 return x
; /* p differs */
75 if (a
->d
== 0 && b
->d
== 0) /* both assertions or binary */
78 if (a
->d
== 0) /* a is assertion or binary, b not */
80 x
= a
->w2
- pool
->whatprovidesdata
[b
->d
];
84 if (b
->d
== 0) /* b is assertion or binary, a not */
86 x
= pool
->whatprovidesdata
[a
->d
] - b
->w2
;
93 /* compare whatprovidesdata */
94 ad
= pool
->whatprovidesdata
+ a
->d
;
95 bd
= pool
->whatprovidesdata
+ b
->d
;
97 if ((x
= *ad
++ - *bd
++) != 0)
103 solver_rulecmp(Solver
*solv
, Rule
*r1
, Rule
*r2
)
105 return unifyrules_sortcmp(r1
, r2
, solv
->pool
);
109 /*-------------------------------------------------------------------
112 * go over all rules and remove duplicates
116 solver_unifyrules(Solver
*solv
)
118 Pool
*pool
= solv
->pool
;
122 if (solv
->nrules
<= 2) /* nothing to unify */
125 if (solv
->recommendsruleq
)
127 /* mis-use n2 as recommends rule marker */
128 for (i
= 1, ir
= solv
->rules
+ i
; i
< solv
->nrules
; i
++, ir
++)
130 for (i
= 0; i
< solv
->recommendsruleq
->count
; i
++)
131 solv
->rules
[solv
->recommendsruleq
->elements
[i
]].n2
= 1;
134 /* sort rules first */
135 solv_sort(solv
->rules
+ 1, solv
->nrules
- 1, sizeof(Rule
), unifyrules_sortcmp
, solv
->pool
);
139 for (i
= j
= 1, ir
= solv
->rules
+ i
; i
< solv
->nrules
; i
++, ir
++)
141 if (jr
&& !unifyrules_sortcmp(ir
, jr
, pool
))
143 jr
->n2
&= ir
->n2
; /* bitwise-and recommends marker */
144 continue; /* prune! */
146 jr
= solv
->rules
+ j
++; /* keep! */
151 /* reduced count from nrules to j rules */
152 POOL_DEBUG(SOLV_DEBUG_STATS
, "pruned rules from %d to %d\n", solv
->nrules
, j
);
154 /* adapt rule buffer */
155 solver_shrinkrules(solv
, j
);
157 if (solv
->recommendsruleq
)
159 /* rebuild recommendsruleq */
160 queue_empty(solv
->recommendsruleq
);
161 for (i
= 1, ir
= solv
->rules
+ i
; i
< solv
->nrules
; i
++, ir
++)
165 queue_push(solv
->recommendsruleq
, i
);
170 * debug: log rule statistics
172 IF_POOLDEBUG (SOLV_DEBUG_STATS
)
179 for (i
= 1; i
< solv
->nrules
; i
++)
186 dp
= pool
->whatprovidesdata
+ r
->d
;
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
);
203 hashrule(Solver
*solv
, Id p
, Id d
, int n
)
205 unsigned int x
= (unsigned int)p
;
209 return (x
* 37) ^ (unsigned int)d
;
210 dp
= solv
->pool
->whatprovidesdata
+ d
;
212 x
= (x
* 37) ^ (unsigned int)*dp
++;
218 /*-------------------------------------------------------------------
225 * A requires b, b provided by B1,B2,B3 => (-A|B1|B2|B3)
227 * p < 0 : pkg id of A
228 * d > 0 : Offset in whatprovidesdata (list of providers of b)
230 * A conflicts b, b provided by B1,B2,B3 => (-A|-B1), (-A|-B2), (-A|-B3)
231 * p < 0 : pkg id of A
232 * p2 < 0 : Id of solvable (e.g. B1)
234 * d == 0, p2 == 0: unary rule, assertion => (A) or (-A)
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>
240 * Conflicts: p < 0, p2 < 0 (-A|-B) either p (conflict issuer) or d (conflict provider) (binary rule)
241 * also used for obsoletes
242 * No-op ?: p = 0, d = 0 (null) (used as placeholder in update/feature rules)
246 * Direct assertion (no watch needed) --> d = 0, w1 = p, w2 = 0
247 * Binary rule: p = first literal, d = 0, w2 = second literal, w1 = p
248 * every other : w1 = p, w2 = whatprovidesdata[d];
250 * always returns a rule for non-pkg rules
254 solver_addrule(Solver
*solv
, Id p
, Id p2
, Id d
)
256 Pool
*pool
= solv
->pool
;
261 assert(!p2
&& d
> 0);
262 if (!pool
->whatprovidesdata
[d
])
264 else if (!pool
->whatprovidesdata
[d
+ 1])
266 p2
= pool
->whatprovidesdata
[d
];
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
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 */
281 r
= solv
->rules
+ solv
->lastpkgrule
;
285 /* check if rule is identical */
291 dp2
= pool
->whatprovidesdata
+ r
->d
;
292 for (dp
= pool
->whatprovidesdata
+ d
; *dp
; dp
++, dp2
++)
298 /* check if rule is self-fulfilling */
299 for (dp
= pool
->whatprovidesdata
+ d
; *dp
; dp
++)
301 return 0; /* rule is self-fulfilling */
307 Id o
= p
; /* switch p1 and p2 */
311 if (r
->p
== p
&& !r
->d
&& r
->w2
== p2
)
314 return 0; /* rule is self-fulfilling */
316 solv
->lastpkgrule
= solv
->nrules
;
319 solv
->rules
= solv_extend(solv
->rules
, solv
->nrules
, 1, sizeof(Rule
), RULES_BLOCK
);
320 r
= solv
->rules
+ solv
->nrules
++; /* point to rule space */
324 r
->w2
= d
? pool
->whatprovidesdata
[d
] : p2
;
327 IF_POOLDEBUG (SOLV_DEBUG_RULE_CREATION
)
329 POOL_DEBUG(SOLV_DEBUG_RULE_CREATION
, " Add rule: ");
330 solver_printrule(solv
, SOLV_DEBUG_RULE_CREATION
, r
);
337 solver_shrinkrules(Solver
*solv
, int nrules
)
339 solv
->nrules
= nrules
;
340 solv
->rules
= solv_extend_resize(solv
->rules
, solv
->nrules
, sizeof(Rule
), RULES_BLOCK
);
341 solv
->lastpkgrule
= 0;
344 /******************************************************************************
346 *** pkg rule part: create rules representing the package dependencies
351 * special multiversion patch conflict handling:
352 * a patch conflict is also satisfied if some other
353 * version with the same name/arch that doesn't conflict
354 * gets installed. The generated rule is thus:
355 * -patch|-cpack|opack1|opack2|...
358 makemultiversionconflict(Solver
*solv
, Id n
, Id con
)
360 Pool
*pool
= solv
->pool
;
365 sn
= pool
->solvables
+ n
;
366 queue_init_buffer(&q
, qbuf
, sizeof(qbuf
)/sizeof(*qbuf
));
368 FOR_PROVIDES(p
, pp
, sn
->name
)
370 s
= pool
->solvables
+ p
;
371 if (s
->name
!= sn
->name
|| s
->arch
!= sn
->arch
)
373 if (!MAPTST(&solv
->multiversion
, p
))
375 if (pool_match_nevr(pool
, pool
->solvables
+ p
, con
))
377 /* here we have a multiversion solvable that doesn't conflict */
378 /* thus we're not in conflict if it is installed */
382 n
= 0; /* no other package found, normal conflict handling */
384 n
= pool_queuetowhatprovides(pool
, &q
);
390 addpkgrule(Solver
*solv
, Id p
, Id p2
, Id d
, int type
, Id dep
)
392 if (!solv
->ruleinfoq
)
393 solver_addrule(solv
, p
, p2
, d
);
395 addpkgruleinfo(solv
, p
, p2
, d
, type
, dep
);
398 #ifdef ENABLE_LINKED_PKGS
401 addlinks_cmp(const void *ap
, const void *bp
, void *dp
)
406 Solvable
*sa
= pool
->solvables
+ a
;
407 Solvable
*sb
= pool
->solvables
+ b
;
408 if (sa
->name
!= sb
->name
)
409 return sa
->name
- sb
->name
;
414 addlinks(Solver
*solv
, Solvable
*s
, Id req
, Queue
*qr
, Id prv
, Queue
*qp
, Map
*m
, Queue
*workq
)
416 Pool
*pool
= solv
->pool
;
421 solv_sort(qp
->elements
, qp
->count
, sizeof(Id
), addlinks_cmp
, pool
);
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
]));
432 addpkgrule(solv
, -(s
- pool
->solvables
), qr
->elements
[0], 0, SOLVER_RULE_PKG_REQUIRES
, req
);
434 addpkgrule(solv
, -(s
- pool
->solvables
), 0, pool_queuetowhatprovides(pool
, qr
), SOLVER_RULE_PKG_REQUIRES
, req
);
438 for (i
= j
= 0; i
< qp
->count
; i
= j
)
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
)
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
);
451 for (i
= 0; i
< qr
->count
; i
++)
452 addpkgrule(solv
, -qr
->elements
[i
], qp
->elements
[0], 0, SOLVER_RULE_PKG_REQUIRES
, prv
);
455 return; /* nothing more to do if called from getpkgruleinfos() */
456 for (i
= 0; i
< qr
->count
; i
++)
457 if (!MAPTST(m
, qr
->elements
[i
]))
458 queue_push(workq
, qr
->elements
[i
]);
459 for (i
= 0; i
< qp
->count
; i
++)
460 if (!MAPTST(m
, qp
->elements
[i
]))
461 queue_push(workq
, qp
->elements
[i
]);
462 if (solv
->installed
&& s
->repo
== solv
->installed
)
464 Repo
*installed
= solv
->installed
;
465 /* record installed buddies */
466 if (!solv
->instbuddy
)
467 solv
->instbuddy
= solv_calloc(installed
->end
- installed
->start
, sizeof(Id
));
469 solv
->instbuddy
[s
- pool
->solvables
- installed
->start
] = qr
->elements
[0];
470 for (i
= 0; i
< qr
->count
; i
++)
472 Id p
= qr
->elements
[i
];
473 if (pool
->solvables
[p
].repo
!= installed
)
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 */
478 solv
->instbuddy
[p
- installed
->start
] = s
- pool
->solvables
;
484 add_package_link(Solver
*solv
, Solvable
*s
, Map
*m
, Queue
*workq
)
490 find_package_link(solv
->pool
, s
, &req
, &qr
, &prv
, &qp
);
492 addlinks(solv
, s
, req
, &qr
, prv
, &qp
, m
, workq
);
499 #ifdef ENABLE_COMPLEX_DEPS
503 suse_isptf(Pool
*pool
, Solvable
*s
)
505 if (!strncmp("ptf-", pool_id2str(pool
, s
->name
), 4))
512 add_complex_deprules(Solver
*solv
, Id p
, Id dep
, int type
, int dontfix
, Queue
*workq
, Map
*m
)
514 Pool
*pool
= solv
->pool
;
515 Repo
*installed
= solv
->installed
;
520 flags
= dontfix
? CPLXDEPS_DONTFIX
: 0;
521 /* CNF expansion for requires, DNF + INVERT expansion for conflicts */
522 if (type
== SOLVER_RULE_PKG_CONFLICTS
)
523 flags
|= CPLXDEPS_TODNF
| CPLXDEPS_EXPAND
| CPLXDEPS_INVERT
;
525 if (type
== SOLVER_RULE_PKG_REQUIRES
&& suse_isptf(pool
, pool
->solvables
+ p
))
526 flags
|= CPLXDEPS_NAME
; /* do not match provides */
529 i
= pool_normalize_complex_dep(pool
, dep
, &bq
, flags
);
530 /* handle special cases */
535 POOL_DEBUG(SOLV_DEBUG_RULE_CREATION
, "ignoring broken dependency %s of installed package %s\n", pool_dep2str(pool
, dep
), pool_solvid2str(pool
, p
));
539 POOL_DEBUG(SOLV_DEBUG_RULE_CREATION
, "package %s [%d] is not installable (%s)\n", pool_solvid2str(pool
, p
), p
, pool_dep2str(pool
, dep
));
540 addpkgrule(solv
, -p
, 0, 0, type
== SOLVER_RULE_PKG_REQUIRES
? SOLVER_RULE_PKG_NOTHING_PROVIDES_DEP
: type
, dep
);
551 /* go through all blocks and add a rule for each block */
552 for (i
= 0; i
< bq
.count
; i
++)
556 if (bq
.elements
[i
] == pool
->nsolvables
)
558 /* conventional requires (cannot be a conflicts as they have been expanded) */
559 Id
*dp
= pool
->whatprovidesdata
+ bq
.elements
[i
+ 1];
563 for (j
= 0; dp
[j
] != 0; j
++)
564 if (pool
->solvables
[dp
[j
]].repo
== installed
)
565 break; /* provider was installed */
569 if (type
== SOLVER_RULE_PKG_RECOMMENDS
&& !*dp
)
571 /* check if the rule contains both p and -p */
572 for (j
= 0; dp
[j
] != 0; j
++)
577 addpkgrule(solv
, -p
, 0, dp
- pool
->whatprovidesdata
, type
, dep
);
578 /* push all non-visited providers on the work queue */
582 queue_push(workq
, *dp
);
585 if (!bq
.elements
[i
+ 1])
587 Id p2
= bq
.elements
[i
++];
588 /* simple rule with just two literals, we'll add a (-p, p2) rule */
591 if (p2
< 0 && pool
->solvables
[-p2
].repo
== installed
)
593 if (p2
> 0 && pool
->solvables
[p2
].repo
!= installed
)
598 if (type
== SOLVER_RULE_PKG_CONFLICTS
)
600 if (pool
->forbidselfconflicts
&& !is_otherproviders_dep(pool
, dep
))
601 addpkgrule(solv
, -p
, 0, 0, SOLVER_RULE_PKG_SELF_CONFLICT
, dep
);
604 addpkgrule(solv
, -p
, 0, 0, type
, dep
);
607 /* check if the rule contains both p and -p */
610 addpkgrule(solv
, -p
, p2
, 0, type
, dep
);
611 if (m
&& p2
> 0 && !MAPTST(m
, p2
))
612 queue_push(workq
, p2
);
619 qele
= bq
.elements
+ i
;
621 while (bq
.elements
[i
])
626 for (j
= 0; j
< qcnt
; j
++)
628 if (qele
[j
] > 0 && pool
->solvables
[qele
[j
]].repo
== installed
)
630 if (qele
[j
] < 0 && pool
->solvables
[-qele
[j
]].repo
!= installed
)
636 /* add -p to (ordered) rule (overwriting the trailing zero) */
639 if (j
== qcnt
|| qele
[j
] > -p
)
642 memmove(qele
+ j
+ 1, qele
+ j
, (qcnt
- j
) * sizeof(Id
));
650 /* check if the rule contains both p and -p */
651 for (j
= 0; j
< qcnt
; j
++)
656 d
= pool_ids2whatprovides(pool
, qele
+ 1, qcnt
- 1);
657 if (solv
->ruleinfoq
&& qele
[0] != p
)
659 int oldcount
= solv
->ruleinfoq
->count
;
660 addpkgrule(solv
, qele
[0], 0, d
, type
, dep
);
661 /* fixup from element of ruleinfo */
662 if (solv
->ruleinfoq
->count
> oldcount
&& solv
->ruleinfoq
->elements
[oldcount
+ 1] != p
)
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
;
670 addpkgrule(solv
, qele
[0], 0, d
, type
, dep
);
672 for (j
= 0; j
< qcnt
; j
++)
673 if (qele
[j
] > 0 && !MAPTST(m
, qele
[j
]))
674 queue_push(workq
, qele
[j
]);
684 add_conda_constrains_rule(Solver
*solv
, Id n
, Id dep
, int dontfix
)
686 Pool
*pool
= solv
->pool
;
691 rd
= GETRELDEP(pool
, dep
);
692 pdep
= pool_whatprovides(pool
, dep
);
693 FOR_PROVIDES(p
, pp
, rd
->name
)
698 if (dontfix
&& pool
->solvables
[p
].repo
== solv
->installed
)
700 while ((p2
= pool
->whatprovidesdata
[pdep
]) != 0 && p2
< p
)
705 addpkgrule(solv
, -n
, -p
, 0, SOLVER_RULE_PKG_CONSTRAINS
, dep
);
710 /*-------------------------------------------------------------------
712 * add dependency rules for solvable
714 * s: Solvable for which to add rules
715 * m: m[s] = 1 for solvables which have rules, prevent rule duplication
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.
722 * for unfulfilled requirements, conflicts, obsoletes,....
723 * add a negative assertion for solvables that are not installable
725 * It will also create rules for all solvables referenced by 's'
726 * i.e. descend to all providers of requirements of 's'
731 solver_addpkgrulesforsolvable(Solver
*solv
, Solvable
*s
, Map
*m
)
733 Pool
*pool
= solv
->pool
;
734 Repo
*installed
= solv
->installed
;
736 Queue workq
; /* list of solvables we still have to work on */
738 Queue depq
; /* list of pre-req ids to ignore */
742 int dontfix
; /* ignore dependency errors for installed solvables */
748 Id p
, pp
; /* whatprovides loops */
749 Id
*dp
; /* ptr to 'whatprovides' */
750 Id n
; /* Id for current solvable 's' */
752 queue_init_buffer(&workq
, workqbuf
, sizeof(workqbuf
)/sizeof(*workqbuf
));
753 queue_push(&workq
, s
- pool
->solvables
); /* push solvable Id to work queue */
755 queue_init_buffer(&depq
, depqbuf
, sizeof(depqbuf
)/sizeof(*depqbuf
));
757 /* loop until there's no more work left */
762 * s: Pointer to solvable
765 n
= queue_shift(&workq
); /* 'pop' next solvable to work on from queue */
768 if (MAPTST(m
, n
)) /* continue if already visited */
770 MAPSET(m
, n
); /* mark as visited */
773 s
= pool
->solvables
+ n
;
776 if (installed
/* Installed system available */
777 && s
->repo
== installed
/* solvable is installed */
778 && !solv
->fixmap_all
/* NOT repair errors in dependency graph */
779 && !(solv
->fixmap
.size
&& MAPTST(&solv
->fixmap
, n
- installed
->start
)))
781 dontfix
= 1; /* dont care about broken deps */
786 if (s
->arch
== ARCH_SRC
|| s
->arch
== ARCH_NOSRC
787 ? pool_disabled_solvable(pool
, s
)
788 : !pool_installable(pool
, s
))
790 POOL_DEBUG(SOLV_DEBUG_RULE_CREATION
, "package %s [%d] is not installable\n", pool_solvid2str(pool
, n
), n
);
791 addpkgrule(solv
, -n
, 0, 0, SOLVER_RULE_PKG_NOT_INSTALLABLE
, 0);
795 #ifdef ENABLE_LINKED_PKGS
796 /* add pseudo-package <-> real-package links */
797 if (has_package_link(pool
, s
))
798 add_package_link(solv
, s
, m
, &workq
);
801 /*-----------------------------------------
802 * check requires of s
808 reqp
= s
->repo
->idarraydata
+ s
->requires
;
809 while ((req
= *reqp
++) != 0) /* go through all requires */
811 if (req
== SOLVABLE_PREREQMARKER
) /* skip the marker */
813 if (installed
&& s
->repo
== installed
)
815 solvable_lookup_idarray(s
, SOLVABLE_PREREQ_IGNOREINST
, &depq
);
816 filterpre
= depq
.count
;
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
])
828 POOL_DEBUG(SOLV_DEBUG_RULE_CREATION
, "package %s: ignoring filtered pre-req dependency %s\n", pool_solvable2str(pool
, s
), pool_dep2str(pool
, req
));
833 #ifdef ENABLE_COMPLEX_DEPS
834 if (pool_is_complex_dep(pool
, req
))
836 /* we have AND/COND deps, normalize */
837 add_complex_deprules(solv
, n
, req
, SOLVER_RULE_PKG_REQUIRES
, dontfix
, &workq
, m
);
842 /* find list of solvables providing 'req' */
843 dp
= pool_whatprovides_ptr(pool
, req
);
845 if (*dp
== SYSTEMSOLVABLE
) /* always installed */
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 */
854 for (i
= 0; (p
= dp
[i
]) != 0; i
++)
855 if (pool
->solvables
[p
].repo
== installed
)
856 break; /* found installed provider */
859 /* didn't find an installed provider: previously broken dependency */
860 POOL_DEBUG(SOLV_DEBUG_RULE_CREATION
, "ignoring broken requires %s of installed package %s\n", pool_dep2str(pool
, req
), pool_solvable2str(pool
, s
));
867 POOL_DEBUG(SOLV_DEBUG_RULE_CREATION
, "package %s [%d] is not installable (%s)\n", pool_solvid2str(pool
, n
), n
, pool_dep2str(pool
, req
));
868 addpkgrule(solv
, -n
, 0, 0, SOLVER_RULE_PKG_NOTHING_PROVIDES_DEP
, req
);
872 for (i
= 0; dp
[i
] != 0; i
++)
876 continue; /* provided by itself, no need to add rule */
878 IF_POOLDEBUG (SOLV_DEBUG_RULE_CREATION
)
880 POOL_DEBUG(SOLV_DEBUG_RULE_CREATION
," %s requires %s\n", pool_solvable2str(pool
, s
), pool_dep2str(pool
, req
));
881 for (i
= 0; dp
[i
]; i
++)
882 POOL_DEBUG(SOLV_DEBUG_RULE_CREATION
, " provided by %s\n", pool_solvid2str(pool
, dp
[i
]));
885 /* add 'requires' dependency */
886 /* rule: (-requestor|provider1|provider2|...|providerN) */
887 addpkgrule(solv
, -n
, 0, dp
- pool
->whatprovidesdata
, SOLVER_RULE_PKG_REQUIRES
, req
);
889 /* push all non-visited providers on the work queue */
893 queue_push(&workq
, *dp
);
897 if (s
->recommends
&& solv
->strongrecommends
)
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 */
904 #ifdef ENABLE_COMPLEX_DEPS
905 if (pool_is_complex_dep(pool
, req
))
907 /* we have AND/COND deps, normalize */
908 add_complex_deprules(solv
, n
, req
, SOLVER_RULE_PKG_RECOMMENDS
, dontfix
, &workq
, m
);
912 dp
= pool_whatprovides_ptr(pool
, req
);
913 if (*dp
== SYSTEMSOLVABLE
|| !*dp
) /* always installed or not installable */
915 for (i
= 0; dp
[i
] != 0; i
++)
919 continue; /* provided by itself, no need to add rule */
920 addpkgrule(solv
, -n
, 0, dp
- pool
->whatprovidesdata
, SOLVER_RULE_PKG_RECOMMENDS
, req
);
924 queue_push(&workq
, *dp
);
926 if (!solv
->ruleinfoq
&& start
< solv
->nrules
)
928 if (!solv
->recommendsruleq
)
930 solv
->recommendsruleq
= solv_calloc(1, sizeof(Queue
));
931 queue_init(solv
->recommendsruleq
);
933 for (i
= start
; i
< solv
->nrules
; i
++)
934 queue_push(solv
->recommendsruleq
, i
);
935 solv
->lastpkgrule
= 0;
940 if (pool
->disttype
== DISTTYPE_CONDA
)
942 solvable_lookup_idarray(s
, SOLVABLE_CONSTRAINS
, &depq
);
943 for (i
= 0; i
< depq
.count
; i
++)
944 add_conda_constrains_rule(solv
, n
, depq
.elements
[i
], dontfix
);
948 /* that's all we check for src packages */
949 if (s
->arch
== ARCH_SRC
|| s
->arch
== ARCH_NOSRC
)
952 /*-----------------------------------------
953 * check conflicts of s
960 /* we treat conflicts in patches a bit differen:
962 * - multiversion handling
963 * XXX: we should really handle this different, looking
964 * at the name is a bad hack
966 if (!strncmp("patch:", pool_id2str(pool
, s
->name
), 6))
968 conp
= s
->repo
->idarraydata
+ s
->conflicts
;
969 /* foreach conflicts of 's' */
970 while ((con
= *conp
++) != 0)
972 #ifdef ENABLE_COMPLEX_DEPS
973 if (!ispatch
&& pool_is_complex_dep(pool
, con
))
975 /* we have AND/COND deps, normalize */
976 add_complex_deprules(solv
, n
, con
, SOLVER_RULE_PKG_CONFLICTS
, dontfix
, &workq
, m
);
980 /* foreach providers of a conflict of 's' */
981 FOR_PROVIDES(p
, pp
, con
)
983 if (ispatch
&& !pool_match_nevr(pool
, pool
->solvables
+ p
, con
))
985 /* dontfix: dont care about conflicts with already installed packs */
986 if (dontfix
&& pool
->solvables
[p
].repo
== installed
)
988 if (p
== n
) /* p == n: self conflict */
990 if (!pool
->forbidselfconflicts
|| is_otherproviders_dep(pool
, con
))
992 addpkgrule(solv
, -n
, 0, 0, SOLVER_RULE_PKG_SELF_CONFLICT
, con
);
995 if (ispatch
&& solv
->multiversion
.size
&& MAPTST(&solv
->multiversion
, p
) && ISRELDEP(con
))
997 /* our patch conflicts with a multiversion package */
998 Id d
= makemultiversionconflict(solv
, p
, con
);
1001 addpkgrule(solv
, -n
, 0, d
, SOLVER_RULE_PKG_CONFLICTS
, con
);
1005 if (p
== SYSTEMSOLVABLE
)
1007 /* rule: -n|-p: either solvable _or_ provider of conflict */
1008 addpkgrule(solv
, -n
, -p
, 0, SOLVER_RULE_PKG_CONFLICTS
, con
);
1013 /*-----------------------------------------
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)
1018 if ((!installed
|| s
->repo
!= installed
) || !pool
->noinstalledobsoletes
)
1020 int multi
= solv
->multiversion
.size
&& MAPTST(&solv
->multiversion
, n
);
1021 int isinstalled
= (installed
&& s
->repo
== installed
);
1022 if (s
->obsoletes
&& (!multi
|| solv
->keepexplicitobsoletes
))
1024 obsp
= s
->repo
->idarraydata
+ s
->obsoletes
;
1025 /* foreach obsoletes */
1026 while ((obs
= *obsp
++) != 0)
1028 /* foreach provider of an obsoletes of 's' */
1029 FOR_PROVIDES(p
, pp
, obs
)
1031 Solvable
*ps
= pool
->solvables
+ p
;
1034 if (isinstalled
&& dontfix
&& ps
->repo
== installed
)
1035 continue; /* don't repair installed/installed problems */
1036 if (!pool
->obsoleteusesprovides
/* obsoletes are matched names, not provides */
1037 && !pool_match_nevr(pool
, ps
, obs
))
1039 if (pool
->obsoleteusescolors
&& !pool_colormatch(pool
, s
, ps
))
1041 if (p
== SYSTEMSOLVABLE
)
1044 addpkgrule(solv
, -n
, -p
, 0, SOLVER_RULE_PKG_OBSOLETES
, obs
);
1046 addpkgrule(solv
, -n
, -p
, 0, SOLVER_RULE_PKG_INSTALLED_OBSOLETES
, obs
);
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.
1055 if (!isinstalled
|| !dontfix
)
1057 FOR_PROVIDES(p
, pp
, s
->name
)
1059 Solvable
*ps
= pool
->solvables
+ p
;
1062 if (isinstalled
&& ps
->repo
!= installed
)
1064 /* we still obsolete packages with same nevra, like rpm does */
1065 /* (actually, rpm mixes those packages. yuck...) */
1066 if (multi
&& (s
->name
!= ps
->name
|| s
->evr
!= ps
->evr
|| s
->arch
!= ps
->arch
))
1068 if (isinstalled
|| ps
->repo
!= installed
)
1070 /* also check the installed package for multi-ness */
1071 if (MAPTST(&solv
->multiversion
, p
))
1074 if (!pool
->implicitobsoleteusesprovides
&& s
->name
!= ps
->name
)
1076 if (pool
->implicitobsoleteusescolors
&& !pool_colormatch(pool
, s
, ps
))
1078 if (p
== SYSTEMSOLVABLE
)
1080 if (s
->name
== ps
->name
)
1082 /* optimization: do not add the same-name conflict rule if it was
1083 * already added when we looked at the other package.
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
)))
1089 addpkgrule(solv
, -n
, -p
, 0, SOLVER_RULE_PKG_SAME_NAME
, 0);
1092 addpkgrule(solv
, -n
, -p
, 0, SOLVER_RULE_PKG_IMPLICIT_OBSOLETES
, s
->name
);
1097 if (m
&& pool
->implicitobsoleteusescolors
&& pool_arch2score(pool
, s
->arch
) > 1)
1099 unsigned int pa
, a
= pool_arch2score(pool
, s
->arch
);
1100 /* check lock-step candidates */
1101 FOR_PROVIDES(p
, pp
, s
->name
)
1103 Solvable
*ps
= pool
->solvables
+ p
;
1104 if (s
->name
!= ps
->name
|| s
->evr
!= ps
->evr
|| MAPTST(m
, p
))
1106 pa
= pool_arch2score(pool
, ps
->arch
);
1107 if (!pa
|| pa
== 1 || pa
>= a
)
1109 queue_push(&workq
, p
);
1113 /*-----------------------------------------
1114 * add recommends/suggests to the work queue
1116 if (s
->recommends
&& m
)
1118 recp
= s
->repo
->idarraydata
+ s
->recommends
;
1119 while ((rec
= *recp
++) != 0)
1121 #ifdef ENABLE_COMPLEX_DEPS
1122 if (pool_is_complex_dep(pool
, rec
))
1124 pool_add_pos_literals_complex_dep(pool
, rec
, &workq
, m
, 0);
1128 FOR_PROVIDES(p
, pp
, rec
)
1130 queue_push(&workq
, p
);
1133 if (s
->suggests
&& m
)
1135 sugp
= s
->repo
->idarraydata
+ s
->suggests
;
1136 while ((sug
= *sugp
++) != 0)
1138 #ifdef ENABLE_COMPLEX_DEPS
1139 if (pool_is_complex_dep(pool
, sug
))
1141 pool_add_pos_literals_complex_dep(pool
, sug
, &workq
, m
, 0);
1145 FOR_PROVIDES(p
, pp
, sug
)
1147 queue_push(&workq
, p
);
1155 #ifdef ENABLE_LINKED_PKGS
1157 solver_addpkgrulesforlinked(Solver
*solv
, Map
*m
)
1159 Pool
*pool
= solv
->pool
;
1165 for (i
= 1; i
< pool
->nsolvables
; i
++)
1169 s
= pool
->solvables
+ i
;
1170 if (!s
->repo
|| s
->repo
== solv
->installed
)
1172 if (!strchr(pool_id2str(pool
, s
->name
), ':'))
1174 if (!pool_installable(pool
, s
))
1176 find_package_link(pool
, s
, 0, &qr
, 0, 0);
1179 for (j
= 0; j
< qr
.count
; j
++)
1180 if (MAPTST(m
, qr
.elements
[j
]))
1182 solver_addpkgrulesforsolvable(solv
, s
, m
);
1192 /*-------------------------------------------------------------------
1194 * Add rules for packages possibly selected in by weak dependencies
1196 * m: already added solvables
1200 solver_addpkgrulesforweak(Solver
*solv
, Map
*m
)
1202 Pool
*pool
= solv
->pool
;
1207 /* foreach solvable in pool */
1208 for (i
= n
= 1; n
< pool
->nsolvables
; i
++, n
++)
1210 if (i
== pool
->nsolvables
) /* wrap i */
1212 if (MAPTST(m
, i
)) /* already added that one */
1215 s
= pool
->solvables
+ i
;
1218 if (s
->repo
!= pool
->installed
&& !pool_installable(pool
, s
))
1219 continue; /* only look at installable ones */
1224 /* find possible supplements */
1225 supp
= s
->repo
->idarraydata
+ s
->supplements
;
1226 while ((sup
= *supp
++) != 0)
1227 if (solver_dep_possible(solv
, sup
, m
))
1231 /* if nothing found, check for enhances */
1232 if (!sup
&& s
->enhances
)
1234 supp
= s
->repo
->idarraydata
+ s
->enhances
;
1235 while ((sup
= *supp
++) != 0)
1236 if (solver_dep_possible(solv
, sup
, m
))
1239 /* if nothing found, goto next solvables */
1242 solver_addpkgrulesforsolvable(solv
, s
, m
);
1243 n
= 0; /* check all solvables again because we added solvables to m */
1248 /*-------------------------------------------------------------------
1250 * add package rules for possible updates
1253 * m: map of already visited solvables
1254 * allow_all: 0 = dont allow downgrades, 1 = allow all candidates
1258 solver_addpkgrulesforupdaters(Solver
*solv
, Solvable
*s
, Map
*m
, int allow_all
)
1260 Pool
*pool
= solv
->pool
;
1262 /* queue and buffer for it */
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
))
1271 solver_addpkgrulesforsolvable(solv
, s
, m
);
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
]))
1275 solver_addpkgrulesforsolvable(solv
, pool
->solvables
+ qs
.elements
[i
], m
);
1280 /***********************************************************************
1282 *** Update/Feature rule part
1284 *** Those rules make sure an installed package isn't silently deleted
1289 dup_maykeepinstalled(Solver
*solv
, Solvable
*s
)
1291 Pool
*pool
= solv
->pool
;
1294 if (solv
->dupmap
.size
&& MAPTST(&solv
->dupmap
, s
- pool
->solvables
))
1296 /* is installed identical to a good one? */
1297 FOR_PROVIDES(ip
, pp
, s
->name
)
1299 Solvable
*is
= pool
->solvables
+ ip
;
1300 if (is
->evr
!= s
->evr
)
1302 if (solv
->dupmap
.size
)
1304 if (!MAPTST(&solv
->dupmap
, ip
))
1307 else if (is
->repo
== pool
->installed
)
1309 if (solvable_identical(s
, is
))
1316 /* stash away the original updaters for multiversion packages. We do this so that
1317 * we can update the package later */
1319 set_specialupdaters(Solver
*solv
, Solvable
*s
, Id d
)
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
;
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 */
1330 is_linked_pseudo_package(Solver
*solv
, Solvable
*s
)
1332 Pool
*pool
= solv
->pool
;
1333 if (solv
->instbuddy
&& solv
->instbuddy
[s
- pool
->solvables
- solv
->installed
->start
])
1335 const char *name
= pool_id2str(pool
, s
->name
);
1336 if (strncmp(name
, "pattern:", 8) == 0 || strncmp(name
, "application:", 12) == 0)
1344 solver_addfeaturerule(Solver
*solv
, Solvable
*s
)
1346 Pool
*pool
= solv
->pool
;
1352 #ifdef ENABLE_LINKED_PKGS
1353 if (is_linked_pseudo_package(solv
, s
))
1355 solver_addrule(solv
, 0, 0, 0); /* no feature rules for those */
1359 queue_init_buffer(&qs
, qsbuf
, sizeof(qsbuf
)/sizeof(*qsbuf
));
1360 p
= s
- pool
->solvables
;
1361 policy_findupdatepackages(solv
, s
, &qs
, 1);
1362 if (solv
->dupinvolvedmap_all
|| (solv
->dupinvolvedmap
.size
&& MAPTST(&solv
->dupinvolvedmap
, p
)))
1364 if (!dup_maykeepinstalled(solv
, s
))
1366 for (i
= 0; i
< qs
.count
; i
++)
1368 Solvable
*ns
= pool
->solvables
+ qs
.elements
[i
];
1369 if (ns
->repo
!= pool
->installed
|| dup_maykeepinstalled(solv
, ns
))
1374 solver_addrule(solv
, 0, 0, 0); /* this is an orphan */
1382 Id d
= pool_queuetowhatprovides(pool
, &qs
);
1384 solver_addrule(solv
, p
, 0, d
); /* allow update of s */
1388 Id d
= qs
.count
? qs
.elements
[0] : 0;
1390 solver_addrule(solv
, p
, d
, 0); /* allow update of s */
1394 /* check if multiversion solvable s2 has an obsoletes for installed solvable s */
1396 is_multiversion_obsoleteed(Pool
*pool
, Solvable
*s
, Solvable
*s2
)
1400 if (pool
->obsoleteusescolors
&& !pool_colormatch(pool
, s
, s2
))
1402 obsp
= s2
->repo
->idarraydata
+ s2
->obsoletes
;
1403 if (!pool
->obsoleteusesprovides
)
1405 while ((obs
= *obsp
++) != 0)
1406 if (pool_match_nevr(pool
, s
, obs
))
1411 while ((obs
= *obsp
++) != 0)
1412 for (wp
= pool_whatprovides_ptr(pool
, obs
); *wp
; wp
++)
1413 if (pool
->solvables
+ *wp
== s
)
1419 /*-------------------------------------------------------------------
1421 * add rule for update
1422 * (A|A1|A2|A3...) An = update candidates for A
1424 * s = (installed) solvable
1428 solver_addupdaterule(Solver
*solv
, Solvable
*s
)
1430 /* installed packages get a special upgrade allowed rule */
1431 Pool
*pool
= solv
->pool
;
1436 int dupinvolved
= 0;
1438 p
= s
- pool
->solvables
;
1440 if (pool
->considered
&& pool_disabled_solvable(pool
, s
))
1442 /* disabled installed solvables must stay installed */
1443 solver_addrule(solv
, p
, 0, 0);
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
);
1452 #ifdef ENABLE_LINKED_PKGS
1453 if (is_linked_pseudo_package(solv
, s
))
1455 solver_addrule(solv
, 0, 0, 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);
1467 /* find update candidates for 's' */
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);
1472 if (qs
.count
&& solv
->multiversion
.size
)
1476 for (i
= 0; i
< qs
.count
; i
++)
1477 if (MAPTST(&solv
->multiversion
, qs
.elements
[i
]))
1481 /* filter out all multiversion packages as they don't update */
1482 d
= pool_queuetowhatprovides(pool
, &qs
); /* save qs away */
1483 for (j
= i
; i
< qs
.count
; i
++)
1485 if (MAPTST(&solv
->multiversion
, qs
.elements
[i
]))
1487 Solvable
*ps
= pool
->solvables
+ qs
.elements
[i
];
1488 /* check if there is an explicit obsoletes */
1489 if (solv
->keepexplicitobsoletes
&& ps
->obsoletes
&& is_multiversion_obsoleteed(pool
, s
, ps
))
1491 qs
.elements
[j
++] = qs
.elements
[i
];
1494 /* it's ok if they have same nevra */
1495 if (ps
->name
!= s
->name
|| ps
->evr
!= s
->evr
|| ps
->arch
!= s
->arch
)
1498 qs
.elements
[j
++] = qs
.elements
[i
];
1501 if (j
== 0 && dupinvolved
&& !dup_maykeepinstalled(solv
, s
))
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
))))
1508 /* we need to keep the orphan */
1510 solver_addrule(solv
, p
, 0, 0);
1513 /* we can drop it as long as we update */
1517 if (j
< qs
.count
) /* filtered at least one package? */
1519 if (d
&& (solv
->updatemap_all
|| (solv
->updatemap
.size
&& MAPTST(&solv
->updatemap
, p
- solv
->installed
->start
))))
1521 /* non-orphan multiversion package, set special updaters if we want an update */
1522 set_specialupdaters(solv
, s
, d
);
1528 /* could fallthrough, but then we would do pool_queuetowhatprovides twice */
1530 solver_addrule(solv
, p
, 0, d
); /* allow update of s */
1537 d
= pool_queuetowhatprovides(pool
, &qs
);
1539 solver_addrule(solv
, p
, 0, d
); /* allow update of s */
1543 d
= qs
.count
? qs
.elements
[0] : 0;
1545 solver_addrule(solv
, p
, d
, 0); /* allow update of s */
1550 disableupdaterule(Solver
*solv
, Id p
)
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
);
1561 if (solv
->bestrules_info
)
1564 ni
= solv
->bestrules_end
- solv
->bestrules
;
1565 for (i
= solv
->bestrules_up
- solv
->bestrules
; i
< ni
; i
++)
1566 if (solv
->bestrules_info
[i
] == p
)
1567 solver_disablerule(solv
, solv
->rules
+ solv
->bestrules
+ i
);
1572 reenableupdaterule(Solver
*solv
, Id p
)
1574 Pool
*pool
= solv
->pool
;
1577 MAPCLR(&solv
->noupdate
, p
- solv
->installed
->start
);
1578 r
= solv
->rules
+ solv
->updaterules
+ (p
- solv
->installed
->start
);
1583 solver_enablerule(solv
, r
);
1584 IF_POOLDEBUG (SOLV_DEBUG_SOLUTIONS
)
1586 POOL_DEBUG(SOLV_DEBUG_SOLUTIONS
, "@@@ re-enabling ");
1587 solver_printruleclass(solv
, SOLV_DEBUG_SOLUTIONS
, r
);
1593 r
= solv
->rules
+ solv
->featurerules
+ (p
- solv
->installed
->start
);
1594 if (r
->p
&& r
->d
< 0)
1596 solver_enablerule(solv
, r
);
1597 IF_POOLDEBUG (SOLV_DEBUG_SOLUTIONS
)
1599 POOL_DEBUG(SOLV_DEBUG_SOLUTIONS
, "@@@ re-enabling ");
1600 solver_printruleclass(solv
, SOLV_DEBUG_SOLUTIONS
, r
);
1604 if (solv
->bestrules_info
)
1607 ni
= solv
->bestrules_end
- solv
->bestrules
;
1608 for (i
= solv
->bestrules_up
- solv
->bestrules
; i
< ni
; i
++)
1609 if (solv
->bestrules_info
[i
] == p
)
1610 solver_enablerule(solv
, solv
->rules
+ solv
->bestrules
+ i
);
1615 /***********************************************************************
1617 *** Infarch rule part
1619 *** Infarch rules make sure the solver uses the best architecture of
1620 *** a package if multiple archetectures are available
1625 solver_addinfarchrules(Solver
*solv
, Map
*addedmap
)
1627 Pool
*pool
= solv
->pool
;
1628 Repo
*installed
= pool
->installed
;
1631 unsigned int a
, bestscore
;
1632 Solvable
*s
, *ps
, *bests
;
1633 Queue badq
, allowedarchs
;
1637 queue_init(&allowedarchs
);
1639 solv
->infarchrules
= solv
->nrules
;
1640 for (i
= 1; i
< pool
->nsolvables
; i
++)
1642 if (i
== SYSTEMSOLVABLE
|| !MAPTST(addedmap
, i
))
1644 s
= pool
->solvables
+ i
;
1648 queue_empty(&allowedarchs
);
1649 FOR_PROVIDES(p
, pp
, s
->name
)
1651 ps
= pool
->solvables
+ p
;
1652 if (ps
->name
!= s
->name
|| !MAPTST(addedmap
, p
))
1658 a
= pool_arch2score(pool
, ps
->arch
);
1659 if (a
!= 1 && installed
&& ps
->repo
== installed
)
1661 if (solv
->dupinvolvedmap_all
|| (solv
->dupinvolvedmap
.size
&& MAPTST(&solv
->dupinvolvedmap
, p
)))
1663 queue_pushunique(&allowedarchs
, ps
->arch
); /* also ok to keep this architecture */
1664 continue; /* but ignore installed solvables when calculating the best arch */
1666 if (a
&& a
!= 1 && (!bestscore
|| a
< bestscore
))
1673 continue; /* not the first in the group */
1675 if (!bestscore
&& allowedarchs
.count
> 1 && pool
->implicitobsoleteusescolors
)
1677 for (j
= 0; j
< allowedarchs
.count
; j
++)
1679 a
= pool_arch2score(pool
, allowedarchs
.elements
[j
]);
1680 if (a
&& a
!= 1 && (!bestscore
|| a
< bestscore
))
1686 continue; /* did not find a score for this group */
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 */
1692 if (allowedarchs
.count
&& pool
->implicitobsoleteusescolors
&& installed
)
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
)
1700 ps
= pool
->solvables
+ p
;
1701 if (ps
->name
!= s
->name
|| ps
->repo
!= installed
|| !MAPTST(addedmap
, p
))
1703 if (solv
->dupinvolvedmap_all
|| (solv
->dupinvolvedmap
.size
&& MAPTST(&solv
->dupinvolvedmap
, p
)))
1705 a
= pool_arch2score(pool
, ps
->arch
);
1708 queue_pushunique(&allowedarchs
, ps
->arch
); /* strange arch, allow */
1711 if (a
== 1 || ((a
^ bestscore
) & 0xffff0000) == 0)
1713 /* have installed package with inferior arch, check if lock-stepped */
1714 FOR_PROVIDES(p2
, pp2
, s
->name
)
1716 Solvable
*s2
= pool
->solvables
+ p2
;
1718 if (p2
== p
|| s2
->name
!= s
->name
|| s2
->evr
!= pool
->solvables
[p
].evr
|| s2
->arch
== pool
->solvables
[p
].arch
)
1720 a2
= pool_arch2score(pool
, s2
->arch
);
1721 if (a2
&& (a2
== 1 || ((a2
^ bestscore
) & 0xffff0000) == 0))
1725 queue_pushunique(&allowedarchs
, ps
->arch
);
1729 /* find all bad packages */
1731 FOR_PROVIDES(p
, pp
, s
->name
)
1733 ps
= pool
->solvables
+ p
;
1734 if (ps
->name
!= s
->name
|| !MAPTST(addedmap
, p
))
1736 a
= pool_arch2score(pool
, ps
->arch
);
1737 if (a
!= 1 && ((a
^ bestscore
) & 0xffff0000) != 0)
1739 if (installed
&& ps
->repo
== installed
)
1741 if (pool
->implicitobsoleteusescolors
)
1742 queue_push(&badq
, p
); /* special lock-step handling, see below */
1743 continue; /* always ok to keep an installed package */
1745 for (j
= 0; j
< allowedarchs
.count
; j
++)
1748 aa
= allowedarchs
.elements
[j
];
1751 aas
= pool_arch2score(pool
, aa
);
1752 if (aas
&& ((a
^ aas
) & 0xffff0000) == 0)
1753 break; /* compatible */
1755 if (j
== allowedarchs
.count
)
1756 queue_push(&badq
, p
);
1760 /* block all solvables in the badq! */
1761 for (j
= 0; j
< badq
.count
; j
++)
1763 p
= badq
.elements
[j
];
1764 /* special lock-step handling */
1765 if (pool
->implicitobsoleteusescolors
)
1768 int haveinstalled
= 0;
1770 FOR_PROVIDES(p2
, pp
, s
->name
)
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
)
1775 a
= pool_arch2score(pool
, s2
->arch
);
1776 if (a
&& (a
== 1 || ((a
^ bestscore
) & 0xffff000) == 0))
1778 queue_push(&lsq
, p2
);
1779 if (installed
&& s2
->repo
== installed
)
1783 if (installed
&& pool
->solvables
[p
].repo
== installed
&& !haveinstalled
)
1784 continue; /* installed package not in lock-step */
1786 solver_addrule(solv
, -p
, lsq
.count
? lsq
.elements
[0] : 0, 0);
1788 solver_addrule(solv
, -p
, 0, pool_queuetowhatprovides(pool
, &lsq
));
1792 solver_addrule(solv
, -p
, 0, 0);
1798 queue_free(&allowedarchs
);
1799 solv
->infarchrules_end
= solv
->nrules
;
1803 disableinfarchrule(Solver
*solv
, Id name
)
1805 Pool
*pool
= solv
->pool
;
1808 for (i
= solv
->infarchrules
, r
= solv
->rules
+ i
; i
< solv
->infarchrules_end
; i
++, r
++)
1810 if (r
->p
< 0 && r
->d
>= 0 && pool
->solvables
[-r
->p
].name
== name
)
1811 solver_disablerule(solv
, r
);
1816 reenableinfarchrule(Solver
*solv
, Id name
)
1818 Pool
*pool
= solv
->pool
;
1821 for (i
= solv
->infarchrules
, r
= solv
->rules
+ i
; i
< solv
->infarchrules_end
; i
++, r
++)
1823 if (r
->p
< 0 && r
->d
< 0 && pool
->solvables
[-r
->p
].name
== name
)
1825 solver_enablerule(solv
, r
);
1826 IF_POOLDEBUG (SOLV_DEBUG_SOLUTIONS
)
1828 POOL_DEBUG(SOLV_DEBUG_SOLUTIONS
, "@@@ re-enabling ");
1829 solver_printruleclass(solv
, SOLV_DEBUG_SOLUTIONS
, r
);
1836 /***********************************************************************
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.
1846 add_cleandeps_updatepkg(Solver
*solv
, Id p
)
1848 if (!solv
->cleandeps_updatepkgs
)
1850 solv
->cleandeps_updatepkgs
= solv_calloc(1, sizeof(Queue
));
1851 queue_init(solv
->cleandeps_updatepkgs
);
1853 queue_pushunique(solv
->cleandeps_updatepkgs
, p
);
1857 solver_addtodupmaps(Solver
*solv
, Id p
, Id how
, int targeted
)
1859 Pool
*pool
= solv
->pool
;
1860 Solvable
*ps
, *s
= pool
->solvables
+ p
;
1861 Repo
*installed
= solv
->installed
;
1862 Id pi
, pip
, obs
, *obsp
;
1864 if (!solv
->dupinvolvedmap
.size
)
1865 map_grow(&solv
->dupinvolvedmap
, pool
->nsolvables
);
1867 MAPSET(&solv
->dupinvolvedmap
, p
);
1869 MAPSET(&solv
->dupmap
, p
);
1870 FOR_PROVIDES(pi
, pip
, s
->name
)
1872 ps
= pool
->solvables
+ pi
;
1873 if (ps
->name
!= s
->name
)
1875 MAPSET(&solv
->dupinvolvedmap
, pi
);
1876 if (targeted
&& ps
->repo
== installed
&& solv
->obsoletes
&& solv
->obsoletes
[pi
- installed
->start
])
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
);
1883 if (ps
->repo
== installed
&& (how
& SOLVER_FORCEBEST
) != 0 && !solv
->bestupdatemap_all
)
1885 if (!solv
->bestupdatemap
.size
)
1886 map_grow(&solv
->bestupdatemap
, installed
->end
- installed
->start
);
1887 MAPSET(&solv
->bestupdatemap
, pi
- installed
->start
);
1889 if (ps
->repo
== installed
&& (how
& SOLVER_CLEANDEPS
) != 0)
1890 add_cleandeps_updatepkg(solv
, pi
);
1891 if (!targeted
&& ps
->repo
!= installed
)
1892 MAPSET(&solv
->dupmap
, pi
);
1894 if (s
->repo
== installed
&& solv
->obsoletes
&& solv
->obsoletes
[p
- installed
->start
])
1897 for (opp
= solv
->obsoletes_data
+ solv
->obsoletes
[p
- installed
->start
]; (pi
= *opp
++) != 0;)
1899 ps
= pool
->solvables
+ pi
;
1900 if (ps
->repo
== installed
)
1902 MAPSET(&solv
->dupinvolvedmap
, pi
);
1904 MAPSET(&solv
->dupmap
, pi
);
1907 if (targeted
&& s
->repo
!= installed
&& s
->obsoletes
)
1909 /* XXX: check obsoletes/provides combination */
1910 obsp
= s
->repo
->idarraydata
+ s
->obsoletes
;
1911 while ((obs
= *obsp
++) != 0)
1913 FOR_PROVIDES(pi
, pip
, obs
)
1915 Solvable
*ps
= pool
->solvables
+ pi
;
1916 if (!pool
->obsoleteusesprovides
&& !pool_match_nevr(pool
, ps
, obs
))
1918 if (pool
->obsoleteusescolors
&& !pool_colormatch(pool
, s
, ps
))
1920 MAPSET(&solv
->dupinvolvedmap
, pi
);
1921 if (targeted
&& ps
->repo
== installed
&& solv
->obsoletes
&& solv
->obsoletes
[pi
- installed
->start
])
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
);
1928 if (ps
->repo
== installed
&& (how
& SOLVER_FORCEBEST
) != 0 && !solv
->bestupdatemap_all
)
1930 if (!solv
->bestupdatemap
.size
)
1931 map_grow(&solv
->bestupdatemap
, installed
->end
- installed
->start
);
1932 MAPSET(&solv
->bestupdatemap
, pi
- installed
->start
);
1934 if (ps
->repo
== installed
&& (how
& SOLVER_CLEANDEPS
) != 0)
1935 add_cleandeps_updatepkg(solv
, pi
);
1941 /* create the two dupmaps:
1942 * - dupmap: packages in that map are good to install/keep
1943 * - dupinvolvedmap: packages are subject to dup mode
1946 solver_createdupmaps(Solver
*solv
)
1948 Pool
*pool
= solv
->pool
;
1949 Queue
*job
= &solv
->job
;
1950 Repo
*installed
= solv
->installed
;
1951 Id select
, how
, what
, p
, pp
;
1955 map_init(&solv
->dupmap
, pool
->nsolvables
);
1956 solv
->dupinvolvedmap_all
= 0;
1957 map_init(&solv
->dupinvolvedmap
, 0);
1958 for (i
= 0; i
< job
->count
; i
+= 2)
1960 how
= job
->elements
[i
];
1961 select
= job
->elements
[i
] & SOLVER_SELECTMASK
;
1962 what
= job
->elements
[i
+ 1];
1963 switch (how
& SOLVER_JOBMASK
)
1965 case SOLVER_DISTUPGRADE
:
1966 if (select
== SOLVER_SOLVABLE_REPO
)
1969 if (what
<= 0 || what
> pool
->nrepos
)
1971 repo
= pool_id2repo(pool
, what
);
1974 if (repo
!= installed
&& !(how
& SOLVER_TARGETED
) && solv
->noautotarget
)
1976 targeted
= repo
!= installed
|| (how
& SOLVER_TARGETED
) != 0;
1977 FOR_REPO_SOLVABLES(repo
, p
, s
)
1979 if (repo
!= installed
&& !pool_installable(pool
, s
))
1981 solver_addtodupmaps(solv
, p
, how
, targeted
);
1984 else if (select
== SOLVER_SOLVABLE_ALL
)
1986 solv
->dupinvolvedmap_all
= 1;
1987 FOR_POOL_SOLVABLES(p
)
1989 Solvable
*s
= pool
->solvables
+ p
;
1990 if (!s
->repo
|| s
->repo
== installed
)
1992 if (!pool_installable(pool
, s
))
1994 MAPSET(&solv
->dupmap
, p
);
1996 if ((how
& SOLVER_FORCEBEST
) != 0)
1997 solv
->bestupdatemap_all
= 1;
1998 if ((how
& SOLVER_CLEANDEPS
) != 0 && installed
)
2000 FOR_REPO_SOLVABLES(installed
, p
, s
)
2001 add_cleandeps_updatepkg(solv
, p
);
2006 targeted
= how
& SOLVER_TARGETED
? 1 : 0;
2007 if (installed
&& !targeted
&& !solv
->noautotarget
)
2009 FOR_JOB_SELECT(p
, pp
, select
, what
)
2010 if (pool
->solvables
[p
].repo
== installed
)
2014 else if (!installed
&& !solv
->noautotarget
)
2016 FOR_JOB_SELECT(p
, pp
, select
, what
)
2018 Solvable
*s
= pool
->solvables
+ p
;
2021 if (s
->repo
!= installed
&& !targeted
)
2023 if (s
->repo
!= installed
&& !pool_installable(pool
, s
))
2025 solver_addtodupmaps(solv
, p
, how
, targeted
);
2033 if (solv
->dupinvolvedmap
.size
)
2034 MAPCLR(&solv
->dupinvolvedmap
, SYSTEMSOLVABLE
);
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;
2039 else if (installed
&& !solv
->updatemap_all
&& solv
->dupinvolvedmap
.size
)
2041 FOR_REPO_SOLVABLES(installed
, p
, s
)
2043 if (!MAPTST(&solv
->dupinvolvedmap
, p
))
2045 if (!solv
->updatemap
.size
)
2046 map_grow(&solv
->updatemap
, installed
->end
- installed
->start
);
2047 MAPSET(&solv
->updatemap
, p
- installed
->start
);
2053 solver_freedupmaps(Solver
*solv
)
2055 map_free(&solv
->dupmap
);
2056 /* we no longer free solv->dupinvolvedmap as we need it in
2057 * policy's priority pruning code. sigh. */
2061 solver_addduprules(Solver
*solv
, Map
*addedmap
)
2063 Pool
*pool
= solv
->pool
;
2064 Repo
*installed
= solv
->installed
;
2070 solv
->duprules
= solv
->nrules
;
2071 for (i
= 1; i
< pool
->nsolvables
; i
++)
2073 if (i
== SYSTEMSOLVABLE
|| !MAPTST(addedmap
, i
))
2075 s
= pool
->solvables
+ i
;
2077 FOR_PROVIDES(p
, pp
, s
->name
)
2079 ps
= pool
->solvables
+ p
;
2080 if (ps
->name
!= s
->name
|| !MAPTST(addedmap
, p
))
2086 if (!solv
->dupinvolvedmap_all
&& !MAPTST(&solv
->dupinvolvedmap
, p
))
2088 if (installed
&& ps
->repo
== installed
)
2090 if (pool
->considered
&& pool_disabled_solvable(pool
, ps
))
2091 continue; /* always keep disabled installed packages */
2092 if (!MAPTST(&solv
->dupmap
, p
))
2095 /* is installed identical to a good one? */
2096 FOR_PROVIDES(ip
, ipp
, ps
->name
)
2098 Solvable
*is
= pool
->solvables
+ ip
;
2099 if (!MAPTST(&solv
->dupmap
, ip
))
2101 if (is
->evr
== ps
->evr
&& solvable_identical(ps
, is
))
2106 /* ok, identical to a good one. we may keep this package. */
2107 MAPSET(&solv
->dupmap
, p
); /* for best rules processing */
2110 /* check if it's orphaned. If yes, we may keep it */
2111 r
= solv
->rules
+ solv
->updaterules
+ (p
- installed
->start
);
2113 r
= solv
->rules
+ solv
->featurerules
+ (p
- installed
->start
);
2116 /* no update/feature rule, this is an orphan */
2117 MAPSET(&solv
->dupmap
, p
); /* for best rules processing */
2120 if (solv
->specialupdaters
&& solv
->specialupdaters
[p
- installed
->start
])
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
]);
2126 if (r
->p
== p
&& !r
->d
&& !r
->w2
)
2128 r
= solv
->rules
+ solv
->featurerules
+ (p
- installed
->start
);
2129 if (!r
->p
|| (!r
->d
&& !r
->w2
))
2131 /* this is an orphan */
2132 MAPSET(&solv
->dupmap
, p
); /* for best rules processing */
2136 solver_addrule(solv
, -p
, 0, 0); /* no match, sorry */
2139 else if (!MAPTST(&solv
->dupmap
, p
))
2140 solver_addrule(solv
, -p
, 0, 0);
2143 solv
->duprules_end
= solv
->nrules
;
2148 disableduprule(Solver
*solv
, Id name
)
2150 Pool
*pool
= solv
->pool
;
2153 for (i
= solv
->duprules
, r
= solv
->rules
+ i
; i
< solv
->duprules_end
; i
++, r
++)
2155 if (r
->p
< 0 && r
->d
>= 0 && pool
->solvables
[-r
->p
].name
== name
)
2156 solver_disablerule(solv
, r
);
2161 reenableduprule(Solver
*solv
, Id name
)
2163 Pool
*pool
= solv
->pool
;
2166 for (i
= solv
->duprules
, r
= solv
->rules
+ i
; i
< solv
->duprules_end
; i
++, r
++)
2168 if (r
->p
< 0 && r
->d
< 0 && pool
->solvables
[-r
->p
].name
== name
)
2170 solver_enablerule(solv
, r
);
2171 IF_POOLDEBUG (SOLV_DEBUG_SOLUTIONS
)
2173 POOL_DEBUG(SOLV_DEBUG_SOLUTIONS
, "@@@ re-enabling ");
2174 solver_printruleclass(solv
, SOLV_DEBUG_SOLUTIONS
, r
);
2180 /***********************************************************************
2186 disableblackrule(Solver
*solv
, Id p
)
2190 for (i
= solv
->blackrules
, r
= solv
->rules
+ i
; i
< solv
->blackrules_end
; i
++, r
++)
2192 solver_disablerule(solv
, r
);
2196 reenableblackrule(Solver
*solv
, Id p
)
2198 Pool
*pool
= solv
->pool
;
2201 for (i
= solv
->blackrules
, r
= solv
->rules
+ i
; i
< solv
->blackrules_end
; i
++, r
++)
2204 solver_enablerule(solv
, r
);
2205 IF_POOLDEBUG (SOLV_DEBUG_SOLUTIONS
)
2207 POOL_DEBUG(SOLV_DEBUG_SOLUTIONS
, "@@@ re-enabling ");
2208 solver_printruleclass(solv
, SOLV_DEBUG_SOLUTIONS
, r
);
2214 solver_addblackrules(Solver
*solv
)
2216 Pool
*pool
= solv
->pool
;
2217 Repo
*installed
= solv
->installed
;
2218 Id how
, select
, what
, p
, pp
;
2219 Queue
*job
= &solv
->job
;
2223 map_init(&updatemap
, 0);
2224 solv
->blackrules
= solv
->nrules
;
2227 for (i
= 0; i
< job
->count
; i
+= 2)
2229 how
= job
->elements
[i
];
2230 select
= job
->elements
[i
] & SOLVER_SELECTMASK
;
2231 what
= job
->elements
[i
+ 1];
2232 switch (how
& SOLVER_JOBMASK
)
2234 case SOLVER_BLACKLIST
:
2235 FOR_JOB_SELECT(p
, pp
, select
, what
)
2237 Solvable
*s
= pool
->solvables
+ p
;
2238 if (s
->repo
!= installed
)
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
);
2248 for (i
= 0; i
< job
->count
; i
+= 2)
2250 how
= job
->elements
[i
];
2251 select
= job
->elements
[i
] & SOLVER_SELECTMASK
;
2252 what
= job
->elements
[i
+ 1];
2253 switch (how
& SOLVER_JOBMASK
)
2255 case SOLVER_BLACKLIST
:
2256 FOR_JOB_SELECT(p
, pp
, select
, what
)
2258 Solvable
*s
= pool
->solvables
+ p
;
2259 if (s
->repo
== installed
)
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);
2268 map_free(&updatemap
);
2269 solv
->blackrules_end
= solv
->nrules
;
2272 /***********************************************************************
2274 *** Strict repo prio rule part
2277 /* add rules to exclude solvables provided by lower
2278 * precedence repositories */
2279 void solver_addstrictrepopriorules(struct s_Solver
*solv
, Map
*addedmap
)
2281 Pool
*pool
= solv
->pool
;
2287 map_init_clone(&priomap
, addedmap
);
2288 solv
->strictrepopriorules
= solv
->nrules
;
2290 FOR_POOL_SOLVABLES(p
)
2292 if (!MAPTST(&priomap
, p
))
2295 s
= pool
->solvables
+ p
;
2296 max_prio
= s
->repo
->priority
;
2297 FOR_PROVIDES(p2
, pp2
, s
->name
)
2299 Solvable
*s2
= pool
->solvables
+ p2
;
2300 if (s
->name
!= s2
->name
)
2302 if (s2
->repo
->priority
> max_prio
)
2303 max_prio
= s2
->repo
->priority
;
2306 FOR_PROVIDES(p2
, pp2
, s
->name
)
2308 Solvable
*s2
= pool
->solvables
+ p2
;
2309 if (s
->name
!= s2
->name
|| !MAPTST(&priomap
, p2
))
2311 MAPCLR(&priomap
, p2
);
2312 if (pool
->installed
&& s2
->repo
== pool
->installed
)
2314 if (s2
->repo
->priority
< max_prio
)
2315 solver_addrule(solv
, -p2
, 0, 0);
2318 solv
->strictrepopriorules_end
= solv
->nrules
;
2323 disablerepopriorule(Solver
*solv
, Id name
)
2325 Pool
*pool
= solv
->pool
;
2328 for (i
= solv
->strictrepopriorules
, r
= solv
->rules
+ i
; i
< solv
->strictrepopriorules_end
; i
++, r
++)
2330 if (r
->p
< 0 && r
->d
>= 0 && pool
->solvables
[-r
->p
].name
== name
)
2331 solver_disablerule(solv
, r
);
2336 reenablerepopriorule(Solver
*solv
, Id name
)
2338 Pool
*pool
= solv
->pool
;
2341 for (i
= solv
->strictrepopriorules
, r
= solv
->rules
+ i
; i
< solv
->strictrepopriorules_end
; i
++, r
++)
2343 if (r
->p
< 0 && r
->d
< 0 && pool
->solvables
[-r
->p
].name
== name
)
2345 solver_enablerule(solv
, r
);
2346 IF_POOLDEBUG (SOLV_DEBUG_SOLUTIONS
)
2348 POOL_DEBUG(SOLV_DEBUG_SOLUTIONS
, "@@@ re-enabling ");
2349 solver_printruleclass(solv
, SOLV_DEBUG_SOLUTIONS
, r
);
2355 /***********************************************************************
2357 *** Policy rule disabling/reenabling
2359 *** Disable all policy rules that conflict with our jobs. If a job
2360 *** gets disabled later on, reenable the involved policy rules again.
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
2370 /* check if installed package p is in lock-step with another installed package */
2372 installed_is_in_lockstep(Solver
*solv
, Id p
)
2374 Pool
*pool
= solv
->pool
;
2375 Repo
*installed
= solv
->installed
;
2382 for (rid
= solv
->infarchrules
, r
= solv
->rules
+ rid
; rid
< solv
->infarchrules_end
; rid
++, r
++)
2386 if (pool
->solvables
[-r
->p
].repo
!= installed
)
2388 FOR_RULELITERALS(l
, pp
, r
)
2396 jobtodisablelist(Solver
*solv
, Id how
, Id what
, Queue
*q
)
2398 Pool
*pool
= solv
->pool
;
2402 int i
, j
, set
, qstart
;
2405 installed
= solv
->installed
;
2406 select
= how
& SOLVER_SELECTMASK
;
2407 switch (how
& SOLVER_JOBMASK
)
2409 case SOLVER_INSTALL
:
2410 set
= how
& SOLVER_SETMASK
;
2411 if (!(set
& SOLVER_NOAUTOSET
))
2413 /* automatically add set bits by analysing the job */
2414 if (select
== SOLVER_SOLVABLE_NAME
)
2415 set
|= SOLVER_SETNAME
;
2416 if (select
== SOLVER_SOLVABLE
)
2417 set
|= SOLVER_SETNAME
| SOLVER_SETARCH
| SOLVER_SETVENDOR
| SOLVER_SETREPO
| SOLVER_SETEVR
;
2418 else if ((select
== SOLVER_SOLVABLE_NAME
|| select
== SOLVER_SOLVABLE_PROVIDES
) && ISRELDEP(what
))
2420 Reldep
*rd
= GETRELDEP(pool
, what
);
2421 if (rd
->flags
== REL_EQ
&& select
== SOLVER_SOLVABLE_NAME
)
2423 if (pool
->disttype
!= DISTTYPE_DEB
)
2425 const char *rel
= strrchr(pool_id2str(pool
, rd
->evr
), '-');
2426 set
|= rel
? SOLVER_SETEVR
: SOLVER_SETEV
;
2429 set
|= SOLVER_SETEVR
;
2431 if (rd
->flags
<= 7 && ISRELDEP(rd
->name
))
2432 rd
= GETRELDEP(pool
, rd
->name
);
2433 if (rd
->flags
== REL_ARCH
)
2434 set
|= SOLVER_SETARCH
;
2438 set
&= ~SOLVER_NOAUTOSET
;
2441 if ((set
& SOLVER_SETARCH
) != 0 && solv
->infarchrules
!= solv
->infarchrules_end
)
2443 if (select
== SOLVER_SOLVABLE
)
2445 for (i
= solv
->infarchrules
; i
< solv
->infarchrules_end
; i
++)
2446 if (solv
->rules
[i
].p
== -what
)
2448 if (i
< solv
->infarchrules_end
)
2449 queue_push2(q
, DISABLE_INFARCH
, pool
->solvables
[what
].name
);
2453 int qcnt
= q
->count
;
2454 /* does not work for SOLVER_SOLVABLE_ALL and SOLVER_SOLVABLE_REPO, but
2455 they are not useful for SOLVER_INSTALL jobs anyway */
2456 FOR_JOB_SELECT(p
, pp
, select
, what
)
2458 s
= pool
->solvables
+ p
;
2460 for (i
= qcnt
; i
< q
->count
; i
+= 2)
2461 if (q
->elements
[i
+ 1] == s
->name
)
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
)
2468 if (i
< solv
->infarchrules_end
)
2469 queue_push2(q
, DISABLE_INFARCH
, s
->name
);
2473 if ((set
& SOLVER_SETREPO
) != 0 && solv
->duprules
!= solv
->duprules_end
)
2475 if (select
== SOLVER_SOLVABLE
)
2476 queue_push2(q
, DISABLE_DUP
, pool
->solvables
[what
].name
);
2479 int qcnt
= q
->count
;
2480 FOR_JOB_SELECT(p
, pp
, select
, what
)
2482 s
= pool
->solvables
+ p
;
2484 for (i
= qcnt
; i
< q
->count
; i
+= 2)
2485 if (q
->elements
[i
+ 1] == s
->name
)
2489 queue_push2(q
, DISABLE_DUP
, s
->name
);
2493 if ((set
& SOLVER_SETREPO
) != 0 && solv
->strictrepopriorules
!= solv
->strictrepopriorules_end
)
2495 if (select
== SOLVER_SOLVABLE
)
2496 queue_push2(q
, DISABLE_REPOPRIO
, pool
->solvables
[what
].name
);
2499 int qcnt
= q
->count
;
2500 FOR_JOB_SELECT(p
, pp
, select
, what
)
2502 s
= pool
->solvables
+ p
;
2504 for (i
= qcnt
; i
< q
->count
; i
+= 2)
2505 if (q
->elements
[i
+ 1] == s
->name
)
2509 queue_push2(q
, DISABLE_REPOPRIO
, s
->name
);
2513 if ((set
& SOLVER_SETEVR
) != 0 && solv
->blackrules
!= solv
->blackrules_end
)
2515 if (select
== SOLVER_SOLVABLE
)
2516 queue_push2(q
, DISABLE_BLACK
, what
);
2519 FOR_JOB_SELECT(p
, pp
, select
, what
)
2520 queue_push2(q
, DISABLE_BLACK
, p
);
2523 if (!installed
|| installed
->end
== installed
->start
)
2525 /* now the hard part: disable some update rules */
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
))
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
)
2535 queue_push2(q
, DISABLE_UPDATE
, what
); /* will also disable the best rule */
2541 /* first check if we have installed or multiversion packages in the job */
2542 FOR_JOB_SELECT(p
, pp
, select
, what
)
2544 if (pool
->solvables
[p
].repo
== installed
)
2546 if (solv
->multiversion
.size
&& MAPTST(&solv
->multiversion
, p
) && !solv
->keepexplicitobsoletes
)
2547 return; /* will not obsolete anything, so just return */
2551 FOR_JOB_SELECT(p
, pp
, select
, what
)
2553 solver_intersect_obsoleted(solv
, p
, q
, qstart
, &omap
);
2554 if (q
->count
== qstart
)
2560 if (qstart
== q
->count
)
2561 return; /* nothing to prune */
2563 /* convert result to (DISABLE_UPDATE, p) pairs */
2565 for (j
= qstart
; j
< i
; j
++)
2566 queue_push(q
, q
->elements
[j
]);
2567 for (j
= qstart
; j
< q
->count
; j
+= 2)
2569 q
->elements
[j
] = DISABLE_UPDATE
;
2570 q
->elements
[j
+ 1] = q
->elements
[i
++];
2573 /* now that we know which installed packages are obsoleted check each of them */
2574 if ((set
& (SOLVER_SETEVR
| SOLVER_SETARCH
| SOLVER_SETVENDOR
)) == (SOLVER_SETEVR
| SOLVER_SETARCH
| SOLVER_SETVENDOR
))
2575 return; /* all is set, nothing to do */
2577 for (i
= j
= qstart
; i
< q
->count
; i
+= 2)
2579 Solvable
*is
= pool
->solvables
+ q
->elements
[i
+ 1];
2580 FOR_JOB_SELECT(p
, pp
, select
, what
)
2583 s
= pool
->solvables
+ p
;
2584 if ((set
& SOLVER_SETEVR
) != 0)
2585 illegal
|= POLICY_ILLEGAL_DOWNGRADE
; /* ignore */
2586 if ((set
& SOLVER_SETNAME
) != 0)
2587 illegal
|= POLICY_ILLEGAL_NAMECHANGE
; /* ignore */
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)
2595 /* it's ok if the EV is different */
2596 if (pool_evrcmp(pool
, is
->evr
, s
->evr
, EVRCMP_COMPARE_EVONLY
) != 0)
2604 /* no package conflicts with the update rule */
2605 /* thus keep the DISABLE_UPDATE */
2606 q
->elements
[j
+ 1] = q
->elements
[i
+ 1];
2610 queue_truncate(q
, j
);
2616 set
= how
& SOLVER_SETMASK
;
2617 if (!(set
& (SOLVER_NOAUTOSET
| SOLVER_SETARCH
)) && pool
->implicitobsoleteusescolors
&& solv
->infarchrules
!= solv
->infarchrules_end
)
2619 if (select
== SOLVER_SOLVABLE
)
2620 set
|= SOLVER_SETARCH
;
2621 else if ((select
== SOLVER_SOLVABLE_NAME
|| select
== SOLVER_SOLVABLE_PROVIDES
) && ISRELDEP(what
))
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
;
2630 if (select
== SOLVER_SOLVABLE_ALL
|| (select
== SOLVER_SOLVABLE_REPO
&& what
== installed
->repoid
))
2632 FOR_REPO_SOLVABLES(installed
, p
, s
)
2633 queue_push2(q
, DISABLE_UPDATE
, p
);
2635 FOR_JOB_SELECT(p
, pp
, select
, what
)
2636 if (pool
->solvables
[p
].repo
== installed
)
2638 queue_push2(q
, DISABLE_UPDATE
, p
);
2639 if ((set
& SOLVER_SETARCH
) != 0 && pool
->implicitobsoleteusescolors
&& solv
->infarchrules
!= solv
->infarchrules_end
)
2640 if (installed_is_in_lockstep(solv
, p
))
2641 queue_push2(q
, DISABLE_INFARCH
, pool
->solvables
[p
].name
); /* allow to break the lock-step */
2642 #ifdef ENABLE_LINKED_PKGS
2643 if (solv
->instbuddy
&& solv
->instbuddy
[p
- installed
->start
] > 1)
2644 queue_push2(q
, DISABLE_UPDATE
, solv
->instbuddy
[p
- installed
->start
]);
2653 if (select
== SOLVER_SOLVABLE_ALL
|| (select
== SOLVER_SOLVABLE_REPO
&& what
== installed
->repoid
))
2655 FOR_REPO_SOLVABLES(installed
, p
, s
)
2657 for (i
= qstart
; i
< q
->count
; i
+= 2)
2658 if (q
->elements
[i
] == DISABLE_DUP
&& q
->elements
[i
+ 1] == pool
->solvables
[p
].name
)
2661 queue_push2(q
, DISABLE_DUP
, pool
->solvables
[p
].name
);
2664 FOR_JOB_SELECT(p
, pp
, select
, what
)
2666 if (pool
->solvables
[p
].repo
!= installed
)
2668 for (i
= qstart
; i
< q
->count
; i
+= 2)
2669 if (q
->elements
[i
] == DISABLE_DUP
&& q
->elements
[i
+ 1] == pool
->solvables
[p
].name
)
2672 queue_push2(q
, DISABLE_DUP
, pool
->solvables
[p
].name
);
2681 /* disable all policy rules that are in conflict with our job list */
2683 solver_disablepolicyrules(Solver
*solv
)
2685 Queue
*job
= &solv
->job
;
2692 queue_init_buffer(&allq
, allqbuf
, sizeof(allqbuf
)/sizeof(*allqbuf
));
2694 for (i
= solv
->jobrules
; i
< solv
->jobrules_end
; i
++)
2696 r
= solv
->rules
+ i
;
2697 if (r
->d
< 0) /* disabled? */
2699 j
= solv
->ruletojob
.elements
[i
- solv
->jobrules
];
2703 jobtodisablelist(solv
, job
->elements
[j
], job
->elements
[j
+ 1], &allq
);
2705 if (solv
->cleandepsmap
.size
)
2707 solver_createcleandepsmap(solv
, &solv
->cleandepsmap
, 0);
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
);
2712 MAPZERO(&solv
->noupdate
);
2713 for (i
= 0; i
< allq
.count
; i
+= 2)
2715 Id type
= allq
.elements
[i
], arg
= allq
.elements
[i
+ 1];
2718 case DISABLE_UPDATE
:
2719 disableupdaterule(solv
, arg
);
2721 case DISABLE_INFARCH
:
2722 disableinfarchrule(solv
, arg
);
2725 disableduprule(solv
, arg
);
2728 disableblackrule(solv
, arg
);
2730 case DISABLE_REPOPRIO
:
2731 disablerepopriorule(solv
, arg
);
2740 /* we just disabled job #jobidx, now reenable all policy rules that were
2741 * disabled because of this job */
2743 solver_reenablepolicyrules(Solver
*solv
, int jobidx
)
2745 Queue
*job
= &solv
->job
;
2750 Id qbuf
[32], allqbuf
[32];
2752 queue_init_buffer(&q
, qbuf
, sizeof(qbuf
)/sizeof(*qbuf
));
2753 jobtodisablelist(solv
, job
->elements
[jobidx
- 1], job
->elements
[jobidx
], &q
);
2759 /* now remove everything from q that is disabled by other jobs */
2761 /* first remove cleandeps packages, they count as DISABLE_UPDATE */
2762 if (solv
->cleandepsmap
.size
)
2764 solver_createcleandepsmap(solv
, &solv
->cleandepsmap
, 0);
2765 for (j
= k
= 0; j
< q
.count
; j
+= 2)
2767 if (q
.elements
[j
] == DISABLE_UPDATE
)
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 */
2773 q
.elements
[k
++] = q
.elements
[j
];
2774 q
.elements
[k
++] = q
.elements
[j
+ 1];
2784 /* now go through the disable list of all other jobs */
2785 queue_init_buffer(&allq
, allqbuf
, sizeof(allqbuf
)/sizeof(*allqbuf
));
2786 for (i
= solv
->jobrules
; i
< solv
->jobrules_end
; i
++)
2788 r
= solv
->rules
+ i
;
2789 if (r
->d
< 0) /* disabled? */
2791 j
= solv
->ruletojob
.elements
[i
- solv
->jobrules
];
2795 jobtodisablelist(solv
, job
->elements
[j
], job
->elements
[j
+ 1], &allq
);
2798 /* remove all elements in allq from q */
2799 for (j
= k
= 0; j
< q
.count
; j
+= 2)
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
)
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];
2821 /* now re-enable anything that's left in q */
2822 for (j
= 0; j
< q
.count
; j
+= 2)
2824 Id type
= q
.elements
[j
], arg
= q
.elements
[j
+ 1];
2827 case DISABLE_UPDATE
:
2828 reenableupdaterule(solv
, arg
);
2830 case DISABLE_INFARCH
:
2831 reenableinfarchrule(solv
, arg
);
2834 reenableduprule(solv
, arg
);
2837 reenableblackrule(solv
, arg
);
2839 case DISABLE_REPOPRIO
:
2840 reenablerepopriorule(solv
, arg
);
2847 /* we just removed a package from the cleandeps map, now reenable all policy rules that were
2848 * disabled because of this */
2850 solver_reenablepolicyrules_cleandeps(Solver
*solv
, Id pkg
)
2852 Queue
*job
= &solv
->job
;
2859 queue_init_buffer(&allq
, allqbuf
, sizeof(allqbuf
)/sizeof(*allqbuf
));
2860 for (i
= solv
->jobrules
; i
< solv
->jobrules_end
; i
++)
2862 r
= solv
->rules
+ i
;
2863 if (r
->d
< 0) /* disabled? */
2865 j
= solv
->ruletojob
.elements
[i
- solv
->jobrules
];
2869 jobtodisablelist(solv
, job
->elements
[j
], job
->elements
[j
+ 1], &allq
);
2871 for (i
= 0; i
< allq
.count
; i
+= 2)
2872 if (allq
.elements
[i
] == DISABLE_UPDATE
&& allq
.elements
[i
+ 1] == pkg
)
2874 if (i
== allq
.count
)
2875 reenableupdaterule(solv
, pkg
);
2880 /***********************************************************************
2882 *** Rule info part, tell the user what the rule is about.
2887 addpkgruleinfo(Solver
*solv
, Id p
, Id p2
, Id d
, int type
, Id dep
)
2889 Pool
*pool
= solv
->pool
;
2894 assert(!p2
&& d
> 0);
2895 if (!pool
->whatprovidesdata
[d
])
2897 else if (!pool
->whatprovidesdata
[d
+ 1])
2899 p2
= pool
->whatprovidesdata
[d
];
2904 /* check if this creates the rule we're searching for */
2905 r
= solv
->rules
+ solv
->ruleinfoq
->elements
[0];
2908 /* three or more literals */
2909 Id od
= r
->d
< 0 ? -r
->d
- 1 : r
->d
;
2910 if (p
!= r
->p
&& !od
)
2914 Id
*dp
= pool
->whatprovidesdata
+ d
;
2915 Id
*odp
= pool
->whatprovidesdata
+ od
;
2917 if (*dp
++ != *odp
++)
2922 /* set p2 for multiversion conflicts */
2923 if (p
< 0 && pool
->whatprovidesdata
[d
] < 0 && pool
->whatprovidesdata
[d
+ 1] >= 0 && type
== SOLVER_RULE_PKG_CONFLICTS
)
2924 p2
= pool
->whatprovidesdata
[d
];
2928 /* one or two literals */
2929 Id op
= p
, op2
= p2
;
2930 if (op2
&& op
> op2
) /* normalize */
2936 if (r
->p
!= op
|| r
->w2
!= op2
|| (r
->d
&& r
->d
!= -1))
2938 if (type
== SOLVER_RULE_PKG_CONFLICTS
&& !p2
)
2939 p2
= -SYSTEMSOLVABLE
;
2940 if (type
== SOLVER_RULE_PKG_SAME_NAME
)
2942 p
= op
; /* we normalize same name order */
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
);
2954 solver_allruleinfos_cmp(const void *ap
, const void *bp
, void *dp
)
2956 const Id
*a
= ap
, *b
= bp
;
2975 getpkgruleinfos(Solver
*solv
, Rule
*r
, Queue
*rq
)
2977 Pool
*pool
= solv
->pool
;
2981 queue_push(rq
, r
- solv
->rules
); /* push the rule we're interested in */
2982 solv
->ruleinfoq
= rq
;
2983 FOR_RULELITERALS(l
, pp
, r
)
2987 solver_addpkgrulesforsolvable(solv
, pool
->solvables
- l
, 0);
2989 #ifdef ENABLE_LINKED_PKGS
2990 FOR_RULELITERALS(l
, pp
, r
)
2998 if (!strchr(pool_id2str(pool
, pool
->solvables
[l
].name
), ':') || !has_package_link(pool
, pool
->solvables
+ l
))
3000 add_package_link(solv
, pool
->solvables
+ l
, 0, 0);
3003 solv
->ruleinfoq
= 0;
3008 solver_allruleinfos(Solver
*solv
, Id rid
, Queue
*rq
)
3010 Rule
*r
= solv
->rules
+ rid
;
3014 if (rid
<= 0 || rid
>= solv
->pkgrules_end
)
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
);
3021 queue_push(rq
, dep
);
3024 getpkgruleinfos(solv
, r
, rq
);
3025 /* now sort & unify em */
3028 solv_sort(rq
->elements
, rq
->count
/ 4, 4 * sizeof(Id
), solver_allruleinfos_cmp
, 0);
3029 /* throw out identical entries */
3030 for (i
= j
= 0; i
< rq
->count
; i
+= 4)
3034 if (rq
->elements
[i
] == rq
->elements
[j
- 4] &&
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])
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];
3050 solver_ruleinfo(Solver
*solv
, Id rid
, Id
*fromp
, Id
*top
, Id
*depp
)
3052 Pool
*pool
= solv
->pool
;
3053 Rule
*r
= solv
->rules
+ rid
;
3054 SolverRuleinfo type
= SOLVER_RULE_UNKNOWN
;
3062 if (rid
> 0 && rid
< solv
->pkgrules_end
)
3068 return SOLVER_RULE_PKG
;
3072 getpkgruleinfos(solv
, r
, &rq
);
3073 type
= SOLVER_RULE_PKG
;
3074 for (i
= 0; i
< rq
.count
; i
+= 4)
3077 qt
= rq
.elements
[i
];
3078 qp
= rq
.elements
[i
+ 1];
3079 qo
= rq
.elements
[i
+ 2];
3080 qd
= rq
.elements
[i
+ 3];
3081 if (type
== SOLVER_RULE_PKG
|| qt
== SOLVER_RULE_PKG_SAME_NAME
|| type
> qt
)
3090 if (qt
== SOLVER_RULE_PKG_SAME_NAME
)
3091 break; /* prefer SOLVER_RULE_PKG_SAME_NAME */
3097 if (rid
>= solv
->jobrules
&& rid
< solv
->jobrules_end
)
3099 Id jidx
= solv
->ruletojob
.elements
[rid
- solv
->jobrules
];
3103 *top
= solv
->job
.elements
[jidx
];
3105 *depp
= solv
->job
.elements
[jidx
+ 1];
3106 if ((r
->d
== 0 || r
->d
== -1) && r
->w2
== 0 && r
->p
== -SYSTEMSOLVABLE
)
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
))
3112 return SOLVER_RULE_JOB_NOTHING_PROVIDES_DEP
;
3113 if ((how
& (SOLVER_JOBMASK
|SOLVER_SELECTMASK
)) == (SOLVER_ERASE
|SOLVER_SOLVABLE_NAME
))
3114 return SOLVER_RULE_JOB_PROVIDED_BY_SYSTEM
;
3115 if ((how
& (SOLVER_JOBMASK
|SOLVER_SELECTMASK
)) == (SOLVER_ERASE
|SOLVER_SOLVABLE_PROVIDES
))
3116 return SOLVER_RULE_JOB_PROVIDED_BY_SYSTEM
;
3117 return SOLVER_RULE_JOB_UNSUPPORTED
;
3119 return SOLVER_RULE_JOB
;
3121 if (rid
>= solv
->updaterules
&& rid
< solv
->updaterules_end
)
3124 *fromp
= solv
->installed
->start
+ (rid
- solv
->updaterules
);
3125 return SOLVER_RULE_UPDATE
;
3127 if (rid
>= solv
->featurerules
&& rid
< solv
->featurerules_end
)
3130 *fromp
= solv
->installed
->start
+ (rid
- solv
->featurerules
);
3131 return SOLVER_RULE_FEATURE
;
3133 if (rid
>= solv
->duprules
&& rid
< solv
->duprules_end
)
3138 *depp
= pool
->solvables
[-r
->p
].name
;
3139 return SOLVER_RULE_DISTUPGRADE
;
3141 if (rid
>= solv
->infarchrules
&& rid
< solv
->infarchrules_end
)
3146 *depp
= pool
->solvables
[-r
->p
].name
;
3147 return SOLVER_RULE_INFARCH
;
3149 if (rid
>= solv
->bestrules
&& rid
< solv
->bestrules_end
)
3151 /* > 0: the package we are updating */
3152 if (fromp
&& solv
->bestrules_info
[rid
- solv
->bestrules
] > 0)
3153 *fromp
= solv
->bestrules_info
[rid
- solv
->bestrules
];
3154 /* < 0: the job rule */
3155 if (top
&& solv
->bestrules_info
[rid
- solv
->bestrules
] < 0)
3156 *top
= -solv
->bestrules_info
[rid
- solv
->bestrules
];
3157 return SOLVER_RULE_BEST
;
3159 if (rid
>= solv
->yumobsrules
&& rid
< solv
->yumobsrules_end
)
3165 /* first solvable is enough, we just need it for the name */
3166 if (!r
->d
|| r
->d
== -1)
3169 *top
= pool
->whatprovidesdata
[r
->d
< 0 ? -r
->d
: r
->d
];
3172 *depp
= solv
->yumobsrules_info
[rid
- solv
->yumobsrules
];
3173 return SOLVER_RULE_YUMOBS
;
3175 if (rid
>= solv
->blackrules
&& rid
< solv
->blackrules_end
)
3179 return SOLVER_RULE_BLACK
;
3181 if (rid
>= solv
->strictrepopriorules
&& rid
< solv
->strictrepopriorules_end
)
3185 return SOLVER_RULE_STRICT_REPO_PRIORITY
;
3187 if (rid
>= solv
->choicerules
&& rid
< solv
->choicerules_end
)
3189 if (solv
->choicerules_info
&& fromp
)
3190 *fromp
= solv
->choicerules_info
[rid
- solv
->choicerules
];
3191 return SOLVER_RULE_CHOICE
;
3193 if (rid
>= solv
->recommendsrules
&& rid
< solv
->recommendsrules_end
)
3195 if (solv
->recommendsrules_info
&& fromp
)
3196 *fromp
= solv
->recommendsrules_info
[rid
- solv
->recommendsrules
];
3197 return SOLVER_RULE_RECOMMENDS
;
3199 if (rid
>= solv
->learntrules
)
3200 return SOLVER_RULE_LEARNT
;
3201 return SOLVER_RULE_UNKNOWN
;
3205 solver_ruleclass(Solver
*solv
, Id rid
)
3208 return SOLVER_RULE_UNKNOWN
;
3209 if (rid
> 0 && rid
< solv
->pkgrules_end
)
3210 return SOLVER_RULE_PKG
;
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
;
3221 if (rid
>= solv
->bestrules
&& rid
< solv
->bestrules_end
)
3222 return SOLVER_RULE_BEST
;
3223 if (rid
>= solv
->yumobsrules
&& rid
< solv
->yumobsrules_end
)
3224 return SOLVER_RULE_YUMOBS
;
3225 if (rid
>= solv
->blackrules
&& rid
< solv
->blackrules_end
)
3226 return SOLVER_RULE_BLACK
;
3227 if (rid
>= solv
->choicerules
&& rid
< solv
->choicerules_end
)
3228 return SOLVER_RULE_CHOICE
;
3229 if (rid
>= solv
->recommendsrules
&& rid
< solv
->recommendsrules_end
)
3230 return SOLVER_RULE_RECOMMENDS
;
3231 if (rid
>= solv
->strictrepopriorules
&& rid
< solv
->strictrepopriorules_end
)
3232 return SOLVER_RULE_STRICT_REPO_PRIORITY
;
3233 if (rid
>= solv
->learntrules
&& rid
< solv
->nrules
)
3234 return SOLVER_RULE_LEARNT
;
3235 return SOLVER_RULE_UNKNOWN
;
3239 solver_ruleliterals(Solver
*solv
, Id rid
, Queue
*q
)
3241 Pool
*pool
= solv
->pool
;
3246 r
= solv
->rules
+ rid
;
3247 FOR_RULELITERALS(p
, pp
, r
)
3248 if (p
!= -SYSTEMSOLVABLE
)
3251 queue_push(q
, -SYSTEMSOLVABLE
); /* hmm, better to return an empty result? */
3255 solver_rule2jobidx(Solver
*solv
, Id rid
)
3257 if (rid
< solv
->jobrules
|| rid
>= solv
->jobrules_end
)
3259 return solv
->ruletojob
.elements
[rid
- solv
->jobrules
] + 1;
3262 /* job rule introspection */
3264 solver_rule2job(Solver
*solv
, Id rid
, Id
*whatp
)
3267 if (rid
< solv
->jobrules
|| rid
>= solv
->jobrules_end
)
3273 idx
= solv
->ruletojob
.elements
[rid
- solv
->jobrules
];
3275 *whatp
= solv
->job
.elements
[idx
+ 1];
3276 return solv
->job
.elements
[idx
];
3279 /* update/feature rule introspection */
3281 solver_rule2solvable(Solver
*solv
, Id rid
)
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
);
3291 solver_rule2pkgrule(Solver
*solv
, Id rid
)
3293 if (rid
>= solv
->choicerules
&& rid
< solv
->choicerules_end
)
3294 return solv
->choicerules_info
[rid
- solv
->choicerules
];
3295 if (rid
>= solv
->recommendsrules
&& rid
< solv
->recommendsrules_end
)
3296 return solv
->recommendsrules_info
[rid
- solv
->recommendsrules
];
3301 solver_rule2rules_rec(Solver
*solv
, Id rid
, Queue
*q
, Map
*seen
)
3308 for (i
= solv
->learnt_why
.elements
[rid
- solv
->learntrules
]; (rid2
= solv
->learnt_pool
.elements
[i
]) != 0; i
++)
3312 if (MAPTST(seen
, rid2
))
3314 if (rid2
>= solv
->learntrules
)
3315 solver_rule2rules_rec(solv
, rid2
, q
, seen
);
3318 queue_push(q
, rid2
);
3322 /* learnt rule introspection */
3324 solver_rule2rules(Solver
*solv
, Id rid
, Queue
*q
, int recursive
)
3327 if (rid
< solv
->learntrules
|| rid
>= solv
->nrules
)
3332 map_init(&seen
, solv
->nrules
);
3333 solver_rule2rules_rec(solv
, rid
, q
, &seen
);
3337 solver_rule2rules_rec(solv
, rid
, q
, 0);
3341 /* check if the newest versions of pi still provides the dependency we're looking for */
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
3349 solver_choicerulecheck(Solver
*solv
, Id pi
, Rule
*r
, Map
*m
, Queue
*q
)
3351 Pool
*pool
= solv
->pool
;
3356 if (!q
->count
|| q
->elements
[0] != pi
)
3360 ur
= solv
->rules
+ solv
->updaterules
+ (pi
- pool
->installed
->start
);
3362 ur
= solv
->rules
+ solv
->featurerules
+ (pi
- pool
->installed
->start
);
3365 queue_push2(q
, pi
, 0);
3366 FOR_RULELITERALS(p
, pp
, ur
)
3375 return MAPTST(m
, p
) ? 0 : 1;
3377 if (!q
->elements
[1])
3379 for (i
= 2; i
< q
->count
; i
++)
3380 if (!MAPTST(m
, q
->elements
[i
]))
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
);
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 */
3397 choicerule_find_installed(Pool
*pool
, Id p
)
3399 Solvable
*s
= pool
->solvables
+ p
;
3404 if (s
->repo
== pool
->installed
)
3406 FOR_PROVIDES(p2
, pp2
, s
->name
)
3408 Solvable
*s2
= pool
->solvables
+ p2
;
3409 if (s2
->repo
!= pool
->installed
)
3411 if (!pool
->implicitobsoleteusesprovides
&& s
->name
!= s2
->name
)
3413 if (pool
->implicitobsoleteusescolors
&& !pool_colormatch(pool
, s
, s2
))
3419 Id obs
, *obsp
= s
->repo
->idarraydata
+ s
->obsoletes
;
3420 while ((obs
= *obsp
++) != 0)
3422 FOR_PROVIDES(p2
, pp2
, obs
)
3424 Solvable
*s2
= pool
->solvables
+ p2
;
3425 if (s2
->repo
!= pool
->installed
)
3427 if (!pool
->obsoleteusesprovides
&& !pool_match_nevr(pool
, pool
->solvables
+ p2
, obs
))
3429 if (pool
->obsoleteusescolors
&& !pool_colormatch(pool
, s
, s2
))
3439 solver_addchoicerules(Solver
*solv
)
3441 Pool
*pool
= solv
->pool
;
3444 Queue q
, qi
, qcheck
, infoq
;
3445 int i
, j
, rid
, havechoice
, negcnt
;
3448 Id lastaddedp
, lastaddedd
;
3453 solv
->choicerules
= solv
->nrules
;
3454 if (!pool
->installed
)
3456 solv
->choicerules_end
= solv
->nrules
;
3459 now
= solv_timems(0);
3462 queue_init(&qcheck
);
3464 map_init(&m
, pool
->nsolvables
);
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
);
3476 for (rid
= 1; rid
< solv
->pkgrules_end
; rid
++)
3478 r
= solv
->rules
+ rid
;
3479 if (r
->p
>= 0 || ((r
->d
== 0 || r
->d
== -1) && r
->w2
<= 0))
3480 continue; /* only look at requires rules */
3481 /* solver_printrule(solv, SOLV_DEBUG_RESULT, r); */
3485 FOR_RULELITERALS(p
, pp
, r
)
3489 Solvable
*s
= pool
->solvables
- p
;
3490 p2
= s
->repo
== pool
->installed
? -p
: 0;
3493 if (!(solv
->updatemap_all
|| (solv
->updatemap
.size
&& MAPTST(&solv
->updatemap
, p2
- solv
->installed
->start
))))
3498 s
= pool
->solvables
+ p
;
3501 if (s
->repo
== pool
->installed
)
3503 queue_push2(&qi
, p
, p
);
3506 /* find an installed package p2 that we can update/downgrade to p */
3507 p2
= choicerule_find_installed(pool
, p
);
3510 if (MAPTST(&mneg
, p
))
3512 if (policy_is_illegal(solv
, pool
->solvables
+ p2
, s
, 0))
3514 queue_push2(&qi
, p2
, p
);
3517 /* package p is independent of the installed ones */
3521 printf("havechoice: %d qcount %d qicount %d\n", havechoice
, q
.count
, qi
.count
);
3523 if (!havechoice
|| !qi
.count
)
3524 continue; /* no choice */
3526 FOR_RULELITERALS(p
, pp
, r
)
3532 /* do extra checking for packages related to installed packages */
3533 for (i
= j
= 0; i
< qi
.count
; i
+= 2)
3535 p2
= qi
.elements
[i
];
3536 if (solv
->updatemap_all
|| (solv
->updatemap
.size
&& MAPTST(&solv
->updatemap
, p2
- solv
->installed
->start
)))
3538 if (solver_choicerulecheck(solv
, p2
, r
, &m
, &qcheck
))
3541 qi
.elements
[j
++] = p2
;
3542 qi
.elements
[j
++] = qi
.elements
[i
+ 1];
3544 queue_truncate(&qi
, j
);
3549 FOR_RULELITERALS(p
, pp
, r
)
3556 /* split q from qi */
3557 for (i
= j
= 0; i
< qi
.count
; i
+= 2)
3559 queue_push(&q
, qi
.elements
[i
+ 1]);
3560 qi
.elements
[j
++] = qi
.elements
[i
];
3562 queue_truncate(&qi
, j
);
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 */
3568 for (i
= 0; i
< qi
.count
; i
++)
3571 if (!qi
.elements
[i
])
3573 ur
= solv
->rules
+ solv
->updaterules
+ (qi
.elements
[i
] - pool
->installed
->start
);
3575 ur
= solv
->rules
+ solv
->featurerules
+ (qi
.elements
[i
] - pool
->installed
->start
);
3578 FOR_RULELITERALS(p
, pp
, ur
)
3583 /* speed improvement: only check each package once */
3584 for (j
= i
+ 1; j
< qi
.count
; j
++)
3585 if (qi
.elements
[i
] == qi
.elements
[j
])
3588 /* empty map again */
3590 FOR_RULELITERALS(p
, pp
, r
)
3598 printf("skipping choice ");
3599 solver_printrule(solv
, SOLV_DEBUG_RESULT
, solv
->rules
+ rid
);
3603 /* add neg elements to the front */
3607 FOR_RULELITERALS(p
, pp
, r
)
3608 if (p
< 0 && p
!= r
->p
)
3609 queue_insert(&q
, i
++, p
);
3611 /* don't add identical rules */
3612 if (lastaddedp
== r
->p
&& lastaddedcnt
== q
.count
)
3614 for (i
= 0; i
< q
.count
; i
++)
3615 if (q
.elements
[i
] != pool
->whatprovidesdata
[lastaddedd
+ i
])
3618 continue; /* already added that one */
3620 d
= q
.count
? pool_queuetowhatprovides(pool
, &q
) : 0;
3624 lastaddedcnt
= q
.count
;
3626 solver_addrule(solv
, r
->p
, 0, d
);
3627 queue_push(&solv
->weakruleq
, solv
->nrules
- 1);
3628 queue_push(&infoq
, rid
);
3631 solver_printrule(solv
, SOLV_DEBUG_RESULT
, solv
->rules
+ rid
);
3632 printf("WEAK CHOICE ");
3633 solver_printrule(solv
, SOLV_DEBUG_RESULT
, solv
->rules
+ solv
->nrules
- 1);
3637 solv
->choicerules_info
= solv_memdup2(infoq
.elements
, infoq
.count
, sizeof(Id
));
3640 queue_free(&qcheck
);
3644 solv
->choicerules_end
= solv
->nrules
;
3645 POOL_DEBUG(SOLV_DEBUG_STATS
, "choice rule creation took %d ms\n", solv_timems(now
));
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
3652 solver_disablechoicerules(Solver
*solv
, Rule
*r
)
3655 Pool
*pool
= solv
->pool
;
3659 solver_disablerule(solv
, r
);
3660 or = solv
->rules
+ solv
->choicerules_info
[(r
- solv
->rules
) - solv
->choicerules
];
3661 map_init(&m
, pool
->nsolvables
);
3662 FOR_RULELITERALS(p
, pp
, or)
3665 FOR_RULELITERALS(p
, pp
, r
)
3668 for (rid
= solv
->choicerules
; rid
< solv
->choicerules_end
; rid
++)
3670 r
= solv
->rules
+ rid
;
3673 or = solv
->rules
+ solv
->choicerules_info
[rid
- solv
->choicerules
];
3674 FOR_RULELITERALS(p
, pp
, or)
3675 if (p
> 0 && MAPTST(&m
, p
))
3678 solver_disablerule(solv
, r
);
3684 prune_to_update_targets(Solver
*solv
, Id
*cp
, Queue
*q
)
3688 for (i
= j
= 0; i
< q
->count
; i
++)
3691 for (cp2
= cp
; *cp2
; cp2
++)
3694 q
->elements
[j
++] = p
;
3698 queue_truncate(q
, j
);
3702 prune_to_dup_packages(Solver
*solv
, Id p
, Queue
*q
)
3705 for (i
= j
= 0; i
< q
->count
; i
++)
3707 Id p
= q
->elements
[i
];
3708 if (MAPTST(&solv
->dupmap
, p
))
3709 q
->elements
[j
++] = p
;
3711 queue_truncate(q
, j
);
3715 prune_best_update(Solver
*solv
, Id p
, Queue
*q
)
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
);
3726 prune_disabled(Pool
*pool
, Queue
*q
)
3729 for (i
= j
= 0; i
< q
->count
; i
++)
3731 Id p
= q
->elements
[i
];
3732 Solvable
*s
= pool
->solvables
+ p
;
3733 if (s
->repo
&& s
->repo
!= pool
->installed
&& !MAPTST(pool
->considered
, p
))
3735 q
->elements
[j
++] = p
;
3737 queue_truncate(q
, j
);
3741 solver_addbestrules(Solver
*solv
, int havebestinstalljobs
, int haslockjob
)
3743 Pool
*pool
= solv
->pool
;
3746 Repo
*installed
= solv
->installed
;
3753 solv
->bestrules
= solv
->nrules
;
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
++)
3765 if (r
->w2
|| (solv
->job
.elements
[solv
->ruletojob
.elements
[i
]] & SOLVER_JOBMASK
) != SOLVER_LOCK
)
3767 p
= r
->p
> 0 ? r
->p
: -r
->p
;
3768 MAPSET(lockedmap
, p
);
3771 if (havebestinstalljobs
)
3773 for (i
= 0; i
< solv
->job
.count
; i
+= 2)
3775 Id how
= solv
->job
.elements
[i
];
3776 if ((how
& (SOLVER_JOBMASK
| SOLVER_FORCEBEST
)) == (SOLVER_INSTALL
| SOLVER_FORCEBEST
))
3780 for (j
= 0; j
< solv
->ruletojob
.count
; j
++)
3782 if (solv
->ruletojob
.elements
[j
] != i
)
3784 r
= solv
->rules
+ solv
->jobrules
+ j
;
3787 FOR_RULELITERALS(p2
, pp2
, r
)
3792 queue_push(&q2
, p2
);
3794 if (pool
->considered
&& pool
->whatprovideswithdisabled
)
3795 prune_disabled(pool
, &q
);
3797 continue; /* orphaned */
3798 /* select best packages, just look at prio and version */
3800 policy_filter_unwanted(solv
, &q
, POLICY_MODE_RECOMMEND
);
3801 if (q
.count
== oldcnt
)
3802 continue; /* nothing filtered */
3805 queue_insertn(&q
, 0, q2
.count
, q2
.elements
);
3807 FOR_RULELITERALS(p2
, pp2
, r
)
3811 if (installed
&& pool
->solvables
[p2
].repo
== installed
)
3813 if (MAPTST(lockedmap
, p2
))
3814 queue_pushunique(&q
, p2
); /* we always want that package */
3816 else if (MAPTST(lockedmap
, p2
))
3818 queue_push(&q2
, p2
);
3820 if (pool
->considered
&& pool
->whatprovideswithdisabled
)
3821 prune_disabled(pool
, &q2
);
3822 policy_filter_unwanted(solv
, &q2
, POLICY_MODE_RECOMMEND
);
3823 for (k
= 0; k
< q2
.count
; k
++)
3824 queue_pushunique(&q
, q2
.elements
[k
]);
3828 queue_insertn(&q
, 0, q2
.count
, q2
.elements
);
3829 p2
= queue_shift(&q
);
3831 solver_addrule(solv
, p2
, q
.count
? q
.elements
[0] : 0, 0);
3833 solver_addrule(solv
, p2
, 0, pool_queuetowhatprovides(pool
, &q
));
3834 if ((how
& SOLVER_WEAK
) != 0)
3835 queue_push(&solv
->weakruleq
, solv
->nrules
- 1);
3836 queue_push(&infoq
, -(solv
->jobrules
+ j
));
3841 solv
->bestrules_up
= solv
->nrules
;
3843 if (installed
&& (solv
->bestupdatemap_all
|| solv
->bestupdatemap
.size
))
3847 if (solv
->allowuninstall
|| solv
->allowuninstall_all
|| solv
->allowuninstallmap
.size
)
3848 map_init(&m
, pool
->nsolvables
);
3851 FOR_REPO_SOLVABLES(installed
, p
, s
)
3854 if (!solv
->updatemap_all
&& (!solv
->updatemap
.size
|| !MAPTST(&solv
->updatemap
, p
- installed
->start
)))
3856 if (!solv
->bestupdatemap_all
&& (!solv
->bestupdatemap
.size
|| !MAPTST(&solv
->bestupdatemap
, p
- installed
->start
)))
3859 if (solv
->bestobeypolicy
)
3860 r
= solv
->rules
+ solv
->updaterules
+ (p
- installed
->start
);
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
);
3867 if (solv
->specialupdaters
&& (d
= solv
->specialupdaters
[p
- installed
->start
]) != 0 && r
== solv
->rules
+ solv
->updaterules
+ (p
- installed
->start
))
3869 /* need to check specialupdaters */
3870 if (r
->p
== p
) /* be careful with the dup case */
3872 while ((p2
= pool
->whatprovidesdata
[d
++]) != 0)
3877 FOR_RULELITERALS(p2
, pp2
, r
)
3884 queue_insertn(&q2
, 0, q
.count
, q
.elements
);
3886 prune_best_update(solv
, p
, &q
);
3888 continue; /* orphaned */
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
++)
3897 Id p2
= q2
.elements
[j
];
3898 if (pool
->solvables
[p2
].repo
== installed
&& MAPTST(lockedmap
, p2
))
3899 queue_pushunique(&q
, p2
);
3901 /* filter out locked packages */
3902 for (i
= j
= 0; j
< q2
.count
; j
++)
3904 Id p2
= q2
.elements
[j
];
3905 if (pool
->solvables
[p2
].repo
== installed
|| !MAPTST(lockedmap
, p2
))
3906 q2
.elements
[i
++] = p2
;
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
]);
3913 if (solv
->bestobeypolicy
)
3915 /* also filter the best of the feature rule packages and add them */
3916 r
= solv
->rules
+ solv
->featurerules
+ (p
- installed
->start
);
3921 FOR_RULELITERALS(p2
, pp2
, r
)
3923 queue_push(&q2
, p2
);
3924 prune_best_update(solv
, p
, &q2
);
3925 for (j
= 0; j
< q2
.count
; j
++)
3926 queue_pushunique(&q
, q2
.elements
[j
]);
3930 FOR_RULELITERALS(p2
, pp2
, r
)
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
]);
3940 if (solv
->allowuninstall
|| solv
->allowuninstall_all
|| (solv
->allowuninstallmap
.size
&& MAPTST(&solv
->allowuninstallmap
, p
- installed
->start
)))
3942 /* package is flagged both for allowuninstall and best, add negative rules */
3943 d
= q
.count
== 1 ? q
.elements
[0] : -pool_queuetowhatprovides(pool
, &q
);
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
)
3954 solver_addrule(solv
, -p2
, d
, 0);
3956 solver_addrule(solv
, -p2
, 0, -d
);
3957 queue_push(&infoq
, p
);
3959 for (i
= 0; i
< q
.count
; i
++)
3960 MAPCLR(&m
, q
.elements
[i
]);
3963 p2
= queue_shift(&q
);
3965 solver_addrule(solv
, p2
, q
.count
? q
.elements
[0] : 0, 0);
3967 solver_addrule(solv
, p2
, 0, pool_queuetowhatprovides(pool
, &q
));
3968 queue_push(&infoq
, p
);
3973 solv
->bestrules_info
= solv_memdup2(infoq
.elements
, infoq
.count
, sizeof(Id
));
3974 solv
->bestrules_end
= solv
->nrules
;
3980 map_free(lockedmap
);
3981 solv_free(lockedmap
);
3988 /* yumobs rule handling */
3989 /* note that we use pool->obsoleteusescolors || pool->implicitobsoleteusescolors
3990 * like in policy_findupdatepackages */
3993 find_obsolete_group(Solver
*solv
, Id obs
, Queue
*q
)
3995 Pool
*pool
= solv
->pool
;
3997 Id p2
, pp2
, op
, *opp
, opp2
;
3998 int i
, j
, qnc
, ncnt
;
4001 FOR_PROVIDES(p2
, pp2
, obs
)
4003 Solvable
*s2
= pool
->solvables
+ p2
;
4004 if (s2
->repo
!= pool
->installed
)
4006 if (!pool
->obsoleteusesprovides
&& !pool_match_nevr(pool
, pool
->solvables
+ p2
, obs
))
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;)
4011 Solvable
*os
= pool
->solvables
+ op
;
4015 if ((pool
->obsoleteusescolors
|| pool
->implicitobsoleteusescolors
) && !pool_colormatch(pool
, s2
, os
))
4017 obsp2
= os
->repo
->idarraydata
+ os
->obsoletes
;
4018 while ((obs2
= *obsp2
++) != 0)
4022 queue_pushunique(q
, op
);
4024 /* also search packages with the same name */
4025 FOR_PROVIDES(op
, opp2
, s2
->name
)
4027 Solvable
*os
= pool
->solvables
+ op
;
4029 if (os
->name
!= s2
->name
)
4033 if ((pool
->obsoleteusescolors
|| pool
->implicitobsoleteusescolors
) && !pool_colormatch(pool
, s2
, os
))
4035 obsp2
= os
->repo
->idarraydata
+ os
->obsoletes
;
4036 while ((obs2
= *obsp2
++) != 0)
4040 queue_pushunique(q
, op
);
4043 /* find names so that we can build groups */
4044 queue_init_clone(&qn
, q
);
4045 prune_to_best_version(pool
, &qn
);
4048 for (i
= 0; i
< qn
.count
; i
++)
4049 printf(" + %s\n", pool_solvid2str(pool
, qn
.elements
[i
]));
4052 /* filter into name groups */
4061 for (i
= 0; i
< qnc
; i
++)
4063 Id n
= pool
->solvables
[qn
.elements
[i
]].name
;
4065 for (j
= 0; j
< q
->count
; j
++)
4067 Id p
= q
->elements
[j
];
4068 if (pool
->solvables
[p
].name
== n
)
4087 queue_insertn(q
, 0, qn
.count
- qnc
, qn
.elements
+ qnc
);
4093 solver_addyumobsrules(Solver
*solv
)
4095 Pool
*pool
= solv
->pool
;
4096 Repo
*installed
= solv
->installed
;
4099 Queue qo
, qq
, infoq
;
4103 solv
->yumobsrules
= solv
->nrules
;
4104 if (!installed
|| !solv
->obsoletes
)
4106 solv
->yumobsrules_end
= solv
->nrules
;
4109 now
= solv_timems(0);
4111 FOR_REPO_SOLVABLES(installed
, p
, s
)
4113 if (!solv
->obsoletes
[p
- installed
->start
])
4116 printf("checking yumobs for %s\n", pool_solvable2str(pool
, s
));
4118 for (opp
= solv
->obsoletes_data
+ solv
->obsoletes
[p
- installed
->start
]; (op
= *opp
++) != 0;)
4120 Solvable
*os
= pool
->solvables
+ op
;
4121 Id obs
, *obsp
= os
->repo
->idarraydata
+ os
->obsoletes
;
4123 while ((obs
= *obsp
++) != 0)
4125 FOR_PROVIDES(p2
, pp2
, obs
)
4127 Solvable
*s2
= pool
->solvables
+ p2
;
4128 if (s2
->repo
!= installed
)
4130 if (!pool
->obsoleteusesprovides
&& !pool_match_nevr(pool
, pool
->solvables
+ p2
, obs
))
4132 if ((pool
->obsoleteusescolors
|| pool
->implicitobsoleteusescolors
) && !pool_colormatch(pool
, s
, s2
))
4134 queue_pushunique(&qo
, obs
);
4147 for (i
= 0; i
< qo
.count
; i
++)
4149 int group
, groupk
, groupstart
;
4152 printf("investigating %s\n", pool_dep2str(pool
, qo
.elements
[i
]));
4154 find_obsolete_group(solv
, qo
.elements
[i
], &qq
);
4156 printf("result:\n");
4157 for (j
= 0; j
< qq
.count
; j
++)
4158 if (qq
.elements
[j
] == 0)
4161 printf("%s\n", pool_solvid2str(pool
, qq
.elements
[j
]));
4166 /* at least two groups, build rules */
4168 for (j
= 0; j
< qq
.count
; j
++)
4176 if (pool
->solvables
[p
].repo
== installed
)
4180 for (k
= 0; k
< qq
.count
; k
++)
4182 Id pk
= qq
.elements
[k
];
4185 if (group
!= groupk
&& k
> groupstart
)
4188 if (k
- groupstart
== 1)
4189 solver_addrule(solv
, -p
, qq
.elements
[groupstart
], 0);
4191 solver_addrule(solv
, -p
, 0, pool_ids2whatprovides(pool
, qq
.elements
+ groupstart
, k
- groupstart
));
4192 queue_push(&infoq
, qo
.elements
[i
]);
4200 solv
->yumobsrules_info
= solv_memdup2(infoq
.elements
, infoq
.count
, sizeof(Id
));
4204 solv
->yumobsrules_end
= solv
->nrules
;
4205 POOL_DEBUG(SOLV_DEBUG_STATS
, "yumobs rule creation took %d ms\n", solv_timems(now
));
4208 /* recommendsrules are a copy of some recommends package rule but
4209 * with some disfavored literals removed */
4211 solver_addrecommendsrules(Solver
*solv
)
4213 Pool
*pool
= solv
->pool
;
4214 int i
, havedis
, havepos
;
4218 solv
->recommendsrules
= solv
->nrules
;
4221 for (i
= 0; i
< solv
->recommendsruleq
->count
; i
++)
4223 int rid
= solv
->recommendsruleq
->elements
[i
];
4224 Rule
*r
= solv
->rules
+ rid
;
4226 havedis
= havepos
= 0;
4227 FOR_RULELITERALS(p
, pp
, r
)
4229 if (p
> 0 && solv
->favormap
[p
] < 0)
4240 solver_disablerule(solv
, r
);
4241 if (!havepos
|| q
.count
< 2)
4244 solver_addrule(solv
, q
.elements
[0], q
.elements
[1], 0);
4246 solver_addrule(solv
, q
.elements
[0], 0, pool_ids2whatprovides(pool
, q
.elements
+ 1, q
.count
- 1));
4247 queue_push(&infoq
, rid
);
4250 solv
->recommendsrules_info
= solv_memdup2(infoq
.elements
, infoq
.count
, sizeof(Id
));
4253 solv
->recommendsrules_end
= solv
->nrules
;
4257 solver_breakorphans(Solver
*solv
)
4259 Pool
*pool
= solv
->pool
;
4260 Repo
*installed
= solv
->installed
;
4264 if (!installed
|| solv
->droporphanedmap_all
)
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
++)
4271 Id p
= solv
->orphaned
.elements
[i
];
4272 if (pool
->solvables
[p
].repo
!= installed
)
4274 if (solv
->droporphanedmap
.size
&& MAPTST(&solv
->droporphanedmap
, p
- installed
->start
))
4276 MAPSET(&m
, p
- installed
->start
);
4278 for (rid
= 1; rid
< solv
->pkgrules_end
; rid
++)
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))
4286 if (p
< installed
->start
|| p
>= installed
->end
|| !MAPTST(&m
, p
- installed
->start
))
4288 /* need to check other literals */
4289 if (r
->d
== 0 || r
->d
== -1)
4291 for (dp
= pool
->whatprovidesdata
+ (r
->d
< 0 ? -r
->d
- 1 : r
->d
); *dp
< 0; dp
++)
4294 if (p
>= installed
->start
&& p
< installed
->end
&& MAPTST(&m
, p
- installed
->start
))
4300 /* ok, disable this rule */
4301 queue_push(solv
->brokenorphanrules
, rid
);
4303 solver_disablerule(solv
, r
);
4306 if (!solv
->brokenorphanrules
->count
)
4308 queue_free(solv
->brokenorphanrules
);
4309 solv
->brokenorphanrules
= solv_free(solv
->brokenorphanrules
);
4314 solver_check_brokenorphanrules(Solver
*solv
, Queue
*dq
)
4316 Pool
*pool
= solv
->pool
;
4321 if (!solv
->brokenorphanrules
)
4323 for (i
= 0; i
< solv
->brokenorphanrules
->count
; i
++)
4325 int rid
= solv
->brokenorphanrules
->elements
[i
];
4326 Rule
*r
= solv
->rules
+ rid
;
4327 FOR_RULELITERALS(l
, pp
, r
)
4331 if (solv
->decisionmap
[-l
] <= 0)
4336 if (solv
->decisionmap
[l
] > 0 && pool
->solvables
[l
].repo
!= solv
->installed
)
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
);
4349 solver_ruleinfo2str(Solver
*solv
, SolverRuleinfo type
, Id source
, Id target
, Id dep
)
4351 Pool
*pool
= solv
->pool
;
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);
4362 case SOLVER_RULE_FEATURE
:
4363 return pool_tmpjoin(pool
, pool_solvid2str(pool
, source
), " needs to stay installed or be updated/downgraded", 0);
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");
4374 case SOLVER_RULE_BEST
:
4376 return pool_tmpjoin(pool
, "install best update candidate for ", pool_solvid2str(pool
, source
), 0);
4379 target
= solver_rule2job(solv
, target
, &dep
);
4380 return pool_tmpjoin(pool
, "best package for job ", pool_job2str(pool
, target
, dep
, 0), 0);
4383 case SOLVER_RULE_PKG
:
4384 return "bad pkg rule type";
4385 case SOLVER_RULE_PKG_NOT_INSTALLABLE
:
4386 ss
= pool
->solvables
+ source
;
4387 if (pool_disabled_solvable(pool
, ss
))
4388 return pool_tmpjoin(pool
, pool_solvid2str(pool
, source
), " is disabled", 0);
4389 if (ss
->arch
&& ss
->arch
!= ARCH_SRC
&& ss
->arch
!= ARCH_NOSRC
&&
4390 pool
->id2arch
&& pool_arch2score(pool
, ss
->arch
) == 0)
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);
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
:
4400 s
= pool_tmpappend(pool
, pool_solvid2str(pool
, source
), " conflicts with ", pool_dep2str(pool
, dep
));
4402 s
= pool_tmpappend(pool
, s
, " provided by ", pool_solvid2str(pool
, target
));
4404 case SOLVER_RULE_PKG_SELF_CONFLICT
:
4405 s
= pool_tmpjoin(pool
, pool_solvid2str(pool
, source
), " conflicts with ", 0);
4406 return pool_tmpappend(pool
, s
, pool_dep2str(pool
, dep
), " provided by itself");
4407 case SOLVER_RULE_PKG_OBSOLETES
:
4408 s
= pool_tmpappend(pool
, pool_solvid2str(pool
, source
), " obsoletes ", pool_dep2str(pool
, dep
));
4410 s
= pool_tmpappend(pool
, s
, " provided by ", pool_solvid2str(pool
, target
));
4412 case SOLVER_RULE_PKG_INSTALLED_OBSOLETES
:
4413 s
= pool_tmpjoin(pool
, "installed ", pool_solvid2str(pool
, source
), 0);
4414 s
= pool_tmpappend(pool
, s
, " obsoletes ", pool_dep2str(pool
, dep
));
4416 s
= pool_tmpappend(pool
, s
, " provided by ", pool_solvid2str(pool
, target
));
4418 case SOLVER_RULE_PKG_IMPLICIT_OBSOLETES
:
4419 s
= pool_tmpappend(pool
, pool_solvid2str(pool
, source
), " implicitly obsoletes ", pool_dep2str(pool
, dep
));
4421 s
= pool_tmpappend(pool
, s
, " provided by ", pool_solvid2str(pool
, target
));
4423 case SOLVER_RULE_PKG_REQUIRES
:
4424 return pool_tmpjoin(pool
, pool_solvid2str(pool
, source
), " requires ", pool_dep2str(pool
, dep
));
4425 case SOLVER_RULE_PKG_RECOMMENDS
:
4426 return pool_tmpjoin(pool
, pool_solvid2str(pool
, source
), " recommends ", pool_dep2str(pool
, dep
));
4427 case SOLVER_RULE_PKG_CONSTRAINS
:
4428 s
= pool_tmpappend(pool
, pool_solvid2str(pool
, source
), " has constraint ", pool_dep2str(pool
, dep
));
4429 return pool_tmpappend(pool
, s
, " conflicting with ", pool_solvid2str(pool
, target
));
4430 case SOLVER_RULE_PKG_SUPPLEMENTS
:
4431 s
= pool_tmpjoin(pool
, pool_solvid2str(pool
, source
), " supplements ", pool_dep2str(pool
, dep
));
4433 s
= pool_tmpappend(pool
, s
, " provided by ", pool_solvid2str(pool
, target
));
4435 case SOLVER_RULE_YUMOBS
:
4436 s
= pool_tmpjoin(pool
, "both ", pool_solvid2str(pool
, source
), " and ");
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
:
4440 return pool_tmpjoin(pool
, pool_solvid2str(pool
, source
), " can only be installed by a direct request", 0);
4441 case SOLVER_RULE_STRICT_REPO_PRIORITY
:
4442 return pool_tmpjoin(pool
, pool_solvid2str(pool
, source
), " is excluded by strict repo priority", 0);
4443 case SOLVER_RULE_LEARNT
:
4444 return "learnt rule";
4445 case SOLVER_RULE_CHOICE
:
4449 type
= solver_ruleinfo(solv
, source
, &source
, &target
, &dep
);
4450 s2
= solver_ruleinfo2str(solv
, type
, source
, target
, dep
);
4451 return pool_tmpjoin(pool
, s2
, " (limited version)", 0);
4453 return "choice rule";
4454 case SOLVER_RULE_RECOMMENDS
:
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);
4462 return "recommends rule";
4464 return "bad rule type";