From: Michael Schroeder Date: Tue, 23 Apr 2013 13:18:20 +0000 (+0200) Subject: add repo_add_rpmdb_reffp to easily add rpmdb content when there is an old solv file X-Git-Tag: BASE-SuSE-Code-12_3-Branch~15 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=843dc7e190acc4e55c3613a8ae05b43dd73bfa33;p=thirdparty%2Flibsolv.git add repo_add_rpmdb_reffp to easily add rpmdb content when there is an old solv file --- diff --git a/examples/solv.c b/examples/solv.c index fbe77881..ceed784d 100644 --- a/examples/solv.c +++ b/examples/solv.c @@ -1723,8 +1723,7 @@ read_repos(Pool *pool, struct repoinfo *repoinfos, int nrepoinfos) else { #if defined(ENABLE_RPMDB) && (defined(SUSE) || defined(FEDORA)) - FILE *ofp; - Repo *ref = 0; + FILE *ofp = 0; #endif printf(" reading\n"); @@ -1736,23 +1735,14 @@ read_repos(Pool *pool, struct repoinfo *repoinfos, int nrepoinfos) exit(1); } # endif - if ((ofp = fopen(calccachepath(repo, 0), "r")) != 0) - { - ref = repo_create(pool, "@System.old"); - if (repo_add_solv(ref, ofp, 0)) - { - repo_free(ref, 1); - ref = 0; - } - fclose(ofp); - } - if (repo_add_rpmdb(repo, ref, REPO_REUSE_REPODATA | REPO_USE_ROOTDIR)) + ofp = fopen(calccachepath(repo, 0), "r"); + if (repo_add_rpmdb_reffp(repo, ofp, REPO_REUSE_REPODATA | REPO_USE_ROOTDIR)) { fprintf(stderr, "installed db: %s\n", pool_errstr(pool)); exit(1); } - if (ref) - repo_free(ref, 1); + if (ofp) + fclose(ofp); #endif #if defined(ENABLE_DEBIAN) && defined(DEBIAN) if (repo_add_debdb(repo, REPO_REUSE_REPODATA | REPO_USE_ROOTDIR)) diff --git a/ext/libsolvext.ver b/ext/libsolvext.ver index bb0270a1..6ebcb46c 100644 --- a/ext/libsolvext.ver +++ b/ext/libsolvext.ver @@ -27,6 +27,7 @@ SOLV_1.0 { repo_add_rpm_handle; repo_add_rpmdb; repo_add_rpmdb_pubkeys; + repo_add_rpmdb_reffp; repo_add_rpmmd; repo_add_susetags; repo_add_updateinfoxml; diff --git a/ext/repo_rpmdb.c b/ext/repo_rpmdb.c index c3fa5ec8..e33ad329 100644 --- a/ext/repo_rpmdb.c +++ b/ext/repo_rpmdb.c @@ -46,6 +46,7 @@ #include "queue.h" #include "chksum.h" #include "repo_rpmdb.h" +#include "repo_solv.h" /* 3: added triggers */ /* 4: fixed triggers */ @@ -1355,29 +1356,12 @@ count_headers(Pool *pool, const char *rootdir, DB_ENV *dbenv) /******************************************************************/ -static Id -copyreldep(Pool *pool, Pool *frompool, Id id) -{ - Reldep *rd = GETRELDEP(frompool, id); - Id name = rd->name, evr = rd->evr; - if (ISRELDEP(name)) - name = copyreldep(pool, frompool, name); - else - name = pool_str2id(pool, pool_id2str(frompool, name), 1); - if (ISRELDEP(evr)) - evr = copyreldep(pool, frompool, evr); - else - evr = pool_str2id(pool, pool_id2str(frompool, evr), 1); - return pool_rel2id(pool, name, evr, rd->flags, 1); -} - static Offset copydeps(Pool *pool, Repo *repo, Offset fromoff, Repo *fromrepo) { int cc; - Id id, *ida, *from; + Id *ida, *from; Offset ido; - Pool *frompool = fromrepo->pool; if (!fromoff) return 0; @@ -1388,46 +1372,32 @@ copydeps(Pool *pool, Repo *repo, Offset fromoff, Repo *fromrepo) return 0; ido = repo_reserve_ids(repo, 0, cc); ida = repo->idarraydata + ido; - if (frompool && pool != frompool) - { - while (*from) - { - id = *from++; - if (ISRELDEP(id)) - id = copyreldep(pool, frompool, id); - else - id = pool_str2id(pool, pool_id2str(frompool, id), 1); - *ida++ = id; - } - *ida = 0; - } - else - memcpy(ida, from, (cc + 1) * sizeof(Id)); + memcpy(ida, from, (cc + 1) * sizeof(Id)); repo->idarraysize += cc + 1; return ido; } #define COPYDIR_DIRCACHE_SIZE 512 -static Id copydir_complex(Pool *pool, Repodata *data, Stringpool *fromspool, Repodata *fromdata, Id did, Id *cache); +static Id copydir_complex(Pool *pool, Repodata *data, Repodata *fromdata, Id did, Id *cache); static inline Id -copydir(Pool *pool, Repodata *data, Stringpool *fromspool, Repodata *fromdata, Id did, Id *cache) +copydir(Pool *pool, Repodata *data, Repodata *fromdata, Id did, Id *cache) { if (cache && cache[did & 255] == did) return cache[(did & 255) + 256]; - return copydir_complex(pool, data, fromspool, fromdata, did, cache); + return copydir_complex(pool, data, fromdata, did, cache); } static Id -copydir_complex(Pool *pool, Repodata *data, Stringpool *fromspool, Repodata *fromdata, Id did, Id *cache) +copydir_complex(Pool *pool, Repodata *data, Repodata *fromdata, Id did, Id *cache) { Id parent = dirpool_parent(&fromdata->dirpool, did); Id compid = dirpool_compid(&fromdata->dirpool, did); if (parent) - parent = copydir(pool, data, fromspool, fromdata, parent, cache); - if (fromspool != &pool->ss) - compid = pool_str2id(pool, stringpool_id2str(fromspool, compid), 1); + parent = copydir(pool, data, fromdata, parent, cache); + if (fromdata->localpool) + compid = repodata_globalize_id(fromdata, compid, 1); compid = dirpool_add_dir(&data->dirpool, parent, compid, 1); if (cache) { @@ -1451,26 +1421,18 @@ solvable_copy_cb(void *vcbdata, Solvable *r, Repodata *fromdata, Repokey *key, K Id id, keyname; Repodata *data = cbdata->data; Id handle = cbdata->handle; - Pool *pool = data->repo->pool, *frompool = fromdata->repo->pool; - Stringpool *fromspool = fromdata->localpool ? &fromdata->spool : &frompool->ss; + Pool *pool = data->repo->pool; keyname = key->name; - if (keyname >= ID_NUM_INTERNAL && pool != frompool) - keyname = pool_str2id(pool, pool_id2str(frompool, keyname), 1); switch(key->type) { case REPOKEY_TYPE_ID: case REPOKEY_TYPE_CONSTANTID: case REPOKEY_TYPE_IDARRAY: /* used for triggers */ id = kv->id; + if (fromdata->localpool) + id = repodata_globalize_id(fromdata, id, 1); assert(!data->localpool); /* implement me! */ - if (pool != frompool || fromdata->localpool) - { - if (ISRELDEP(id)) - id = copyreldep(pool, frompool, id); - else - id = pool_str2id(pool, stringpool_id2str(fromspool, id), 1); - } if (key->type == REPOKEY_TYPE_ID) repodata_set_id(data, handle, keyname, id); else if (key->type == REPOKEY_TYPE_CONSTANTID) @@ -1492,14 +1454,14 @@ solvable_copy_cb(void *vcbdata, Solvable *r, Repodata *fromdata, Repokey *key, K break; case REPOKEY_TYPE_DIRNUMNUMARRAY: id = kv->id; + id = copydir(pool, data, fromdata, id, cbdata->dircache); assert(!data->localpool); /* implement me! */ - id = copydir(pool, data, fromspool, fromdata, id, cbdata->dircache); repodata_add_dirnumnum(data, handle, keyname, id, kv->num, kv->num2); break; case REPOKEY_TYPE_DIRSTRARRAY: id = kv->id; + id = copydir(pool, data, fromdata, id, cbdata->dircache); assert(!data->localpool); /* implement me! */ - id = copydir(pool, data, fromspool, fromdata, id, cbdata->dircache); repodata_add_dirstr(data, handle, keyname, id, kv->str); break; case REPOKEY_TYPE_FLEXARRAY: @@ -1528,29 +1490,15 @@ static void solvable_copy(Solvable *s, Solvable *r, Repodata *data, Id *dircache) { Repo *repo = s->repo; - Repo *fromrepo = r->repo; Pool *pool = repo->pool; + Repo *fromrepo = r->repo; struct solvable_copy_cbdata cbdata; /* copy solvable data */ - if (pool == fromrepo->pool) - { - s->name = r->name; - s->evr = r->evr; - s->arch = r->arch; - s->vendor = r->vendor; - } - else - { - if (r->name) - s->name = pool_str2id(pool, pool_id2str(fromrepo->pool, r->name), 1); - if (r->evr) - s->evr = pool_str2id(pool, pool_id2str(fromrepo->pool, r->evr), 1); - if (r->arch) - s->arch = pool_str2id(pool, pool_id2str(fromrepo->pool, r->arch), 1); - if (r->vendor) - s->vendor = pool_str2id(pool, pool_id2str(fromrepo->pool, r->vendor), 1); - } + s->name = r->name; + s->evr = r->evr; + s->arch = r->arch; + s->vendor = r->vendor; s->provides = copydeps(pool, repo, r->provides, fromrepo); s->requires = copydeps(pool, repo, r->requires, fromrepo); s->conflicts = copydeps(pool, repo, r->conflicts, fromrepo); @@ -1655,8 +1603,12 @@ repo_add_rpmdb(Repo *repo, Repo *ref, int flags) data = repo_add_repodata(repo, flags); - if (ref && !(ref->nsolvables && ref->rpmdbid)) - ref = 0; + if (ref && !(ref->nsolvables && ref->rpmdbid && ref->pool == repo->pool)) + { + if ((flags & RPMDB_EMPTY_REFREPO) != 0) + repo_empty(ref, 1); + ref = 0; + } if (flags & REPO_USE_ROOTDIR) rootdir = pool_get_rootdir(pool); @@ -1682,6 +1634,8 @@ repo_add_rpmdb(Repo *repo, Repo *ref, int flags) Id dbid; DBC *dbc = 0; + if (ref && (flags & RPMDB_EMPTY_REFREPO) != 0) + repo_empty(ref, 1); /* get it out of the way */ if ((flags & RPMDB_REPORT_PROGRESS) != 0) count = count_headers(pool, rootdir, state.dbenv); if (!openpkgdb(&state)) @@ -1820,7 +1774,10 @@ repo_add_rpmdb(Repo *repo, Repo *ref, int flags) } } - s = pool_id2solvable(pool, repo_add_solvable_block(repo, nentries)); + if (ref && (flags & RPMDB_EMPTY_REFREPO) != 0) + s = pool_id2solvable(pool, repo_add_solvable_block_before(repo, nentries, ref)); + else + s = pool_id2solvable(pool, repo_add_solvable_block(repo, nentries)); if (!repo->rpmdbid) repo->rpmdbid = repo_sidedata_create(repo, sizeof(Id)); @@ -1871,6 +1828,8 @@ repo_add_rpmdb(Repo *repo, Repo *ref, int flags) solv_free(entries); solv_free(namedata); solv_free(refhash); + if (ref && (flags & RPMDB_EMPTY_REFREPO) != 0) + repo_empty(ref, 1); } freestate(&state); @@ -1884,6 +1843,32 @@ repo_add_rpmdb(Repo *repo, Repo *ref, int flags) return 0; } +int +repo_add_rpmdb_reffp(Repo *repo, FILE *fp, int flags) +{ + int res; + Repo *ref = 0; + + if (!fp) + return repo_add_rpmdb(repo, 0, flags); + ref = repo_create(repo->pool, "add_rpmdb_reffp"); + if (repo_add_solv(ref, fp, 0) != 0) + { + repo_free(ref, 1); + ref = 0; + } + if (ref && ref->start == ref->end) + { + repo_free(ref, 1); + ref = 0; + } + if (ref) + repo_disable_paging(ref); + res = repo_add_rpmdb(repo, ref, flags | RPMDB_EMPTY_REFREPO); + if (ref) + repo_free(ref, 1); + return res; +} static inline unsigned int getu32(const unsigned char *dp) diff --git a/ext/repo_rpmdb.h b/ext/repo_rpmdb.h index a0d8a815..a63d6f25 100644 --- a/ext/repo_rpmdb.h +++ b/ext/repo_rpmdb.h @@ -11,6 +11,7 @@ struct headerToken_s; extern int repo_add_rpmdb(Repo *repo, Repo *ref, int flags); +extern int repo_add_rpmdb_reffp(Repo *repo, FILE *reffp, int flags); extern Id repo_add_rpm(Repo *repo, const char *rpm, int flags); #define RPMDB_REPORT_PROGRESS (1 << 8) @@ -22,7 +23,9 @@ extern Id repo_add_rpm(Repo *repo, const char *rpm, int flags); #define RPM_ADD_TRIGGERS (1 << 14) #define RPM_ADD_WITH_HDRID (1 << 15) #define RPM_ADD_WITH_LEADSIGID (1 << 16) -#define RPM_ADD_WITH_CHANGELOG (1 << 17) +#define RPM_ADD_WITH_CHANGELOG (1 << 17) + +#define RPMDB_EMPTY_REFREPO (1 << 30) /* internal */ #define RPM_ITERATE_FILELIST_ONLYDIRS (1 << 0) #define RPM_ITERATE_FILELIST_WITHMD5 (1 << 1) diff --git a/src/libsolv.ver b/src/libsolv.ver index 1f21e4ac..ffeb4982 100644 --- a/src/libsolv.ver +++ b/src/libsolv.ver @@ -135,6 +135,7 @@ SOLV_1.0 { repo_add_solv; repo_add_solvable; repo_add_solvable_block; + repo_add_solvable_block_before; repo_addid; repo_addid_dep; repo_create; diff --git a/src/repo.c b/src/repo.c index 146df07f..9ea328f9 100644 --- a/src/repo.c +++ b/src/repo.c @@ -218,6 +218,54 @@ repo_free_solvable_block(Repo *repo, Id start, int count, int reuseids) } } +/* 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 diff --git a/src/repo.h b/src/repo.h index 06848278..ad27449b 100644 --- a/src/repo.h +++ b/src/repo.h @@ -67,6 +67,7 @@ extern void repo_free_solvable(Repo *repo, Id p, int reuseids); extern void repo_free_solvable_block(Repo *repo, Id start, int count, int reuseids); extern void *repo_sidedata_create(Repo *repo, size_t size); extern void *repo_sidedata_extend(Repo *repo, void *b, size_t size, Id p, int count); +extern Id repo_add_solvable_block_before(Repo *repo, int count, Repo *beforerepo); extern Offset repo_addid(Repo *repo, Offset olddeps, Id id); extern Offset repo_addid_dep(Repo *repo, Offset olddeps, Id id, Id marker); diff --git a/tools/rpmdb2solv.c b/tools/rpmdb2solv.c index 1a637557..c0a2fc3e 100644 --- a/tools/rpmdb2solv.c +++ b/tools/rpmdb2solv.c @@ -36,9 +36,8 @@ static void usage(int status) { fprintf(stderr, "\nUsage:\n" - "rpmdb2solv [-n] [-x] [-b ] [-p ] [-r ]\n" + "rpmdb2solv [-n] [-b ] [-p ] [-r ]\n" " -n : No packages, do not read rpmdb, useful to only parse products\n" - " -x : use extrapool\n" " -b : Write .solv to .solv instead of stdout\n" " -p : Scan for .prod files, representing installed products\n" " -r : Prefix rpmdb path and with \n" @@ -51,11 +50,11 @@ usage(int status) int main(int argc, char **argv) { + FILE *reffp = 0; Pool *pool = pool_create(); - Repo *repo, *ref = 0; + Repo *repo; Repodata *data; int c, percent = 0; - int extrapool = 0; int nopacks = 0; const char *root = 0; const char *basefile = 0; @@ -96,7 +95,6 @@ main(int argc, char **argv) #endif break; case 'x': - extrapool = 1; break; case 'o': outfile = optarg; @@ -127,28 +125,8 @@ main(int argc, char **argv) if (refname && !nopacks) { - FILE *fp; - if ((fp = fopen(refname, "r")) == NULL) - { - perror(refname); - } - else - { - Pool *refpool = extrapool ? pool_create() : 0; - ref = repo_create(refpool ? refpool : pool, "ref"); - if (repo_add_solv(ref, fp, 0) != 0) - { - fprintf(stderr, "%s: %s\n", refname, pool_errstr(ref->pool)); - if (ref->pool != pool) - pool_free(ref->pool); - else - repo_free(ref, 1); - ref = 0; - } - else - repo_disable_paging(ref); - fclose(fp); - } + if ((reffp = fopen(refname, "r")) == NULL) + perror(refname); } /* @@ -166,7 +144,7 @@ main(int argc, char **argv) if (!nopacks) { - if (repo_add_rpmdb(repo, ref, REPO_USE_ROOTDIR | REPO_REUSE_REPODATA | REPO_NO_INTERNALIZE | (percent ? RPMDB_REPORT_PROGRESS : 0))) + if (repo_add_rpmdb_reffp(repo, reffp, REPO_USE_ROOTDIR | REPO_REUSE_REPODATA | REPO_NO_INTERNALIZE | (percent ? RPMDB_REPORT_PROGRESS : 0))) { fprintf(stderr, "rpmdb2solv: %s\n", pool_errstr(pool)); exit(1); @@ -205,14 +183,8 @@ main(int argc, char **argv) #endif repodata_internalize(data); - if (ref) - { - if (ref->pool != pool) - pool_free(ref->pool); - else - repo_free(ref, 1); - ref = 0; - } + if (reffp) + fclose(reffp); tool_write(repo, basefile, 0); pool_free(pool);