- fix di->repoid to be consistent with repo->repoid
[platform/upstream/libsolv.git] / src / repodata.c
index e256245..55517c5 100644 (file)
 #include "repopack.h"
 #include "repopage.h"
 
-extern unsigned int compress_buf (const unsigned char *in, unsigned int in_len,
-                                 unsigned char *out, unsigned int out_len);
-extern unsigned int unchecked_decompress_buf (const unsigned char *in,
-                                             unsigned int in_len,
-                                             unsigned char *out,
-                                             unsigned int out_len);
-
 #define REPODATA_BLOCK 255
 
+static unsigned char *data_skip_key(Repodata *data, unsigned char *dp, Repokey *key);
 
 void
 repodata_initdata(Repodata *data, Repo *repo, int localpool)
@@ -52,6 +46,7 @@ repodata_initdata(Repodata *data, Repo *repo, int localpool)
   data->localpool = localpool;
   if (localpool)
     stringpool_init_empty(&data->spool);
+  /* dirpool_init(&data->dirpool);     just zeros out again */
   data->keys = sat_calloc(1, sizeof(Repokey));
   data->nkeys = 1;
   data->schemata = sat_calloc(1, sizeof(Id));
@@ -116,10 +111,21 @@ repodata_free(Repodata *data)
   int i = data - repo->repodata;
   repodata_freedata(data);
   if (i < repo->nrepodata - 1)
-  memmove(repo->repodata + i, repo->repodata + i + 1, (repo->nrepodata - 1 - i) * sizeof(Repodata));
+    memmove(repo->repodata + i, repo->repodata + i + 1, (repo->nrepodata - 1 - i) * sizeof(Repodata));
   repo->nrepodata--;
 }
 
