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 repo_create(Pool *pool, const char *name)
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;
41 repo->name = name ? strdup(name) : 0;
43 repo->start = pool->nsolvables;
44 repo->end = pool->nsolvables;
50 repo_freedata(Repo *repo)
52 xfree(repo->idarraydata);
54 xfree((char *)repo->name);
60 * olddeps = old array to extend
65 repo_addid(Repo *repo, Offset olddeps, Id id)
71 idarray = repo->idarraydata;
72 idarraysize = repo->idarraysize;
74 if (!idarray) /* alloc idarray if not done yet */
76 idarray = (Id *)xmalloc((1 + IDARRAY_BLOCK) * sizeof(Id));
82 if (!olddeps) /* no deps yet */
84 olddeps = idarraysize;
85 if ((idarraysize & IDARRAY_BLOCK) == 0)
86 idarray = (Id *)xrealloc(idarray, (idarraysize + 1 + IDARRAY_BLOCK) * sizeof(Id));
88 else if (olddeps == repo->lastoff) /* extend at end */
90 else /* can't extend, copy old */
93 olddeps = idarraysize;
94 for (; idarray[i]; i++)
96 if ((idarraysize & IDARRAY_BLOCK) == 0)
97 idarray = (Id *)xrealloc(idarray, (idarraysize + 1 + IDARRAY_BLOCK) * sizeof(Id));
98 idarray[idarraysize++] = idarray[i];
100 if ((idarraysize & IDARRAY_BLOCK) == 0)
101 idarray = (Id *)xrealloc(idarray, (idarraysize + 1 + IDARRAY_BLOCK) * sizeof(Id));
104 idarray[idarraysize++] = id; /* insert Id into array */
106 if ((idarraysize & IDARRAY_BLOCK) == 0) /* realloc if at block boundary */
107 idarray = (Id *)xrealloc(idarray, (idarraysize + 1 + IDARRAY_BLOCK) * sizeof(Id));
109 idarray[idarraysize++] = 0; /* ensure NULL termination */
111 repo->idarraydata = idarray;
112 repo->idarraysize = idarraysize;
113 repo->lastoff = olddeps;
120 * add dependency (as Id) to repo
121 * olddeps = offset into idarraydata
122 * isreq = 0 for normal dep
123 * isreq = 1 for requires
124 * isreq = 2 for pre-requires
129 repo_addid_dep(Repo *repo, Offset olddeps, Id id, int isreq)
131 Id oid, *oidp, *marker = 0;
134 return repo_addid(repo, olddeps, id);
138 for (oidp = repo->idarraydata + olddeps; (oid = *oidp) != ID_NULL; oidp++)
143 return repo_addid(repo, olddeps, id);
146 for (oidp = repo->idarraydata + olddeps; (oid = *oidp) != ID_NULL; oidp++)
148 if (oid == SOLVABLE_PREREQMARKER)
156 if (marker || isreq == 1)
159 for (; (oid = *oidp) != ID_NULL; oidp++)
160 if (oid == SOLVABLE_PREREQMARKER)
166 memmove(marker, marker + 1, (oidp - marker) * sizeof(Id));
167 *oidp = SOLVABLE_PREREQMARKER;
168 return repo_addid(repo, olddeps, id);
172 memmove(marker, marker + 1, (oidp - marker) * sizeof(Id));
176 if (isreq == 2 && !marker)
177 olddeps = repo_addid(repo, olddeps, SOLVABLE_PREREQMARKER);
178 else if (isreq == 1 && marker)
183 memmove(marker + 1, marker, (oidp - marker) * sizeof(Id));
184 *marker = SOLVABLE_PREREQMARKER;
186 return repo_addid(repo, olddeps, id);
192 * make space for 'num' more dependencies
196 repo_reserve_ids(Repo *repo, Offset olddeps, int num)
198 num++; /* room for trailing ID_NULL */
200 if (!repo->idarraysize) /* ensure buffer space */
202 repo->idarraysize = 1;
203 repo->idarraydata = (Id *)xmalloc(((1 + num + IDARRAY_BLOCK) & ~IDARRAY_BLOCK) * sizeof(Id));
204 repo->idarraydata[0] = 0;
209 if (olddeps && olddeps != repo->lastoff) /* if not appending */
211 /* can't insert into idarray, this would invalidate all 'larger' offsets
212 * so create new space at end and move existing deps there.
213 * Leaving 'hole' at old position.
219 for (idstart = idend = repo->idarraydata + olddeps; *idend++; ) /* find end */
221 count = idend - idstart - 1 + num; /* new size */
223 /* realloc if crossing block boundary */
224 if (((repo->idarraysize - 1) | IDARRAY_BLOCK) != ((repo->idarraysize + count - 1) | IDARRAY_BLOCK))
225 repo->idarraydata = (Id *)xrealloc(repo->idarraydata, ((repo->idarraysize + count + IDARRAY_BLOCK) & ~IDARRAY_BLOCK) * sizeof(Id));
227 /* move old deps to end */
228 olddeps = repo->lastoff = repo->idarraysize;
229 memcpy(repo->idarraydata + olddeps, idstart, count - num);
230 repo->idarraysize = olddeps + count - num;
235 if (olddeps) /* appending */
238 /* realloc if crossing block boundary */
239 if (((repo->idarraysize - 1) | IDARRAY_BLOCK) != ((repo->idarraysize + num - 1) | IDARRAY_BLOCK))
240 repo->idarraydata = (Id *)xrealloc(repo->idarraydata, ((repo->idarraysize + num + IDARRAY_BLOCK) & ~IDARRAY_BLOCK) * sizeof(Id));
242 /* appending or new */
243 repo->lastoff = olddeps ? olddeps : repo->idarraysize;
245 return repo->lastoff;
250 * remove repo from pool, zero out solvables
255 repo_free(Repo *repo, int reuseids)
257 Pool *pool = repo->pool;
261 pool_freewhatprovides(pool);
263 if (reuseids && repo->end == pool->nsolvables)
265 /* it's ok to reuse the ids. As this is the last repo, we can
266 just shrink the solvable array */
267 for (i = repo->end - 1, s = pool->solvables + i; i >= repo->start; i--, s--)
271 pool->nsolvables = i + 1;
273 /* zero out solvables belonging to this repo */
274 for (i = repo->start, s = pool->solvables + i; i < repo->end; i++, s++)
276 memset(s, 0, sizeof(*s));
277 for (i = 0; i < pool->nrepos; i++) /* find repo in pool */
278 if (pool->repos[i] == repo)
280 if (i == pool->nrepos) /* repo not in pool, return */
282 if (i < pool->nrepos - 1)
283 memmove(pool->repos + i, pool->repos + i + 1, (pool->nrepos - 1 - i) * sizeof(Repo *));
289 pool_freeallrepos(Pool *pool, int reuseids)
293 pool_freewhatprovides(pool);
294 for (i = 0; i < pool->nrepos; i++)
295 repo_freedata(pool->repos[i]);
296 /* the first two solvables don't belong to a repo */
297 if (pool->nsolvables > 2 && !reuseids)
298 memset(pool->solvables + 2, 0, (pool->nsolvables - 2) * sizeof(Solvable));
299 pool->repos = xfree(pool->repos);
302 pool->nsolvables = 2;
306 repo_fix_legacy(Repo *repo, Offset provides, Offset supplements)
308 Pool *pool = repo->pool;
309 Id id, idp, idl, idns;
310 char buf[1024], *p, *dep;
315 for (i = provides; repo->idarraydata[i]; i++)
317 id = repo->idarraydata[i];
320 dep = (char *)id2str(pool, id);
321 if (!strncmp(dep, "locale(", 7) && strlen(dep) < sizeof(buf) - 2)
324 strcpy(buf + 2, dep);
326 if ((p = strchr(dep, ':')) != 0 && p != dep)
329 idp = str2id(pool, dep, 1);
333 while ((p = strchr(dep, ';')) != 0)
340 strncpy(dep - 9, "language:", 9);
342 idl = str2id(pool, dep - 9, 1);
344 id = rel2id(pool, id, idl, REL_OR, 1);
349 if (dep[0] && dep[1])
351 for (p = dep; *p && *p != ')'; p++)
354 strncpy(dep - 9, "language:", 9);
355 idl = str2id(pool, dep - 9, 1);
357 id = rel2id(pool, id, idl, REL_OR, 1);
362 id = rel2id(pool, idp, id, REL_AND, 1);
364 supplements = repo_addid_dep(repo, supplements, id, 0);
366 else if ((p = strchr(dep, ':')) != 0 && p != dep && p[1] == '/' && strlen(dep) < sizeof(buf))
371 idp = str2id(pool, buf, 1);
372 idns = str2id(pool, "namespace:installed", 1);
373 id = str2id(pool, p, 1);
374 id = rel2id(pool, idns, id, REL_NAMESPACE, 1);
375 id = rel2id(pool, idp, id, REL_AND, 1);
376 supplements = repo_addid_dep(repo, supplements, id, 0);
382 for (i = supplements; repo->idarraydata[i]; i++)
384 id = repo->idarraydata[i];
387 dep = (char *)id2str(pool, id);
388 if (!strncmp(dep, "system:modalias(", 16))
390 if (!strncmp(dep, "modalias(", 9) && dep[9] && dep[10] && strlen(dep) < sizeof(buf))
393 p = strchr(buf + 9, ':');
394 idns = str2id(pool, "namespace:modalias", 1);
395 if (p && p != buf + 9 && strchr(p + 1, ':'))
398 idp = str2id(pool, buf + 9, 1);
399 p[strlen(p) - 1] = 0;
400 id = str2id(pool, p, 1);
401 id = rel2id(pool, idns, id, REL_NAMESPACE, 1);
402 id = rel2id(pool, idp, id, REL_AND, 1);
407 p[strlen(p) - 1] = 0;
408 id = str2id(pool, p, 1);
409 id = rel2id(pool, idns, id, REL_NAMESPACE, 1);
412 repo->idarraydata[i] = id;
414 else if (!strncmp(dep, "packageand(", 11) && strlen(dep) < sizeof(buf))
419 while ((p = strchr(dep, ':')) != 0)
427 idp = str2id(pool, dep, 1);
429 id = rel2id(pool, id, idp, REL_AND, 1);
434 if (dep[0] && dep[1])
436 dep[strlen(dep) - 1] = 0;
437 idp = str2id(pool, dep, 1);
439 id = rel2id(pool, id, idp, REL_AND, 1);
444 repo->idarraydata[i] = id;