From: Michael Schroeder Date: Tue, 6 Dec 2022 13:52:22 +0000 (+0100) Subject: Provide new solvidset2str() function to print a set of solvables X-Git-Tag: 0.7.23~28 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=58c1b4264ef0390bfee439b1292fe8435ee1df87;p=thirdparty%2Flibsolv.git Provide new solvidset2str() function to print a set of solvables This is multipkg() from testcase.c. We'll switch to the new function in a later commit. --- diff --git a/src/libsolv.ver b/src/libsolv.ver index 3d175211..ae35b424 100644 --- a/src/libsolv.ver +++ b/src/libsolv.ver @@ -113,6 +113,7 @@ SOLV_1.0 { pool_shrink_rels; pool_shrink_strings; pool_solvable2str; + pool_solvidset2str; pool_str2id; pool_strn2id; pool_tmpappend; diff --git a/src/pool.h b/src/pool.h index 935a3263..60878cf2 100644 --- a/src/pool.h +++ b/src/pool.h @@ -297,6 +297,7 @@ static inline const char *pool_solvid2str(Pool *pool, Id p) { return pool_solvable2str(pool, pool->solvables + p); } +extern const char *pool_solvidset2str(Pool *pool, Queue *q); void pool_set_languages(Pool *pool, const char **languages, int nlanguages); Id pool_id2langid(Pool *pool, Id id, const char *lang, int create); diff --git a/src/solvable.c b/src/solvable.c index 181d9bc7..fc4e9826 100644 --- a/src/solvable.c +++ b/src/solvable.c @@ -24,6 +24,7 @@ #include "poolvendor.h" #include "chksum.h" #include "linkedpkg.h" +#include "evr.h" const char * pool_solvable2str(Pool *pool, Solvable *s) @@ -746,3 +747,124 @@ solvable_matchessolvable(Solvable *s, Id keyname, Id solvid, Queue *depq, int ma queue_free(&qq); return res; } + +static int +solvidset2str_evrcmp(Pool *pool, Id a, Id b) +{ + Solvable *as = pool->solvables + a, *bs = pool->solvables + b; + return as->evr != bs->evr ? pool_evrcmp(pool, as->evr, bs->evr, EVRCMP_COMPARE) : 0; +} + +static int +solvidset2str_sortcmp(const void *va, const void *vb, void *vd) +{ + Pool *pool = vd; + Solvable *as = pool->solvables + *(Id *)va, *bs = pool->solvables + *(Id *)vb; + if (as->name != bs->name) + { + int r = strcmp(pool_id2str(pool, as->name), pool_id2str(pool, bs->name)); + if (r) + return r; + return as->name - bs->name; + } + if (as->evr != bs->evr) + { + int r = pool_evrcmp(pool, as->evr, bs->evr, EVRCMP_COMPARE); + if (r) + return r; + } + return *(Id *)va - *(Id *)vb; +} + +static const char * +solvidset2str_striprelease(Pool *pool, Id evr, Id otherevr) +{ + const char *evrstr = pool_id2str(pool, evr); + const char *r = strchr(evrstr, '-'); + char *evrstr2; + int cmp; + if (!r) + return evrstr; + evrstr2 = pool_tmpjoin(pool, evrstr, 0, 0); + evrstr2[r - evrstr] = 0; + cmp = pool_evrcmp_str(pool, evrstr2, pool_id2str(pool, otherevr), pool->disttype != DISTTYPE_DEB ? EVRCMP_MATCH_RELEASE : EVRCMP_COMPARE); + return cmp == 1 ? evrstr2 : evrstr; +} + +const char * +pool_solvidset2str(Pool *pool, Queue *q) +{ + Queue pq; + Queue pr; + char *s = 0; + int i, j, k, kstart; + Id name = 0; + + if (!q->count) + return ""; + if (q->count == 1) + return pool_solvid2str(pool, q->elements[0]); + queue_init_clone(&pq, q); + queue_init(&pr); + solv_sort(pq.elements, pq.count, sizeof(Id), solvidset2str_sortcmp, pool); + + for (i = 0; i < pq.count; i++) + { + Id p = pq.elements[i]; + if (s) + s = pool_tmpappend(pool, s, ", ", 0); + + if (i == 0 || pool->solvables[p].name != name) + { + Id p2, pp2; + name = pool->solvables[p].name; + queue_empty(&pr); + FOR_PROVIDES(p2, pp2, name) + if (pool->solvables[p].name == name) + queue_push(&pr, p2); + if (pr.count > 1) + solv_sort(pr.elements, pr.count, sizeof(Id), solvidset2str_sortcmp, pool); + } + + for (k = 0; k < pr.count; k++) + if (pr.elements[k] == p) + break; + if (k == pr.count) + { + /* not in provides, list as singularity */ + s = pool_tmpappend(pool, s, pool_solvid2str(pool, pq.elements[i]), 0); + continue; + } + if (k && solvidset2str_evrcmp(pool, pr.elements[k], pr.elements[k - 1]) == 0) + { + /* unclear start, list as single package */ + s = pool_tmpappend(pool, s, pool_solvid2str(pool, pq.elements[i]), 0); + continue; + } + kstart = k; + for (j = i + 1, k = k + 1; j < pq.count; j++, k++) + if (k == pr.count || pq.elements[j] != pr.elements[k]) + break; + while (j > i + 1 && k && k < pr.count && solvidset2str_evrcmp(pool, pr.elements[k], pr.elements[k - 1]) == 0) + { + j--; + k--; + } + if (k == 0 || j == i + 1) + { + s = pool_tmpappend(pool, s, pool_solvid2str(pool, pq.elements[i]), 0); + continue; + } + /* create an interval */ + s = pool_tmpappend(pool, s, pool_id2str(pool, name), 0); + if (kstart > 0) + s = pool_tmpappend(pool, s, " >= ", solvidset2str_striprelease(pool, pool->solvables[pr.elements[kstart]].evr, pool->solvables[pr.elements[kstart - 1]].evr)); + if (k < pr.count) + s = pool_tmpappend(pool, s, " < ", solvidset2str_striprelease(pool, pool->solvables[pr.elements[k]].evr, pool->solvables[pr.elements[k - 1]].evr)); + i = j - 1; + } + queue_free(&pq); + queue_free(&pr); + return s; +} +