2 * Copyright (c) 2007, Novell Inc.
4 * This program is licensed under the BSD license, read LICENSE.BSD
5 * for further information
11 * Manage data coming from one repository
13 * a repository can contain multiple repodata entries, consisting of
14 * different sets of keys and different sets of solvables
29 #include "poolid_private.h"
37 extern unsigned int compress_buf (const unsigned char *in, unsigned int in_len,
38 unsigned char *out, unsigned int out_len);
39 extern unsigned int unchecked_decompress_buf (const unsigned char *in,
42 unsigned int out_len);
44 #define REPODATA_BLOCK 255
48 repodata_initdata(Repodata *data, Repo *repo, int localpool)
50 memset(data, 0, sizeof (*data));
52 data->localpool = localpool;
54 stringpool_init_empty(&data->spool);
55 /* dirpool_init(&data->dirpool); just zeros out again */
56 data->keys = sat_calloc(1, sizeof(Repokey));
58 data->schemata = sat_calloc(1, sizeof(Id));
59 data->schemadata = sat_calloc(1, sizeof(Id));
61 data->schemadatalen = 1;
62 repopagestore_init(&data->store);
66 repodata_freedata(Repodata *data)
72 sat_free(data->schemata);
73 sat_free(data->schemadata);
74 sat_free(data->schematahash);
76 stringpool_free(&data->spool);
77 dirpool_free(&data->dirpool);
79 sat_free(data->mainschemaoffsets);
80 sat_free(data->incoredata);
81 sat_free(data->incoreoffset);
82 sat_free(data->verticaloffset);
84 repopagestore_free(&data->store);
86 sat_free(data->vincore);
89 for (i = 0; i < data->end - data->start; i++)
90 sat_free(data->attrs[i]);
91 sat_free(data->attrs);
93 for (i = 0; i < data->nxattrs; i++)
94 sat_free(data->xattrs[i]);
95 sat_free(data->xattrs);
97 sat_free(data->attrdata);
98 sat_free(data->attriddata);
102 repodata_create(Repo *repo, int localpool)
107 repo->repodata = sat_realloc2(repo->repodata, repo->nrepodata, sizeof(*data));
108 data = repo->repodata + repo->nrepodata - 1;
109 repodata_initdata(data, repo, localpool);
114 repodata_free(Repodata *data)
116 Repo *repo = data->repo;
117 int i = data - repo->repodata;
118 repodata_freedata(data);
119 if (i < repo->nrepodata - 1)
120 memmove(repo->repodata + i, repo->repodata + i + 1, (repo->nrepodata - 1 - i) * sizeof(Repodata));
125 repodata_empty(Repodata *data, int localpool)
127 void (*loadcallback)(Repodata *) = data->loadcallback;
128 int state = data->state;
129 repodata_freedata(data);
130 repodata_initdata(data, data->repo, localpool);
132 data->loadcallback = loadcallback;
136 /***************************************************************
137 * key pool management
140 /* this is not so time critical that we need a hash, so we do a simple
143 repodata_key2id(Repodata *data, Repokey *key, int create)
147 for (keyid = 1; keyid < data->nkeys; keyid++)
148 if (data->keys[keyid].name == key->name && data->keys[keyid].type == key->type)
150 if ((key->type == REPOKEY_TYPE_CONSTANT || key->type == REPOKEY_TYPE_CONSTANTID) && key->size != data->keys[keyid].size)
154 if (keyid == data->nkeys)
158 /* allocate new key */
159 data->keys = sat_realloc2(data->keys, data->nkeys + 1, sizeof(Repokey));
160 data->keys[data->nkeys++] = *key;
161 if (data->verticaloffset)
163 data->verticaloffset = sat_realloc2(data->verticaloffset, data->nkeys, sizeof(Id));
164 data->verticaloffset[data->nkeys - 1] = 0;
166 data->keybits[(key->name >> 3) & (sizeof(data->keybits) - 1)] |= 1 << (key->name & 7);
172 /***************************************************************
173 * schema pool management
176 #define SCHEMATA_BLOCK 31
177 #define SCHEMATADATA_BLOCK 255
180 repodata_schema2id(Repodata *data, Id *schema, int create)
187 return 0; /* XXX: allow empty schema? */
188 if ((schematahash = data->schematahash) == 0)
190 data->schematahash = schematahash = sat_calloc(256, sizeof(Id));
191 for (i = 1; i < data->nschemata; i++)
193 for (sp = data->schemadata + data->schemata[i], h = 0; *sp; len++)
198 data->schemadata = sat_extend_resize(data->schemadata, data->schemadatalen, sizeof(Id), SCHEMATADATA_BLOCK);
199 data->schemata = sat_extend_resize(data->schemata, data->nschemata, sizeof(Id), SCHEMATA_BLOCK);
202 for (sp = schema, len = 0, h = 0; *sp; len++)
207 cid = schematahash[h];
210 if (!memcmp(data->schemadata + data->schemata[cid], schema, len * sizeof(Id)))
212 /* cache conflict, do a slow search */
213 for (cid = 1; cid < data->nschemata; cid++)
214 if (!memcmp(data->schemadata + data->schemata[cid], schema, len * sizeof(Id)))
220 data->schemadata = sat_extend(data->schemadata, data->schemadatalen, len, sizeof(Id), SCHEMATADATA_BLOCK);
221 data->schemata = sat_extend(data->schemata, data->nschemata, 1, sizeof(Id), SCHEMATA_BLOCK);
223 memcpy(data->schemadata + data->schemadatalen, schema, len * sizeof(Id));
224 data->schemata[data->nschemata] = data->schemadatalen;
225 data->schemadatalen += len;
226 schematahash[h] = data->nschemata;
228 fprintf(stderr, "schema2id: new schema\n");
230 return data->nschemata++;
234 repodata_free_schemahash(Repodata *data)
236 data->schematahash = sat_free(data->schematahash);
238 data->schemata = sat_realloc2(data->schemata, data->nschemata, sizeof(Id));
239 data->schemadata = sat_realloc2(data->schemadata, data->schemadatalen, sizeof(Id));
243 /***************************************************************
244 * dir pool management
247 #ifndef HAVE_STRCHRNUL
248 static inline const char *strchrnul(const char *str, char x)
250 const char *p = strchr(str, x);
251 return p ? p : str + strlen(str);
256 repodata_str2dir(Repodata *data, const char *dir, int create)
262 while (*dir == '/' && dir[1] == '/')
264 if (*dir == '/' && !dir[1])
266 if (data->dirpool.ndirs)
268 return dirpool_add_dir(&data->dirpool, 0, 1, create);
272 dire = strchrnul(dir, '/');
274 id = stringpool_strn2id(&data->spool, dir, dire - dir, create);
276 id = strn2id(data->repo->pool, dir, dire - dir, create);
279 parent = dirpool_add_dir(&data->dirpool, parent, id, create);
292 repodata_dir2str(Repodata *data, Id did, const char *suf)
294 Pool *pool = data->repo->pool;
301 return suf ? suf : "";
305 comp = dirpool_compid(&data->dirpool, parent);
306 comps = stringpool_id2str(data->localpool ? &data->spool : &pool->ss, comp);
308 parent = dirpool_parent(&data->dirpool, parent);
313 l += strlen(suf) + 1;
314 p = pool_alloctmpspace(pool, l + 1) + l;
325 comp = dirpool_compid(&data->dirpool, parent);
326 comps = stringpool_id2str(data->localpool ? &data->spool : &pool->ss, comp);
329 strncpy(p, comps, l);
330 parent = dirpool_parent(&data->dirpool, parent);
338 /***************************************************************
342 static inline unsigned char *
343 data_skip_schema(Repodata *data, unsigned char *dp, Id schema)
345 Id *keyp = data->schemadata + data->schemata[schema];
346 for (; *keyp; keyp++)
347 dp = data_skip_key(data, dp, data->keys + *keyp);
352 data_skip_key(Repodata *data, unsigned char *dp, Repokey *key)
354 int nentries, schema;
357 case REPOKEY_TYPE_FIXARRAY:
358 dp = data_read_id(dp, &nentries);
361 dp = data_read_id(dp, &schema);
363 dp = data_skip_schema(data, dp, schema);
365 case REPOKEY_TYPE_FLEXARRAY:
366 dp = data_read_id(dp, &nentries);
369 dp = data_read_id(dp, &schema);
370 dp = data_skip_schema(data, dp, schema);
374 if (key->storage == KEY_STORAGE_INCORE)
375 dp = data_skip(dp, key->type);
376 else if (key->storage == KEY_STORAGE_VERTICAL_OFFSET)
378 dp = data_skip(dp, REPOKEY_TYPE_ID);
379 dp = data_skip(dp, REPOKEY_TYPE_ID);
385 static unsigned char *
386 forward_to_key(Repodata *data, Id keyid, Id *keyp, unsigned char *dp)
392 if (data->mainschemaoffsets && dp == data->incoredata + data->mainschemaoffsets[0] && keyp == data->schemadata + data->schemata[data->mainschema])
395 for (i = 0; (k = *keyp++) != 0; i++)
397 return data->incoredata + data->mainschemaoffsets[i];
400 while ((k = *keyp++) != 0)
404 if (data->keys[k].storage == KEY_STORAGE_VERTICAL_OFFSET)
406 dp = data_skip(dp, REPOKEY_TYPE_ID); /* skip offset */
407 dp = data_skip(dp, REPOKEY_TYPE_ID); /* skip length */
410 if (data->keys[k].storage != KEY_STORAGE_INCORE)
412 dp = data_skip_key(data, dp, data->keys + k);
417 static unsigned char *
418 get_vertical_data(Repodata *data, Repokey *key, Id off, Id len)
423 if (off >= data->lastverticaloffset)
425 off -= data->lastverticaloffset;
426 if (off + len > data->vincorelen)
428 return data->vincore + off;
430 if (off + len > key->size)
432 /* we now have the offset, go into vertical */
433 off += data->verticaloffset[key - data->keys];
434 /* fprintf(stderr, "key %d page %d\n", key->name, off / BLOB_PAGESIZE); */
435 dp = repopagestore_load_page_range(&data->store, off / BLOB_PAGESIZE, (off + len - 1) / BLOB_PAGESIZE);
437 dp += off % BLOB_PAGESIZE;
441 static inline unsigned char *
442 get_data(Repodata *data, Repokey *key, unsigned char **dpp, int advance)
444 unsigned char *dp = *dpp;
448 if (key->storage == KEY_STORAGE_INCORE)
451 *dpp = data_skip_key(data, dp, key);
454 else if (key->storage == KEY_STORAGE_VERTICAL_OFFSET)
457 dp = data_read_id(dp, &off);
458 dp = data_read_id(dp, &len);
461 return get_vertical_data(data, key, off, len);
467 load_repodata(Repodata *data)
469 if (data->loadcallback)
471 data->loadcallback(data);
472 if (data->state == REPODATA_AVAILABLE)
475 data->state = REPODATA_ERROR;
480 maybe_load_repodata(Repodata *data, Id keyname)
482 if (keyname && !repodata_precheck_keyname(data, keyname))
483 return 0; /* do not bother... */
490 for (i = 0; i < data->nkeys; i++)
491 if (keyname == data->keys[i].name)
493 if (i == data->nkeys)
496 return load_repodata(data);
499 case REPODATA_AVAILABLE:
500 case REPODATA_LOADING:
503 data->state = REPODATA_ERROR;
508 static inline unsigned char *
509 solvid2data(Repodata *data, Id solvid, Id *schemap)
511 unsigned char *dp = data->incoredata;
514 if (solvid == SOLVID_META) /* META */
516 else if (solvid == SOLVID_POS) /* META */
518 Pool *pool = data->repo->pool;
519 if (data->repo != pool->pos.repo)
521 if (data != data->repo->repodata + pool->pos.repodataid)
523 *schemap = pool->pos.schema;
524 return data->incoredata + pool->pos.dp;
528 if (solvid < data->start || solvid >= data->end)
530 dp += data->incoreoffset[solvid - data->start];
532 return data_read_id(dp, schemap);
535 /************************************************************************
539 static inline unsigned char *
540 find_key_data(Repodata *data, Id solvid, Id keyname, Repokey **keypp)
543 Id schema, *keyp, *kp;
546 if (!maybe_load_repodata(data, keyname))
548 dp = solvid2data(data, solvid, &schema);
551 keyp = data->schemadata + data->schemata[schema];
552 for (kp = keyp; *kp; kp++)
553 if (data->keys[*kp].name == keyname)
557 *keypp = key = data->keys + *kp;
558 if (key->type == REPOKEY_TYPE_DELETED)
560 if (key->type == REPOKEY_TYPE_VOID || key->type == REPOKEY_TYPE_CONSTANT || key->type == REPOKEY_TYPE_CONSTANTID)
561 return dp; /* no need to forward... */
562 dp = forward_to_key(data, *kp, keyp, dp);
565 return get_data(data, key, &dp, 0);
569 repodata_lookup_type(Repodata *data, Id solvid, Id keyname)
571 Id schema, *keyp, *kp;
572 if (!maybe_load_repodata(data, keyname))
574 if (!solvid2data(data, solvid, &schema))
576 keyp = data->schemadata + data->schemata[schema];
577 for (kp = keyp; *kp; kp++)
578 if (data->keys[*kp].name == keyname)
579 return data->keys[*kp].type;
584 repodata_lookup_id(Repodata *data, Id solvid, Id keyname)
590 dp = find_key_data(data, solvid, keyname, &key);
593 if (key->type == REPOKEY_TYPE_CONSTANTID)
595 if (key->type != REPOKEY_TYPE_ID)
597 dp = data_read_id(dp, &id);
602 repodata_lookup_str(Repodata *data, Id solvid, Id keyname)
608 dp = find_key_data(data, solvid, keyname, &key);
611 if (key->type == REPOKEY_TYPE_STR)
612 return (const char *)dp;
613 if (key->type == REPOKEY_TYPE_CONSTANTID)
615 else if (key->type == REPOKEY_TYPE_ID)
616 dp = data_read_id(dp, &id);
620 return stringpool_id2str(&data->spool, id);
621 return id2str(data->repo->pool, id);
625 repodata_lookup_num(Repodata *data, Id solvid, Id keyname, unsigned int *value)
632 dp = find_key_data(data, solvid, keyname, &key);
635 if (key->type == REPOKEY_TYPE_NUM
636 || key->type == REPOKEY_TYPE_U32
637 || key->type == REPOKEY_TYPE_CONSTANT)
639 dp = data_fetch(dp, &kv, key);
647 repodata_lookup_void(Repodata *data, Id solvid, Id keyname)
653 if (!maybe_load_repodata(data, keyname))
655 dp = solvid2data(data, solvid, &schema);
658 /* can't use find_key_data as we need to test the type */
659 for (keyp = data->schemadata + data->schemata[schema]; *keyp; keyp++)
660 if (data->keys[*keyp].name == keyname && data->keys[*keyp].type == REPOKEY_TYPE_VOID)
665 const unsigned char *
666 repodata_lookup_bin_checksum(Repodata *data, Id solvid, Id keyname, Id *typep)
671 dp = find_key_data(data, solvid, keyname, &key);
679 repodata_lookup_idarray(Repodata *data, Id solvid, Id keyname, Queue *q)
687 dp = find_key_data(data, solvid, keyname, &key);
690 if (key->type != REPOKEY_TYPE_IDARRAY && key->type != REPOKEY_TYPE_REL_IDARRAY)
694 dp = data_read_ideof(dp, &id, &eof);
703 repodata_globalize_id(Repodata *data, Id id, int create)
705 if (!id || !data || !data->localpool)
707 return str2id(data->repo->pool, stringpool_id2str(&data->spool, id), create);
711 repodata_localize_id(Repodata *data, Id id, int create)
713 if (!id || !data || !data->localpool)
715 return stringpool_str2id(&data->spool, id2str(data->repo->pool, id), create);
719 /************************************************************************
725 repodata_stringify(Pool *pool, Repodata *data, Repokey *key, KeyValue *kv, int flags)
729 case REPOKEY_TYPE_ID:
730 case REPOKEY_TYPE_CONSTANTID:
731 case REPOKEY_TYPE_IDARRAY:
732 if (data && data->localpool)
733 kv->str = stringpool_id2str(&data->spool, kv->id);
735 kv->str = id2str(pool, kv->id);
736 if ((flags & SEARCH_SKIP_KIND) != 0 && key->storage == KEY_STORAGE_SOLVABLE)
739 for (s = kv->str; *s >= 'a' && *s <= 'z'; s++)
741 if (*s == ':' && s > kv->str)
745 case REPOKEY_TYPE_STR:
747 case REPOKEY_TYPE_DIRSTRARRAY:
748 if (!(flags & SEARCH_FILES))
749 return 1; /* match just the basename */
750 /* Put the full filename into kv->str. */
751 kv->str = repodata_dir2str(data, kv->id, kv->str);
752 /* And to compensate for that put the "empty" directory into
753 kv->id, so that later calls to repodata_dir2str on this data
754 come up with the same filename again. */
757 case REPOKEY_TYPE_MD5:
758 case REPOKEY_TYPE_SHA1:
759 case REPOKEY_TYPE_SHA256:
760 if (!(flags & SEARCH_CHECKSUMS))
761 return 0; /* skip em */
762 kv->str = repodata_chk2str(data, key->type, (const unsigned char *)kv->str);
770 struct subschema_data {
776 /* search a specific repodata */
778 repodata_search(Repodata *data, Id solvid, Id keyname, int flags, int (*callback)(void *cbdata, Solvable *s, Repodata *data, Repokey *key, KeyValue *kv), void *cbdata)
782 Id keyid, *kp, *keyp;
783 unsigned char *dp, *ddp;
789 if (!maybe_load_repodata(data, keyname))
791 if (solvid == SOLVID_SUBSCHEMA)
793 struct subschema_data *subd = cbdata;
794 cbdata = subd->cbdata;
796 schema = subd->parent->id;
797 dp = (unsigned char *)subd->parent->str;
798 kv.parent = subd->parent;
803 dp = solvid2data(data, solvid, &schema);
806 s = data->repo->pool->solvables + solvid;
809 keyp = data->schemadata + data->schemata[schema];
812 /* search for a specific key */
813 for (kp = keyp; *kp; kp++)
814 if (data->keys[*kp].name == keyname)
818 dp = forward_to_key(data, *kp, keyp, dp);
824 while ((keyid = *keyp++) != 0)
827 key = data->keys + keyid;
828 ddp = get_data(data, key, &dp, *keyp ? 1 : 0);
830 if (key->type == REPOKEY_TYPE_DELETED)
832 if (key->type == REPOKEY_TYPE_FLEXARRAY || key->type == REPOKEY_TYPE_FIXARRAY)
834 struct subschema_data subd;
838 subd.cbdata = cbdata;
841 ddp = data_read_id(ddp, &nentries);
845 while (ddp && nentries > 0)
849 if (key->type == REPOKEY_TYPE_FLEXARRAY || !kv.entry)
850 ddp = data_read_id(ddp, &schema);
852 kv.str = (char *)ddp;
853 stop = callback(cbdata, s, data, key, &kv);
854 if (stop > SEARCH_NEXT_KEY)
856 if (stop && stop != SEARCH_ENTERSUB)
858 if ((flags & SEARCH_SUB) != 0 || stop == SEARCH_ENTERSUB)
859 repodata_search(data, SOLVID_SUBSCHEMA, 0, flags, callback, &subd);
860 ddp = data_skip_schema(data, ddp, schema);
863 if (!nentries && (flags & SEARCH_ARRAYSENTINEL) != 0)
867 kv.str = (char *)ddp;
868 stop = callback(cbdata, s, data, key, &kv);
869 if (stop > SEARCH_NEXT_KEY)
879 ddp = data_fetch(ddp, &kv, key);
882 stop = callback(cbdata, s, data, key, &kv);
885 while (!kv.eof && !stop);
886 if (onekey || stop > SEARCH_NEXT_KEY)
892 repodata_setpos_kv(Repodata *data, KeyValue *kv)
894 Pool *pool = data->repo->pool;
896 pool_clear_pos(pool);
899 pool->pos.repo = data->repo;
900 pool->pos.repodataid = data - data->repo->repodata;
901 pool->pos.dp = (unsigned char *)kv->str - data->incoredata;
902 pool->pos.schema = kv->id;
906 /************************************************************************
907 * data iterator functions
910 static Repokey solvablekeys[RPM_RPMDBID - SOLVABLE_NAME + 1] = {
911 { SOLVABLE_NAME, REPOKEY_TYPE_ID, 0, KEY_STORAGE_SOLVABLE },
912 { SOLVABLE_ARCH, REPOKEY_TYPE_ID, 0, KEY_STORAGE_SOLVABLE },
913 { SOLVABLE_EVR, REPOKEY_TYPE_ID, 0, KEY_STORAGE_SOLVABLE },
914 { SOLVABLE_VENDOR, REPOKEY_TYPE_ID, 0, KEY_STORAGE_SOLVABLE },
915 { SOLVABLE_PROVIDES, REPOKEY_TYPE_IDARRAY, 0, KEY_STORAGE_SOLVABLE },
916 { SOLVABLE_OBSOLETES, REPOKEY_TYPE_IDARRAY, 0, KEY_STORAGE_SOLVABLE },
917 { SOLVABLE_CONFLICTS, REPOKEY_TYPE_IDARRAY, 0, KEY_STORAGE_SOLVABLE },
918 { SOLVABLE_REQUIRES, REPOKEY_TYPE_IDARRAY, 0, KEY_STORAGE_SOLVABLE },
919 { SOLVABLE_RECOMMENDS, REPOKEY_TYPE_IDARRAY, 0, KEY_STORAGE_SOLVABLE },
920 { SOLVABLE_SUGGESTS, REPOKEY_TYPE_IDARRAY, 0, KEY_STORAGE_SOLVABLE },
921 { SOLVABLE_SUPPLEMENTS, REPOKEY_TYPE_IDARRAY, 0, KEY_STORAGE_SOLVABLE },
922 { SOLVABLE_ENHANCES, REPOKEY_TYPE_IDARRAY, 0, KEY_STORAGE_SOLVABLE },
923 { RPM_RPMDBID, REPOKEY_TYPE_U32, 0, KEY_STORAGE_SOLVABLE },
927 solvabledata_fetch(Solvable *s, KeyValue *kv, Id keyname)
941 case SOLVABLE_VENDOR:
944 case SOLVABLE_PROVIDES:
946 return s->provides ? s->repo->idarraydata + s->provides : 0;
947 case SOLVABLE_OBSOLETES:
949 return s->obsoletes ? s->repo->idarraydata + s->obsoletes : 0;
950 case SOLVABLE_CONFLICTS:
952 return s->conflicts ? s->repo->idarraydata + s->conflicts : 0;
953 case SOLVABLE_REQUIRES:
955 return s->requires ? s->repo->idarraydata + s->requires : 0;
956 case SOLVABLE_RECOMMENDS:
958 return s->recommends ? s->repo->idarraydata + s->recommends : 0;
959 case SOLVABLE_SUPPLEMENTS:
961 return s->supplements ? s->repo->idarraydata + s->supplements : 0;
962 case SOLVABLE_SUGGESTS:
964 return s->suggests ? s->repo->idarraydata + s->suggests : 0;
965 case SOLVABLE_ENHANCES:
967 return s->enhances ? s->repo->idarraydata + s->enhances : 0;
970 return s->repo->rpmdbid ? s->repo->rpmdbid + (s - s->repo->pool->solvables - s->repo->start) : 0;
977 datamatcher_init(Datamatcher *ma, const char *match, int flags)
983 if ((flags & SEARCH_STRINGMASK) == SEARCH_REGEX)
985 ma->matchdata = sat_calloc(1, sizeof(regex_t));
986 ma->error = regcomp((regex_t *)ma->matchdata, match, REG_EXTENDED | REG_NOSUB | REG_NEWLINE | ((flags & SEARCH_NOCASE) ? REG_ICASE : 0));
989 sat_free(ma->matchdata);
990 ma->flags = (flags & ~SEARCH_STRINGMASK) | SEARCH_ERROR;
997 datamatcher_free(Datamatcher *ma)
999 if ((ma->flags & SEARCH_STRINGMASK) == SEARCH_REGEX && ma->matchdata)
1001 regfree(ma->matchdata);
1002 ma->matchdata = sat_free(ma->matchdata);
1007 datamatcher_match(Datamatcher *ma, const char *str)
1010 switch ((ma->flags & SEARCH_STRINGMASK))
1012 case SEARCH_SUBSTRING:
1013 if (ma->flags & SEARCH_NOCASE)
1015 if (!strcasestr(str, ma->match))
1020 if (!strstr(str, ma->match))
1025 if (ma->flags & SEARCH_NOCASE)
1027 if (strcasecmp(ma->match, str))
1032 if (strcmp(ma->match, str))
1036 case SEARCH_STRINGSTART:
1037 if (ma->flags & SEARCH_NOCASE)
1039 if (strncasecmp(ma->match, str, strlen(ma->match)))
1044 if (strncmp(ma->match, str, strlen(ma->match)))
1048 case SEARCH_STRINGEND:
1049 l = strlen(str) - strlen(ma->match);
1052 if (ma->flags & SEARCH_NOCASE)
1054 if (strcasecmp(ma->match, str + l))
1059 if (strcmp(ma->match, str + l))
1064 if (fnmatch(ma->match, str, (ma->flags & SEARCH_NOCASE) ? FNM_CASEFOLD : 0))
1068 if (regexec((const regex_t *)ma->matchdata, str, 0, NULL, 0))
1078 repodata_filelistfilter_matches(Repodata *data, const char *str)
1080 /* '.*bin\/.*', '^\/etc\/.*', '^\/usr\/lib\/sendmail$' */
1081 /* for now hardcoded */
1082 if (strstr(str, "bin/"))
1084 if (!strncmp(str, "/etc/", 5))
1086 if (!strcmp(str, "/usr/lib/sendmail"))
1108 di_nextarrayelement,
1113 di_nextsolvableattr,
1118 /* see repo.h for documentation */
1120 dataiterator_init(Dataiterator *di, Pool *pool, Repo *repo, Id p, Id keyname, const char *match, int flags)
1122 memset(di, 0, sizeof(*di));
1124 di->flags = flags & ~SEARCH_THISSOLVID;
1125 if (!pool || (repo && repo->pool != pool))
1133 if ((error = datamatcher_init(&di->matcher, match, flags)) != 0)
1139 di->keyname = keyname;
1140 di->keynames[0] = keyname;
1141 dataiterator_set_search(di, repo, p);
1146 dataiterator_init_clone(Dataiterator *di, Dataiterator *from)
1149 memset(&di->matcher, 0, sizeof(di->matcher));
1150 if (from->matcher.match)
1151 datamatcher_init(&di->matcher, from->matcher.match, from->matcher.flags);
1156 for (i = 1; i < di->nparents; i++)
1157 di->parents[i].kv.parent = &di->parents[i - 1].kv;
1158 di->kv.parent = &di->parents[di->nparents - 1].kv;
1163 dataiterator_set_match(Dataiterator *di, const char *match, int flags)
1165 di->flags = (flags & ~SEARCH_THISSOLVID) | (di->flags & SEARCH_THISSOLVID);
1166 datamatcher_free(&di->matcher);
1167 memset(&di->matcher, 0, sizeof(di->matcher));
1171 if ((error = datamatcher_init(&di->matcher, match, flags)) != 0)
1181 dataiterator_set_search(Dataiterator *di, Repo *repo, Id p)
1185 di->flags &= ~SEARCH_THISSOLVID;
1189 if (!di->pool->nrepos)
1197 di->repo = di->pool->repos[0];
1199 di->state = di_enterrepo;
1201 dataiterator_jump_to_solvid(di, p);
1205 dataiterator_set_keyname(Dataiterator *di, Id keyname)
1208 di->keyname = keyname;
1209 di->keynames[0] = keyname;
1213 dataiterator_prepend_keyname(Dataiterator *di, Id keyname)
1217 if (di->nkeynames >= sizeof(di->keynames)/sizeof(*di->keynames) - 2)
1219 di->state = di_bye; /* sorry */
1222 for (i = di->nkeynames + 1; i > 0; i--)
1223 di->keynames[i] = di->keynames[i - 1];
1224 di->keynames[0] = di->keyname = keyname;
1229 dataiterator_free(Dataiterator *di)
1231 if (di->matcher.match)
1232 datamatcher_free(&di->matcher);
1235 static inline unsigned char *
1236 dataiterator_find_keyname(Dataiterator *di, Id keyname)
1238 Id *keyp = di->keyp;
1239 Repokey *keys = di->data->keys;
1242 for (keyp = di->keyp; *keyp; keyp++)
1243 if (keys[*keyp].name == keyname)
1247 dp = forward_to_key(di->data, *keyp, di->keyp, di->dp);
1255 dataiterator_filelistcheck(Dataiterator *di)
1258 int needcomplete = 0;
1259 Repodata *data = di->data;
1261 if ((di->matcher.flags & SEARCH_COMPLETE_FILELIST) != 0)
1262 if (!di->matcher.match
1263 || ((di->matcher.flags & (SEARCH_STRINGMASK|SEARCH_NOCASE)) != SEARCH_STRING
1264 && (di->matcher.flags & (SEARCH_STRINGMASK|SEARCH_NOCASE)) != SEARCH_GLOB)
1265 || !repodata_filelistfilter_matches(di->data, di->matcher.match))
1267 if (data->state != REPODATA_AVAILABLE)
1268 return needcomplete ? 1 : 0;
1269 for (j = 1; j < data->nkeys; j++)
1270 if (data->keys[j].name != REPOSITORY_SOLVABLES && data->keys[j].name != SOLVABLE_FILELIST)
1272 return j == data->nkeys && !needcomplete ? 0 : 1;
1276 dataiterator_step(Dataiterator *di)
1284 case di_enterrepo: di_enterrepo:
1287 if (di->repo->disabled && !(di->flags & SEARCH_DISABLED_REPOS))
1289 if (!(di->flags & SEARCH_THISSOLVID))
1291 di->solvid = di->repo->start - 1; /* reset solvid iterator */
1292 goto di_nextsolvable;
1296 case di_entersolvable: di_entersolvable:
1297 if (di->repodataid >= 0)
1299 di->repodataid = 0; /* reset repodata iterator */
1300 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)
1302 di->key = solvablekeys + (di->keyname ? di->keyname - SOLVABLE_NAME : 0);
1304 goto di_entersolvablekey;
1309 case di_enterrepodata: di_enterrepodata:
1310 if (di->repodataid >= 0)
1312 if (di->repodataid >= di->repo->nrepodata)
1313 goto di_nextsolvable;
1314 di->data = di->repo->repodata + di->repodataid;
1316 if (di->repodataid >= 0 && di->keyname == SOLVABLE_FILELIST && !dataiterator_filelistcheck(di))
1317 goto di_nextrepodata;
1318 if (!maybe_load_repodata(di->data, di->keyname))
1319 goto di_nextrepodata;
1320 di->dp = solvid2data(di->data, di->solvid, &schema);
1322 goto di_nextrepodata;
1323 if (di->solvid == SOLVID_POS)
1324 di->solvid = di->pool->pos.solvid;
1325 /* reset key iterator */
1326 di->keyp = di->data->schemadata + di->data->schemata[schema];
1329 case di_enterschema: di_enterschema:
1331 di->dp = dataiterator_find_keyname(di, di->keyname);
1332 if (!di->dp || !*di->keyp)
1336 goto di_nextrepodata;
1340 case di_enterkey: di_enterkey:
1342 di->key = di->data->keys + *di->keyp;
1343 di->ddp = get_data(di->data, di->key, &di->dp, di->keyp[1] && (!di->keyname || (di->flags & SEARCH_SUB) != 0) ? 1 : 0);
1346 if (di->key->type == REPOKEY_TYPE_DELETED)
1348 if (di->key->type == REPOKEY_TYPE_FIXARRAY || di->key->type == REPOKEY_TYPE_FLEXARRAY)
1350 if (di->nkeynames && di->nparents - di->rootlevel < di->nkeynames)
1356 di->ddp = data_fetch(di->ddp, &di->kv, di->key);
1358 di->state = di_nextkey;
1360 di->state = di_nextattr;
1363 case di_nextkey: di_nextkey:
1364 if (!di->keyname && *++di->keyp)
1370 case di_nextrepodata: di_nextrepodata:
1371 if (di->repodataid >= 0 && ++di->repodataid < di->repo->nrepodata)
1372 goto di_enterrepodata;
1375 case di_nextsolvable: di_nextsolvable:
1376 if (!(di->flags & SEARCH_THISSOLVID))
1379 di->solvid = di->repo->start;
1382 for (; di->solvid < di->repo->end; di->solvid++)
1384 if (di->pool->solvables[di->solvid].repo == di->repo)
1385 goto di_entersolvable;
1390 case di_nextrepo: di_nextrepo:
1391 if (di->repoid >= 0)
1395 if (di->repoid < di->pool->nrepos)
1397 di->repo = di->pool->repos[di->repoid];
1403 case di_bye: di_bye:
1407 case di_enterarray: di_enterarray:
1408 if (di->key->name == REPOSITORY_SOLVABLES)
1410 di->ddp = data_read_id(di->ddp, &di->kv.num);
1415 case di_nextarrayelement: di_nextarrayelement:
1418 di->ddp = data_skip_schema(di->data, di->ddp, di->kv.id);
1419 if (di->kv.entry == di->kv.num)
1421 if (di->nkeynames && di->nparents - di->rootlevel < di->nkeynames)
1423 if (!(di->flags & SEARCH_ARRAYSENTINEL))
1425 di->kv.str = (char *)di->ddp;
1427 di->state = di_nextkey;
1430 if (di->kv.entry == di->kv.num - 1)
1432 if (di->key->type == REPOKEY_TYPE_FLEXARRAY || !di->kv.entry)
1433 di->ddp = data_read_id(di->ddp, &di->kv.id);
1434 di->kv.str = (char *)di->ddp;
1435 if (di->nkeynames && di->nparents - di->rootlevel < di->nkeynames)
1437 if ((di->flags & SEARCH_SUB) != 0)
1438 di->state = di_entersub;
1440 di->state = di_nextarrayelement;
1443 case di_entersub: di_entersub:
1444 if (di->nparents == sizeof(di->parents)/sizeof(*di->parents) - 1)
1445 goto di_nextarrayelement; /* sorry, full */
1446 di->parents[di->nparents].kv = di->kv;
1447 di->parents[di->nparents].dp = di->dp;
1448 di->parents[di->nparents].keyp = di->keyp;
1449 di->dp = (unsigned char *)di->kv.str;
1450 di->keyp = di->data->schemadata + di->data->schemata[di->kv.id];
1451 memset(&di->kv, 0, sizeof(di->kv));
1452 di->kv.parent = &di->parents[di->nparents].kv;
1454 di->keyname = di->keynames[di->nparents - di->rootlevel];
1455 goto di_enterschema;
1457 case di_leavesub: di_leavesub:
1458 if (di->nparents - 1 < di->rootlevel)
1461 di->dp = di->parents[di->nparents].dp;
1462 di->kv = di->parents[di->nparents].kv;
1463 di->keyp = di->parents[di->nparents].keyp;
1464 di->key = di->data->keys + *di->keyp;
1465 di->ddp = (unsigned char *)di->kv.str;
1466 di->keyname = di->keynames[di->nparents - di->rootlevel];
1467 goto di_nextarrayelement;
1469 /* special solvable attr handling follows */
1471 case di_nextsolvableattr:
1472 di->kv.id = *di->idp++;
1477 di->state = di_nextsolvablekey;
1481 case di_nextsolvablekey: di_nextsolvablekey:
1482 if (di->keyname || di->key->name == RPM_RPMDBID)
1483 goto di_enterrepodata;
1487 case di_entersolvablekey: di_entersolvablekey:
1488 di->idp = solvabledata_fetch(di->pool->solvables + di->solvid, &di->kv, di->key->name);
1489 if (!di->idp || !di->idp[0])
1490 goto di_nextsolvablekey;
1491 di->kv.id = di->idp[0];
1492 di->kv.num = di->idp[0];
1494 if (!di->kv.eof && !di->idp[0])
1498 di->state = di_nextsolvablekey;
1500 di->state = di_nextsolvableattr;
1504 if (di->matcher.match)
1506 /* simple pre-check so that we don't need to stringify */
1507 if (di->keyname == SOLVABLE_FILELIST && di->key->type == REPOKEY_TYPE_DIRSTRARRAY && di->matcher.match && (di->matcher.flags & (SEARCH_FILES|SEARCH_NOCASE|SEARCH_STRINGMASK)) == (SEARCH_FILES|SEARCH_STRING))
1509 int l = strlen(di->matcher.match) - strlen(di->kv.str);
1510 if (l < 0 || strcmp(di->matcher.match + l, di->kv.str))
1513 if (!repodata_stringify(di->pool, di->data, di->key, &di->kv, di->flags))
1515 if (di->keyname && (di->key->type == REPOKEY_TYPE_FIXARRAY || di->key->type == REPOKEY_TYPE_FLEXARRAY))
1519 if (!datamatcher_match(&di->matcher, di->kv.str))
1522 /* found something! */
1528 dataiterator_entersub(Dataiterator *di)
1530 if (di->state == di_nextarrayelement)
1531 di->state = di_entersub;
1535 dataiterator_setpos(Dataiterator *di)
1537 if (di->kv.eof == 2)
1539 pool_clear_pos(di->pool);
1542 di->pool->pos.solvid = di->solvid;
1543 di->pool->pos.repo = di->repo;
1544 di->pool->pos.repodataid = di->data - di->repo->repodata;
1545 di->pool->pos.schema = di->kv.id;
1546 di->pool->pos.dp = (unsigned char *)di->kv.str - di->data->incoredata;
1550 dataiterator_setpos_parent(Dataiterator *di)
1552 if (!di->kv.parent || di->kv.parent->eof == 2)
1554 pool_clear_pos(di->pool);
1557 di->pool->pos.solvid = di->solvid;
1558 di->pool->pos.repo = di->repo;
1559 di->pool->pos.repodataid = di->data - di->repo->repodata;
1560 di->pool->pos.schema = di->kv.parent->id;
1561 di->pool->pos.dp = (unsigned char *)di->kv.parent->str - di->data->incoredata;
1564 /* clones just the position, not the search keys/matcher */
1566 dataiterator_clonepos(Dataiterator *di, Dataiterator *from)
1568 di->state = from->state;
1569 di->flags &= ~SEARCH_THISSOLVID;
1570 di->flags |= (from->flags & SEARCH_THISSOLVID);
1571 di->repo = from->repo;
1572 di->data = from->data;
1574 di->ddp = from->ddp;
1575 di->idp = from->idp;
1576 di->keyp = from->keyp;
1577 di->key = from->key;
1579 di->repodataid = from->repodataid;
1580 di->solvid = from->solvid;
1581 di->repoid = from->repoid;
1582 di->rootlevel = from->rootlevel;
1583 memcpy(di->parents, from->parents, sizeof(from->parents));
1584 di->nparents = from->nparents;
1588 for (i = 1; i < di->nparents; i++)
1589 di->parents[i].kv.parent = &di->parents[i - 1].kv;
1590 di->kv.parent = &di->parents[di->nparents - 1].kv;
1595 dataiterator_seek(Dataiterator *di, int whence)
1597 if ((whence & DI_SEEK_STAY) != 0)
1598 di->rootlevel = di->nparents;
1599 switch (whence & ~DI_SEEK_STAY)
1602 if (di->state != di_nextarrayelement)
1604 if ((whence & DI_SEEK_STAY) != 0)
1605 di->rootlevel = di->nparents + 1; /* XXX: dangerous! */
1606 di->state = di_entersub;
1608 case DI_SEEK_PARENT:
1615 if (di->rootlevel > di->nparents)
1616 di->rootlevel = di->nparents;
1617 di->dp = di->parents[di->nparents].dp;
1618 di->kv = di->parents[di->nparents].kv;
1619 di->keyp = di->parents[di->nparents].keyp;
1620 di->key = di->data->keys + *di->keyp;
1621 di->ddp = (unsigned char *)di->kv.str;
1622 di->keyname = di->keynames[di->nparents - di->rootlevel];
1623 di->state = di_nextarrayelement;
1625 case DI_SEEK_REWIND:
1631 di->dp = (unsigned char *)di->kv.parent->str;
1632 di->keyp = di->data->schemadata + di->data->schemata[di->kv.parent->id];
1633 di->state = di_enterschema;
1641 dataiterator_skip_attribute(Dataiterator *di)
1643 if (di->state == di_nextsolvableattr)
1644 di->state = di_nextsolvablekey;
1646 di->state = di_nextkey;
1650 dataiterator_skip_solvable(Dataiterator *di)
1655 di->keyname = di->keynames[0];
1656 di->state = di_nextsolvable;
1660 dataiterator_skip_repo(Dataiterator *di)
1665 di->keyname = di->keynames[0];
1666 di->state = di_nextrepo;
1670 dataiterator_jump_to_solvid(Dataiterator *di, Id solvid)
1675 di->keyname = di->keynames[0];
1676 if (solvid == SOLVID_POS)
1678 di->repo = di->pool->pos.repo;
1685 di->data = di->repo->repodata + di->pool->pos.repodataid;
1686 di->repodataid = -1;
1687 di->solvid = solvid;
1688 di->state = di_enterrepo;
1689 di->flags |= SEARCH_THISSOLVID;
1694 di->repo = di->pool->solvables[solvid].repo;
1697 else if (di->repoid >= 0)
1699 if (!di->pool->nrepos)
1704 di->repo = di->pool->repos[0];
1708 di->solvid = solvid;
1710 di->flags |= SEARCH_THISSOLVID;
1711 di->state = di_enterrepo;
1715 dataiterator_jump_to_repo(Dataiterator *di, Repo *repo)
1724 di->flags &= ~SEARCH_THISSOLVID;
1725 di->state = di_enterrepo;
1729 dataiterator_match(Dataiterator *di, Datamatcher *ma)
1731 if (!repodata_stringify(di->pool, di->data, di->key, &di->kv, di->flags))
1735 return datamatcher_match(ma, di->kv.str);
1738 /************************************************************************
1739 * data modify functions
1742 /* extend repodata so that it includes solvables p */
1744 repodata_extend(Repodata *data, Id p)
1746 if (data->start == data->end)
1747 data->start = data->end = p;
1750 int old = data->end - data->start;
1751 int new = p - data->end + 1;
1754 data->attrs = sat_extend(data->attrs, old, new, sizeof(Id *), REPODATA_BLOCK);
1755 memset(data->attrs + old, 0, new * sizeof(Id *));
1757 data->incoreoffset = sat_extend(data->incoreoffset, old, new, sizeof(Id), REPODATA_BLOCK);
1758 memset(data->incoreoffset + old, 0, new * sizeof(Id));
1761 if (p < data->start)
1763 int old = data->end - data->start;
1764 int new = data->start - p;
1767 data->attrs = sat_extend_resize(data->attrs, old + new, sizeof(Id *), REPODATA_BLOCK);
1768 memmove(data->attrs + new, data->attrs, old * sizeof(Id *));
1769 memset(data->attrs, 0, new * sizeof(Id *));
1771 data->incoreoffset = sat_extend_resize(data->incoreoffset, old + new, sizeof(Id), REPODATA_BLOCK);
1772 memmove(data->incoreoffset + new, data->incoreoffset, old * sizeof(Id));
1773 memset(data->incoreoffset, 0, new * sizeof(Id));
1778 /* shrink end of repodata */
1780 repodata_shrink(Repodata *data, int end)
1784 if (data->end <= end)
1786 if (data->start >= end)
1790 for (i = 0; i < data->end - data->start; i++)
1791 sat_free(data->attrs[i]);
1792 data->attrs = sat_free(data->attrs);
1794 data->incoreoffset = sat_free(data->incoreoffset);
1795 data->start = data->end = 0;
1800 for (i = end; i < data->end; i++)
1801 sat_free(data->attrs[i - data->start]);
1802 data->attrs = sat_extend_resize(data->attrs, end - data->start, sizeof(Id *), REPODATA_BLOCK);
1804 if (data->incoreoffset)
1805 data->incoreoffset = sat_extend_resize(data->incoreoffset, end - data->start, sizeof(Id), REPODATA_BLOCK);
1809 /* extend repodata so that it includes solvables from start to start + num - 1 */
1811 repodata_extend_block(Repodata *data, Id start, Id num)
1815 if (!data->incoreoffset)
1817 data->incoreoffset = sat_calloc_block(num, sizeof(Id), REPODATA_BLOCK);
1818 data->start = start;
1819 data->end = start + num;
1822 repodata_extend(data, start);
1824 repodata_extend(data, start + num - 1);
1827 /**********************************************************************/
1830 #define REPODATA_ATTRS_BLOCK 31
1831 #define REPODATA_ATTRDATA_BLOCK 1023
1832 #define REPODATA_ATTRIDDATA_BLOCK 63
1836 repodata_new_handle(Repodata *data)
1840 data->xattrs = sat_calloc_block(1, sizeof(Id *), REPODATA_BLOCK);
1841 data->nxattrs = 2; /* -1: SOLVID_META */
1843 data->xattrs = sat_extend(data->xattrs, data->nxattrs, 1, sizeof(Id *), REPODATA_BLOCK);
1844 data->xattrs[data->nxattrs] = 0;
1845 return -(data->nxattrs++);
1849 repodata_get_attrp(Repodata *data, Id handle)
1853 if (handle == SOLVID_META && !data->xattrs)
1855 data->xattrs = sat_calloc_block(1, sizeof(Id *), REPODATA_BLOCK);
1858 return data->xattrs - handle;
1860 if (handle < data->start || handle >= data->end)
1861 repodata_extend(data, handle);
1863 data->attrs = sat_calloc_block(data->end - data->start, sizeof(Id *), REPODATA_BLOCK);
1864 return data->attrs + (handle - data->start);
1868 repodata_insert_keyid(Repodata *data, Id handle, Id keyid, Id val, int overwrite)
1874 app = repodata_get_attrp(data, handle);
1879 /* Determine equality based on the name only, allows us to change
1880 type (when overwrite is set), and makes TYPE_CONSTANT work. */
1881 for (pp = ap; *pp; pp += 2)
1882 if (data->keys[*pp].name == data->keys[keyid].name)
1886 if (overwrite || data->keys[*pp].type == REPOKEY_TYPE_DELETED)
1895 ap = sat_extend(ap, i, 3, sizeof(Id), REPODATA_ATTRS_BLOCK);
1905 repodata_set(Repodata *data, Id solvid, Repokey *key, Id val)
1909 keyid = repodata_key2id(data, key, 1);
1910 repodata_insert_keyid(data, solvid, keyid, val, 1);
1914 repodata_set_id(Repodata *data, Id solvid, Id keyname, Id id)
1918 key.type = REPOKEY_TYPE_ID;
1920 key.storage = KEY_STORAGE_INCORE;
1921 repodata_set(data, solvid, &key, id);
1925 repodata_set_num(Repodata *data, Id solvid, Id keyname, unsigned int num)
1929 key.type = REPOKEY_TYPE_NUM;
1931 key.storage = KEY_STORAGE_INCORE;
1932 repodata_set(data, solvid, &key, (Id)num);
1936 repodata_set_poolstr(Repodata *data, Id solvid, Id keyname, const char *str)
1940 if (data->localpool)
1941 id = stringpool_str2id(&data->spool, str, 1);
1943 id = str2id(data->repo->pool, str, 1);
1945 key.type = REPOKEY_TYPE_ID;
1947 key.storage = KEY_STORAGE_INCORE;
1948 repodata_set(data, solvid, &key, id);
1952 repodata_set_constant(Repodata *data, Id solvid, Id keyname, unsigned int constant)
1956 key.type = REPOKEY_TYPE_CONSTANT;
1957 key.size = constant;
1958 key.storage = KEY_STORAGE_INCORE;
1959 repodata_set(data, solvid, &key, 0);
1963 repodata_set_constantid(Repodata *data, Id solvid, Id keyname, Id id)
1967 key.type = REPOKEY_TYPE_CONSTANTID;
1969 key.storage = KEY_STORAGE_INCORE;
1970 repodata_set(data, solvid, &key, 0);
1974 repodata_set_void(Repodata *data, Id solvid, Id keyname)
1978 key.type = REPOKEY_TYPE_VOID;
1980 key.storage = KEY_STORAGE_INCORE;
1981 repodata_set(data, solvid, &key, 0);
1985 repodata_set_str(Repodata *data, Id solvid, Id keyname, const char *str)
1990 l = strlen(str) + 1;
1992 key.type = REPOKEY_TYPE_STR;
1994 key.storage = KEY_STORAGE_INCORE;
1995 data->attrdata = sat_extend(data->attrdata, data->attrdatalen, l, 1, REPODATA_ATTRDATA_BLOCK);
1996 memcpy(data->attrdata + data->attrdatalen, str, l);
1997 repodata_set(data, solvid, &key, data->attrdatalen);
1998 data->attrdatalen += l;
2002 repodata_set_binary(Repodata *data, Id solvid, Id keyname, void *buf, int len)
2008 key.type = REPOKEY_TYPE_BINARY;
2010 key.storage = KEY_STORAGE_INCORE;
2011 data->attrdata = sat_extend(data->attrdata, data->attrdatalen, len + 5, 1, REPODATA_ATTRDATA_BLOCK);
2012 dp = data->attrdata + data->attrdatalen;
2013 if (len >= (1 << 14))
2015 if (len >= (1 << 28))
2016 *dp++ = (len >> 28) | 128;
2017 if (len >= (1 << 21))
2018 *dp++ = (len >> 21) | 128;
2019 *dp++ = (len >> 14) | 128;
2021 if (len >= (1 << 7))
2022 *dp++ = (len >> 7) | 128;
2025 memcpy(dp, buf, len);
2026 repodata_set(data, solvid, &key, data->attrdatalen);
2027 data->attrdatalen = dp + len - data->attrdata;
2030 /* add an array element consisting of entrysize Ids to the repodata. modifies attriddata
2031 * so that the caller can append entrysize new elements plus the termination zero there */
2033 repodata_add_array(Repodata *data, Id handle, Id keyname, Id keytype, int entrysize)
2036 Id *ida, *pp, **ppp;
2038 /* check if it is the same as last time, this speeds things up a lot */
2039 if (handle == data->lasthandle && data->keys[data->lastkey].name == keyname && data->keys[data->lastkey].type == keytype && data->attriddatalen == data->lastdatalen)
2041 /* great! just append the new data */
2042 data->attriddata = sat_extend(data->attriddata, data->attriddatalen, entrysize, sizeof(Id), REPODATA_ATTRIDDATA_BLOCK);
2043 data->attriddatalen--; /* overwrite terminating 0 */
2044 data->lastdatalen += entrysize;
2048 ppp = repodata_get_attrp(data, handle);
2052 for (; *pp; pp += 2)
2053 if (data->keys[*pp].name == keyname)
2056 if (!pp || !*pp || data->keys[*pp].type != keytype)
2058 /* not found. allocate new key */
2064 key.storage = KEY_STORAGE_INCORE;
2065 data->attriddata = sat_extend(data->attriddata, data->attriddatalen, entrysize + 1, sizeof(Id), REPODATA_ATTRIDDATA_BLOCK);
2066 keyid = repodata_key2id(data, &key, 1);
2067 repodata_insert_keyid(data, handle, keyid, data->attriddatalen, 1);
2068 data->lasthandle = handle;
2069 data->lastkey = keyid;
2070 data->lastdatalen = data->attriddatalen + entrysize + 1;
2074 for (ida = data->attriddata + pp[1]; *ida; ida += entrysize)
2075 oldsize += entrysize;
2076 if (ida + 1 == data->attriddata + data->attriddatalen)
2078 /* this was the last entry, just append it */
2079 data->attriddata = sat_extend(data->attriddata, data->attriddatalen, entrysize, sizeof(Id), REPODATA_ATTRIDDATA_BLOCK);
2080 data->attriddatalen--; /* overwrite terminating 0 */
2084 /* too bad. move to back. */
2085 data->attriddata = sat_extend(data->attriddata, data->attriddatalen, oldsize + entrysize + 1, sizeof(Id), REPODATA_ATTRIDDATA_BLOCK);
2086 memcpy(data->attriddata + data->attriddatalen, data->attriddata + pp[1], oldsize * sizeof(Id));
2087 pp[1] = data->attriddatalen;
2088 data->attriddatalen += oldsize;
2090 data->lasthandle = handle;
2091 data->lastkey = *pp;
2092 data->lastdatalen = data->attriddatalen + entrysize + 1;
2096 repodata_set_bin_checksum(Repodata *data, Id solvid, Id keyname, Id type,
2097 const unsigned char *str)
2102 if (!(l = sat_chksum_len(type)))
2107 key.storage = KEY_STORAGE_INCORE;
2108 data->attrdata = sat_extend(data->attrdata, data->attrdatalen, l, 1, REPODATA_ATTRDATA_BLOCK);
2109 memcpy(data->attrdata + data->attrdatalen, str, l);
2110 repodata_set(data, solvid, &key, data->attrdatalen);
2111 data->attrdatalen += l;
2115 repodata_set_checksum(Repodata *data, Id solvid, Id keyname, Id type,
2118 unsigned char buf[64];
2121 if (!(l = sat_chksum_len(type)))
2123 if (l > sizeof(buf) || sat_hex2bin(&str, buf, l) != l)
2125 repodata_set_bin_checksum(data, solvid, keyname, type, buf);
2129 repodata_chk2str(Repodata *data, Id type, const unsigned char *buf)
2133 if (!(l = sat_chksum_len(type)))
2135 return pool_bin2hex(data->repo->pool, buf, l);
2138 /* rpm filenames don't contain the epoch, so strip it */
2139 static inline const char *
2140 evrid2vrstr(Pool *pool, Id evrid)
2142 const char *p, *evr = id2str(pool, evrid);
2145 for (p = evr; *p >= '0' && *p <= '9'; p++)
2147 return p != evr && *p == ':' ? p + 1 : evr;
2151 repodata_set_location(Repodata *data, Id solvid, int medianr, const char *dir, const char *file)
2153 Pool *pool = data->repo->pool;
2155 const char *str, *fp;
2159 repodata_set_constant(data, solvid, SOLVABLE_MEDIANR, medianr);
2162 if ((dir = strrchr(file, '/')) != 0)
2173 if (l >= 2 && dir[0] == '.' && dir[1] == '/' && (l == 2 || dir[2] != '/'))
2178 if (l == 1 && dir[0] == '.')
2180 s = pool->solvables + solvid;
2183 str = id2str(pool, s->arch);
2184 if (!strncmp(dir, str, l) && !str[l])
2185 repodata_set_void(data, solvid, SOLVABLE_MEDIADIR);
2187 repodata_set_str(data, solvid, SOLVABLE_MEDIADIR, dir);
2190 char *dir2 = strdup(dir);
2192 repodata_set_str(data, solvid, SOLVABLE_MEDIADIR, dir2);
2197 str = id2str(pool, s->name);
2199 if ((!l || !strncmp(fp, str, l)) && fp[l] == '-')
2202 str = evrid2vrstr(pool, s->evr);
2204 if ((!l || !strncmp(fp, str, l)) && fp[l] == '.')
2207 str = id2str(pool, s->arch);
2209 if ((!l || !strncmp(fp, str, l)) && !strcmp(fp + l, ".rpm"))
2211 repodata_set_void(data, solvid, SOLVABLE_MEDIAFILE);
2216 repodata_set_str(data, solvid, SOLVABLE_MEDIAFILE, file);
2220 repodata_set_idarray(Repodata *data, Id solvid, Id keyname, Queue *q)
2226 key.type = REPOKEY_TYPE_IDARRAY;
2228 key.storage = KEY_STORAGE_INCORE;
2229 repodata_set(data, solvid, &key, data->attriddatalen);
2230 data->attriddata = sat_extend(data->attriddata, data->attriddatalen, q->count + 1, sizeof(Id), REPODATA_ATTRIDDATA_BLOCK);
2231 for (i = 0; i < q->count; i++)
2232 data->attriddata[data->attriddatalen++] = q->elements[i];
2233 data->attriddata[data->attriddatalen++] = 0;
2237 repodata_add_dirnumnum(Repodata *data, Id solvid, Id keyname, Id dir, Id num, Id num2)
2241 fprintf(stderr, "repodata_add_dirnumnum %d %d %d %d (%d)\n", solvid, dir, num, num2, data->attriddatalen);
2243 repodata_add_array(data, solvid, keyname, REPOKEY_TYPE_DIRNUMNUMARRAY, 3);
2244 data->attriddata[data->attriddatalen++] = dir;
2245 data->attriddata[data->attriddatalen++] = num;
2246 data->attriddata[data->attriddatalen++] = num2;
2247 data->attriddata[data->attriddatalen++] = 0;
2251 repodata_add_dirstr(Repodata *data, Id solvid, Id keyname, Id dir, const char *str)
2257 l = strlen(str) + 1;
2258 data->attrdata = sat_extend(data->attrdata, data->attrdatalen, l, 1, REPODATA_ATTRDATA_BLOCK);
2259 memcpy(data->attrdata + data->attrdatalen, str, l);
2260 stroff = data->attrdatalen;
2261 data->attrdatalen += l;
2264 fprintf(stderr, "repodata_add_dirstr %d %d %s (%d)\n", solvid, dir, str, data->attriddatalen);
2266 repodata_add_array(data, solvid, keyname, REPOKEY_TYPE_DIRSTRARRAY, 2);
2267 data->attriddata[data->attriddatalen++] = dir;
2268 data->attriddata[data->attriddatalen++] = stroff;
2269 data->attriddata[data->attriddatalen++] = 0;
2273 repodata_add_idarray(Repodata *data, Id solvid, Id keyname, Id id)
2276 fprintf(stderr, "repodata_add_idarray %d %d (%d)\n", solvid, id, data->attriddatalen);
2278 repodata_add_array(data, solvid, keyname, REPOKEY_TYPE_IDARRAY, 1);
2279 data->attriddata[data->attriddatalen++] = id;
2280 data->attriddata[data->attriddatalen++] = 0;
2284 repodata_add_poolstr_array(Repodata *data, Id solvid, Id keyname,
2288 if (data->localpool)
2289 id = stringpool_str2id(&data->spool, str, 1);
2291 id = str2id(data->repo->pool, str, 1);
2292 repodata_add_idarray(data, solvid, keyname, id);
2296 repodata_add_fixarray(Repodata *data, Id solvid, Id keyname, Id ghandle)
2298 repodata_add_array(data, solvid, keyname, REPOKEY_TYPE_FIXARRAY, 1);
2299 data->attriddata[data->attriddatalen++] = ghandle;
2300 data->attriddata[data->attriddatalen++] = 0;
2304 repodata_add_flexarray(Repodata *data, Id solvid, Id keyname, Id ghandle)
2306 repodata_add_array(data, solvid, keyname, REPOKEY_TYPE_FLEXARRAY, 1);
2307 data->attriddata[data->attriddatalen++] = ghandle;
2308 data->attriddata[data->attriddatalen++] = 0;
2312 repodata_delete_uninternalized(Repodata *data, Id solvid, Id keyname)
2315 app = repodata_get_attrp(data, solvid);
2319 for (; *ap; ap += 2)
2320 if (data->keys[*ap].name == keyname)
2326 for (; *ap; ap += 2)
2328 if (data->keys[*ap].name == keyname)
2336 /* XXX: does not work correctly, needs fix in iterators! */
2338 repodata_delete(Repodata *data, Id solvid, Id keyname)
2342 key.type = REPOKEY_TYPE_DELETED;
2344 key.storage = KEY_STORAGE_INCORE;
2345 repodata_set(data, solvid, &key, 0);
2348 /* add all (uninternalized) attrs from src to dest */
2350 repodata_merge_attrs(Repodata *data, Id dest, Id src)
2353 if (dest == src || !(keyp = data->attrs[src - data->start]))
2355 for (; *keyp; keyp += 2)
2356 repodata_insert_keyid(data, dest, keyp[0], keyp[1], 0);
2359 /* add some (uninternalized) attrs from src to dest */
2361 repodata_merge_some_attrs(Repodata *data, Id dest, Id src, Map *keyidmap, int overwrite)
2364 if (dest == src || !(keyp = data->attrs[src - data->start]))
2366 for (; *keyp; keyp += 2)
2367 if (!keyidmap || MAPTST(keyidmap, keyp[0]))
2368 repodata_insert_keyid(data, dest, keyp[0], keyp[1], overwrite);
2373 /**********************************************************************/
2375 /* TODO: unify with repo_write and repo_solv! */
2377 #define EXTDATA_BLOCK 1023
2385 data_addid(struct extdata *xd, Id x)
2389 xd->buf = sat_extend(xd->buf, xd->len, 5, 1, EXTDATA_BLOCK);
2390 dp = xd->buf + xd->len;
2395 *dp++ = (x >> 28) | 128;
2397 *dp++ = (x >> 21) | 128;
2398 *dp++ = (x >> 14) | 128;
2401 *dp++ = (x >> 7) | 128;
2403 xd->len = dp - xd->buf;
2407 data_addideof(struct extdata *xd, Id x, int eof)
2410 x = (x & 63) | ((x & ~63) << 1);
2411 data_addid(xd, (eof ? x : x | 64));
2415 data_addblob(struct extdata *xd, unsigned char *blob, int len)
2417 xd->buf = sat_extend(xd->buf, xd->len, len, 1, EXTDATA_BLOCK);
2418 memcpy(xd->buf + xd->len, blob, len);
2422 /*********************************/
2424 /* internalalize some key into incore/vincore data */
2427 repodata_serialize_key(Repodata *data, struct extdata *newincore,
2428 struct extdata *newvincore,
2430 Repokey *key, Id val)
2434 unsigned int oldvincorelen = 0;
2438 if (key->storage == KEY_STORAGE_VERTICAL_OFFSET)
2441 oldvincorelen = xd->len;
2445 case REPOKEY_TYPE_VOID:
2446 case REPOKEY_TYPE_CONSTANT:
2447 case REPOKEY_TYPE_CONSTANTID:
2449 case REPOKEY_TYPE_STR:
2450 data_addblob(xd, data->attrdata + val, strlen((char *)(data->attrdata + val)) + 1);
2452 case REPOKEY_TYPE_MD5:
2453 data_addblob(xd, data->attrdata + val, SIZEOF_MD5);
2455 case REPOKEY_TYPE_SHA1:
2456 data_addblob(xd, data->attrdata + val, SIZEOF_SHA1);
2458 case REPOKEY_TYPE_SHA256:
2459 data_addblob(xd, data->attrdata + val, SIZEOF_SHA256);
2461 case REPOKEY_TYPE_ID:
2462 case REPOKEY_TYPE_NUM:
2463 case REPOKEY_TYPE_DIR:
2464 data_addid(xd, val);
2466 case REPOKEY_TYPE_BINARY:
2469 unsigned char *dp = data_read_id(data->attrdata + val, &len);
2471 data_addblob(xd, data->attrdata + val, dp - (data->attrdata + val));
2474 case REPOKEY_TYPE_IDARRAY:
2475 for (ida = data->attriddata + val; *ida; ida++)
2476 data_addideof(xd, ida[0], ida[1] ? 0 : 1);
2478 case REPOKEY_TYPE_DIRNUMNUMARRAY:
2479 for (ida = data->attriddata + val; *ida; ida += 3)
2481 data_addid(xd, ida[0]);
2482 data_addid(xd, ida[1]);
2483 data_addideof(xd, ida[2], ida[3] ? 0 : 1);
2486 case REPOKEY_TYPE_DIRSTRARRAY:
2487 for (ida = data->attriddata + val; *ida; ida += 2)
2489 data_addideof(xd, ida[0], ida[2] ? 0 : 1);
2490 data_addblob(xd, data->attrdata + ida[1], strlen((char *)(data->attrdata + ida[1])) + 1);
2493 case REPOKEY_TYPE_FIXARRAY:
2497 for (ida = data->attriddata + val; *ida; ida++)
2500 Id *kp = data->xattrs[-*ida];
2508 schemaid = repodata_schema2id(data, schema, 1);
2509 else if (schemaid != repodata_schema2id(data, schema, 0))
2511 pool_debug(data->repo->pool, SAT_FATAL, "fixarray substructs with different schemas\n");
2517 data_addid(xd, num);
2518 data_addid(xd, schemaid);
2519 for (ida = data->attriddata + val; *ida; ida++)
2521 Id *kp = data->xattrs[-*ida];
2525 repodata_serialize_key(data, newincore, newvincore, schema, data->keys + *kp, kp[1]);
2529 case REPOKEY_TYPE_FLEXARRAY:
2532 for (ida = data->attriddata + val; *ida; ida++)
2534 data_addid(xd, num);
2535 for (ida = data->attriddata + val; *ida; ida++)
2537 Id *kp = data->xattrs[-*ida];
2540 data_addid(xd, 0); /* XXX */
2547 schemaid = repodata_schema2id(data, schema, 1);
2548 data_addid(xd, schemaid);
2549 kp = data->xattrs[-*ida];
2551 repodata_serialize_key(data, newincore, newvincore, schema, data->keys + *kp, kp[1]);
2556 pool_debug(data->repo->pool, SAT_FATAL, "don't know how to handle type %d\n", key->type);
2559 if (key->storage == KEY_STORAGE_VERTICAL_OFFSET)
2561 /* put offset/len in incore */
2562 data_addid(newincore, data->lastverticaloffset + oldvincorelen);
2563 oldvincorelen = xd->len - oldvincorelen;
2564 data_addid(newincore, oldvincorelen);
2569 repodata_internalize(Repodata *data)
2571 Repokey *key, solvkey;
2573 Id schemaid, *schema, *sp, oldschema, *keyp, *keypstart, *seen;
2574 unsigned char *dp, *ndp;
2575 int newschema, oldcount;
2576 struct extdata newincore;
2577 struct extdata newvincore;
2580 if (!data->attrs && !data->xattrs)
2583 newvincore.buf = data->vincore;
2584 newvincore.len = data->vincorelen;
2586 /* find the solvables key, create if needed */
2587 memset(&solvkey, 0, sizeof(solvkey));
2588 solvkey.name = REPOSITORY_SOLVABLES;
2589 solvkey.type = REPOKEY_TYPE_FLEXARRAY;
2591 solvkey.storage = KEY_STORAGE_INCORE;
2592 solvkeyid = repodata_key2id(data, &solvkey, data->end != data->start ? 1 : 0);
2594 schema = sat_malloc2(data->nkeys, sizeof(Id));
2595 seen = sat_malloc2(data->nkeys, sizeof(Id));
2597 /* Merge the data already existing (in data->schemata, ->incoredata and
2598 friends) with the new attributes in data->attrs[]. */
2599 nentry = data->end - data->start;
2600 memset(&newincore, 0, sizeof(newincore));
2601 data_addid(&newincore, 0); /* start data at offset 1 */
2603 data->mainschema = 0;
2604 data->mainschemaoffsets = sat_free(data->mainschemaoffsets);
2606 /* join entry data */
2607 /* we start with the meta data, entry -1 */
2608 for (entry = -1; entry < nentry; entry++)
2610 memset(seen, 0, data->nkeys * sizeof(Id));
2612 dp = data->incoredata;
2615 dp += entry >= 0 ? data->incoreoffset[entry] : 1;
2616 dp = data_read_id(dp, &oldschema);
2619 fprintf(stderr, "oldschema %d\n", oldschema);
2620 fprintf(stderr, "schemata %d\n", data->schemata[oldschema]);
2621 fprintf(stderr, "schemadata %p\n", data->schemadata);
2623 /* seen: -1: old data 0: skipped >0: id + 1 */
2627 for (keyp = data->schemadata + data->schemata[oldschema]; *keyp; keyp++)
2631 pool_debug(data->repo->pool, SAT_FATAL, "Inconsistent old data (key occured twice).\n");
2639 keyp = data->attrs ? data->attrs[entry] : 0;
2642 /* strip solvables key */
2644 for (sp = keyp = schema; *sp; sp++)
2645 if (*sp != solvkeyid)
2650 seen[solvkeyid] = 0;
2651 keyp = data->xattrs ? data->xattrs[1] : 0;
2654 for (; *keyp; keyp += 2)
2661 seen[*keyp] = keyp[1] + 1;
2663 if (entry < 0 && data->end != data->start)
2670 /* Ideally we'd like to sort the new schema here, to ensure
2671 schema equality independend of the ordering. We can't do that
2672 yet. For once see below (old ids need to come before new ids).
2673 An additional difficulty is that we also need to move
2674 the values with the keys. */
2675 schemaid = repodata_schema2id(data, schema, 1);
2677 schemaid = oldschema;
2680 /* Now create data blob. We walk through the (possibly new) schema
2681 and either copy over old data, or insert the new. */
2682 /* XXX Here we rely on the fact that the (new) schema has the form
2683 o1 o2 o3 o4 ... | n1 n2 n3 ...
2684 (oX being the old keyids (possibly overwritten), and nX being
2685 the new keyids). This rules out sorting the keyids in order
2686 to ensure a small schema count. */
2688 data->incoreoffset[entry] = newincore.len;
2689 data_addid(&newincore, schemaid);
2692 data->mainschema = schemaid;
2693 data->mainschemaoffsets = sat_calloc(sp - schema, sizeof(Id));
2695 keypstart = data->schemadata + data->schemata[schemaid];
2696 for (keyp = keypstart; *keyp; keyp++)
2699 data->mainschemaoffsets[keyp - keypstart] = newincore.len;
2700 if (*keyp == solvkeyid)
2702 /* add flexarray entry count */
2703 data_addid(&newincore, data->end - data->start);
2706 key = data->keys + *keyp;
2708 fprintf(stderr, "internalize %d(%d):%s:%s\n", entry, entry + data->start, id2str(data->repo->pool, key->name), id2str(data->repo->pool, key->type));
2713 /* Skip the data associated with this old key. */
2714 if (key->storage == KEY_STORAGE_VERTICAL_OFFSET)
2716 ndp = data_skip(dp, REPOKEY_TYPE_ID);
2717 ndp = data_skip(ndp, REPOKEY_TYPE_ID);
2719 else if (key->storage == KEY_STORAGE_INCORE)
2720 ndp = data_skip_key(data, dp, key);
2723 if (seen[*keyp] == -1)
2725 /* If this key was an old one _and_ was not overwritten with
2726 a different value copy over the old value (we skipped it
2729 data_addblob(&newincore, dp, ndp - dp);
2732 else if (seen[*keyp])
2734 /* Otherwise we have a new value. Parse it into the internal
2736 repodata_serialize_key(data, &newincore, &newvincore,
2737 schema, key, seen[*keyp] - 1);
2741 if (entry >= 0 && data->attrs && data->attrs[entry])
2742 data->attrs[entry] = sat_free(data->attrs[entry]);
2744 /* free all xattrs */
2745 for (entry = 0; entry < data->nxattrs; entry++)
2746 if (data->xattrs[entry])
2747 sat_free(data->xattrs[entry]);
2748 data->xattrs = sat_free(data->xattrs);
2751 data->lasthandle = 0;
2753 data->lastdatalen = 0;
2756 repodata_free_schemahash(data);
2758 sat_free(data->incoredata);
2759 data->incoredata = newincore.buf;
2760 data->incoredatalen = newincore.len;
2761 data->incoredatafree = 0;
2763 sat_free(data->vincore);
2764 data->vincore = newvincore.buf;
2765 data->vincorelen = newvincore.len;
2767 data->attrs = sat_free(data->attrs);
2768 data->attrdata = sat_free(data->attrdata);
2769 data->attriddata = sat_free(data->attriddata);
2770 data->attrdatalen = 0;
2771 data->attriddatalen = 0;
2775 repodata_disable_paging(Repodata *data)
2777 if (maybe_load_repodata(data, 0))
2778 repopagestore_disable_paging(&data->store);
2782 repodata_load_stub(Repodata *data)
2784 Repo *repo = data->repo;
2785 Pool *pool = repo->pool;
2787 struct _Pool_tmpspace oldtmpspace;
2789 if (!pool->loadcallback)
2791 data->state = REPODATA_ERROR;
2794 data->state = REPODATA_LOADING;
2796 /* save tmp space */
2797 oldtmpspace = pool->tmpspace;
2798 memset(&pool->tmpspace, 0, sizeof(pool->tmpspace));
2800 r = pool->loadcallback(pool, data, pool->loadcallbackdata);
2802 /* restore tmp space */
2803 for (i = 0; i < POOL_TMPSPACEBUF; i++)
2804 sat_free(pool->tmpspace.buf[i]);
2805 pool->tmpspace = oldtmpspace;
2807 data->state = r ? REPODATA_AVAILABLE : REPODATA_ERROR;
2811 repodata_create_stubs(Repodata *data)
2813 Repo *repo = data->repo;
2814 Pool *pool = repo->pool;
2821 int datastart, dataend;
2823 repodataid = data - repo->repodata;
2824 datastart = data->start;
2825 dataend = data->end;
2826 dataiterator_init(&di, pool, repo, SOLVID_META, REPOSITORY_EXTERNAL, 0, 0);
2827 while (dataiterator_step(&di))
2829 if (di.data - repo->repodata != repodataid)
2833 dataiterator_free(&di);
2836 stubdataids = sat_calloc(cnt, sizeof(*stubdataids));
2837 for (i = 0; i < cnt; i++)
2839 sdata = repo_add_repodata(repo, 0);
2840 if (dataend > datastart)
2841 repodata_extend_block(sdata, datastart, dataend - datastart);
2842 stubdataids[i] = sdata - repo->repodata;
2843 sdata->state = REPODATA_STUB;
2844 sdata->loadcallback = repodata_load_stub;
2847 dataiterator_init(&di, pool, repo, SOLVID_META, REPOSITORY_EXTERNAL, 0, 0);
2849 while (dataiterator_step(&di))
2851 if (di.data - repo->repodata != repodataid)
2853 if (di.key->name == REPOSITORY_EXTERNAL && !di.nparents)
2855 dataiterator_entersub(&di);
2856 sdata = repo->repodata + stubdataids[i++];
2860 switch (di.key->type)
2862 case REPOKEY_TYPE_ID:
2863 repodata_set_id(sdata, SOLVID_META, di.key->name, di.kv.id);
2865 case REPOKEY_TYPE_CONSTANTID:
2866 repodata_set_constantid(sdata, SOLVID_META, di.key->name, di.kv.id);
2868 case REPOKEY_TYPE_STR:
2869 repodata_set_str(sdata, SOLVID_META, di.key->name, di.kv.str);
2871 case REPOKEY_TYPE_VOID:
2872 repodata_set_void(sdata, SOLVID_META, di.key->name);
2874 case REPOKEY_TYPE_NUM:
2875 repodata_set_num(sdata, SOLVID_META, di.key->name, di.kv.num);
2877 case REPOKEY_TYPE_MD5:
2878 case REPOKEY_TYPE_SHA1:
2879 case REPOKEY_TYPE_SHA256:
2880 repodata_set_bin_checksum(sdata, SOLVID_META, di.key->name, di.key->type, (const unsigned char *)di.kv.str);
2882 case REPOKEY_TYPE_IDARRAY:
2883 repodata_add_idarray(sdata, SOLVID_META, di.key->name, di.kv.id);
2884 if (di.key->name == REPOSITORY_KEYS)
2891 xkeyname = di.kv.id;
2894 xkey.name = xkeyname;
2895 xkey.type = di.kv.id;
2896 xkey.storage = KEY_STORAGE_INCORE;
2898 repodata_key2id(sdata, &xkey, 1);
2905 dataiterator_free(&di);
2906 for (i = 0; i < cnt; i++)
2907 repodata_internalize(repo->repodata + stubdataids[i]);
2908 sat_free(stubdataids);
2912 vim:cinoptions={.5s,g0,p5,t0,(0,^-0.5s,n-0.5s:tw=78:cindent:sw=4: