diff options
Diffstat (limited to 'src/rules.c')
-rw-r--r-- | src/rules.c | 206 |
1 files changed, 155 insertions, 51 deletions
diff --git a/src/rules.c b/src/rules.c index 4cd53d3..32855e4 100644 --- a/src/rules.c +++ b/src/rules.c @@ -671,7 +671,7 @@ add_complex_deprules(Solver *solv, Id p, Id dep, int type, int dontfix, Queue *w /*------------------------------------------------------------------- * - * add (install) rules for solvable + * add dependency rules for solvable * * s: Solvable for which to add rules * m: m[s] = 1 for solvables which have rules, prevent rule duplication @@ -697,6 +697,8 @@ solver_addpkgrulesforsolvable(Solver *solv, Solvable *s, Map *m) Queue workq; /* list of solvables we still have to work on */ Id workqbuf[64]; + Queue prereqq; /* list of pre-req ids to ignore */ + Id prereqbuf[16]; int i; int dontfix; /* ignore dependency errors for installed solvables */ @@ -712,6 +714,8 @@ solver_addpkgrulesforsolvable(Solver *solv, Solvable *s, Map *m) queue_init_buffer(&workq, workqbuf, sizeof(workqbuf)/sizeof(*workqbuf)); queue_push(&workq, s - pool->solvables); /* push solvable Id to work queue */ + queue_init_buffer(&prereqq, prereqbuf, sizeof(prereqbuf)/sizeof(*prereqbuf)); + /* loop until there's no more work left */ while (workq.count) { @@ -762,11 +766,33 @@ solver_addpkgrulesforsolvable(Solver *solv, Solvable *s, Map *m) if (s->requires) { + int filterpre = 0; reqp = s->repo->idarraydata + s->requires; while ((req = *reqp++) != 0) /* go through all requires */ { if (req == SOLVABLE_PREREQMARKER) /* skip the marker */ - continue; + { + if (installed && s->repo == installed) + { + if (prereqq.count) + queue_empty(&prereqq); + solvable_lookup_idarray(s, SOLVABLE_PREREQ_IGNOREINST, &prereqq); + filterpre = prereqq.count; + } + continue; + } + if (filterpre) + { + /* check if this id is filtered. assumes that prereqq.count is small */ + for (i = 0; i < prereqq.count; i++) + if (req == prereqq.elements[i]) + break; + if (i < prereqq.count) + { + POOL_DEBUG(SOLV_DEBUG_RULE_CREATION, "package %s: ignoring filtered pre-req dependency %s\n", pool_solvable2str(pool, s), pool_dep2str(pool, req)); + continue; + } + } #ifdef ENABLE_COMPLEX_DEPS if (pool_is_complex_dep(pool, req)) @@ -1034,6 +1060,7 @@ solver_addpkgrulesforsolvable(Solver *solv, Solvable *s, Map *m) } } } + queue_free(&prereqq); queue_free(&workq); } @@ -1170,35 +1197,56 @@ solver_addpkgrulesforupdaters(Solver *solv, Solvable *s, Map *m, int allow_all) *** ***/ +static int +dup_maykeepinstalled(Solver *solv, Solvable *s) +{ + Pool *pool = solv->pool; + Id ip, pp; + + if (solv->dupmap.size && MAPTST(&solv->dupmap, s - pool->solvables)) + return 1; + /* is installed identical to a good one? */ + FOR_PROVIDES(ip, pp, s->name) + { + Solvable *is = pool->solvables + ip; + if (is->evr != s->evr) + continue; + if (solv->dupmap.size) + { + if (!MAPTST(&solv->dupmap, ip)) + continue; + } + else if (is->repo == pool->installed) + continue; + if (solvable_identical(s, is)) + return 1; + } + return 0; +} + + static Id -finddistupgradepackages(Solver *solv, Solvable *s, Queue *qs, int allow_all) +finddistupgradepackages(Solver *solv, Solvable *s, Queue *qs) { Pool *pool = solv->pool; - int i; + int i, j; - policy_findupdatepackages(solv, s, qs, allow_all ? allow_all : 2); - if (!qs->count) + policy_findupdatepackages(solv, s, qs, 2); + if (qs->count) { - if (allow_all) - return 0; /* orphaned, don't create feature rule */ - /* check if this is an orphaned package */ - policy_findupdatepackages(solv, s, qs, 1); - if (!qs->count) - return 0; /* orphaned, don't create update rule */ - qs->count = 0; - return -SYSTEMSOLVABLE; /* supported but not installable */ + /* remove installed packages we can't keep */ + for (i = j = 0; i < qs->count; i++) + { + Solvable *ns = pool->solvables + qs->elements[i]; + if (ns->repo == pool->installed && !dup_maykeepinstalled(solv, ns)) + continue; + qs->elements[j++] = qs->elements[i]; + } + queue_truncate(qs, j); } - if (allow_all) - return s - pool->solvables; /* check if it is ok to keep the installed package */ - if (solv->dupmap.size && MAPTST(&solv->dupmap, s - pool->solvables)) + if (dup_maykeepinstalled(solv, s)) return s - pool->solvables; - for (i = 0; i < qs->count; i++) - { - Solvable *ns = pool->solvables + qs->elements[i]; - if (s->evr == ns->evr && solvable_identical(s, ns)) - return s - pool->solvables; - } /* nope, it must be some other package */ return -SYSTEMSOLVABLE; } @@ -1240,6 +1288,73 @@ set_specialupdaters(Solver *solv, Solvable *s, Id d) solv->specialupdaters[s - solv->pool->solvables - installed->start] = d; } +#ifdef ENABLE_LINKED_PKGS +/* Check if this is a linked pseudo package. As it is linked, we do not need an update/feature rule */ +static inline int +is_linked_pseudo_package(Solver *solv, Solvable *s) +{ + Pool *pool = solv->pool; + if (solv->instbuddy && solv->instbuddy[s - pool->solvables - solv->installed->start]) + { + const char *name = pool_id2str(pool, s->name); + if (strncmp(name, "pattern:", 8) == 0 || strncmp(name, "application:", 12) == 0) + return 1; + } + return 0; +} +#endif + +void +solver_addfeaturerule(Solver *solv, Solvable *s) +{ + Pool *pool = solv->pool; + int i; + Id p; + Queue qs; + Id qsbuf[64]; + +#ifdef ENABLE_LINKED_PKGS + if (is_linked_pseudo_package(solv, s)) + { + solver_addrule(solv, 0, 0, 0); /* no feature rules for those */ + return; + } +#endif + queue_init_buffer(&qs, qsbuf, sizeof(qsbuf)/sizeof(*qsbuf)); + p = s - pool->solvables; + policy_findupdatepackages(solv, s, &qs, 1); + if (solv->dupmap_all || (solv->dupinvolvedmap.size && MAPTST(&solv->dupinvolvedmap, p))) + { + if (!dup_maykeepinstalled(solv, s)) + { + for (i = 0; i < qs.count; i++) + { + Solvable *ns = pool->solvables + qs.elements[i]; + if (ns->repo != pool->installed || dup_maykeepinstalled(solv, ns)) + break; + } + if (i == qs.count) + { + solver_addrule(solv, 0, 0, 0); /* this is an orphan */ + queue_free(&qs); + return; + } + } + } + if (qs.count > 1) + { + Id d = pool_queuetowhatprovides(pool, &qs); + queue_free(&qs); + solver_addrule(solv, p, 0, d); /* allow update of s */ + } + else + { + Id d = qs.count ? qs.elements[0] : 0; + queue_free(&qs); + solver_addrule(solv, p, d, 0); /* allow update of s */ + } +} + /*------------------------------------------------------------------- * * add rule for update @@ -1249,7 +1364,7 @@ set_specialupdaters(Solver *solv, Solvable *s, Id d) */ void -solver_addupdaterule(Solver *solv, Solvable *s, int allow_all) +solver_addupdaterule(Solver *solv, Solvable *s) { /* installed packages get a special upgrade allowed rule */ Pool *pool = solv->pool; @@ -1257,48 +1372,37 @@ solver_addupdaterule(Solver *solv, Solvable *s, int allow_all) Queue qs; Id qsbuf[64]; int isorphaned = 0; + Rule *r; - queue_init_buffer(&qs, qsbuf, sizeof(qsbuf)/sizeof(*qsbuf)); p = s - pool->solvables; - /* find update candidates for 's' */ - if (solv->dupmap_all || (solv->dupinvolvedmap.size && MAPTST(&solv->dupinvolvedmap, p))) - p = finddistupgradepackages(solv, s, &qs, allow_all); - else - policy_findupdatepackages(solv, s, &qs, allow_all); - -#ifdef ENABLE_LINKED_PKGS - if (solv->instbuddy && solv->instbuddy[s - pool->solvables - solv->installed->start]) + /* Orphan detection. We cheat by looking at the feature rule, which + * we already calculated */ + r = solv->rules + solv->featurerules + (p - solv->installed->start); + if (!r->p) { - const char *name = pool_id2str(pool, s->name); - if (strncmp(name, "pattern:", 8) == 0 || strncmp(name, "application:", 12) == 0) +#ifdef ENABLE_LINKED_PKGS + if (is_linked_pseudo_package(solv, s)) { - /* a linked pseudo package. As it is linked, we do not need an update/feature rule */ - /* nevertheless we set specialupdaters so we can update */ solver_addrule(solv, 0, 0, 0); - if (!allow_all && qs.count) - { - if (p != -SYSTEMSOLVABLE) - queue_unshift(&qs, p); - if (qs.count) - set_specialupdaters(solv, s, pool_queuetowhatprovides(pool, &qs)); - } - queue_free(&qs); return; } - } #endif - - if (!allow_all && !p) /* !p implies qs.count == 0 */ - { + p = 0; queue_push(&solv->orphaned, s - pool->solvables); /* an orphaned package */ if (solv->keep_orphans && !(solv->droporphanedmap_all || (solv->droporphanedmap.size && MAPTST(&solv->droporphanedmap, s - pool->solvables - solv->installed->start)))) p = s - pool->solvables; /* keep this orphaned package installed */ - queue_free(&qs); solver_addrule(solv, p, 0, 0); return; } - if (!allow_all && qs.count && solv->multiversion.size) + queue_init_buffer(&qs, qsbuf, sizeof(qsbuf)/sizeof(*qsbuf)); + /* find update candidates for 's' */ + if (solv->dupmap_all || (solv->dupinvolvedmap.size && MAPTST(&solv->dupinvolvedmap, p))) + p = finddistupgradepackages(solv, s, &qs); + else + policy_findupdatepackages(solv, s, &qs, 0); + + if (qs.count && solv->multiversion.size) { int i, j; |