From 316da141ed291a88512a23233c14c09a2841d60d Mon Sep 17 00:00:00 2001 From: Wolf Vollprecht Date: Sun, 30 May 2021 14:49:00 +0200 Subject: [PATCH] improve conda variant handling --- src/conda.c | 2 +- src/policy.c | 104 +++++++++++++++++++++++++++++++++++++++++++-------- src/policy.h | 3 ++ src/solver.c | 29 +++++++++++++- 4 files changed, 121 insertions(+), 17 deletions(-) diff --git a/src/conda.c b/src/conda.c index 21ad6bfbe..408a236a7 100644 --- a/src/conda.c +++ b/src/conda.c @@ -134,7 +134,7 @@ solv_vercmp_conda(const char *s1, const char *q1, const char *s2, const char *q2 return -1; if (s1p - s1 > s2p - s2) return 1; - r = s1p - s1 ? strncmp(s1, s2, s1p - s1) : 0; + r = (s1p - s1) ? strncmp(s1, s2, s1p - s1) : 0; if (r) return r; } diff --git a/src/policy.c b/src/policy.c index c02d23730..44028cc13 100644 --- a/src/policy.c +++ b/src/policy.c @@ -874,6 +874,11 @@ pool_buildflavorcmp(Pool *pool, Solvable *s1, Solvable *s2) void prune_to_best_version(Pool *pool, Queue *plist) { +#ifdef ENABLE_CONDA + if (pool->disttype == DISTTYPE_CONDA) + return prune_to_best_version_conda(pool, plist); +#endif + int i, j, r; Solvable *s, *best; @@ -909,30 +914,16 @@ prune_to_best_version(Pool *pool, Queue *plist) } r = 0; -#ifdef ENABLE_CONDA - if (pool->disttype == DISTTYPE_CONDA) - r = pool_featurecountcmp(pool, best, s); -#endif if (r == 0) r = best->evr != s->evr ? pool_evrcmp(pool, best->evr, s->evr, EVRCMP_COMPARE) : 0; #ifdef ENABLE_LINKED_PKGS if (r == 0 && has_package_link(pool, s)) r = pool_link_evrcmp(pool, best, s); -#endif -#ifdef ENABLE_CONDA - if (pool->disttype == DISTTYPE_CONDA) - { - if (r == 0) - r = (best->repo ? best->repo->subpriority : 0) - (s->repo ? s->repo->subpriority : 0); - if (r == 0) - r = pool_buildversioncmp(pool, best, s); - if (r == 0) - r = pool_buildflavorcmp(pool, best, s); - } #endif if (r < 0) best = s; } + plist->elements[j++] = best - pool->solvables; /* finish last group */ plist->count = j; @@ -947,6 +938,89 @@ prune_to_best_version(Pool *pool, Queue *plist) } } +#ifdef ENABLE_CONDA +/* + * prune_to_best_version_conda + * + * sort list of packages (given through plist) by name and evr + * return result through plist + */ +void +prune_to_best_version_conda(Pool *pool, Queue *plist) +{ + int i, j, r; + Solvable *s, *best; + + if (plist->count < 2) /* no need to prune for a single entry */ + return; + POOL_DEBUG(SOLV_DEBUG_POLICY, "prune_to_best_version_conda %d\n", plist->count); + + /* sort by name first, prefer installed */ + solv_sort(plist->elements, plist->count, sizeof(Id), prune_to_best_version_sortcmp, pool); + + /* now find best 'per name' */ + best = 0; + for (i = j = 0; i < plist->count; i++) + { + s = pool->solvables + plist->elements[i]; + + POOL_DEBUG(SOLV_DEBUG_POLICY, "- %s [%d]%s\n", + pool_solvable2str(pool, s), plist->elements[i], + (pool->installed && s->repo == pool->installed) ? "I" : ""); + + if (!best) /* if no best yet, the current is best */ + { + best = s; + continue; + } + + /* name switch: finish group, re-init */ + if (best->name != s->name) /* new name */ + { + plist->elements[j++] = best - pool->solvables; /* move old best to front */ + best = s; /* take current as new best */ + continue; + } + + r = 0; + r = pool_featurecountcmp(pool, best, s); + if (r == 0) + r = best->evr != s->evr ? pool_evrcmp(pool, best->evr, s->evr, EVRCMP_COMPARE) : 0; + if (r == 0) + r = (best->repo ? best->repo->subpriority : 0) - (s->repo ? s->repo->subpriority : 0); + if (r == 0) + r = pool_buildversioncmp(pool, best, s); + if (r == 0) + r = pool_buildflavorcmp(pool, best, s); + if (r < 0) + best = s; + } + + Queue q; + queue_init(&q); + for (i = j = 0; i < plist->count; i++) + { + s = pool->solvables + plist->elements[i]; + r = pool_featurecountcmp(pool, best, s); + if (r == 0) + r = best->evr != s->evr ? pool_evrcmp(pool, best->evr, s->evr, EVRCMP_COMPARE) : 0; + if (r == 0) + r = (best->repo ? best->repo->subpriority : 0) - (s->repo ? s->repo->subpriority : 0); + if (r == 0) + r = pool_buildversioncmp(pool, best, s); + if (r == 0) + queue_push(&q, s - pool->solvables); + } + + for (i = 0; i < q.count; ++i) + { + plist->elements[i] = q.elements[i]; + } + + plist->count = q.count; + queue_free(&q); +} +#endif // ENABLE_CONDA static int sort_by_name_evr_sortcmp(const void *ap, const void *bp, void *dp) diff --git a/src/policy.h b/src/policy.h index 3ae1005a1..1210f585e 100644 --- a/src/policy.h +++ b/src/policy.h @@ -43,6 +43,9 @@ extern void pool_best_solvables(Pool *pool, Queue *plist, int flags); /* internal, do not use */ extern void prune_to_best_version(Pool *pool, Queue *plist); +#ifdef ENABLE_CONDA +extern void prune_to_best_version_conda(Pool *pool, Queue *plist); +#endif extern void policy_prefer_favored(Solver *solv, Queue *plist); diff --git a/src/solver.c b/src/solver.c index 89a2ed10f..9cb798dab 100644 --- a/src/solver.c +++ b/src/solver.c @@ -3360,6 +3360,30 @@ setup_favormap(Solver *solv) } } +static void +setup_trackfeatures_favor(Solver *solv) +{ + Pool *pool = solv->pool; + int idx, cnt; + Id p; + + solv_free(solv->favormap); + solv->favormap = solv_calloc(pool->nsolvables, sizeof(Id)); + + idx = 0; + FOR_POOL_SOLVABLES(p) + { + Solvable *s = pool->solvables + p; + cnt = solvable_lookup_count(s, SOLVABLE_TRACK_FEATURES); + if (cnt != 0) + { + idx++; + solv->favormap[p] = -idx; + solv->havedisfavored = 1; + } + } +} + /* * * solve job queue @@ -4022,7 +4046,10 @@ solver_solve(Solver *solv, Queue *job) /* create favormap if we have favor jobs */ if (hasfavorjob) setup_favormap(solv); - +#ifdef ENABLE_CONDA + else + setup_trackfeatures_favor(solv); +#endif /* now create infarch and dup rules */ if (!solv->noinfarchcheck) solver_addinfarchrules(solv, &addedmap);