- write info block containing addedprovides
authorMichael Schroeder <mls@suse.de>
Wed, 19 Mar 2008 18:22:35 +0000 (18:22 +0000)
committerMichael Schroeder <mls@suse.de>
Wed, 19 Mar 2008 18:22:35 +0000 (18:22 +0000)
- do not load filelist in addfileproviders if the provides
  are already there
- fix some mem leaks

12 files changed:
src/knownid.h
src/pool.c
src/pool.h
src/repo_solv.c
src/repodata.c
src/repodata.h
src/solver.c
src/util.h
tools/common_write.c
tools/dumpsolv.c
tools/repo_write.c
tools/repo_write.h

index f3ea72f..2346fc2 100644 (file)
@@ -48,9 +48,11 @@ KNOWNID(SYSTEM_SYSTEM,                       "system:system"),
 KNOWNID(ARCH_SRC,                      "src"),
 KNOWNID(ARCH_NOSRC,                    "nosrc"),
 KNOWNID(ARCH_NOARCH,                   "noarch"),
+KNOWNID(REPODATA_INFO,                 "repodata:info"),
 KNOWNID(REPODATA_EXTERNAL,             "repodata:external"),
 KNOWNID(REPODATA_KEYS,                 "repodata:keys"),
 KNOWNID(REPODATA_LOCATION,             "repodata:location"),
+KNOWNID(REPODATA_ADDEDFILEPROVIDES,    "repodata:addedfileprovides"),
 
 /* The void type is usable to encode one-valued attributes, they have
    no associated data.  This is useful to encode values which many solvables
index 422e1d5..5caa887 100644 (file)
@@ -647,7 +647,7 @@ pool_addfileprovides_dep(Pool *pool, Id *ida, struct searchfiles *sf, struct sea
       s = id2str(pool, dep);
       if (*s != '/')
        continue;
-      sf->ids = sat_extend(sf->ids, sf->nfiles, 1, sizeof(const char *), SEARCHFILES_BLOCK);
+      sf->ids = sat_extend(sf->ids, sf->nfiles, 1, sizeof(Id), SEARCHFILES_BLOCK);
       sf->dirs = sat_extend(sf->dirs, sf->nfiles, 1, sizeof(const char *), SEARCHFILES_BLOCK);
       sf->names = sat_extend(sf->names, sf->nfiles, 1, sizeof(const char *), SEARCHFILES_BLOCK);
       sf->ids[sf->nfiles] = dep;
@@ -706,8 +706,80 @@ addfileprovides_cb(void *cbdata, Solvable *s, Repodata *data, Repokey *key, KeyV
   return 0;
 }
 
+
+static void
+pool_addfileprovides_search(Pool *pool, struct addfileprovides_cbdata *cbd, struct searchfiles *sf, Repo *repoonly)
+{
+  Id p, start, end, *idp;
+  Solvable *s;
+  Repodata *data = 0, *nextdata;
+  Repo *oldrepo = 0;
+  int dataincludes = 0;
+  int i;
+  Map providedids;
+
+  cbd->nfiles = sf->nfiles;
+  cbd->ids = sf->ids;
+  cbd->dirs = sf->dirs;
+  cbd->names = sf->names;
+  cbd->olddata = 0;
+  cbd->dids = sat_realloc2(cbd->dids, sf->nfiles, sizeof(Id));
+  if (repoonly)
+    {
+      start = repoonly->start;
+      end = repoonly->end;
+    }
+  else
+    {
+      start = 2;       /* skip system solvable */
+      end = pool->nsolvables;
+    }
+  for (p = start, s = pool->solvables + p; p < end; p++, s++)
+    {
+      if (!s->repo || (repoonly && s->repo != repoonly))
+       continue;
+      if (s->repo != oldrepo || (data && p >= data->end))
+       {
+         data = 0;
+         oldrepo = 0;
+       }
+      if (oldrepo == 0)
+       {
+         nextdata = 0;
+         for (i = 0, data = s->repo->repodata; i < s->repo->nrepodata; i++, data++)
+           {
+             if (!data->addedfileprovides || p >= data->end)
+               continue;
+             if (!nextdata || nextdata->start > data->start)
+               nextdata = data;
+             if (p >= data->start)
+               break;
+           }
+         if (i == s->repo->nrepodata)
+           data = nextdata;
+         if (data)
+           {
+             map_init(&providedids, pool->ss.nstrings);
+             for (idp = data->addedfileprovides; *idp; idp++)
+               MAPSET(&providedids, *idp);
+             for (i = 0; i < cbd->nfiles; i++)
+               if (!MAPTST(&providedids, cbd->ids[i]))
+                 {
+                   break;
+                 }
+             map_free(&providedids);
+             dataincludes = i == cbd->nfiles;
+           }
+         oldrepo = s->repo;
+       }
+      if (data && p >= data->start && dataincludes)
+       continue;
+      repo_search(s->repo, p, SOLVABLE_FILELIST, 0, 0, addfileprovides_cb, cbd);
+    }
+}
+
 void
