From: Michael Schroeder Date: Thu, 4 Oct 2018 15:22:43 +0000 (+0200) Subject: Add pool_whatmatchessolvable() function to match against the provides of a solvable X-Git-Tag: 0.7.0~19 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=0416f0d488626b3d26eaf8bab201782e369235f0;p=thirdparty%2Flibsolv.git Add pool_whatmatchessolvable() function to match against the provides of a solvable --- diff --git a/examples/solv/solv.c b/examples/solv/solv.c index 42ab751b..c35cc2fa 100644 --- a/examples/solv/solv.c +++ b/examples/solv/solv.c @@ -169,6 +169,40 @@ find_repo(const char *name, Pool *pool, struct repoinfo *repoinfos, int nrepoinf return 0; } +static int +selection_alldeps(Pool *pool, Queue *selection, const char *name, int flags, int keyname, int marker) +{ + int i, j, r; + Queue pkgs, q; + + queue_empty(selection); + queue_init(&q); + r = selection_make(pool, &q, name, flags); + if (!q.count) + { + queue_free(&q); + return 0; + } + queue_init(&pkgs); + selection_solvables(pool, &q, &pkgs); + 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++) + if (q.elements[j] != pkgs.elements[i]) + queue_pushunique(selection, q.elements[j]); + } + queue_free(&q); + 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]; + } + return j ? r : 0; +} #define MODE_LIST 0 #define MODE_INSTALL 1 @@ -227,6 +261,7 @@ main(int argc, char **argv) char *rootdir = 0; char *keyname = 0; int keyname_depstr = 0; + int keyname_alldeps = 0; /* dnf repoquesy --alldeps */ int debuglevel = 0; int answer, acnt = 0; char *testcase = 0; @@ -316,9 +351,15 @@ main(int argc, char **argv) argc--; argv++; } + else if (argc > 1 && !strcmp(argv[1], "--alldeps")) + { + keyname_alldeps = 1; /* dnf repoquesy --alldeps */ + argc--; + argv++; + } else if (argc > 1 && !strcmp(argv[1], "--depstr")) { - keyname_depstr = 1; + keyname_depstr = 1; /* do literal matching instead of dep intersection */ argc--; argv++; } @@ -541,6 +582,8 @@ main(int argc, char **argv) flags |= SELECTION_MATCH_DEPSTR; if (!keyname) rflags = selection_make(pool, &job2, argv[i], flags); + else if (keyname_alldeps) + rflags = selection_alldeps(pool, &job2, argv[i], flags, pool_str2id(pool, keyname, 1), 0); else rflags = selection_make_matchdeps(pool, &job2, argv[i], flags, pool_str2id(pool, keyname, 1), 0); if (repofilter.count) @@ -554,6 +597,8 @@ main(int argc, char **argv) flags |= SELECTION_NOCASE; if (!keyname) rflags = selection_make(pool, &job2, argv[i], flags); + else if (keyname_alldeps) + rflags = selection_alldeps(pool, &job2, argv[i], flags, pool_str2id(pool, keyname, 1), 0); else rflags = selection_make_matchdeps(pool, &job2, argv[i], flags, pool_str2id(pool, keyname, 1), 0); if (repofilter.count) diff --git a/src/libsolv.ver b/src/libsolv.ver index d31d902c..c2acc137 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_whatmatchessolvable; pool_whatcontainsdep; queue_alloc_one; queue_alloc_one_head; diff --git a/src/pool.c b/src/pool.c index 3ff5bd20..aa994cc7 100644 --- a/src/pool.c +++ b/src/pool.c @@ -1485,6 +1485,77 @@ pool_whatcontainsdep(Pool *pool, Id keyname, Id dep, Queue *q, int marker) queue_free(&qq); } +/* intersect dependencies in keyname with all provides of solvable solvid, + * return list of matching packages */ +/* this currently only works for installable packages */ +void +pool_whatmatchessolvable(Pool *pool, Id keyname, Id solvid, Queue *q, int marker) +{ + Id p, *wp; + Queue qq; + int i; + Map missc; /* cache for misses */ + int reloff, boff; + + queue_empty(q); + queue_init(&qq); + reloff = pool->ss.nstrings; + map_init(&missc, reloff + pool->nrels); + FOR_POOL_SOLVABLES(p) + { + Solvable *s = pool->solvables + p; + if (p == solvid) + continue; /* filter out self-matches */ + 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++) + { + Id dep = qq.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); + 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); + for (wp = pool_whatprovides_ptr(pool, dep); *wp; wp++) + if (*wp == solvid) + break; + if (*wp) + { + queue_push(q, p); + break; + } + MAPSET(&missc, boff); + } + } + map_free(&missc); + queue_free(&qq); +} + /*************************************************************************/ void diff --git a/src/pool.h b/src/pool.h index e6d1700c..7b147432 100644 --- a/src/pool.h +++ b/src/pool.h @@ -348,6 +348,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); +void pool_whatmatchessolvable(Pool *pool, Id keyname, Id solvid, Queue *q, int marker); void pool_set_whatprovides(Pool *pool, Id id, Id providers);