+static void
+repodata_load_stub(Repodata *data)
+{
+ Repo *repo = data->repo;
+ Pool *pool = repo->pool;
+ int r, i;
+ struct _Pool_tmpspace oldtmpspace;
+
+ if (!pool->loadcallback)
+ {
+ data->state = REPODATA_ERROR;
+ 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);
+
+ /* 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
+repodata_create_stubs(Repodata *data)
+{
+ Repo *repo = data->repo;
+ Pool *pool = repo->pool;
+ Repodata *sdata;
+ int *stubdataids;
+ 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))
+ {
+ if (di.data - repo->repodata != repodataid)
+ continue;
+ cnt++;
+ }
+ dataiterator_free(&di);
+ if (!cnt)
+ return;
+ stubdataids = sat_calloc(cnt, sizeof(*stubdataids));
+ for (i = 0; i < cnt; i++)
+ {
+ sdata = repo_add_repodata(repo, 0);
+ if (dataend > datastart)
+ repodata_extend_block(sdata, datastart, dataend - datastart);
+ stubdataids[i] = sdata - repo->repodata;
+ sdata->state = REPODATA_STUB;
+ sdata->loadcallback = repodata_load_stub;
+ }
+ i = 0;
+ dataiterator_init(&di, pool, repo, SOLVID_META, REPOSITORY_EXTERNAL, 0, 0);
+ sdata = 0;
+ while (dataiterator_step(&di))
+ {
+ if (di.data - repo->repodata != repodataid)
+ continue;
+ if (di.key->name == REPOSITORY_EXTERNAL && !di.nparents)
+ {
+ dataiterator_entersub(&di);
+ sdata = repo->repodata + stubdataids[i++];
+ xkeyname = 0;
+ continue;
+ }
+ switch (di.key->type)
+ {
+ 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_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);
+ if (di.key->name == REPOSITORY_KEYS)
+ {
+ 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;
+ }
+ default:
+ break;
+ }
+ }
+ dataiterator_free(&di);
+ for (i = 0; i < cnt; i++)
+ repodata_internalize(repo->repodata + stubdataids[i]);
+ sat_free(stubdataids);
+}
+