Always return IGNORE for pseudo packages in RPM_ONLY mode
[platform/upstream/libsolv.git] / src / linkedpkg.c
1 /*
2  * Copyright (c) 2013, SUSE Inc.
3  *
4  * This program is licensed under the BSD license, read LICENSE.BSD
5  * for further information
6  */
7
8 /*
9  * linkedpkg.c
10  *
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.
15  *
16  * We currently support:
17  *
18  * application:
19  *   created from AppStream appdata xml in the repository (which is generated
20  *   from files in /usr/share/appdata)
21  *
22  * product:
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.
26  *
27  * pattern:
28  *   created from pattern() provides of packages.
29  *
30  */
31
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <unistd.h>
35 #include <string.h>
36 #include <assert.h>
37
38 #include "pool.h"
39 #include "repo.h"
40 #include "linkedpkg.h"
41
42 #ifdef ENABLE_LINKED_PKGS
43
44 void
45 find_application_link(Pool *pool, Solvable *s, Id *reqidp, Queue *qr, Id *prvidp, Queue *qp)
46 {
47   Id req = 0;
48   Id prv = 0;
49   Id p, pp;
50
51   /* find appdata requires */
52   if (s->requires)
53     {
54       Id *reqp = s->repo->idarraydata + s->requires;
55       while ((req = *reqp++) != 0)            /* go through all requires */
56         {
57           if (ISRELDEP(req))
58             continue;
59           if (!strncmp("appdata(", pool_id2str(pool, req), 8))
60             break;
61         }
62     }
63   if (!req)
64     return;
65   /* find application-appdata provides */
66   if (s->provides)
67     {
68       Id *prvp = s->repo->idarraydata + s->provides;
69       while ((prv = *prvp++) != 0)            /* go through all provides */
70         {
71           if (ISRELDEP(prv))
72             continue;
73           if (strncmp("application-appdata(", pool_id2str(pool, prv), 20))
74             continue;
75           if (!strcmp(pool_id2str(pool, prv) + 12, pool_id2str(pool, req)))
76             break;
77         }
78     }
79   if (!prv)
80     return;
81   /* now link em */
82   FOR_PROVIDES(p, pp, req)
83     if (pool->solvables[p].repo == s->repo)
84       queue_push(qr, p);
85   if (qp)
86     {
87       FOR_PROVIDES(p, pp, prv)
88         if (pool->solvables[p].repo == s->repo)
89           queue_push(qp, p);
90     }
91   if (reqidp)
92     *reqidp = req;
93   if (prvidp)
94     *prvidp = prv;
95 }
96
97 void
98 find_product_link(Pool *pool, Solvable *s, Id *reqidp, Queue *qr, Id *prvidp, Queue *qp)
99 {
100   Id p, pp, namerelid;
101   char *str;
102
103   /* search for project requires */
104   namerelid = 0;
105   if (s->requires)
106     {
107       Id req, *reqp = s->repo->idarraydata + s->requires;
108       const char *nn = pool_id2str(pool, s->name);
109       int nnl = strlen(nn);
110       while ((req = *reqp++) != 0)            /* go through all requires */
111         if (ISRELDEP(req))
112           {
113             const char *rn;
114             Reldep *rd = GETRELDEP(pool, req);
115             if (rd->flags != REL_EQ || rd->evr != s->evr)
116               continue;
117             rn = pool_id2str(pool, rd->name);
118             if (!strncmp(rn, "product(", 8) && !strncmp(rn + 8, nn + 8, nnl - 8) && !strcmp( rn + nnl, ")"))
119               {
120                 namerelid = req;
121                 break;
122               }
123           }
124     }
125   if (!namerelid)
126     {
127       /* too bad. construct from scratch */
128       str = pool_tmpjoin(pool, pool_id2str(pool, s->name), ")", 0);
129       str[7] = '(';
130       namerelid = pool_rel2id(pool, pool_str2id(pool, str, 1), s->evr, REL_EQ, 1);
131     }
132   FOR_PROVIDES(p, pp, namerelid)
133     {
134       Solvable *ps = pool->solvables + p;
135       if (ps->repo != s->repo || ps->arch != s->arch)
136         continue;
137       queue_push(qr, p);
138     }
139   if (!qr->count && s->repo == pool->installed)
140     {
141       /* oh no! Look up reference file */
142       Dataiterator di;
143       const char *refbasename = solvable_lookup_str(s, PRODUCT_REFERENCEFILE);
144       dataiterator_init(&di, pool, s->repo, 0, SOLVABLE_FILELIST, refbasename, SEARCH_STRING);
145       while (dataiterator_step(&di))
146         queue_push(qr, di.solvid);
147       dataiterator_free(&di);
148       if (qp)
149         {
150           dataiterator_init(&di, pool, s->repo, 0, PRODUCT_REFERENCEFILE, refbasename, SEARCH_STRING);
151           while (dataiterator_step(&di))
152             queue_push(qp, di.solvid);
153           dataiterator_free(&di);
154         }
155     }
156   else if (qp)
157     {
158       /* find qp */
159       FOR_PROVIDES(p, pp, s->name)
160         {
161           Solvable *ps = pool->solvables + p;
162           if (s->name != ps->name || ps->repo != s->repo || ps->arch != s->arch || s->evr != ps->evr)
163             continue;
164           queue_push(qp, p);
165         }
166     }
167   if (reqidp)
168     *reqidp = namerelid;
169   if (prvidp)
170     *prvidp = solvable_selfprovidedep(s);
171 }
172
173 void
174 find_pattern_link(Pool *pool, Solvable *s, Id *reqidp, Queue *qr, Id *prvidp, Queue *qp)
175 {
176   Id p, pp, *pr, apevr = 0, aprel = 0;
177
178   /* check if autopattern */
179   if (!s->provides)
180     return;
181   for (pr = s->repo->idarraydata + s->provides; (p = *pr++) != 0; )
182     if (ISRELDEP(p))
183       {
184         Reldep *rd = GETRELDEP(pool, p);
185         if (rd->flags == REL_EQ && !strcmp(pool_id2str(pool, rd->name), "autopattern()"))
186           {
187             aprel = p;
188             apevr = rd->evr;
189             break;
190           }
191       }
192   if (!apevr)
193     return;
194   FOR_PROVIDES(p, pp, apevr)
195     {
196       Solvable *s2 = pool->solvables + p;
197       if (s2->repo == s->repo && s2->name == apevr && s2->evr == s->evr && s2->vendor == s->vendor)
198         queue_push(qr, p);
199     }
200   if (qp)
201     {
202       FOR_PROVIDES(p, pp, aprel)
203         {
204           Solvable *s2 = pool->solvables + p;
205           if (s2->repo == s->repo && s2->evr == s->evr && s2->vendor == s->vendor)
206             queue_push(qp, p);
207         }
208     }
209   if (reqidp)
210     *reqidp = apevr;
211   if (prvidp)
212     *prvidp = aprel;
213 }
214
215 /* the following two functions are used in solvable_lookup_str_base to do
216  * translated lookups on the product/pattern packages
217  */
218 Id
219 find_autopattern_name(Pool *pool, Solvable *s)
220 {
221   Id prv, *prvp;
222   if (!s->provides)
223     return 0;
224   for (prvp = s->repo->idarraydata + s->provides; (prv = *prvp++) != 0; )
225     if (ISRELDEP(prv))
226       {
227         Reldep *rd = GETRELDEP(pool, prv);
228         if (rd->flags == REL_EQ && !strcmp(pool_id2str(pool, rd->name), "autopattern()"))
229           return strncmp(pool_id2str(pool, rd->evr), "pattern:", 8) != 0 ? rd->evr : 0;
230       }
231   return 0;
232 }
233
234 Id
235 find_autoproduct_name(Pool *pool, Solvable *s)
236 {
237   Id prv, *prvp;
238   if (!s->provides)
239     return 0;
240   for (prvp = s->repo->idarraydata + s->provides; (prv = *prvp++) != 0; )
241     if (ISRELDEP(prv))
242       {
243         Reldep *rd = GETRELDEP(pool, prv);
244         if (rd->flags == REL_EQ && !strcmp(pool_id2str(pool, rd->name), "autoproduct()"))
245           return strncmp(pool_id2str(pool, rd->evr), "product:", 8) != 0 ? rd->evr : 0;
246       }
247   return 0;
248 }
249
250 void
251 find_package_link(Pool *pool, Solvable *s, Id *reqidp, Queue *qr, Id *prvidp, Queue *qp)
252 {
253   const char *name = pool_id2str(pool, s->name);
254   if (name[0] == 'a' && !strncmp("application:", name, 12))
255     find_application_link(pool, s, reqidp, qr, prvidp, qp);
256   else if (name[0] == 'p' && !strncmp("pattern:", name, 7))
257     find_pattern_link(pool, s, reqidp, qr, prvidp, qp);
258   else if (name[0] == 'p' && !strncmp("product:", name, 8))
259     find_product_link(pool, s, reqidp, qr, prvidp, qp);
260 }
261
262 #endif