2 * Copyright (c) 2013, SUSE Inc.
4 * This program is licensed under the BSD license, read LICENSE.BSD
5 * for further information
11 * Linked packages are "pseudo" packages that are bound to real packages but
12 * contain different information (name/summary/description). They are normally
13 * somehow generated from the real packages, either when the repositories are
14 * created or automatically from the packages by looking at the provides.
16 * We currently support:
19 * created from AppStream appdata xml in the repository (which is generated
20 * from files in /usr/share/appdata)
23 * created from product data in the repository (which is generated from files
24 * in /etc/products.d. In the future we may switch to using product()
25 * provides of packages.
28 * created from pattern() provides of packages.
40 #include "linkedpkg.h"
42 #ifdef ENABLE_LINKED_PKGS
45 find_application_link(Pool *pool, Solvable *s, Id *reqidp, Queue *qr, Id *prvidp, Queue *qp)
52 /* find appdata requires */
56 Id *reqp = s->repo->idarraydata + s->requires;
57 while ((req = *reqp++) != 0) /* go through all requires */
61 if (!strncmp("appdata(", pool_id2str(pool, req), 8))
70 /* find application-appdata provides */
73 Id *prvp = s->repo->idarraydata + s->provides;
74 while ((prv = *prvp++) != 0) /* go through all provides */
78 if (strncmp("application-appdata(", pool_id2str(pool, prv), 20))
80 if (!strcmp(pool_id2str(pool, prv) + 12, pool_id2str(pool, req)))
85 return; /* huh, no provides found? */
87 FOR_PROVIDES(p, pp, req)
88 if (pool->solvables[p].repo == s->repo)
89 if (!pkgname || pool->solvables[p].name == pkgname)
91 if (!qr->count && pkgname)
93 /* huh, no matching package? try without pkgname filter */
94 FOR_PROVIDES(p, pp, req)
95 if (pool->solvables[p].repo == s->repo)
100 FOR_PROVIDES(p, pp, prv)
101 if (pool->solvables[p].repo == s->repo)
111 find_product_link(Pool *pool, Solvable *s, Id *reqidp, Queue *qr, Id *prvidp, Queue *qp)
116 /* search for project requires */
120 Id req, *reqp = s->repo->idarraydata + s->requires;
121 const char *nn = pool_id2str(pool, s->name);
122 int nnl = strlen(nn);
123 while ((req = *reqp++) != 0) /* go through all requires */
127 Reldep *rd = GETRELDEP(pool, req);
128 if (rd->flags != REL_EQ || rd->evr != s->evr)
130 rn = pool_id2str(pool, rd->name);
131 if (!strncmp(rn, "product(", 8) && !strncmp(rn + 8, nn + 8, nnl - 8) && !strcmp( rn + nnl, ")"))
140 /* too bad. construct from scratch */
141 str = pool_tmpjoin(pool, pool_id2str(pool, s->name), ")", 0);
143 namerelid = pool_rel2id(pool, pool_str2id(pool, str, 1), s->evr, REL_EQ, 1);
145 FOR_PROVIDES(p, pp, namerelid)
147 Solvable *ps = pool->solvables + p;
148 if (ps->repo != s->repo || ps->arch != s->arch)
152 if (!qr->count && s->repo == pool->installed)
154 /* oh no! Look up reference file */
156 const char *refbasename = solvable_lookup_str(s, PRODUCT_REFERENCEFILE);
157 dataiterator_init(&di, pool, s->repo, 0, SOLVABLE_FILELIST, refbasename, SEARCH_STRING);
158 while (dataiterator_step(&di))
159 queue_push(qr, di.solvid);
160 dataiterator_free(&di);
163 dataiterator_init(&di, pool, s->repo, 0, PRODUCT_REFERENCEFILE, refbasename, SEARCH_STRING);
164 while (dataiterator_step(&di))
165 queue_push(qp, di.solvid);
166 dataiterator_free(&di);
172 FOR_PROVIDES(p, pp, s->name)
174 Solvable *ps = pool->solvables + p;
175 if (s->name != ps->name || ps->repo != s->repo || ps->arch != s->arch || s->evr != ps->evr)
183 *prvidp = solvable_selfprovidedep(s);
187 find_pattern_link(Pool *pool, Solvable *s, Id *reqidp, Queue *qr, Id *prvidp, Queue *qp)
189 Id p, pp, *pr, apevr = 0, aprel = 0;
191 /* check if autopattern */
194 for (pr = s->repo->idarraydata + s->provides; (p = *pr++) != 0; )
197 Reldep *rd = GETRELDEP(pool, p);
198 if (rd->flags == REL_EQ && !strcmp(pool_id2str(pool, rd->name), "autopattern()"))
207 FOR_PROVIDES(p, pp, apevr)
209 Solvable *s2 = pool->solvables + p;
210 if (s2->repo == s->repo && s2->name == apevr && s2->evr == s->evr && s2->vendor == s->vendor)
215 FOR_PROVIDES(p, pp, aprel)
217 Solvable *s2 = pool->solvables + p;
218 if (s2->repo == s->repo && s2->evr == s->evr && s2->vendor == s->vendor)
228 /* the following two functions are used in solvable_lookup_str_base to do
229 * translated lookups on the product/pattern packages
232 find_autopattern_name(Pool *pool, Solvable *s)
237 for (prvp = s->repo->idarraydata + s->provides; (prv = *prvp++) != 0; )
240 Reldep *rd = GETRELDEP(pool, prv);
241 if (rd->flags == REL_EQ && !strcmp(pool_id2str(pool, rd->name), "autopattern()"))
242 return strncmp(pool_id2str(pool, rd->evr), "pattern:", 8) != 0 ? rd->evr : 0;
248 find_autoproduct_name(Pool *pool, Solvable *s)
253 for (prvp = s->repo->idarraydata + s->provides; (prv = *prvp++) != 0; )
256 Reldep *rd = GETRELDEP(pool, prv);
257 if (rd->flags == REL_EQ && !strcmp(pool_id2str(pool, rd->name), "autoproduct()"))
258 return strncmp(pool_id2str(pool, rd->evr), "product:", 8) != 0 ? rd->evr : 0;
264 find_package_link(Pool *pool, Solvable *s, Id *reqidp, Queue *qr, Id *prvidp, Queue *qp)
266 const char *name = pool_id2str(pool, s->name);
267 if (name[0] == 'a' && !strncmp("application:", name, 12))
268 find_application_link(pool, s, reqidp, qr, prvidp, qp);
269 else if (name[0] == 'p' && !strncmp("pattern:", name, 7))
270 find_pattern_link(pool, s, reqidp, qr, prvidp, qp);
271 else if (name[0] == 'p' && !strncmp("product:", name, 8))
272 find_product_link(pool, s, reqidp, qr, prvidp, qp);