summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/libsolv.ver2
-rw-r--r--src/policy.c202
-rw-r--r--src/policy.h2
-rw-r--r--src/pool.c47
-rw-r--r--src/pool.h1
-rw-r--r--src/poolarch.c25
-rw-r--r--src/selection.c93
-rw-r--r--src/selection.h2
-rw-r--r--src/solver.c130
-rw-r--r--src/solver.h7
10 files changed, 472 insertions, 39 deletions
diff --git a/src/libsolv.ver b/src/libsolv.ver
index cc79704..a5efd6a 100644
--- a/src/libsolv.ver
+++ b/src/libsolv.ver
@@ -120,6 +120,7 @@ SOLV_1.0 {
pool_trivial_installable_multiversionmap;
pool_vendor2mask;
pool_whatmatchesdep;
+ pool_whatcontainsdep;
queue_alloc_one;
queue_alloc_one_head;
queue_delete;
@@ -245,6 +246,7 @@ SOLV_1.0 {
selection_add;
selection_filter;
selection_make;
+ selection_make_matchdepid;
selection_make_matchdeps;
selection_solvables;
solv_bin2hex;
diff --git a/src/policy.c b/src/policy.c
index 12ad771..3a0a737 100644
--- a/src/policy.c
+++ b/src/policy.c
@@ -453,6 +453,89 @@ prefer_suggested(Solver *solv, Queue *plist)
}
}
+static int
+sort_by_favorq_cmp(const void *ap, const void *bp, void *dp)
+{
+ const Id *a = ap, *b = bp, *d = dp;
+ return d[b[0]] - d[a[0]];
+}
+
+static void
+sort_by_favorq(Queue *favorq, Id *el, int cnt)
+{
+ int i;
+ /* map to offsets into favorq */
+ for (i = 0; i < cnt; i++)
+ {
+ Id p = el[i];
+ /* lookup p in sorted favorq */
+ int med = 0, low = 0;
+ int high = favorq->count / 2;
+ while (low != high)
+ {
+ med = (low + high) / 2;
+ Id pp = favorq->elements[2 * med];
+ if (pp < p)
+ low = med;
+ else if (pp > p)
+ high = med;
+ else
+ break;
+ }
+ while(med && favorq->elements[2 * med - 2] == p)
+ med--;
+ if (favorq->elements[2 * med] == p)
+ el[i] = 2 * med + 1;
+ else
+ el[i] = 0; /* hmm */
+ }
+ /* sort by position */
+ solv_sort(el, cnt, sizeof(Id), sort_by_favorq_cmp, favorq->elements);
+ /* map back */
+ for (i = 0; i < cnt; i++)
+ if (el[i])
+ el[i] = favorq->elements[el[i] - 1];
+}
+
+/* bring favored packages to front and disfavored packages to back */
+void
+policy_prefer_favored(Solver *solv, Queue *plist)
+{
+ int i, fav, disfav, count;
+ if (!solv->favormap.size)
+ return;
+ for (i = fav = disfav = 0, count = plist->count; i < count; i++)
+ {
+ Id p = plist->elements[i];
+ if (!MAPTST(&solv->favormap, p))
+ continue;
+ if (solv->isdisfavormap.size && MAPTST(&solv->isdisfavormap, p))
+ {
+ /* disfavored package. bring to back */
+ if (i < plist->count - 1)
+ {
+ memmove(plist->elements + i, plist->elements + i + 1, (plist->count - 1 - i) * sizeof(Id));
+ plist->elements[plist->count - 1] = p;
+ }
+ i--;
+ count--;
+ disfav++;
+ }
+ else
+ {
+ /* favored package. bring to front */
+ if (i > fav)
+ memmove(plist->elements + fav + 1, plist->elements + fav, (i - fav) * sizeof(Id));
+ plist->elements[fav++] = p;
+ }
+ }
+ /* if we have multiple favored/disfavored packages, sort by favorq index */
+ if (fav > 1)
+ sort_by_favorq(solv->favorq, plist->elements, fav);
+ if (disfav > 1)
+ sort_by_favorq(solv->favorq, plist->elements + plist->count - disfav, disfav);
+}
+
/*
* prune to recommended/suggested packages.
* does not prune installed packages (they are also somewhat recommended).
@@ -1112,6 +1195,111 @@ dislike_old_versions(Pool *pool, Queue *plist)
}
}
+
+/* special lang package handling for urpm */
+/* see https://bugs.mageia.org/show_bug.cgi?id=18315 */
+
+static int
+urpm_reorder_cmp(const void *ap, const void *bp, void *dp)
+{
+ return ((Id *)bp)[1] - ((Id *)ap)[1];
+}
+
+static void
+urpm_reorder(Solver *solv, Queue *plist)
+{
+ Pool *pool = solv->pool;
+ int i, count = plist->count;
+ /* add locale score to packages */
+ queue_insertn(plist, count, count, 0);
+ for (i = count - 1; i >= 0; i--)
+ {
+ Solvable *s = pool->solvables + plist->elements[i];
+ int score = 1;
+ const char *sn = pool_id2str(pool, s->name);
+
+ if (!strncmp(sn, "kernel-", 7))
+ {
+ const char *devel = strstr(sn, "-devel-");
+ if (devel && strlen(sn) < 256)
+ {
+ char kn[256];
+ Id p, pp, knid;
+ memcpy(kn, sn, devel - sn);
+ strcpy(kn + (devel - sn), devel + 6);
+ knid = pool_str2id(pool, kn, 0);
+ if (knid)
+ {
+ FOR_PROVIDES(p, pp, knid)
+ if (solv->decisionmap[p] > 0 || (pool->installed && pool->solvables[p].repo == pool->installed))
+ score = 3;
+ }
+ }
+ }
+ else if ((sn = strstr(sn, "-kernel-")) != 0)
+ {
+ sn += 8;
+ if (strlen(sn) < 256 - 8 && *sn >= '0' && *sn <= '9' && sn[1] == '.')
+ {
+ const char *flavor = strchr(sn, '-');
+ if (flavor)
+ {
+ const char *release = strchr(flavor + 1, '-');
+ if (release)
+ {
+ char kn[256];
+ Id p, pp, knid;
+ memcpy(kn, "kernel", 8);
+ memcpy(kn + 6, flavor, release - flavor + 1);
+ memcpy(kn + 6 + (release - flavor) + 1, sn, flavor - sn);
+ strcpy(kn + 6 + (release + 1 - sn), release);
+ knid = pool_str2id(pool, kn, 0);
+ if (knid)
+ {
+ FOR_PROVIDES(p, pp, knid)
+ if (solv->decisionmap[p] > 0 || (pool->installed && pool->solvables[p].repo == pool->installed))
+ score = 3;
+ }
+ }
+ }
+ }
+ }
+ if (score == 1 && s->requires)
+ {
+ Id id, *idp, p, pp;
+ const char *deps;
+ for (idp = s->repo->idarraydata + s->requires; (id = *idp) != 0; idp++)
+ {
+ while (ISRELDEP(id))
+ {
+ Reldep *rd = GETRELDEP(pool, id);
+ id = rd->name;
+ }
+ deps = strstr(pool_id2str(pool, id), "locales-");
+ if (!deps)
+ continue;
+ if (!strncmp(deps + 8, "en", 2))
+ score = 2;
+ else
+ {
+ score = 0;
+ FOR_PROVIDES(p, pp, id)
+ if (solv->decisionmap[p] > 0 || (pool->installed && pool->solvables[p].repo == pool->installed))
+ score = 3;
+ break;
+ }
+ }
+ }
+ plist->elements[i * 2] = plist->elements[i];
+ plist->elements[i * 2 + 1] = score;
+ }
+ solv_sort(plist->elements, count, sizeof(Id) * 2, urpm_reorder_cmp, pool);
+ for (i = 0; i < count; i++)
+ plist->elements[i] = plist->elements[2 * i];
+ queue_truncate(plist, count);
+}
+
+
/*
* POLICY_MODE_CHOOSE: default, do all pruning steps
* POLICY_MODE_RECOMMEND: leave out prune_to_recommended
@@ -1121,6 +1309,17 @@ void
policy_filter_unwanted(Solver *solv, Queue *plist, int mode)
{
Pool *pool = solv->pool;
+ if (mode == POLICY_MODE_SUPPLEMENT)
+ {
+ /* reorder only */
+ dislike_old_versions(pool, plist);
+ sort_by_common_dep(pool, plist);
+ if (solv->urpmreorder)
+ urpm_reorder(solv, plist);
+ prefer_suggested(solv, plist);
+ policy_prefer_favored(solv, plist);
+ return;
+ }
if (plist->count > 1)
{
if (mode != POLICY_MODE_SUGGEST)
@@ -1143,7 +1342,10 @@ policy_filter_unwanted(Solver *solv, Queue *plist, int mode)
#endif
dislike_old_versions(pool, plist);
sort_by_common_dep(pool, plist);
+ if (solv->urpmreorder)
+ urpm_reorder(solv, plist);
prefer_suggested(solv, plist);
+ policy_prefer_favored(solv, plist);
}
}
}
diff --git a/src/policy.h b/src/policy.h
index 73410ee..0c3c7cb 100644
--- a/src/policy.h
+++ b/src/policy.h
@@ -20,6 +20,7 @@ extern "C" {
#define POLICY_MODE_RECOMMEND 1
#define POLICY_MODE_SUGGEST 2
#define POLICY_MODE_CHOOSE_NOREORDER 3 /* internal, do not use */
+#define POLICY_MODE_SUPPLEMENT 4 /* internal, do not use */
#define POLICY_ILLEGAL_DOWNGRADE 1
@@ -39,6 +40,7 @@ extern void policy_create_obsolete_index(Solver *solv);
/* internal, do not use */
extern void prune_to_best_version(Pool *pool, Queue *plist);
+extern void policy_prefer_favored(Solver *solv, Queue *plist);
#ifdef __cplusplus
diff --git a/src/pool.c b/src/pool.c
index ecc3686..c51c62e 100644
--- a/src/pool.c
+++ b/src/pool.c
@@ -1331,8 +1331,11 @@ void
pool_whatmatchesdep(Pool *pool, Id keyname, Id dep, Queue *q, int marker)
{
Id p;
+ Queue qq;
+ int i;
queue_empty(q);
+ queue_init(&qq);
FOR_POOL_SOLVABLES(p)
{
Solvable *s = pool->solvables + p;
@@ -1340,9 +1343,49 @@ pool_whatmatchesdep(Pool *pool, Id keyname, Id dep, Queue *q, int marker)
continue;
if (s->repo != pool->installed && !pool_installable(pool, s))
continue;
- if (solvable_matchesdep(s, keyname, dep, marker))
- queue_push(q, p);
+ if (qq.count)
+ queue_empty(&qq);
+ solvable_lookup_deparray(s, keyname, &qq, marker);
+ for (i = 0; i < qq.count; i++)
+ if (pool_match_dep(pool, qq.elements[i], dep))
+ {
+ queue_push(q, p);
+ break;
+ }
+ }
+ queue_free(&qq);
+}
+
+/* check if keyname contains dep, return list of matching packages */
+void
+pool_whatcontainsdep(Pool *pool, Id keyname, Id dep, Queue *q, int marker)
+{
+ Id p;
+ Queue qq;
+ int i;
+
+ queue_empty(q);
+ if (!dep)
+ return;
+ queue_init(&qq);
+ FOR_POOL_SOLVABLES(p)
+ {
+ Solvable *s = pool->solvables + p;
+ if (s->repo->disabled)
+ continue;
+ if (s->repo != pool->installed && !pool_installable(pool, s))
+ continue;
+ if (qq.count)
+ queue_empty(&qq);
+ solvable_lookup_deparray(s, keyname, &qq, marker);
+ for (i = 0; i < qq.count; i++)
+ if (qq.elements[i] == dep)
+ {
+ queue_push(q, p);
+ break;
+ }
}
+ queue_free(&qq);
}
/*************************************************************************/
diff --git a/src/pool.h b/src/pool.h
index b9e2ed6..069594b 100644
--- a/src/pool.h
+++ b/src/pool.h
@@ -347,6 +347,7 @@ static inline Id *pool_whatprovides_ptr(Pool *pool, Id d)
}
void pool_whatmatchesdep(Pool *pool, Id keyname, Id dep, Queue *q, int marker);
+void pool_whatcontainsdep(Pool *pool, Id keyname, Id dep, Queue *q, int marker);
/* search the pool. the following filters are available:
* p - search just this solvable
diff --git a/src/poolarch.c b/src/poolarch.c
index 788646b..83cbd62 100644
--- a/src/poolarch.c
+++ b/src/poolarch.c
@@ -29,16 +29,10 @@ static const char *archpolicies[] = {
"i686", "i686:i586:i486:i386",
"i586", "i586:i486:i386",
"i486", "i486:i386",
- "i386", "i386",
"s390x", "s390x:s390",
- "s390", "s390",
- "ppc64le", "ppc64le",
"ppc64", "ppc64:ppc",
- "ppc", "ppc",
"ppc64p7", "ppc64p7:ppc64:ppc",
"ia64", "ia64:i686:i586:i486:i386",
- "aarch64", "aarch64",
- "armv6hl", "armv6hl",
"armv7hnl", "armv7hnl:armv7hl:armv6hl",
"armv7hl", "armv7hl:armv6hl",
"armv7l", "armv7l:armv6l:armv5tejl:armv5tel:armv5l:armv4tl:armv4l:armv3l",
@@ -49,21 +43,12 @@ static const char *archpolicies[] = {
"armv5l", "armv5l:armv4tl:armv4l:armv3l",
"armv4tl", "armv4tl:armv4l:armv3l",
"armv4l", "armv4l:armv3l",
- "armv3l", "armv3l",
- "sh3", "sh3",
- "sh4", "sh4",
"sh4a", "sh4a:sh4",
"sparc64v", "sparc64v:sparc64:sparcv9v:sparcv9:sparcv8:sparc",
"sparc64", "sparc64:sparcv9:sparcv8:sparc",
"sparcv9v", "sparcv9v:sparcv9:sparcv8:sparc",
"sparcv9", "sparcv9:sparcv8:sparc",
"sparcv8", "sparcv8:sparc",
- "sparc", "sparc",
- "mips", "mips",
- "mipsel", "mipsel",
- "mips64", "mips64",
- "mips64el", "mips64el",
- "m68k", "m68k",
#if defined(FEDORA) || defined(MAGEIA)
"ia32e", "ia32e:x86_64:athlon:i686:i586:i486:i386",
"athlon", "athlon:i686:i586:i486:i386",
@@ -81,15 +66,13 @@ pool_setarch(Pool *pool, const char *arch)
if (arch)
{
int i;
-
/* convert arch to known policy */
for (i = 0; archpolicies[i]; i += 2)
if (!strcmp(archpolicies[i], arch))
- break;
- if (archpolicies[i])
- arch = archpolicies[i + 1];
- else
- arch = "";
+ {
+ arch = archpolicies[i + 1];
+ break;
+ }
}
pool_setarchpolicy(pool, arch);
}
diff --git a/src/selection.c b/src/selection.c
index 7d9a918..6b89ab0 100644
--- a/src/selection.c
+++ b/src/selection.c
@@ -867,6 +867,19 @@ selection_make(Pool *pool, Queue *selection, const char *name, int flags)
return ret;
}
+static inline int
+matchdep_str(const char *pattern, const char *string, int flags)
+{
+ if (flags & SELECTION_GLOB)
+ {
+ int globflags = (flags & SELECTION_NOCASE) != 0 ? FNM_CASEFOLD : 0;
+ return fnmatch(pattern, string, globflags) == 0 ? 1 : 0;
+ }
+ if (flags & SELECTION_NOCASE)
+ return strcasecmp(pattern, string) == 0 ? 1 : 0;
+ return strcmp(pattern, string) == 0 ? 1 : 0;
+}
+
static int
matchdep(Pool *pool, Id id, char *rname, int rflags, char *revr, int flags)
{
@@ -899,14 +912,7 @@ matchdep(Pool *pool, Id id, char *rname, int rflags, char *revr, int flags)
}
return 1;
}
- if (flags & SELECTION_GLOB)
- {
- int globflags = (flags & SELECTION_NOCASE) != 0 ? FNM_CASEFOLD : 0;
- return fnmatch(rname, pool_id2str(pool, id), globflags) == 0 ? 1 : 0;
- }
- if (flags & SELECTION_NOCASE)
- return strcasecmp(rname, pool_id2str(pool, id)) == 0 ? 1 : 0;
- return strcmp(rname, pool_id2str(pool, id)) == 0 ? 1 : 0;
+ return matchdep_str(rname, pool_id2str(pool, id), flags);
}
/*
@@ -917,22 +923,25 @@ matchdep(Pool *pool, Id id, char *rname, int rflags, char *revr, int flags)
int
selection_make_matchdeps(Pool *pool, Queue *selection, const char *name, int flags, int keyname, int marker)
{
- char *rname, *r;
+ char *rname, *r = 0;
int rflags = 0;
Id p;
Queue q;
queue_empty(selection);
rname = solv_strdup(name);
- if ((r = strpbrk(rname, "<=>")) != 0)
+ if (!(flags & SELECTION_MATCH_DEPSTR))
{
- if ((r = splitrel(rname, r, &rflags)) == 0)
+ if ((r = strpbrk(rname, "<=>")) != 0)
{
- solv_free(rname);
- return 0;
+ if ((r = splitrel(rname, r, &rflags)) == 0)
+ {
+ solv_free(rname);
+ return 0;
+ }
}
}
- if ((flags & SELECTION_GLOB) != 0 && !strpbrk(name, "[*?") != 0)
+ if ((flags & SELECTION_GLOB) != 0 && !strpbrk(rname, "[*?") != 0)
flags &= ~SELECTION_GLOB;
queue_init(&q);
@@ -957,6 +966,12 @@ selection_make_matchdeps(Pool *pool, Queue *selection, const char *name, int fla
for (i = 0; i < q.count; i++)
{
Id id = q.elements[i];
+ if ((flags & SELECTION_MATCH_DEPSTR) != 0)
+ {
+ if (matchdep_str(rname, pool_dep2str(pool, id), flags))
+ break;
+ continue;
+ }
if (matchdep(pool, id, rname, rflags, r, flags))
break;
}
@@ -972,6 +987,56 @@ selection_make_matchdeps(Pool *pool, Queue *selection, const char *name, int fla
return SELECTION_PROVIDES;
}
+int
+selection_make_matchdepid(Pool *pool, Queue *selection, Id dep, int flags, int keyname, int marker)
+{
+ Id p;
+ Queue q;
+
+ queue_empty(selection);
+ if (!dep)
+ return 0;
+ queue_init(&q);
+ FOR_POOL_SOLVABLES(p)
+ {
+ Solvable *s = pool->solvables + p;
+ int i;
+
+ if (s->repo != pool->installed && !pool_installable(pool, s))
+ {
+ if (!(flags & SELECTION_SOURCE_ONLY) || (s->arch != ARCH_SRC && s->arch != ARCH_NOSRC))
+ continue;
+ if (pool_disabled_solvable(pool, s))
+ continue;
+ }
+ if ((flags & SELECTION_INSTALLED_ONLY) != 0 && s->repo != pool->installed)
+ continue;
+ if ((s->arch == ARCH_SRC || s->arch == ARCH_NOSRC) && !(flags & SELECTION_SOURCE_ONLY) && !(flags & SELECTION_WITH_SOURCE))
+ continue;
+ queue_empty(&q);
+ repo_lookup_deparray(s->repo, p, keyname, &q, marker);
+ for (i = 0; i < q.count; i++)
+ {
+ if ((flags & SELECTION_MATCH_DEPSTR) != 0) /* mis-use */
+ {
+ if (q.elements[i] == dep)
+ break;
+ continue;
+ }
+ if (pool_match_dep(pool, q.elements[i], dep))
+ break;
+ }
+ if (i < q.count)
+ queue_push2(selection, SOLVER_SOLVABLE | SOLVER_NOAUTOSET, p);
+ }
+ queue_free(&q);
+ if (!selection->count)
+ return 0;
+ if ((flags & SELECTION_FLAT) != 0)
+ selection_flatten(pool, selection);
+ return SELECTION_PROVIDES;
+}
+
static inline int
pool_is_kind(Pool *pool, Id name, Id kind)
{
diff --git a/src/selection.h b/src/selection.h
index fc2b15d..0dd6150 100644
--- a/src/selection.h
+++ b/src/selection.h
@@ -33,9 +33,11 @@ extern "C" {
#define SELECTION_SOURCE_ONLY (1 << 12)
#define SELECTION_WITH_SOURCE (1 << 13)
#define SELECTION_SKIP_KIND (1 << 14)
+#define SELECTION_MATCH_DEPSTR (1 << 15)
extern int selection_make(Pool *pool, Queue *selection, const char *name, int flags);
extern int selection_make_matchdeps(Pool *pool, Queue *selection, const char *name, int flags, int keyname, int marker);
+extern int selection_make_matchdepid(Pool *pool, Queue *selection, Id dep, int flags, int keyname, int marker);
extern void selection_filter(Pool *pool, Queue *sel1, Queue *sel2);
extern void selection_add(Pool *pool, Queue *sel1, Queue *sel2);
diff --git a/src/solver.c b/src/solver.c
index d5989cc..4f849ec 100644
--- a/src/solver.c
+++ b/src/solver.c
@@ -1432,6 +1432,8 @@ reorder_dq_for_jobrules(Solver *solv, int level, Queue *dq)
solv->recommends_index = -1;
queue_truncate(&solv->decisionq, decisionqcount);
}
+ /* but obey favored maps */
+ policy_prefer_favored(solv, dq);
}
/*-------------------------------------------------------------------
@@ -1701,6 +1703,7 @@ solver_free(Solver *solv)
queuep_free(&solv->recommendscplxq);
queuep_free(&solv->suggestscplxq);
queuep_free(&solv->brokenorphanrules);
+ queuep_free(&solv->favorq);
map_free(&solv->recommendsmap);
map_free(&solv->suggestsmap);
@@ -1716,6 +1719,8 @@ solver_free(Solver *solv)
map_free(&solv->droporphanedmap);
map_free(&solv->cleandepsmap);
map_free(&solv->allowuninstallmap);
+ map_free(&solv->favormap);
+ map_free(&solv->isdisfavormap);
solv_free(solv->decisionmap);
solv_free(solv->rules);
@@ -1779,6 +1784,8 @@ solver_get_flag(Solver *solv, int flag)
return solv->do_yum_obsoletes;
case SOLVER_FLAG_NEED_UPDATEPROVIDE:
return solv->needupdateprovide;
+ case SOLVER_FLAG_URPM_REORDER:
+ return solv->urpmreorder;
default:
break;
}
@@ -1857,6 +1864,9 @@ solver_set_flag(Solver *solv, int flag, int value)
case SOLVER_FLAG_NEED_UPDATEPROVIDE:
solv->needupdateprovide = value;
break;
+ case SOLVER_FLAG_URPM_REORDER:
+ solv->urpmreorder = value;
+ break;
default:
break;
}
@@ -2063,6 +2073,22 @@ do_complex_recommendations(Solver *solv, Id rec, Map *m, int noselected)
#endif
+static void
+prune_disfavored(Solver *solv, Queue *plist)
+{
+ int i, j;
+ if (!solv->isdisfavormap.size)
+ return;
+ for (i = j = 0; i < plist->count; i++)
+ {
+ Id p = plist->elements[i];
+ if (!MAPTST(&solv->isdisfavormap, p))
+ plist->elements[j++] = p;
+ }
+ if (i != j)
+ queue_truncate(plist, j);
+}
+
/*-------------------------------------------------------------------
*
* solver_run_sat
@@ -2522,10 +2548,16 @@ solver_run_sat(Solver *solv, int disablerules, int doweak)
continue;
if (solv->dupmap_all && solv->installed && s->repo == solv->installed && (solv->droporphanedmap_all || (solv->droporphanedmap.size && MAPTST(&solv->droporphanedmap, i - solv->installed->start))))
continue;
+ if (solv->isdisfavormap.size && MAPTST(&solv->isdisfavormap, i))
+ continue; /* disfavored supplements, do not install */
queue_push(&dqs, i);
}
}
+ /* filter out disfavored recommended packages */
+ if (dq.count && solv->isdisfavormap.size)
+ prune_disfavored(solv, &dq);
+
/* filter out all packages obsoleted by installed packages */
/* this is no longer needed if we have reverse obsoletes */
if ((dqs.count || dq.count) && solv->installed)
@@ -2604,6 +2636,26 @@ solver_run_sat(Solver *solv, int disablerules, int doweak)
dqs.count = j;
}
+ /* implicitobsoleteusescolors doesn't mix well with supplements.
+ * filter supplemented packages where we already decided
+ * to install a different architecture */
+ if (dqs.count && pool->implicitobsoleteusescolors)
+ {
+ for (i = j = 0; i < dqs.count; i++)
+ {
+ Id p2, pp2;
+ p = dqs.elements[i];
+ s = pool->solvables + p;
+ FOR_PROVIDES(p2, pp2, s->name)
+ if (solv->decisionmap[p2] > 0 && pool->solvables[p2].name == s->name && pool->solvables[p2].arch != s->arch)
+ break;
+ if (p2)
+ continue; /* ignore this package */
+ dqs.elements[j++] = p;
+ }
+ dqs.count = j;
+ }
+
/* make dq contain both recommended and supplemented pkgs */
if (dqs.count)
{
@@ -2636,11 +2688,22 @@ solver_run_sat(Solver *solv, int disablerules, int doweak)
for (i = 0; i < dq.count; i++)
MAPSET(&dqmap, dq.elements[i]);
- /* install all supplemented packages */
+ /* prune dqs so that it only contains the best versions */
+ for (i = j = 0; i < dqs.count; i++)
+ {
+ p = dqs.elements[i];
+ if (MAPTST(&dqmap, p))
+ dqs.elements[j++] = p;
+ }
+ dqs.count = j;
+
+ /* install all supplemented packages, but order first */
+ if (dqs.count > 1)
+ policy_filter_unwanted(solv, &dqs, POLICY_MODE_SUPPLEMENT);
for (i = 0; i < dqs.count; i++)
{
p = dqs.elements[i];
- if (solv->decisionmap[p] || !MAPTST(&dqmap, p))
+ if (solv->decisionmap[p])
continue;
POOL_DEBUG(SOLV_DEBUG_POLICY, "installing supplemented %s\n", pool_solvid2str(pool, p));
olevel = level;
@@ -3327,6 +3390,42 @@ add_complex_jobrules(Solver *solv, Id dep, int flags, int jobidx, int weak)
}
#endif
+/* sort by package id, last entry wins */
+static int
+setup_favormaps_cmp(const void *ap, const void *bp, void *dp)
+{
+ const Id *a = ap, *b = bp;
+ if ((*a - *b) != 0)
+ return *a - *b;
+ return (b[1] < 0 ? -b[1] : b[1]) - (a[1] < 0 ? -a[1] : a[1]);
+}
+
+static void
+setup_favormaps(Solver *solv)
+{
+ Queue *q = solv->favorq;
+ Pool *pool = solv->pool;
+ int i;
+ Id oldp = 0;
+ if (q->count > 2)
+ solv_sort(q->elements, q->count / 2, 2 * sizeof(Id), setup_favormaps_cmp, solv);
+ map_grow(&solv->favormap, pool->nsolvables);
+ for (i = 0; i < q->count; i += 2)
+ {
+ Id p = q->elements[i];
+ if (p == oldp)
+ continue;
+ oldp = p;
+ MAPSET(&solv->favormap, p);
+ if (q->elements[i + 1] < 0)
+ {
+ if (!solv->isdisfavormap.size)
+ map_grow(&solv->isdisfavormap, pool->nsolvables);
+ MAPSET(&solv->isdisfavormap, p);
+ }
+ }
+}
+
/*
*
* solve job queue
@@ -3400,6 +3499,8 @@ solver_solve(Solver *solv, Queue *job)
map_zerosize(&solv->allowuninstallmap);
map_zerosize(&solv->cleandepsmap);
map_zerosize(&solv->weakrulemap);
+ map_zerosize(&solv->favormap);
+ map_zerosize(&solv->isdisfavormap);
queue_empty(&solv->weakruleq);
solv->watches = solv_free(solv->watches);
queue_empty(&solv->ruletojob);
@@ -3935,6 +4036,21 @@ solver_solve(Solver *solv, Queue *job)
case SOLVER_ALLOWUNINSTALL:
POOL_DEBUG(SOLV_DEBUG_JOB, "job: allowuninstall %s\n", solver_select2str(pool, select, what));
break;
+ case SOLVER_FAVOR:
+ case SOLVER_DISFAVOR:
+ POOL_DEBUG(SOLV_DEBUG_JOB, "job: %s %s\n", (how & SOLVER_JOBMASK) == SOLVER_FAVOR ? "favor" : "disfavor", solver_select2str(pool, select, what));
+ FOR_JOB_SELECT(p, pp, select, what)
+ {
+ int j;
+ if (!solv->favorq)
+ {
+ solv->favorq = solv_calloc(1, sizeof(Queue));
+ queue_init(solv->favorq);
+ }
+ j = solv->favorq->count + 1;
+ queue_push2(solv->favorq, p, (how & SOLVER_JOBMASK) == SOLVER_FAVOR ? j : -j);
+ }
+ break;
default:
POOL_DEBUG(SOLV_DEBUG_JOB, "job: unknown job\n");
break;
@@ -3955,6 +4071,10 @@ solver_solve(Solver *solv, Queue *job)
assert(solv->ruletojob.count == solv->nrules - solv->jobrules);
solv->jobrules_end = solv->nrules;
+ /* transform favorq into two maps */
+ if (solv->favorq)
+ setup_favormaps(solv);
+
/* now create infarch and dup rules */
if (!solv->noinfarchcheck)
{
@@ -5157,6 +5277,12 @@ pool_job2str(Pool *pool, Id how, Id what, Id flagmask)
case SOLVER_ALLOWUNINSTALL:
strstart = "allow deinstallation of ";
break;
+ case SOLVER_FAVOR:
+ strstart = "favor ";
+ break;
+ case SOLVER_DISFAVOR:
+ strstart = "disfavor ";
+ break;
default:
strstart = "unknown job ";
break;
diff --git a/src/solver.h b/src/solver.h
index 2ae9c8d..3495fd8 100644
--- a/src/solver.h
+++ b/src/solver.h
@@ -167,6 +167,7 @@ struct _Solver {
int noautotarget; /* true: do not assume targeted for up/dup jobs that contain no installed solvable */
int focus_installed; /* true: resolve update rules first */
int do_yum_obsoletes; /* true: add special yumobs rules */
+ int urpmreorder; /* true: do special urpm package reordering */
Map dupmap; /* dup these packages*/
int dupmap_all; /* dup all packages */
@@ -199,6 +200,9 @@ struct _Solver {
Map allowuninstallmap; /* ok to uninstall those */
int allowuninstall_all;
+ Queue *favorq;
+ Map favormap; /* favored / disfavored packages */
+ Map isdisfavormap;
#endif /* LIBSOLV_INTERNAL */
};
@@ -229,6 +233,8 @@ typedef struct _Solver Solver;
#define SOLVER_DROP_ORPHANED 0x0900
#define SOLVER_USERINSTALLED 0x0a00
#define SOLVER_ALLOWUNINSTALL 0x0b00
+#define SOLVER_FAVOR 0x0c00
+#define SOLVER_DISFAVOR 0x0d00
#define SOLVER_JOBMASK 0xff00
@@ -302,6 +308,7 @@ typedef struct _Solver Solver;
#define SOLVER_FLAG_FOCUS_INSTALLED 20
#define SOLVER_FLAG_YUM_OBSOLETES 21
#define SOLVER_FLAG_NEED_UPDATEPROVIDE 22
+#define SOLVER_FLAG_URPM_REORDER 23
#define GET_USERINSTALLED_NAMES (1 << 0) /* package names instead of ids */
#define GET_USERINSTALLED_INVERTED (1 << 1) /* autoinstalled */