add repo_add_rpmdb_reffp to easily add rpmdb content when there is an old solv file
authorMichael Schroeder <mls@suse.de>
Tue, 23 Apr 2013 13:18:20 +0000 (15:18 +0200)
committerMichael Schroeder <mls@suse.de>
Tue, 23 Apr 2013 13:18:20 +0000 (15:18 +0200)
examples/solv.c
ext/libsolvext.ver
ext/repo_rpmdb.c
ext/repo_rpmdb.h
src/libsolv.ver
src/repo.c
src/repo.h
tools/rpmdb2solv.c

index fbe7788..ceed784 100644 (file)
@@ -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))
index bb0270a..6ebcb46 100644 (file)
@@ -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;
index c3fa5ec..e33ad32 100644 (file)
@@ -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)
index a0d8a81..a63d6f2 100644 (file)
@@ -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)
index 1f21e4a..ffeb498 100644 (file)
@@ -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;
index 146df07..9ea328f 100644 (file)
@@ -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
index 0684827..ad27449 100644 (file)
@@ -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);
index 1a63755..c0a2fc3 100644 (file)
@@ -36,9 +36,8 @@ static void
 usage(int status)
 {
   fprintf(stderr, "\nUsage:\n"
-         "rpmdb2solv [-n] [-x] [-b <basefile>] [-p <productsdir>] [-r <root>]\n"
+         "rpmdb2solv [-n] [-b <basefile>] [-p <productsdir>] [-r <root>]\n"
          " -n : No packages, do not read rpmdb, useful to only parse products\n"
-         " -x : use extrapool\n"
          " -b <basefile> : Write .solv to <basefile>.solv instead of stdout\n"
          " -p <productsdir> : Scan <productsdir> for .prod files, representing installed products\n"
          " -r <root> : Prefix rpmdb path and <productsdir> with <root>\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);