+void
+repodata_empty(Repodata *data, int localpool)
+{
+  void (*loadcallback)(Repodata *) = data->loadcallback;
+  int state = data->state;
+  repodata_freedata(data);
+  repodata_initdata(data, data->repo, localpool);
+  data->state = state;
+  data->loadcallback = loadcallback;
+}
+
 
 /***************************************************************
  * key pool management
@@ -171,15 +177,17 @@ repodata_schema2id(Repodata *data, Id *schema, int create)
   Id *sp, cid;
   Id *schematahash;
 
+  if (!*schema)
+    return 0;  /* XXX: allow empty schema? */
   if ((schematahash = data->schematahash) == 0)
     {
       data->schematahash = schematahash = sat_calloc(256, sizeof(Id));
-      for (i = 0; i < data->nschemata; i++)
+      for (i = 1; i < data->nschemata; i++)
        {
          for (sp = data->schemadata + data->schemata[i], h = 0; *sp; len++)
            h = h * 7 + *sp++;
          h &= 255;
-         schematahash[h] = i + 1;
+         schematahash[h] = i;
        }
       data->schemadata = sat_extend_resize(data->schemadata, data->schemadatalen, sizeof(Id), SCHEMATADATA_BLOCK);
       data->schemata = sat_extend_resize(data->schemata, data->nschemata, sizeof(Id), SCHEMATA_BLOCK);
@@ -193,11 +201,10 @@ repodata_schema2id(Repodata *data, Id *schema, int create)
   cid = schematahash[h];
   if (cid)
     {
-      cid--;
       if (!memcmp(data->schemadata + data->schemata[cid], schema, len * sizeof(Id)))
         return cid;
-      /* cache conflict */
-      for (cid = 0; cid < data->nschemata; cid++)
+      /* cache conflict, do a slow search */
+      for (cid = 1; cid < data->nschemata; cid++)
         if (!memcmp(data->schemadata + data->schemata[cid], schema, len * sizeof(Id)))
           return cid;
     }
@@ -210,7 +217,7 @@ repodata_schema2id(Repodata *data, Id *schema, int create)
   memcpy(data->schemadata + data->schemadatalen, schema, len * sizeof(Id));
   data->schemata[data->nschemata] = data->schemadatalen;
   data->schemadatalen += len;
-  schematahash[h] = data->nschemata + 1;
+  schematahash[h] = data->nschemata;
 #if 0
 fprintf(stderr, "schema2id: new schema\n");
 #endif
@@ -231,6 +238,14 @@ repodata_free_schemahash(Repodata *data)
  * dir pool management
  */
 
+#ifndef HAVE_STRCHRNUL
+static inline const char *strchrnul(const char *str, char x)
+{
+  const char *p = strchr(str, x);
+  return p ? p : str + strlen(str);
+}
+#endif
+
 Id
 repodata_str2dir(Repodata *data, const char *dir, int create)
 {
@@ -241,14 +256,18 @@ repodata_str2dir(Repodata *data, const char *dir, int create)
   while (*dir == '/' && dir[1] == '/')
     dir++;
   if (*dir == '/' && !dir[1])
-    return 1;
+    {
+      if (data->dirpool.ndirs)
+        return 1;
+      return dirpool_add_dir(&data->dirpool, 0, 1, create);
+    }
   while (*dir)
     {
       dire = strchrnul(dir, '/');
       if (data->localpool)
         id = stringpool_strn2id(&data->spool, dir, dire - dir, create);
       else
-       id = strn2id(data->repo->pool, dir, dire - dir, create);
+       id = pool_strn2id(data->repo->pool, dir, dire - dir, create);
       if (!id)
        return 0;
       parent = dirpool_add_dir(&data->dirpool, parent, id, create);
@@ -323,7 +342,7 @@ data_skip_schema(Repodata *data, unsigned char *dp, Id schema)
   return dp;
 }
 
-unsigned char *
+static unsigned char *
 data_skip_key(Repodata *data, unsigned char *dp, Repokey *key)
 {
   int nentries, schema;
@@ -406,10 +425,10 @@ get_vertical_data(Repodata *data, Repokey *key, Id off, Id len)
     return 0;
   /* we now have the offset, go into vertical */
   off += data->verticaloffset[key - data->keys];
-  /* fprintf(stderr, "key %d page %d\n", key->name, off / BLOB_PAGESIZE); */
-  dp = repopagestore_load_page_range(&data->store, off / BLOB_PAGESIZE, (off + len - 1) / BLOB_PAGESIZE);
+  /* fprintf(stderr, "key %d page %d\n", key->name, off / REPOPAGE_BLOBSIZE); */
+  dp = repopagestore_load_page_range(&data->store, off / REPOPAGE_BLOBSIZE, (off + len - 1) / REPOPAGE_BLOBSIZE);
   if (dp)
-    dp += off % BLOB_PAGESIZE;
+    dp += off % REPOPAGE_BLOBSIZE;
   return dp;
 }
 
@@ -530,6 +549,8 @@ find_key_data(Repodata *data, Id solvid, Id keyname, Repokey **keypp)
   if (!*kp)
     return 0;
   *keypp = key = data->keys + *kp;
+  if (key->type == REPOKEY_TYPE_DELETED)
+    return 0;
   if (key->type == REPOKEY_TYPE_VOID || key->type == REPOKEY_TYPE_CONSTANT || key->type == REPOKEY_TYPE_CONSTANTID)
     return dp; /* no need to forward... */
   dp = forward_to_key(data, *kp, keyp, dp);
@@ -538,6 +559,20 @@ find_key_data(Repodata *data, Id solvid, Id keyname, Repokey **keypp)
   return get_data(data, key, &dp, 0);
 }
 
+Id
+repodata_lookup_type(Repodata *data, Id solvid, Id keyname)
+{
+  Id schema, *keyp, *kp;
+  if (!maybe_load_repodata(data, keyname))
+    return 0;
+  if (!solvid2data(data, solvid, &schema))
+    return 0;
+  keyp = data->schemadata + data->schemata[schema];
+  for (kp = keyp; *kp; kp++)
+    if (data->keys[*kp].name == keyname)
+      return data->keys[*kp].type;
+  return 0;
+}
 
 Id
 repodata_lookup_id(Repodata *data, Id solvid, Id keyname)
@@ -557,14 +592,6 @@ repodata_lookup_id(Repodata *data, Id solvid, Id keyname)
   return id;
 }
 
-Id
-repodata_globalize_id(Repodata *data, Id id, int create)
-{
-  if (!id || !data || !data->localpool)
-    return id;
-  return str2id(data->repo->pool, stringpool_id2str(&data->spool, id), create);
-}
-
 const char *
 repodata_lookup_str(Repodata *data, Id solvid, Id keyname)
 {
@@ -578,14 +605,14 @@ repodata_lookup_str(Repodata *data, Id solvid, Id keyname)
   if (key->type == REPOKEY_TYPE_STR)
     return (const char *)dp;
   if (key->type == REPOKEY_TYPE_CONSTANTID)
-    return id2str(data->repo->pool, key->size);
-  if (key->type == REPOKEY_TYPE_ID)
+    id = key->size;
+  else if (key->type == REPOKEY_TYPE_ID)
     dp = data_read_id(dp, &id);
   else
     return 0;
   if (data->localpool)
-    return data->spool.stringspace + data->spool.strings[id];
-  return id2str(data->repo->pool, id);
+    return stringpool_id2str(&data->spool, id);
+  return pool_id2str(data->repo->pool, id);
 }
 
 int
@@ -603,6 +630,7 @@ repodata_lookup_num(Repodata *data, Id solvid, Id keyname, unsigned int *value)
       || key->type == REPOKEY_TYPE_U32
       || key->type == REPOKEY_TYPE_CONSTANT)
     {
+      kv.num = 0;
       dp = data_fetch(dp, &kv, key);
       *value = kv.num;
       return 1;
@@ -642,6 +670,46 @@ repodata_lookup_bin_checksum(Repodata *data, Id solvid, Id keyname, Id *typep)
   return dp;
 }
 
