2 * Copyright (c) 2007, Novell Inc.
4 * This program is licensed under the BSD license, read LICENSE.BSD
5 * for further information
11 * Manage metadata coming from one repository
21 #include "poolid_private.h"
24 #define IDARRAY_BLOCK 4095
33 pool_addrepo_empty(Pool *pool)
37 pool_freewhatprovides(pool);
38 repo = (Repo *)xcalloc(1, sizeof(*repo));
39 pool->repos = (Repo **)xrealloc(pool->repos, (pool->nrepos + 1) * sizeof(Repo *));
40 pool->repos[pool->nrepos++] = repo;
43 repo->start = pool->nsolvables;
50 * olddeps = old array to extend
55 repo_addid(Repo *repo, Offset olddeps, Id id)
61 idarray = repo->idarraydata;
62 idarraysize = repo->idarraysize;
64 if (!idarray) /* alloc idarray if not done yet */
66 idarray = (Id *)xmalloc((1 + IDARRAY_BLOCK) * sizeof(Id));
72 if (!olddeps) /* no deps yet */
74 olddeps = idarraysize;
75 if ((idarraysize & IDARRAY_BLOCK) == 0)
76 idarray = (Id *)xrealloc(idarray, (idarraysize + 1 + IDARRAY_BLOCK) * sizeof(Id));
78 else if (olddeps == repo->lastoff) /* extend at end */
80 else /* can't extend, copy old */
83 olddeps = idarraysize;
84 for (; idarray[i]; i++)
86 if ((idarraysize & IDARRAY_BLOCK) == 0)
87 idarray = (Id *)xrealloc(idarray, (idarraysize + 1 + IDARRAY_BLOCK) * sizeof(Id));
88 idarray[idarraysize++] = idarray[i];
90 if ((idarraysize & IDARRAY_BLOCK) == 0)
91 idarray = (Id *)xrealloc(idarray, (idarraysize + 1 + IDARRAY_BLOCK) * sizeof(Id));
94 idarray[idarraysize++] = id; /* insert Id into array */
96 if ((idarraysize & IDARRAY_BLOCK) == 0) /* realloc if at block boundary */
97 idarray = (Id *)xrealloc(idarray, (idarraysize + 1 + IDARRAY_BLOCK) * sizeof(Id));
99 idarray[idarraysize++] = 0; /* ensure NULL termination */
101 repo->idarraydata = idarray;
102 repo->idarraysize = idarraysize;
103 repo->lastoff = olddeps;
110 * add dependency (as Id) to repo
111 * olddeps = offset into idarraydata
112 * isreq = 0 for normal dep
113 * isreq = 1 for requires
114 * isreq = 2 for pre-requires
119 repo_addid_dep(Repo *repo, Offset olddeps, Id id, int isreq)
121 Id oid, *oidp, *marker = 0;
124 return repo_addid(repo, olddeps, id);
128 for (oidp = repo->idarraydata + olddeps; (oid = *oidp) != ID_NULL; oidp++)
133 return repo_addid(repo, olddeps, id);
136 for (oidp = repo->idarraydata + olddeps; (oid = *oidp) != ID_NULL; oidp++)
138 if (oid == SOLVABLE_PREREQMARKER)
146 if (marker || isreq == 1)
149 for (; (oid = *oidp) != ID_NULL; oidp++)
150 if (oid == SOLVABLE_PREREQMARKER)
156 memmove(marker, marker + 1, (oidp - marker) * sizeof(Id));
157 *oidp = SOLVABLE_PREREQMARKER;
158 return repo_addid(repo, olddeps, id);
162 memmove(marker, marker + 1, (oidp - marker) * sizeof(Id));
166 if (isreq == 2 && !marker)
167 olddeps = repo_addid(repo, olddeps, SOLVABLE_PREREQMARKER);
168 else if (isreq == 1 && marker)
173 memmove(marker + 1, marker, (oidp - marker) * sizeof(Id));
174 *marker = SOLVABLE_PREREQMARKER;
176 return repo_addid(repo, olddeps, id);
182 * make space for 'num' more dependencies
186 repo_reserve_ids(Repo *repo, Offset olddeps, int num)
188 num++; /* room for trailing ID_NULL */
190 if (!repo->idarraysize) /* ensure buffer space */
192 repo->idarraysize = 1;
193 repo->idarraydata = (Id *)xmalloc(((1 + num + IDARRAY_BLOCK) & ~IDARRAY_BLOCK) * sizeof(Id));
194 repo->idarraydata[0] = 0;
199 if (olddeps && olddeps != repo->lastoff) /* if not appending */
201 /* can't insert into idarray, this would invalidate all 'larger' offsets
202 * so create new space at end and move existing deps there.
203 * Leaving 'hole' at old position.
209 for (idstart = idend = repo->idarraydata + olddeps; *idend++; ) /* find end */
211 count = idend - idstart - 1 + num; /* new size */
213 /* realloc if crossing block boundary */
214 if (((repo->idarraysize - 1) | IDARRAY_BLOCK) != ((repo->idarraysize + count - 1) | IDARRAY_BLOCK))
215 repo->idarraydata = (Id *)xrealloc(repo->idarraydata, ((repo->idarraysize + count + IDARRAY_BLOCK) & ~IDARRAY_BLOCK) * sizeof(Id));
217 /* move old deps to end */
218 olddeps = repo->lastoff = repo->idarraysize;
219 memcpy(repo->idarraydata + olddeps, idstart, count - num);
220 repo->idarraysize = olddeps + count - num;
225 if (olddeps) /* appending */
228 /* realloc if crossing block boundary */
229 if (((repo->idarraysize - 1) | IDARRAY_BLOCK) != ((repo->idarraysize + num - 1) | IDARRAY_BLOCK))
230 repo->idarraydata = (Id *)xrealloc(repo->idarraydata, ((repo->idarraysize + num + IDARRAY_BLOCK) & ~IDARRAY_BLOCK) * sizeof(Id));
232 /* appending or new */
233 repo->lastoff = olddeps ? olddeps : repo->idarraysize;
235 return repo->lastoff;
240 * remove repo from pool
245 pool_freerepo(Pool *pool, Repo *repo)
249 pool_freewhatprovides(pool);
251 for (i = 0; i < pool->nrepos; i++) /* find repo in pool */
253 if (pool->repos[i] == repo)
256 if (i == pool->nrepos) /* repo not in pool, return */
260 * all repos point into pool->solvables _relatively_ to repo->start
261 * so closing the gap only needs adaption of repo->start for all
265 nsolvables = repo->nsolvables;
266 if (pool->nsolvables > repo->start + nsolvables)
267 memmove(pool->solvables + repo->start, pool->solvables + repo->start + nsolvables, (pool->nsolvables - repo->start - nsolvables) * sizeof(Solvable));
268 pool->nsolvables -= nsolvables;
270 for (; i < pool->nrepos - 1; i++)
272 pool->repos[i] = pool->repos[i + 1]; /* remove repo */
273 pool->repos[i]->start -= nsolvables; /* adapt start offset of remaining repos */
277 xfree(repo->idarraydata);
278 xfree(repo->rpmdbid);
283 repo_fix_legacy(Repo *repo, Offset provides, Offset supplements)
285 Pool *pool = repo->pool;
286 Id id, idp, idl, idns;
287 char buf[1024], *p, *dep;
292 for (i = provides; repo->idarraydata[i]; i++)
294 id = repo->idarraydata[i];
297 dep = (char *)id2str(pool, id);
298 if (!strncmp(dep, "locale(", 7) && strlen(dep) < sizeof(buf) - 2)
301 strcpy(buf + 2, dep);
303 if ((p = strchr(dep, ':')) != 0 && p != dep)
306 idp = str2id(pool, dep, 1);
310 while ((p = strchr(dep, ';')) != 0)
317 strncpy(dep - 9, "language:", 9);
319 idl = str2id(pool, dep - 9, 1);
321 id = rel2id(pool, id, idl, REL_OR, 1);
326 if (dep[0] && dep[1])
328 for (p = dep; *p && *p != ')'; p++)
331 strncpy(dep - 9, "language:", 9);
332 idl = str2id(pool, dep - 9, 1);
334 id = rel2id(pool, id, idl, REL_OR, 1);
339 id = rel2id(pool, idp, id, REL_AND, 1);
341 supplements = repo_addid_dep(repo, supplements, id, 0);
343 else if ((p = strchr(dep, ':')) != 0 && p != dep && p[1] == '/' && strlen(dep) < sizeof(buf))
348 idp = str2id(pool, buf, 1);
349 idns = str2id(pool, "namespace:installed", 1);
350 id = str2id(pool, p, 1);
351 id = rel2id(pool, idns, id, REL_NAMESPACE, 1);
352 id = rel2id(pool, idp, id, REL_AND, 1);
353 supplements = repo_addid_dep(repo, supplements, id, 0);
359 for (i = supplements; repo->idarraydata[i]; i++)
361 id = repo->idarraydata[i];
364 dep = (char *)id2str(pool, id);
365 if (!strncmp(dep, "system:modalias(", 16))
367 if (!strncmp(dep, "modalias(", 9) && dep[9] && dep[10] && strlen(dep) < sizeof(buf))
370 p = strchr(buf + 9, ':');
371 idns = str2id(pool, "namespace:modalias", 1);
372 if (p && p != buf + 9 && strchr(p + 1, ':'))
375 idp = str2id(pool, buf + 9, 1);
376 p[strlen(p) - 1] = 0;
377 id = str2id(pool, p, 1);
378 id = rel2id(pool, idns, id, REL_NAMESPACE, 1);
379 id = rel2id(pool, idp, id, REL_AND, 1);
384 p[strlen(p) - 1] = 0;
385 id = str2id(pool, p, 1);
386 id = rel2id(pool, idns, id, REL_NAMESPACE, 1);
389 repo->idarraydata[i] = id;
391 else if (!strncmp(dep, "packageand(", 11) && strlen(dep) < sizeof(buf))
396 while ((p = strchr(dep, ':')) != 0)
404 idp = str2id(pool, dep, 1);
406 id = rel2id(pool, id, idp, REL_AND, 1);
411 if (dep[0] && dep[1])
413 dep[strlen(dep) - 1] = 0;
414 idp = str2id(pool, dep, 1);
416 id = rel2id(pool, id, idp, REL_AND, 1);
421 repo->idarraydata[i] = id;