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