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;
49 repo_freedata(Repo *repo)
51 xfree(repo->idarraydata);
53 xfree((char *)repo->name);
59 * olddeps = old array to extend
64 repo_addid(Repo *repo, Offset olddeps, Id id)
70 idarray = repo->idarraydata;
71 idarraysize = repo->idarraysize;
73 if (!idarray) /* alloc idarray if not done yet */
75 idarray = (Id *)xmalloc((1 + IDARRAY_BLOCK) * sizeof(Id));
81 if (!olddeps) /* no deps yet */
83 olddeps = idarraysize;
84 if ((idarraysize & IDARRAY_BLOCK) == 0)
85 idarray = (Id *)xrealloc(idarray, (idarraysize + 1 + IDARRAY_BLOCK) * sizeof(Id));
87 else if (olddeps == repo->lastoff) /* extend at end */
89 else /* can't extend, copy old */
92 olddeps = idarraysize;
93 for (; idarray[i]; i++)
95 if ((idarraysize & IDARRAY_BLOCK) == 0)
96 idarray = (Id *)xrealloc(idarray, (idarraysize + 1 + IDARRAY_BLOCK) * sizeof(Id));
97 idarray[idarraysize++] = idarray[i];
99 if ((idarraysize & IDARRAY_BLOCK) == 0)
100 idarray = (Id *)xrealloc(idarray, (idarraysize + 1 + IDARRAY_BLOCK) * sizeof(Id));
103 idarray[idarraysize++] = id; /* insert Id into array */
105 if ((idarraysize & IDARRAY_BLOCK) == 0) /* realloc if at block boundary */
106 idarray = (Id *)xrealloc(idarray, (idarraysize + 1 + IDARRAY_BLOCK) * sizeof(Id));
108 idarray[idarraysize++] = 0; /* ensure NULL termination */
110 repo->idarraydata = idarray;
111 repo->idarraysize = idarraysize;
112 repo->lastoff = olddeps;
119 * add dependency (as Id) to repo
120 * olddeps = offset into idarraydata
121 * isreq = 0 for normal dep
122 * isreq = 1 for requires
123 * isreq = 2 for pre-requires
128 repo_addid_dep(Repo *repo, Offset olddeps, Id id, int isreq)
130 Id oid, *oidp, *marker = 0;
133 return repo_addid(repo, olddeps, id);
137 for (oidp = repo->idarraydata + olddeps; (oid = *oidp) != ID_NULL; oidp++)
142 return repo_addid(repo, olddeps, id);
145 for (oidp = repo->idarraydata + olddeps; (oid = *oidp) != ID_NULL; oidp++)
147 if (oid == SOLVABLE_PREREQMARKER)
155 if (marker || isreq == 1)
158 for (; (oid = *oidp) != ID_NULL; oidp++)
159 if (oid == SOLVABLE_PREREQMARKER)
165 memmove(marker, marker + 1, (oidp - marker) * sizeof(Id));
166 *oidp = SOLVABLE_PREREQMARKER;
167 return repo_addid(repo, olddeps, id);
171 memmove(marker, marker + 1, (oidp - marker) * sizeof(Id));
175 if (isreq == 2 && !marker)
176 olddeps = repo_addid(repo, olddeps, SOLVABLE_PREREQMARKER);
177 else if (isreq == 1 && marker)
182 memmove(marker + 1, marker, (oidp - marker) * sizeof(Id));
183 *marker = SOLVABLE_PREREQMARKER;
185 return repo_addid(repo, olddeps, id);
191 * make space for 'num' more dependencies
195 repo_reserve_ids(Repo *repo, Offset olddeps, int num)
197 num++; /* room for trailing ID_NULL */
199 if (!repo->idarraysize) /* ensure buffer space */
201 repo->idarraysize = 1;
202 repo->idarraydata = (Id *)xmalloc(((1 + num + IDARRAY_BLOCK) & ~IDARRAY_BLOCK) * sizeof(Id));
203 repo->idarraydata[0] = 0;
208 if (olddeps && olddeps != repo->lastoff) /* if not appending */
210 /* can't insert into idarray, this would invalidate all 'larger' offsets
211 * so create new space at end and move existing deps there.
212 * Leaving 'hole' at old position.
218 for (idstart = idend = repo->idarraydata + olddeps; *idend++; ) /* find end */
220 count = idend - idstart - 1 + num; /* new size */
222 /* realloc if crossing block boundary */
223 if (((repo->idarraysize - 1) | IDARRAY_BLOCK) != ((repo->idarraysize + count - 1) | IDARRAY_BLOCK))
224 repo->idarraydata = (Id *)xrealloc(repo->idarraydata, ((repo->idarraysize + count + IDARRAY_BLOCK) & ~IDARRAY_BLOCK) * sizeof(Id));
226 /* move old deps to end */
227 olddeps = repo->lastoff = repo->idarraysize;
228 memcpy(repo->idarraydata + olddeps, idstart, count - num);
229 repo->idarraysize = olddeps + count - num;
234 if (olddeps) /* appending */
237 /* realloc if crossing block boundary */
238 if (((repo->idarraysize - 1) | IDARRAY_BLOCK) != ((repo->idarraysize + num - 1) | IDARRAY_BLOCK))
239 repo->idarraydata = (Id *)xrealloc(repo->idarraydata, ((repo->idarraysize + num + IDARRAY_BLOCK) & ~IDARRAY_BLOCK) * sizeof(Id));
241 /* appending or new */
242 repo->lastoff = olddeps ? olddeps : repo->idarraysize;
244 return repo->lastoff;
249 * remove repo from pool
254 repo_free(Repo *repo)
256 Pool *pool = repo->pool;
259 pool_freewhatprovides(pool);
261 for (i = 0; i < pool->nrepos; i++) /* find repo in pool */
263 if (pool->repos[i] == repo)
266 if (i == pool->nrepos) /* repo not in pool, return */
270 * all repos point into pool->solvables _relatively_ to repo->start
271 * so closing the gap only needs adaption of repo->start for all
275 nsolvables = repo->nsolvables;
276 if (pool->nsolvables > repo->start + nsolvables)
277 memmove(pool->solvables + repo->start, pool->solvables + repo->start + nsolvables, (pool->nsolvables - repo->start - nsolvables) * sizeof(Solvable));
278 pool->nsolvables -= nsolvables;
280 for (; i < pool->nrepos - 1; i++)
282 pool->repos[i] = pool->repos[i + 1]; /* remove repo */
283 pool->repos[i]->start -= nsolvables; /* adapt start offset of remaining repos */
290 pool_freeallrepos(Pool *pool)
293 for (i = 0; i < pool->nrepos; i++)
294 repo_freedata(pool->repos[i]);
295 pool->repos = xfree(pool->repos);
300 repo_fix_legacy(Repo *repo, Offset provides, Offset supplements)
302 Pool *pool = repo->pool;
303 Id id, idp, idl, idns;
304 char buf[1024], *p, *dep;
309 for (i = provides; repo->idarraydata[i]; i++)
311 id = repo->idarraydata[i];
314 dep = (char *)id2str(pool, id);
315 if (!strncmp(dep, "locale(", 7) && strlen(dep) < sizeof(buf) - 2)
318 strcpy(buf + 2, dep);
320 if ((p = strchr(dep, ':')) != 0 && p != dep)
323 idp = str2id(pool, dep, 1);
327 while ((p = strchr(dep, ';')) != 0)
334 strncpy(dep - 9, "language:", 9);
336 idl = str2id(pool, dep - 9, 1);
338 id = rel2id(pool, id, idl, REL_OR, 1);
343 if (dep[0] && dep[1])
345 for (p = dep; *p && *p != ')'; p++)
348 strncpy(dep - 9, "language:", 9);
349 idl = str2id(pool, dep - 9, 1);
351 id = rel2id(pool, id, idl, REL_OR, 1);
356 id = rel2id(pool, idp, id, REL_AND, 1);
358 supplements = repo_addid_dep(repo, supplements, id, 0);
360 else if ((p = strchr(dep, ':')) != 0 && p != dep && p[1] == '/' && strlen(dep) < sizeof(buf))
365 idp = str2id(pool, buf, 1);
366 idns = str2id(pool, "namespace:installed", 1);
367 id = str2id(pool, p, 1);
368 id = rel2id(pool, idns, id, REL_NAMESPACE, 1);
369 id = rel2id(pool, idp, id, REL_AND, 1);
370 supplements = repo_addid_dep(repo, supplements, id, 0);
376 for (i = supplements; repo->idarraydata[i]; i++)
378 id = repo->idarraydata[i];
381 dep = (char *)id2str(pool, id);
382 if (!strncmp(dep, "system:modalias(", 16))
384 if (!strncmp(dep, "modalias(", 9) && dep[9] && dep[10] && strlen(dep) < sizeof(buf))
387 p = strchr(buf + 9, ':');
388 idns = str2id(pool, "namespace:modalias", 1);
389 if (p && p != buf + 9 && strchr(p + 1, ':'))
392 idp = str2id(pool, buf + 9, 1);
393 p[strlen(p) - 1] = 0;
394 id = str2id(pool, p, 1);
395 id = rel2id(pool, idns, id, REL_NAMESPACE, 1);
396 id = rel2id(pool, idp, id, REL_AND, 1);
401 p[strlen(p) - 1] = 0;
402 id = str2id(pool, p, 1);
403 id = rel2id(pool, idns, id, REL_NAMESPACE, 1);
406 repo->idarraydata[i] = id;
408 else if (!strncmp(dep, "packageand(", 11) && strlen(dep) < sizeof(buf))
413 while ((p = strchr(dep, ':')) != 0)
421 idp = str2id(pool, dep, 1);
423 id = rel2id(pool, id, idp, REL_AND, 1);
428 if (dep[0] && dep[1])
430 dep[strlen(dep) - 1] = 0;
431 idp = str2id(pool, dep, 1);
433 id = rel2id(pool, id, idp, REL_AND, 1);
438 repo->idarraydata[i] = id;