+int
+repodata_lookup_idarray(Repodata *data, Id solvid, Id keyname, Queue *q)
+{
+  unsigned char *dp;
+  Repokey *key;
+  Id id;
+  int eof = 0;
+
+  queue_empty(q);
+  dp = find_key_data(data, solvid, keyname, &key);
+  if (!dp)
+    return 0;
+  if (key->type != REPOKEY_TYPE_IDARRAY && key->type != REPOKEY_TYPE_REL_IDARRAY)
+    return 0;
+  for (;;)
+    {
+      dp = data_read_ideof(dp, &id, &eof);
+      queue_push(q, id);
+      if (eof)
+       break;
+    }
+  return 1;
+}
+
+Id
+repodata_globalize_id(Repodata *data, Id id, int create)
+{
+  if (!id || !data || !data->localpool)
+    return id;
+  return pool_str2id(data->repo->pool, stringpool_id2str(&data->spool, id), create);
+}
+
+Id
+repodata_localize_id(Repodata *data, Id id, int create)
+{
+  if (!id || !data || !data->localpool)
+    return id;
+  return stringpool_str2id(&data->spool, pool_id2str(data->repo->pool, id), create);
+}
+
 
 /************************************************************************
  * data search
@@ -659,7 +727,7 @@ repodata_stringify(Pool *pool, Repodata *data, Repokey *key, KeyValue *kv, int f
       if (data && data->localpool)
        kv->str = stringpool_id2str(&data->spool, kv->id);
       else
-       kv->str = id2str(pool, kv->id);
+       kv->str = pool_id2str(pool, kv->id);
       if ((flags & SEARCH_SKIP_KIND) != 0 && key->storage == KEY_STORAGE_SOLVABLE)
        {
          const char *s;
@@ -754,6 +822,8 @@ repodata_search(Repodata *data, Id solvid, Id keyname, int flags, int (*callback
       key = data->keys + keyid;
       ddp = get_data(data, key, &dp, *keyp ? 1 : 0);
 
+      if (key->type == REPOKEY_TYPE_DELETED)
+       continue;
       if (key->type == REPOKEY_TYPE_FLEXARRAY || key->type == REPOKEY_TYPE_FIXARRAY)
        {
          struct subschema_data subd;
@@ -1106,7 +1176,7 @@ void
 dataiterator_set_search(Dataiterator *di, Repo *repo, Id p)
 {
   di->repo = repo;
-  di->repoid = -1;
+  di->repoid = 0;
   di->flags &= ~SEARCH_THISSOLVID;
   di->nparents = 0;
   di->rootlevel = 0;
@@ -1118,7 +1188,7 @@ dataiterator_set_search(Dataiterator *di, Repo *repo, Id p)
     }
   if (!repo)
     {
-      di->repoid = 0;
+      di->repoid = 1;
       di->repo = di->pool->repos[0];
     }
   di->state = di_enterrepo;
@@ -1184,7 +1254,10 @@ dataiterator_filelistcheck(Dataiterator *di)
   Repodata *data = di->data;
 
   if ((di->matcher.flags & SEARCH_COMPLETE_FILELIST) != 0)
-    if (!di->matcher.match || (di->matcher.flags & (SEARCH_STRINGMASK|SEARCH_NOCASE)) != SEARCH_STRING || !repodata_filelistfilter_matches(di->data, di->matcher.match))
+    if (!di->matcher.match
+       || ((di->matcher.flags & (SEARCH_STRINGMASK|SEARCH_NOCASE)) != SEARCH_STRING
+           && (di->matcher.flags & (SEARCH_STRINGMASK|SEARCH_NOCASE)) != SEARCH_GLOB)
+       || !repodata_filelistfilter_matches(di->data, di->matcher.match))
       needcomplete = 1;
   if (data->state != REPODATA_AVAILABLE)
     return needcomplete ? 1 : 0;
@@ -1265,6 +1338,8 @@ dataiterator_step(Dataiterator *di)
          di->ddp = get_data(di->data, di->key, &di->dp, di->keyp[1] && (!di->keyname || (di->flags & SEARCH_SUB) != 0) ? 1 : 0);
          if (!di->ddp)
            goto di_nextkey;
+          if (di->key->type == REPOKEY_TYPE_DELETED)
+           goto di_nextkey;
          if (di->key->type == REPOKEY_TYPE_FIXARRAY || di->key->type == REPOKEY_TYPE_FLEXARRAY)
            goto di_enterarray;
          if (di->nkeynames && di->nparents - di->rootlevel < di->nkeynames)
@@ -1308,13 +1383,13 @@ dataiterator_step(Dataiterator *di)
          /* FALLTHROUGH */
 
        case di_nextrepo: di_nextrepo:
