- add new flags for the load functions:
authorMichael Schroeder <mls@suse.de>
Tue, 14 Jul 2009 16:34:49 +0000 (18:34 +0200)
committerMichael Schroeder <mls@suse.de>
Tue, 14 Jul 2009 16:34:49 +0000 (18:34 +0200)
  REPO_LOCALPOOL        - create local pool
  REPO_EXTEND_SOLVABLES - extend existing solvables instead of creating new ones
  REPO_USE_LOADING      - replace repodata in state loading
- add repo_add_solv_flags to make repo_add_solv use flags
- make repo_add_solv obey the flags instead of using defaults if this is a subload
- change loadcallback definition to return a boolean, the callback is now
  responsible for the loading
- change repo_write so that the keyfilter can select which repodata to use (hack)
- change pool_addfileprovides to load the complete filelist if needed
- add SEARCH_COMPLETE_FILELIST flag to searches
- add transaction_create_installedmap/transaction_calc_installsizechange

17 files changed:
examples/solv.c
ext/repo_rpmmd.c
ext/repo_susetags.c
ext/repo_susetags.h
ext/repo_write.c
src/pool.c
src/pool.h
src/repo.c
src/repo.h
src/repo_solv.c
src/repo_solv.h
src/repodata.c
src/repodata.h
src/transaction.c
src/transaction.h
tools/dumpsolv.c
tools/mergesolv.c

index 15878e4..e04221c 100644 (file)
@@ -72,6 +72,8 @@ struct repoinfo {
   int gpgcheck;
   int priority;
   int keeppackages;
+
+  unsigned char extcookie[32];
 };
 
 #ifdef FEDORA
@@ -556,10 +558,16 @@ setarch(Pool *pool)
   pool_setarch(pool, un.machine);
 }
 
-char *calccachepath(Repo *repo)
+char *calccachepath(Repo *repo, const char *repoext)
 {
   char *q, *p = pool_tmpjoin(repo->pool, SOLVCACHE_PATH, "/", repo->name);
-  p = pool_tmpjoin(repo->pool, p, ".solv", 0);
+  if (repoext)
+    {
+      p = pool_tmpjoin(repo->pool, p, "_", repoext);
+      p = pool_tmpjoin(repo->pool, p, ".solvx", 0);
+    }
+  else
+    p = pool_tmpjoin(repo->pool, p, ".solv", 0);
   q = p + strlen(SOLVCACHE_PATH) + 1;
   if (*q == '.')
     *q = '_';
@@ -570,12 +578,15 @@ char *calccachepath(Repo *repo)
 }
 
 int
-usecachedrepo(Repo *repo, unsigned char *cookie)
+usecachedrepo(Repo *repo, const char *repoext, unsigned char *cookie)
 {
   FILE *fp;
   unsigned char mycookie[32];
+  struct repoinfo *cinfo;
+  int flags = 0;
 
-  if (!(fp = fopen(calccachepath(repo), "r")))
+  cinfo = repo->appdata;
+  if (!(fp = fopen(calccachepath(repo, repoext), "r")))
     return 0;
   if (fseek(fp, -sizeof(mycookie), SEEK_END) || fread(mycookie, sizeof(mycookie), 1, fp) != 1)
     {
@@ -588,28 +599,53 @@ usecachedrepo(Repo *repo, unsigned char *cookie)
       return 0;
     }
   rewind(fp);
-  if (repo_add_solv(repo, fp))
+  if (repoext && !strcmp(repoext, "DL"))
+    flags = REPO_USE_LOADING|REPO_EXTEND_SOLVABLES;
+  else if (repoext)
+    flags = REPO_USE_LOADING|REPO_LOCALPOOL|REPO_EXTEND_SOLVABLES;
+
+  if (repo_add_solv_flags(repo, fp, flags))
     {
       fclose(fp);
       return 0;
     }
+  if (!repoext && cinfo)
+    {
+      struct stat stb;
+      if (!fstat(fileno(fp), &stb))
+        calc_checksum_stat(&stb, REPOKEY_TYPE_SHA256, cinfo->extcookie);
+    }
   fclose(fp);
   return 1;
 }
 
-void
-writecachedrepo(Repo *repo, unsigned char *cookie)
+int
+myrepodatafilter(Repo *repo, Repokey *key, void *kfdata)
+{
+  Repodata *data = kfdata;
+
+  if (key->name == 1 && key->size != data - repo->repodata)
+    return -1;
+  if (key->storage == KEY_STORAGE_SOLVABLE)
+    return KEY_STORAGE_DROPPED;
+  return repo_write_stdkeyfilter(repo, key, kfdata);
+}
+
+static void
+writecachedrepo(Repo *repo, Repodata *info, const char *repoext, unsigned char *cookie)
 {
   Id *addedfileprovides = 0;
   FILE *fp;
   int i, fd;
   char *tmpl;
-  Repodata *info;
+  int myinfo = 0;
+  struct repoinfo *cinfo;
 
+  cinfo = repo->appdata;
   mkdir(SOLVCACHE_PATH, 0755);
   tmpl = sat_dupjoin(SOLVCACHE_PATH, "/", ".newsolv-XXXXXX");
   fd = mkstemp(tmpl);
-  if (!fd)
+  if (fd < 0)
     {
       free(tmpl);
       return;
@@ -622,17 +658,27 @@ writecachedrepo(Repo *repo, unsigned char *cookie)
       free(tmpl);
       return;
     }
-  info = repo_add_repodata(repo, 0);
-  pool_addfileprovides_ids(repo->pool, 0, &addedfileprovides);
-  if (addedfileprovides && *addedfileprovides)
+  if (!repoext)
     {
-      for (i = 0; addedfileprovides[i]; i++)
-       repodata_add_idarray(info, SOLVID_META, REPOSITORY_ADDEDFILEPROVIDES, addedfileprovides[i]);
+      if (!info)
+       {
+         info = repo_add_repodata(repo, 0);
+         myinfo = 1;
+       }
+      pool_addfileprovides_ids(repo->pool, 0, &addedfileprovides);
+      if (addedfileprovides && *addedfileprovides)
+       {
+         for (i = 0; addedfileprovides[i]; i++)
+           repodata_add_idarray(info, SOLVID_META, REPOSITORY_ADDEDFILEPROVIDES, addedfileprovides[i]);
+       }
+      sat_free(addedfileprovides);
+      repodata_internalize(info);
+      repo_write(repo, fp, repo_write_stdkeyfilter, 0, 0);
     }
-  sat_free(addedfileprovides);
-  repodata_internalize(info);
-  repo_write(repo, fp, 0, 0, 0);
-  repodata_free(info);
+  else
+    repo_write(repo, fp, myrepodatafilter, info, 0);
+  if (myinfo)
+    repodata_free(info);
   if (fwrite(cookie, 32, 1, fp) != 1)
     {
       fclose(fp);
@@ -646,7 +692,13 @@ writecachedrepo(Repo *repo, unsigned char *cookie)
       free(tmpl);
       return;
     }
-  if (!rename(tmpl, calccachepath(repo)))
+  if (!repoext && cinfo)
+    {
+      struct stat stb;
+      if (!stat(tmpl, &stb))
+        calc_checksum_stat(&stb, REPOKEY_TYPE_SHA256, cinfo->extcookie);
+    }
+  if (!rename(tmpl, calccachepath(repo, repoext)))
     unlink(tmpl);
   free(tmpl);
 }
@@ -668,7 +720,7 @@ iscompressed(const char *name)
 }
 
 static inline const char *
