trivial_installable: check vendor of affected package to see if a patch should be...
[platform/upstream/libsolv.git] / src / solvable.c
1 /*
2  * Copyright (c) 2008, Novell Inc.
3  *
4  * This program is licensed under the BSD license, read LICENSE.BSD
5  * for further information
6  */
7
8 /*
9  * solvable.c
10  *
11  * set/retrieve data from solvables
12  */
13
14 #include <stdio.h>
15 #include <stdlib.h>
16 #include <stdarg.h>
17 #include <unistd.h>
18 #include <string.h>
19
20 #include "pool.h"
21 #include "repo.h"
22 #include "util.h"
23 #include "policy.h"
24 #include "poolvendor.h"
25 #include "chksum.h"
26
27 const char *
28 pool_solvable2str(Pool *pool, Solvable *s)
29 {
30   const char *n, *e, *a;
31   int nl, el, al;
32   char *p;
33   n = pool_id2str(pool, s->name);
34   e = pool_id2str(pool, s->evr);
35   /* XXX: may want to skip the epoch here */
36   a = pool_id2str(pool, s->arch);
37   nl = strlen(n);
38   el = strlen(e);
39   al = strlen(a);
40   if (pool->havedistepoch)
41     {
42       /* strip the distepoch from the evr */
43       const char *de = strrchr(e, '-');
44       if (de && (de = strchr(de, ':')) != 0)
45         el = de - e;
46     }
47   p = pool_alloctmpspace(pool, nl + el + al + 3);
48   strcpy(p, n);
49   p[nl] = '-';
50   strncpy(p + nl + 1, e, el);
51   p[nl + 1 + el] = '.';
52   strcpy(p + nl + 1 + el + 1, a);
53   return p;
54 }
55
56 Id
57 solvable_lookup_type(Solvable *s, Id keyname)
58 {
59   if (!s->repo)
60     return 0;
61   return repo_lookup_type(s->repo, s - s->repo->pool->solvables, keyname);
62 }
63
64 Id
65 solvable_lookup_id(Solvable *s, Id keyname)
66 {
67   if (!s->repo)
68     return 0;
69   return repo_lookup_id(s->repo, s - s->repo->pool->solvables, keyname);
70 }
71
72 int
73 solvable_lookup_idarray(Solvable *s, Id keyname, Queue *q)
74 {
75   if (!s->repo)
76     {
77       queue_empty(q);
78       return 0;
79     }
80   return repo_lookup_idarray(s->repo, s - s->repo->pool->solvables, keyname, q);
81 }
82
83 int
84 solvable_lookup_deparray(Solvable *s, Id keyname, Queue *q, Id marker)
85 {
86   if (!s->repo)
87     {
88       queue_empty(q);
89       return 0;
90     }
91   return repo_lookup_deparray(s->repo, s - s->repo->pool->solvables, keyname, q, marker);
92 }
93
94 const char *
95 solvable_lookup_str(Solvable *s, Id keyname)
96 {
97   if (!s->repo)
98     return 0;
99   return repo_lookup_str(s->repo, s - s->repo->pool->solvables, keyname);
100 }
101
102 static const char *
103 solvable_lookup_str_base(Solvable *s, Id keyname, Id basekeyname, int usebase)
104 {
105   Pool *pool;
106   const char *str, *basestr;
107   Id p, pp;
108   Solvable *s2;
109   int pass;
110
111   if (!s->repo)
112     return 0;
113   pool = s->repo->pool;
114   str = solvable_lookup_str(s, keyname);
115   if (str || keyname == basekeyname)
116     return str;
117   basestr = solvable_lookup_str(s, basekeyname);
118   if (!basestr)
119     return 0;
120   /* search for a solvable with same name and same base that has the
121    * translation */
122   if (!pool->whatprovides)
123     return usebase ? basestr : 0;
124   /* we do this in two passes, first same vendor, then all other vendors */
125   for (pass = 0; pass < 2; pass++)
126     {
127       FOR_PROVIDES(p, pp, s->name)
128         {
129           s2 = pool->solvables + p;
130           if (s2->name != s->name)
131             continue;
132           if ((s->vendor == s2->vendor) != (pass == 0))
133             continue;
134           str = solvable_lookup_str(s2, basekeyname);
135           if (!str || strcmp(str, basestr))
136             continue;
137           str = solvable_lookup_str(s2, keyname);
138           if (str)
139             return str;
140         }
141     }
142   return usebase ? basestr : 0;
143 }
144
145 const char *
146 solvable_lookup_str_poollang(Solvable *s, Id keyname)
147 {
148   Pool *pool;
149   int i, cols;
150   const char *str;
151   Id *row;
152
153   if (!s->repo)
154     return 0;
155   pool = s->repo->pool;
156   if (!pool->nlanguages)
157     return solvable_lookup_str(s, keyname);
158   cols = pool->nlanguages + 1;
159   if (!pool->languagecache)
160     {
161       pool->languagecache = solv_calloc(cols * ID_NUM_INTERNAL, sizeof(Id));
162       pool->languagecacheother = 0;
163     }
164   if (keyname >= ID_NUM_INTERNAL)
165     {
166       row = pool->languagecache + ID_NUM_INTERNAL * cols;
167       for (i = 0; i < pool->languagecacheother; i++, row += cols)
168         if (*row == keyname)
169           break;
170       if (i >= pool->languagecacheother)
171         {
172           pool->languagecache = solv_realloc2(pool->languagecache, pool->languagecacheother + 1, cols * sizeof(Id));
173           row = pool->languagecache + cols * (ID_NUM_INTERNAL + pool->languagecacheother++);
174           *row = keyname;
175         }
176     }
177   else
178     row = pool->languagecache + keyname * cols;
179   row++;        /* skip keyname */
180   for (i = 0; i < pool->nlanguages; i++, row++)
181     {
182       if (!*row)
183         *row = pool_id2langid(pool, keyname, pool->languages[i], 1);
184       str = solvable_lookup_str_base(s, *row, keyname, 0);
185       if (str)
186         return str;
187     }
188   return solvable_lookup_str(s, keyname);
189 }
190
191 const char *
192 solvable_lookup_str_lang(Solvable *s, Id keyname, const char *lang, int usebase)
193 {
194   if (s->repo)
195     {
196       Id id = pool_id2langid(s->repo->pool, keyname, lang, 0);
197       if (id)
198         return solvable_lookup_str_base(s, id, keyname, usebase);
199       if (!usebase)
200         return 0;
201     }
202   return solvable_lookup_str(s, keyname);
203 }
204
205 unsigned long long
206 solvable_lookup_num(Solvable *s, Id keyname, unsigned long long notfound)
207 {
208   if (!s->repo)
209     return notfound;
210   return repo_lookup_num(s->repo, s - s->repo->pool->solvables, keyname, notfound);
211 }
212
213 unsigned int
214 solvable_lookup_sizek(Solvable *s, Id keyname, unsigned int notfound)
215 {
216   unsigned long long size;
217   if (!s->repo)
218     return notfound;
219   size = solvable_lookup_num(s, keyname, (unsigned long long)notfound << 10);
220   return (unsigned int)((size + 1023) >> 10);
221 }
222
223 int
224 solvable_lookup_void(Solvable *s, Id keyname)
225 {
226   if (!s->repo)
227     return 0;
228   return repo_lookup_void(s->repo, s - s->repo->pool->solvables, keyname);
229 }
230
231 int
232 solvable_lookup_bool(Solvable *s, Id keyname)
233 {
234   if (!s->repo)
235     return 0;
236   /* historic nonsense: there are two ways of storing a bool, as num == 1 or void. test both. */
237   if (repo_lookup_type(s->repo, s - s->repo->pool->solvables, keyname) == REPOKEY_TYPE_VOID)
238     return 1;
239   return repo_lookup_num(s->repo, s - s->repo->pool->solvables, keyname, 0) == 1;
240 }
241
242 const unsigned char *
243 solvable_lookup_bin_checksum(Solvable *s, Id keyname, Id *typep)
244 {
245   Repo *repo = s->repo;
246
247   if (!repo)
248     {
249       *typep = 0;
250       return 0;
251     }
252   return repo_lookup_bin_checksum(repo, s - repo->pool->solvables, keyname, typep);
253 }
254
255 const char *
256 solvable_lookup_checksum(Solvable *s, Id keyname, Id *typep)
257 {
258   const unsigned char *chk = solvable_lookup_bin_checksum(s, keyname, typep);
259   return chk ? pool_bin2hex(s->repo->pool, chk, solv_chksum_len(*typep)) : 0;
260 }
261
262 static inline const char *
263 evrid2vrstr(Pool *pool, Id evrid)
264 {
265   const char *p, *evr = pool_id2str(pool, evrid);
266   if (!evr)
267     return evr;
268   for (p = evr; *p >= '0' && *p <= '9'; p++)
269     ;
270   return p != evr && *p == ':' && p[1] ? p + 1 : evr;
271 }
272
273 const char *
274 solvable_lookup_location(Solvable *s, unsigned int *medianrp)
275 {
276   Pool *pool;
277   int l = 0;
278   char *loc;
279   const char *mediadir, *mediafile;
280
281   if (medianrp)
282     *medianrp = 0;
283   if (!s->repo)
284     return 0;
285   pool = s->repo->pool;
286   if (medianrp)
287     *medianrp = solvable_lookup_num(s, SOLVABLE_MEDIANR, 0);
288   if (solvable_lookup_void(s, SOLVABLE_MEDIADIR))
289     mediadir = pool_id2str(pool, s->arch);
290   else
291     mediadir = solvable_lookup_str(s, SOLVABLE_MEDIADIR);
292   if (mediadir)
293     l = strlen(mediadir) + 1;
294   if (solvable_lookup_void(s, SOLVABLE_MEDIAFILE))
295     {
296       const char *name, *evr, *arch;
297       name = pool_id2str(pool, s->name);
298       evr = evrid2vrstr(pool, s->evr);
299       arch = pool_id2str(pool, s->arch);
300       /* name-vr.arch.rpm */
301       loc = pool_alloctmpspace(pool, l + strlen(name) + strlen(evr) + strlen(arch) + 7);
302       if (mediadir)
303         sprintf(loc, "%s/%s-%s.%s.rpm", mediadir, name, evr, arch);
304       else
305         sprintf(loc, "%s-%s.%s.rpm", name, evr, arch);
306     }
307   else
308     {
309       mediafile = solvable_lookup_str(s, SOLVABLE_MEDIAFILE);
310       if (!mediafile)
311         return 0;
312       loc = pool_alloctmpspace(pool, l + strlen(mediafile) + 1);
313       if (mediadir)
314         sprintf(loc, "%s/%s", mediadir, mediafile);
315       else
316         strcpy(loc, mediafile);
317     }
318   return loc;
319 }
320
321 const char *
322 solvable_get_location(Solvable *s, unsigned int *medianrp)
323 {
324   const char *loc = solvable_lookup_location(s, medianrp);
325   if (medianrp && *medianrp == 0)
326     *medianrp = 1;      /* compat, to be removed */
327   return loc;
328 }
329
330 const char *
331 solvable_lookup_sourcepkg(Solvable *s)
332 {
333   Pool *pool;
334   const char *evr, *name;
335   Id archid;
336
337   if (!s->repo)
338     return 0;
339   pool = s->repo->pool;
340   if (solvable_lookup_void(s, SOLVABLE_SOURCENAME))
341     name = pool_id2str(pool, s->name);
342   else
343     name = solvable_lookup_str(s, SOLVABLE_SOURCENAME);
344   if (!name)
345     return 0;
346   archid = solvable_lookup_id(s, SOLVABLE_SOURCEARCH);
347   if (solvable_lookup_void(s, SOLVABLE_SOURCEEVR))
348     evr = evrid2vrstr(pool, s->evr);
349   else
350     evr = solvable_lookup_str(s, SOLVABLE_SOURCEEVR);
351   if (archid == ARCH_SRC || archid == ARCH_NOSRC)
352     {
353       char *str;
354       str = pool_tmpjoin(pool, name, evr ? "-" : 0, evr);
355       str = pool_tmpappend(pool, str, ".", pool_id2str(pool, archid));
356       return pool_tmpappend(pool, str, ".rpm", 0);
357     }
358   else 
359     return name;        /* FIXME */
360 }
361
362
363 /*****************************************************************************/
364
365 static inline Id dep2name(Pool *pool, Id dep)
366 {
367   while (ISRELDEP(dep))
368     {
369       Reldep *rd = rd = GETRELDEP(pool, dep);
370       dep = rd->name;
371     }
372   return dep;
373 }
374
375 static int providedbyinstalled_multiversion(Pool *pool, Map *installed, Id n, Id con) 
376 {
377   Id p, pp;
378   Solvable *sn = pool->solvables + n; 
379
380   FOR_PROVIDES(p, pp, sn->name)
381     {    
382       Solvable *s = pool->solvables + p; 
383       if (s->name != sn->name || s->arch != sn->arch)
384         continue;
385       if (!MAPTST(installed, p))
386         continue;
387       if (pool_match_nevr(pool, pool->solvables + p, con))
388         continue;
389       return 1;         /* found installed package that doesn't conflict */
390     }    
391   return 0;
392 }
393
394 static inline int providedbyinstalled(Pool *pool, Map *installed, Id dep, int ispatch, Map *noobsoletesmap)
395 {
396   Id p, pp;
397   FOR_PROVIDES(p, pp, dep)
398     {
399       if (p == SYSTEMSOLVABLE)
400         return -1;
401       if (ispatch && !pool_match_nevr(pool, pool->solvables + p, dep))
402         continue;
403       if (ispatch && noobsoletesmap && noobsoletesmap->size && MAPTST(noobsoletesmap, p) && ISRELDEP(dep))
404         if (providedbyinstalled_multiversion(pool, installed, p, dep))
405           continue;
406       if (MAPTST(installed, p))
407         return 1;
408     }
409   return 0;
410 }
411
412 /*
413  * solvable_trivial_installable_map - anwers is a solvable is installable
414  * without any other installs/deinstalls.
415  * The packages considered to be installed are provided via the
416  * installedmap bitmap. A additional "conflictsmap" bitmap providing
417  * information about the conflicts of the installed packages can be
418  * used for extra speed up. Provide a NULL pointer if you do not
419  * have this information.
420  * Both maps can be created with pool_create_state_maps() or
421  * solver_create_state_maps().
422  *
423  * returns:
424  * 1:  solvable is installable without any other package changes
425  * 0:  solvable is not installable
426  * -1: solvable is installable, but doesn't constrain any installed packages
427  */
428 int
429 solvable_trivial_installable_map(Solvable *s, Map *installedmap, Map *conflictsmap, Map *noobsoletesmap)
430 {
431   Pool *pool = s->repo->pool;
432   Solvable *s2;
433   Id p, *dp;
434   Id *reqp, req;
435   Id *conp, con;
436   int r, interesting = 0;
437
438   if (conflictsmap && MAPTST(conflictsmap, s - pool->solvables))
439     return 0;
440   if (s->requires)
441     {
442       reqp = s->repo->idarraydata + s->requires;
443       while ((req = *reqp++) != 0)
444         {
445           if (req == SOLVABLE_PREREQMARKER)
446             continue;
447           r = providedbyinstalled(pool, installedmap, req, 0, 0);
448           if (!r)
449             return 0;
450           if (r > 0)
451             interesting = 1;
452         }
453     }
454   if (s->conflicts)
455     {
456       int ispatch = 0;
457
458       if (!strncmp("patch:", pool_id2str(pool, s->name), 6))
459         ispatch = 1;
460       conp = s->repo->idarraydata + s->conflicts;
461       while ((con = *conp++) != 0)
462         {
463           if (providedbyinstalled(pool, installedmap, con, ispatch, noobsoletesmap))
464             {
465               if (ispatch && solvable_is_irrelevant_patch(s, installedmap, 0))
466                 return -1;
467               return 0;
468             }
469           if (!interesting && ISRELDEP(con))
470             {
471               con = dep2name(pool, con);
472               if (providedbyinstalled(pool, installedmap, con, ispatch, noobsoletesmap))
473                 interesting = 1;
474             }
475         }
476       if (ispatch && interesting && solvable_is_irrelevant_patch(s, installedmap, 0))
477         interesting = 0;
478     }
479 #if 0
480   if (s->repo)
481     {
482       Id *obsp, obs;
483       Repo *installed = 0;
484       if (s->obsoletes && s->repo != installed)
485         {
486           obsp = s->repo->idarraydata + s->obsoletes;
487           while ((obs = *obsp++) != 0)
488             {
489               if (providedbyinstalled(pool, installedmap, obs, 0, 0))
490                 return 0;
491             }
492         }
493       if (s->repo != installed)
494         {
495           Id pp;
496           FOR_PROVIDES(p, pp, s->name)
497             {
498               s2 = pool->solvables + p;
499               if (s2->repo == installed && s2->name == s->name)
500                 return 0;
501             }
502         }
503     }
504 #endif
505   if (!conflictsmap)
506     {
507       int i;
508
509       p = s - pool->solvables;
510       for (i = 1; i < pool->nsolvables; i++)
511         {
512           if (!MAPTST(installedmap, i))
513             continue;
514           s2 = pool->solvables + i;
515           if (!s2->conflicts)
516             continue;
517           conp = s2->repo->idarraydata + s2->conflicts;
518           while ((con = *conp++) != 0)
519             {
520               dp = pool_whatprovides_ptr(pool, con);
521               for (; *dp; dp++)
522                 if (*dp == p)
523                   return 0;
524             }
525         }
526      }
527   return interesting ? 1 : -1;
528 }
529
530 /*
531  * different interface for solvable_trivial_installable_map, where
532  * the information about the installed packages is provided
533  * by a queue.
534  */
535 int
536 solvable_trivial_installable_queue(Solvable *s, Queue *installed, Map *noobsoletesmap)
537 {
538   Pool *pool = s->repo->pool;
539   int i;
540   Id p;
541   Map installedmap;
542   int r;
543
544   map_init(&installedmap, pool->nsolvables);
545   for (i = 0; i < installed->count; i++)
546     {
547       p = installed->elements[i];
548       if (p > 0)                /* makes it work with decisionq */
549         MAPSET(&installedmap, p);
550     }
551   r = solvable_trivial_installable_map(s, &installedmap, 0, noobsoletesmap);
552   map_free(&installedmap);
553   return r;
554 }
555
556 /*
557  * different interface for solvable_trivial_installable_map, where
558  * the information about the installed packages is provided
559  * by a repo containing the installed solvables.
560  */
561 int
562 solvable_trivial_installable_repo(Solvable *s, Repo *installed, Map *noobsoletesmap)
563 {
564   Pool *pool = s->repo->pool;
565   Id p;
566   Solvable *s2;
567   Map installedmap;
568   int r;
569
570   map_init(&installedmap, pool->nsolvables);
571   FOR_REPO_SOLVABLES(installed, p, s2)
572     MAPSET(&installedmap, p);
573   r = solvable_trivial_installable_map(s, &installedmap, 0, noobsoletesmap);
574   map_free(&installedmap);
575   return r;
576 }
577
578
579 /* check if this patch is relevant according to the vendor. To bad that patches
580  * don't have a vendor, so we need to do some careful repo testing. */
581 int
582 solvable_is_irrelevant_patch(Solvable *s, Map *installedmap, Solver *solv)
583 {
584   Pool *pool = s->repo->pool;
585   Id con, *conp;
586   int hadpatchpackage = 0;
587
588   if (!s->conflicts)
589     return 0;
590   conp = s->repo->idarraydata + s->conflicts;
591   while ((con = *conp++) != 0)
592     {
593       Reldep *rd;
594       Id p, pp, p2, pp2;
595       if (!ISRELDEP(con))
596         continue;
597       rd = GETRELDEP(pool, con);
598       if (rd->flags != REL_LT)
599         continue;
600       FOR_PROVIDES(p, pp, con)
601         {
602           Solvable *si;
603           if (!MAPTST(installedmap, p))
604             continue;
605           si = pool->solvables + p;
606           if (!pool_match_nevr(pool, si, con))
607             continue;
608           FOR_PROVIDES(p2, pp2, rd->name)
609             {
610               Solvable *s2 = pool->solvables + p2;
611               if (!pool_match_nevr(pool, s2, rd->name))
612                 continue;
613               if (pool_match_nevr(pool, s2, con))
614                 continue;       /* does not fulfill patch */
615               if (s2->repo == s->repo)
616                 {
617                   hadpatchpackage = 1;
618                   /* ok, we have a package from the patch repo that solves the conflict. check vendor */
619                   if (si->vendor == s2->vendor)
620                     return 0;
621                   /* FIXME: solv is only needed for the vendorchange callback */
622                   if (solv)
623                     {
624                       if (!policy_illegal_vendorchange(solv, si, s2))
625                         return 0;
626                     }
627                   else
628                     {
629                       Id v1 = si->vendor ? si->vendor : ID_EMPTY;
630                       Id v2 = s2->vendor ? s2->vendor : ID_EMPTY;
631                       if (v1 == v2)
632                         return 0;
633                       v1 = pool_vendor2mask(pool, v1);
634                       v2 = pool_vendor2mask(pool, v2);
635                       if ((v1 & v2) != 0)
636                         return 0;
637                     }
638                   /* vendor change was illegal, ignore conflict */
639                 }
640             }
641         }
642     }
643   /* if we didn't find a patchpackage don't claim that the patch is irrelevant */
644   if (!hadpatchpackage)
645     return 0;
646   return 1;
647 }
648
649 /*****************************************************************************/
650
651 /*
652  * Create maps containing the state of each solvable. Input is a "installed" queue,
653  * it contains all solvable ids that are considered to be installed.
654  * 
655  * The created maps can be used for solvable_trivial_installable_map(),
656  * pool_calc_duchanges(), pool_calc_installsizechange().
657  *
658  */
659 void
660 pool_create_state_maps(Pool *pool, Queue *installed, Map *installedmap, Map *conflictsmap)
661 {
662   int i;
663   Solvable *s;
664   Id p, *dp;
665   Id *conp, con;
666
667   map_init(installedmap, pool->nsolvables);
668   if (conflictsmap)
669     map_init(conflictsmap, pool->nsolvables);
670   for (i = 0; i < installed->count; i++)
671     {
672       p = installed->elements[i];
673       if (p <= 0)       /* makes it work with decisionq */
674         continue;
675       MAPSET(installedmap, p);
676       if (!conflictsmap)
677         continue;
678       s = pool->solvables + p;
679       if (!s->conflicts)
680         continue;
681       conp = s->repo->idarraydata + s->conflicts;
682       while ((con = *conp++) != 0)
683         {
684           dp = pool_whatprovides_ptr(pool, con);
685           for (; *dp; dp++)
686             MAPSET(conflictsmap, *dp);
687         }
688     }
689 }
690
691 /* Tests if two solvables have identical content. Currently
692  * both solvables need to come from the same pool
693  */
694 int
695 solvable_identical(Solvable *s1, Solvable *s2)
696 {
697   unsigned int bt1, bt2;
698   Id rq1, rq2;
699   Id *reqp;
700
701   if (s1->name != s2->name)
702     return 0;
703   if (s1->arch != s2->arch)
704     return 0;
705   if (s1->evr != s2->evr)
706     return 0;
707   /* map missing vendor to empty string */
708   if ((s1->vendor ? s1->vendor : 1) != (s2->vendor ? s2->vendor : 1))
709     return 0;
710
711   /* looking good, try some fancier stuff */
712   /* might also look up the package checksum here */
713   bt1 = solvable_lookup_num(s1, SOLVABLE_BUILDTIME, 0);
714   bt2 = solvable_lookup_num(s2, SOLVABLE_BUILDTIME, 0);
715   if (bt1 && bt2)
716     {
717       if (bt1 != bt2)
718         return 0;
719     }
720   else
721     {
722       /* look at requires in a last attempt to find recompiled packages */
723       rq1 = rq2 = 0;
724       if (s1->requires)
725         for (reqp = s1->repo->idarraydata + s1->requires; *reqp; reqp++)
726           rq1 ^= *reqp;
727       if (s2->requires)
728         for (reqp = s2->repo->idarraydata + s2->requires; *reqp; reqp++)
729           rq2 ^= *reqp;
730       if (rq1 != rq2)
731          return 0;
732     }
733   return 1;
734 }
735
736 /* return the self provide dependency of a solvable */
737 Id
738 solvable_selfprovidedep(Solvable *s)
739 {
740   Pool *pool;
741   Reldep *rd;
742   Id prov, *provp;
743
744   if (!s->repo)
745     return s->name;
746   pool = s->repo->pool;
747   if (s->provides)
748     {
749       provp = s->repo->idarraydata + s->provides;
750       while ((prov = *provp++) != 0)
751         {
752           if (!ISRELDEP(prov))
753             continue;
754           rd = GETRELDEP(pool, prov);
755           if (rd->name == s->name && rd->evr == s->evr && rd->flags == REL_EQ)
756             return prov;
757         }
758     }
759   return pool_rel2id(pool, s->name, s->evr, REL_EQ, 1);
760 }
761
762 /* setter functions, simply call the repo variants */
763 void
764 solvable_set_id(Solvable *s, Id keyname, Id id)
765 {
766   repo_set_id(s->repo, s - s->repo->pool->solvables, keyname, id);
767 }
768
769 void
770 solvable_set_num(Solvable *s, Id keyname, unsigned long long num)
771 {
772   repo_set_num(s->repo, s - s->repo->pool->solvables, keyname, num);
773 }
774
775 void
776 solvable_set_str(Solvable *s, Id keyname, const char *str)
777 {
778   repo_set_str(s->repo, s - s->repo->pool->solvables, keyname, str);
779 }
780
781 void
782 solvable_set_poolstr(Solvable *s, Id keyname, const char *str)
783 {
784   repo_set_poolstr(s->repo, s - s->repo->pool->solvables, keyname, str);
785 }
786
787 void
788 solvable_add_poolstr_array(Solvable *s, Id keyname, const char *str)
789 {
790   repo_add_poolstr_array(s->repo, s - s->repo->pool->solvables, keyname, str);
791 }
792
793 void
794 solvable_add_idarray(Solvable *s, Id keyname, Id id)
795 {
796   repo_add_idarray(s->repo, s - s->repo->pool->solvables, keyname, id);
797 }
798
799 void
800 solvable_add_deparray(Solvable *s, Id keyname, Id dep, Id marker)
801 {
802   repo_add_deparray(s->repo, s - s->repo->pool->solvables, keyname, dep, marker);
803 }
804
805 void
806 solvable_set_idarray(Solvable *s, Id keyname, Queue *q)
807 {
808   repo_set_idarray(s->repo, s - s->repo->pool->solvables, keyname, q);
809 }
810
811 void
812 solvable_set_deparray(Solvable *s, Id keyname, Queue *q, Id marker)
813 {
814   repo_set_deparray(s->repo, s - s->repo->pool->solvables, keyname, q, marker);
815 }
816
817 void
818 solvable_unset(Solvable *s, Id keyname)
819 {
820   repo_unset(s->repo, s - s->repo->pool->solvables, keyname);
821 }