-pool_addfileprovides(Pool *pool, Repo *installed)
+pool_addfileprovides_ids(Pool *pool, Repo *installed, Id **idp)
 {
   Solvable *s;
   Repo *repo;
@@ -748,19 +820,22 @@ pool_addfileprovides(Pool *pool, Repo *installed)
   POOL_DEBUG(SAT_DEBUG_STATS, "found %d installed file dependencies\n", isf.nfiles);
   cbd.dids = 0;
   map_init(&cbd.useddirs, 1);
+  if (idp)
+    *idp = 0;
   if (sf.nfiles)
     {
 #if 0
       for (i = 0; i < sf.nfiles; i++)
        POOL_DEBUG(SAT_DEBUG_STATS, "looking up %s in filelist\n", id2str(pool, sf.ids[i]));
 #endif
-      cbd.nfiles = sf.nfiles;
-      cbd.ids = sf.ids;
-      cbd.dirs = sf.dirs;
-      cbd.names = sf.names;
-      cbd.olddata = 0;
-      cbd.dids = sat_realloc2(cbd.dids, sf.nfiles, sizeof(Id));
-      pool_search(pool, 0, SOLVABLE_FILELIST, 0, 0, addfileprovides_cb, &cbd);
+      pool_addfileprovides_search(pool, &cbd, &sf, 0);
+      if (idp)
+       {
+         sf.ids = sat_extend(sf.ids, sf.nfiles, 1, sizeof(Id), SEARCHFILES_BLOCK);
+         sf.ids[sf.nfiles] = 0;
+         *idp = sf.ids;
+         sf.ids = 0;
+       }
       sat_free(sf.ids);
       for (i = 0; i < sf.nfiles; i++)
        {
@@ -776,13 +851,7 @@ pool_addfileprovides(Pool *pool, Repo *installed)
       for (i = 0; i < isf.nfiles; i++)
        POOL_DEBUG(SAT_DEBUG_STATS, "looking up %s in installed filelist\n", id2str(pool, isf.ids[i]));
 #endif
-      cbd.nfiles = isf.nfiles;
-      cbd.ids = isf.ids;
-      cbd.dirs = isf.dirs;
-      cbd.names = isf.names;
-      cbd.olddata = 0;
-      cbd.dids = sat_realloc2(cbd.dids, isf.nfiles, sizeof(Id));
-      repo_search(installed, 0, SOLVABLE_FILELIST, 0, 0, addfileprovides_cb, &cbd);
+      pool_addfileprovides_search(pool, &cbd, &isf, installed);
       sat_free(isf.ids);
       for (i = 0; i < isf.nfiles; i++)
        {
@@ -798,6 +867,12 @@ pool_addfileprovides(Pool *pool, Repo *installed)
 }
 
 void
+pool_addfileprovides(Pool *pool, Repo *installed)
+{
+  pool_addfileprovides_ids(pool, installed, 0);
+}
+
+void
 pool_search(Pool *pool, Id p, Id key, const char *match, int flags, int (*callback)(void *cbdata, Solvable *s, struct _Repodata *data, struct _Repokey *key, struct _KeyValue *kv), void *cbdata)
 {
   if (p)
@@ -1060,6 +1135,7 @@ pool_calc_duchanges(Pool *pool, Queue *pkgs, DUChanges *mps, int nmps)
       if (sp < 0)
         repo_search(pool->solvables[-sp].repo, -sp, SOLVABLE_DISKUSAGE, 0, 0, solver_fill_DU_cb, &cbd);
     }
+  sat_free(cbd.dirmap);
   sat_free(mptree);
 }
 
index 2b0ade6..3331c33 100644 (file)
@@ -179,6 +179,7 @@ char * solvable_get_location(Solvable *s, unsigned int *medianrp);
  */
 extern void pool_createwhatprovides(Pool *pool);
 extern void pool_addfileprovides(Pool *pool, struct _Repo *installed);
+extern void pool_addfileprovides_ids(Pool *pool, struct _Repo *installed, Id **idp);
 extern void pool_freewhatprovides(Pool *pool);
 extern Id pool_queuetowhatprovides(Pool *pool, Queue *q);
 
index 64ade8d..a543dd3 100644 (file)
@@ -465,8 +465,9 @@ key_cmp (const void *pa, const void *pb)
 static void repodata_load_solv(Repodata *data);
 
 static void
-parse_repodata(Repodata *maindata, Id *keyp, Repokey *keys, Id *idmap, unsigned numid, unsigned numrel, Repo *repo)
+parse_external_repodata(Repodata *maindata, Id *keyp, Repokey *keys, Id *idmap, unsigned numid, unsigned numrel)
 {
+  Repo *repo = maindata->repo;
   Id key, id;
   Id *ida, *ide;
   Repodata *data;
@@ -493,12 +494,12 @@ parse_repodata(Repodata *maindata, Id *keyp, Repokey *keys, Id *idmap, unsigned
            }
          /* read_idarray writes a terminating 0, that's why the + 1 */
          ida = sat_calloc(keys[key].size + 1, sizeof(Id));
-         ide = read_idarray(maindata, 0, 0, ida, ida + keys[key].size + 1);
+         ide = read_idarray(maindata, numid, idmap, ida, ida + keys[key].size + 1);
          n = ide - ida - 1;
          if (n & 1)
            {
              pool_debug (mypool, SAT_ERROR, "invalid attribute data\n");
-             data->error = SOLV_ERROR_CORRUPT;
+             maindata->error = SOLV_ERROR_CORRUPT;
              return;
            }
          data->nkeys = 1 + (n >> 1);
@@ -506,14 +507,8 @@ parse_repodata(Repodata *maindata, Id *keyp, Repokey *keys, Id *idmap, unsigned
          memset(data->keys, 0, sizeof(Repokey));
          for (i = 1, ide = ida; i < data->nkeys; i++)
            {
-             if (*ide >= numid)
-               {
-                 pool_debug (mypool, SAT_ERROR, "invalid attribute data\n");
-                 data->error = SOLV_ERROR_CORRUPT;
-                 return;
-               }
-             data->keys[i].name = idmap ? idmap[*ide++] : *ide++;
-             data->keys[i].type = idmap ? idmap[*ide++] : *ide++;
+             data->keys[i].name = *ide++;
+             data->keys[i].type = *ide++;
              data->keys[i].size = 0;
              data->keys[i].storage = 0;
            }
@@ -542,6 +537,26 @@ parse_repodata(Repodata *maindata, Id *keyp, Repokey *keys, Id *idmap, unsigned
     }
 }
 
+static void
+parse_info_repodata(Repodata *maindata, Id *keyp, Repokey *keys, Id *idmap, unsigned numid, unsigned numrel)
+{
+  Id key, id;
+  Id *ida;
+  while ((key = *keyp++) != 0)
+    {
+      id = keys[key].name;
+      if (id == REPODATA_ADDEDFILEPROVIDES && keys[key].type == REPOKEY_TYPE_IDARRAY)
+       {
+         /* + 1 just in case */
+         ida = sat_calloc(keys[key].size + 1, sizeof(Id));
+         read_idarray(maindata, numid, idmap, ida, ida + keys[key].size + 1);
+         maindata->addedfileprovides = ida;
+         continue;
+       }
+      skip_item(maindata, keys[key].type, numid, numrel);
+    }
+}
+
 /*-----------------------------------------------------------------*/
 
 
@@ -1127,10 +1142,16 @@ repo_add_solv_parent(Repo *repo, FILE *fp, Repodata *parent)
       if (keys[key].name == REPODATA_EXTERNAL && keys[key].type == REPOKEY_TYPE_VOID)
        {
          /* external data for some ids */
-         parse_repodata(&data, keyp, keys, idmap, numid, numrel, repo);
+         parse_external_repodata(&data, keyp, keys, idmap, numid, numrel);
+       }
+      else if (keys[key].name == REPODATA_INFO)
+       {
+         parse_info_repodata(&data, keyp, keys, idmap, numid, numrel);
        }
       else
-       skip_schema(&data, keyp, keys, numid, numrel);
+       {
+         skip_schema(&data, keyp, keys, numid, numrel);
+       }
     }
 
 
@@ -1189,7 +1210,11 @@ repo_add_solv_parent(Repo *repo, FILE *fp, Repodata *parent)
     s = 0;
 
   if (have_xdata)
-    repodata_extend_block(&data, data.start, numsolv);
+    {
+      /* reserve one byte so that all offsets are not zero */
+      incore_add_id(&data, 0);
+      repodata_extend_block(&data, data.start, numsolv);
+    }
 
   left = 0;
   buf = sat_calloc(maxsize + 4, 1);
index f974837..1f52a3e 100644 (file)
@@ -87,6 +87,7 @@ repodata_free(Repodata *data)
   sat_free(data->attriddata);
   
   sat_free(data->location);
+  sat_free(data->addedfileprovides);
 
   if (data->pagefd != -1)
     close(data->pagefd);
@@ -1291,6 +1292,7 @@ repodata_internalize(Repodata *data)
   nentry = data->end - data->start;
   addschema_prepare(data, schematacache);
   memset(&newincore, 0, sizeof(newincore));
+  data_addid(&newincore, 0);
   for (entry = 0; entry < nentry; entry++)
     {
       memset(seen, 0, data->nkeys * sizeof(Id));
index 49d8e0c..8e3ffcd 100644 (file)
@@ -101,6 +101,7 @@ typedef struct _Repodata {
   Id *attriddata;              /* their id space */
   unsigned int attriddatalen;
 
+  Id *addedfileprovides;
 } Repodata;
 
 /* Search key <keyname> (all keys, if keyname == 0) for Id <entry>
index 9364b5a..65f2959 100644 (file)
@@ -3911,6 +3911,7 @@ solver_calc_changed_pkgs(Solver *solv, Queue *pkgs)
   for (p = 1; p < pool->nsolvables; p++)
     if (MAPTST(&installmap, p))
       queue_push(pkgs, p);
+  map_free(&installmap);
   /* run through erase solvable dudata */
   if (solv->installed)
     {
index cb3b87f..e955c07 100644 (file)
@@ -38,6 +38,13 @@ static inline void *sat_extend(void *buf, size_t len, size_t nmemb, size_t size,
   return buf;
 }
 
+static inline void *sat_zextend(void *buf, size_t len, size_t nmemb, size_t size, size_t block)
+{
+  buf = sat_extend(buf, len, nmemb, size, block);
+  memset(buf + len * size, 0, nmemb * size);
+  return buf;
+}
+
 static inline void *sat_extend_resize(void *buf, size_t len, size_t size, size_t block)
 {
   if (len)
index 747388a..c9ea71c 100644 (file)
@@ -143,6 +143,8 @@ keyfilter_other(Repo *repo, Repokey *key, void *kfdata)
  * If <basename> is given, split attributes
  */
 
+#define REPODATAFILE_BLOCK 15
+
 int
 tool_write(Repo *repo, const char *basename, const char *attrname)
 {
@@ -154,6 +156,10 @@ tool_write(Repo *repo, const char *basename, const char *attrname)
   int nlanguages = 0;
   int i, j, k, l;
 
+  fileinfos = sat_zextend(fileinfos, nfileinfos, 1, sizeof(Repodatafile), REPODATAFILE_BLOCK);
+  pool_addfileprovides_ids(repo->pool, 0, &fileinfos[nfileinfos].addedfileprovides);
+  nfileinfos++;
+
   if (basename)
     {
       struct keyfilter_other_data kd;
@@ -189,7 +195,7 @@ tool_write(Repo *repo, const char *basename, const char *attrname)
              languages[nlanguages++] = strdup(keyname + l);
            }
        }
-      fileinfos = sat_calloc(nlanguages + 2, sizeof(Repodatafile));
+      fileinfos = sat_zextend(fileinfos, nfileinfos, nlanguages + 2, sizeof(Repodatafile), REPODATAFILE_BLOCK);
       /* write language subfiles */
       for (i = 0; i < nlanguages; i++)
         {
@@ -200,8 +206,9 @@ tool_write(Repo *repo, const char *basename, const char *attrname)
              exit(1);
            }
           repo_write(repo, fp, keyfilter_language, languages[i], fileinfos + nfileinfos, 0);
-         fileinfos[nfileinfos++].location = strdup(fn);
+         fileinfos[nfileinfos].location = strdup(fn);
          fclose(fp);
+         nfileinfos++;
         }
       /* write DU subfile */
       if (has_DU)
@@ -213,8 +220,9 @@ tool_write(Repo *repo, const char *basename, const char *attrname)
              exit(1);
            }
          repo_write(repo, fp, keyfilter_DU, 0, fileinfos + nfileinfos, 0);
-         fileinfos[nfileinfos++].location = strdup(fn);
+         fileinfos[nfileinfos].location = strdup(fn);
          fclose(fp);
+         nfileinfos++;
        }
       /* write filelist */
       if (has_FL)
@@ -226,8 +234,9 @@ tool_write(Repo *repo, const char *basename, const char *attrname)
              exit(1);
            }
          repo_write(repo, fp, keyfilter_FL, 0, fileinfos + nfileinfos, 0);
-         fileinfos[nfileinfos++].location = strdup(fn);
+         fileinfos[nfileinfos].location = strdup(fn);
          fclose(fp);
+         nfileinfos++;
        }
       /* write everything else */
       sprintf(fn, "%s.solv", basename);
