#include "poolvendor.h"
#include "chksum.h"
#include "linkedpkg.h"
+#include "evr.h"
const char *
pool_solvable2str(Pool *pool, Solvable *s)
int nl, el, al;
char *p;
n = pool_id2str(pool, s->name);
- e = pool_id2str(pool, s->evr);
+ e = s->evr ? pool_id2str(pool, s->evr) : "";
/* XXX: may want to skip the epoch here */
- a = pool_id2str(pool, s->arch);
+ a = s->arch ? pool_id2str(pool, s->arch) : "";
nl = strlen(n);
el = strlen(e);
al = strlen(a);
p[nl + el] = pool->disttype == DISTTYPE_HAIKU ? '-' : '.';
strcpy(p + nl + el + 1, a);
}
+ if (pool->disttype == DISTTYPE_CONDA && solvable_lookup_type(s, SOLVABLE_BUILDFLAVOR))
+ {
+ Queue flavorq;
+ int i;
+ queue_init(&flavorq);
+ solvable_lookup_idarray(s, SOLVABLE_BUILDFLAVOR, &flavorq);
+ for (i = 0; i < flavorq.count; i++)
+ p = pool_tmpappend(pool, p, "-", pool_id2str(pool, flavorq.elements[i]));
+ queue_free(&flavorq);
+ }
return p;
}
if (solvable_lookup_idarray(s, keyname, &q) && q.count)
{
Pool *pool = s->repo->pool;
- int i;
- str = pool_tmpjoin(pool, pool_id2str(pool, q.elements[0]), 0, 0);
- for (i = 1; i < q.count; i++)
- str = pool_tmpappend(pool, str, joinstr, pool_id2str(pool, q.elements[i]));
+ if (q.count == 1)
+ str = (char *)pool_id2str(pool, q.elements[0]);
+ else
+ {
+ int i;
+ str = pool_tmpjoin(pool, pool_id2str(pool, q.elements[0]), 0, 0);
+ for (i = 1; i < q.count; i++)
+ str = pool_tmpappend(pool, str, joinstr, pool_id2str(pool, q.elements[i]));
+ }
}
queue_free(&q);
return str;
if (!s->repo)
return 0;
str = repo_lookup_str(s->repo, s - s->repo->pool->solvables, keyname);
- if (!str && (keyname == SOLVABLE_LICENSE || keyname == SOLVABLE_GROUP))
+ if (!str && (keyname == SOLVABLE_LICENSE || keyname == SOLVABLE_GROUP || keyname == SOLVABLE_BUILDFLAVOR))
str = solvable_lookup_str_joinarray(s, keyname, ", ");
return str;
}
}
#ifdef ENABLE_LINKED_PKGS
/* autopattern/product translation magic */
- if (pass)
+ if (pass == 1 && name == s->name)
{
- const char *n = pool_id2str(pool, name);
- if (*n == 'p')
- {
- if (!strncmp("pattern:", n, 8) && (name = find_autopattern_name(pool, s)) != 0)
- pass = -1;
- if (!strncmp("product:", n, 8) && (name = find_autoproduct_name(pool, s)) != 0)
- pass = -1;
- }
+ name = find_autopackage_name(pool, s);
+ if (name && name != s->name)
+ pass = -1; /* start over with new name */
}
#endif
}
const char *
solvable_lookup_str_lang(Solvable *s, Id keyname, const char *lang, int usebase)
{
- if (s->repo)
- {
- Id id = pool_id2langid(s->repo->pool, keyname, lang, 0);
- if (id)
- return solvable_lookup_str_base(s, id, keyname, usebase);
- if (!usebase)
- return 0;
- }
+ Id id;
+ if (!s->repo)
+ return 0;
+ id = pool_id2langid(s->repo->pool, keyname, lang, 0);
+ if (id)
+ return solvable_lookup_str_base(s, id, keyname, usebase);
+ if (!usebase)
+ return 0;
return solvable_lookup_str(s, keyname);
}
return repo_lookup_num(s->repo, s - s->repo->pool->solvables, keyname, notfound);
}
-unsigned int
-solvable_lookup_sizek(Solvable *s, Id keyname, unsigned int notfound)
+unsigned long long
+solvable_lookup_sizek(Solvable *s, Id keyname, unsigned long long notfound)
{
unsigned long long size;
if (!s->repo)
return notfound;
- size = solvable_lookup_num(s, keyname, (unsigned long long)notfound << 10);
- return (unsigned int)((size + 1023) >> 10);
+ size = solvable_lookup_num(s, keyname, (unsigned long long)-1);
+ return size == (unsigned long long)-1 ? notfound : ((size + 1023) >> 10);
}
int
int
solvable_lookup_bool(Solvable *s, Id keyname)
{
+ Id type;
if (!s->repo)
return 0;
/* historic nonsense: there are two ways of storing a bool, as num == 1 or void. test both. */
- if (repo_lookup_type(s->repo, s - s->repo->pool->solvables, keyname) == REPOKEY_TYPE_VOID)
+ type = repo_lookup_type(s->repo, s - s->repo->pool->solvables, keyname);
+ if (type == REPOKEY_TYPE_VOID)
return 1;
- return repo_lookup_num(s->repo, s - s->repo->pool->solvables, keyname, 0) == 1;
+ if (type == REPOKEY_TYPE_NUM || type == REPOKEY_TYPE_CONSTANT)
+ return repo_lookup_num(s->repo, s - s->repo->pool->solvables, keyname, 0) == 1;
+ return 0;
}
const unsigned char *
solvable_lookup_bin_checksum(Solvable *s, Id keyname, Id *typep)
{
- Repo *repo = s->repo;
-
- if (!repo)
+ if (!s->repo)
{
*typep = 0;
return 0;
}
- return repo_lookup_bin_checksum(repo, s - repo->pool->solvables, keyname, typep);
+ return repo_lookup_bin_checksum(s->repo, s - s->repo->pool->solvables, keyname, typep);
}
const char *
return chk ? pool_bin2hex(s->repo->pool, chk, solv_chksum_len(*typep)) : 0;
}
+unsigned int
+solvable_lookup_count(Solvable *s, Id keyname)
+{
+ return s->repo ? repo_lookup_count(s->repo, s - s->repo->pool->solvables, keyname) : 0;
+}
+
static inline const char *
evrid2vrstr(Pool *pool, Id evrid)
{
int
solvable_identical(Solvable *s1, Solvable *s2)
{
- unsigned int bt1, bt2;
+ unsigned long long bt1, bt2;
Id rq1, rq2;
Id *reqp;
if (s1->name != s2->name)
if (rq1 != rq2)
return 0;
}
+ if (s1->repo && s1->repo->pool->disttype == DISTTYPE_CONDA)
+ {
+ /* check buildflavor and buildversion */
+ const char *str1, *str2;
+ str1 = solvable_lookup_str(s1, SOLVABLE_BUILDFLAVOR);
+ str2 = solvable_lookup_str(s2, SOLVABLE_BUILDFLAVOR);
+ if (str1 != str2 && (!str1 || !str2 || strcmp(str1, str2) != 0))
+ return 0;
+ str1 = solvable_lookup_str(s1, SOLVABLE_BUILDVERSION);
+ str2 = solvable_lookup_str(s2, SOLVABLE_BUILDVERSION);
+ if (str1 != str2 && (!str1 || !str2 || strcmp(str1, str2) != 0))
+ return 0;
+ }
return 1;
}
int i;
Pool *pool = s->repo->pool;
Queue q;
+
+ if (keyname == SOLVABLE_NAME)
+ return pool_match_nevr(pool, s, dep) ? 1 : 0; /* nevr match hack */
queue_init(&q);
solvable_lookup_deparray(s, keyname, &q, marker);
for (i = 0; i < q.count; i++)
queue_free(&q);
return i;
}
+
+int
+solvable_matchessolvable_int(Solvable *s, Id keyname, int marker, Id solvid, Map *solvidmap, Queue *depq, Map *missc, int reloff, Queue *outdepq)
+{
+ Pool *pool = s->repo->pool;
+ int i, boff;
+ Id *wp;
+
+ if (depq->count)
+ queue_empty(depq);
+ if (outdepq && outdepq->count)
+ queue_empty(outdepq);
+ solvable_lookup_deparray(s, keyname, depq, marker);
+ for (i = 0; i < depq->count; i++)
+ {
+ Id dep = depq->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 (solvidmap)
+ {
+ for (; *wp; wp++)
+ if (MAPTST(solvidmap, *wp))
+ break;
+ }
+ else
+ {
+ for (; *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 (solvidmap)
+ {
+ for (; *wp; wp++)
+ if (MAPTST(solvidmap, *wp))
+ break;
+ }
+ else
+ {
+ for (; *wp; wp++)
+ if (*wp == solvid)
+ break;
+ }
+ if (*wp)
+ {
+ if (outdepq)
+ {
+ queue_pushunique(outdepq, dep);
+ continue;
+ }
+ return 1;
+ }
+ MAPSET(missc, boff);
+ }
+ return outdepq && outdepq->count ? 1 : 0;
+}
+
+int
+solvable_matchessolvable(Solvable *s, Id keyname, Id solvid, Queue *depq, int marker)
+{
+ Pool *pool = s->repo->pool;
+ Map missc; /* cache for misses */
+ int res, reloff;
+ Queue qq;
+
+ if (depq && depq->count)
+ queue_empty(depq);
+ if (s - pool->solvables == solvid)
+ return 0; /* no self-matches */
+
+ queue_init(&qq);
+ reloff = pool->ss.nstrings;
+ map_init(&missc, reloff + pool->nrels);
+ res = solvable_matchessolvable_int(s, keyname, marker, solvid, 0, &qq, &missc, reloff, depq);
+ map_free(&missc);
+ 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;
+}
+