*
* product:
* created from product data in the repository (which is generated from files
- * in /etc/products.d. In the future we may switch to using product()
+ * in /etc/products.d). In the future we may switch to using product()
* provides of packages.
- *
+ *
* pattern:
* created from pattern() provides of packages.
*
#include "pool.h"
#include "repo.h"
+#include "solver.h"
+#include "evr.h"
+#include "bitmap.h"
#include "linkedpkg.h"
#ifdef ENABLE_LINKED_PKGS
Id req = 0;
Id prv = 0;
Id p, pp;
+ Id pkgname = 0, appdataid = 0;
/* find appdata requires */
if (s->requires)
if (ISRELDEP(req))
continue;
if (!strncmp("appdata(", pool_id2str(pool, req), 8))
- break;
+ appdataid = req;
+ else
+ pkgname = req;
}
}
+ req = appdataid ? appdataid : pkgname;
if (!req)
return;
/* find application-appdata provides */
if (s->provides)
{
Id *prvp = s->repo->idarraydata + s->provides;
+ const char *reqs = pool_id2str(pool, req);
+ const char *prvs;
while ((prv = *prvp++) != 0) /* go through all provides */
{
if (ISRELDEP(prv))
continue;
- if (strncmp("application-appdata(", pool_id2str(pool, prv), 20))
+ prvs = pool_id2str(pool, prv);
+ if (strncmp("application-appdata(", prvs, 20))
continue;
- if (!strcmp(pool_id2str(pool, prv) + 12, pool_id2str(pool, req)))
- break;
+ if (appdataid)
+ {
+ if (!strcmp(prvs + 12, reqs))
+ break;
+ }
+ else
+ {
+ int reqsl = strlen(reqs);
+ if (!strncmp(prvs + 20, reqs, reqsl) && !strcmp(prvs + 20 + reqsl, ")"))
+ break;
+ }
}
}
if (!prv)
- return;
+ return; /* huh, no provides found? */
/* now link em */
FOR_PROVIDES(p, pp, req)
if (pool->solvables[p].repo == s->repo)
- queue_push(qr, p);
- if (reqidp)
- *reqidp = req;
+ if (!pkgname || pool->solvables[p].name == pkgname)
+ queue_push(qr, p);
+ if (!qr->count && pkgname && appdataid)
+ {
+ /* huh, no matching package? try without pkgname filter */
+ FOR_PROVIDES(p, pp, req)
+ if (pool->solvables[p].repo == s->repo)
+ queue_push(qr, p);
+ }
if (qp)
{
FOR_PROVIDES(p, pp, prv)
if (pool->solvables[p].repo == s->repo)
- queue_push(qp, pp);
- if (prvidp)
- *prvidp = req;
+ queue_push(qp, p);
}
+ if (reqidp)
+ *reqidp = req;
+ if (prvidp)
+ *prvidp = prv;
}
void
find_product_link(Pool *pool, Solvable *s, Id *reqidp, Queue *qr, Id *prvidp, Queue *qp)
{
- Id n = s - pool->solvables;
Id p, pp, namerelid;
char *str;
+ unsigned int sbt = 0;
- if (pool->nscallback)
- {
- Id buddy = pool->nscallback(pool, pool->nscallbackdata, NAMESPACE_PRODUCTBUDDY, n);
- if (buddy > 0 && buddy != SYSTEMSOLVABLE && buddy != n && buddy < pool->nsolvables)
- {
- if (reqidp)
- *reqidp = solvable_selfprovidedep(pool->solvables + buddy);
- queue_push(qr, buddy);
- if (prvidp)
- *prvidp = solvable_selfprovidedep(s);
- if (qp)
- queue_push(qp, n);
- return;
- }
- }
/* search for project requires */
namerelid = 0;
if (s->requires)
continue;
queue_push(qr, p);
}
+ if (qr->count > 1)
+ {
+ /* multiple providers. try buildtime filter */
+ sbt = solvable_lookup_num(s, SOLVABLE_BUILDTIME, 0);
+ if (sbt)
+ {
+ unsigned int bt;
+ int i, j;
+ int filterqp = 1;
+ for (i = j = 0; i < qr->count; i++)
+ {
+ bt = solvable_lookup_num(pool->solvables + qr->elements[i], SOLVABLE_BUILDTIME, 0);
+ if (!bt)
+ filterqp = 0; /* can't filter */
+ if (!bt || bt == sbt)
+ qr->elements[j++] = qr->elements[i];
+ }
+ if (j)
+ qr->count = j;
+ if (!j || !filterqp)
+ sbt = 0; /* filter failed */
+ }
+ }
if (!qr->count && s->repo == pool->installed)
{
/* oh no! Look up reference file */
Dataiterator di;
const char *refbasename = solvable_lookup_str(s, PRODUCT_REFERENCEFILE);
- dataiterator_init(&di, pool, s->repo, 0, SOLVABLE_FILELIST, refbasename, SEARCH_STRING);
- while (dataiterator_step(&di))
- queue_push(qr, di.solvid);
- dataiterator_free(&di);
- if (qp)
+ if (refbasename)
{
- dataiterator_init(&di, pool, s->repo, 0, PRODUCT_REFERENCEFILE, refbasename, SEARCH_STRING);
+ dataiterator_init(&di, pool, s->repo, 0, SOLVABLE_FILELIST, refbasename, SEARCH_STRING);
while (dataiterator_step(&di))
- queue_push(qp, di.solvid);
+ {
+ if (di.key->type != REPOKEY_TYPE_DIRSTRARRAY)
+ continue;
+ if (strcmp(repodata_dir2str(di.data, di.kv.id, 0), "/etc/products.d") != 0)
+ continue;
+ queue_push(qr, di.solvid);
+ }
dataiterator_free(&di);
+ if (qp)
+ {
+ dataiterator_init(&di, pool, s->repo, 0, PRODUCT_REFERENCEFILE, refbasename, SEARCH_STRING);
+ while (dataiterator_step(&di))
+ queue_push(qp, di.solvid);
+ dataiterator_free(&di);
+ }
}
}
- else
+ else if (qp)
{
/* find qp */
FOR_PROVIDES(p, pp, s->name)
Solvable *ps = pool->solvables + p;
if (s->name != ps->name || ps->repo != s->repo || ps->arch != s->arch || s->evr != ps->evr)
continue;
+ if (sbt && solvable_lookup_num(ps, SOLVABLE_BUILDTIME, 0) != sbt)
+ continue;
queue_push(qp, p);
}
}
*prvidp = aprel;
}
+/* the following two functions are used in solvable_lookup_str_base to do
+ * translated lookups on the product/pattern packages
+ */
Id
find_autopattern_name(Pool *pool, Solvable *s)
{
return 0;
for (prvp = s->repo->idarraydata + s->provides; (prv = *prvp++) != 0; )
if (ISRELDEP(prv))
- {
+ {
Reldep *rd = GETRELDEP(pool, prv);
if (rd->flags == REL_EQ && !strcmp(pool_id2str(pool, rd->name), "autopattern()"))
return strncmp(pool_id2str(pool, rd->evr), "pattern:", 8) != 0 ? rd->evr : 0;
- }
+ }
+ return 0;
+}
+
+Id
+find_autoproduct_name(Pool *pool, Solvable *s)
+{
+ Id prv, *prvp;
+ if (!s->provides)
+ return 0;
+ for (prvp = s->repo->idarraydata + s->provides; (prv = *prvp++) != 0; )
+ if (ISRELDEP(prv))
+ {
+ Reldep *rd = GETRELDEP(pool, prv);
+ if (rd->flags == REL_EQ && !strcmp(pool_id2str(pool, rd->name), "autoproduct()"))
+ return strncmp(pool_id2str(pool, rd->evr), "product:", 8) != 0 ? rd->evr : 0;
+ }
return 0;
}
find_product_link(pool, s, reqidp, qr, prvidp, qp);
}
+static int
+name_min_max(Pool *pool, Solvable *s, Id *namep, Id *minp, Id *maxp)
+{
+ Queue q;
+ Id qbuf[4];
+ Id name, min, max;
+ int i;
+
+ queue_init_buffer(&q, qbuf, sizeof(qbuf)/sizeof(*qbuf));
+ find_package_link(pool, s, 0, &q, 0, 0);
+ if (!q.count)
+ {
+ queue_free(&q);
+ return 0;
+ }
+ s = pool->solvables + q.elements[0];
+ name = s->name;
+ min = max = s->evr;
+ for (i = 1; i < q.count; i++)
+ {
+ s = pool->solvables + q.elements[i];
+ if (s->name != name)
+ {
+ queue_free(&q);
+ return 0;
+ }
+ if (s->evr == min || s->evr == max)
+ continue;
+ if (pool_evrcmp(pool, min, s->evr, EVRCMP_COMPARE) >= 0)
+ min = s->evr;
+ else if (min == max || pool_evrcmp(pool, max, s->evr, EVRCMP_COMPARE) <= 0)
+ max = s->evr;
+ }
+ queue_free(&q);
+ *namep = name;
+ *minp = min;
+ *maxp = max;
+ return 1;
+}
+
+int
+pool_link_evrcmp(Pool *pool, Solvable *s1, Solvable *s2)
+{
+ Id name1, evrmin1, evrmax1;
+ Id name2, evrmin2, evrmax2;
+
+ if (s1->name != s2->name)
+ return 0; /* can't compare */
+ if (!name_min_max(pool, s1, &name1, &evrmin1, &evrmax1))
+ return 0;
+ if (!name_min_max(pool, s2, &name2, &evrmin2, &evrmax2))
+ return 0;
+ /* compare linked names */
+ if (name1 != name2)
+ return 0;
+ if (evrmin1 == evrmin2 && evrmax1 == evrmax2)
+ return 0;
+ /* now compare evr intervals */
+ if (evrmin1 == evrmax1 && evrmin2 == evrmax2)
+ return pool_evrcmp(pool, evrmin1, evrmax2, EVRCMP_COMPARE);
+ if (evrmin1 != evrmax2 && pool_evrcmp(pool, evrmin1, evrmax2, EVRCMP_COMPARE) > 0)
+ return 1;
+ if (evrmax1 != evrmin2 && pool_evrcmp(pool, evrmax1, evrmin2, EVRCMP_COMPARE) < 0)
+ return -1;
+ return 0;
+}
+
+void
+extend_updatemap_to_buddies(Solver *solv)
+{
+ Pool *pool = solv->pool;
+ Repo *installed = solv->installed;
+ Solvable *s;
+ int p, ip;
+
+ if (!installed)
+ return;
+ if (!solv->updatemap.size || !solv->instbuddy)
+ return;
+ FOR_REPO_SOLVABLES(installed, p, s)
+ {
+ if (!MAPTST(&solv->updatemap, p - installed->start))
+ continue;
+ if ((ip = solv->instbuddy[p - installed->start]) <= 1)
+ continue;
+ if (!has_package_link(pool, s)) /* only look at pseudo -> real relations */
+ continue;
+ if (ip < installed->start || ip >= installed->end || pool->solvables[ip].repo != installed)
+ continue; /* just in case... */
+ MAPSET(&solv->updatemap, ip - installed->start);
+ }
+}
+
#endif