2 * Copyright (c) 2008, Novell Inc.
4 * This program is licensed under the BSD license, read LICENSE.BSD
5 * for further information
11 * set/retrieve data from solvables
24 #include "poolvendor.h"
28 pool_solvable2str(Pool *pool, Solvable *s)
30 const char *n, *e, *a;
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);
40 if (pool->havedistepoch)
42 /* strip the distepoch from the evr */
43 const char *de = strrchr(e, '-');
44 if (de && (de = strchr(de, ':')) != 0)
47 p = pool_alloctmpspace(pool, nl + el + al + 3);
52 strncpy(p + nl, e, el);
56 p[nl + el] = pool->disttype == DISTTYPE_HAIKU ? '-' : '.';
57 strcpy(p + nl + el + 1, a);
63 solvable_lookup_type(Solvable *s, Id keyname)
67 return repo_lookup_type(s->repo, s - s->repo->pool->solvables, keyname);
71 solvable_lookup_id(Solvable *s, Id keyname)
75 return repo_lookup_id(s->repo, s - s->repo->pool->solvables, keyname);
79 solvable_lookup_idarray(Solvable *s, Id keyname, Queue *q)
86 return repo_lookup_idarray(s->repo, s - s->repo->pool->solvables, keyname, q);
90 solvable_lookup_deparray(Solvable *s, Id keyname, Queue *q, Id marker)
97 return repo_lookup_deparray(s->repo, s - s->repo->pool->solvables, keyname, q, marker);
101 solvable_lookup_str_joinarray(Solvable *s, Id keyname, const char *joinstr)
107 queue_init_buffer(&q, qbuf, sizeof(qbuf)/sizeof(*qbuf));
108 if (solvable_lookup_idarray(s, keyname, &q) && q.count)
110 Pool *pool = s->repo->pool;
112 str = pool_tmpjoin(pool, pool_id2str(pool, q.elements[0]), 0, 0);
113 for (i = 1; i < q.count; i++)
114 str = pool_tmpappend(pool, str, joinstr, pool_id2str(pool, q.elements[i]));
121 solvable_lookup_str(Solvable *s, Id keyname)
126 str = repo_lookup_str(s->repo, s - s->repo->pool->solvables, keyname);
127 if (!str && (keyname == SOLVABLE_LICENSE || keyname == SOLVABLE_GROUP))
128 str = solvable_lookup_str_joinarray(s, keyname, ", ");
133 solvable_lookup_str_base(Solvable *s, Id keyname, Id basekeyname, int usebase)
136 const char *str, *basestr;
143 pool = s->repo->pool;
144 str = solvable_lookup_str(s, keyname);
145 if (str || keyname == basekeyname)
147 basestr = solvable_lookup_str(s, basekeyname);
150 /* search for a solvable with same name and same base that has the
152 if (!pool->whatprovides)
153 return usebase ? basestr : 0;
154 /* we do this in two passes, first same vendor, then all other vendors */
155 for (pass = 0; pass < 2; pass++)
157 FOR_PROVIDES(p, pp, s->name)
159 s2 = pool->solvables + p;
160 if (s2->name != s->name)
162 if ((s->vendor == s2->vendor) != (pass == 0))
164 str = solvable_lookup_str(s2, basekeyname);
165 if (!str || strcmp(str, basestr))
167 str = solvable_lookup_str(s2, keyname);
172 return usebase ? basestr : 0;
176 solvable_lookup_str_poollang(Solvable *s, Id keyname)
185 pool = s->repo->pool;
186 if (!pool->nlanguages)
187 return solvable_lookup_str(s, keyname);
188 cols = pool->nlanguages + 1;
189 if (!pool->languagecache)
191 pool->languagecache = solv_calloc(cols * ID_NUM_INTERNAL, sizeof(Id));
192 pool->languagecacheother = 0;
194 if (keyname >= ID_NUM_INTERNAL)
196 row = pool->languagecache + ID_NUM_INTERNAL * cols;
197 for (i = 0; i < pool->languagecacheother; i++, row += cols)
200 if (i >= pool->languagecacheother)
202 pool->languagecache = solv_realloc2(pool->languagecache, pool->languagecacheother + 1, cols * sizeof(Id));
203 row = pool->languagecache + cols * (ID_NUM_INTERNAL + pool->languagecacheother++);
208 row = pool->languagecache + keyname * cols;
209 row++; /* skip keyname */
210 for (i = 0; i < pool->nlanguages; i++, row++)
213 *row = pool_id2langid(pool, keyname, pool->languages[i], 1);
214 str = solvable_lookup_str_base(s, *row, keyname, 0);
218 return solvable_lookup_str(s, keyname);
222 solvable_lookup_str_lang(Solvable *s, Id keyname, const char *lang, int usebase)
226 Id id = pool_id2langid(s->repo->pool, keyname, lang, 0);
228 return solvable_lookup_str_base(s, id, keyname, usebase);
232 return solvable_lookup_str(s, keyname);
236 solvable_lookup_num(Solvable *s, Id keyname, unsigned long long notfound)
240 return repo_lookup_num(s->repo, s - s->repo->pool->solvables, keyname, notfound);
244 solvable_lookup_sizek(Solvable *s, Id keyname, unsigned int notfound)
246 unsigned long long size;
249 size = solvable_lookup_num(s, keyname, (unsigned long long)notfound << 10);
250 return (unsigned int)((size + 1023) >> 10);
254 solvable_lookup_void(Solvable *s, Id keyname)
258 return repo_lookup_void(s->repo, s - s->repo->pool->solvables, keyname);
262 solvable_lookup_bool(Solvable *s, Id keyname)
266 /* historic nonsense: there are two ways of storing a bool, as num == 1 or void. test both. */
267 if (repo_lookup_type(s->repo, s - s->repo->pool->solvables, keyname) == REPOKEY_TYPE_VOID)
269 return repo_lookup_num(s->repo, s - s->repo->pool->solvables, keyname, 0) == 1;
272 const unsigned char *
273 solvable_lookup_bin_checksum(Solvable *s, Id keyname, Id *typep)
275 Repo *repo = s->repo;
282 return repo_lookup_bin_checksum(repo, s - repo->pool->solvables, keyname, typep);
286 solvable_lookup_checksum(Solvable *s, Id keyname, Id *typep)
288 const unsigned char *chk = solvable_lookup_bin_checksum(s, keyname, typep);
289 return chk ? pool_bin2hex(s->repo->pool, chk, solv_chksum_len(*typep)) : 0;
292 static inline const char *
293 evrid2vrstr(Pool *pool, Id evrid)
295 const char *p, *evr = pool_id2str(pool, evrid);
298 for (p = evr; *p >= '0' && *p <= '9'; p++)
300 return p != evr && *p == ':' && p[1] ? p + 1 : evr;
304 solvable_lookup_location(Solvable *s, unsigned int *medianrp)
309 const char *mediadir, *mediafile;
315 pool = s->repo->pool;
317 *medianrp = solvable_lookup_num(s, SOLVABLE_MEDIANR, 0);
318 if (solvable_lookup_void(s, SOLVABLE_MEDIADIR))
319 mediadir = pool_id2str(pool, s->arch);
321 mediadir = solvable_lookup_str(s, SOLVABLE_MEDIADIR);
323 l = strlen(mediadir) + 1;
324 if (solvable_lookup_void(s, SOLVABLE_MEDIAFILE))
326 const char *name, *evr, *arch;
327 name = pool_id2str(pool, s->name);
328 evr = evrid2vrstr(pool, s->evr);
329 arch = pool_id2str(pool, s->arch);
330 /* name-vr.arch.rpm */
331 loc = pool_alloctmpspace(pool, l + strlen(name) + strlen(evr) + strlen(arch) + 7);
333 sprintf(loc, "%s/%s-%s.%s.rpm", mediadir, name, evr, arch);
335 sprintf(loc, "%s-%s.%s.rpm", name, evr, arch);
339 mediafile = solvable_lookup_str(s, SOLVABLE_MEDIAFILE);
342 loc = pool_alloctmpspace(pool, l + strlen(mediafile) + 1);
344 sprintf(loc, "%s/%s", mediadir, mediafile);
346 strcpy(loc, mediafile);
352 solvable_get_location(Solvable *s, unsigned int *medianrp)
354 const char *loc = solvable_lookup_location(s, medianrp);
355 if (medianrp && *medianrp == 0)
356 *medianrp = 1; /* compat, to be removed */
361 solvable_lookup_sourcepkg(Solvable *s)
364 const char *evr, *name;
369 pool = s->repo->pool;
370 if (solvable_lookup_void(s, SOLVABLE_SOURCENAME))
371 name = pool_id2str(pool, s->name);
373 name = solvable_lookup_str(s, SOLVABLE_SOURCENAME);
376 archid = solvable_lookup_id(s, SOLVABLE_SOURCEARCH);
377 if (solvable_lookup_void(s, SOLVABLE_SOURCEEVR))
378 evr = evrid2vrstr(pool, s->evr);
380 evr = solvable_lookup_str(s, SOLVABLE_SOURCEEVR);
381 if (archid == ARCH_SRC || archid == ARCH_NOSRC)
384 str = pool_tmpjoin(pool, name, evr ? "-" : 0, evr);
385 str = pool_tmpappend(pool, str, ".", pool_id2str(pool, archid));
386 return pool_tmpappend(pool, str, ".rpm", 0);
389 return name; /* FIXME */
393 /*****************************************************************************/
395 static inline Id dep2name(Pool *pool, Id dep)
397 while (ISRELDEP(dep))
399 Reldep *rd = rd = GETRELDEP(pool, dep);
405 static int providedbyinstalled_multiversion(Pool *pool, Map *installed, Id n, Id con)
408 Solvable *sn = pool->solvables + n;
410 FOR_PROVIDES(p, pp, sn->name)
412 Solvable *s = pool->solvables + p;
413 if (s->name != sn->name || s->arch != sn->arch)
415 if (!MAPTST(installed, p))
417 if (pool_match_nevr(pool, pool->solvables + p, con))
419 return 1; /* found installed package that doesn't conflict */
424 static inline int providedbyinstalled(Pool *pool, Map *installed, Id dep, int ispatch, Map *multiversionmap)
427 FOR_PROVIDES(p, pp, dep)
429 if (p == SYSTEMSOLVABLE)
431 if (ispatch && !pool_match_nevr(pool, pool->solvables + p, dep))
433 if (ispatch && multiversionmap && multiversionmap->size && MAPTST(multiversionmap, p) && ISRELDEP(dep))
434 if (providedbyinstalled_multiversion(pool, installed, p, dep))
436 if (MAPTST(installed, p))
443 * solvable_trivial_installable_map - anwers is a solvable is installable
444 * without any other installs/deinstalls.
445 * The packages considered to be installed are provided via the
446 * installedmap bitmap. A additional "conflictsmap" bitmap providing
447 * information about the conflicts of the installed packages can be
448 * used for extra speed up. Provide a NULL pointer if you do not
449 * have this information.
450 * Both maps can be created with pool_create_state_maps() or
451 * solver_create_state_maps().
454 * 1: solvable is installable without any other package changes
455 * 0: solvable is not installable
456 * -1: solvable is installable, but doesn't constrain any installed packages
459 solvable_trivial_installable_map(Solvable *s, Map *installedmap, Map *conflictsmap, Map *multiversionmap)
461 Pool *pool = s->repo->pool;
466 int r, interesting = 0;
468 if (conflictsmap && MAPTST(conflictsmap, s - pool->solvables))
472 reqp = s->repo->idarraydata + s->requires;
473 while ((req = *reqp++) != 0)
475 if (req == SOLVABLE_PREREQMARKER)
477 r = providedbyinstalled(pool, installedmap, req, 0, 0);
488 if (!strncmp("patch:", pool_id2str(pool, s->name), 6))
490 conp = s->repo->idarraydata + s->conflicts;
491 while ((con = *conp++) != 0)
493 if (providedbyinstalled(pool, installedmap, con, ispatch, multiversionmap))
495 if (ispatch && solvable_is_irrelevant_patch(s, installedmap))
499 if (!interesting && ISRELDEP(con))
501 con = dep2name(pool, con);
502 if (providedbyinstalled(pool, installedmap, con, ispatch, multiversionmap))
506 if (ispatch && interesting && solvable_is_irrelevant_patch(s, installedmap))
514 if (s->obsoletes && s->repo != installed)
516 obsp = s->repo->idarraydata + s->obsoletes;
517 while ((obs = *obsp++) != 0)
519 if (providedbyinstalled(pool, installedmap, obs, 0, 0))
523 if (s->repo != installed)
526 FOR_PROVIDES(p, pp, s->name)
528 s2 = pool->solvables + p;
529 if (s2->repo == installed && s2->name == s->name)
539 p = s - pool->solvables;
540 for (i = 1; i < pool->nsolvables; i++)
542 if (!MAPTST(installedmap, i))
544 s2 = pool->solvables + i;
547 conp = s2->repo->idarraydata + s2->conflicts;
548 while ((con = *conp++) != 0)
550 dp = pool_whatprovides_ptr(pool, con);
557 return interesting ? 1 : -1;
561 * different interface for solvable_trivial_installable_map, where
562 * the information about the installed packages is provided
566 solvable_trivial_installable_queue(Solvable *s, Queue *installed, Map *multiversionmap)
568 Pool *pool = s->repo->pool;
574 map_init(&installedmap, pool->nsolvables);
575 for (i = 0; i < installed->count; i++)
577 p = installed->elements[i];
578 if (p > 0) /* makes it work with decisionq */
579 MAPSET(&installedmap, p);
581 r = solvable_trivial_installable_map(s, &installedmap, 0, multiversionmap);
582 map_free(&installedmap);
587 * different interface for solvable_trivial_installable_map, where
588 * the information about the installed packages is provided
589 * by a repo containing the installed solvables.
592 solvable_trivial_installable_repo(Solvable *s, Repo *installed, Map *multiversionmap)
594 Pool *pool = s->repo->pool;
600 map_init(&installedmap, pool->nsolvables);
601 FOR_REPO_SOLVABLES(installed, p, s2)
602 MAPSET(&installedmap, p);
603 r = solvable_trivial_installable_map(s, &installedmap, 0, multiversionmap);
604 map_free(&installedmap);
608 /* FIXME: this mirrors policy_illegal_vendorchange */
610 pool_illegal_vendorchange(Pool *pool, Solvable *s1, Solvable *s2)
613 Id vendormask1, vendormask2;
615 if (pool->custom_vendorcheck)
616 return pool->custom_vendorcheck(pool, s1, s2);
617 /* treat a missing vendor as empty string */
618 v1 = s1->vendor ? s1->vendor : ID_EMPTY;
619 v2 = s2->vendor ? s2->vendor : ID_EMPTY;
622 vendormask1 = pool_vendor2mask(pool, v1);
624 return 1; /* can't match */
625 vendormask2 = pool_vendor2mask(pool, v2);
626 if ((vendormask1 & vendormask2) != 0)
628 return 1; /* no class matches */
631 /* check if this patch is relevant according to the vendor. To bad that patches
632 * don't have a vendor, so we need to do some careful repo testing. */
634 solvable_is_irrelevant_patch(Solvable *s, Map *installedmap)
636 Pool *pool = s->repo->pool;
638 int hadpatchpackage = 0;
642 conp = s->repo->idarraydata + s->conflicts;
643 while ((con = *conp++) != 0)
649 rd = GETRELDEP(pool, con);
650 if (rd->flags != REL_LT)
652 FOR_PROVIDES(p, pp, con)
655 if (!MAPTST(installedmap, p))
657 si = pool->solvables + p;
658 if (!pool_match_nevr(pool, si, con))
660 FOR_PROVIDES(p2, pp2, rd->name)
662 Solvable *s2 = pool->solvables + p2;
663 if (!pool_match_nevr(pool, s2, rd->name))
665 if (pool_match_nevr(pool, s2, con))
666 continue; /* does not fulfill patch */
667 if (s2->repo == s->repo)
670 /* ok, we have a package from the patch repo that solves the conflict. check vendor */
671 if (si->vendor == s2->vendor)
673 if (!pool_illegal_vendorchange(pool, si, s2))
675 /* vendor change was illegal, ignore conflict */
680 /* if we didn't find a patchpackage don't claim that the patch is irrelevant */
681 if (!hadpatchpackage)
686 /*****************************************************************************/
689 * Create maps containing the state of each solvable. Input is a "installed" queue,
690 * it contains all solvable ids that are considered to be installed.
692 * The created maps can be used for solvable_trivial_installable_map(),
693 * pool_calc_duchanges(), pool_calc_installsizechange().
697 pool_create_state_maps(Pool *pool, Queue *installed, Map *installedmap, Map *conflictsmap)
704 map_init(installedmap, pool->nsolvables);
706 map_init(conflictsmap, pool->nsolvables);
707 for (i = 0; i < installed->count; i++)
709 p = installed->elements[i];
710 if (p <= 0) /* makes it work with decisionq */
712 MAPSET(installedmap, p);
715 s = pool->solvables + p;
718 conp = s->repo->idarraydata + s->conflicts;
719 while ((con = *conp++) != 0)
721 dp = pool_whatprovides_ptr(pool, con);
723 MAPSET(conflictsmap, *dp);
728 /* Tests if two solvables have identical content. Currently
729 * both solvables need to come from the same pool
732 solvable_identical(Solvable *s1, Solvable *s2)
734 unsigned int bt1, bt2;
738 if (s1->name != s2->name)
740 if (s1->arch != s2->arch)
742 if (s1->evr != s2->evr)
744 /* map missing vendor to empty string */
745 if ((s1->vendor ? s1->vendor : 1) != (s2->vendor ? s2->vendor : 1))
748 /* looking good, try some fancier stuff */
749 /* might also look up the package checksum here */
750 bt1 = solvable_lookup_num(s1, SOLVABLE_BUILDTIME, 0);
751 bt2 = solvable_lookup_num(s2, SOLVABLE_BUILDTIME, 0);
759 /* look at requires in a last attempt to find recompiled packages */
762 for (reqp = s1->repo->idarraydata + s1->requires; *reqp; reqp++)
765 for (reqp = s2->repo->idarraydata + s2->requires; *reqp; reqp++)
773 /* return the self provide dependency of a solvable */
775 solvable_selfprovidedep(Solvable *s)
783 pool = s->repo->pool;
786 provp = s->repo->idarraydata + s->provides;
787 while ((prov = *provp++) != 0)
791 rd = GETRELDEP(pool, prov);
792 if (rd->name == s->name && rd->evr == s->evr && rd->flags == REL_EQ)
796 return pool_rel2id(pool, s->name, s->evr, REL_EQ, 1);
799 /* setter functions, simply call the repo variants */
801 solvable_set_id(Solvable *s, Id keyname, Id id)
803 repo_set_id(s->repo, s - s->repo->pool->solvables, keyname, id);
807 solvable_set_num(Solvable *s, Id keyname, unsigned long long num)
809 repo_set_num(s->repo, s - s->repo->pool->solvables, keyname, num);
813 solvable_set_str(Solvable *s, Id keyname, const char *str)
815 repo_set_str(s->repo, s - s->repo->pool->solvables, keyname, str);
819 solvable_set_poolstr(Solvable *s, Id keyname, const char *str)
821 repo_set_poolstr(s->repo, s - s->repo->pool->solvables, keyname, str);
825 solvable_add_poolstr_array(Solvable *s, Id keyname, const char *str)
827 repo_add_poolstr_array(s->repo, s - s->repo->pool->solvables, keyname, str);
831 solvable_add_idarray(Solvable *s, Id keyname, Id id)
833 repo_add_idarray(s->repo, s - s->repo->pool->solvables, keyname, id);
837 solvable_add_deparray(Solvable *s, Id keyname, Id dep, Id marker)
839 repo_add_deparray(s->repo, s - s->repo->pool->solvables, keyname, dep, marker);
843 solvable_set_idarray(Solvable *s, Id keyname, Queue *q)
845 repo_set_idarray(s->repo, s - s->repo->pool->solvables, keyname, q);
849 solvable_set_deparray(Solvable *s, Id keyname, Queue *q, Id marker)
851 repo_set_deparray(s->repo, s - s->repo->pool->solvables, keyname, q, marker);
855 solvable_unset(Solvable *s, Id keyname)
857 repo_unset(s->repo, s - s->repo->pool->solvables, keyname);