9537a336eb87815c1da4ecb3490299ac11407082
[platform/upstream/libsolv.git] / src / suse.c
1 /*
2  * Copyright (c) 2016, SUSE LLC.
3  *
4  * This program is licensed under the BSD license, read LICENSE.BSD
5  * for further information
6  */
7
8 /* weird SUSE stuff. better not use it for your projects. */
9
10 #include <stdio.h>
11 #include <stdlib.h>
12 #include <unistd.h>
13 #include <string.h>
14
15 #include "solver.h"
16 #include "solver_private.h"
17 #include "bitmap.h"
18 #include "pool.h"
19 #include "poolvendor.h"
20 #include "util.h"
21
22 Offset
23 repo_fix_supplements(Repo *repo, Offset provides, Offset supplements, Offset freshens)
24 {
25   Pool *pool = repo->pool;
26   Id id, idp, idl;
27   char buf[1024], *p, *dep;
28   int i, l;
29
30   if (provides)
31     {
32       for (i = provides; repo->idarraydata[i]; i++)
33         {
34           id = repo->idarraydata[i];
35           if (ISRELDEP(id))
36             continue;
37           dep = (char *)pool_id2str(pool, id);
38           if (!strncmp(dep, "locale(", 7) && strlen(dep) < sizeof(buf) - 2)
39             {
40               idp = 0;
41               strcpy(buf + 2, dep);
42               dep = buf + 2 + 7;
43               if ((p = strchr(dep, ':')) != 0 && p != dep)
44                 {
45                   *p++ = 0;
46                   idp = pool_str2id(pool, dep, 1);
47                   dep = p;
48                 }
49               id = 0;
50               while ((p = strchr(dep, ';')) != 0)
51                 {
52                   if (p == dep)
53                     {
54                       dep = p + 1;
55                       continue;
56                     }
57                   *p++ = 0;
58                   idl = pool_str2id(pool, dep, 1);
59                   idl = pool_rel2id(pool, NAMESPACE_LANGUAGE, idl, REL_NAMESPACE, 1);
60                   if (id)
61                     id = pool_rel2id(pool, id, idl, REL_OR, 1);
62                   else
63                     id = idl;
64                   dep = p;
65                 }
66               if (dep[0] && dep[1])
67                 {
68                   for (p = dep; *p && *p != ')'; p++)
69                     ;
70                   *p = 0;
71                   idl = pool_str2id(pool, dep, 1);
72                   idl = pool_rel2id(pool, NAMESPACE_LANGUAGE, idl, REL_NAMESPACE, 1);
73                   if (id)
74                     id = pool_rel2id(pool, id, idl, REL_OR, 1);
75                   else
76                     id = idl;
77                 }
78               if (idp)
79                 id = pool_rel2id(pool, idp, id, REL_AND, 1);
80               if (id)
81                 supplements = repo_addid_dep(repo, supplements, id, 0);
82             }
83           else if ((p = strchr(dep, ':')) != 0 && p != dep && p[1] == '/' && strlen(dep) < sizeof(buf))
84             {
85               strcpy(buf, dep);
86               p = buf + (p - dep);
87               *p++ = 0;
88               idp = pool_str2id(pool, buf, 1);
89               /* strip trailing slashes */
90               l = strlen(p);
91               while (l > 1 && p[l - 1] == '/')
92                 p[--l] = 0;
93               id = pool_str2id(pool, p, 1);
94               id = pool_rel2id(pool, idp, id, REL_WITH, 1);
95               id = pool_rel2id(pool, NAMESPACE_SPLITPROVIDES, id, REL_NAMESPACE, 1);
96               supplements = repo_addid_dep(repo, supplements, id, 0);
97             }
98         }
99     }
100   if (supplements)
101     {
102       for (i = supplements; repo->idarraydata[i]; i++)
103         {
104           id = repo->idarraydata[i];
105           if (ISRELDEP(id))
106             continue;
107           dep = (char *)pool_id2str(pool, id);
108           if (!strncmp(dep, "system:modalias(", 16))
109             dep += 7;
110           if (!strncmp(dep, "modalias(", 9) && dep[9] && dep[10] && strlen(dep) < sizeof(buf))
111             {
112               strcpy(buf, dep);
113               p = strchr(buf + 9, ':');
114               if (p && p != buf + 9 && strchr(p + 1, ':'))
115                 {
116                   *p++ = 0;
117                   idp = pool_str2id(pool, buf + 9, 1);
118                   p[strlen(p) - 1] = 0;
119                   id = pool_str2id(pool, p, 1);
120                   id = pool_rel2id(pool, NAMESPACE_MODALIAS, id, REL_NAMESPACE, 1);
121                   id = pool_rel2id(pool, idp, id, REL_AND, 1);
122                 }
123               else
124                 {
125                   p = buf + 9;
126                   p[strlen(p) - 1] = 0;
127                   id = pool_str2id(pool, p, 1);
128                   id = pool_rel2id(pool, NAMESPACE_MODALIAS, id, REL_NAMESPACE, 1);
129                 }
130               if (id)
131                 repo->idarraydata[i] = id;
132             }
133           else if (!strncmp(dep, "packageand(", 11) && strlen(dep) < sizeof(buf))
134             {
135               strcpy(buf, dep);
136               id = 0;
137               dep = buf + 11;
138               while ((p = strchr(dep, ':')) != 0)
139                 {
140                   if (p == dep)
141                     {
142                       dep = p + 1;
143                       continue;
144                     }
145                   /* argh, allow pattern: prefix. sigh */
146                   if (p - dep == 7 && !strncmp(dep, "pattern", 7))
147                     {
148                       p = strchr(p + 1, ':');
149                       if (!p)
150                         break;
151                     }
152                   *p++ = 0;
153                   idp = pool_str2id(pool, dep, 1);
154                   if (id)
155                     id = pool_rel2id(pool, id, idp, REL_AND, 1);
156                   else
157                     id = idp;
158                   dep = p;
159                 }
160               if (dep[0] && dep[1])
161                 {
162                   dep[strlen(dep) - 1] = 0;
163                   idp = pool_str2id(pool, dep, 1);
164                   if (id)
165                     id = pool_rel2id(pool, id, idp, REL_AND, 1);
166                   else
167                     id = idp;
168                 }
169               if (id)
170                 repo->idarraydata[i] = id;
171             }
172           else if (!strncmp(dep, "filesystem(", 11) && strlen(dep) < sizeof(buf))
173             {
174               strcpy(buf, dep + 11);
175               if ((p = strrchr(buf, ')')) != 0)
176                 *p = 0;
177               id = pool_str2id(pool, buf, 1);
178               id = pool_rel2id(pool, NAMESPACE_FILESYSTEM, id, REL_NAMESPACE, 1);
179               repo->idarraydata[i] = id;
180             }
181         }
182     }
183   if (freshens && repo->idarraydata[freshens])
184     {
185       Id idsupp = 0, idfresh = 0;
186       if (!supplements || !repo->idarraydata[supplements])
187         return freshens;
188       for (i = supplements; repo->idarraydata[i]; i++)
189         {
190           if (!idsupp)
191             idsupp = repo->idarraydata[i];
192           else
193             idsupp = pool_rel2id(pool, idsupp, repo->idarraydata[i], REL_OR, 1);
194         }
195       for (i = freshens; repo->idarraydata[i]; i++)
196         {
197           if (!idfresh)
198             idfresh = repo->idarraydata[i];
199           else
200             idfresh = pool_rel2id(pool, idfresh, repo->idarraydata[i], REL_OR, 1);
201         }
202       if (!idsupp)
203         idsupp = idfresh;
204       else
205         idsupp = pool_rel2id(pool, idsupp, idfresh, REL_AND, 1);
206       supplements = repo_addid_dep(repo, 0, idsupp, 0);
207     }
208   return supplements;
209 }
210
211 Offset
212 repo_fix_conflicts(Repo *repo, Offset conflicts)
213 {
214   char buf[1024], *dep;
215   Pool *pool = repo->pool;
216   Id id;
217   int i;
218
219   if (!conflicts)
220     return conflicts;
221   for (i = conflicts; repo->idarraydata[i]; i++)
222     {
223       id = repo->idarraydata[i];
224       if (ISRELDEP(id))
225         continue;
226       dep = (char *)pool_id2str(pool, id);
227       if (!strncmp(dep, "otherproviders(", 15) && dep[15] && strlen(dep) < sizeof(buf) - 2)
228         {
229           strcpy(buf, dep + 15);
230           buf[strlen(buf) - 1] = 0;
231           id = pool_str2id(pool, buf, 1);
232           id = pool_rel2id(pool, NAMESPACE_OTHERPROVIDERS, id, REL_NAMESPACE, 1);
233           repo->idarraydata[i] = id;
234         }
235     }
236   return conflicts;
237 }
238
239 void
240 repo_rewrite_suse_deps(Solvable *s, Offset freshens)
241 {
242   s->supplements = repo_fix_supplements(s->repo, s->provides, s->supplements, freshens);
243   if (s->conflicts)
244     s->conflicts = repo_fix_conflicts(s->repo, s->conflicts);
245 }
246
247 /**********************************************************************************/
248
249 static inline Id
250 dep2name(Pool *pool, Id dep)
251 {
252   while (ISRELDEP(dep))
253     {
254       Reldep *rd = GETRELDEP(pool, dep);
255       dep = rd->name;
256     }
257   return dep;
258 }
259
260 static int
261 providedbyinstalled_multiversion(Pool *pool, Map *installed, Id n, Id con)
262 {
263   Id p, pp;
264   Solvable *sn = pool->solvables + n;
265
266   FOR_PROVIDES(p, pp, sn->name)
267     {
268       Solvable *s = pool->solvables + p;
269       if (s->name != sn->name || s->arch != sn->arch)
270         continue;
271       if (!MAPTST(installed, p))
272         continue;
273       if (pool_match_nevr(pool, pool->solvables + p, con))
274         continue;
275       return 1;         /* found installed package that doesn't conflict */
276     }
277   return 0;
278 }
279
280 static inline int
281 providedbyinstalled(Pool *pool, Map *installed, Id dep, int ispatch, Map *multiversionmap)
282 {
283   Id p, pp;
284   FOR_PROVIDES(p, pp, dep)
285     {
286       if (p == SYSTEMSOLVABLE)
287         return -1;
288       if (ispatch && !pool_match_nevr(pool, pool->solvables + p, dep))
289         continue;
290       if (ispatch && multiversionmap && multiversionmap->size && MAPTST(multiversionmap, p) && ISRELDEP(dep))
291         if (providedbyinstalled_multiversion(pool, installed, p, dep))
292           continue;
293       if (MAPTST(installed, p))
294         return 1;
295     }
296   return 0;
297 }
298
299 /* xmap:
300  *  1: installed
301  *  2: conflicts with installed
302  *  8: interesting (only true if installed)
303  * 16: undecided
304  */
305
306 static int
307 providedbyinstalled_multiversion_xmap(Pool *pool, unsigned char *map, Id n, Id con) 
308 {
309   Id p, pp;
310   Solvable *sn = pool->solvables + n; 
311
312   FOR_PROVIDES(p, pp, sn->name)
313     {    
314       Solvable *s = pool->solvables + p; 
315       if (s->name != sn->name || s->arch != sn->arch)
316         continue;
317       if ((map[p] & 9) != 9)
318         continue;
319       if (pool_match_nevr(pool, pool->solvables + p, con))
320         continue;
321       return 1;         /* found installed package that doesn't conflict */
322     }    
323   return 0;
324 }
325
326
327 static inline int
328 providedbyinstalled_xmap(Pool *pool, unsigned char *map, Id dep, int ispatch, Map *multiversionmap)
329 {
330   Id p, pp;
331   int r = 0; 
332   FOR_PROVIDES(p, pp, dep) 
333     {    
334       if (p == SYSTEMSOLVABLE)
335         return 1;       /* always boring, as never constraining */
336       if (ispatch && !pool_match_nevr(pool, pool->solvables + p, dep))
337         continue;
338       if (ispatch && multiversionmap && multiversionmap->size && MAPTST(multiversionmap, p) && ISRELDEP(dep))
339         if (providedbyinstalled_multiversion_xmap(pool, map, p, dep))
340           continue;
341       if ((map[p] & 9) == 9)
342         return 9;
343       r |= map[p] & 17;
344     }    
345   return r;
346 }
347
348 /* FIXME: this mirrors policy_illegal_vendorchange */
349 static int
350 pool_illegal_vendorchange(Pool *pool, Solvable *s1, Solvable *s2)
351 {
352   Id v1, v2;
353   Id vendormask1, vendormask2;
354
355   if (pool->custom_vendorcheck)
356     return pool->custom_vendorcheck(pool, s1, s2);
357   /* treat a missing vendor as empty string */
358   v1 = s1->vendor ? s1->vendor : ID_EMPTY;
359   v2 = s2->vendor ? s2->vendor : ID_EMPTY;
360   if (v1 == v2)
361     return 0;
362   vendormask1 = pool_vendor2mask(pool, v1);
363   if (!vendormask1)
364     return 1;   /* can't match */
365   vendormask2 = pool_vendor2mask(pool, v2);
366   if ((vendormask1 & vendormask2) != 0)
367     return 0;
368   return 1;     /* no class matches */
369 }
370
371 /* check if this patch is relevant according to the vendor. To bad that patches
372  * don't have a vendor, so we need to do some careful repo testing. */
373 int
374 solvable_is_irrelevant_patch(Solvable *s, Map *installedmap)
375 {
376   Pool *pool = s->repo->pool;
377   Id con, *conp;
378   int hadpatchpackage = 0;
379
380   if (!s->conflicts)
381     return 0;
382   conp = s->repo->idarraydata + s->conflicts;
383   while ((con = *conp++) != 0)
384     {
385       Reldep *rd;
386       Id p, pp, p2, pp2;
387       if (!ISRELDEP(con))
388         continue;
389       rd = GETRELDEP(pool, con);
390       if (rd->flags != REL_LT)
391         continue;
392       FOR_PROVIDES(p, pp, con)
393         {
394           Solvable *si;
395           if (!MAPTST(installedmap, p))
396             continue;
397           si = pool->solvables + p;
398           if (!pool_match_nevr(pool, si, con))
399             continue;
400           FOR_PROVIDES(p2, pp2, rd->name)
401             {
402               Solvable *s2 = pool->solvables + p2;
403               if (!pool_match_nevr(pool, s2, rd->name))
404                 continue;
405               if (pool_match_nevr(pool, s2, con))
406                 continue;       /* does not fulfill patch */
407               if (s2->repo == s->repo)
408                 {
409                   hadpatchpackage = 1;
410                   /* ok, we have a package from the patch repo that solves the conflict. check vendor */
411                   if (si->vendor == s2->vendor)
412                     return 0;
413                   if (!pool_illegal_vendorchange(pool, si, s2))
414                     return 0;
415                   /* vendor change was illegal, ignore conflict */
416                 }
417             }
418         }
419     }
420   /* if we didn't find a patchpackage don't claim that the patch is irrelevant */
421   if (!hadpatchpackage)
422     return 0;
423   return 1;
424 }
425
426 /*
427  * solvable_trivial_installable_map - answers if a solvable is installable
428  * without any other installs/deinstalls.
429  * The packages considered to be installed are provided via the
430  * installedmap bitmap. A additional "conflictsmap" bitmap providing
431  * information about the conflicts of the installed packages can be
432  * used for extra speed up. Provide a NULL pointer if you do not
433  * have this information.
434  * Both maps can be created with pool_create_state_maps() or
435  * solver_create_state_maps().
436  *
437  * returns:
438  * 1:  solvable is installable without any other package changes
439  * 0:  solvable is not installable
440  * -1: solvable is installable, but doesn't constrain any installed packages
441  */
442 int
443 solvable_trivial_installable_map(Solvable *s, Map *installedmap, Map *conflictsmap, Map *multiversionmap)
444 {
445   Pool *pool = s->repo->pool;
446   Solvable *s2;
447   Id p, *dp;
448   Id *reqp, req;
449   Id *conp, con;
450   int r, interesting = 0;
451
452   if (conflictsmap && MAPTST(conflictsmap, s - pool->solvables))
453     return 0;
454   if (s->requires)
455     {
456       reqp = s->repo->idarraydata + s->requires;
457       while ((req = *reqp++) != 0)
458         {
459           if (req == SOLVABLE_PREREQMARKER)
460             continue;
461           r = providedbyinstalled(pool, installedmap, req, 0, 0);
462           if (!r)
463             return 0;
464           if (r > 0)
465             interesting = 1;
466         }
467     }
468   if (s->conflicts)
469     {
470       int ispatch = 0;
471
472       if (!strncmp("patch:", pool_id2str(pool, s->name), 6))
473         ispatch = 1;
474       conp = s->repo->idarraydata + s->conflicts;
475       while ((con = *conp++) != 0)
476         {
477           if (providedbyinstalled(pool, installedmap, con, ispatch, multiversionmap))
478             {
479               if (ispatch && solvable_is_irrelevant_patch(s, installedmap))
480                 return -1;
481               return 0;
482             }
483           if (!interesting && ISRELDEP(con))
484             {
485               con = dep2name(pool, con);
486               if (providedbyinstalled(pool, installedmap, con, ispatch, multiversionmap))
487                 interesting = 1;
488             }
489         }
490       if (ispatch && interesting && solvable_is_irrelevant_patch(s, installedmap))
491         interesting = 0;
492     }
493   if (!conflictsmap)
494     {
495       int i;
496
497       p = s - pool->solvables;
498       for (i = 1; i < pool->nsolvables; i++)
499         {
500           if (!MAPTST(installedmap, i))
501             continue;
502           s2 = pool->solvables + i;
503           if (!s2->conflicts)
504             continue;
505           conp = s2->repo->idarraydata + s2->conflicts;
506           while ((con = *conp++) != 0)
507             {
508               dp = pool_whatprovides_ptr(pool, con);
509               for (; *dp; dp++)
510                 if (*dp == p)
511                   return 0;
512             }
513         }
514      }
515   return interesting ? 1 : -1;
516 }
517
518 /*
519  * different interface for solvable_trivial_installable_map, where
520  * the information about the installed packages is provided
521  * by a queue.
522  */
523 int
524 solvable_trivial_installable_queue(Solvable *s, Queue *installed, Map *multiversionmap)
525 {
526   Pool *pool = s->repo->pool;
527   int i;
528   Id p;
529   Map installedmap;
530   int r;
531
532   map_init(&installedmap, pool->nsolvables);
533   for (i = 0; i < installed->count; i++)
534     {
535       p = installed->elements[i];
536       if (p > 0)                /* makes it work with decisionq */
537         MAPSET(&installedmap, p);
538     }
539   r = solvable_trivial_installable_map(s, &installedmap, 0, multiversionmap);
540   map_free(&installedmap);
541   return r;
542 }
543
544 /*
545  * different interface for solvable_trivial_installable_map, where
546  * the information about the installed packages is provided
547  * by a repo containing the installed solvables.
548  */
549 int
550 solvable_trivial_installable_repo(Solvable *s, Repo *installed, Map *multiversionmap)
551 {
552   Pool *pool = s->repo->pool;
553   Id p;
554   Solvable *s2;
555   Map installedmap;
556   int r;
557
558   map_init(&installedmap, pool->nsolvables);
559   FOR_REPO_SOLVABLES(installed, p, s2)
560     MAPSET(&installedmap, p);
561   r = solvable_trivial_installable_map(s, &installedmap, 0, multiversionmap);
562   map_free(&installedmap);
563   return r;
564 }
565
566 /*
567  * pool_trivial_installable - calculate if a set of solvables is
568  * trivial installable without any other installs/deinstalls of
569  * packages not belonging to the set.
570  *
571  * the state is returned in the result queue:
572  * 1:  solvable is installable without any other package changes
573  * 0:  solvable is not installable
574  * -1: solvable is installable, but doesn't constrain any installed packages
575  */
576
577 void
578 pool_trivial_installable_multiversionmap(Pool *pool, Map *installedmap, Queue *pkgs, Queue *res, Map *multiversionmap)
579 {
580   int i, r, m, did;
581   Id p, *dp, con, *conp, req, *reqp;
582   unsigned char *map;
583   Solvable *s;
584
585   map = solv_calloc(pool->nsolvables, 1);
586   for (p = 1; p < pool->nsolvables; p++)
587     {
588       if (!MAPTST(installedmap, p))
589         continue;
590       map[p] |= 9;
591       s = pool->solvables + p;
592       if (!s->conflicts)
593         continue;
594       conp = s->repo->idarraydata + s->conflicts;
595       while ((con = *conp++) != 0)
596         {
597           dp = pool_whatprovides_ptr(pool, con);
598           for (; *dp; dp++)
599             map[p] |= 2;        /* XXX: self conflict ? */
600         }
601     }
602   for (i = 0; i < pkgs->count; i++)
603     map[pkgs->elements[i]] = 16;
604
605   for (i = 0, did = 0; did < pkgs->count; i++, did++)
606     {
607       if (i == pkgs->count)
608         i = 0;
609       p = pkgs->elements[i];
610       if ((map[p] & 16) == 0)
611         continue;
612       if ((map[p] & 2) != 0)
613         {
614           map[p] = 2;
615           continue;
616         }
617       s = pool->solvables + p;
618       m = 1;
619       if (s->requires)
620         {
621           reqp = s->repo->idarraydata + s->requires;
622           while ((req = *reqp++) != 0)
623             {
624               if (req == SOLVABLE_PREREQMARKER)
625                 continue;
626               r = providedbyinstalled_xmap(pool, map, req, 0, 0);
627               if (!r)
628                 {
629                   /* decided and miss */
630                   map[p] = 2;
631                   did = 0;
632                   break;
633                 }
634               if (r == 16)
635                 break;  /* undecided */
636               m |= r;   /* 1 | 9 | 17 */
637             }
638           if (req)
639             continue;
640           if ((m & 9) == 9)
641             m = 9;
642         }
643       if (s->conflicts)
644         {
645           int ispatch = 0;      /* see solver.c patch handling */
646
647           if (!strncmp("patch:", pool_id2str(pool, s->name), 6))
648             ispatch = 1;
649           conp = s->repo->idarraydata + s->conflicts;
650           while ((con = *conp++) != 0)
651             {
652               if ((providedbyinstalled_xmap(pool, map, con, ispatch, multiversionmap) & 1) != 0)
653                 {
654                   map[p] = 2;
655                   did = 0;
656                   break;
657                 }
658               if ((m == 1 || m == 17) && ISRELDEP(con))
659                 {
660                   con = dep2name(pool, con);
661                   if ((providedbyinstalled_xmap(pool, map, con, ispatch, multiversionmap) & 1) != 0)
662                     m = 9;
663                 }
664             }
665           if (con)
666             continue;   /* found a conflict */
667         }
668       if (m != map[p])
669         {
670           map[p] = m;
671           did = 0;
672         }
673     }
674   queue_free(res);
675   queue_init_clone(res, pkgs);
676   for (i = 0; i < pkgs->count; i++)
677     {
678       m = map[pkgs->elements[i]];
679       if ((m & 9) == 9)
680         r = 1;
681       else if (m & 1)
682         r = -1;
683       else
684         r = 0;
685       res->elements[i] = r;
686     }
687   free(map);
688 }
689
690 void
691 pool_trivial_installable(Pool *pool, Map *installedmap, Queue *pkgs, Queue *res)
692 {
693   pool_trivial_installable_multiversionmap(pool, installedmap, pkgs, res, 0);
694 }
695
696 void
697 solver_trivial_installable(Solver *solv, Queue *pkgs, Queue *res)
698 {
699   Pool *pool = solv->pool;
700   Map installedmap;
701   int i;
702   pool_create_state_maps(pool,  &solv->decisionq, &installedmap, 0);
703   pool_trivial_installable_multiversionmap(pool, &installedmap, pkgs, res, solv->multiversion.size ? &solv->multiversion : 0);
704   for (i = 0; i < res->count; i++) 
705     if (res->elements[i] != -1)
706       {    
707         Solvable *s = pool->solvables + pkgs->elements[i];
708         if (!strncmp("patch:", pool_id2str(pool, s->name), 6) && solvable_is_irrelevant_patch(s, &installedmap))
709           res->elements[i] = -1;
710       }    
711   map_free(&installedmap);
712 }
713
714 void
715 solver_printtrivial(Solver *solv)
716 {
717   Pool *pool = solv->pool;
718   Queue in, out;
719   Id p;
720   const char *n; 
721   Solvable *s; 
722   int i;
723
724   queue_init(&in);
725   for (p = 1, s = pool->solvables + p; p < solv->pool->nsolvables; p++, s++)
726     {   
727       n = pool_id2str(pool, s->name);
728       if (strncmp(n, "patch:", 6) != 0 && strncmp(n, "pattern:", 8) != 0)
729         continue;
730       queue_push(&in, p); 
731     }   
732   if (!in.count)
733     {   
734       queue_free(&in);
735       return;
736     }   
737   queue_init(&out);
738   solver_trivial_installable(solv, &in, &out);
739   POOL_DEBUG(SOLV_DEBUG_RESULT, "trivial installable status:\n");
740   for (i = 0; i < in.count; i++)
741     POOL_DEBUG(SOLV_DEBUG_RESULT, "  %s: %d\n", pool_solvid2str(pool, in.elements[i]), out.elements[i]);
742   POOL_DEBUG(SOLV_DEBUG_RESULT, "\n");
743   queue_free(&in);
744   queue_free(&out);
745 }
746
747