make pattern translations also look at the linked packages
[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
12 #include <stdio.h>
13 #include <stdlib.h>
14 #include <unistd.h>
15 #include <string.h>
16 #include <assert.h>
17
18 #include "pool.h"
19 #include "repo.h"
20 #include "linkedpkg.h"
21
22 #ifdef ENABLE_LINKED_PKGS
23
24 void
25 find_application_link(Pool *pool, Solvable *s, Id *reqidp, Queue *qr, Id *prvidp, Queue *qp)
26 {
27   Id req = 0;
28   Id prv = 0;
29   Id p, pp;
30
31   /* find appdata requires */
32   if (s->requires)
33     {
34       Id *reqp = s->repo->idarraydata + s->requires;
35       while ((req = *reqp++) != 0)            /* go through all requires */
36         {
37           if (ISRELDEP(req))
38             continue;
39           if (!strncmp("appdata(", pool_id2str(pool, req), 8))
40             break;
41         }
42     }
43   if (!req)
44     return;
45   /* find application-appdata provides */
46   if (s->provides)
47     {
48       Id *prvp = s->repo->idarraydata + s->provides;
49       while ((prv = *prvp++) != 0)            /* go through all provides */
50         {
51           if (ISRELDEP(prv))
52             continue;
53           if (strncmp("application-appdata(", pool_id2str(pool, prv), 20))
54             continue;
55           if (!strcmp(pool_id2str(pool, prv) + 12, pool_id2str(pool, req)))
56             break;
57         }
58     }
59   if (!prv)
60     return;
61   /* now link em */
62   FOR_PROVIDES(p, pp, req)
63     if (pool->solvables[p].repo == s->repo)
64       queue_push(qr, p);
65   if (reqidp)
66     *reqidp = req;
67   if (qp)
68     {
69       FOR_PROVIDES(p, pp, prv)
70         if (pool->solvables[p].repo == s->repo)
71           queue_push(qp, pp);
72       if (prvidp)
73         *prvidp = req;
74     }
75 }
76
77 void
78 find_product_link(Pool *pool, Solvable *s, Id *reqidp, Queue *qr, Id *prvidp, Queue *qp)
79 {
80   Id n = s - pool->solvables;
81   Id p, pp, namerelid;
82   char *str;
83
84   if (pool->nscallback)
85     {
86       Id buddy = pool->nscallback(pool, pool->nscallbackdata, NAMESPACE_PRODUCTBUDDY, n);
87       if (buddy > 0 && buddy != SYSTEMSOLVABLE && buddy != n && buddy < pool->nsolvables)
88         {
89           if (reqidp)
90             *reqidp = solvable_selfprovidedep(pool->solvables + buddy);
91           queue_push(qr, buddy);
92           if (prvidp)
93             *prvidp = solvable_selfprovidedep(s);
94           if (qp)
95             queue_push(qp, n);
96           return;
97         }
98     }
99   /* search for project requires */
100   namerelid = 0;
101   if (s->requires)
102     {
103       Id req, *reqp = s->repo->idarraydata + s->requires;
104       const char *nn = pool_id2str(pool, s->name);
105       int nnl = strlen(nn);
106       while ((req = *reqp++) != 0)            /* go through all requires */
107         if (ISRELDEP(req))
108           {
109             const char *rn;
110             Reldep *rd = GETRELDEP(pool, req);
111             if (rd->flags != REL_EQ || rd->evr != s->evr)
112               continue;
113             rn = pool_id2str(pool, rd->name);
114             if (!strncmp(rn, "product(", 8) && !strncmp(rn + 8, nn + 8, nnl - 8) && !strcmp( rn + nnl, ")"))
115               {
116                 namerelid = req;
117                 break;
118               }
119           }
120     }
121   if (!namerelid)
122     {
123       /* too bad. construct from scratch */
124       str = pool_tmpjoin(pool, pool_id2str(pool, s->name), ")", 0);
125       str[7] = '(';
126       namerelid = pool_rel2id(pool, pool_str2id(pool, str, 1), s->evr, REL_EQ, 1);
127     }
128   FOR_PROVIDES(p, pp, namerelid)
129     {
130       Solvable *ps = pool->solvables + p;
131       if (ps->repo != s->repo || ps->arch != s->arch)
132         continue;
133       queue_push(qr, p);
134     }
135   if (!qr->count && s->repo == pool->installed)
136     {
137       /* oh no! Look up reference file */
138       Dataiterator di;
139       const char *refbasename = solvable_lookup_str(s, PRODUCT_REFERENCEFILE);
140       dataiterator_init(&di, pool, s->repo, 0, SOLVABLE_FILELIST, refbasename, SEARCH_STRING);
141       while (dataiterator_step(&di))
142         queue_push(qr, di.solvid);
143       dataiterator_free(&di);
144       if (qp)
145         {
146           dataiterator_init(&di, pool, s->repo, 0, PRODUCT_REFERENCEFILE, refbasename, SEARCH_STRING);
147           while (dataiterator_step(&di))
148             queue_push(qp, di.solvid);
149           dataiterator_free(&di);
150         }
151     }
152   else
153     {
154       /* find qp */
155       FOR_PROVIDES(p, pp, s->name)
156         {
157           Solvable *ps = pool->solvables + p;
158           if (s->name != ps->name || ps->repo != s->repo || ps->arch != s->arch || s->evr != ps->evr)
159             continue;
160           queue_push(qp, p);
161         }
162     }
163   if (reqidp)
164     *reqidp = namerelid;
165   if (prvidp)
166     *prvidp = solvable_selfprovidedep(s);
167 }
168
169 void
170 find_pattern_link(Pool *pool, Solvable *s, Id *reqidp, Queue *qr, Id *prvidp, Queue *qp)
171 {
172   Id p, pp, *pr, apevr = 0, aprel = 0;
173
174   /* check if autopattern */
175   if (!s->provides)
176     return;
177   for (pr = s->repo->idarraydata + s->provides; (p = *pr++) != 0; )
178     if (ISRELDEP(p))
179       {
180         Reldep *rd = GETRELDEP(pool, p);
181         if (rd->flags == REL_EQ && !strcmp(pool_id2str(pool, rd->name), "autopattern()"))
182           {
183             aprel = p;
184             apevr = rd->evr;
185             break;
186           }
187       }
188   if (!apevr)
189     return;
190   FOR_PROVIDES(p, pp, apevr)
191     {
192       Solvable *s2 = pool->solvables + p;
193       if (s2->repo == s->repo && s2->name == apevr && s2->evr == s->evr && s2->vendor == s->vendor)
194         queue_push(qr, p);
195     }
196   if (qp)
197     {
198       FOR_PROVIDES(p, pp, aprel)
199         {
200           Solvable *s2 = pool->solvables + p;
201           if (s2->repo == s->repo && s2->evr == s->evr && s2->vendor == s->vendor)
202             queue_push(qp, pp);
203         }
204     }
205   if (reqidp)
206     *reqidp = apevr;
207   if (prvidp)
208     *prvidp = aprel;
209 }
210
211 Id
212 find_autopattern_name(Pool *pool, Solvable *s)
213 {
214   Id prv, *prvp;
215   if (!s->provides)
216     return 0;
217   for (prvp = s->repo->idarraydata + s->provides; (prv = *prvp++) != 0; )
218     if (ISRELDEP(prv))
219       {   
220         Reldep *rd = GETRELDEP(pool, prv);
221         if (rd->flags == REL_EQ && !strcmp(pool_id2str(pool, rd->name), "autopattern()"))
222           return strncmp(pool_id2str(pool, rd->evr), "pattern:", 8) != 0 ? rd->evr : 0;
223       }   
224   return 0;
225 }
226
227 void
228 find_package_link(Pool *pool, Solvable *s, Id *reqidp, Queue *qr, Id *prvidp, Queue *qp)
229 {
230   const char *name = pool_id2str(pool, s->name);
231   if (name[0] == 'a' && !strncmp("application:", name, 12))
232     find_application_link(pool, s, reqidp, qr, prvidp, qp);
233   else if (name[0] == 'p' && !strncmp("pattern:", name, 7))
234     find_pattern_link(pool, s, reqidp, qr, prvidp, qp);
235   else if (name[0] == 'p' && !strncmp("product:", name, 8))
236     find_product_link(pool, s, reqidp, qr, prvidp, qp);
237 }
238
239 #endif