-findinrepomd(Repo *repo, const char *what, const unsigned char **chksump, Id *chksumtypep)
+repomd_find(Repo *repo, const char *what, const unsigned char **chksump, Id *chksumtypep)
 {
   Pool *pool = repo->pool;
   Dataiterator di;
@@ -694,6 +746,228 @@ findinrepomd(Repo *repo, const char *what, const unsigned char **chksump, Id *ch
   return filename;
 }
 
+int
+repomd_add_ext(Repo *repo, Repodata *data, const char *what)
+{
+  Pool *pool = repo->pool;
+  Dataiterator di;
+  Id chksumtype, handle;
+  const unsigned char *chksum;
+  const char *filename;
+
+  dataiterator_init(&di, pool, repo, SOLVID_META, REPOSITORY_REPOMD_TYPE, what, SEARCH_STRING);
+  dataiterator_prepend_keyname(&di, REPOSITORY_REPOMD);
+  if (!dataiterator_step(&di))
+    {
+      dataiterator_free(&di);
+      return 0;
+    }
+  if (!strcmp(what, "prestodelta"))
+    what = "deltainfo";
+  dataiterator_setpos_parent(&di);
+  filename = pool_lookup_str(pool, SOLVID_POS, REPOSITORY_REPOMD_LOCATION);
+  chksum = pool_lookup_bin_checksum(pool, SOLVID_POS, REPOSITORY_REPOMD_CHECKSUM, &chksumtype);
+  if (!filename || !chksum)
+    {
+      dataiterator_free(&di);
+      return 0;
+    }
+  handle = repodata_new_handle(data);
+  repodata_set_poolstr(data, handle, REPOSITORY_REPOMD_TYPE, what);
+  repodata_set_str(data, handle, REPOSITORY_REPOMD_LOCATION, filename);
+  if (chksumtype)
+    repodata_set_bin_checksum(data, handle, REPOSITORY_REPOMD_CHECKSUM, chksumtype, chksum);
+  if (!strcmp(what, "deltainfo"))
+    {
+      repodata_add_idarray(data, handle, REPOSITORY_KEYS, REPOSITORY_DELTAINFO);
+      repodata_add_idarray(data, handle, REPOSITORY_KEYS, REPOKEY_TYPE_FLEXARRAY);
+      repodata_add_idarray(data, handle, REPOSITORY_KEYS, DELTA_PACKAGE_NAME);
+      repodata_add_idarray(data, handle, REPOSITORY_KEYS, REPOKEY_TYPE_ID);
+      repodata_add_idarray(data, handle, REPOSITORY_KEYS, DELTA_PACKAGE_EVR);
+      repodata_add_idarray(data, handle, REPOSITORY_KEYS, REPOKEY_TYPE_ID);
+      repodata_add_idarray(data, handle, REPOSITORY_KEYS, DELTA_PACKAGE_ARCH);
+      repodata_add_idarray(data, handle, REPOSITORY_KEYS, REPOKEY_TYPE_ID);
+      repodata_add_idarray(data, handle, REPOSITORY_KEYS, DELTA_BASE_EVR);
+      repodata_add_idarray(data, handle, REPOSITORY_KEYS, REPOKEY_TYPE_ID);
+    }
+  if (!strcmp(what, "filelists"))
+    {
+      repodata_add_idarray(data, handle, REPOSITORY_KEYS, SOLVABLE_FILELIST);
+      repodata_add_idarray(data, handle, REPOSITORY_KEYS, REPOKEY_TYPE_DIRSTRARRAY);
+    }
+  dataiterator_free(&di);
+  repodata_add_flexarray(data, SOLVID_META, REPOSITORY_EXTERNAL, handle);
+  return 1;
+}
+
+static inline const char *
+susetags_find(Repo *repo, const char *what, const unsigned char **chksump, Id *chksumtypep)
+{
+  Pool *pool = repo->pool;
+  Dataiterator di;
+  const char *filename;
+
+  filename = 0;
+  *chksump = 0;
+  *chksumtypep = 0;
+  dataiterator_init(&di, pool, repo, SOLVID_META, SUSETAGS_FILE_NAME, what, SEARCH_STRING);
+  dataiterator_prepend_keyname(&di, SUSETAGS_FILE);
+  if (dataiterator_step(&di))
+    {
+      dataiterator_setpos_parent(&di);
+      *chksump = pool_lookup_bin_checksum(pool, SOLVID_POS, SUSETAGS_FILE_CHECKSUM, chksumtypep);
+      filename = what;
+    }
+  dataiterator_free(&di);
+  if (filename && !*chksumtypep)
+    {
+      printf("no %s file checksum!\n", what);
+      filename = 0;
+    }
+  return filename;
+}
+
+
+int
+load_stub(Pool *pool, Repodata *data, void *dp)
+{
+  const char *filename, *descrdir, *repomdtype;
+  const unsigned char *filechksum;
+  Id filechksumtype;
+  struct repoinfo *cinfo;
+  FILE *fp;
+  Id defvendor;
+  char ext[3];
+
+  cinfo = data->repo->appdata;
+
+  filename = repodata_lookup_str(data, SOLVID_META, SUSETAGS_FILE_NAME);
+  if (filename)
+    {
+      /* susetags load */
+      ext[0] = filename[9];
+      ext[1] = filename[10];
+      ext[2] = 0;
+#if 1
+      printf("[%s:%s", data->repo->name, ext);
+#endif
+      if (usecachedrepo(data->repo, ext, cinfo->extcookie))
+       {
+          printf(" cached]"); fflush(stdout);
+         return 1;
+       }
+#if 1
+      printf(" loading]"); fflush(stdout);
+#endif
+      defvendor = repo_lookup_id(data->repo, SOLVID_META, SUSETAGS_DEFAULTVENDOR);
+      descrdir = repo_lookup_str(data->repo, SOLVID_META, SUSETAGS_DESCRDIR);
+      if (!descrdir)
+       descrdir = "suse/setup/descr";
+      filechksumtype = 0;
+      filechksum = repodata_lookup_bin_checksum(data, SOLVID_META, SUSETAGS_FILE_CHECKSUM, &filechksumtype);
+      if ((fp = curlfopen(cinfo, pool_tmpjoin(pool, descrdir, "/", filename), iscompressed(filename), filechksum, filechksumtype)) == 0)
+       return 0;
+      repo_add_susetags(data->repo, fp, defvendor, ext, REPO_USE_LOADING|REPO_EXTEND_SOLVABLES);
+      fclose(fp);
+      writecachedrepo(data->repo, data, ext, cinfo->extcookie);
+      return 1;
+    }
+
+  repomdtype = repodata_lookup_str(data, SOLVID_META, REPOSITORY_REPOMD_TYPE);
+  if (repomdtype)
+    {
+      if (!strcmp(repomdtype, "filelists"))
+       strcpy(ext, "FL");
+      else if (!strcmp(repomdtype, "deltainfo"))
+       strcpy(ext, "DL");
+      else
+       return 0;
+#if 1
+      printf("[%s:%s", data->repo->name, ext);
+#endif
+      if (usecachedrepo(data->repo, ext, cinfo->extcookie))
+       {
+         printf(" cached]");fflush(stdout);
+         return 1;
+       }
+      printf(" loading]"); fflush(stdout);
+      filename = repodata_lookup_str(data, SOLVID_META, REPOSITORY_REPOMD_LOCATION);
+      filechksumtype = 0;
+      filechksum = repodata_lookup_bin_checksum(data, SOLVID_META, SUSETAGS_FILE_CHECKSUM, &filechksumtype);
+      if ((fp = curlfopen(cinfo, filename, iscompressed(filename), filechksum, filechksumtype)) == 0)
+       return 0;
+      if (!strcmp(ext, "FL"))
+        repo_add_rpmmd(data->repo, fp, ext, REPO_USE_LOADING|REPO_EXTEND_SOLVABLES);
+      else if (!strcmp(ext, "DL"))
+        repo_add_deltainfoxml(data->repo, fp, REPO_USE_LOADING);
+      fclose(fp);
+      writecachedrepo(data->repo, data, ext, cinfo->extcookie);
+      return 1;
+    }
+
+  return 0;
+}
+
+Id susetags_langtags[] = {
+  SOLVABLE_SUMMARY, REPOKEY_TYPE_STR,
+  SOLVABLE_DESCRIPTION, REPOKEY_TYPE_STR,
+  SOLVABLE_EULA, REPOKEY_TYPE_STR,
+  SOLVABLE_MESSAGEINS, REPOKEY_TYPE_STR,
+  SOLVABLE_MESSAGEDEL, REPOKEY_TYPE_STR,
+  SOLVABLE_CATEGORY, REPOKEY_TYPE_ID,
+  0, 0
+};
+
+void
+susetags_add_ext(Repo *repo, Repodata *data)
+{
+  Pool *pool = repo->pool;
+  Dataiterator di;
+  char ext[3];
+  Id handle, filechksumtype;
+  const unsigned char *filechksum;
+  int i;
+
+  dataiterator_init(&di, pool, repo, SOLVID_META, SUSETAGS_FILE_NAME, 0, 0);
+  dataiterator_prepend_keyname(&di, SUSETAGS_FILE);
+  while (dataiterator_step(&di))
+    {
+      if (strncmp(di.kv.str, "packages.", 9) != 0)
+       continue;
+      if (!di.kv.str[9] || !di.kv.str[10] || (di.kv.str[11] && di.kv.str[11] != '.'))
+       continue;
+      ext[0] = di.kv.str[9];
+      ext[1] = di.kv.str[10];
+      ext[2] = 0;
+      if (!susetags_find(repo, di.kv.str, &filechksum, &filechksumtype))
+       continue;
+      handle = repodata_new_handle(data);
+      repodata_set_str(data, handle, SUSETAGS_FILE_NAME, di.kv.str);
+      if (filechksumtype)
+       repodata_set_bin_checksum(data, handle, SUSETAGS_FILE_CHECKSUM, filechksumtype, filechksum);
+      if (!strcmp(ext, "DU"))
+       {
+         repodata_add_idarray(data, handle, REPOSITORY_KEYS, SOLVABLE_DISKUSAGE);
+         repodata_add_idarray(data, handle, REPOSITORY_KEYS, REPOKEY_TYPE_DIRNUMNUMARRAY);
+       }
+      if (!strcmp(ext, "FL"))
+       {
+         repodata_add_idarray(data, handle, REPOSITORY_KEYS, SOLVABLE_FILELIST);
+         repodata_add_idarray(data, handle, REPOSITORY_KEYS, REPOKEY_TYPE_DIRSTRARRAY);
+       }
+      else
+       {
+         for (i = 0; susetags_langtags[i]; i += 2)
+           {
+             repodata_add_idarray(data, handle, REPOSITORY_KEYS, pool_id2langid(pool, susetags_langtags[i], ext, 1));
+             repodata_add_idarray(data, handle, REPOSITORY_KEYS, susetags_langtags[i + 1]);
+           }
+       }
+      repodata_add_flexarray(data, SOLVID_META, REPOSITORY_EXTERNAL, handle);
+    }
+  dataiterator_free(&di);
+}
+
 void
 read_repos(Pool *pool, struct repoinfo *repoinfos, int nrepoinfos)
 {
@@ -702,7 +976,6 @@ read_repos(Pool *pool, struct repoinfo *repoinfos, int nrepoinfos)
   int i;
   FILE *fp;
   FILE *sigfp;
-  Dataiterator di;
   const char *filename;
   const unsigned char *filechksum;
   Id filechksumtype;
@@ -711,13 +984,14 @@ read_repos(Pool *pool, struct repoinfo *repoinfos, int nrepoinfos)
   struct stat stb;
   unsigned char cookie[32];
   Pool *sigpool = 0;
+  Repodata *data;
 
   repo = repo_create(pool, "@System");
   printf("rpm database:");
   if (stat("/var/lib/rpm/Packages", &stb))
     memset(&stb, 0, sizeof(&stb));
   calc_checksum_stat(&stb, REPOKEY_TYPE_SHA256, cookie);
-  if (usecachedrepo(repo, cookie))
+  if (usecachedrepo(repo, 0, cookie))
     printf(" cached\n");
   else
     {
@@ -728,7 +1002,7 @@ read_repos(Pool *pool, struct repoinfo *repoinfos, int nrepoinfos)
 #ifdef PRODUCTS_PATH
       repo_add_products(repo, PRODUCTS_PATH, 0, REPO_NO_INTERNALIZE);
 #endif
-      if ((ofp = fopen(calccachepath(repo), "r")) != 0)
+      if ((ofp = fopen(calccachepath(repo, 0), "r")) != 0)
        {
          Repo *ref = repo_create(pool, "@System.old");
          if (!repo_add_solv(ref, ofp))
@@ -741,7 +1015,7 @@ read_repos(Pool *pool, struct repoinfo *repoinfos, int nrepoinfos)
        }
       if (!done)
         repo_add_rpmdb(repo, 0, 0, REPO_REUSE_REPODATA);
-      writecachedrepo(repo, cookie);
+      writecachedrepo(repo, 0, 0, cookie);
     }
   pool_set_installed(pool, repo);
 
@@ -756,7 +1030,7 @@ read_repos(Pool *pool, struct repoinfo *repoinfos, int nrepoinfos)
       repo->appdata = cinfo;
       repo->priority = 99 - cinfo->priority;
 
-      if (!cinfo->autorefresh && usecachedrepo(repo, 0))
+      if (!cinfo->autorefresh && usecachedrepo(repo, 0, 0))
        {
          printf("repo '%s':", cinfo->alias);
          printf(" cached\n");
@@ -775,7 +1049,7 @@ read_repos(Pool *pool, struct repoinfo *repoinfos, int nrepoinfos)
              break;
            }
          calc_checksum_fp(fp, REPOKEY_TYPE_SHA256, cookie);
-         if (usecachedrepo(repo, cookie))
+         if (usecachedrepo(repo, 0, cookie))
            {
              printf(" cached\n");
               fclose(fp);
@@ -806,39 +1080,32 @@ read_repos(Pool *pool, struct repoinfo *repoinfos, int nrepoinfos)
          repo_add_repomdxml(repo, fp, 0);
          fclose(fp);
          printf(" reading\n");
-         filename = findinrepomd(repo, "primary", &filechksum, &filechksumtype);
+         filename = repomd_find(repo, "primary", &filechksum, &filechksumtype);
          if (filename && (fp = curlfopen(cinfo, filename, iscompressed(filename), filechksum, filechksumtype)) != 0)
            {
              repo_add_rpmmd(repo, fp, 0, 0);
              fclose(fp);
            }
 
-         filename = findinrepomd(repo, "updateinfo", &filechksum, &filechksumtype);
+         filename = repomd_find(repo, "updateinfo", &filechksum, &filechksumtype);
          if (filename && (fp = curlfopen(cinfo, filename, iscompressed(filename), filechksum, filechksumtype)) != 0)
            {
              repo_add_updateinfoxml(repo, fp, 0);
              fclose(fp);
            }
 
-         filename = findinrepomd(repo, "deltainfo", &filechksum, &filechksumtype);
-         if (!filename)
-           filename = findinrepomd(repo, "prestodelta", &filechksum, &filechksumtype);
-         if (filename && (fp = curlfopen(cinfo, filename, iscompressed(filename), filechksum, filechksumtype)) != 0)
-           {
-             repo_add_deltainfoxml(repo, fp, 0);
-             fclose(fp);
-           }
-         
-         writecachedrepo(repo, cookie);
+         data = repo_last_repodata(repo);
+         if (!repomd_add_ext(repo, data, "deltainfo"))
+           repomd_add_ext(repo, data, "prestodelta");
+         repomd_add_ext(repo, data, "filelists");
+         repodata_internalize(data);
+         writecachedrepo(repo, data, 0, cookie);
+         repodata_create_stubs(data);
          break;
 
         case TYPE_SUSETAGS:
          printf("susetags repo '%s':", cinfo->alias);
          fflush(stdout);
-         repo = repo_create(pool, cinfo->alias);
-         cinfo->repo = repo;
-         repo->appdata = cinfo;
-         repo->priority = 99 - cinfo->priority;
          descrdir = 0;
          defvendor = 0;
          if ((fp = curlfopen(cinfo, "content", 0, 0, 0)) == 0)
@@ -849,7 +1116,7 @@ read_repos(Pool *pool, struct repoinfo *repoinfos, int nrepoinfos)
              break;
            }
          calc_checksum_fp(fp, REPOKEY_TYPE_SHA256, cookie);
-         if (usecachedrepo(repo, cookie))
+         if (usecachedrepo(repo, 0, cookie))
            {
              printf(" cached\n");
              fclose(fp);
@@ -881,44 +1148,24 @@ read_repos(Pool *pool, struct repoinfo *repoinfos, int nrepoinfos)
          descrdir = repo_lookup_str(repo, SOLVID_META, SUSETAGS_DESCRDIR);
          if (!descrdir)
            descrdir = "suse/setup/descr";
-         filename = 0;
-         dataiterator_init(&di, pool, repo, SOLVID_META, SUSETAGS_FILE_NAME, "packages.gz", SEARCH_STRING);
-         dataiterator_prepend_keyname(&di, SUSETAGS_FILE);
-         if (dataiterator_step(&di))
-           {
-             dataiterator_setpos_parent(&di);
-             filechksum = pool_lookup_bin_checksum(pool, SOLVID_POS, SUSETAGS_FILE_CHECKSUM, &filechksumtype);
-             filename = "packages.gz";
-           }
-         dataiterator_free(&di);
-         if (!filename)
-           {
-             dataiterator_init(&di, pool, repo, SOLVID_META, SUSETAGS_FILE_NAME, "packages", SEARCH_STRING);
-             dataiterator_prepend_keyname(&di, SUSETAGS_FILE);
-             if (dataiterator_step(&di))
-               {
-                 dataiterator_setpos_parent(&di);
-                 filechksum = pool_lookup_bin_checksum(pool, SOLVID_POS, SUSETAGS_FILE_CHECKSUM, &filechksumtype);
-                 filename = "packages";
-               }
-             dataiterator_free(&di);
-           }
+         filename = susetags_find(repo, "packages.gz", &filechksum, &filechksumtype);
+          if (!filename)
+           filename = susetags_find(repo, "packages", &filechksum, &filechksumtype);
          if (!filename)
            {
              printf(" no packages file entry, skipped\n");
              break;
            }
-         if (!filechksumtype)
-           {
-             printf(" no packages file checksum, skipped\n");
-             break;
-           }
          printf(" reading\n");
          if ((fp = curlfopen(cinfo, pool_tmpjoin(pool, descrdir, "/", filename), iscompressed(filename), filechksum, filechksumtype)) == 0)
            break;
          repo_add_susetags(repo, fp, defvendor, 0, 0);
          fclose(fp);
-         writecachedrepo(repo, cookie);
+         data = repo_last_repodata(repo);
+         susetags_add_ext(repo, data);
+         repodata_internalize(data);
+         writecachedrepo(repo, data, 0, cookie);
+         repodata_create_stubs(data);
          break;
        default:
          printf("unsupported repo '%s': skipped\n", cinfo->alias);
@@ -1184,6 +1431,7 @@ main(int argc, char **argv)
     }
 
   pool = pool_create();
+  pool_setloadcallback(pool, load_stub, 0);
   pool->nscallback = nscallback;
   // pool_setdebuglevel(pool, 2);
   setarch(pool);
@@ -1213,7 +1461,10 @@ main(int argc, char **argv)
          FOR_JOB_SELECT(p, pp, job.elements[i], job.elements[i + 1])
            {
              Solvable *s = pool_id2solvable(pool, p);
+             const char *sum = solvable_lookup_str_lang(s, SOLVABLE_SUMMARY, "de");
              printf("  - %s [%s]\n", solvable2str(pool, s), s->repo->name);
+             if (sum)
+                printf("    %s\n", sum);
            }
        }
       exit(0);
@@ -1352,7 +1603,9 @@ rerunsolver:
       solver_free(solv);
       solv = 0;
     }
