KeyValue kv;
Pool *pool = repo->pool;
Repodata *data;
- int i, j, flags;
+ int i, flags;
Solvable *s;
kv.parent = 0;
return;
}
else if (p < 0)
- /* The callback only supports solvables, so we can't iterate over the
- extra things. */
+ /* The callback only supports solvables, so we can't iterate over the extra things. */
return;
flags = md->flags;
if (!(flags & SEARCH_NO_STORAGE_SOLVABLE))
}
}
+ if (keyname)
+ {
+ if (keyname == SOLVABLE_FILELIST)
+ data = repo_lookup_filelist_repodata(repo, p, &md->matcher);
+ else
+ data = repo_lookup_repodata_opt(repo, p, keyname);
+ if (data)
+ repodata_search(data, p, keyname, md->flags, repo_matchvalue, md);
+ return;
+ }
+
FOR_REPODATAS(repo, i, data)
{
if (p < data->start || p >= data->end)
continue;
- if (keyname && !repodata_precheck_keyname(data, keyname))
- continue;
- if (keyname == SOLVABLE_FILELIST && !(md->flags & SEARCH_COMPLETE_FILELIST))
- {
- /* do not search filelist extensions */
- if (data->state != REPODATA_AVAILABLE)
- continue;
- for (j = 1; j < data->nkeys; j++)
- if (data->keys[j].name != REPOSITORY_SOLVABLES && data->keys[j].name != SOLVABLE_FILELIST)
- break;
- if (j == data->nkeys)
- continue;
- }
- if (data->state == REPODATA_STUB)
- {
- if (keyname)
- {
- for (j = 1; j < data->nkeys; j++)
- if (keyname == data->keys[j].name)
- break;
- if (j == data->nkeys)
- continue;
- }
- /* load it */
- if (data->loadcallback)
- data->loadcallback(data);
- else
- data->state = REPODATA_ERROR;
- }
- if (data->state == REPODATA_ERROR)
- continue;
repodata_search(data, p, keyname, md->flags, repo_matchvalue, md);
if (md->stop > SEARCH_NEXT_KEY)
break;
datamatcher_free(&md.matcher);
}
+Repodata *
+repo_lookup_repodata(Repo *repo, Id entry, Id keyname)
+{
+ Repodata *data;
+ int rdid;
+ Id type;
+
+ if (entry == SOLVID_POS)
+ {
+ Pool *pool = repo->pool;
+ return pool->pos.repo == repo && pool->pos.repodataid ? pool->pos.repo->repodata + pool->pos.repodataid : 0;
+ }
+ for (rdid = repo->nrepodata - 1, data = repo->repodata + rdid; rdid > 0; rdid--, data--)
+ {
+ if (entry != SOLVID_META && (entry < data->start || entry >= data->end))
+ continue;
+ if (!repodata_precheck_keyname(data, keyname))
+ continue;
+ if ((type = repodata_lookup_type(data, entry, keyname)) != 0)
+ return type == REPOKEY_TYPE_DELETED ? 0 : data;
+ }
+ return 0;
+}
+
+/* like repo_lookup_repodata, but may return a repodata that contains no match instead of NULL */
+Repodata *
+repo_lookup_repodata_opt(Repo *repo, Id entry, Id keyname)
+{
+ Repodata *data, *found = 0;
+ int rdid;
+ Id type;
+
+ if (entry == SOLVID_POS)
+ {
+ Pool *pool = repo->pool;
+ return pool->pos.repo == repo && pool->pos.repodataid ? pool->pos.repo->repodata + pool->pos.repodataid : 0;
+ }
+ for (rdid = repo->nrepodata - 1, data = repo->repodata + rdid; rdid > 0; rdid--, data--)
+ {
+ if (entry != SOLVID_META && (entry < data->start || entry >= data->end))
+ continue;
+ if (!repodata_precheck_keyname(data, keyname))
+ continue;
+ if (found && (type = repodata_lookup_type(found, entry, keyname)) != 0)
+ return type == REPOKEY_TYPE_DELETED ? 0 : found;
+ found = data;
+ }
+ return found;
+}
+
+Repodata *
+repo_lookup_filelist_repodata(Repo *repo, Id entry, Datamatcher *matcher)
+{
+ Repodata *data;
+ int haveextension;
+ int rdid;
+ Id type;
+
+ if (entry <= 0 || !matcher || !matcher->match || ((matcher->flags & (SEARCH_STRINGMASK|SEARCH_NOCASE)) != SEARCH_STRING
+ && (matcher->flags & (SEARCH_STRINGMASK|SEARCH_NOCASE)) != SEARCH_GLOB))
+ return repo_lookup_repodata_opt(repo, entry, SOLVABLE_FILELIST); /* cannot use filtered filelist */
+
+ haveextension = 0;
+ for (rdid = repo->nrepodata - 1, data = repo->repodata + rdid; rdid > 0; rdid--, data--)
+ {
+ if (entry < data->start || entry >= data->end)
+ continue;
+ if (data->filelisttype == REPODATA_FILELIST_FILTERED)
+ {
+ if (data->state != REPODATA_AVAILABLE)
+ {
+ if (data->state != REPODATA_STUB)
+ continue;
+ repodata_load(data);
+ if (data->state != REPODATA_AVAILABLE || entry < data->start || entry >= data->end)
+ continue;
+ }
+ /* does this contain any data about the solvable we're looking for? */
+ if (!data->incoreoffset[entry - data->start])
+ continue; /* no, ignore */
+ if (haveextension && repodata_filelistfilter_matches(data, matcher->match))
+ return data;
+ break; /* fall back to normal code */
+ }
+ if (!repodata_has_keyname(data, SOLVABLE_FILELIST))
+ continue;
+ if (data->filelisttype == REPODATA_FILELIST_EXTENSION)
+ {
+ haveextension++;
+ continue;
+ }
+ if ((type = repodata_lookup_type(data, entry, SOLVABLE_FILELIST)) != 0)
+ {
+ if (haveextension)
+ break; /* need to look in extension */
+ return type == REPOKEY_TYPE_DELETED ? 0 : data;
+ }
+ }
+ /* cannot use filtered filelist */
+ return repo_lookup_repodata_opt(repo, entry, SOLVABLE_FILELIST);
+}
+
const char *
repo_lookup_str(Repo *repo, Id entry, Id keyname)
{
Pool *pool = repo->pool;
Repodata *data;
- int i;
- const char *str;
if (entry >= 0)
{
return pool_id2str(pool, pool->solvables[entry].vendor);
}
}
- else if (entry == SOLVID_POS && pool->pos.repo == repo && pool->pos.repodataid)
- return repodata_lookup_str(pool->pos.repo->repodata + pool->pos.repodataid, entry, keyname);
- FOR_REPODATAS(repo, i, data)
- {
- if (entry != SOLVID_META && (entry < data->start || entry >= data->end))
- continue;
- if (!repodata_precheck_keyname(data, keyname))
- continue;
- str = repodata_lookup_str(data, entry, keyname);
- if (str)
- return str;
- if (repodata_lookup_type(data, entry, keyname))
- return 0;
- }
- return 0;
+ data = repo_lookup_repodata_opt(repo, entry, keyname);
+ return data ? repodata_lookup_str(data, entry, keyname) : 0;
}
unsigned long long
repo_lookup_num(Repo *repo, Id entry, Id keyname, unsigned long long notfound)
{
- Pool *pool = repo->pool;
Repodata *data;
- int i;
unsigned long long value;
if (entry >= 0)
return notfound;
}
}
- else if (entry == SOLVID_POS && pool->pos.repo == repo && pool->pos.repodataid)
- return repodata_lookup_num(pool->pos.repo->repodata + pool->pos.repodataid, entry, keyname, &value) ? value : notfound;
- FOR_REPODATAS(repo, i, data)
- {
- if (entry != SOLVID_META && (entry < data->start || entry >= data->end))
- continue;
- if (!repodata_precheck_keyname(data, keyname))
- continue;
- if (repodata_lookup_num(data, entry, keyname, &value))
- return value;
- if (repodata_lookup_type(data, entry, keyname))
- return notfound;
- }
- return notfound;
+ data = repo_lookup_repodata_opt(repo, entry, keyname);
+ return data && repodata_lookup_num(data, entry, keyname, &value) ? value : notfound;
}
Id
repo_lookup_id(Repo *repo, Id entry, Id keyname)
{
- Pool *pool = repo->pool;
Repodata *data;
- int i;
Id id;
if (entry >= 0)
return repo->pool->solvables[entry].vendor;
}
}
- else if (entry == SOLVID_POS && pool->pos.repo == repo && pool->pos.repodataid)
- {
- Repodata *data = pool->pos.repo->repodata + pool->pos.repodataid;
- Id id = repodata_lookup_id(data, entry, keyname);
- return data->localpool ? repodata_globalize_id(data, id, 1) : id;
- }
- FOR_REPODATAS(repo, i, data)
- {
- if (entry != SOLVID_META && (entry < data->start || entry >= data->end))
- continue;
- if (!repodata_precheck_keyname(data, keyname))
- continue;
- id = repodata_lookup_id(data, entry, keyname);
- if (id)
- return data->localpool ? repodata_globalize_id(data, id, 1) : id;
- if (repodata_lookup_type(data, entry, keyname))
- return 0;
- }
+ data = repo_lookup_repodata_opt(repo, entry, keyname);
+ if (data && (id = repodata_lookup_id(data, entry, keyname)) != 0)
+ return data->localpool ? repodata_globalize_id(data, id, 1) : id;
return 0;
}
int
repo_lookup_idarray(Repo *repo, Id entry, Id keyname, Queue *q)
{
- Pool *pool = repo->pool;
Repodata *data;
int i;
if (entry >= 0)
return lookup_idarray_solvable(repo, repo->pool->solvables[entry].enhances, q);
}
}
- else if (entry == SOLVID_POS && pool->pos.repo == repo && pool->pos.repodataid)
+ data = repo_lookup_repodata_opt(repo, entry, keyname);
+ if (data && repodata_lookup_idarray(data, entry, keyname, q))
{
- Repodata *data = pool->pos.repo->repodata + pool->pos.repodataid;
- if (repodata_lookup_idarray(data, entry, keyname, q))
+ if (data->localpool)
{
- if (data->localpool)
- {
- for (i = 0; i < q->count; i++)
- q->elements[i] = repodata_globalize_id(data, q->elements[i], 1);
- }
- return 1;
- }
- }
- FOR_REPODATAS(repo, i, data)
- {
- if (entry != SOLVID_META && (entry < data->start || entry >= data->end))
- continue;
- if (!repodata_precheck_keyname(data, keyname))
- continue;
- if (repodata_lookup_idarray(data, entry, keyname, q))
- {
- if (data->localpool)
- {
- for (i = 0; i < q->count; i++)
- q->elements[i] = repodata_globalize_id(data, q->elements[i], 1);
- }
- return 1;
+ for (i = 0; i < q->count; i++)
+ q->elements[i] = repodata_globalize_id(data, q->elements[i], 1);
}
- if (repodata_lookup_type(data, entry, keyname))
- break;
+ return 1;
}
queue_empty(q);
return 0;
const unsigned char *
repo_lookup_bin_checksum(Repo *repo, Id entry, Id keyname, Id *typep)
{
- Pool *pool = repo->pool;
- Repodata *data;
- int i;
const unsigned char *chk;
-
- if (entry == SOLVID_POS && pool->pos.repo == repo && pool->pos.repodataid)
- return repodata_lookup_bin_checksum(pool->pos.repo->repodata + pool->pos.repodataid, entry, keyname, typep);
- FOR_REPODATAS(repo, i, data)
- {
- if (entry != SOLVID_META && (entry < data->start || entry >= data->end))
- continue;
- if (!repodata_precheck_keyname(data, keyname))
- continue;
- chk = repodata_lookup_bin_checksum(data, entry, keyname, typep);
- if (chk)
- return chk;
- if (repodata_lookup_type(data, entry, keyname))
- return 0;
- }
+ Repodata *data = repo_lookup_repodata_opt(repo, entry, keyname);
+ if (data && (chk = repodata_lookup_bin_checksum(data, entry, keyname, typep)) != 0)
+ return chk;
*typep = 0;
return 0;
}
int
repo_lookup_void(Repo *repo, Id entry, Id keyname)
{
- Pool *pool = repo->pool;
- Repodata *data;
- int i;
- Id type;
-
- if (entry == SOLVID_POS && pool->pos.repo == repo && pool->pos.repodataid)
- return repodata_lookup_void(pool->pos.repo->repodata + pool->pos.repodataid, entry, keyname);
- FOR_REPODATAS(repo, i, data)
- {
- if (entry != SOLVID_META && (entry < data->start || entry >= data->end))
- continue;
- if (!repodata_precheck_keyname(data, keyname))
- continue;
- type = repodata_lookup_type(data, entry, keyname);
- if (type)
- return type == REPOKEY_TYPE_VOID;
- }
+ Repodata *data = repo_lookup_repodata_opt(repo, entry, keyname);
+ if (data)
+ return repodata_lookup_void(data, entry, keyname);
return 0;
}
Id
repo_lookup_type(Repo *repo, Id entry, Id keyname)
{
- Pool *pool = repo->pool;
- Repodata *data;
- int i;
Id type;
-
- if (entry == SOLVID_POS && pool->pos.repo == repo && pool->pos.repodataid)
- return repodata_lookup_type(pool->pos.repo->repodata + pool->pos.repodataid, entry, keyname);
- FOR_REPODATAS(repo, i, data)
- {
- if (entry != SOLVID_META && (entry < data->start || entry >= data->end))
- continue;
- if (!repodata_precheck_keyname(data, keyname))
- continue;
- type = repodata_lookup_type(data, entry, keyname);
- if (type)
- return type == REPOKEY_TYPE_DELETED ? 0 : type;
- }
+ Repodata *data = repo_lookup_repodata_opt(repo, entry, keyname);
+ if (data && (type = repodata_lookup_type(data, entry, keyname)) != 0 && type != REPOKEY_TYPE_DELETED)
+ return type;
return 0;
}
const void *
repo_lookup_binary(Repo *repo, Id entry, Id keyname, int *lenp)
{
- Pool *pool = repo->pool;
- Repodata *data;
- int i;
const void *bin;
-
- if (entry == SOLVID_POS && pool->pos.repo == repo && pool->pos.repodataid)
- return repodata_lookup_binary(pool->pos.repo->repodata + pool->pos.repodataid, entry, keyname, lenp);
- FOR_REPODATAS(repo, i, data)
- {
- if (entry != SOLVID_META && (entry < data->start || entry >= data->end))
- continue;
- if (!repodata_precheck_keyname(data, keyname))
- continue;
- bin = repodata_lookup_binary(data, entry, keyname, lenp);
- if (bin)
- return bin;
- }
+ Repodata *data = repo_lookup_repodata_opt(repo, entry, keyname);
+ if (data && (bin = repodata_lookup_binary(data, entry, keyname, lenp)) != 0)
+ return bin;
*lenp = 0;
return 0;
}
int
repodata_lookup_void(Repodata *data, Id solvid, Id keyname)
{
- Id schema;
- Id *keyp;
- unsigned char *dp;
-
- if (!maybe_load_repodata(data, keyname))
- return 0;
- dp = solvid2data(data, solvid, &schema);
- if (!dp)
- return 0;
- /* can't use find_key_data as we need to test the type */
- for (keyp = data->schemadata + data->schemata[schema]; *keyp; keyp++)
- if (data->keys[*keyp].name == keyname && data->keys[*keyp].type == REPOKEY_TYPE_VOID)
- return 1;
- return 0;
+ return repodata_lookup_type(data, solvid, keyname) == REPOKEY_TYPE_VOID ? 1 : 0;
}
const unsigned char *
queue_empty(q);
dp = find_key_data(data, solvid, keyname, &key);
- if (!dp)
- return 0;
- if (key->type != REPOKEY_TYPE_IDARRAY)
+ if (!dp || key->type != REPOKEY_TYPE_IDARRAY)
return 0;
for (;;)
{
return dp;
}
-static inline int
-is_filelist_extension(Repodata *data)
-{
- int j;
- if (!repodata_precheck_keyname(data, SOLVABLE_FILELIST))
- return 0;
- for (j = 1; j < data->nkeys; j++)
- if (data->keys[j].name == SOLVABLE_FILELIST)
- break;
- if (j == data->nkeys)
- return 0;
- if (data->state != REPODATA_AVAILABLE)
- return 1;
- for (j = 1; j < data->nkeys; j++)
- if (data->keys[j].name != REPOSITORY_SOLVABLES && data->keys[j].name != SOLVABLE_FILELIST)
- return 0;
- return 1;
-}
-
-static int
-dataiterator_filelistcheck(Dataiterator *di)
-{
- int j;
- int needcomplete = 0;
- Repodata *data = di->data;
-
- if ((di->flags & SEARCH_COMPLETE_FILELIST) != 0)
- 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(data, di->matcher.match))
- needcomplete = 1;
- if (data->state != REPODATA_AVAILABLE)
- return needcomplete ? 1 : 0;
- if (!needcomplete)
- {
- /* we don't need the complete filelist, so ignore all stubs */
- if (data->repo->nrepodata == 2)
- return 1;
- for (j = 1; j < data->nkeys; j++)
- if (data->keys[j].name != REPOSITORY_SOLVABLES && data->keys[j].name != SOLVABLE_FILELIST)
- return 1;
- return 0;
- }
- else
- {
- /* we need the complete filelist. check if we habe a filtered filelist and there's
- * a extension with the complete filelist later on */
- for (j = 1; j < data->nkeys; j++)
- if (data->keys[j].name == SOLVABLE_FILELIST)
- break;
- if (j == data->nkeys)
- return 0; /* does not have filelist */
- for (j = 1; j < data->nkeys; j++)
- if (data->keys[j].name != REPOSITORY_SOLVABLES && data->keys[j].name != SOLVABLE_FILELIST)
- break;
- if (j == data->nkeys)
- return 1; /* this is the externsion */
- while (data - data->repo->repodata + 1 < data->repo->nrepodata)
- {
- data++;
- if (is_filelist_extension(data))
- return 0;
- }
- return 1;
- }
-}
-
int
dataiterator_step(Dataiterator *di)
{
Id schema;
- if (di->state == di_nextattr && di->key->storage == KEY_STORAGE_VERTICAL_OFFSET && di->vert_ddp && di->vert_storestate != di->data->storestate) {
- unsigned int ddpoff = di->ddp - di->vert_ddp;
- di->vert_off += ddpoff;
- di->vert_len -= ddpoff;
- di->ddp = di->vert_ddp = get_vertical_data(di->data, di->key, di->vert_off, di->vert_len);
- di->vert_storestate = di->data->storestate;
- if (!di->ddp)
- di->state = di_nextkey;
- }
+ if (di->state == di_nextattr && di->key->storage == KEY_STORAGE_VERTICAL_OFFSET && di->vert_ddp && di->vert_storestate != di->data->storestate)
+ {
+ unsigned int ddpoff = di->ddp - di->vert_ddp;
+ di->vert_off += ddpoff;
+ di->vert_len -= ddpoff;
+ di->ddp = di->vert_ddp = get_vertical_data(di->data, di->key, di->vert_off, di->vert_len);
+ di->vert_storestate = di->data->storestate;
+ if (!di->ddp)
+ di->state = di_nextkey;
+ }
for (;;)
{
switch (di->state)
if (di->solvid > 0 && !(di->flags & SEARCH_NO_STORAGE_SOLVABLE) && (!di->keyname || (di->keyname >= SOLVABLE_NAME && di->keyname <= RPM_RPMDBID)) && di->nparents - di->rootlevel == di->nkeynames)
{
extern Repokey repo_solvablekeys[RPM_RPMDBID - SOLVABLE_NAME + 1];
-
di->key = repo_solvablekeys + (di->keyname ? di->keyname - SOLVABLE_NAME : 0);
di->data = 0;
goto di_entersolvablekey;
}
+ if (di->keyname)
+ {
+ di->data = di->keyname == SOLVABLE_FILELIST ? repo_lookup_filelist_repodata(di->repo, di->solvid, &di->matcher) : repo_lookup_repodata_opt(di->repo, di->solvid, di->keyname);
+ if (!di->data)
+ goto di_nextsolvable;
+ di->repodataid = di->data - di->repo->repodata;
+ }
}
/* FALLTHROUGH */
goto di_nextsolvable;
di->data = di->repo->repodata + di->repodataid;
}
- if (di->repodataid && 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);
case di_nextattr:
di->kv.entry++;
di->ddp = data_fetch(di->ddp, &di->kv, di->key);
- if (di->kv.eof)
- di->state = di_nextkey;
- else
- di->state = di_nextattr;
+ di->state = di->kv.eof ? di_nextkey : di_nextattr;
break;
case di_nextkey: di_nextkey:
/* FALLTHROUGH */
case di_nextrepodata: di_nextrepodata:
- if (di->repodataid && ++di->repodataid < di->repo->nrepodata)
+ if (!di->keyname && di->repodataid && ++di->repodataid < di->repo->nrepodata)
goto di_enterrepodata;
/* FALLTHROUGH */
/* special solvable attr handling follows */
case di_nextsolvablekey: di_nextsolvablekey:
- if (di->keyname || di->key->name == RPM_RPMDBID)
+ if (di->keyname)
+ goto di_nextsolvable;
+ if (di->key->name == RPM_RPMDBID) /* reached end of list? */
goto di_enterrepodata;
di->key++;
/* FALLTHROUGH */
}
+ /* we have a potential match */
if (di->matcher.match)
{
const char *str;
if (di->keyname == SOLVABLE_FILELIST && di->key->type == REPOKEY_TYPE_DIRSTRARRAY && (di->matcher.flags & SEARCH_FILES) != 0)
if (!datamatcher_checkbasename(&di->matcher, di->kv.str))
continue;
+ /* now stringify so that we can do the matching */
if (!(str = repodata_stringify(di->pool, di->data, di->key, &di->kv, di->flags)))
{
if (di->keyname && (di->key->type == REPOKEY_TYPE_FIXARRAY || di->key->type == REPOKEY_TYPE_FLEXARRAY))
}
else
{
+ /* stringify filelist if requested */
if (di->keyname == SOLVABLE_FILELIST && di->key->type == REPOKEY_TYPE_DIRSTRARRAY && (di->flags & SEARCH_FILES) != 0)
repodata_stringify(di->pool, di->data, di->key, &di->kv, di->flags);
}