@@ -245,6 +254,7 @@ tool_write(Repo *repo, const char *basename, const char *attrname)
       sat_free(languages);
       for (i = 0; i < nfileinfos; i++)
        {
+         sat_free(fileinfos[i].addedfileprovides);
          sat_free(fileinfos[i].location);
          sat_free(fileinfos[i].keys);
        }
@@ -253,19 +263,21 @@ tool_write(Repo *repo, const char *basename, const char *attrname)
     }
   if (attrname)
     {
-      fileinfos = sat_calloc(1, sizeof(Repodatafile));
+      fileinfos = sat_zextend(fileinfos, nfileinfos, 1, sizeof(Repodatafile), REPODATAFILE_BLOCK);
       test_separate = 1;
       FILE *fp = fopen (attrname, "w");
-      repo_write(repo, fp, keyfilter_attr, 0, fileinfos + nfileinfos++, 0);
-      fileinfos[nfileinfos - 1].location = strdup(attrname);
+      repo_write(repo, fp, keyfilter_attr, 0, fileinfos + nfileinfos, 0);
+      fileinfos[nfileinfos].location = strdup(attrname);
       fclose(fp);
+      nfileinfos++;
     }
   repo_write(repo, stdout, keyfilter_solv, 0, fileinfos, nfileinfos);