-  if (!solv->trans.steps.count)
+
+  trans = &solv->trans;
+  if (!trans->steps.count)
     {
       printf("Nothing to do.\n");
       exit(1);
@@ -1360,13 +1613,30 @@ rerunsolver:
   printf("\n");
   printf("Transaction summary:\n\n");
   solver_printtransaction(solv);
+
+#if 1
+  if (1)
+    {
+      DUChanges duc[4];
+      int i;
+
+      duc[0].path = "/";
+      duc[1].path = "/usr/share/man";
+      duc[2].path = "/sbin";
+      duc[3].path = "/etc";
+      transaction_calc_duchanges(trans, duc, 4);
+      for (i = 0; i < 4; i++)
+        printf("duchanges %s: %d K  %d\n", duc[i].path, duc[i].kbytes, duc[i].files);
+      printf("install size change: %d K\n", transaction_calc_installsizechange(trans));
+    }
+#endif
+
   if (!yesno("OK to continue (y/n)? "))
     {
       printf("Abort.\n");
       exit(1);
     }
 
-  trans = &solv->trans;
   queue_init(&checkq);
   newpkgs = transaction_installedresult(trans, &checkq);
   newpkgsfps = 0;
@@ -1400,7 +1670,7 @@ rerunsolver:
          if (pool->installed && pool->installed->nsolvables)
            {
              /* try a delta first */
-             dataiterator_init(&di, pool, 0, SOLVID_META, DELTA_PACKAGE_NAME, id2str(pool, s->name), SEARCH_STRING);
+             dataiterator_init(&di, pool, s->repo, SOLVID_META, DELTA_PACKAGE_NAME, id2str(pool, s->name), SEARCH_STRING);
              dataiterator_prepend_keyname(&di, REPOSITORY_DELTAINFO);
              while (dataiterator_step(&di))
                {
index 10dbf4e..8c97ab2 100644 (file)
@@ -18,6 +18,7 @@
 #define DISABLE_SPLIT
 #include "tools_util.h"
 #include "repo_rpmmd.h"
+#include "chksum.h"
 
 
 enum state {
@@ -126,6 +127,7 @@ static struct stateswitch stateswitches[] = {
   /** tags for different package data, we just ignore the tag **/
   { STATE_START,       "metadata",        STATE_START,    0 },
   { STATE_START,       "otherdata",       STATE_START,    0 },
+  { STATE_START,       "filelists",       STATE_START,    0 },
   { STATE_START,       "diskusagedata",   STATE_START,    0 },
   { STATE_START,       "susedata",        STATE_START,    0 },
 
@@ -1125,6 +1127,29 @@ repo_add_rpmmd(Repo *repo, FILE *fp, const char *language, int flags)
      the package checksums we know about, to get an Id
      we can use in a cache */
   stringpool_init_empty(&pd.cspool);
+  if ((flags & REPO_EXTEND_SOLVABLES) != 0)
+    {
+      /* setup join data */
+      Dataiterator di;
+      dataiterator_init(&di, pool, repo, 0, SOLVABLE_CHECKSUM, 0, 0);
+      while (dataiterator_step(&di))
+       {
+         const char *str;
+         int index;
+         
+         if (!sat_chksum_len(di.key->type))
+           continue;
+         str = repodata_chk2str(di.data, di.key->type, (const unsigned char *)di.kv.str);
+          index = stringpool_str2id(&pd.cspool, str, 1);
+         if (index >= pd.ncscache)
+           {
+             pd.cscache = sat_zextend(pd.cscache, pd.ncscache, index + 1 - pd.ncscache, sizeof(Id), 255);
+             pd.ncscache = index + 1;
+           }
+          pd.cscache[index] = di.solvid;
+       }
+      dataiterator_free(&di);
+    }
 
   XML_Parser parser = XML_ParserCreate(NULL);
   XML_SetUserData(parser, &pd);
@@ -1147,6 +1172,7 @@ repo_add_rpmmd(Repo *repo, FILE *fp, const char *language, int flags)
   join_freemem();
   stringpool_free(&pd.cspool);
   sat_free(pd.cscache);
+  
   if (!(flags & REPO_NO_INTERNALIZE))
     repodata_internalize(data);
   POOL_DEBUG(SAT_DEBUG_STATS, "repo_add_rpmmd took %d ms\n", sat_timems(now));
index a7b0a51..e73afed 100644 (file)
@@ -14,6 +14,7 @@
 
 #include "pool.h"
 #include "repo.h"
+#include "hash.h"
 #include "tools_util.h"
 #include "repo_susetags.h"
 
@@ -394,6 +395,46 @@ finish_solvable(struct parsedata *pd, Solvable *s, Id handle, Offset freshens)
     commit_diskusage(pd, handle);
 }
 
+static Hashtable
+joinhash_init(Repo *repo, Hashmask *hmp)
+{
+  Hashmask hm = mkmask(repo->nsolvables);
+  Hashtable ht = sat_calloc(hm + 1, sizeof(*ht));
+  Hashval h, hh;
+  Solvable *s;
+  int i;
+
+  FOR_REPO_SOLVABLES(repo, i, s)
+    {
+      hh = HASHCHAIN_START;
+      h = s->name & hm;
+      while (ht[h])
+        h = HASHCHAIN_NEXT(h, hh, hm);
+      ht[h] = i;
+    }
+  *hmp = hm;
+  return ht;
+}
+
+static Solvable *
+joinhash_lookup(Repo *repo, Hashtable ht, Hashmask hm, Id name, Id evr, Id arch)
+{
+  Hashval h, hh;
+
+  if (!name || !arch || !evr)
+    return 0;
+  hh = HASHCHAIN_START;
+  h = name & hm;
+  while (ht[h])
+    {
+      Solvable *s = repo->pool->solvables + ht[h];
+      if (s->name == name && s->evr == evr && s->arch == arch)
+       return s;
+      h = HASHCHAIN_NEXT(h, hh, hm);
+    }
+  return 0;
+}
+
 
 /*
  * parse susetags
@@ -420,9 +461,14 @@ repo_add_susetags(Repo *repo, FILE *fp, Id defvendor, const char *language, int
   struct parsedata pd;
   Repodata *data = 0;
   Id handle = 0;
+  Hashtable joinhash = 0;
+  Hashmask joinhashm = 0;
 
-  if ((flags & SUSETAGS_EXTEND) && repo->nrepodata)
-    indesc = 1;
+  if ((flags & (SUSETAGS_EXTEND|REPO_EXTEND_SOLVABLES)) != 0 && repo->nrepodata)
+    {
+      joinhash = joinhash_init(repo, &joinhashm);
+      indesc = 1;
+    }
 
   data = repo_add_repodata(repo, flags);
 
@@ -566,7 +612,6 @@ repo_add_susetags(Repo *repo, FILE *fp, Id defvendor, const char *language, int
       if ((tag == CTAG('=', 'P', 'k', 'g')
           || tag == CTAG('=', 'P', 'a', 't')))
        {
-         Id name, evr, arch;
          /* If we have an old solvable, complete it by filling in some
             default stuff.  */
          if (s)
@@ -589,66 +634,49 @@ repo_add_susetags(Repo *repo, FILE *fp, Id defvendor, const char *language, int
              pool_debug(pool, SAT_FATAL, "susetags: bad line: %d: %s\n", pd.lineno, line);
              exit(1);
            }
-         /* Lookup (but don't construct) the name and arch.  */
-         if (pd.kind)
-           name = str2id(pool, join2(pd.kind, ":", sp[0]), 0);
-         else
-           name = str2id(pool, sp[0], 0);
-         arch = str2id(pool, sp[3], 0);
-         evr = makeevr(pool, join2(sp[1], "-", sp[2]));
-
          s = 0;
           freshens = 0;
 
-         /* Now see if we know this solvable already.  If we found neither
-            the name nor the arch at all in this repo
-            there's no chance of finding the exact solvable either.  */
-         if (name && arch && (indesc >= 2))
-           {
-             int n, nn;
-             /* Now look for a solvable with the given name,evr,arch.
-              Our input is structured so, that the second set of =Pkg
-              lines comes in roughly the same order as the first set, so we
-              have a hint at where to start our search, namely were we found
-              the last entry.  */
-             for (n = repo->start, nn = n + last_found_pack; n < repo->end; n++, nn++)
-               {
-                 if (nn >= repo->end)
-                   nn = repo->start;
-                 s = pool->solvables + nn;
-                 if (s->repo == repo && s->name == name && s->evr == evr && s->arch == arch)
-                   break;
-               }
-             if (n == repo->end)
-               s = 0;
-             else
-               {
-                 last_found_pack = nn - repo->start;
-                 handle = nn;
-               }
-           }
-
-
-         /* And if we still don't have a solvable, create a new one.  */
-         if (!s)
+         if (!joinhash)
            {
+             /* normal operation. create a new solvable. */
              s = pool_id2solvable(pool, repo_add_solvable(repo));
-             last_found_pack = (s - pool->solvables) - repo->start;
-             if (data)
-               handle = s - pool->solvables;
-             if (name)
-               s->name = name;
-             else if (pd.kind)
+             if (pd.kind)
                s->name = str2id(pool, join2(pd.kind, ":", sp[0]), 1);
              else
                s->name = str2id(pool, sp[0], 1);
-             s->evr = evr;
-             if (arch)
-               s->arch = arch;
-             else
-               s->arch = str2id(pool, sp[3], 1);
+             s->evr = makeevr(pool, join2(sp[1], "-", sp[2]));
+             s->arch = str2id(pool, sp[3], 1);
              s->vendor = defvendor;
            }
+         else
+           {
+             /* data join operation. find solvable matching name/arch/evr and
+               * add data to it */
+             Id name, evr, arch;
+             /* we don't use the create flag here as a simple pre-check for existance */
+             if (pd.kind)
+               name = str2id(pool, join2(pd.kind, ":", sp[0]), 0);
+             else
+               name = str2id(pool, sp[0], 0);
+             evr = makeevr(pool, join2(sp[1], "-", sp[2]));
+             arch = str2id(pool, sp[3], 0);
+             if (!name || !arch)
+               continue;       /* ids didn't exist */
+             if (repo->start + last_found_pack + 1 < repo->end)
+               {
+                 s = pool->solvables + repo->start + last_found_pack + 1;
+                 if (s->repo != repo || s->name != name || s->evr != evr || s->arch != arch)
+                   s = 0;
+               }
+             if (!s)
+               s = joinhash_lookup(repo, joinhash, joinhashm, name, evr, arch);
+             if (!s)
+               continue;
+           }
+         last_found_pack = (s - pool->solvables) - repo->start;
+         if (data)
+           handle = s - pool->solvables;
        }
 
       /* If we have no current solvable to add to, ignore all further lines
@@ -656,7 +684,9 @@ repo_add_susetags(Repo *repo, FILE *fp, Id defvendor, const char *language, int
         solvables.  */
       if (indesc >= 2 && !s)
         {
+#if 0
          pool_debug(pool, SAT_ERROR, "susetags: huh %d: %s?\n", pd.lineno, line);
+#endif
           continue;
        }
       switch (tag)
@@ -745,6 +775,12 @@ repo_add_susetags(Repo *repo, FILE *fp, Id defvendor, const char *language, int
            last_found_pack = 0;
            handle = 0;
            indesc++;
+           if (indesc > 1)
+             {
+               sat_free(joinhash);
+               repodata_internalize(data);
+               joinhash = joinhash_init(repo, &joinhashm);
+             }
            continue;
           case CTAG('=', 'V', 'n', 'd'):                                        /* vendor */
             s->vendor = str2id(pool, line + 6, 1);
@@ -943,6 +979,7 @@ repo_add_susetags(Repo *repo, FILE *fp, Id defvendor, const char *language, int
       free(pd.share_with);
     }
 
+  sat_free(joinhash);
   if (!(flags & REPO_NO_INTERNALIZE))
     repodata_internalize(data);
 
index 57acaeb..91acd2a 100644 (file)
@@ -9,7 +9,7 @@
  * if <attrname> given, write attributes as '<attrname>.attr'
  */
 
-#define SUSETAGS_KINDS_SEPARATELY      (1 << 2)
-#define SUSETAGS_EXTEND                        (1 << 3)
+#define SUSETAGS_KINDS_SEPARATELY      (1 << 8)
+#define SUSETAGS_EXTEND                        (1 << 9)
 
 extern void repo_add_susetags(Repo *repo, FILE *fp, Id defvendor, const char *language, int flags);
index 46dfbdb..c17ead4 100644 (file)
@@ -1120,6 +1120,17 @@ repo_write(Repo *repo, FILE *fp, int (*keyfilter)(Repo *repo, Repokey *key, void
       cbdata.keymap[n++] = 0;  /* key 0 */
       idused = 0;
       dirused = 0;
+      if (keyfilter)
+       {
+         Repokey zerokey;
+         /* check if we want this repodata */
+         memset(&zerokey, 0, sizeof(zerokey));
+         zerokey.name = 1;
+         zerokey.type = 1;
+         zerokey.size = i;
+         if (keyfilter(repo, &zerokey, kfdata) == -1)
+           continue;
+       }
       for (j = 1; j < data->nkeys; j++, n++)
        {
          key = data->keys + j;
index 4988b0a..ad1e8cb 100644 (file)
@@ -926,10 +926,11 @@ pool_addfileprovides_search(Pool *pool, struct addfileprovides_cbdata *cbd, stru
   Id p, start, end;
   Solvable *s;
   Repodata *data = 0, *nextdata;
-  Repo *oldrepo = 0;
+  Repo *repo, *oldrepo = 0;
   int dataincludes = 0;
-  int i, j;
+  int i, j, flags;
   Map providedids;
+  Repodata *ffldata = 0;
 
   cbd->nfiles = sf->nfiles;
   cbd->ids = sf->ids;
@@ -947,12 +948,14 @@ pool_addfileprovides_search(Pool *pool, struct addfileprovides_cbdata *cbd, stru
       start = 2;       /* skip system solvable */
       end = pool->nsolvables;
     }
+  flags = 0;
   for (p = start, s = pool->solvables + p; p < end; p++, s++)
     {
-      if (!s->repo || (repoonly && s->repo != repoonly))
+      repo = s->repo;
+      if (!repo || (repoonly && repo != repoonly))
        continue;
       /* check if p is in (oldrepo,data) */
-      if (s->repo != oldrepo || (data && p >= data->end))
+      if (repo != oldrepo || (data && p >= data->end))
        {
          data = 0;
          oldrepo = 0;
@@ -962,7 +965,7 @@ pool_addfileprovides_search(Pool *pool, struct addfileprovides_cbdata *cbd, stru
          /* nope, find new repo/repodata */
           /* if we don't find a match, set data to the next repodata */
          nextdata = 0;
-         for (i = 0, data = s->repo->repodata; i < s->repo->nrepodata; i++, data++)
+         for (i = 0, data = repo->repodata; i < repo->nrepodata; i++, data++)
            {
              if (p >= data->end)
                continue;
@@ -979,7 +982,7 @@ pool_addfileprovides_search(Pool *pool, struct addfileprovides_cbdata *cbd, stru
              if (p >= data->start)
                break;
            }
-         if (i == s->repo->nrepodata)
+         if (i == repo->nrepodata)
            data = nextdata;    /* no direct hit, use next repodata */
          if (data)
            {
@@ -991,11 +994,32 @@ pool_addfileprovides_search(Pool *pool, struct addfileprovides_cbdata *cbd, stru
              map_free(&providedids);
              dataincludes = i == cbd->nfiles;
            }
-         oldrepo = s->repo;
+         oldrepo = repo;
        }
       if (data && p >= data->start && dataincludes)
        continue;
-      repo_search(s->repo, p, SOLVABLE_FILELIST, 0, 0, addfileprovides_cb, cbd);
+      if (ffldata == 0 || p < ffldata->start || p >= ffldata->end)
+       {
+         for (i = 0, ffldata = repo->repodata; i < repo->nrepodata; i++, ffldata++)
+           if (p >= ffldata->start && p < ffldata->end)
+             break;
+         if (i == repo->nrepodata)
+           ffldata = 0;
+         flags = 0;
+         if (ffldata)
+           {
+             for (i = 0; i < cbd->nfiles; i++)
+               if (!repodata_filelistfilter_matches(ffldata, id2str(pool, cbd->ids[i])))
+                 {
+#if 0
+                   printf("Need the complete filelist in repo %s because of %s\n", repo->name, id2str(pool, cbd->ids[i]));
+#endif
+                   flags = SEARCH_COMPLETE_FILELIST;
+                   break;
+                 }
+           }
+       }
+      repo_search(repo, p, SOLVABLE_FILELIST, 0, flags, addfileprovides_cb, cbd);
     }
 }
 
index 365bd66..347c7f3 100644 (file)
@@ -117,7 +117,7 @@ struct _Pool {
   void *debugcallbackdata;
 
   /* load callback */
-  FILE * (*loadcallback)(struct _Pool *, struct _Repodata *, void *);
+  int (*loadcallback)(struct _Pool *, struct _Repodata *, void *);
   void *loadcallbackdata;
 
   /* search position */
@@ -276,7 +276,7 @@ static inline void pool_setdebugmask(Pool *pool, int mask)
   pool->debugmask = mask;
 }
 
-static inline void pool_setloadcallback(Pool *pool, FILE *(*cb)(struct _Pool *, struct _Repodata *, void *), void *loadcbdata)
+static inline void pool_setloadcallback(Pool *pool, int (*cb)(struct _Pool *, struct _Repodata *, void *), void *loadcbdata)
 {
   pool->loadcallback = cb;
   pool->loadcallbackdata = loadcbdata;
@@ -292,7 +292,7 @@ void pool_search(Pool *pool, Id p, Id key, const char *match, int flags, int (*c
 void pool_clear_pos(Pool *pool);
 
 
-typedef struct _duchanges {
+typedef struct _DUChanges {
   const char *path;
   int kbytes;
   int files;
index 943a1c1..bfac9f3 100644 (file)
@@ -805,6 +805,13 @@ repo_search_md(Repo *repo, Id p, Id keyname, struct matchdata *md)
       repodata_search(data, p, keyname, md->flags, repo_matchvalue, md);
       if (md->stop > SEARCH_NEXT_KEY)
        break;
+      if (keyname == SOLVABLE_FILELIST)
+       {
+         if (!(md->flags & SEARCH_COMPLETE_FILELIST))
+           break;
+          if (md->matcher.match && (md->flags & (SEARCH_STRINGMASK|SEARCH_NOCASE)) == SEARCH_STRING && repodata_filelistfilter_matches(data, md->matcher.match))
+           break;
+       }
     }
 }
 
@@ -985,9 +992,26 @@ repo_lookup_void(Repo *repo, Id entry, Id keyname)
 Repodata *
 repo_add_repodata(Repo *repo, int flags)
 {
+  int i;
+  if ((flags & REPO_USE_LOADING) != 0)
+    {
+      for (i = repo->nrepodata - 1; i >= 0; i--)
+       if (repo->repodata[i].state == REPODATA_LOADING)
+         {
+           Repodata *data = repo->repodata + i;
+           /* re-init */
+           /* hack: we mis-use REPO_REUSE_REPODATA here */
+           if (!(flags & REPO_REUSE_REPODATA))
+             {
+               repodata_freedata(data);
+               repodata_initdata(data, repo, (flags & REPO_LOCALPOOL) ? 1 : 0);
+             }
+           return data;
+         }
+      return 0;        /* must not create a new repodata! */
+    }
   if ((flags & REPO_REUSE_REPODATA) != 0)
     {
-      int i;
       for (i = repo->nrepodata - 1; i >= 0; i--)
        if (repo->repodata[i].state != REPODATA_STUB)
          return repo->repodata + i;
index 65114b7..2f7c49a 100644 (file)
@@ -166,6 +166,7 @@ typedef struct _KeyValue {
 #define SEARCH_SUB                     (1<<9)
 #define SEARCH_ARRAYSENTINEL           (1<<10)
 #define SEARCH_DISABLED_REPOS          (1<<11)
+#define SEARCH_COMPLETE_FILELIST       (1<<12)
 
 /* stringification flags */
 #define SEARCH_SKIP_KIND               (1<<16)
@@ -183,6 +184,8 @@ typedef struct _KeyValue {
 #define REPO_REUSE_REPODATA            (1 << 0)
 #define REPO_NO_INTERNALIZE            (1 << 1)
 #define REPO_LOCALPOOL                 (1 << 2)
+#define REPO_USE_LOADING               (1 << 3)
+#define REPO_EXTEND_SOLVABLES          (1 << 4)
 
 Repodata *repo_add_repodata(Repo *repo, int flags);
 Repodata *repo_last_repodata(Repo *repo);
index 813d3c4..3be8dd6 100644 (file)
@@ -42,8 +42,6 @@
 static Pool *mypool;           /* for pool_debug... */
 
 
-static void repodata_load_stub(Repodata *data);
-
 
 /*******************************************************************************
  * functions to extract data from a file handle
@@ -408,101 +406,15 @@ incore_add_u8(Repodata *data, unsigned int x)
 
 
 /*******************************************************************************
- * callback to create our stub sub-repodatas from the incore data
- */
-
-struct create_stub_data {
-  Repodata *data;
-  Id xkeyname;
-};
-
-static int
-create_stub_cb(void *cbdata, Solvable *s, Repodata *data, Repokey *key, KeyValue *kv)
-{
-  struct create_stub_data *stubdata = cbdata;
-  if (key->name == REPOSITORY_EXTERNAL && key->type == REPOKEY_TYPE_FLEXARRAY)
-    {
-      if (stubdata->data)
-       {
-         repodata_internalize(stubdata->data);
-         if (data->start != data->end)
-           {
-             repodata_extend(stubdata->data, data->start);
-             repodata_extend(stubdata->data, data->end - 1);
-           }
-         stubdata->data = 0;
-       }
-      if (kv->eof == 2)
-       return SEARCH_NEXT_SOLVABLE;
-      stubdata->data = repo_add_repodata(data->repo, 0);
-      stubdata->data->state = REPODATA_STUB;
-      stubdata->data->loadcallback = repodata_load_stub;
-      return SEARCH_ENTERSUB;
-    }
-  if (!stubdata->data)
-    return SEARCH_NEXT_KEY;
-  switch(key->type)
-    {
-    case REPOKEY_TYPE_ID:
-      repodata_set_id(stubdata->data, SOLVID_META, key->name, kv->id);
-      break;
-    case REPOKEY_TYPE_CONSTANTID:
-      repodata_set_constantid(stubdata->data, SOLVID_META, key->name, kv->id);
-      break;
-    case REPOKEY_TYPE_STR:
-      repodata_set_str(stubdata->data, SOLVID_META, key->name, kv->str);
-      break;
-    case REPOKEY_TYPE_VOID:
-      repodata_set_void(stubdata->data, SOLVID_META, key->name);
-      break;
-    case REPOKEY_TYPE_NUM:
-      repodata_set_num(stubdata->data, SOLVID_META, key->name, kv->num);
-      break;
-    case REPOKEY_TYPE_IDARRAY:
-      repodata_add_idarray(stubdata->data, SOLVID_META, key->name, kv->id);
-      if (key->name == REPOSITORY_KEYS)
-       {
-         if (!stubdata->xkeyname)
-           stubdata->xkeyname = kv->id;
-         else
-           {
-             Repokey xkey;
-
-             xkey.name = stubdata->xkeyname;
-             xkey.type = kv->id;
-             xkey.storage = KEY_STORAGE_INCORE;
-             xkey.size = 0;
-             repodata_key2id(stubdata->data, &xkey, 1);
-             stubdata->xkeyname = 0;
-           }
-         if (kv->eof)
-           stubdata->xkeyname = 0;
-       }
-      break;
-    case REPOKEY_TYPE_MD5:
-    case REPOKEY_TYPE_SHA1:
-    case REPOKEY_TYPE_SHA256:
-      repodata_set_checksum(stubdata->data, SOLVID_META, key->name, key->type, kv->str);
-      break;
-    default:
-      return SEARCH_NEXT_KEY;
-    }
-  return 0;
-}
-
-
-/*******************************************************************************
  * our main function
  */
 
 /*
  * read repo from .solv file and add it to pool
- * if stubdata is set, substitute it with read data
- * (this is used to replace a repodata stub with the real data)
  */
 
-static int
-repo_add_solv_parent(Repo *repo, FILE *fp, Repodata *parent)
+int
+repo_add_solv_flags(Repo *repo, FILE *fp, int flags)
 {
   Pool *pool = repo->pool;
   int i, l;
@@ -519,7 +431,7 @@ repo_add_solv_parent(Repo *repo, FILE *fp, Repodata *parent)
   int hh;
   Id *hashtbl;
   Id name, evr, did;
-  int flags;
+  int relflags;
   Reldep *ran;
   unsigned int size_idarray;
   Id *idarraydatap, *idarraydataend;
@@ -541,10 +453,18 @@ repo_add_solv_parent(Repo *repo, FILE *fp, Repodata *parent)
 
   struct _Stringpool *spool;
 
+  Repodata *parent = 0;
   Repodata data;
 
   now = sat_timems(0);
 
+  if ((flags & REPO_USE_LOADING) != 0)
+    {
+      /* this is a stub replace operation */
+      flags |= REPO_EXTEND_SOLVABLES;
+      parent = repo_add_repodata(repo, flags | REPO_REUSE_REPODATA);
+    }
+    
   memset(&data, 0, sizeof(data));
   data.repo = repo;
   data.fp = fp;
@@ -583,18 +503,15 @@ repo_add_solv_parent(Repo *repo, FILE *fp, Repodata *parent)
       return SOLV_ERROR_CORRUPT;
     }
 
-  if (parent)
+  if (numrel && (flags & REPO_LOCALPOOL) != 0)
     {
-      if (numrel)
-       {
-         pool_debug(pool, SAT_ERROR, "relations are forbidden in a sub-repository\n");
-         return SOLV_ERROR_CORRUPT;
-       }
-      if (parent->end - parent->start != numsolv)
-       {
-         pool_debug(pool, SAT_ERROR, "sub-repository solvable number doesn't match main repository (%d - %d)\n", parent->end - parent->start, numsolv);
-         return SOLV_ERROR_CORRUPT;
-       }
+      pool_debug(pool, SAT_ERROR, "relations are forbidden in a local pool\n");
+      return SOLV_ERROR_CORRUPT;
+    }
+  if (parent && numsolv && parent->end - parent->start != numsolv)
+    {
+      pool_debug(pool, SAT_ERROR, "sub-repository solvable number doesn't match main repository (%d - %d)\n", parent->end - parent->start, numsolv);
+      return SOLV_ERROR_CORRUPT;
     }
 
   /*******  Part 1: string IDs  *****************************************/
@@ -611,7 +528,7 @@ repo_add_solv_parent(Repo *repo, FILE *fp, Repodata *parent)
    * alloc buffers
    */
 
-  if (!parent)
+  if (!(flags & REPO_LOCALPOOL))
     spool = &pool->ss;
   else
     {
@@ -690,7 +607,7 @@ repo_add_solv_parent(Repo *repo, FILE *fp, Repodata *parent)
   strsp[sizeid] = 0;                  /* make string space \0 terminated */
   sp = strsp;
 
-  if (parent)
+  if ((flags & REPO_LOCALPOOL) != 0)
     {
       /* no shared pool, thus no idmap and no unification */
       idmap = 0;
@@ -841,17 +758,17 @@ repo_add_solv_parent(Repo *repo, FILE *fp, Repodata *parent)
        {
          name = read_id(&data, i + numid);     /* read (repo relative) Ids */
          evr = read_id(&data, i + numid);
-         flags = read_u8(&data);
+         relflags = read_u8(&data);
          name = idmap[name];           /* map to (pool relative) Ids */
          evr = idmap[evr];
-         h = relhash(name, evr, flags) & hashmask;
+         h = relhash(name, evr, relflags) & hashmask;
          hh = HASHCHAIN_START;
          for (;;)
            {
              id = hashtbl[h];
              if (id == ID_NULL)        /* end of hash chain */
                break;
-             if (ran[id].name == name && ran[id].evr == evr && ran[id].flags == flags)
+             if (ran[id].name == name && ran[id].evr == evr && ran[id].flags == relflags)
                break;
              h = HASHCHAIN_NEXT(h, hh, hashmask);
            }
@@ -861,7 +778,7 @@ repo_add_solv_parent(Repo *repo, FILE *fp, Repodata *parent)
              hashtbl[h] = id;
              ran[id].name = name;
              ran[id].evr = evr;
-             ran[id].flags = flags;
+             ran[id].flags = relflags;
            }
          idmap[i + numid] = MAKERELDEP(id);   /* fill Id map */
        }
@@ -898,12 +815,12 @@ repo_add_solv_parent(Repo *repo, FILE *fp, Repodata *parent)
       id = read_id(&data, numid);
       if (idmap)
        id = idmap[id];
-      else if (parent)
+      else if ((flags & REPO_LOCALPOOL) != 0)
         id = str2id(pool, stringpool_id2str(spool, id), 1);
       type = read_id(&data, numid);
       if (idmap)
        type = idmap[type];
-      else if (parent)
+      else if ((flags & REPO_LOCALPOOL) != 0)
         type = str2id(pool, stringpool_id2str(spool, type), 1);
       if (type < REPOKEY_TYPE_VOID || type > REPOKEY_TYPE_FLEXARRAY)
        {
@@ -923,7 +840,7 @@ repo_add_solv_parent(Repo *repo, FILE *fp, Repodata *parent)
        {
          if (idmap)
            keys[i].size = idmap[keys[i].size];
-         else if (parent)
+         else if ((flags & REPO_LOCALPOOL) != 0)
            keys[i].size = str2id(pool, stringpool_id2str(spool, keys[i].size), 1);
        }
 #if 0
@@ -1345,7 +1262,7 @@ printf("=> %s %s %p\n", id2str(pool, keys[key].name), id2str(pool, keys[key].typ
   if (parent)
     {
       /* overwrite stub repodata */
-      repodata_free(parent);
+      repodata_freedata(parent);
       *parent = data;
     }
   else
@@ -1359,13 +1276,8 @@ printf("=> %s %s %p\n", id2str(pool, keys[key].name), id2str(pool, keys[key].typ
   for (key = 1 ; key < data.nkeys; key++)
     if (data.keys[key].name == REPOSITORY_EXTERNAL && data.keys[key].type == REPOKEY_TYPE_FLEXARRAY)
       break;
-  if (key < data.nkeys)
-    {
-      struct create_stub_data stubdata;
-      /* got some */
-      memset(&stubdata, 0, sizeof(stubdata));
-      repodata_search(&data, SOLVID_META, REPOSITORY_EXTERNAL, SEARCH_ARRAYSENTINEL, create_stub_cb, &stubdata);
-    }
+  if (key < data.nkeys && !parent)
+    repodata_create_stubs(&data);
 
   POOL_DEBUG(SAT_DEBUG_STATS, "repo_add_solv took %d ms\n", sat_timems(now));
   POOL_DEBUG(SAT_DEBUG_STATS, "repo size: %d solvables\n", repo->nsolvables);
@@ -1376,30 +1288,5 @@ printf("=> %s %s %p\n", id2str(pool, keys[key].name), id2str(pool, keys[key].typ
 int
 repo_add_solv(Repo *repo, FILE *fp)
 {
-  return repo_add_solv_parent(repo, fp, 0);
-}
-
-static void
-repodata_load_stub(Repodata *data)
-{
-  FILE *fp;
-  Pool *pool = data->repo->pool;
-  if (!pool->loadcallback)
-    {   
-      data->state = REPODATA_ERROR;
-      return;
-    }   
-  /* so that we can retrieve meta data */
-  data->state = REPODATA_AVAILABLE;
-  fp = pool->loadcallback(pool, data, pool->loadcallbackdata);
-  if (!fp)
-    {   
-      data->state = REPODATA_ERROR;
-      return;
-    }   
-  if (repo_add_solv_parent(data->repo, fp, data))
-    data->state = REPODATA_ERROR;
-  else
-    data->state = REPODATA_AVAILABLE;
-  fclose(fp);
+  return repo_add_solv_flags(repo, fp, 0);
 }
index 3127258..e3e63a5 100644 (file)
@@ -23,6 +23,7 @@ extern "C" {
 #include "repo.h"
 
 extern int repo_add_solv(Repo *repo, FILE *fp);
+extern int repo_add_solv_flags(Repo *repo, FILE *fp, int flags);
 
 #ifdef __cplusplus
 }
index 13b4922..0879eaa 100644 (file)
@@ -472,6 +472,7 @@ maybe_load_repodata(Repodata *data, Id keyname)
     case REPODATA_ERROR:
       return 0;
     case REPODATA_AVAILABLE:
+    case REPODATA_LOADING:
       return 1;
     default:
       data->state = REPODATA_ERROR;
@@ -1133,6 +1134,47 @@ dataiterator_find_keyname(Dataiterator *di, Id keyname)
 }
 
 int
+repodata_filelistfilter_matches(Repodata *data, const char *str)
+{
+  /* '.*bin\/.*', '^\/etc\/.*', '^\/usr\/lib\/sendmail$' */
+  /* for now hardcoded */
+  if (strstr(str, "bin/"))
+    return 1;
+  if (!strncmp(str, "/etc/", 5))
+    return 1;
+  if (!strcmp(str, "/usr/bin/sendmail"))
+    return 1;
+  return 0;
+}
+
+static int
+dataiterator_filelistcheck(Dataiterator *di)
+{
+  int i;
+  Repodata *data = di->data;
+  if (data->state != REPODATA_AVAILABLE)
+    return 1;
+  if (!repodata_precheck_keyname(data, REPOSITORY_EXTERNAL))
+    return 1;
+  for (i = 0; i < data->nkeys; i++)
+    if (data->keys[i].name == REPOSITORY_EXTERNAL)
+      break;
+  if (i == data->nkeys)
+    return 1;
+  if (!(di->matcher.flags & SEARCH_COMPLETE_FILELIST))
+    {
+      di->repodataid = -1;     /* do not look somewhere else */
+      return 1;
+    }
+  if (di->matcher.match && (di->matcher.flags & (SEARCH_STRINGMASK|SEARCH_NOCASE)) == SEARCH_STRING && repodata_filelistfilter_matches(di->data, di->matcher.match))
+    {
+      di->repodataid = -1;     /* do not look somewhere else */
+      return 1;
+    }
+  return 1;
+}
+
+int
 dataiterator_step(Dataiterator *di)
 {
   Id schema;
@@ -1173,6 +1215,8 @@ dataiterator_step(Dataiterator *di)
                goto di_nextsolvable;
              di->data = di->repo->repodata + di->repodataid;
            }
+         if (di->repodataid >= 0 && di->keyname == SOLVABLE_FILELIST && !dataiterator_filelistcheck(di))
+           goto di_nextrepodata;
          if (!maybe_load_repodata(di->data, di->keyname))
            goto di_nextrepodata;
          di->dp = solvid2data(di->data, di->solvid, &schema);
@@ -1247,6 +1291,7 @@ dataiterator_step(Dataiterator *di)
          if (di->repoid >= 0)
            {
              di->repoid++;
+             di->repodataid = 0;
              if (di->repoid < di->pool->nrepos)
                {
                  di->repo = di->pool->repos[di->repoid];
@@ -2500,7 +2545,7 @@ fprintf(stderr, "schemadata %p\n", data->schemadata);
            }
          key = data->keys + *keyp;
 #if 0
-         fprintf(stderr, "internalize %d:%s:%s\n", entry, id2str(data->repo->pool, key->name), id2str(data->repo->pool, key->type));
+         fprintf(stderr, "internalize %d(%d):%s:%s\n", entry, entry + data->start, id2str(data->repo->pool, key->name), id2str(data->repo->pool, key->type));
 #endif
          ndp = dp;
          if (oldcount)
@@ -2573,96 +2618,113 @@ repodata_disable_paging(Repodata *data)
     repopagestore_disable_paging(&data->store);
 }
 
-static inline Hashval
-repodata_join_hash(Solvable *s, Id joinkey)
+static void
+repodata_load_stub(Repodata *data)
 {
-  if (joinkey == SOLVABLE_NAME)
-    return s->name;
-  if (joinkey == SOLVABLE_CHECKSUM)
-    {
-      Id type;
-      const unsigned char *chk = solvable_lookup_bin_checksum(s, joinkey, &type);
-      if (chk)
-        return 1 << 31 | chk[0] << 24 | chk[1] << 16 | chk[2] << 7 | chk[3];
-    }
-  return 0;
-}
+  Repo *repo = data->repo;
+  Pool *pool = repo->pool;
+  int r;
 
-static inline int
-repodata_join_match(Solvable *s1, Solvable *s2, Id joinkey)
-{
-  if (joinkey == SOLVABLE_NAME)
-    return s1->name == s2->name && s1->evr == s2->evr && s1->arch == s2->arch ? 1 : 0;
-  if (joinkey == SOLVABLE_CHECKSUM)
+  if (!pool->loadcallback)
     {
-      const unsigned char *chk1, *chk2;
-      Id type1, type2;
-      chk1 = solvable_lookup_bin_checksum(s1, joinkey, &type1);
-      if (!chk1)
-       return 0;
-      chk2 = solvable_lookup_bin_checksum(s2, joinkey, &type2);
-      if (!chk2 || type1 != type2)
-       return 0;
-      return memcmp(chk1, chk2, sat_chksum_len(type1)) ? 0 : 1;
+      data->state = REPODATA_ERROR;
+      return;
     }
-  return 0;
+  data->state = REPODATA_LOADING;
+  r = pool->loadcallback(pool, data, pool->loadcallbackdata);
+  if (!r)
+    data->state = REPODATA_ERROR;
 }
 
 void
-repodata_join(Repodata *data, Id joinkey)
+repodata_create_stubs(Repodata *data)
 {
   Repo *repo = data->repo;
   Pool *pool = repo->pool;
-  Hashmask hm = mkmask(repo->nsolvables);
-  Hashtable ht = sat_calloc(hm + 1, sizeof(*ht));
-  Hashval h, hh;
-  int i, datastart, dataend;
-  Solvable *s;
-
-  datastart = data->start;
-  dataend = data->end;
-  if (datastart == dataend || repo->start == repo->end)
+  Repodata *sdata;
+  int *stubdataids;
+  Dataiterator di;
+  Id xkeyname = 0;
+  int i, cnt = 0;
+
+  dataiterator_init(&di, pool, repo, SOLVID_META, REPOSITORY_EXTERNAL, 0, 0);
+  while (dataiterator_step(&di))
+    cnt++;
+  dataiterator_free(&di);
+  if (!cnt)
     return;
-  FOR_REPO_SOLVABLES(repo, i, s)
+  stubdataids = sat_calloc(cnt, sizeof(*stubdataids));
+  for (i = 0; i < cnt; i++)
     {
-      if (i >= datastart && i < dataend)
-       continue;
-      h = repodata_join_hash(s, joinkey);
-      if (!h)
-       continue;
-      h &= hm;
-      hh = HASHCHAIN_START;
-      while (ht[h])
-        h = HASHCHAIN_NEXT(h, hh, hm);
-      ht[h] = i;
+      sdata = repo_add_repodata(repo, 0);
+      if (data->end > data->start)
+       {
+         repodata_extend(sdata, data->start);
+         repodata_extend(sdata, data->end - 1);
+       }
+      stubdataids[i] = sdata - repo->repodata;
+      sdata->state = REPODATA_STUB;
+      sdata->loadcallback = repodata_load_stub;
     }
-  for (i = datastart; i < dataend; i++)
+  i = 0;
+  dataiterator_init(&di, pool, repo, SOLVID_META, REPOSITORY_EXTERNAL, 0, 0);
+  sdata = 0;
+  while (dataiterator_step(&di))
     {
-      Solvable *s = pool->solvables + i;
-      if (s->repo != data->repo)
-       continue;
-      if (!data->attrs[i - data->start])
-       continue;
-      h = repodata_join_hash(s, joinkey);
-      if (!h)
-       continue;
-      h &= hm;
-      hh = HASHCHAIN_START;
-      while (ht[h])
+      if (di.key->name == REPOSITORY_EXTERNAL && !di.nparents)
+       {
+         dataiterator_entersub(&di);
+         sdata = repo->repodata + stubdataids[i++];
+         xkeyname = 0;
+         continue;
+       }
+      switch (di.key->type)
        {
-         Solvable *s2 = pool->solvables + ht[h];
-         if (repodata_join_match(s, s2, joinkey))
+        case REPOKEY_TYPE_ID:
+         repodata_set_id(sdata, SOLVID_META, di.key->name, di.kv.id);
+         break;
+       case REPOKEY_TYPE_CONSTANTID:
+         repodata_set_constantid(sdata, SOLVID_META, di.key->name, di.kv.id);
+         break;
+       case REPOKEY_TYPE_STR:
+         repodata_set_str(sdata, SOLVID_META, di.key->name, di.kv.str);
+         break;
+       case REPOKEY_TYPE_VOID:
+         repodata_set_void(sdata, SOLVID_META, di.key->name);
+         break;
+       case REPOKEY_TYPE_NUM:
+         repodata_set_num(sdata, SOLVID_META, di.key->name, di.kv.num);
+         break;
+       case REPOKEY_TYPE_MD5:
+       case REPOKEY_TYPE_SHA1:
+       case REPOKEY_TYPE_SHA256:
+         repodata_set_checksum(sdata, SOLVID_META, di.key->name, di.key->type, di.kv.str);
+         break;
+       case REPOKEY_TYPE_IDARRAY:
+         repodata_add_idarray(sdata, SOLVID_META, di.key->name, di.kv.id);
+         if (di.key->name == REPOSITORY_KEYS)
            {
-             /* a match! move data over */
-             repodata_extend(data, ht[h]);
-             repodata_merge_attrs(data, ht[h], i);
+             Repokey xkey;
+
+             if (!xkeyname)
+               {
+                 if (!di.kv.eof)
+                   xkeyname = di.kv.id;
+                 continue;
+               }
+             xkey.name = xkeyname;
+              xkey.type = di.kv.id;
+              xkey.storage = KEY_STORAGE_INCORE;
+              xkey.size = 0; 
+              repodata_key2id(sdata, &xkey, 1);
+              xkeyname = 0;
            }
-          h = HASHCHAIN_NEXT(h, hh, hm);
        }
     }
-  sat_free(ht);
-  /* all done! now free solvables */
-  repo_free_solvable_block(repo, datastart, dataend - datastart, 1);
+  dataiterator_free(&di);
+  for (i = 0; i < cnt; i++)
+    repodata_internalize(repo->repodata + stubdataids[i]);
+  sat_free(stubdataids);
 }
 
 /*
index ed3c474..527043d 100644 (file)
@@ -47,6 +47,8 @@ typedef struct _Repodata {
 #define REPODATA_STUB          1
 #define REPODATA_ERROR         2
 #define REPODATA_STORE         3
+#define REPODATA_LOADING       4
+
   int state;                   /* available, stub or error */
 
   void (*loadcallback)(struct _Repodata *);
@@ -161,6 +163,8 @@ void repodata_search(Repodata *data, Id solvid, Id keyname, int flags, int (*cal
  * if not possible */
 int repodata_stringify(Pool *pool, Repodata *data, Repokey *key, struct _KeyValue *kv, int flags);
 
+int repodata_filelistfilter_matches(Repodata *data, const char *str);
+
 
 /* lookup functions */
 Id repodata_lookup_id(Repodata *data, Id solvid, Id keyname);
@@ -228,6 +232,7 @@ void repodata_add_flexarray(Repodata *data, Id solvid, Id keyname, Id ghandle);
 */
 void repodata_merge_attrs(Repodata *data, Id dest, Id src);
 
+void repodata_create_stubs(Repodata *data);
 void repodata_join(Repodata *data, Id joinkey);
 
 /*
index 7d67a55..914e94b 100644 (file)
@@ -705,6 +705,53 @@ transaction_installedresult(Transaction *trans, Queue *installedq)
   return cutoff;
 }
 
+static void
+transaction_create_installedmap(Transaction *trans, Map *installedmap)
+{
+  Pool *pool = trans->pool;
+  Repo *installed = pool->installed;
+  Solvable *s;
+  Id p;
+  int i;
+
+  map_init(installedmap, pool->nsolvables);
+  for (i = 0; i < trans->steps.count; i++)
+    {
+      p = trans->steps.elements[i];
+      s = pool->solvables + p;
+      if (!installed || s->repo != installed)
+        MAPSET(installedmap, p);
+    }
+  if (installed)
+    {
+      FOR_REPO_SOLVABLES(installed, p, s)
+       if (!MAPTST(&trans->transactsmap, p))
+          MAPSET(installedmap, p);
+    }
+}
+
+int
+transaction_calc_installsizechange(Transaction *trans)
+{
+  Map installedmap;
+  int change;
+
+  transaction_create_installedmap(trans, &installedmap);
+  change = pool_calc_installsizechange(trans->pool, &installedmap);
+  map_free(&installedmap);
+  return change;
+}
+
+void
+transaction_calc_duchanges(Transaction *trans, DUChanges *mps, int nmps)
+{
+  Map installedmap;
+
+  transaction_create_installedmap(trans, &installedmap);
+  pool_calc_duchanges(trans->pool, &installedmap, mps, nmps);
+  map_free(&installedmap);
+}
+
 struct _TransactionElement {
   Id p;                /* solvable id */
   Id edges;    /* pointer into edges data */
index 8bd1ebd..c929520 100644 (file)
@@ -22,6 +22,7 @@ extern "C" {
 #include "bitmap.h"
 
 struct _Pool;
+struct _DUChanges;
 struct _TransactionOrderdata;
 
 typedef struct _Transaction {
@@ -103,6 +104,9 @@ extern void transaction_classify_pkgs(Transaction *trans, int mode, Id type, Id
    packages is returned */
 extern int transaction_installedresult(Transaction *trans, Queue *installedq);
 
+int transaction_calc_installsizechange(Transaction *trans);
+void transaction_calc_duchanges(Transaction *trans, struct _DUChanges *mps, int nmps);
+
 /* order a transaction */
 extern void transaction_order(Transaction *trans, int flags);
 
index cc6ce94..95a5730 100644 (file)
@@ -169,21 +169,27 @@ dump_some_attrs(Repo *repo, Solvable *s)
 #endif
 
 
-static FILE *
+static int
 loadcallback (Pool *pool, Repodata *data, void *vdata)
 {
   FILE *fp = 0;
+  int r;
+
 printf("LOADCALLBACK\n");
   const char *location = repodata_lookup_str(data, SOLVID_META, REPOSITORY_LOCATION);
 printf("loc %s\n", location);
-  if (location && with_attr)
+  if (!location || !with_attr)
+    return 0;
+  fprintf (stderr, "Loading SOLV file %s\n", location);
+  fp = fopen (location, "r");
+  if (!fp)
     {
-      fprintf (stderr, "Loading SOLV file %s\n", location);
-      fp = fopen (location, "r");
-      if (!fp)
-       perror(location);
+      perror(location);
+      return 0;
     }
-  return fp;
+  r = repo_add_solv_flags(data->repo, fp, REPO_USE_LOADING|REPO_LOCALPOOL);
+  fclose(fp);
+  return !r ? 1 : 0;
 }
 
 
index 87a3295..653de47 100644 (file)
@@ -33,19 +33,25 @@ usage()
   exit(0);
 }
 
-static FILE *
+static int
 loadcallback (Pool *pool, Repodata *data, void *vdata)
 {
-  FILE *fp = 0;
+  FILE *fp;
   const char *location = repodata_lookup_str(data, SOLVID_META, REPOSITORY_LOCATION);
-  if (location)
+  int r;
+
+  if (!location)
+    return 0;
+  fprintf(stderr, "Loading SOLV file %s\n", location);
+  fp = fopen (location, "r");
+  if (!fp)
     {
-      fprintf(stderr, "Loading SOLV file %s\n", location);
-      fp = fopen (location, "r");
-      if (!fp)
-       perror(location);
+      perror(location);
+      return 0;
     }
-  return fp;
+  r = repo_add_solv_flags(data->repo, fp, REPO_USE_LOADING|REPO_LOCALPOOL);
+  fclose(fp);
+  return r ? 0 : 1;
 }
 
 int