+ int i;
+ for (i = 1; i < repo->nrepodata; i++)
+ repodata_freedata(repo->repodata + i);
+ solv_free(repo->repodata);
+ solv_free(repo->idarraydata);
+ solv_free(repo->rpmdbid);
+ solv_free(repo->lastidhash);
+ solv_free((char *)repo->name);
+ solv_free(repo);
+}
+
+/* delete all solvables and repodata blocks from this repo */
+
+void
+repo_empty(Repo *repo, int reuseids)
+{
+ Pool *pool = repo->pool;
+ Solvable *s;
+ int i;
+
+ pool_freewhatprovides(pool);
+ if (reuseids && repo->end == pool->nsolvables)
+ {
+ /* it's ok to reuse the ids. As this is the last repo, we can
+ just shrink the solvable array */
+ for (i = repo->end - 1, s = pool->solvables + i; i >= repo->start; i--, s--)
+ if (s->repo != repo)
+ break;
+ pool_free_solvable_block(pool, i + 1, repo->end - (i + 1), reuseids);
+ repo->end = i + 1;
+ }
+ /* zero out (i.e. free) solvables belonging to this repo */
+ for (i = repo->start, s = pool->solvables + i; i < repo->end; i++, s++)
+ if (s->repo == repo)
+ memset(s, 0, sizeof(*s));
+ repo->end = repo->start;
+ repo->nsolvables = 0;
+
+ /* free all data belonging to this repo */
+ repo->idarraydata = solv_free(repo->idarraydata);
+ repo->idarraysize = 0;
+ repo->lastoff = 0;
+ repo->rpmdbid = solv_free(repo->rpmdbid);
+ for (i = 1; i < repo->nrepodata; i++)
+ repodata_freedata(repo->repodata + i);
+ solv_free(repo->repodata);
+ repo->repodata = 0;
+ repo->nrepodata = 0;
+}
+
+/*
+ * remove repo from pool, delete solvables
+ *
+ */
+
+void
+repo_free(Repo *repo, int reuseids)
+{
+ Pool *pool = repo->pool;
+ int i;
+
+ if (repo == pool->installed)
+ pool->installed = 0;
+ repo_empty(repo, reuseids);
+ for (i = 1; i < pool->nrepos; i++) /* find repo in pool */
+ if (pool->repos[i] == repo)
+ break;
+ if (i == pool->nrepos) /* repo not in pool, return */
+ return;
+ if (i == pool->nrepos - 1 && reuseids)
+ pool->nrepos--;
+ else
+ pool->repos[i] = 0;
+ pool->urepos--;
+ repo_freedata(repo);
+}
+
+Id
+repo_add_solvable(Repo *repo)
+{
+ Id p = pool_add_solvable(repo->pool);
+ if (!repo->start || repo->start == repo->end)
+ repo->start = repo->end = p;
+ /* warning: sidedata must be extended before adapting start/end */
+ if (repo->rpmdbid)
+ repo->rpmdbid = (Id *)repo_sidedata_extend(repo, repo->rpmdbid, sizeof(Id), p, 1);
+ if (p < repo->start)
+ repo->start = p;
+ if (p + 1 > repo->end)
+ repo->end = p + 1;
+ repo->nsolvables++;
+ repo->pool->solvables[p].repo = repo;
+ return p;
+}
+
+Id
+repo_add_solvable_block(Repo *repo, int count)
+{
+ Id p;
+ Solvable *s;
+ if (!count)
+ return 0;
+ p = pool_add_solvable_block(repo->pool, count);
+ if (!repo->start || repo->start == repo->end)
+ repo->start = repo->end = p;
+ /* warning: sidedata must be extended before adapting start/end */
+ if (repo->rpmdbid)
+ repo->rpmdbid = (Id *)repo_sidedata_extend(repo, repo->rpmdbid, sizeof(Id), p, count);
+ if (p < repo->start)
+ repo->start = p;
+ if (p + count > repo->end)
+ repo->end = p + count;
+ repo->nsolvables += count;
+ for (s = repo->pool->solvables + p; count--; s++)
+ s->repo = repo;
+ return p;
+}
+
+void
+repo_free_solvable(Repo *repo, Id p, int reuseids)
+{
+ repo_free_solvable_block(repo, p, 1, reuseids);
+}
+
+void
+repo_free_solvable_block(Repo *repo, Id start, int count, int reuseids)
+{
+ Solvable *s;
+ Repodata *data;
+ int i;
+ if (start + count == repo->end)
+ repo->end -= count;
+ repo->nsolvables -= count;
+ for (s = repo->pool->solvables + start, i = count; i--; s++)
+ s->repo = 0;
+ pool_free_solvable_block(repo->pool, start, count, reuseids);
+ FOR_REPODATAS(repo, i, data)
+ {
+ int dstart, dend;
+ if (data->end > repo->end)
+ repodata_shrink(data, repo->end);
+ dstart = data->start > start ? data->start : start;
+ dend = data->end < start + count ? data->end : start + count;
+ if (dstart < dend)
+ {
+ if (data->attrs)
+ {
+ int j;
+ for (j = dstart; j < dend; j++)
+ data->attrs[j - data->start] = solv_free(data->attrs[j - data->start]);
+ }
+ if (data->incoreoffset)
+ memset(data->incoreoffset + (dstart - data->start), 0, (dend - dstart) * sizeof(Id));
+ }
+ }
+}
+
+/* specialized version of repo_add_solvable_block that inserts the new solvable
+ * block before the indicated repo, which gets relocated.
+ * used in repo_add_rpmdb
+ */
+Id
+repo_add_solvable_block_before(Repo *repo, int count, Repo *beforerepo)
+{
+ Pool *pool = repo->pool;
+ Id p;
+ Solvable *s;
+ Repodata *data;
+ int i;
+
+ if (!count || !beforerepo || beforerepo->end != pool->nsolvables || beforerepo->start == beforerepo->end)
+ return repo_add_solvable_block(repo, count);
+ p = beforerepo->start;
+ /* make sure all solvables belong to beforerepo */
+ for (i = p, s = pool->solvables + i; i < beforerepo->end; i++, s++)
+ if (s->repo && s->repo != beforerepo)
+ return repo_add_solvable_block(repo, count);
+ /* now move beforerepo to back */
+ pool_add_solvable_block(pool, count); /* must return beforerepo->end! */
+ memmove(pool->solvables + p + count, pool->solvables + p, (beforerepo->end - p) * sizeof(Solvable));
+ memset(pool->solvables + p, 0, sizeof(Solvable) * count);
+ /* adapt repodata */
+ FOR_REPODATAS(beforerepo, i, data)
+ {
+ if (data->start < p)
+ continue;
+ data->start += count;
+ data->end += count;
+ }
+ beforerepo->start += count;
+ beforerepo->end += count;
+ /* we now have count free solvables at id p */
+ /* warning: sidedata must be extended before adapting start/end */
+ if (repo->rpmdbid)
+ repo->rpmdbid = (Id *)repo_sidedata_extend(repo, repo->rpmdbid, sizeof(Id), p, count);
+ if (p < repo->start)
+ repo->start = p;
+ if (p + count > repo->end)
+ repo->end = p + count;
+ repo->nsolvables += count;
+ for (s = pool->solvables + p; count--; s++)
+ s->repo = repo;
+ return p;
+}
+
+
+/* repository sidedata is solvable data allocated on demand.
+ * It is used for data that is normally not present
+ * in the solvable like the rpmdbid.
+ * The solvable allocation funcions need to make sure that
+ * the sidedata gets extended if new solvables get added.
+ */
+
+#define REPO_SIDEDATA_BLOCK 63
+
+void *
+repo_sidedata_create(Repo *repo, size_t size)
+{
+ return solv_calloc_block(repo->end - repo->start, size, REPO_SIDEDATA_BLOCK);
+}
+
+void *
+repo_sidedata_extend(Repo *repo, void *b, size_t size, Id p, int count)
+{
+ int n = repo->end - repo->start;
+ if (p < repo->start)
+ {
+ int d = repo->start - p;
+ b = solv_extend(b, n, d, size, REPO_SIDEDATA_BLOCK);
+ memmove((char *)b + d * size, b, n * size);
+ memset(b, 0, d * size);
+ n += d;
+ }
+ if (p + count > repo->end)
+ {
+ int d = p + count - repo->end;
+ b = solv_extend(b, n, d, size, REPO_SIDEDATA_BLOCK);
+ memset((char *)b + n * size, 0, d * size);
+ }
+ return b;