diff options
author | Michael Schroeder <mls@suse.de> | 2013-07-10 16:52:00 +0200 |
---|---|---|
committer | Michael Schroeder <mls@suse.de> | 2013-07-10 16:54:53 +0200 |
commit | 9147c5f23b506709adb9d75a434250d59bf31985 (patch) | |
tree | 05d19de6984b4220c0a2dfb666dddd0ff6b52591 /src/policy.c | |
parent | 61f72e28eaf8bf263e73a47c855cd1d9db601719 (diff) | |
download | libsolv-9147c5f23b506709adb9d75a434250d59bf31985.tar.gz libsolv-9147c5f23b506709adb9d75a434250d59bf31985.tar.bz2 libsolv-9147c5f23b506709adb9d75a434250d59bf31985.zip |
fix another edge case will dup mode and multiversion packages [bnc#828389]
Diffstat (limited to 'src/policy.c')
-rw-r--r-- | src/policy.c | 130 |
1 files changed, 78 insertions, 52 deletions
diff --git a/src/policy.c b/src/policy.c index a73fc14..5a88ed3 100644 --- a/src/policy.c +++ b/src/policy.c @@ -115,9 +115,78 @@ prune_to_highest_prio(Pool *pool, Queue *plist) plist->count = j; } + +/* installed packages involed in a dup operation can only be kept + * if they are identical to a non-installed one */ +static void +solver_prune_installed_dup_packages(Solver *solv, Queue *plist) +{ + Pool *pool = solv->pool; + int i, j, bestprio = 0; + + /* find bestprio (again) */ + for (i = 0; i < plist->count; i++) + { + Solvable *s = pool->solvables + plist->elements[i]; + if (s->repo != pool->installed) + { + bestprio = s->repo->priority; + break; + } + } + if (i == plist->count) + return; /* only installed packages, could not find prio */ + for (i = j = 0; i < plist->count; i++) + { + Id p = plist->elements[i]; + Solvable *s = pool->solvables + p; + if (s->repo != pool->installed && s->repo->priority < bestprio) + continue; + if (s->repo == pool->installed && (solv->dupmap_all || (solv->dupinvolvedmap.size && MAPTST(&solv->dupinvolvedmap, p)))) + { + Id p2, pp2; + int keepit = 0; + FOR_PROVIDES(p2, pp2, s->name) + { + Solvable *s2 = pool->solvables + p2; + if (s2->repo == pool->installed || s2->evr != s->evr || s2->repo->priority < bestprio) + continue; + if (!solvable_identical(s, s2)) + continue; + keepit = 1; + if (s2->repo->priority > bestprio) + { + /* new max prio! */ + bestprio = s2->repo->priority; + j = 0; + } + } + if (!keepit) + continue; /* no identical package found, ignore installed package */ + } + plist->elements[j++] = p; + } + if (j) + plist->count = j; +} + +/* + * like prune_to_highest_prio, but calls solver prune_installed_dup_packages + * when there are dup packages + */ +static inline void +solver_prune_to_highest_prio(Solver *solv, Queue *plist) +{ + prune_to_highest_prio(solv->pool, plist); + if (plist->count > 1 && solv->pool->installed && (solv->dupmap_all || solv->dupinvolvedmap.size)) + solver_prune_installed_dup_packages(solv, plist); +} + + static void -prune_to_highest_prio_per_name(Pool *pool, Queue *plist) +solver_prune_to_highest_prio_per_name(Solver *solv, Queue *plist) { + Pool *pool = solv->pool; Queue pq; int i, j, k; Id name; @@ -131,7 +200,7 @@ prune_to_highest_prio_per_name(Pool *pool, Queue *plist) if (pool->solvables[plist->elements[i]].name != name) { if (pq.count > 2) - prune_to_highest_prio(pool, &pq); + solver_prune_to_highest_prio(solv, &pq); for (k = 0; k < pq.count; k++) plist->elements[j++] = pq.elements[k]; queue_empty(&pq); @@ -140,7 +209,7 @@ prune_to_highest_prio_per_name(Pool *pool, Queue *plist) } } if (pq.count > 2) - prune_to_highest_prio(pool, &pq); + solver_prune_to_highest_prio(solv, &pq); for (k = 0; k < pq.count; k++) plist->elements[j++] = pq.elements[k]; queue_free(&pq); @@ -603,48 +672,6 @@ prune_to_best_version(Pool *pool, Queue *plist) } -/* legacy, do not use anymore! - * (rates arch higher than version, but thats a policy) - */ - -static void -prune_best_arch_name_version(const Solver *solv, Pool *pool, Queue *plist) -{ - if (plist->count > 1) - prune_to_best_arch(pool, plist); - if (plist->count > 1) - prune_to_best_version(pool, plist); -} - -/* installed packages involed in a dup operation can only be kept - * if they are identical to a non-installed one */ -static void -prune_installed_dup_packages(Solver *solv, Queue *plist) -{ - Pool *pool = solv->pool; - int i, j, k; - - for (i = j = 0; i < plist->count; i++) - { - Id p = plist->elements[i]; - Solvable *s = pool->solvables + p; - if (s->repo == pool->installed && (solv->dupmap_all || (solv->dupinvolvedmap.size && MAPTST(&solv->dupinvolvedmap, p)))) - { - for (k = 0; k < plist->count; k++) - { - Solvable *s2 = pool->solvables + plist->elements[k]; - if (s2->repo != pool->installed && solvable_identical(s, s2)) - break; - } - if (k == plist->count) - continue; /* no identical package found, ignore installed package */ - } - plist->elements[j++] = p; - } - if (j) - plist->count = j; -} - /* * POLICY_MODE_CHOOSE: default, do all pruning steps * POLICY_MODE_RECOMMEND: leave out prune_to_recommended @@ -657,15 +684,14 @@ policy_filter_unwanted(Solver *solv, Queue *plist, int mode) if (plist->count > 1) { if (mode != POLICY_MODE_SUGGEST) - prune_to_highest_prio(pool, plist); + solver_prune_to_highest_prio(solv, plist); else - prune_to_highest_prio_per_name(pool, plist); - /* installed dup packages need special treatment as prio pruning - * does not prune installed packages */ - if (plist->count > 1 && pool->installed && (solv->dupmap_all || solv->dupinvolvedmap.size)) - prune_installed_dup_packages(solv, plist); + solver_prune_to_highest_prio_per_name(solv, plist); } - prune_best_arch_name_version(solv, pool, plist); + if (plist->count > 1) + prune_to_best_arch(pool, plist); + if (plist->count > 1) + prune_to_best_version(pool, plist); if (plist->count > 1 && mode == POLICY_MODE_CHOOSE) prune_to_recommended(solv, plist); } |