X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=src%2Fselection.c;h=a8e60f79005dff864a9b2e820934752ebf50bea6;hb=d7f392b2f466c04078ccda3c9871b18edc0cdd86;hp=6ca72e5d12202b416a1857c86a9b5ffeb26afb8e;hpb=5390c526e6b93e97d269cb8a75a699631e5bb189;p=platform%2Fupstream%2Flibsolv.git diff --git a/src/selection.c b/src/selection.c index 6ca72e5..a8e60f7 100644 --- a/src/selection.c +++ b/src/selection.c @@ -21,7 +21,13 @@ #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) @@ -32,7 +38,7 @@ str2archid(Pool *pool, const char *arch) id = pool_str2id(pool, arch, 0); if (!id || id == ARCH_SRC || id == ARCH_NOSRC || id == ARCH_NOARCH) return id; - if (pool->id2arch && (id > pool->lastarch || !pool->id2arch[id])) + if (pool->id2arch && pool_arch2score(pool, id) == 0) return 0; return id; } @@ -89,6 +95,7 @@ selection_solvables(Pool *pool, Queue *selection, Queue *pkgs) 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) @@ -97,16 +104,18 @@ selection_solvables(Pool *pool, Queue *selection, Queue *pkgs) 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); } } @@ -141,6 +150,7 @@ selection_flatten(Pool *pool, Queue *selection) if (!q.count) { queue_empty(selection); + queue_free(&q); return; } queue_truncate(selection, 2); @@ -154,6 +164,7 @@ selection_flatten(Pool *pool, Queue *selection) selection->elements[0] = SOLVER_SOLVABLE | SOLVER_NOAUTOSET; selection->elements[1] = q.elements[0]; } + queue_free(&q); } /* only supports simple rels plus REL_ARCH */ @@ -260,7 +271,7 @@ selection_filter_rel(Pool *pool, Queue *selection, Id relflags, Id relevr) /* 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; @@ -285,7 +296,12 @@ selection_filter_repo(Pool *pool, Queue *selection, Repo *repo) 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 { @@ -299,11 +315,11 @@ selection_filter_repo(Pool *pool, Queue *selection, Repo *repo) 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]; @@ -315,8 +331,6 @@ selection_filter_repo(Pool *pool, Queue *selection, Repo *repo) } } } - if (!select) - continue; /* job is now empty */ if (select == SOLVER_SOLVABLE_REPO) { Id p; @@ -326,7 +340,7 @@ selection_filter_repo(Pool *pool, Queue *selection, Repo *repo) 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); @@ -538,8 +552,8 @@ selection_addextra_provides(Pool *pool, Queue *selection, const char *name, int } /* 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) { @@ -550,20 +564,18 @@ 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; @@ -575,7 +587,6 @@ selection_provides_id(Pool *pool, Queue *selection, Id id, int flags) 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. */ @@ -619,7 +630,7 @@ selection_provides(Pool *pool, Queue *selection, const char *name, int flags) 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) @@ -632,6 +643,13 @@ selection_provides(Pool *pool, Queue *selection, const char *name, int flags) 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; } @@ -704,6 +722,34 @@ selection_name_id(Pool *pool, Queue *selection, Id id, int flags) 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 @@ -743,20 +789,8 @@ selection_name(Pool *pool, Queue *selection, const char *name, int flags) 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) @@ -940,31 +974,14 @@ selection_filelist(Pool *pool, Queue *selection, const char *name, int flags) 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 */ @@ -1140,6 +1157,19 @@ selection_canon(Pool *pool, Queue *selection, const char *name, int flags) 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) @@ -1291,46 +1321,57 @@ selection_extrabits(Pool *pool, Queue *selection, int flags) 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) @@ -1348,7 +1389,7 @@ selection_make(Pool *pool, Queue *selection, const char *name, int flags) /* 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) @@ -1356,33 +1397,11 @@ selection_make(Pool *pool, Queue *selection, const char *name, int flags) 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) { + if (!pattern || !string) + return 0; if (flags & SELECTION_GLOB) { int globflags = (flags & SELECTION_NOCASE) != 0 ? FNM_CASEFOLD : 0; @@ -1428,8 +1447,88 @@ matchdep(Pool *pool, Id id, char *rname, int rflags, Id revr, 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; @@ -1439,11 +1538,21 @@ selection_make_matchdeps_common_limited(Pool *pool, Queue *selection, const char 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; if (!name && !dep) return 0; + if (name && dep) + return 0; if ((flags & SELECTION_MATCH_DEPSTR) != 0) flags &= ~SELECTION_REL; @@ -1464,7 +1573,7 @@ selection_make_matchdeps_common_limited(Pool *pool, Queue *selection, const char revr = pool_str2id(pool, r, 1); ret |= SELECTION_REL; } - if ((flags & SELECTION_GLOB) != 0 && !strpbrk(rname, "[*?") != 0) + if ((flags & SELECTION_GLOB) != 0 && strpbrk(rname, "[*?") == 0) flags &= ~SELECTION_GLOB; if ((flags & SELECTION_GLOB) == 0 && (flags & SELECTION_NOCASE) == 0 && (flags & SELECTION_MATCH_DEPSTR) == 0) @@ -1501,25 +1610,8 @@ selection_make_matchdeps_common_limited(Pool *pool, Queue *selection, const char 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) @@ -1554,7 +1646,8 @@ selection_make_matchdeps_common_limited(Pool *pool, Queue *selection, const char 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; @@ -1593,16 +1686,16 @@ selection_make_matchdeps_common_limited(Pool *pool, Queue *selection, const char } 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) @@ -1610,75 +1703,56 @@ selection_make_matchdeps_common_limited(Pool *pool, Queue *selection, const char 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); } /* @@ -1692,7 +1766,12 @@ selection_make_matchdeps_common(Pool *pool, Queue *selection, const char *name, 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; } /* @@ -1701,7 +1780,34 @@ selection_make_matchdeps(Pool *pool, Queue *selection, const char *name, int fla 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 @@ -1738,7 +1844,9 @@ selection_filter_map(Pool *pool, Queue *sel, Map *m, int setflags) 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) { @@ -1753,7 +1861,7 @@ selection_filter_map(Pool *pool, Queue *sel, Map *m, int setflags) 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) @@ -1765,9 +1873,18 @@ selection_filter_map(Pool *pool, Queue *sel, Map *m, int setflags) } } } + 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); @@ -1780,7 +1897,7 @@ selection_filter_map(Pool *pool, Queue *sel, Map *m, int setflags) 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) { @@ -1807,6 +1924,7 @@ selection_filter_int(Pool *pool, Queue *sel1, Queue *sel2, int invert) Map m2; Id setflags = 0; + /* handle special cases */ if (!sel1->count || !sel2->count) { if (invert && !sel2->count) @@ -1817,11 +1935,35 @@ selection_filter_int(Pool *pool, Queue *sel1, Queue *sel2, int invert) 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; } @@ -1893,7 +2035,7 @@ selection_filter_int(Pool *pool, Queue *sel1, Queue *sel2, int invert) 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); }