-  if (fileinfos)
+  for (i = 0; i < nfileinfos; i++)
     {
-      free(fileinfos[0].location);
-      free(fileinfos[0].keys);
-      free(fileinfos);
+      sat_free(fileinfos[i].addedfileprovides);
+      sat_free(fileinfos[i].location);
+      sat_free(fileinfos[i].keys);
     }
+  sat_free(fileinfos);
   return 0;
 }
index c33a21e..69b84c7 100644 (file)
@@ -33,6 +33,12 @@ dump_repodata (Repo *repo)
        printf("  localpool has %d strings, size is %d\n", data->spool.nstrings, data->spool.sstrings);
       if (data->dirpool.ndirs)
        printf("  localpool has %d directories\n", data->dirpool.ndirs);
+      if (data->addedfileprovides)
+       {
+         printf("  added file provides:\n");
+         for (j = 0; data->addedfileprovides[j]; j++)
+           printf("    %s\n", id2str(repo->pool, data->addedfileprovides[j]));
+       }
       printf("\n");
     }
   printf("\n");
index 26ec556..2a17c18 100644 (file)
@@ -850,8 +850,7 @@ repo_write(Repo *repo, FILE *fp, int (*keyfilter)(Repo *repo, Repokey *key, void
   Dirpool owndirpool, *dirpool;
 
   int setfileinfo = 0;
-  Id repodataschema = 0;
-  Id repodataschema_internal = 0;
+  Id *repodataschemata = 0;
 
   struct extdata *xd;
 
@@ -863,6 +862,8 @@ repo_write(Repo *repo, FILE *fp, int (*keyfilter)(Repo *repo, Repokey *key, void
      writing a subfile and our callers wants info about it.  */
   if (fileinfo && nsubfiles == 0)
     setfileinfo = 1;
+  if (nsubfiles)
+    repodataschemata = sat_calloc(nsubfiles, sizeof(Id));
 
   memset(&cbdata, 0, sizeof(cbdata));
   cbdata.repo = repo;
@@ -912,32 +913,43 @@ repo_write(Repo *repo, FILE *fp, int (*keyfilter)(Repo *repo, Repokey *key, void
     }
   cbdata.nmykeys = i;
 
-  /* If we store subfile info, generate the three necessary keys.  */
+  /* If we store subfile info, generate the necessary keys.  */
   if (nsubfiles)
     {
       key = cbdata.mykeys + cbdata.nmykeys;
+      key->name = REPODATA_INFO;
+      key->type = REPOKEY_TYPE_VOID;
+      key->size = 0;
+      key->storage = KEY_STORAGE_SOLVABLE;
+      cbdata.keymap[key->name] = cbdata.nmykeys++;
+
+      key = cbdata.mykeys + cbdata.nmykeys;
       key->name = REPODATA_EXTERNAL;
       key->type = REPOKEY_TYPE_VOID;
       key->size = 0;
       key->storage = KEY_STORAGE_SOLVABLE;
-      cbdata.keymap[key->name] = key - cbdata.mykeys;
-      key++;
+      cbdata.keymap[key->name] = cbdata.nmykeys++;
 
+      key = cbdata.mykeys + cbdata.nmykeys;
       key->name = REPODATA_KEYS;
       key->type = REPOKEY_TYPE_IDARRAY;
       key->size = 0;
       key->storage = KEY_STORAGE_SOLVABLE;
-      cbdata.keymap[key->name] = key - cbdata.mykeys;
-      key++;
+      cbdata.keymap[key->name] = cbdata.nmykeys++;
 
+      key = cbdata.mykeys + cbdata.nmykeys;
       key->name = REPODATA_LOCATION;
       key->type = REPOKEY_TYPE_STR;
       key->size = 0;
       key->storage = KEY_STORAGE_SOLVABLE;
-      cbdata.keymap[key->name] = key - cbdata.mykeys;
-      key++;
+      cbdata.keymap[key->name] = cbdata.nmykeys++;
 
-      cbdata.nmykeys = key - cbdata.mykeys;
+      key = cbdata.mykeys + cbdata.nmykeys;
+      key->name = REPODATA_ADDEDFILEPROVIDES;
+      key->type = REPOKEY_TYPE_IDARRAY;
+      key->size = 0;
+      key->storage = KEY_STORAGE_SOLVABLE;
+      cbdata.keymap[key->name] = cbdata.nmykeys++;
     }
 
   dirpoolusage = 0;
@@ -1095,7 +1107,7 @@ fprintf(stderr, "poolusage: %d\n", poolusage);
 fprintf(stderr, "dirpoolusage: %d\n", dirpoolusage);
 fprintf(stderr, "nmykeys: %d\n", cbdata.nmykeys);
 for (i = 1; i < cbdata.nmykeys; i++)
-  fprintf(stderr, "  %2d: %d %d %d %d\n", i, cbdata.mykeys[i].name, cbdata.mykeys[i].type, cbdata.mykeys[i].size, cbdata.mykeys[i].storage);
+  fprintf(stderr, "  %2d: %s[%d] %d %d %d\n", i, id2str(pool, cbdata.mykeys[i].name), cbdata.mykeys[i].name, cbdata.mykeys[i].type, cbdata.mykeys[i].size, cbdata.mykeys[i].storage);
 #endif
 
 /********************************************************************/
@@ -1220,44 +1232,34 @@ for (i = 1; i < cbdata.nmykeys; i++)
   for (i = 0; i < nsubfiles; i++)
     {
       int j;
+      Id schema[4], *sp;
 
-      if (fileinfo[i].location && !repodataschema)
-        {
-         Id schema[4];
-         schema[0] = cbdata.keymap[REPODATA_EXTERNAL];
-         schema[1] = cbdata.keymap[REPODATA_KEYS];
-         schema[2] = cbdata.keymap[REPODATA_LOCATION];
-         schema[3] = 0;
-         repodataschema = addschema(&cbdata, schema);
+      sp = schema;
+      if (fileinfo[i].addedfileprovides)
+       {
+         /* extra info about this file */
+         *sp++ = cbdata.keymap[REPODATA_INFO];
+         *sp++ = cbdata.keymap[REPODATA_ADDEDFILEPROVIDES];
+         for (j = 0; fileinfo[i].addedfileprovides[j]; j++)
+           j++;
+         cbdata.mykeys[cbdata.keymap[REPODATA_ADDEDFILEPROVIDES]].size += j + 1;
        }
-      else if (!repodataschema_internal)
-        {
-         Id schema[3];
-         schema[0] = cbdata.keymap[REPODATA_EXTERNAL];
-         schema[1] = cbdata.keymap[REPODATA_KEYS];
-         schema[2] = 0;
-         repodataschema_internal = addschema(&cbdata, schema);
+      else
+       {
+         *sp++ = cbdata.keymap[REPODATA_EXTERNAL];
+         *sp++ = cbdata.keymap[REPODATA_KEYS];
+         if (fileinfo[i].location)
+           *sp++ = cbdata.keymap[REPODATA_LOCATION];
        }
-      if (2 * fileinfo[i].nkeys > cbdata.mykeys[cbdata.keymap[REPODATA_KEYS]].size)
-       cbdata.mykeys[cbdata.keymap[REPODATA_KEYS]].size = 2 * fileinfo[i].nkeys;
+      *sp = 0;
+      repodataschemata[i] = addschema(&cbdata, schema);
+      cbdata.mykeys[cbdata.keymap[REPODATA_KEYS]].size += 2 * fileinfo[i].nkeys + 1;
       for (j = 1; j < fileinfo[i].nkeys; j++)
        {
          needid[fileinfo[i].keys[j].type].need++;
          needid[fileinfo[i].keys[j].name].need++;
        }
-#if 0
-      fprintf (stderr, " %d nkeys: %d:", i, fileinfo[i].nkeys);
-      for (j = 1; j < fileinfo[i].nkeys; j++)
-        {
-         needid[fileinfo[i].keys[j].name].need++;
-         fprintf (stderr, " %s(%d,%d)", id2str(pool, fileinfo[i].keys[j].name),
-                  fileinfo[i].keys[j].name, fileinfo[i].keys[j].type);
-       }
-      fprintf (stderr, "\n");
-#endif
     }
-  if (nsubfiles)
-    cbdata.mykeys[cbdata.keymap[REPODATA_KEYS]].size -= 2;
 
 /********************************************************************/
 
@@ -1601,18 +1603,23 @@ fprintf(stderr, "dir %d used %d\n", i, cbdata.dirused ? cbdata.dirused[i] : 1);
          int j;
 
          cur = xd.len;
-         if (fileinfo[i].location)
-           data_addid(&xd, repodataschema);
+         data_addid(&xd, repodataschemata[i]);
+         if (fileinfo[i].addedfileprovides)
+           {
+             for (j = 0; fileinfo[i].addedfileprovides[j]; j++)
+               data_addideof(&xd, needid[fileinfo[i].addedfileprovides[j]].need, fileinfo[i].addedfileprovides[j + 1] ? 0 : 1);
+           }
          else
-           data_addid(&xd, repodataschema_internal);
-         /* key,type array + location, write idarray */
-         for (j = 1; j < fileinfo[i].nkeys; j++)
            {
-             data_addideof(&xd, needid[fileinfo[i].keys[j].name].need, 0);
-             data_addideof(&xd, needid[fileinfo[i].keys[j].type].need, j == fileinfo[i].nkeys - 1);
+             /* key,type array + location, write idarray */
+             for (j = 1; j < fileinfo[i].nkeys; j++)
+               {
+                 data_addideof(&xd, needid[fileinfo[i].keys[j].name].need, 0);
+                 data_addideof(&xd, needid[fileinfo[i].keys[j].type].need, j == fileinfo[i].nkeys - 1);
+               }
+             if (fileinfo[i].location)
+               data_addblob(&xd, (unsigned char *)fileinfo[i].location, strlen(fileinfo[i].location) + 1);
            }
-         if (fileinfo[i].location)
-           data_addblob(&xd, (unsigned char *)fileinfo[i].location, strlen(fileinfo[i].location) + 1);
          cur = xd.len - cur;
          if (cur > max)
            max = cur;
@@ -1716,4 +1723,5 @@ fprintf(stderr, "dir %d used %d\n", i, cbdata.dirused ? cbdata.dirused[i] : 1);
   sat_free(cbdata.keymapstart);
   sat_free(cbdata.dirused);
   sat_free(repodataused);
+  sat_free(repodataschemata);
 }
index 149eb3e..0d9d51d 100644 (file)
@@ -29,6 +29,7 @@ typedef struct _Repodatafile
   unsigned checksumtype;
   struct _Repokey *keys;
   unsigned int nkeys;
+  Id *addedfileprovides;
 } Repodatafile;
 
 void repo_write(Repo *repo, FILE *fp, int (*keyfilter)(Repo *repo, Repokey *key, void *kfdata), void *kfdata, Repodatafile *fileinfo, int nsubfiles);