-         if (di->repoid >= 0)
+         if (di->repoid > 0)
            {
              di->repoid++;
              di->repodataid = 0;
-             if (di->repoid < di->pool->nrepos)
+             if (di->repoid - 1 < di->pool->nrepos)
                {
-                 di->repo = di->pool->repos[di->repoid];
+                 di->repo = di->pool->repos[di->repoid - 1];
                  goto di_enterrepo;
                }
            }
@@ -1570,6 +1645,7 @@ void
 dataiterator_skip_solvable(Dataiterator *di)
 {
   di->nparents = 0;
+  di->kv.parent = 0;
   di->rootlevel = 0;
   di->keyname = di->keynames[0];
   di->state = di_nextsolvable;
@@ -1579,6 +1655,7 @@ void
 dataiterator_skip_repo(Dataiterator *di)
 {
   di->nparents = 0;
+  di->kv.parent = 0;
   di->rootlevel = 0;
   di->keyname = di->keynames[0];
   di->state = di_nextrepo;
@@ -1588,6 +1665,7 @@ void
 dataiterator_jump_to_solvid(Dataiterator *di, Id solvid)
 {
   di->nparents = 0;
+  di->kv.parent = 0;
   di->rootlevel = 0;
   di->keyname = di->keynames[0];
   if (solvid == SOLVID_POS)
@@ -1598,7 +1676,7 @@ dataiterator_jump_to_solvid(Dataiterator *di, Id solvid)
          di->state = di_bye;
          return;
        }
-      di->repoid = -1;
+      di->repoid = 0;
       di->data = di->repo->repodata + di->pool->pos.repodataid;
       di->repodataid = -1;
       di->solvid = solvid;
@@ -1609,17 +1687,17 @@ dataiterator_jump_to_solvid(Dataiterator *di, Id solvid)
   if (solvid > 0)
     {
       di->repo = di->pool->solvables[solvid].repo;
-      di->repoid = -1;
+      di->repoid = 0;
     }
-  else if (di->repoid >= 0)
+  else if (di->repoid > 0)
     {
       if (!di->pool->nrepos)
        {
          di->state = di_bye;
          return;
        }
+      di->repoid = 1;
       di->repo = di->pool->repos[0];
-      di->repoid = 0;
     }
   di->repodataid = 0;
   di->solvid = solvid;
@@ -1632,9 +1710,10 @@ void
 dataiterator_jump_to_repo(Dataiterator *di, Repo *repo)
 {
   di->nparents = 0;
+  di->kv.parent = 0;
   di->rootlevel = 0;
   di->repo = repo;
-  di->repoid = -1;
+  di->repoid = 0;      /* 0 means stay at repo */
   di->repodataid = 0;
   di->solvid = 0;
   di->flags &= ~SEARCH_THISSOLVID;
@@ -1743,7 +1822,7 @@ repodata_extend_block(Repodata *data, Id start, Id num)
 /**********************************************************************/
 
 
-#define REPODATA_ATTRS_BLOCK 63
+#define REPODATA_ATTRS_BLOCK 31
 #define REPODATA_ATTRDATA_BLOCK 1023
 #define REPODATA_ATTRIDDATA_BLOCK 63
 
@@ -1754,7 +1833,7 @@ repodata_new_handle(Repodata *data)
   if (!data->nxattrs)
     {
       data->xattrs = sat_calloc_block(1, sizeof(Id *), REPODATA_BLOCK);
-      data->nxattrs = 2;
+      data->nxattrs = 2;       /* -1: SOLVID_META */
     }
   data->xattrs = sat_extend(data->xattrs, data->nxattrs, 1, sizeof(Id *), REPODATA_BLOCK);
   data->xattrs[data->nxattrs] = 0;
@@ -1764,16 +1843,15 @@ repodata_new_handle(Repodata *data)
 static inline Id **
 repodata_get_attrp(Repodata *data, Id handle)
 {
-  if (handle == SOLVID_META)
+  if (handle < 0)
     {
-      if (!data->xattrs)
+      if (handle == SOLVID_META && !data->xattrs)
        {
          data->xattrs = sat_calloc_block(1, sizeof(Id *), REPODATA_BLOCK);
           data->nxattrs = 2;
        }
+      return data->xattrs - handle;
     }
-  if (handle < 0)
-    return data->xattrs - handle;
   if (handle < data->start || handle >= data->end)
     repodata_extend(data, handle);
   if (!data->attrs)
@@ -1800,7 +1878,7 @@ repodata_insert_keyid(Repodata *data, Id handle, Id keyid, Id val, int overwrite
           break;
       if (*pp)
         {
-         if (overwrite)
+         if (overwrite || data->keys[*pp].type == REPOKEY_TYPE_DELETED)
            {
              pp[0] = keyid;
               pp[1] = val;
@@ -1857,7 +1935,7 @@ repodata_set_poolstr(Repodata *data, Id solvid, Id keyname, const char *str)
   if (data->localpool)
     id = stringpool_str2id(&data->spool, str, 1);
   else
-    id = str2id(data->repo->pool, str, 1);
+    id = pool_str2id(data->repo->pool, str, 1);
   key.name = keyname;
   key.type = REPOKEY_TYPE_ID;
   key.size = 0;
@@ -1915,8 +1993,37 @@ repodata_set_str(Repodata *data, Id solvid, Id keyname, const char *str)
   data->attrdatalen += l;
 }
 
+void
+repodata_set_binary(Repodata *data, Id solvid, Id keyname, void *buf, int len)
+{
+  Repokey key;
+  unsigned char *dp;
+
+  key.name = keyname;
+  key.type = REPOKEY_TYPE_BINARY;
+  key.size = 0;
+  key.storage = KEY_STORAGE_INCORE;
+  data->attrdata = sat_extend(data->attrdata, data->attrdatalen, len + 5, 1, REPODATA_ATTRDATA_BLOCK);
+  dp = data->attrdata + data->attrdatalen;
+  if (len >= (1 << 14))
+    {
+      if (len >= (1 << 28))
+        *dp++ = (len >> 28) | 128;
+      if (len >= (1 << 21))
+        *dp++ = (len >> 21) | 128;
+      *dp++ = (len >> 14) | 128;
+    }
+  if (len >= (1 << 7))
+    *dp++ = (len >> 7) | 128;
+  *dp++ = len & 127;
+  if (len)
+    memcpy(dp, buf, len);
+  repodata_set(data, solvid, &key, data->attrdatalen);
+  data->attrdatalen = dp + len - data->attrdata;
+}
+
 /* add an array element consisting of entrysize Ids to the repodata. modifies attriddata
- * so that the caller can append the new element there */
+ * so that the caller can append entrysize new elements plus the termination zero there */
 static void
 repodata_add_array(Repodata *data, Id handle, Id keyname, Id keytype, int entrysize)
 {
@@ -1936,20 +2043,26 @@ repodata_add_array(Repodata *data, Id handle, Id keyname, Id keytype, int entrys
   ppp = repodata_get_attrp(data, handle);
   pp = *ppp;
   if (pp)
-    for (; *pp; pp += 2)
-      if (data->keys[*pp].name == keyname && data->keys[*pp].type == keytype)
-        break;
-  if (!pp || !*pp)
+    {
+      for (; *pp; pp += 2)
+        if (data->keys[*pp].name == keyname)
+          break;
+    }
+  if (!pp || !*pp || data->keys[*pp].type != keytype)
     {
       /* not found. allocate new key */
       Repokey key;
+      Id keyid;
       key.name = keyname;
       key.type = keytype;
       key.size = 0;
       key.storage = KEY_STORAGE_INCORE;
       data->attriddata = sat_extend(data->attriddata, data->attriddatalen, entrysize + 1, sizeof(Id), REPODATA_ATTRIDDATA_BLOCK);
-      repodata_set(data, handle, &key, data->attriddatalen);
-      data->lasthandle = 0;    /* next time... */
+      keyid = repodata_key2id(data, &key, 1);
+      repodata_insert_keyid(data, handle, keyid, data->attriddatalen, 1);
+      data->lasthandle = handle;
+      data->lastkey = keyid;
+      data->lastdatalen = data->attriddatalen + entrysize + 1;
       return;
     }
   oldsize = 0;
@@ -1993,31 +2106,6 @@ repodata_set_bin_checksum(Repodata *data, Id solvid, Id keyname, Id type,
   data->attrdatalen += l;
 }
 
-static int
-hexstr2bytes(unsigned char *buf, const char *str, int buflen)
-{
-  int i;
-  for (i = 0; i < buflen; i++)
-    {
-#define c2h(c) (((c)>='0' && (c)<='9') ? ((c)-'0')             \
-               : ((c)>='a' && (c)<='f') ? ((c)-('a'-10))       \
-               : ((c)>='A' && (c)<='F') ? ((c)-('A'-10))       \
-               : -1)
-      int v = c2h(*str);
-      str++;
-      if (v < 0)
-       return 0;
-      buf[i] = v;
-      v = c2h(*str);
-      str++;
-      if (v < 0)
-       return 0;
-      buf[i] = (buf[i] << 4) | v;
-#undef c2h
-    }
-  return buflen;
-}
-
 void
 repodata_set_checksum(Repodata *data, Id solvid, Id keyname, Id type,
                      const char *str)
@@ -2027,7 +2115,7 @@ repodata_set_checksum(Repodata *data, Id solvid, Id keyname, Id type,
 
   if (!(l = sat_chksum_len(type)))
     return;
-  if (hexstr2bytes(buf, str, l) != l)
+  if (l > sizeof(buf) || sat_hex2bin(&str, buf, l) != l)
     return;
   repodata_set_bin_checksum(data, solvid, keyname, type, buf);
 }
@@ -2035,29 +2123,18 @@ repodata_set_checksum(Repodata *data, Id solvid, Id keyname, Id type,
 const char *
 repodata_chk2str(Repodata *data, Id type, const unsigned char *buf)
 {
-  int i, l;
-  char *str, *s;
+  int l;
 
   if (!(l = sat_chksum_len(type)))
     return "";
-  s = str = pool_alloctmpspace(data->repo->pool, 2 * l + 1);
-  for (i = 0; i < l; i++)
-    {
-      unsigned char v = buf[i];
-      unsigned char w = v >> 4;
-      *s++ = w >= 10 ? w + ('a' - 10) : w + '0';
-      w = v & 15;
-      *s++ = w >= 10 ? w + ('a' - 10) : w + '0';
-    }
-  *s = 0;
-  return str;
+  return pool_bin2hex(data->repo->pool, buf, l);
 }
 
 /* rpm filenames don't contain the epoch, so strip it */
 static inline const char *
 evrid2vrstr(Pool *pool, Id evrid)
 {
-  const char *p, *evr = id2str(pool, evrid);
+  const char *p, *evr = pool_id2str(pool, evrid);
   if (!evr)
     return evr;
   for (p = evr; *p >= '0' && *p <= '9'; p++)
@@ -2098,7 +2175,7 @@ repodata_set_location(Repodata *data, Id solvid, int medianr, const char *dir, c
   s = pool->solvables + solvid;
   if (dir && l)
     {
-      str = id2str(pool, s->arch);
+      str = pool_id2str(pool, s->arch);
       if (!strncmp(dir, str, l) && !str[l])
        repodata_set_void(data, solvid, SOLVABLE_MEDIADIR);
       else if (!dir[l])
@@ -2112,7 +2189,7 @@ repodata_set_location(Repodata *data, Id solvid, int medianr, const char *dir, c
        }
     }
   fp = file;
-  str = id2str(pool, s->name);
+  str = pool_id2str(pool, s->name);
   l = strlen(str);
   if ((!l || !strncmp(fp, str, l)) && fp[l] == '-')
     {
@@ -2122,7 +2199,7 @@ repodata_set_location(Repodata *data, Id solvid, int medianr, const char *dir, c
       if ((!l || !strncmp(fp, str, l)) && fp[l] == '.')
        {
          fp += l + 1;
-         str = id2str(pool, s->arch);
+         str = pool_id2str(pool, s->arch);
          l = strlen(str);
          if ((!l || !strncmp(fp, str, l)) && !strcmp(fp + l, ".rpm"))
            {
@@ -2135,6 +2212,23 @@ repodata_set_location(Repodata *data, Id solvid, int medianr, const char *dir, c
 }
 
 void
+repodata_set_idarray(Repodata *data, Id solvid, Id keyname, Queue *q)
+{
+  Repokey key;
+  int i;
+
+  key.name = keyname;
+  key.type = REPOKEY_TYPE_IDARRAY;
+  key.size = 0;
+  key.storage = KEY_STORAGE_INCORE;
+  repodata_set(data, solvid, &key, data->attriddatalen);
+  data->attriddata = sat_extend(data->attriddata, data->attriddatalen, q->count + 1, sizeof(Id), REPODATA_ATTRIDDATA_BLOCK);
+  for (i = 0; i < q->count; i++)
+    data->attriddata[data->attriddatalen++] = q->elements[i];
+  data->attriddata[data->attriddatalen++] = 0;
+}
+
+void
 repodata_add_dirnumnum(Repodata *data, Id solvid, Id keyname, Id dir, Id num, Id num2)
 {
   assert(dir);
@@ -2189,7 +2283,7 @@ repodata_add_poolstr_array(Repodata *data, Id solvid, Id keyname,
   if (data->localpool)
     id = stringpool_str2id(&data->spool, str, 1);
   else
-    id = str2id(data->repo->pool, str, 1);
+    id = pool_str2id(data->repo->pool, str, 1);
   repodata_add_idarray(data, solvid, keyname, id);
 }
 
@@ -2209,7 +2303,44 @@ repodata_add_flexarray(Repodata *data, Id solvid, Id keyname, Id ghandle)
   data->attriddata[data->attriddatalen++] = 0;
 }
 
-/* add all attrs from src to dest */
+void
+repodata_delete_uninternalized(Repodata *data, Id solvid, Id keyname)
+{
+  Id *pp, *ap, **app;
+  app = repodata_get_attrp(data, solvid);
+  ap = *app;
+  if (!ap)
+    return;
+  for (; *ap; ap += 2)
+    if (data->keys[*ap].name == keyname)
+      break;
+  if (!*ap)
+    return;
+  pp = ap;
+  ap += 2;
+  for (; *ap; ap += 2)
+    {
+      if (data->keys[*ap].name == keyname)
+       continue;
+      *pp++ = ap[0];
+      *pp++ = ap[1];
+    }
+  *pp = 0;
+}
+
+/* XXX: does not work correctly, needs fix in iterators! */
+void
+repodata_delete(Repodata *data, Id solvid, Id keyname)
+{
+  Repokey key;
+  key.name = keyname;
+  key.type = REPOKEY_TYPE_DELETED;
+  key.size = 0;
+  key.storage = KEY_STORAGE_INCORE;
+  repodata_set(data, solvid, &key, 0);
+}
+
+/* add all (uninternalized) attrs from src to dest */
 void
 repodata_merge_attrs(Repodata *data, Id dest, Id src)
 {
@@ -2220,6 +2351,7 @@ repodata_merge_attrs(Repodata *data, Id dest, Id src)
     repodata_insert_keyid(data, dest, keyp[0], keyp[1], 0);
 }
 
+/* add some (uninternalized) attrs from src to dest */
 void
 repodata_merge_some_attrs(Repodata *data, Id dest, Id src, Map *keyidmap, int overwrite)
 {
@@ -2235,7 +2367,7 @@ repodata_merge_some_attrs(Repodata *data, Id dest, Id src, Map *keyidmap, int ov
 
 /**********************************************************************/
 
-/* TODO: unify with repo_write! */
+/* TODO: unify with repo_write and repo_solv! */
 
 #define EXTDATA_BLOCK 1023
 
@@ -2248,6 +2380,7 @@ static void
 data_addid(struct extdata *xd, Id x)
 {
   unsigned char *dp;
+
   xd->buf = sat_extend(xd->buf, xd->len, 5, 1, EXTDATA_BLOCK);
   dp = xd->buf + xd->len;
 
@@ -2270,7 +2403,7 @@ data_addideof(struct extdata *xd, Id x, int eof)
 {
   if (x >= 64)
     x = (x & 63) | ((x & ~63) << 1);
-  data_addid(xd, (eof ? x: x | 64));
+  data_addid(xd, (eof ? x : x | 64));
 }
 
 static void
@@ -2283,14 +2416,14 @@ data_addblob(struct extdata *xd, unsigned char *blob, int len)
 
 /*********************************/
 
+/* internalalize some key into incore/vincore data */
+
 static void
 repodata_serialize_key(Repodata *data, struct extdata *newincore,
                       struct extdata *newvincore,
                       Id *schema,
                       Repokey *key, Id val)
 {
-  /* Otherwise we have a new value.  Parse it into the internal
-     form.  */
   Id *ida;
   struct extdata *xd;
   unsigned int oldvincorelen = 0;
@@ -2325,6 +2458,14 @@ repodata_serialize_key(Repodata *data, struct extdata *newincore,
     case REPOKEY_TYPE_DIR:
       data_addid(xd, val);
       break;
+    case REPOKEY_TYPE_BINARY:
+      {
+       Id len;
+       unsigned char *dp = data_read_id(data->attrdata + val, &len);
+       dp += len;
+       data_addblob(xd, data->attrdata + val, dp - (data->attrdata + val));
+      }
+      break;
     case REPOKEY_TYPE_IDARRAY:
       for (ida = data->attriddata + val; *ida; ida++)
        data_addideof(xd, ida[0], ida[1] ? 0 : 1);
@@ -2350,21 +2491,13 @@ repodata_serialize_key(Repodata *data, struct extdata *newincore,
        schemaid = 0;
        for (ida = data->attriddata + val; *ida; ida++)
          {
-#if 0
-           fprintf(stderr, "serialize struct %d\n", *ida);
-#endif
            sp = schema;
            Id *kp = data->xattrs[-*ida];
            if (!kp)
              continue;
            num++;
            for (;*kp; kp += 2)
-             {
-#if 0
-               fprintf(stderr, "  %s:%d\n", id2str(data->repo->pool, data->keys[*kp].name), kp[1]);
-#endif
-               *sp++ = *kp;
-             }
+             *sp++ = *kp;
            *sp = 0;
            if (!schemaid)
              schemaid = repodata_schema2id(data, schema, 1);
@@ -2373,9 +2506,6 @@ repodata_serialize_key(Repodata *data, struct extdata *newincore,
                pool_debug(data->repo->pool, SAT_FATAL, "fixarray substructs with different schemas\n");
                exit(1);
              }
-#if 0
-           fprintf(stderr, "  schema %d\n", schemaid);
-#endif
          }
        if (!num)
          break;
@@ -2387,10 +2517,7 @@ repodata_serialize_key(Repodata *data, struct extdata *newincore,
            if (!kp)
              continue;
            for (;*kp; kp += 2)
-             {
-               repodata_serialize_key(data, newincore, newvincore,
-                                      schema, data->keys + *kp, kp[1]);
-             }
+             repodata_serialize_key(data, newincore, newvincore, schema, data->keys + *kp, kp[1]);
          }
        break;
       }
@@ -2416,10 +2543,7 @@ repodata_serialize_key(Repodata *data, struct extdata *newincore,
            data_addid(xd, schemaid);
            kp = data->xattrs[-*ida];
            for (;*kp; kp += 2)
-             {
-               repodata_serialize_key(data, newincore, newvincore,
-                                      schema, data->keys + *kp, kp[1]);
-             }
+             repodata_serialize_key(data, newincore, newvincore, schema, data->keys + *kp, kp[1]);
          }
        break;
       }
@@ -2576,7 +2700,7 @@ fprintf(stderr, "schemadata %p\n", data->schemadata);
            }
          key = data->keys + *keyp;
 #if 0
-         fprintf(stderr, "internalize %d(%d):%s:%s\n", entry, entry + data->start, id2str(data->repo->pool, key->name), id2str(data->repo->pool, key->type));
+         fprintf(stderr, "internalize %d(%d):%s:%s\n", entry, entry + data->start, pool_id2str(data->repo->pool, key->name), pool_id2str(data->repo->pool, key->type));
 #endif
          ndp = dp;
          if (oldcount)
@@ -2654,7 +2778,8 @@ repodata_load_stub(Repodata *data)
 {
   Repo *repo = data->repo;
   Pool *pool = repo->pool;
-  int r;
+  int r, i;
+  struct _Pool_tmpspace oldtmpspace;
 
   if (!pool->loadcallback)
     {
@@ -2662,9 +2787,19 @@ repodata_load_stub(Repodata *data)
       return;
     }
   data->state = REPODATA_LOADING;
+
+  /* save tmp space */
+  oldtmpspace = pool->tmpspace;
+  memset(&pool->tmpspace, 0, sizeof(pool->tmpspace));
+
   r = pool->loadcallback(pool, data, pool->loadcallbackdata);
-  if (!r)
-    data->state = REPODATA_ERROR;
+
+  /* restore tmp space */
+  for (i = 0; i < POOL_TMPSPACEBUF; i++)
+    sat_free(pool->tmpspace.buf[i]);
+  pool->tmpspace = oldtmpspace;
+
+  data->state = r ? REPODATA_AVAILABLE : REPODATA_ERROR;
 }
 
 void
@@ -2677,10 +2812,19 @@ repodata_create_stubs(Repodata *data)
   Dataiterator di;
   Id xkeyname = 0;
   int i, cnt = 0;
+  int repodataid;
+  int datastart, dataend;
 
+  repodataid = data - repo->repodata;
+  datastart = data->start;
+  dataend = data->end;
   dataiterator_init(&di, pool, repo, SOLVID_META, REPOSITORY_EXTERNAL, 0, 0);
   while (dataiterator_step(&di))
-    cnt++;
+    {
+      if (di.data - repo->repodata != repodataid)
+       continue;
+      cnt++;
+    }
   dataiterator_free(&di);
   if (!cnt)
     return;
@@ -2688,11 +2832,8 @@ repodata_create_stubs(Repodata *data)
   for (i = 0; i < cnt; i++)
     {
       sdata = repo_add_repodata(repo, 0);
-      if (data->end > data->start)
-       {
-         repodata_extend(sdata, data->start);
-         repodata_extend(sdata, data->end - 1);
-       }
+      if (dataend > datastart)
+        repodata_extend_block(sdata, datastart, dataend - datastart);
       stubdataids[i] = sdata - repo->repodata;
       sdata->state = REPODATA_STUB;
       sdata->loadcallback = repodata_load_stub;
@@ -2702,6 +2843,8 @@ repodata_create_stubs(Repodata *data)
   sdata = 0;
   while (dataiterator_step(&di))
     {
+      if (di.data - repo->repodata != repodataid)
+       continue;
       if (di.key->name == REPOSITORY_EXTERNAL && !di.nparents)
        {
          dataiterator_entersub(&di);
@@ -2729,7 +2872,7 @@ repodata_create_stubs(Repodata *data)
        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);
+         repodata_set_bin_checksum(sdata, SOLVID_META, di.key->name, di.key->type, (const unsigned char *)di.kv.str);
          break;
        case REPOKEY_TYPE_IDARRAY:
          repodata_add_idarray(sdata, SOLVID_META, di.key->name, di.kv.id);
@@ -2750,6 +2893,8 @@ repodata_create_stubs(Repodata *data)
               repodata_key2id(sdata, &xkey, 1);
               xkeyname = 0;
            }
+       default:
+         break;
        }
     }
   dataiterator_free(&di);