From bb0ec6baf44908f2d76ca4b6f9c47c6ee1f65a6e Mon Sep 17 00:00:00 2001 From: Michael Schroeder Date: Wed, 16 Oct 2013 12:06:07 +0200 Subject: [PATCH] make pattern translations also look at the linked packages --- src/linkedpkg.c | 239 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/linkedpkg.h | 37 +++++++++ src/solvable.c | 13 ++- 3 files changed, 286 insertions(+), 3 deletions(-) create mode 100644 src/linkedpkg.c create mode 100644 src/linkedpkg.h diff --git a/src/linkedpkg.c b/src/linkedpkg.c new file mode 100644 index 0000000..6df497c --- /dev/null +++ b/src/linkedpkg.c @@ -0,0 +1,239 @@ +/* + * Copyright (c) 2013, SUSE Inc. + * + * This program is licensed under the BSD license, read LICENSE.BSD + * for further information + */ + +/* + * linkedpkg.c + */ + +#include +#include +#include +#include +#include + +#include "pool.h" +#include "repo.h" +#include "linkedpkg.h" + +#ifdef ENABLE_LINKED_PKGS + +void +find_application_link(Pool *pool, Solvable *s, Id *reqidp, Queue *qr, Id *prvidp, Queue *qp) +{ + Id req = 0; + Id prv = 0; + Id p, pp; + + /* find appdata requires */ + if (s->requires) + { + Id *reqp = s->repo->idarraydata + s->requires; + while ((req = *reqp++) != 0) /* go through all requires */ + { + if (ISRELDEP(req)) + continue; + if (!strncmp("appdata(", pool_id2str(pool, req), 8)) + break; + } + } + if (!req) + return; + /* find application-appdata provides */ + if (s->provides) + { + Id *prvp = s->repo->idarraydata + s->provides; + while ((prv = *prvp++) != 0) /* go through all provides */ + { + if (ISRELDEP(prv)) + continue; + if (strncmp("application-appdata(", pool_id2str(pool, prv), 20)) + continue; + if (!strcmp(pool_id2str(pool, prv) + 12, pool_id2str(pool, req))) + break; + } + } + if (!prv) + return; + /* now link em */ + FOR_PROVIDES(p, pp, req) + if (pool->solvables[p].repo == s->repo) + queue_push(qr, p); + if (reqidp) + *reqidp = req; + if (qp) + { + FOR_PROVIDES(p, pp, prv) + if (pool->solvables[p].repo == s->repo) + queue_push(qp, pp); + if (prvidp) + *prvidp = req; + } +} + +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; + + 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) + { + Id req, *reqp = s->repo->idarraydata + s->requires; + const char *nn = pool_id2str(pool, s->name); + int nnl = strlen(nn); + while ((req = *reqp++) != 0) /* go through all requires */ + if (ISRELDEP(req)) + { + const char *rn; + Reldep *rd = GETRELDEP(pool, req); + if (rd->flags != REL_EQ || rd->evr != s->evr) + continue; + rn = pool_id2str(pool, rd->name); + if (!strncmp(rn, "product(", 8) && !strncmp(rn + 8, nn + 8, nnl - 8) && !strcmp( rn + nnl, ")")) + { + namerelid = req; + break; + } + } + } + if (!namerelid) + { + /* too bad. construct from scratch */ + str = pool_tmpjoin(pool, pool_id2str(pool, s->name), ")", 0); + str[7] = '('; + namerelid = pool_rel2id(pool, pool_str2id(pool, str, 1), s->evr, REL_EQ, 1); + } + FOR_PROVIDES(p, pp, namerelid) + { + Solvable *ps = pool->solvables + p; + if (ps->repo != s->repo || ps->arch != s->arch) + continue; + queue_push(qr, p); + } + 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) + { + 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 + { + /* 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; + queue_push(qp, p); + } + } + if (reqidp) + *reqidp = namerelid; + if (prvidp) + *prvidp = solvable_selfprovidedep(s); +} + +void +find_pattern_link(Pool *pool, Solvable *s, Id *reqidp, Queue *qr, Id *prvidp, Queue *qp) +{ + Id p, pp, *pr, apevr = 0, aprel = 0; + + /* check if autopattern */ + if (!s->provides) + return; + for (pr = s->repo->idarraydata + s->provides; (p = *pr++) != 0; ) + if (ISRELDEP(p)) + { + Reldep *rd = GETRELDEP(pool, p); + if (rd->flags == REL_EQ && !strcmp(pool_id2str(pool, rd->name), "autopattern()")) + { + aprel = p; + apevr = rd->evr; + break; + } + } + if (!apevr) + return; + FOR_PROVIDES(p, pp, apevr) + { + Solvable *s2 = pool->solvables + p; + if (s2->repo == s->repo && s2->name == apevr && s2->evr == s->evr && s2->vendor == s->vendor) + queue_push(qr, p); + } + if (qp) + { + FOR_PROVIDES(p, pp, aprel) + { + Solvable *s2 = pool->solvables + p; + if (s2->repo == s->repo && s2->evr == s->evr && s2->vendor == s->vendor) + queue_push(qp, pp); + } + } + if (reqidp) + *reqidp = apevr; + if (prvidp) + *prvidp = aprel; +} + +Id +find_autopattern_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), "autopattern()")) + return strncmp(pool_id2str(pool, rd->evr), "pattern:", 8) != 0 ? rd->evr : 0; + } + return 0; +} + +void +find_package_link(Pool *pool, Solvable *s, Id *reqidp, Queue *qr, Id *prvidp, Queue *qp) +{ + const char *name = pool_id2str(pool, s->name); + if (name[0] == 'a' && !strncmp("application:", name, 12)) + find_application_link(pool, s, reqidp, qr, prvidp, qp); + else if (name[0] == 'p' && !strncmp("pattern:", name, 7)) + find_pattern_link(pool, s, reqidp, qr, prvidp, qp); + else if (name[0] == 'p' && !strncmp("product:", name, 8)) + find_product_link(pool, s, reqidp, qr, prvidp, qp); +} + +#endif diff --git a/src/linkedpkg.h b/src/linkedpkg.h new file mode 100644 index 0000000..3114702 --- /dev/null +++ b/src/linkedpkg.h @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2013, Novell Inc. + * + * This program is licensed under the BSD license, read LICENSE.BSD + * for further information + */ + +/* + * linkedpkg.h (internal) + */ + +#ifndef LIBSOLV_LINKEDPKG_H +#define LIBSOLV_LINKEDPKG_H + +static inline int +has_package_link(Pool *pool, Solvable *s) +{ + const char *name = pool_id2str(pool, s->name); + if (name[0] == 'a' && !strncmp("application:", name, 12)) + return 1; + if (name[0] == 'p' && !strncmp("pattern:", name, 7)) + return 1; + if (name[0] == 'p' && !strncmp("product:", name, 8)) + return 1; + return 0; +} + +extern void find_application_link(Pool *pool, Solvable *s, Id *reqidp, Queue *qr, Id *prvidp, Queue *qp); +extern void find_product_link(Pool *pool, Solvable *s, Id *reqidp, Queue *qr, Id *prvidp, Queue *qp); +extern void find_pattern_link(Pool *pool, Solvable *s, Id *reqidp, Queue *qr, Id *prvidp, Queue *qp); + +extern Id find_autopattern_name(Pool *pool, Solvable *s); + +/* generic */ +extern void find_package_link(Pool *pool, Solvable *s, Id *reqidp, Queue *qr, Id *prvidp, Queue *qp); + +#endif diff --git a/src/solvable.c b/src/solvable.c index bfe25ce..c07f4c8 100644 --- a/src/solvable.c +++ b/src/solvable.c @@ -23,6 +23,7 @@ #include "policy.h" #include "poolvendor.h" #include "chksum.h" +#include "linkedpkg.h" const char * pool_solvable2str(Pool *pool, Solvable *s) @@ -134,7 +135,7 @@ solvable_lookup_str_base(Solvable *s, Id keyname, Id basekeyname, int usebase) { Pool *pool; const char *str, *basestr; - Id p, pp; + Id p, pp, name; Solvable *s2; int pass; @@ -151,13 +152,14 @@ solvable_lookup_str_base(Solvable *s, Id keyname, Id basekeyname, int usebase) * translation */ if (!pool->whatprovides) return usebase ? basestr : 0; + name = s->name; /* we do this in two passes, first same vendor, then all other vendors */ for (pass = 0; pass < 2; pass++) { - FOR_PROVIDES(p, pp, s->name) + FOR_PROVIDES(p, pp, name) { s2 = pool->solvables + p; - if (s2->name != s->name) + if (s2->name != name) continue; if ((s->vendor == s2->vendor) != (pass == 0)) continue; @@ -168,6 +170,11 @@ solvable_lookup_str_base(Solvable *s, Id keyname, Id basekeyname, int usebase) if (str) return str; } +#ifdef ENABLE_LINKED_PKGS + /* autopattern translation magic */ + if (pass && !strncmp("pattern:", pool_id2str(pool, name), 8) && (name = find_autopattern_name(pool, s)) != 0) + pass = -1; +#endif } return usebase ? basestr : 0; } -- 2.7.4