From 321bb2ac1bd4a88addfd2875f467d2e24b8a0005 Mon Sep 17 00:00:00 2001 From: Michael Schroeder Date: Fri, 5 Oct 2018 14:41:20 +0200 Subject: [PATCH] Add selection_make_matchsolvable and selection_make_matchsolvablelist This is like pool_whatmatchessolvable, but works on a selection. The advantage is that it supports filtering. --- examples/solv/solv.c | 36 ++--------- src/libsolv.ver | 2 + src/selection.c | 149 ++++++++++++++++++++++++++++++++++++++++++- src/selection.h | 6 +- 4 files changed, 162 insertions(+), 31 deletions(-) diff --git a/examples/solv/solv.c b/examples/solv/solv.c index b23669f8..6a5dab73 100644 --- a/examples/solv/solv.c +++ b/examples/solv/solv.c @@ -169,34 +169,6 @@ find_repo(const char *name, Pool *pool, struct repoinfo *repoinfos, int nrepoinf return 0; } -static void -selection_alldeps(Pool *pool, Queue *selection, int keyname, int marker) -{ - Queue pkgs, q; - int i, j; - - queue_init(&pkgs); - queue_init(&q); - selection_solvables(pool, selection, &pkgs); - queue_empty(selection); - for (i = 0; i < pkgs.count; i++) - { - queue_empty(&q); - pool_whatmatchessolvable(pool, keyname, pkgs.elements[i], &q, marker); - for (j = 0; j < q.count; j++) - queue_pushunique(selection, q.elements[j]); - } - queue_free(&q); - queue_free(&pkgs); - j = selection->count; - queue_insertn(selection, 0, j, 0); - for (i = 0; i < j; i++) - { - selection->elements[2 * i] = SOLVER_SOLVABLE | SOLVER_NOAUTOSET; - selection->elements[2 * i + 1] = selection->elements[i + j]; - } -} - #define MODE_LIST 0 #define MODE_INSTALL 1 #define MODE_ERASE 2 @@ -609,7 +581,13 @@ main(int argc, char **argv) if (rflags & SELECTION_PROVIDES) printf("[using capability match for '%s']\n", argv[i]); if (keyname && keyname_alldeps) - selection_alldeps(pool, &job2, pool_str2id(pool, keyname, 1), 0); + { + Queue q; + queue_init(&q); + selection_solvables(pool, &job2, &q); + selection_make_matchsolvablelist(pool, &job2, &q, 0, pool_str2id(pool, keyname, 1), 0); + queue_free(&q); + } queue_insertn(&job, job.count, job2.count, job2.elements); queue_free(&job2); } diff --git a/src/libsolv.ver b/src/libsolv.ver index c2acc137..db453a01 100644 --- a/src/libsolv.ver +++ b/src/libsolv.ver @@ -259,6 +259,8 @@ SOLV_1.0 { selection_make; selection_make_matchdepid; selection_make_matchdeps; + selection_make_matchsolvable; + selection_make_matchsolvablelist; selection_solvables; solv_bin2hex; solv_calloc; diff --git a/src/selection.c b/src/selection.c index f0422d4f..9277dfd7 100644 --- a/src/selection.c +++ b/src/selection.c @@ -1430,6 +1430,137 @@ matchdep(Pool *pool, Id id, char *rname, int rflags, Id revr, int flags) return matchdep_str(rname, pool_id2str(pool, id), flags); } +static int +selection_make_matchsolvable_common_limited(Pool *pool, Queue *selection, Queue *solvidq, Id solvid, int flags, int keyname, int marker, struct limiter *limiter) +{ + Id *wp; + Map m, missc; + int reloff, boff; + int li, i, j; + Id p; + Queue q; + + 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 (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 (q.count) + queue_empty(&q); + repo_lookup_deparray(s->repo, p, keyname, &q, marker); + if (!q.count) + continue; + for (i = 0; i < q.count; i++) + { + Id dep = q.elements[i]; + boff = ISRELDEP(dep) ? reloff + GETRELID(dep) : dep; + if (MAPTST(&missc, boff)) + continue; + if (ISRELDEP(dep)) + { + Reldep *rd = GETRELDEP(pool, dep); + if (!ISRELDEP(rd->name) && rd->flags < 8) + { + /* do pre-filtering on the base */ + if (MAPTST(&missc, rd->name)) + continue; + wp = pool_whatprovides_ptr(pool, rd->name); + if (solvidq) + { + for (wp = pool_whatprovides_ptr(pool, dep); *wp; wp++) + if (MAPTST(&m, *wp)) + break; + } + else + { + for (wp = pool_whatprovides_ptr(pool, dep); *wp; wp++) + if (*wp == solvid) + break; + } + if (!*wp) + { + /* the base does not include solvid, no need to check the complete dep */ + MAPSET(&missc, rd->name); + MAPSET(&missc, boff); + continue; + } + } + } + wp = pool_whatprovides_ptr(pool, dep); + if (solvidq) + { + for (wp = pool_whatprovides_ptr(pool, dep); *wp; wp++) + if (MAPTST(&m, *wp)) + break; + } + else + { + for (wp = pool_whatprovides_ptr(pool, dep); *wp; wp++) + if (*wp == solvid) + break; + } + if (*wp) + { + queue_push(selection, p); + break; + } + MAPSET(&missc, boff); + } + } + queue_free(&q); + map_free(&missc); + if (solvidq) + map_free(&m); + if (!selection->count) + return 0; + + /* convert package list to selection */ + j = selection->count; + queue_insertn(selection, 0, selection->count, 0); + for (i = 0; i < selection->count; ) + { + selection->elements[i++] = SOLVER_SOLVABLE | SOLVER_NOAUTOSET; + selection->elements[i++] = 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) { @@ -1449,6 +1580,9 @@ selection_make_matchdeps_common_limited(Pool *pool, Queue *selection, const char if (name && dep) return 0; + if ((flags & SELECTION_MATCH_SOLVABLE) != 0) + return selection_make_matchsolvable_common_limited(pool, selection, (Queue *)name, dep, flags, keyname, marker, limiter); + if ((flags & SELECTION_MATCH_DEPSTR) != 0) flags &= ~SELECTION_REL; @@ -1558,7 +1692,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; @@ -1708,6 +1843,18 @@ selection_make_matchdepid(Pool *pool, Queue *selection, Id dep, int flags, int k return selection_make_matchdeps_common(pool, selection, 0, dep, flags, keyname, marker); } +int +selection_make_matchsolvable(Pool *pool, Queue *selection, Id solvid, int flags, int keyname, int marker) +{ + return selection_make_matchdeps_common(pool, selection, 0, solvid, flags | SELECTION_MATCH_SOLVABLE, keyname, marker); +} + +int +selection_make_matchsolvablelist(Pool *pool, Queue *selection, Queue *solvidq, int flags, int keyname, int marker) +{ + return selection_make_matchdeps_common(pool, selection, (const char *)solvidq, 0, flags | SELECTION_MATCH_SOLVABLE, keyname, marker); +} + static inline int pool_is_kind(Pool *pool, Id name, Id kind) { diff --git a/src/selection.h b/src/selection.h index 9938c2f9..f3ed2c20 100644 --- a/src/selection.h +++ b/src/selection.h @@ -52,16 +52,20 @@ extern "C" { #define SELECTION_SUBTRACT (2 << 28) #define SELECTION_FILTER (3 << 28) -#define SELECTION_MODEBITS (3 << 28) /* internal */ /* extra SELECTION_FILTER bits */ #define SELECTION_FILTER_KEEP_IFEMPTY (1 << 30) #define SELECTION_FILTER_SWAPPED (1 << 31) +/* internal */ +#define SELECTION_MATCH_SOLVABLE (1 << 27) +#define SELECTION_MODEBITS (3 << 28) 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 int selection_make_matchsolvable(Pool *pool, Queue *selection, Id solvid, int flags, int keyname, int marker); +extern int selection_make_matchsolvablelist(Pool *pool, Queue *selection, Queue *solvidq, 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); -- 2.47.2