#include "selection.h"
#include "solver.h"
#include "evr.h"
+#ifdef ENABLE_CONDA
+#include "conda.h"
+#endif
+#ifdef _WIN32
+#include "strfncs.h"
+#endif
static int
str2archid(Pool *pool, const char *arch)
for (i = 0; i < selection->count; i += 2)
{
Id select = selection->elements[i] & SOLVER_SELECTMASK;
+ Id id = selection->elements[i + 1];
if (select == SOLVER_SOLVABLE_ALL)
{
FOR_POOL_SOLVABLES(p)
if (select == SOLVER_SOLVABLE_REPO)
{
Solvable *s;
- Repo *repo = pool_id2repo(pool, selection->elements[i + 1]);
+ Repo *repo = pool_id2repo(pool, id);
if (repo)
{
FOR_REPO_SOLVABLES(repo, p, s)
queue_push(pkgs, p);
}
}
+ else if (select == SOLVER_SOLVABLE)
+ queue_push(pkgs, id);
else
{
- FOR_JOB_SELECT(p, pp, select, selection->elements[i + 1])
+ FOR_JOB_SELECT(p, pp, select, id)
queue_push(pkgs, p);
}
}
/* limit a selection to to repository */
/* prunes empty jobs */
static void
-selection_filter_repo(Pool *pool, Queue *selection, Repo *repo)
+selection_filter_repo(Pool *pool, Queue *selection, Repo *repo, int setflags)
{
Queue q;
int i, j;
else if (select == SOLVER_SOLVABLE_REPO)
{
if (id != repo->repoid)
- select = 0;
+ continue;
+ }
+ else if (select == SOLVER_SOLVABLE)
+ {
+ if (pool->solvables[id].repo != repo)
+ continue;
}
else
{
else
queue_push(&q, p);
}
- if (bad || !q.count)
+ if (!q.count)
+ continue;
+ if (bad)
{
- if (!q.count)
- select = 0; /* prune empty jobs */
- else if (q.count == 1)
+ if (q.count == 1)
{
select = SOLVER_SOLVABLE | SOLVER_NOAUTOSET;
id = q.elements[0];
}
}
}
- if (!select)
- continue; /* job is now empty */
if (select == SOLVER_SOLVABLE_REPO)
{
Id p;
if (!p)
continue; /* repo is empty */
}
- selection->elements[j++] = select | (selection->elements[i] & ~SOLVER_SELECTMASK) | SOLVER_SETREPO;
+ selection->elements[j++] = select | (selection->elements[i] & ~SOLVER_SELECTMASK) | setflags;
selection->elements[j++] = id;
}
queue_truncate(selection, j);
}
/* this is the fast path of selection_provides: the id for the name
- * is known and thus we can quickly check the existance of a
- * package with that provides */
+ * is known and thus we can use the whatprovides data to quickly
+ * check the existance of a package with that provides */
static int
selection_provides_id(Pool *pool, Queue *selection, Id id, int flags)
{
Solvable *s = pool->solvables + p;
if ((flags & SELECTION_INSTALLED_ONLY) != 0 && s->repo != pool->installed)
continue;
- break;
- }
- if (p)
- {
queue_push2(selection, SOLVER_SOLVABLE_PROVIDES, id);
return SELECTION_PROVIDES;
}
if ((flags & (SELECTION_WITH_BADARCH | SELECTION_WITH_DISABLED)) != 0)
{
+ /* misuse selection_addextra to test if there is an extra package
+ * that provides the id */
queue_push2(selection, SOLVER_SOLVABLE_PROVIDES, id);
selection_addextra(pool, selection, flags);
if (selection->elements[0] == SOLVER_SOLVABLE_PROVIDES)
- queue_empty(selection);
+ queue_empty(selection); /* no extra package found */
else
{
selection->elements[0] = SOLVER_SOLVABLE_PROVIDES;
return 0;
}
-/* add missing provides matchers to the selection */
/* match the provides of a package */
/* note that we only return raw SOLVER_SOLVABLE_PROVIDES jobs
* so that the selection can be modified later. */
for (id = 1; id < pool->ss.nstrings; id++)
{
/* do we habe packages providing this id? */
- if (!pool->whatprovides[id] || pool->whatprovides[id] == 1)
+ if ((!pool->whatprovides[id] && pool->addedfileprovides == 2) || pool->whatprovides[id] == 1)
continue;
n = pool_id2str(pool, id);
if ((doglob ? fnmatch(name, n, globflags) : nocase ? strcasecmp(name, n) : strcmp(name, n)) == 0)
if (!p)
continue;
}
+ else if (!pool->whatprovides[id])
+ {
+ FOR_PROVIDES(p, pp, id)
+ break;
+ if (!p)
+ continue;
+ }
queue_push2(selection, SOLVER_SOLVABLE_PROVIDES, id);
match = 1;
}
return 0;
}
+/* does not check SELECTION_INSTALLED_ONLY, as it is normally done
+ * by other means */
+static inline int
+solvable_matches_selection_flags(Pool *pool, Solvable *s, int flags)
+{
+ if (s->arch == ARCH_SRC || s->arch == ARCH_NOSRC)
+ {
+ if (!(flags & SELECTION_SOURCE_ONLY) && !(flags & SELECTION_WITH_SOURCE))
+ return 0;
+ /* source package are never installed and never have a bad arch */
+ if (!(flags & SELECTION_WITH_DISABLED) && pool_disabled_solvable(pool, s))
+ return 0;
+ }
+ else
+ {
+ if ((flags & SELECTION_SOURCE_ONLY) != 0)
+ return 0;
+ if (s->repo != pool->installed)
+ {
+ if (!(flags & SELECTION_WITH_DISABLED) && pool_disabled_solvable(pool, s))
+ return 0;
+ if (!(flags & SELECTION_WITH_BADARCH) && pool_badarch_solvable(pool, s))
+ return 0;
+ }
+ }
+ return 1;
+}
+
/* match the name of a package */
/* note that for SELECTION_INSTALLED_ONLY the result is not trimmed */
static int
Solvable *s = pool->solvables + p;
if ((flags & SELECTION_INSTALLED_ONLY) != 0 && s->repo != pool->installed)
continue;
- if (s->arch == ARCH_SRC || s->arch == ARCH_NOSRC)
- {
- if (!(flags & SELECTION_SOURCE_ONLY) && !(flags & SELECTION_WITH_SOURCE))
- continue;
- if (!(flags & SELECTION_WITH_DISABLED) && pool_disabled_solvable(pool, s))
- continue;
- }
- else if (s->repo != pool->installed)
- {
- if (!(flags & SELECTION_WITH_DISABLED) && pool_disabled_solvable(pool, s))
- continue;
- if (!(flags & SELECTION_WITH_BADARCH) && pool_badarch_solvable(pool, s))
- continue;
- }
+ if (!solvable_matches_selection_flags(pool, s, flags))
+ continue;
id = s->name;
n = pool_id2str(pool, id);
if (flags & SELECTION_SKIP_KIND)
if ((flags & SELECTION_NOCASE) != 0)
type |= SEARCH_NOCASE;
queue_init(&q);
- dataiterator_init(&di, pool, flags & SELECTION_INSTALLED_ONLY ? pool->installed : 0, 0, SOLVABLE_FILELIST, name, type|SEARCH_FILES|SEARCH_COMPLETE_FILELIST);
+ dataiterator_init(&di, pool, flags & SELECTION_INSTALLED_ONLY ? pool->installed : 0, 0, SOLVABLE_FILELIST, name, type|SEARCH_FILES);
while (dataiterator_step(&di))
{
Solvable *s = pool->solvables + di.solvid;
if (!s->repo)
continue;
- if (s->arch == ARCH_SRC || s->arch == ARCH_NOSRC)
- {
- if (!(flags & SELECTION_SOURCE_ONLY) && !(flags & SELECTION_WITH_SOURCE))
- continue;
- if (!(flags & SELECTION_WITH_DISABLED) && pool_disabled_solvable(pool, s))
- continue;
- }
- else
- {
- if ((flags & SELECTION_SOURCE_ONLY) != 0)
- continue;
- if (s->repo != pool->installed)
- {
- if (!(flags & SELECTION_WITH_DISABLED) && pool_disabled_solvable(pool, s))
- continue;
- if (!(flags & SELECTION_WITH_BADARCH) && pool_badarch_solvable(pool, s))
- continue;
- }
- }
+ if (!solvable_matches_selection_flags(pool, s, flags))
+ continue;
if ((flags & SELECTION_FLAT) != 0)
{
/* don't bother with the complex stuff */
flags |= SELECTION_NAME;
flags &= ~SELECTION_PROVIDES;
+#ifdef ENABLE_CONDA
+ if (pool->disttype == DISTTYPE_CONDA)
+ {
+ Id *wp, id = pool_conda_matchspec(pool, name);
+ if (!id)
+ return 0;
+ wp = pool_whatprovides_ptr(pool, id); /* check if there is a match */
+ if (!wp || !*wp)
+ return 0;
+ queue_push2(selection, SOLVER_SOLVABLE_PROVIDES, id);
+ return SELECTION_CANON;
+ }
+#endif
if (pool->disttype == DISTTYPE_DEB)
{
if ((r = strchr(name, '_')) == 0)
return needflags;
}
+static int
+selection_combine(Pool *pool, Queue *sel1, Queue *sel2, int flags, int ret)
+{
+ if ((flags & SELECTION_MODEBITS) == SELECTION_ADD)
+ selection_add(pool, sel1, sel2);
+ else if ((flags & SELECTION_MODEBITS) == SELECTION_SUBTRACT)
+ selection_subtract(pool, sel1, sel2);
+ else if ((flags & SELECTION_MODEBITS) == SELECTION_FILTER)
+ {
+ if (ret || !(flags & SELECTION_FILTER_KEEP_IFEMPTY))
+ {
+ if ((flags & SELECTION_FILTER_SWAPPED) != 0)
+ {
+ selection_filter(pool, sel2, sel1);
+ queue_free(sel1);
+ queue_init_clone(sel1, sel2);
+ }
+ else
+ selection_filter(pool, sel1, sel2);
+ }
+ }
+ else /* SELECTION_REPLACE */
+ {
+ queue_free(sel1);
+ queue_init_clone(sel1, sel2);
+ }
+ queue_free(sel2);
+ return ret;
+}
+
int
selection_make(Pool *pool, Queue *selection, const char *name, int flags)
{
int ret = 0;
- if ((flags & SELECTION_MODEBITS) != 0)
+ if ((flags & SELECTION_MODEBITS) != SELECTION_REPLACE)
{
Queue q;
- queue_init(&q);
if ((flags & SELECTION_MODEBITS) == SELECTION_SUBTRACT || (flags & SELECTION_MODEBITS) == SELECTION_FILTER)
{
if (!selection->count)
- {
- queue_free(&q);
- return 0;
- }
+ return 0;
if ((flags & (SELECTION_WITH_DISABLED | SELECTION_WITH_BADARCH | SELECTION_WITH_SOURCE)) != 0)
{
/* try to drop expensive extra bits */
flags = (flags & ~(SELECTION_WITH_DISABLED | SELECTION_WITH_BADARCH | SELECTION_WITH_SOURCE)) | selection_extrabits(pool, selection, flags);
}
}
+ queue_init(&q);
ret = selection_make(pool, &q, name, flags & ~SELECTION_MODEBITS);
- if ((flags & SELECTION_MODEBITS) == SELECTION_ADD)
- selection_add(pool, selection, &q);
- else if ((flags & SELECTION_MODEBITS) == SELECTION_SUBTRACT)
- selection_subtract(pool, selection, &q);
- else if (ret || !(flags & SELECTION_FILTER_KEEP_IFEMPTY))
- {
- if ((flags & SELECTION_FILTER_SWAPPED) != 0)
- {
- selection_filter(pool, &q, selection);
- queue_free(selection);
- queue_init_clone(selection, &q);
- }
- else
- selection_filter(pool, selection, &q);
- }
- queue_free(&q);
- return ret;
+ return selection_combine(pool, selection, &q, flags, ret);
}
queue_empty(selection);
if ((flags & SELECTION_INSTALLED_ONLY) != 0 && !pool->installed)
/* now do result filtering */
if (ret && (flags & SELECTION_INSTALLED_ONLY) != 0)
- selection_filter_repo(pool, selection, pool->installed);
+ selection_filter_repo(pool, selection, pool->installed, SOLVER_SETREPO);
/* flatten if requested */
if (ret && (flags & SELECTION_FLAT) != 0)
return selection->count ? ret : 0;
}
-struct limiter {
- int start; /* either 2 or repofilter->start */
- int end; /* either nsolvables or repofilter->end */
- Id *mapper;
- Repo *repofilter;
-};
-
-/* add matching src packages to simple SOLVABLE_NAME selections */
-static void
-setup_limiter(Pool *pool, int flags, struct limiter *limiter)
-{
- limiter->start = 2;
- limiter->end = pool->nsolvables;
- limiter->mapper = 0;
- limiter->repofilter = 0;
- if ((flags & SELECTION_INSTALLED_ONLY) != 0)
- {
- Repo *repo = pool->installed;
- limiter->repofilter = repo;
- limiter->start = repo ? repo->start : 0;
- limiter->end = repo ? repo->end : 0;
- }
-}
-
static int
matchdep_str(const char *pattern, const char *string, int flags)
{
return matchdep_str(rname, pool_id2str(pool, id), flags);
}
+struct limiter {
+ int start; /* either 2 or repofilter->start */
+ int end; /* either nsolvables or repofilter->end */
+ Repo *repofilter;
+ Id *mapper;
+ Queue qlimit;
+};
+
+
+static int
+selection_make_matchsolvable_common(Pool *pool, Queue *selection, Queue *solvidq, Id solvid, int flags, int keyname, int marker, struct limiter *limiter)
+{
+ Map m, missc;
+ int reloff;
+ int li, i, j;
+ Id p;
+ Queue q;
+
+ if ((flags & SELECTION_MODEBITS) != SELECTION_REPLACE)
+ {
+ int ret;
+ Queue q;
+ queue_init(&q);
+ ret = selection_make_matchsolvable_common(pool, &q, solvidq, solvid, flags & ~SELECTION_MODEBITS, keyname, marker, limiter);
+ return selection_combine(pool, selection, &q, flags, ret);
+ }
+
+ queue_empty(selection);
+ if (!limiter->end)
+ return 0;
+ if (!solvidq && !solvid)
+ return 0;
+ if (solvidq && solvid)
+ return 0;
+
+ if (solvidq)
+ {
+ map_init(&m, pool->nsolvables);
+ for (i = 0; i < solvidq->count; i++)
+ MAPSET(&m, solvidq->elements[i]);
+ }
+ queue_init(&q);
+ reloff = pool->ss.nstrings;
+ map_init(&missc, reloff + pool->nrels);
+ for (li = limiter->start; li < limiter->end; li++)
+ {
+ Solvable *s;
+ p = limiter->mapper ? limiter->mapper[li] : li;
+ if (solvidq && MAPTST(&m, p))
+ continue;
+ if (!solvidq && p == solvid)
+ continue;
+ s = pool->solvables + p;
+ if (!s->repo || (limiter->repofilter && s->repo != limiter->repofilter))
+ continue;
+ if (!solvable_matches_selection_flags(pool, s, flags))
+ continue;
+ if (solvable_matchessolvable_int(s, keyname, marker, solvid, solvidq ? &m : 0, &q, &missc, reloff, 0))
+ queue_push(selection, p);
+ }
+ queue_free(&q);
+ map_free(&missc);
+ if (solvidq)
+ map_free(&m);
+
+ /* convert package list to selection */
+ if (!selection->count)
+ return 0;
+ j = selection->count;
+ queue_insertn(selection, 0, selection->count, 0);
+ for (i = 0; i < selection->count; i += 2)
+ {
+ selection->elements[i] = SOLVER_SOLVABLE | SOLVER_NOAUTOSET;
+ selection->elements[i + 1] = selection->elements[j++];
+ }
+ if ((flags & SELECTION_FLAT) != 0)
+ selection_flatten(pool, selection);
+ return SELECTION_PROVIDES;
+}
+
static int
-selection_make_matchdeps_common_limited(Pool *pool, Queue *selection, const char *name, Id dep, int flags, int keyname, int marker, struct limiter *limiter)
+selection_make_matchdeps_common(Pool *pool, Queue *selection, const char *name, Id dep, int flags, int keyname, int marker, struct limiter *limiter)
{
int li, i, j;
int ret = 0;
Id p;
Queue q;
+ if ((flags & SELECTION_MODEBITS) != SELECTION_REPLACE)
+ {
+ Queue q;
+ queue_init(&q);
+ ret = selection_make_matchdeps_common(pool, &q, name, dep, flags & ~SELECTION_MODEBITS, keyname, marker, limiter);
+ return selection_combine(pool, selection, &q, flags, ret);
+ }
+
queue_empty(selection);
if (!limiter->end)
return 0;
s = pool->solvables + p;
if (!s->repo || (limiter->repofilter && s->repo != limiter->repofilter))
continue;
- if (s->arch == ARCH_SRC || s->arch == ARCH_NOSRC)
- {
- if (!(flags & SELECTION_SOURCE_ONLY) && !(flags & SELECTION_WITH_SOURCE))
- continue;
- if (!(flags & SELECTION_WITH_DISABLED) && pool_disabled_solvable(pool, s))
- continue;
- }
- else
- {
- if ((flags & SELECTION_SOURCE_ONLY) != 0)
- continue;
- if (s->repo != pool->installed)
- {
- if (!(flags & SELECTION_WITH_DISABLED) && pool_disabled_solvable(pool, s))
- continue;
- if (!(flags & SELECTION_WITH_BADARCH) && pool_badarch_solvable(pool, s))
- continue;
- }
- }
+ if (!solvable_matches_selection_flags(pool, s, flags))
+ continue;
if (keyname == SOLVABLE_NAME) /* nevr match hack */
{
if (dep)
queue_push(selection, p);
continue;
}
- queue_empty(&q);
+ if (q.count)
+ queue_empty(&q);
repo_lookup_deparray(s->repo, p, keyname, &q, marker);
if (!q.count)
continue;
}
queue_free(&q);
solv_free(rname);
- if (!selection->count)
- return 0;
/* convert package list to selection */
+ if (!selection->count)
+ return 0;
j = selection->count;
queue_insertn(selection, 0, selection->count, 0);
- for (i = 0; i < selection->count; )
+ for (i = 0; i < selection->count; i += 2)
{
- selection->elements[i++] = SOLVER_SOLVABLE | SOLVER_NOAUTOSET;
- selection->elements[i++] = selection->elements[j++];
+ selection->elements[i] = SOLVER_SOLVABLE | SOLVER_NOAUTOSET;
+ selection->elements[i + 1] = selection->elements[j++];
}
if ((flags & SELECTION_FLAT) != 0)
return ret | (keyname == SOLVABLE_NAME ? SELECTION_NAME : SELECTION_PROVIDES);
}
-static int
-selection_make_matchdeps_common(Pool *pool, Queue *selection, const char *name, Id dep, int flags, int keyname, int marker)
+static void
+setup_limiter(Pool *pool, Queue *selection, int flags, struct limiter *limiter)
{
- struct limiter limiter;
-
- setup_limiter(pool, flags, &limiter);
- if ((flags & SELECTION_MODEBITS) != SELECTION_REPLACE)
+ limiter->start = 2;
+ limiter->end = pool->nsolvables;
+ limiter->mapper = 0;
+ limiter->repofilter = 0;
+ if ((flags & SELECTION_INSTALLED_ONLY) != 0)
{
- int ret;
- Queue q, qlimit;
- queue_init(&q);
- queue_init(&qlimit);
- /* deal with special filter cases */
- if ((flags & SELECTION_MODEBITS) == SELECTION_FILTER && selection->count == 2 && limiter.end)
- {
- if ((selection->elements[0] & SOLVER_SELECTMASK) == SOLVER_SOLVABLE_ALL)
- flags = (flags & ~SELECTION_MODEBITS) | SELECTION_REPLACE;
- else if ((selection->elements[0] & SOLVER_SELECTMASK) == SOLVER_SOLVABLE_REPO)
- {
- Repo *repo = pool_id2repo(pool, selection->elements[1]);
- if (limiter.repofilter && repo != limiter.repofilter)
- repo = 0;
- limiter.repofilter = repo;
- limiter.start = repo ? repo->start : 0;
- limiter.end = repo ? repo->end : 0;
- flags = (flags & ~SELECTION_MODEBITS) | SELECTION_REPLACE;
- }
- }
- if (limiter.end && ((flags & SELECTION_MODEBITS) == SELECTION_SUBTRACT || (flags & SELECTION_MODEBITS) == SELECTION_FILTER))
- {
- selection_solvables(pool, selection, &qlimit);
- limiter.start = 0;
- limiter.end = qlimit.count;
- limiter.mapper = qlimit.elements;
- }
- ret = selection_make_matchdeps_common_limited(pool, &q, name, dep, flags & ~SELECTION_MODEBITS, keyname, marker, &limiter);
- queue_free(&qlimit);
- if ((flags & SELECTION_MODEBITS) == SELECTION_ADD)
- selection_add(pool, selection, &q);
- else if ((flags & SELECTION_MODEBITS) == SELECTION_SUBTRACT)
- selection_subtract(pool, selection, &q);
- else if ((flags & SELECTION_MODEBITS) == SELECTION_FILTER)
- {
- if (ret || !(flags & SELECTION_FILTER_KEEP_IFEMPTY))
- {
- if ((flags & SELECTION_FILTER_SWAPPED) != 0)
- {
- selection_filter(pool, &q, selection);
- queue_free(selection);
- queue_init_clone(selection, &q);
- }
- else
- selection_filter(pool, selection, &q);
- }
- }
- else if (ret || !(flags & SELECTION_FILTER_KEEP_IFEMPTY))
- {
- /* special filter case from above */
- int i;
- Id f = selection->elements[0] & ~(SOLVER_SELECTMASK|SOLVER_NOAUTOSET); /* job, jobflags, setflags */
- queue_free(selection);
- queue_init_clone(selection, &q);
- for (i = 0; i < selection->count; i += 2)
- selection->elements[i] = (selection->elements[i] & (SOLVER_SELECTMASK | SOLVER_SETMASK)) | f;
- }
- queue_free(&q);
- return ret;
+ Repo *repo = pool->installed;
+ limiter->repofilter = repo;
+ limiter->start = repo ? repo->start : 0;
+ limiter->end = repo ? repo->end : 0;
+ }
+ if ((flags & SELECTION_MODEBITS) != SELECTION_SUBTRACT && (flags & SELECTION_MODEBITS) != SELECTION_FILTER)
+ return;
+ /* the result will be limited to the first selection */
+ if (!selection->count)
+ limiter->start = limiter->end = 0;
+ if (!limiter->end)
+ return;
+ /* check for special cases where we do not need to call selection_solvables() */
+ if (selection->count == 2 && (selection->elements[0] & SOLVER_SELECTMASK) == SOLVER_SOLVABLE_ALL)
+ return;
+ if (selection->count == 2 && (selection->elements[0] & SOLVER_SELECTMASK) == SOLVER_SOLVABLE_REPO)
+ {
+ Repo *repo = pool_id2repo(pool, selection->elements[1]);
+ if (limiter->repofilter && repo != limiter->repofilter)
+ repo = 0;
+ limiter->repofilter = repo;
+ limiter->start = repo ? repo->start : 0;
+ limiter->end = repo ? repo->end : 0;
+ return;
}
- return selection_make_matchdeps_common_limited(pool, selection, name, dep, flags, keyname, marker, &limiter);
+ /* convert selection into a package list and use it in the limiter */
+ queue_init(&limiter->qlimit);
+ selection_solvables(pool, selection, &limiter->qlimit);
+ limiter->start = 0;
+ limiter->end = limiter->qlimit.count;
+ if (!limiter->qlimit.count)
+ queue_free(&limiter->qlimit);
+ else
+ limiter->mapper = limiter->qlimit.elements;
+}
+
+static void
+free_limiter(struct limiter *limiter)
+{
+ if (limiter->mapper)
+ queue_free(&limiter->qlimit);
}
/*
int
selection_make_matchdeps(Pool *pool, Queue *selection, const char *name, int flags, int keyname, int marker)
{
- return selection_make_matchdeps_common(pool, selection, name, 0, flags, keyname, marker);
+ struct limiter limiter;
+ int ret;
+ setup_limiter(pool, selection, flags, &limiter);
+ ret = selection_make_matchdeps_common(pool, selection, name, 0, flags, keyname, marker, &limiter);
+ free_limiter(&limiter);
+ return ret;
}
/*
int
selection_make_matchdepid(Pool *pool, Queue *selection, Id dep, int flags, int keyname, int marker)
{
- return selection_make_matchdeps_common(pool, selection, 0, dep, flags, keyname, marker);
+ struct limiter limiter;
+ int ret;
+ setup_limiter(pool, selection, flags, &limiter);
+ ret = selection_make_matchdeps_common(pool, selection, 0, dep, flags, keyname, marker, &limiter);
+ free_limiter(&limiter);
+ return ret;
+}
+
+int
+selection_make_matchsolvable(Pool *pool, Queue *selection, Id solvid, int flags, int keyname, int marker)
+{
+ struct limiter limiter;
+ int ret;
+ setup_limiter(pool, selection, flags, &limiter);
+ ret = selection_make_matchsolvable_common(pool, selection, 0, solvid, flags, keyname, marker, &limiter);
+ free_limiter(&limiter);
+ return ret;
+}
+
+int
+selection_make_matchsolvablelist(Pool *pool, Queue *selection, Queue *solvidq, int flags, int keyname, int marker)
+{
+ struct limiter limiter;
+ int ret;
+ setup_limiter(pool, selection, flags, &limiter);
+ ret = selection_make_matchsolvable_common(pool, selection, solvidq, 0, flags, keyname, marker, &limiter);
+ free_limiter(&limiter);
+ return ret;
}
static inline int
for (i = j = 0; i < sel->count; i += 2)
{
Id select = sel->elements[i] & SOLVER_SELECTMASK;
- queue_empty(&q);
+ Id id = sel->elements[i + 1];
+ if (q.count)
+ queue_empty(&q);
miss = 0;
if (select == SOLVER_SOLVABLE_ALL)
{
else if (select == SOLVER_SOLVABLE_REPO)
{
Solvable *s;
- Repo *repo = pool_id2repo(pool, sel->elements[i + 1]);
+ Repo *repo = pool_id2repo(pool, id);
if (repo)
{
FOR_REPO_SOLVABLES(repo, p, s)
}
}
}
+ else if (select == SOLVER_SOLVABLE)
+ {
+ if (!map_tst(m, id))
+ continue;
+ sel->elements[j] = sel->elements[i] | setflags;
+ sel->elements[j + 1] = id;
+ j += 2;
+ continue;
+ }
else
{
- FOR_JOB_SELECT(p, pp, select, sel->elements[i + 1])
+ FOR_JOB_SELECT(p, pp, select, id)
{
if (map_tst(m, p))
queue_pushunique(&q, p);
if (!miss)
{
sel->elements[j] = sel->elements[i] | setflags;
- sel->elements[j + 1] = sel->elements[i + 1];
+ sel->elements[j + 1] = id;
}
else if (q.count > 1)
{
Map m2;
Id setflags = 0;
+ /* handle special cases */
if (!sel1->count || !sel2->count)
{
if (invert && !sel2->count)
if (sel1->count == 2 && (sel1->elements[0] & SOLVER_SELECTMASK) == SOLVER_SOLVABLE_ALL && !invert)
{
/* XXX: not 100% correct, but very useful */
- p = sel1->elements[0] & ~(SOLVER_SELECTMASK | SOLVER_SETMASK); /* job & jobflags */
+ setflags = sel1->elements[0] & ~(SOLVER_SELECTMASK | SOLVER_SETMASK); /* job & jobflags */
+ queue_free(sel1);
+ queue_init_clone(sel1, sel2);
+ for (i = 0; i < sel1->count; i += 2)
+ sel1->elements[i] = (sel1->elements[i] & (SOLVER_SELECTMASK | SOLVER_SETMASK)) | setflags;
+ return;
+ }
+ if (sel1->count == 2 && (sel1->elements[0] & SOLVER_SELECTMASK) == SOLVER_SOLVABLE_REPO && !invert)
+ {
+ Repo *repo = pool_id2repo(pool, sel1->elements[1]);
+ setflags = sel1->elements[0] & ~(SOLVER_SELECTMASK | SOLVER_NOAUTOSET); /* job, jobflags, setflags */
queue_free(sel1);
queue_init_clone(sel1, sel2);
for (i = 0; i < sel1->count; i += 2)
- sel1->elements[i] = (sel1->elements[i] & (SOLVER_SELECTMASK | SOLVER_SETMASK)) | p ;
+ sel1->elements[i] &= SOLVER_SELECTMASK | SOLVER_SETMASK; /* remove job and jobflags */
+ selection_filter_repo(pool, sel1, repo, setflags);
+ return;
+ }
+ if (sel2->count == 2 && (sel2->elements[0] & SOLVER_SELECTMASK) == SOLVER_SOLVABLE_ALL)
+ {
+ if (invert)
+ queue_empty(sel1);
+ return;
+ }
+ if (sel2->count == 2 && (sel2->elements[0] & SOLVER_SELECTMASK) == SOLVER_SOLVABLE_REPO && !invert)
+ {
+ Repo *repo = pool_id2repo(pool, sel2->elements[1]);
+ setflags = sel2->elements[0] & (SOLVER_SETMASK & ~SOLVER_NOAUTOSET);
+ selection_filter_repo(pool, sel1, repo, setflags);
return;
}
if (invert)
map_invertall(&m2);
if (sel2->count == 2)
- setflags = sel2->elements[0] & SOLVER_SETMASK & ~SOLVER_NOAUTOSET;
+ setflags = sel2->elements[0] & (SOLVER_SETMASK & ~SOLVER_NOAUTOSET);
selection_filter_map(pool, sel1, &m2, setflags);
map_free(&m2);
}