00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #define _GNU_SOURCE
00016 #include <string.h>
00017 #include <fnmatch.h>
00018
00019 #include <stdio.h>
00020 #include <stdlib.h>
00021
00022
00023
00024 #include "repo.h"
00025 #include "pool.h"
00026 #include "poolid_private.h"
00027 #include "util.h"
00028 #if 0
00029 #include "attr_store_p.h"
00030 #endif
00031
00032 #define IDARRAY_BLOCK 4095
00033
00034
00035
00036
00037
00038
00039
00040 Repo *
00041 repo_create(Pool *pool, const char *name)
00042 {
00043 Repo *repo;
00044
00045 pool_freewhatprovides(pool);
00046 repo = (Repo *)sat_calloc(1, sizeof(*repo));
00047 pool->repos = (Repo **)sat_realloc2(pool->repos, pool->nrepos + 1, sizeof(Repo *));
00048 pool->repos[pool->nrepos++] = repo;
00049 repo->repoid = pool->nrepos;
00050 repo->name = name ? strdup(name) : 0;
00051 repo->pool = pool;
00052 repo->start = pool->nsolvables;
00053 repo->end = pool->nsolvables;
00054 repo->nsolvables = 0;
00055 return repo;
00056 }
00057
00058 static void
00059 repo_freedata(Repo *repo)
00060 {
00061 int i;
00062 for (i = 0; i < repo->nrepodata; i++)
00063 repodata_freedata(repo->repodata + i);
00064 sat_free(repo->repodata);
00065 sat_free(repo->idarraydata);
00066 sat_free(repo->rpmdbid);
00067 sat_free((char *)repo->name);
00068 sat_free(repo);
00069 }
00070
00071
00072
00073 void
00074 repo_empty(Repo *repo, int reuseids)
00075 {
00076 Pool *pool = repo->pool;
00077 Solvable *s;
00078 int i;
00079
00080 pool_freewhatprovides(pool);
00081 if (repo == pool->installed)
00082 pool->installed = 0;
00083
00084 if (reuseids && repo->end == pool->nsolvables)
00085 {
00086
00087
00088 for (i = repo->end - 1, s = pool->solvables + i; i >= repo->start; i--, s--)
00089 if (s->repo != repo)
00090 break;
00091 pool_free_solvable_block(pool, i + 1, repo->end - (i + 1), reuseids);
00092 }
00093
00094 for (i = repo->start, s = pool->solvables + i; i < repo->end; i++, s++)
00095 if (s->repo == repo)
00096 memset(s, 0, sizeof(*s));
00097 repo->nsolvables = 0;
00098
00099
00100 repo->idarraydata = sat_free(repo->idarraydata);
00101 repo->idarraysize = 0;
00102 repo->lastoff = 0;
00103 repo->rpmdbid = sat_free(repo->rpmdbid);
00104 for (i = 0; i < repo->nrepodata; i++)
00105 repodata_freedata(repo->repodata + i);
00106 sat_free(repo->repodata);
00107 repo->repodata = 0;
00108 repo->nrepodata = 0;
00109 }
00110
00111
00112
00113
00114
00115
00116 void
00117 repo_free(Repo *repo, int reuseids)
00118 {
00119 Pool *pool = repo->pool;
00120 int i;
00121
00122 repo_empty(repo, reuseids);
00123 for (i = 0; i < pool->nrepos; i++)
00124 if (pool->repos[i] == repo)
00125 break;
00126 if (i == pool->nrepos)
00127 return;
00128 if (i < pool->nrepos - 1)
00129 {
00130 memmove(pool->repos + i, pool->repos + i + 1, (pool->nrepos - 1 - i) * sizeof(Repo *));
00131
00132 for (; i < pool->nrepos - 1; i++)
00133 pool->repos[i]->repoid = i + 1;
00134 }
00135 pool->nrepos--;
00136 repo_freedata(repo);
00137 }
00138
00139 void
00140 repo_freeallrepos(Pool *pool, int reuseids)
00141 {
00142 int i;
00143
00144 pool_freewhatprovides(pool);
00145 for (i = 0; i < pool->nrepos; i++)
00146 repo_freedata(pool->repos[i]);
00147 pool->repos = sat_free(pool->repos);
00148 pool->nrepos = 0;
00149
00150 pool_free_solvable_block(pool, 2, pool->nsolvables - 2, reuseids);
00151 }
00152
00153 void repo_free_solvable_block(Repo *repo, Id start, int count, int reuseids)
00154 {
00155 Solvable *s;
00156 Repodata *data;
00157 int i;
00158 if (start + count == repo->end)
00159 repo->end -= count;
00160 repo->nsolvables -= count;
00161 for (s = repo->pool->solvables + start, i = count; i--; s++)
00162 s->repo = 0;
00163 pool_free_solvable_block(repo->pool, start, count, reuseids);
00164 for (i = 0, data = repo->repodata; i < repo->nrepodata; i++, data++)
00165 if (data->end > repo->end)
00166 repodata_shrink(data, repo->end);
00167 }
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177 #define REPO_SIDEDATA_BLOCK 63
00178
00179 void *
00180 repo_sidedata_create(Repo *repo, size_t size)
00181 {
00182 return sat_calloc_block(repo->end - repo->start, size, REPO_SIDEDATA_BLOCK);
00183 }
00184
00185 void *
00186 repo_sidedata_extend(Repo *repo, void *b, size_t size, Id p, int count)
00187 {
00188 int n = repo->end - repo->start;
00189 if (p < repo->start)
00190 {
00191 int d = repo->start - p;
00192 b = sat_extend(b, n, d, size, REPO_SIDEDATA_BLOCK);
00193 memmove((char *)b + d * size, b, n * size);
00194 memset(b, 0, d * size);
00195 n += d;
00196 }
00197 if (p + count > repo->end)
00198 {
00199 int d = p + count - repo->end;
00200 b = sat_extend(b, n, d, size, REPO_SIDEDATA_BLOCK);
00201 memset((char *)b + n * size, 0, d * size);
00202 }
00203 return b;
00204 }
00205
00206
00207
00208
00209
00210
00211
00212 Offset
00213 repo_addid(Repo *repo, Offset olddeps, Id id)
00214 {
00215 Id *idarray;
00216 int idarraysize;
00217 int i;
00218
00219 idarray = repo->idarraydata;
00220 idarraysize = repo->idarraysize;
00221
00222 if (!idarray)
00223 {
00224 idarraysize = 1;
00225 idarray = sat_extend_resize(0, 1, sizeof(Id), IDARRAY_BLOCK);
00226 idarray[0] = 0;
00227 repo->lastoff = 0;
00228 }
00229
00230 if (!olddeps)
00231 {
00232 olddeps = idarraysize;
00233 idarray = sat_extend(idarray, idarraysize, 1, sizeof(Id), IDARRAY_BLOCK);
00234 }
00235 else if (olddeps == repo->lastoff)
00236 idarraysize--;
00237 else
00238 {
00239 i = olddeps;
00240 olddeps = idarraysize;
00241 for (; idarray[i]; i++)
00242 {
00243 idarray = sat_extend(idarray, idarraysize, 1, sizeof(Id), IDARRAY_BLOCK);
00244 idarray[idarraysize++] = idarray[i];
00245 }
00246 idarray = sat_extend(idarray, idarraysize, 1, sizeof(Id), IDARRAY_BLOCK);
00247 }
00248
00249 idarray[idarraysize++] = id;
00250 idarray = sat_extend(idarray, idarraysize, 1, sizeof(Id), IDARRAY_BLOCK);
00251 idarray[idarraysize++] = 0;
00252
00253 repo->idarraydata = idarray;
00254 repo->idarraysize = idarraysize;
00255 repo->lastoff = olddeps;
00256
00257 return olddeps;
00258 }
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269 Offset
00270 repo_addid_dep(Repo *repo, Offset olddeps, Id id, Id marker)
00271 {
00272 Id oid, *oidp, *markerp;
00273 int before;
00274
00275 if (!olddeps)
00276 {
00277 if (marker > 0)
00278 olddeps = repo_addid(repo, olddeps, marker);
00279 return repo_addid(repo, olddeps, id);
00280 }
00281
00282 if (!marker)
00283 {
00284 for (oidp = repo->idarraydata + olddeps; (oid = *oidp) != ID_NULL; oidp++)
00285 {
00286 if (oid == id)
00287 return olddeps;
00288 }
00289 return repo_addid(repo, olddeps, id);
00290 }
00291
00292 before = 0;
00293 markerp = 0;
00294 if (marker < 0)
00295 {
00296 before = 1;
00297 marker = -marker;
00298 }
00299 for (oidp = repo->idarraydata + olddeps; (oid = *oidp) != ID_NULL; oidp++)
00300 {
00301 if (oid == marker)
00302 markerp = oidp;
00303 else if (oid == id)
00304 break;
00305 }
00306
00307 if (oid)
00308 {
00309 if (markerp || before)
00310 return olddeps;
00311
00312 markerp = oidp++;
00313 for (; (oid = *oidp) != ID_NULL; oidp++)
00314 if (oid == marker)
00315 break;
00316 if (!oid)
00317 {
00318
00319 oidp--;
00320 if (markerp < oidp)
00321 memmove(markerp, markerp + 1, (oidp - markerp) * sizeof(Id));
00322 *oidp = marker;
00323 return repo_addid(repo, olddeps, id);
00324 }
00325 while (oidp[1])
00326 oidp++;
00327 memmove(markerp, markerp + 1, (oidp - markerp) * sizeof(Id));
00328 *oidp = id;
00329 return olddeps;
00330 }
00331
00332 if (!before && !markerp)
00333 olddeps = repo_addid(repo, olddeps, marker);
00334 else if (before && markerp)
00335 {
00336 *markerp++ = id;
00337 id = *--oidp;
00338 if (markerp < oidp)
00339 memmove(markerp + 1, markerp, (oidp - markerp) * sizeof(Id));
00340 *markerp = marker;
00341 }
00342 return repo_addid(repo, olddeps, id);
00343 }
00344
00345
00346
00347
00348
00349
00350
00351
00352
00353
00354 Offset
00355 repo_reserve_ids(Repo *repo, Offset olddeps, int num)
00356 {
00357 num++;
00358
00359 if (!repo->idarraysize)
00360 {
00361 repo->idarraysize = 1;
00362 repo->idarraydata = sat_extend_resize(0, 1 + num, sizeof(Id), IDARRAY_BLOCK);
00363 repo->idarraydata[0] = 0;
00364 repo->lastoff = 1;
00365 return 1;
00366 }
00367
00368 if (olddeps && olddeps != repo->lastoff)
00369 {
00370
00371
00372
00373
00374
00375 Id *idstart, *idend;
00376 int count;
00377
00378 for (idstart = idend = repo->idarraydata + olddeps; *idend++; )
00379 ;
00380 count = idend - idstart - 1 + num;
00381
00382 repo->idarraydata = sat_extend(repo->idarraydata, repo->idarraysize, count, sizeof(Id), IDARRAY_BLOCK);
00383
00384 olddeps = repo->lastoff = repo->idarraysize;
00385 memcpy(repo->idarraydata + olddeps, idstart, count - num);
00386 repo->idarraysize = olddeps + count - num;
00387
00388 return olddeps;
00389 }
00390
00391 if (olddeps)
00392 repo->idarraysize--;
00393
00394
00395 repo->idarraydata = sat_extend(repo->idarraydata, repo->idarraysize, num, sizeof(Id), IDARRAY_BLOCK);
00396
00397
00398 repo->lastoff = olddeps ? olddeps : repo->idarraysize;
00399
00400 return repo->lastoff;
00401 }
00402
00403
00404
00405 Offset
00406 repo_fix_supplements(Repo *repo, Offset provides, Offset supplements, Offset freshens)
00407 {
00408 Pool *pool = repo->pool;
00409 Id id, idp, idl;
00410 char buf[1024], *p, *dep;
00411 int i, l;
00412
00413 if (provides)
00414 {
00415 for (i = provides; repo->idarraydata[i]; i++)
00416 {
00417 id = repo->idarraydata[i];
00418 if (ISRELDEP(id))
00419 continue;
00420 dep = (char *)id2str(pool, id);
00421 if (!strncmp(dep, "locale(", 7) && strlen(dep) < sizeof(buf) - 2)
00422 {
00423 idp = 0;
00424 strcpy(buf + 2, dep);
00425 dep = buf + 2 + 7;
00426 if ((p = strchr(dep, ':')) != 0 && p != dep)
00427 {
00428 *p++ = 0;
00429 idp = str2id(pool, dep, 1);
00430 dep = p;
00431 }
00432 id = 0;
00433 while ((p = strchr(dep, ';')) != 0)
00434 {
00435 if (p == dep)
00436 {
00437 dep = p + 1;
00438 continue;
00439 }
00440 *p++ = 0;
00441 #if 0
00442 strncpy(dep - 9, "language:", 9);
00443 idl = str2id(pool, dep - 9, 1);
00444 #else
00445 idl = str2id(pool, dep, 1);
00446 idl = rel2id(pool, NAMESPACE_LANGUAGE, idl, REL_NAMESPACE, 1);
00447 #endif
00448 if (id)
00449 id = rel2id(pool, id, idl, REL_OR, 1);
00450 else
00451 id = idl;
00452 dep = p;
00453 }
00454 if (dep[0] && dep[1])
00455 {
00456 for (p = dep; *p && *p != ')'; p++)
00457 ;
00458 *p = 0;
00459 #if 0
00460 strncpy(dep - 9, "language:", 9);
00461 idl = str2id(pool, dep - 9, 1);
00462 #else
00463 idl = str2id(pool, dep, 1);
00464 idl = rel2id(pool, NAMESPACE_LANGUAGE, idl, REL_NAMESPACE, 1);
00465 #endif
00466 if (id)
00467 id = rel2id(pool, id, idl, REL_OR, 1);
00468 else
00469 id = idl;
00470 }
00471 if (idp)
00472 id = rel2id(pool, idp, id, REL_AND, 1);
00473 if (id)
00474 supplements = repo_addid_dep(repo, supplements, id, 0);
00475 }
00476 else if ((p = strchr(dep, ':')) != 0 && p != dep && p[1] == '/' && strlen(dep) < sizeof(buf))
00477 {
00478 strcpy(buf, dep);
00479 p = buf + (p - dep);
00480 *p++ = 0;
00481 idp = str2id(pool, buf, 1);
00482
00483 l = strlen(p);
00484 while (l > 1 && p[l - 1] == '/')
00485 p[--l] = 0;
00486 id = str2id(pool, p, 1);
00487 id = rel2id(pool, idp, id, REL_WITH, 1);
00488 id = rel2id(pool, NAMESPACE_SPLITPROVIDES, id, REL_NAMESPACE, 1);
00489 supplements = repo_addid_dep(repo, supplements, id, 0);
00490 }
00491 }
00492 }
00493 if (supplements)
00494 {
00495 for (i = supplements; repo->idarraydata[i]; i++)
00496 {
00497 id = repo->idarraydata[i];
00498 if (ISRELDEP(id))
00499 continue;
00500 dep = (char *)id2str(pool, id);
00501 if (!strncmp(dep, "system:modalias(", 16))
00502 dep += 7;
00503 if (!strncmp(dep, "modalias(", 9) && dep[9] && dep[10] && strlen(dep) < sizeof(buf))
00504 {
00505 strcpy(buf, dep);
00506 p = strchr(buf + 9, ':');
00507 if (p && p != buf + 9 && strchr(p + 1, ':'))
00508 {
00509 *p++ = 0;
00510 idp = str2id(pool, buf + 9, 1);
00511 p[strlen(p) - 1] = 0;
00512 id = str2id(pool, p, 1);
00513 id = rel2id(pool, NAMESPACE_MODALIAS, id, REL_NAMESPACE, 1);
00514 id = rel2id(pool, idp, id, REL_AND, 1);
00515 }
00516 else
00517 {
00518 p = buf + 9;
00519 p[strlen(p) - 1] = 0;
00520 id = str2id(pool, p, 1);
00521 id = rel2id(pool, NAMESPACE_MODALIAS, id, REL_NAMESPACE, 1);
00522 }
00523 if (id)
00524 repo->idarraydata[i] = id;
00525 }
00526 else if (!strncmp(dep, "packageand(", 11) && strlen(dep) < sizeof(buf))
00527 {
00528 strcpy(buf, dep);
00529 id = 0;
00530 dep = buf + 11;
00531 while ((p = strchr(dep, ':')) != 0)
00532 {
00533 if (p == dep)
00534 {
00535 dep = p + 1;
00536 continue;
00537 }
00538 *p++ = 0;
00539 idp = str2id(pool, dep, 1);
00540 if (id)
00541 id = rel2id(pool, id, idp, REL_AND, 1);
00542 else
00543 id = idp;
00544 dep = p;
00545 }
00546 if (dep[0] && dep[1])
00547 {
00548 dep[strlen(dep) - 1] = 0;
00549 idp = str2id(pool, dep, 1);
00550 if (id)
00551 id = rel2id(pool, id, idp, REL_AND, 1);
00552 else
00553 id = idp;
00554 }
00555 if (id)
00556 repo->idarraydata[i] = id;
00557 }
00558 else if (!strncmp(dep, "filesystem(", 11) && strlen(dep) < sizeof(buf))
00559 {
00560 strcpy(buf, dep + 11);
00561 if ((p = strrchr(buf, ')')) != 0)
00562 *p = 0;
00563 id = str2id(pool, buf, 1);
00564 id = rel2id(pool, NAMESPACE_FILESYSTEM, id, REL_NAMESPACE, 1);
00565 repo->idarraydata[i] = id;
00566 }
00567 }
00568 }
00569 if (freshens && repo->idarraydata[freshens])
00570 {
00571 Id idsupp = 0, idfresh = 0;
00572 if (!supplements)
00573 return freshens;
00574 for (i = supplements; repo->idarraydata[i]; i++)
00575 {
00576 if (!idsupp)
00577 idsupp = repo->idarraydata[i];
00578 else
00579 idsupp = rel2id(pool, idsupp, repo->idarraydata[i], REL_OR, 1);
00580 }
00581 for (i = freshens; repo->idarraydata[i]; i++)
00582 {
00583 if (!idfresh)
00584 idfresh = repo->idarraydata[i];
00585 else
00586 idfresh = rel2id(pool, idfresh, repo->idarraydata[i], REL_OR, 1);
00587 }
00588 if (!idsupp)
00589 idsupp = idfresh;
00590 else
00591 idsupp = rel2id(pool, idsupp, idfresh, REL_AND, 1);
00592 supplements = repo_addid_dep(repo, 0, idsupp, 0);
00593 }
00594 return supplements;
00595 }
00596
00597 Offset
00598 repo_fix_conflicts(Repo *repo, Offset conflicts)
00599 {
00600 char buf[1024], *p, *dep;
00601 Pool *pool = repo->pool;
00602 Id id;
00603 int i;
00604
00605 if (!conflicts)
00606 return conflicts;
00607 for (i = conflicts; repo->idarraydata[i]; i++)
00608 {
00609 id = repo->idarraydata[i];
00610 if (ISRELDEP(id))
00611 continue;
00612 dep = (char *)id2str(pool, id);
00613 if (!strncmp(dep, "otherproviders(", 15) && strlen(dep) < sizeof(buf) - 2)
00614 {
00615 strcpy(buf, dep + 15);
00616 if ((p = strchr(buf, ')')) != 0)
00617 *p = 0;
00618 id = str2id(pool, buf, 1);
00619 id = rel2id(pool, NAMESPACE_OTHERPROVIDERS, id, REL_NAMESPACE, 1);
00620 repo->idarraydata[i] = id;
00621 }
00622 }
00623 return conflicts;
00624 }
00625
00626 struct matchdata
00627 {
00628 Pool *pool;
00629 int flags;
00630 Datamatcher matcher;
00631 int stop;
00632 int (*callback)(void *cbdata, Solvable *s, Repodata *data, Repokey *key, KeyValue *kv);
00633 void *callback_data;
00634 };
00635
00636 int
00637 repo_matchvalue(void *cbdata, Solvable *s, Repodata *data, Repokey *key, KeyValue *kv)
00638 {
00639 struct matchdata *md = cbdata;
00640
00641 if (md->matcher.match)
00642 {
00643 if (!repodata_stringify(md->pool, data, key, kv, md->flags))
00644 return 0;
00645 if (!datamatcher_match(&md->matcher, kv->str))
00646 return 0;
00647 }
00648 md->stop = md->callback(md->callback_data, s, data, key, kv);
00649 return md->stop;
00650 }
00651
00652
00653 static Repokey solvablekeys[RPM_RPMDBID - SOLVABLE_NAME + 1] = {
00654 { SOLVABLE_NAME, REPOKEY_TYPE_ID, 0, KEY_STORAGE_SOLVABLE },
00655 { SOLVABLE_ARCH, REPOKEY_TYPE_ID, 0, KEY_STORAGE_SOLVABLE },
00656 { SOLVABLE_EVR, REPOKEY_TYPE_ID, 0, KEY_STORAGE_SOLVABLE },
00657 { SOLVABLE_VENDOR, REPOKEY_TYPE_ID, 0, KEY_STORAGE_SOLVABLE },
00658 { SOLVABLE_PROVIDES, REPOKEY_TYPE_IDARRAY, 0, KEY_STORAGE_SOLVABLE },
00659 { SOLVABLE_OBSOLETES, REPOKEY_TYPE_IDARRAY, 0, KEY_STORAGE_SOLVABLE },
00660 { SOLVABLE_CONFLICTS, REPOKEY_TYPE_IDARRAY, 0, KEY_STORAGE_SOLVABLE },
00661 { SOLVABLE_REQUIRES, REPOKEY_TYPE_IDARRAY, 0, KEY_STORAGE_SOLVABLE },
00662 { SOLVABLE_RECOMMENDS, REPOKEY_TYPE_IDARRAY, 0, KEY_STORAGE_SOLVABLE },
00663 { SOLVABLE_SUGGESTS, REPOKEY_TYPE_IDARRAY, 0, KEY_STORAGE_SOLVABLE },
00664 { SOLVABLE_SUPPLEMENTS, REPOKEY_TYPE_IDARRAY, 0, KEY_STORAGE_SOLVABLE },
00665 { SOLVABLE_ENHANCES, REPOKEY_TYPE_IDARRAY, 0, KEY_STORAGE_SOLVABLE },
00666 { RPM_RPMDBID, REPOKEY_TYPE_U32, 0, KEY_STORAGE_SOLVABLE },
00667 };
00668
00669 static void
00670 domatch_idarray(Solvable *s, Id keyname, struct matchdata *md, Id *ida)
00671 {
00672 KeyValue kv;
00673 kv.entry = 0;
00674 kv.parent = 0;
00675 for (; *ida && !md->stop; ida++)
00676 {
00677 kv.id = *ida;
00678 kv.eof = ida[1] ? 0 : 1;
00679 repo_matchvalue(md, s, 0, solvablekeys + (keyname - SOLVABLE_NAME), &kv);
00680 kv.entry++;
00681 }
00682 }
00683
00684 static void
00685 repo_search_md(Repo *repo, Id p, Id keyname, struct matchdata *md)
00686 {
00687 KeyValue kv;
00688 Pool *pool = repo->pool;
00689 Repodata *data;
00690 int i, j, flags;
00691 Solvable *s;
00692
00693 kv.parent = 0;
00694 md->stop = 0;
00695 if (!p)
00696 {
00697 for (p = repo->start, s = repo->pool->solvables + p; p < repo->end; p++, s++)
00698 {
00699 if (s->repo == repo)
00700 repo_search_md(repo, p, keyname, md);
00701 if (md->stop > SEARCH_NEXT_SOLVABLE)
00702 break;
00703 }
00704 return;
00705 }
00706 else if (p < 0)
00707
00708
00709 return;
00710 flags = md->flags;
00711 if (!(flags & SEARCH_NO_STORAGE_SOLVABLE))
00712 {
00713 s = pool->solvables + p;
00714 switch(keyname)
00715 {
00716 case 0:
00717 case SOLVABLE_NAME:
00718 if (s->name)
00719 {
00720 kv.id = s->name;
00721 repo_matchvalue(md, s, 0, solvablekeys + 0, &kv);
00722 }
00723 if (keyname || md->stop > SEARCH_NEXT_KEY)
00724 return;
00725 case SOLVABLE_ARCH:
00726 if (s->arch)
00727 {
00728 kv.id = s->arch;
00729 repo_matchvalue(md, s, 0, solvablekeys + 1, &kv);
00730 }
00731 if (keyname || md->stop > SEARCH_NEXT_KEY)
00732 return;
00733 case SOLVABLE_EVR:
00734 if (s->evr)
00735 {
00736 kv.id = s->evr;
00737 repo_matchvalue(md, s, 0, solvablekeys + 2, &kv);
00738 }
00739 if (keyname || md->stop > SEARCH_NEXT_KEY)
00740 return;
00741 case SOLVABLE_VENDOR:
00742 if (s->vendor)
00743 {
00744 kv.id = s->vendor;
00745 repo_matchvalue(md, s, 0, solvablekeys + 3, &kv);
00746 }
00747 if (keyname || md->stop > SEARCH_NEXT_KEY)
00748 return;
00749 case SOLVABLE_PROVIDES:
00750 if (s->provides)
00751 domatch_idarray(s, SOLVABLE_PROVIDES, md, repo->idarraydata + s->provides);
00752 if (keyname || md->stop > SEARCH_NEXT_KEY)
00753 return;
00754 case SOLVABLE_OBSOLETES:
00755 if (s->obsoletes)
00756 domatch_idarray(s, SOLVABLE_OBSOLETES, md, repo->idarraydata + s->obsoletes);
00757 if (keyname || md->stop > SEARCH_NEXT_KEY)
00758 return;
00759 case SOLVABLE_CONFLICTS:
00760 if (s->conflicts)
00761 domatch_idarray(s, SOLVABLE_CONFLICTS, md, repo->idarraydata + s->conflicts);
00762 if (keyname || md->stop > SEARCH_NEXT_KEY)
00763 return;
00764 case SOLVABLE_REQUIRES:
00765 if (s->requires)
00766 domatch_idarray(s, SOLVABLE_REQUIRES, md, repo->idarraydata + s->requires);
00767 if (keyname || md->stop > SEARCH_NEXT_KEY)
00768 return;
00769 case SOLVABLE_RECOMMENDS:
00770 if (s->recommends)
00771 domatch_idarray(s, SOLVABLE_RECOMMENDS, md, repo->idarraydata + s->recommends);
00772 if (keyname || md->stop > SEARCH_NEXT_KEY)
00773 return;
00774 case SOLVABLE_SUPPLEMENTS:
00775 if (s->supplements)
00776 domatch_idarray(s, SOLVABLE_SUPPLEMENTS, md, repo->idarraydata + s->supplements);
00777 if (keyname || md->stop > SEARCH_NEXT_KEY)
00778 return;
00779 case SOLVABLE_SUGGESTS:
00780 if (s->suggests)
00781 domatch_idarray(s, SOLVABLE_SUGGESTS, md, repo->idarraydata + s->suggests);
00782 if (keyname || md->stop > SEARCH_NEXT_KEY)
00783 return;
00784 case SOLVABLE_ENHANCES:
00785 if (s->enhances)
00786 domatch_idarray(s, SOLVABLE_ENHANCES, md, repo->idarraydata + s->enhances);
00787 if (keyname || md->stop > SEARCH_NEXT_KEY)
00788 return;
00789 case RPM_RPMDBID:
00790 if (repo->rpmdbid)
00791 {
00792 kv.num = repo->rpmdbid[p - repo->start];
00793 repo_matchvalue(md, s, 0, solvablekeys + (RPM_RPMDBID - SOLVABLE_NAME), &kv);
00794 }
00795 if (keyname || md->stop > SEARCH_NEXT_KEY)
00796 return;
00797 break;
00798 default:
00799 break;
00800 }
00801 }
00802
00803 for (i = 0, data = repo->repodata; i < repo->nrepodata; i++, data++)
00804 {
00805 if (p < data->start || p >= data->end)
00806 continue;
00807 if (keyname && !repodata_precheck_keyname(data, keyname))
00808 continue;
00809 if (keyname == SOLVABLE_FILELIST && !(md->flags & SEARCH_COMPLETE_FILELIST))
00810 {
00811
00812 if (data->state != REPODATA_AVAILABLE)
00813 continue;
00814 for (j = 1; j < data->nkeys; j++)
00815 if (data->keys[j].name != REPOSITORY_SOLVABLES && data->keys[j].name != SOLVABLE_FILELIST)
00816 break;
00817 if (j == data->nkeys)
00818 continue;
00819 }
00820 if (data->state == REPODATA_STUB)
00821 {
00822 if (keyname)
00823 {
00824 for (j = 1; j < data->nkeys; j++)
00825 if (keyname == data->keys[j].name)
00826 break;
00827 if (j == data->nkeys)
00828 continue;
00829 }
00830
00831 if (data->loadcallback)
00832 data->loadcallback(data);
00833 else
00834 data->state = REPODATA_ERROR;
00835 }
00836 if (data->state == REPODATA_ERROR)
00837 continue;
00838 repodata_search(data, p, keyname, md->flags, repo_matchvalue, md);
00839 if (md->stop > SEARCH_NEXT_KEY)
00840 break;
00841 }
00842 }
00843
00844 void
00845 repo_search(Repo *repo, Id p, Id keyname, const char *match, int flags, int (*callback)(void *cbdata, Solvable *s, Repodata *data, Repokey *key, KeyValue *kv), void *cbdata)
00846 {
00847 struct matchdata md;
00848
00849 if (repo->disabled && !(flags & SEARCH_DISABLED_REPOS))
00850 return;
00851 memset(&md, 0, sizeof(md));
00852 md.pool = repo->pool;
00853 md.flags = flags;
00854 md.callback = callback;
00855 md.callback_data = cbdata;
00856 if (match)
00857 datamatcher_init(&md.matcher, match, flags);
00858 repo_search_md(repo, p, keyname, &md);
00859 if (match)
00860 datamatcher_free(&md.matcher);
00861 }
00862
00863 const char *
00864 repo_lookup_str(Repo *repo, Id entry, Id keyname)
00865 {
00866 Pool *pool = repo->pool;
00867 Repodata *data;
00868 int i, j;
00869
00870 switch(keyname)
00871 {
00872 case SOLVABLE_NAME:
00873 return id2str(pool, pool->solvables[entry].name);
00874 case SOLVABLE_ARCH:
00875 return id2str(pool, pool->solvables[entry].arch);
00876 case SOLVABLE_EVR:
00877 return id2str(pool, pool->solvables[entry].evr);
00878 case SOLVABLE_VENDOR:
00879 return id2str(pool, pool->solvables[entry].vendor);
00880 }
00881 for (i = 0, data = repo->repodata; i < repo->nrepodata; i++, data++)
00882 {
00883 if (entry != SOLVID_META && (entry < data->start || entry >= data->end))
00884 continue;
00885 if (!repodata_precheck_keyname(data, keyname))
00886 continue;
00887 for (j = 1; j < data->nkeys; j++)
00888 {
00889 if (data->keys[j].name == keyname && (data->keys[j].type == REPOKEY_TYPE_ID || data->keys[j].type == REPOKEY_TYPE_CONSTANTID || data->keys[j].type == REPOKEY_TYPE_STR))
00890 return repodata_lookup_str(data, entry, keyname);
00891 }
00892 }
00893 return 0;
00894 }
00895
00896
00897 unsigned int
00898 repo_lookup_num(Repo *repo, Id entry, Id keyname, unsigned int notfound)
00899 {
00900 Repodata *data;
00901 int i, j;
00902
00903 if (keyname == RPM_RPMDBID)
00904 {
00905 if (repo->rpmdbid && entry >= repo->start && entry < repo->end)
00906 return repo->rpmdbid[entry - repo->start];
00907 return notfound;
00908 }
00909 for (i = 0, data = repo->repodata; i < repo->nrepodata; i++, data++)
00910 {
00911 if (entry != SOLVID_META && (entry < data->start || entry >= data->end))
00912 continue;
00913 if (!repodata_precheck_keyname(data, keyname))
00914 continue;
00915 for (j = 1; j < data->nkeys; j++)
00916 {
00917 if (data->keys[j].name == keyname
00918 && (data->keys[j].type == REPOKEY_TYPE_U32
00919 || data->keys[j].type == REPOKEY_TYPE_NUM
00920 || data->keys[j].type == REPOKEY_TYPE_CONSTANT))
00921 {
00922 unsigned value;
00923 if (repodata_lookup_num(data, entry, keyname, &value))
00924 return value;
00925 }
00926 }
00927 }
00928 return notfound;
00929 }
00930
00931 Id
00932 repo_lookup_id(Repo *repo, Id entry, Id keyname)
00933 {
00934 Repodata *data;
00935 int i, j;
00936
00937 switch(keyname)
00938 {
00939 case SOLVABLE_NAME:
00940 return repo->pool->solvables[entry].name;
00941 case SOLVABLE_ARCH:
00942 return repo->pool->solvables[entry].arch;
00943 case SOLVABLE_EVR:
00944 return repo->pool->solvables[entry].evr;
00945 case SOLVABLE_VENDOR:
00946 return repo->pool->solvables[entry].vendor;
00947 }
00948 for (i = 0, data = repo->repodata; i < repo->nrepodata; i++, data++)
00949 {
00950 if (entry != SOLVID_META && (entry < data->start || entry >= data->end))
00951 continue;
00952 if (!repodata_precheck_keyname(data, keyname))
00953 continue;
00954 for (j = 1; j < data->nkeys; j++)
00955 {
00956 if (data->keys[j].name == keyname && (data->keys[j].type == REPOKEY_TYPE_ID || data->keys[j].type == REPOKEY_TYPE_CONSTANTID))
00957 {
00958 Id id = repodata_lookup_id(data, entry, keyname);
00959 if (id)
00960 return data->localpool ? repodata_globalize_id(data, id, 1) : id;
00961 }
00962 }
00963 }
00964 return 0;
00965 }
00966
00967 const unsigned char *
00968 repo_lookup_bin_checksum(Repo *repo, Id entry, Id keyname, Id *typep)
00969 {
00970 Repodata *data;
00971 int i, j;
00972 for (i = 0, data = repo->repodata; i < repo->nrepodata; i++, data++)
00973 {
00974 if (entry != SOLVID_META && (entry < data->start || entry >= data->end))
00975 continue;
00976 if (!repodata_precheck_keyname(data, keyname))
00977 continue;
00978 for (j = 1; j < data->nkeys; j++)
00979 {
00980 if (data->keys[j].name == keyname)
00981 {
00982 const unsigned char *chk = repodata_lookup_bin_checksum(data, entry, keyname, typep);
00983 if (chk)
00984 return chk;
00985 }
00986 }
00987 }
00988 *typep = 0;
00989 return 0;
00990 }
00991
00992 int
00993 repo_lookup_void(Repo *repo, Id entry, Id keyname)
00994 {
00995 Repodata *data;
00996 int i, j;
00997 for (i = 0, data = repo->repodata; i < repo->nrepodata; i++, data++)
00998 {
00999 if (entry != SOLVID_META && (entry < data->start || entry >= data->end))
01000 continue;
01001 if (!repodata_precheck_keyname(data, keyname))
01002 continue;
01003 for (j = 1; j < data->nkeys; j++)
01004 {
01005 if (data->keys[j].name == keyname
01006 && (data->keys[j].type == REPOKEY_TYPE_VOID))
01007 {
01008 if (repodata_lookup_void(data, entry, keyname))
01009 return 1;
01010 }
01011 }
01012 }
01013 return 0;
01014 }
01015
01016
01017
01018 Repodata *
01019 repo_add_repodata(Repo *repo, int flags)
01020 {
01021 int i;
01022 if ((flags & REPO_USE_LOADING) != 0)
01023 {
01024 for (i = repo->nrepodata - 1; i >= 0; i--)
01025 if (repo->repodata[i].state == REPODATA_LOADING)
01026 {
01027 Repodata *data = repo->repodata + i;
01028
01029
01030 if (!(flags & REPO_REUSE_REPODATA))
01031 {
01032 repodata_freedata(data);
01033 repodata_initdata(data, repo, (flags & REPO_LOCALPOOL) ? 1 : 0);
01034 }
01035 return data;
01036 }
01037 return 0;
01038 }
01039 if ((flags & REPO_REUSE_REPODATA) != 0)
01040 {
01041 for (i = repo->nrepodata - 1; i >= 0; i--)
01042 if (repo->repodata[i].state != REPODATA_STUB)
01043 return repo->repodata + i;
01044 }
01045 return repodata_create(repo, (flags & REPO_LOCALPOOL) ? 1 : 0);
01046 }
01047
01048 Repodata *
01049 repo_last_repodata(Repo *repo)
01050 {
01051 int i;
01052 for (i = repo->nrepodata - 1; i >= 0; i--)
01053 if (repo->repodata[i].state != REPODATA_STUB)
01054 return repo->repodata + i;
01055 return repo_add_repodata(repo, 0);
01056 }
01057
01058 void
01059 repo_set_id(Repo *repo, Id p, Id keyname, Id id)
01060 {
01061 Repodata *data = repo_last_repodata(repo);
01062 repodata_set_id(data, p, keyname, id);
01063 }
01064
01065 void
01066 repo_set_num(Repo *repo, Id p, Id keyname, Id num)
01067 {
01068 Repodata *data = repo_last_repodata(repo);
01069 repodata_set_num(data, p, keyname, num);
01070 }
01071
01072 void
01073 repo_set_str(Repo *repo, Id p, Id keyname, const char *str)
01074 {
01075 Repodata *data = repo_last_repodata(repo);
01076 repodata_set_str(data, p, keyname, str);
01077 }
01078
01079 void
01080 repo_set_poolstr(Repo *repo, Id p, Id keyname, const char *str)
01081 {
01082 Repodata *data = repo_last_repodata(repo);
01083 repodata_set_poolstr(data, p, keyname, str);
01084 }
01085
01086 void
01087 repo_add_poolstr_array(Repo *repo, Id p, Id keyname, const char *str)
01088 {
01089 Repodata *data = repo_last_repodata(repo);
01090 repodata_add_poolstr_array(data, p, keyname, str);
01091 }
01092
01093 void
01094 repo_internalize(Repo *repo)
01095 {
01096 int i;
01097 Repodata *data;
01098
01099 for (i = 0, data = repo->repodata; i < repo->nrepodata; i++, data++)
01100 if (data->attrs || data->xattrs)
01101 repodata_internalize(data);
01102 }
01103
01104 void
01105 repo_disable_paging(Repo *repo)
01106 {
01107 int i;
01108 Repodata *data;
01109
01110 for (i = 0, data = repo->repodata; i < repo->nrepodata; i++, data++)
01111 repodata_disable_paging(data);
01112 }
01113
01114
01115
01116