KNOWNID(ARCH_SRC, "src"),
KNOWNID(ARCH_NOSRC, "nosrc"),
KNOWNID(ARCH_NOARCH, "noarch"),
+KNOWNID(REPODATA_INFO, "repodata:info"),
KNOWNID(REPODATA_EXTERNAL, "repodata:external"),
KNOWNID(REPODATA_KEYS, "repodata:keys"),
KNOWNID(REPODATA_LOCATION, "repodata:location"),
+KNOWNID(REPODATA_ADDEDFILEPROVIDES, "repodata:addedfileprovides"),
/* The void type is usable to encode one-valued attributes, they have
no associated data. This is useful to encode values which many solvables
s = id2str(pool, dep);
if (*s != '/')
continue;
- sf->ids = sat_extend(sf->ids, sf->nfiles, 1, sizeof(const char *), SEARCHFILES_BLOCK);
+ sf->ids = sat_extend(sf->ids, sf->nfiles, 1, sizeof(Id), SEARCHFILES_BLOCK);
sf->dirs = sat_extend(sf->dirs, sf->nfiles, 1, sizeof(const char *), SEARCHFILES_BLOCK);
sf->names = sat_extend(sf->names, sf->nfiles, 1, sizeof(const char *), SEARCHFILES_BLOCK);
sf->ids[sf->nfiles] = dep;
return 0;
}
+
+static void
+pool_addfileprovides_search(Pool *pool, struct addfileprovides_cbdata *cbd, struct searchfiles *sf, Repo *repoonly)
+{
+ Id p, start, end, *idp;
+ Solvable *s;
+ Repodata *data = 0, *nextdata;
+ Repo *oldrepo = 0;
+ int dataincludes = 0;
+ int i;
+ Map providedids;
+
+ cbd->nfiles = sf->nfiles;
+ cbd->ids = sf->ids;
+ cbd->dirs = sf->dirs;
+ cbd->names = sf->names;
+ cbd->olddata = 0;
+ cbd->dids = sat_realloc2(cbd->dids, sf->nfiles, sizeof(Id));
+ if (repoonly)
+ {
+ start = repoonly->start;
+ end = repoonly->end;
+ }
+ else
+ {
+ start = 2; /* skip system solvable */
+ end = pool->nsolvables;
+ }
+ for (p = start, s = pool->solvables + p; p < end; p++, s++)
+ {
+ if (!s->repo || (repoonly && s->repo != repoonly))
+ continue;
+ if (s->repo != oldrepo || (data && p >= data->end))
+ {
+ data = 0;
+ oldrepo = 0;
+ }
+ if (oldrepo == 0)
+ {
+ nextdata = 0;
+ for (i = 0, data = s->repo->repodata; i < s->repo->nrepodata; i++, data++)
+ {
+ if (!data->addedfileprovides || p >= data->end)
+ continue;
+ if (!nextdata || nextdata->start > data->start)
+ nextdata = data;
+ if (p >= data->start)
+ break;
+ }
+ if (i == s->repo->nrepodata)
+ data = nextdata;
+ if (data)
+ {
+ map_init(&providedids, pool->ss.nstrings);
+ for (idp = data->addedfileprovides; *idp; idp++)
+ MAPSET(&providedids, *idp);
+ for (i = 0; i < cbd->nfiles; i++)
+ if (!MAPTST(&providedids, cbd->ids[i]))
+ {
+ break;
+ }
+ map_free(&providedids);
+ dataincludes = i == cbd->nfiles;
+ }
+ oldrepo = s->repo;
+ }
+ if (data && p >= data->start && dataincludes)
+ continue;
+ repo_search(s->repo, p, SOLVABLE_FILELIST, 0, 0, addfileprovides_cb, cbd);
+ }
+}
+
void
-pool_addfileprovides(Pool *pool, Repo *installed)
+pool_addfileprovides_ids(Pool *pool, Repo *installed, Id **idp)
{
Solvable *s;
Repo *repo;
POOL_DEBUG(SAT_DEBUG_STATS, "found %d installed file dependencies\n", isf.nfiles);
cbd.dids = 0;
map_init(&cbd.useddirs, 1);
+ if (idp)
+ *idp = 0;
if (sf.nfiles)
{
#if 0
for (i = 0; i < sf.nfiles; i++)
POOL_DEBUG(SAT_DEBUG_STATS, "looking up %s in filelist\n", id2str(pool, sf.ids[i]));
#endif
- cbd.nfiles = sf.nfiles;
- cbd.ids = sf.ids;
- cbd.dirs = sf.dirs;
- cbd.names = sf.names;
- cbd.olddata = 0;
- cbd.dids = sat_realloc2(cbd.dids, sf.nfiles, sizeof(Id));
- pool_search(pool, 0, SOLVABLE_FILELIST, 0, 0, addfileprovides_cb, &cbd);
+ pool_addfileprovides_search(pool, &cbd, &sf, 0);
+ if (idp)
+ {
+ sf.ids = sat_extend(sf.ids, sf.nfiles, 1, sizeof(Id), SEARCHFILES_BLOCK);
+ sf.ids[sf.nfiles] = 0;
+ *idp = sf.ids;
+ sf.ids = 0;
+ }
sat_free(sf.ids);
for (i = 0; i < sf.nfiles; i++)
{
for (i = 0; i < isf.nfiles; i++)
POOL_DEBUG(SAT_DEBUG_STATS, "looking up %s in installed filelist\n", id2str(pool, isf.ids[i]));
#endif
- cbd.nfiles = isf.nfiles;
- cbd.ids = isf.ids;
- cbd.dirs = isf.dirs;
- cbd.names = isf.names;
- cbd.olddata = 0;
- cbd.dids = sat_realloc2(cbd.dids, isf.nfiles, sizeof(Id));
- repo_search(installed, 0, SOLVABLE_FILELIST, 0, 0, addfileprovides_cb, &cbd);
+ pool_addfileprovides_search(pool, &cbd, &isf, installed);
sat_free(isf.ids);
for (i = 0; i < isf.nfiles; i++)
{
}
void
+pool_addfileprovides(Pool *pool, Repo *installed)
+{
+ pool_addfileprovides_ids(pool, installed, 0);
+}
+
+void
pool_search(Pool *pool, Id p, Id key, const char *match, int flags, int (*callback)(void *cbdata, Solvable *s, struct _Repodata *data, struct _Repokey *key, struct _KeyValue *kv), void *cbdata)
{
if (p)
if (sp < 0)
repo_search(pool->solvables[-sp].repo, -sp, SOLVABLE_DISKUSAGE, 0, 0, solver_fill_DU_cb, &cbd);
}
+ sat_free(cbd.dirmap);
sat_free(mptree);
}
*/
extern void pool_createwhatprovides(Pool *pool);
extern void pool_addfileprovides(Pool *pool, struct _Repo *installed);
+extern void pool_addfileprovides_ids(Pool *pool, struct _Repo *installed, Id **idp);
extern void pool_freewhatprovides(Pool *pool);
extern Id pool_queuetowhatprovides(Pool *pool, Queue *q);
static void repodata_load_solv(Repodata *data);
static void
-parse_repodata(Repodata *maindata, Id *keyp, Repokey *keys, Id *idmap, unsigned numid, unsigned numrel, Repo *repo)
+parse_external_repodata(Repodata *maindata, Id *keyp, Repokey *keys, Id *idmap, unsigned numid, unsigned numrel)
{
+ Repo *repo = maindata->repo;
Id key, id;
Id *ida, *ide;
Repodata *data;
}
/* read_idarray writes a terminating 0, that's why the + 1 */
ida = sat_calloc(keys[key].size + 1, sizeof(Id));
- ide = read_idarray(maindata, 0, 0, ida, ida + keys[key].size + 1);
+ ide = read_idarray(maindata, numid, idmap, ida, ida + keys[key].size + 1);
n = ide - ida - 1;
if (n & 1)
{
pool_debug (mypool, SAT_ERROR, "invalid attribute data\n");
- data->error = SOLV_ERROR_CORRUPT;
+ maindata->error = SOLV_ERROR_CORRUPT;
return;
}
data->nkeys = 1 + (n >> 1);
memset(data->keys, 0, sizeof(Repokey));
for (i = 1, ide = ida; i < data->nkeys; i++)
{
- if (*ide >= numid)
- {
- pool_debug (mypool, SAT_ERROR, "invalid attribute data\n");
- data->error = SOLV_ERROR_CORRUPT;
- return;
- }
- data->keys[i].name = idmap ? idmap[*ide++] : *ide++;
- data->keys[i].type = idmap ? idmap[*ide++] : *ide++;
+ data->keys[i].name = *ide++;
+ data->keys[i].type = *ide++;
data->keys[i].size = 0;
data->keys[i].storage = 0;
}
}
}
+static void
+parse_info_repodata(Repodata *maindata, Id *keyp, Repokey *keys, Id *idmap, unsigned numid, unsigned numrel)
+{
+ Id key, id;
+ Id *ida;
+ while ((key = *keyp++) != 0)
+ {
+ id = keys[key].name;
+ if (id == REPODATA_ADDEDFILEPROVIDES && keys[key].type == REPOKEY_TYPE_IDARRAY)
+ {
+ /* + 1 just in case */
+ ida = sat_calloc(keys[key].size + 1, sizeof(Id));
+ read_idarray(maindata, numid, idmap, ida, ida + keys[key].size + 1);
+ maindata->addedfileprovides = ida;
+ continue;
+ }
+ skip_item(maindata, keys[key].type, numid, numrel);
+ }
+}
+
/*-----------------------------------------------------------------*/
if (keys[key].name == REPODATA_EXTERNAL && keys[key].type == REPOKEY_TYPE_VOID)
{
/* external data for some ids */
- parse_repodata(&data, keyp, keys, idmap, numid, numrel, repo);
+ parse_external_repodata(&data, keyp, keys, idmap, numid, numrel);
+ }
+ else if (keys[key].name == REPODATA_INFO)
+ {
+ parse_info_repodata(&data, keyp, keys, idmap, numid, numrel);
}
else
- skip_schema(&data, keyp, keys, numid, numrel);
+ {
+ skip_schema(&data, keyp, keys, numid, numrel);
+ }
}
s = 0;
if (have_xdata)
- repodata_extend_block(&data, data.start, numsolv);
+ {
+ /* reserve one byte so that all offsets are not zero */
+ incore_add_id(&data, 0);
+ repodata_extend_block(&data, data.start, numsolv);
+ }
left = 0;
buf = sat_calloc(maxsize + 4, 1);
sat_free(data->attriddata);
sat_free(data->location);
+ sat_free(data->addedfileprovides);
if (data->pagefd != -1)
close(data->pagefd);
nentry = data->end - data->start;
addschema_prepare(data, schematacache);
memset(&newincore, 0, sizeof(newincore));
+ data_addid(&newincore, 0);
for (entry = 0; entry < nentry; entry++)
{
memset(seen, 0, data->nkeys * sizeof(Id));
Id *attriddata; /* their id space */
unsigned int attriddatalen;
+ Id *addedfileprovides;
} Repodata;
/* Search key <keyname> (all keys, if keyname == 0) for Id <entry>
for (p = 1; p < pool->nsolvables; p++)
if (MAPTST(&installmap, p))
queue_push(pkgs, p);
+ map_free(&installmap);
/* run through erase solvable dudata */
if (solv->installed)
{
return buf;
}
+static inline void *sat_zextend(void *buf, size_t len, size_t nmemb, size_t size, size_t block)
+{
+ buf = sat_extend(buf, len, nmemb, size, block);
+ memset(buf + len * size, 0, nmemb * size);
+ return buf;
+}
+
static inline void *sat_extend_resize(void *buf, size_t len, size_t size, size_t block)
{
if (len)
* If <basename> is given, split attributes
*/
+#define REPODATAFILE_BLOCK 15
+
int
tool_write(Repo *repo, const char *basename, const char *attrname)
{
int nlanguages = 0;
int i, j, k, l;
+ fileinfos = sat_zextend(fileinfos, nfileinfos, 1, sizeof(Repodatafile), REPODATAFILE_BLOCK);
+ pool_addfileprovides_ids(repo->pool, 0, &fileinfos[nfileinfos].addedfileprovides);
+ nfileinfos++;
+
if (basename)
{
struct keyfilter_other_data kd;
languages[nlanguages++] = strdup(keyname + l);
}
}
- fileinfos = sat_calloc(nlanguages + 2, sizeof(Repodatafile));
+ fileinfos = sat_zextend(fileinfos, nfileinfos, nlanguages + 2, sizeof(Repodatafile), REPODATAFILE_BLOCK);
/* write language subfiles */
for (i = 0; i < nlanguages; i++)
{
exit(1);
}
repo_write(repo, fp, keyfilter_language, languages[i], fileinfos + nfileinfos, 0);
- fileinfos[nfileinfos++].location = strdup(fn);
+ fileinfos[nfileinfos].location = strdup(fn);
fclose(fp);
+ nfileinfos++;
}
/* write DU subfile */
if (has_DU)
exit(1);
}
repo_write(repo, fp, keyfilter_DU, 0, fileinfos + nfileinfos, 0);
- fileinfos[nfileinfos++].location = strdup(fn);
+ fileinfos[nfileinfos].location = strdup(fn);
fclose(fp);
+ nfileinfos++;
}
/* write filelist */
if (has_FL)
exit(1);
}
repo_write(repo, fp, keyfilter_FL, 0, fileinfos + nfileinfos, 0);
- fileinfos[nfileinfos++].location = strdup(fn);
+ fileinfos[nfileinfos].location = strdup(fn);
fclose(fp);
+ nfileinfos++;
}
/* write everything else */
sprintf(fn, "%s.solv", basename);
sat_free(languages);
for (i = 0; i < nfileinfos; i++)
{
+ sat_free(fileinfos[i].addedfileprovides);
sat_free(fileinfos[i].location);
sat_free(fileinfos[i].keys);
}
}
if (attrname)
{
- fileinfos = sat_calloc(1, sizeof(Repodatafile));
+ fileinfos = sat_zextend(fileinfos, nfileinfos, 1, sizeof(Repodatafile), REPODATAFILE_BLOCK);
test_separate = 1;
FILE *fp = fopen (attrname, "w");
- repo_write(repo, fp, keyfilter_attr, 0, fileinfos + nfileinfos++, 0);
- fileinfos[nfileinfos - 1].location = strdup(attrname);
+ repo_write(repo, fp, keyfilter_attr, 0, fileinfos + nfileinfos, 0);
+ fileinfos[nfileinfos].location = strdup(attrname);
fclose(fp);
+ nfileinfos++;
}
repo_write(repo, stdout, keyfilter_solv, 0, fileinfos, nfileinfos);
- if (fileinfos)
+ for (i = 0; i < nfileinfos; i++)
{
- free(fileinfos[0].location);
- free(fileinfos[0].keys);
- free(fileinfos);
+ sat_free(fileinfos[i].addedfileprovides);
+ sat_free(fileinfos[i].location);
+ sat_free(fileinfos[i].keys);
}
+ sat_free(fileinfos);
return 0;
}
printf(" localpool has %d strings, size is %d\n", data->spool.nstrings, data->spool.sstrings);
if (data->dirpool.ndirs)
printf(" localpool has %d directories\n", data->dirpool.ndirs);
+ if (data->addedfileprovides)
+ {
+ printf(" added file provides:\n");
+ for (j = 0; data->addedfileprovides[j]; j++)
+ printf(" %s\n", id2str(repo->pool, data->addedfileprovides[j]));
+ }
printf("\n");
}
printf("\n");
Dirpool owndirpool, *dirpool;
int setfileinfo = 0;
- Id repodataschema = 0;
- Id repodataschema_internal = 0;
+ Id *repodataschemata = 0;
struct extdata *xd;
writing a subfile and our callers wants info about it. */
if (fileinfo && nsubfiles == 0)
setfileinfo = 1;
+ if (nsubfiles)
+ repodataschemata = sat_calloc(nsubfiles, sizeof(Id));
memset(&cbdata, 0, sizeof(cbdata));
cbdata.repo = repo;
}
cbdata.nmykeys = i;
- /* If we store subfile info, generate the three necessary keys. */
+ /* If we store subfile info, generate the necessary keys. */
if (nsubfiles)
{
key = cbdata.mykeys + cbdata.nmykeys;
+ key->name = REPODATA_INFO;
+ key->type = REPOKEY_TYPE_VOID;
+ key->size = 0;
+ key->storage = KEY_STORAGE_SOLVABLE;
+ cbdata.keymap[key->name] = cbdata.nmykeys++;
+
+ key = cbdata.mykeys + cbdata.nmykeys;
key->name = REPODATA_EXTERNAL;
key->type = REPOKEY_TYPE_VOID;
key->size = 0;
key->storage = KEY_STORAGE_SOLVABLE;
- cbdata.keymap[key->name] = key - cbdata.mykeys;
- key++;
+ cbdata.keymap[key->name] = cbdata.nmykeys++;
+ key = cbdata.mykeys + cbdata.nmykeys;
key->name = REPODATA_KEYS;
key->type = REPOKEY_TYPE_IDARRAY;
key->size = 0;
key->storage = KEY_STORAGE_SOLVABLE;
- cbdata.keymap[key->name] = key - cbdata.mykeys;
- key++;
+ cbdata.keymap[key->name] = cbdata.nmykeys++;
+ key = cbdata.mykeys + cbdata.nmykeys;
key->name = REPODATA_LOCATION;
key->type = REPOKEY_TYPE_STR;
key->size = 0;
key->storage = KEY_STORAGE_SOLVABLE;
- cbdata.keymap[key->name] = key - cbdata.mykeys;
- key++;
+ cbdata.keymap[key->name] = cbdata.nmykeys++;
- cbdata.nmykeys = key - cbdata.mykeys;
+ key = cbdata.mykeys + cbdata.nmykeys;
+ key->name = REPODATA_ADDEDFILEPROVIDES;
+ key->type = REPOKEY_TYPE_IDARRAY;
+ key->size = 0;
+ key->storage = KEY_STORAGE_SOLVABLE;
+ cbdata.keymap[key->name] = cbdata.nmykeys++;
}
dirpoolusage = 0;
fprintf(stderr, "dirpoolusage: %d\n", dirpoolusage);
fprintf(stderr, "nmykeys: %d\n", cbdata.nmykeys);
for (i = 1; i < cbdata.nmykeys; i++)
- fprintf(stderr, " %2d: %d %d %d %d\n", i, cbdata.mykeys[i].name, cbdata.mykeys[i].type, cbdata.mykeys[i].size, cbdata.mykeys[i].storage);
+ fprintf(stderr, " %2d: %s[%d] %d %d %d\n", i, id2str(pool, cbdata.mykeys[i].name), cbdata.mykeys[i].name, cbdata.mykeys[i].type, cbdata.mykeys[i].size, cbdata.mykeys[i].storage);
#endif
/********************************************************************/
for (i = 0; i < nsubfiles; i++)
{
int j;
+ Id schema[4], *sp;
- if (fileinfo[i].location && !repodataschema)
- {
- Id schema[4];
- schema[0] = cbdata.keymap[REPODATA_EXTERNAL];
- schema[1] = cbdata.keymap[REPODATA_KEYS];
- schema[2] = cbdata.keymap[REPODATA_LOCATION];
- schema[3] = 0;
- repodataschema = addschema(&cbdata, schema);
+ sp = schema;
+ if (fileinfo[i].addedfileprovides)
+ {
+ /* extra info about this file */
+ *sp++ = cbdata.keymap[REPODATA_INFO];
+ *sp++ = cbdata.keymap[REPODATA_ADDEDFILEPROVIDES];
+ for (j = 0; fileinfo[i].addedfileprovides[j]; j++)
+ j++;
+ cbdata.mykeys[cbdata.keymap[REPODATA_ADDEDFILEPROVIDES]].size += j + 1;
}
- else if (!repodataschema_internal)
- {
- Id schema[3];
- schema[0] = cbdata.keymap[REPODATA_EXTERNAL];
- schema[1] = cbdata.keymap[REPODATA_KEYS];
- schema[2] = 0;
- repodataschema_internal = addschema(&cbdata, schema);
+ else
+ {
+ *sp++ = cbdata.keymap[REPODATA_EXTERNAL];
+ *sp++ = cbdata.keymap[REPODATA_KEYS];
+ if (fileinfo[i].location)
+ *sp++ = cbdata.keymap[REPODATA_LOCATION];
}
- if (2 * fileinfo[i].nkeys > cbdata.mykeys[cbdata.keymap[REPODATA_KEYS]].size)
- cbdata.mykeys[cbdata.keymap[REPODATA_KEYS]].size = 2 * fileinfo[i].nkeys;
+ *sp = 0;
+ repodataschemata[i] = addschema(&cbdata, schema);
+ cbdata.mykeys[cbdata.keymap[REPODATA_KEYS]].size += 2 * fileinfo[i].nkeys + 1;
for (j = 1; j < fileinfo[i].nkeys; j++)
{
needid[fileinfo[i].keys[j].type].need++;
needid[fileinfo[i].keys[j].name].need++;
}
-#if 0
- fprintf (stderr, " %d nkeys: %d:", i, fileinfo[i].nkeys);
- for (j = 1; j < fileinfo[i].nkeys; j++)
- {
- needid[fileinfo[i].keys[j].name].need++;
- fprintf (stderr, " %s(%d,%d)", id2str(pool, fileinfo[i].keys[j].name),
- fileinfo[i].keys[j].name, fileinfo[i].keys[j].type);
- }
- fprintf (stderr, "\n");
-#endif
}
- if (nsubfiles)
- cbdata.mykeys[cbdata.keymap[REPODATA_KEYS]].size -= 2;
/********************************************************************/
int j;
cur = xd.len;
- if (fileinfo[i].location)
- data_addid(&xd, repodataschema);
+ data_addid(&xd, repodataschemata[i]);
+ if (fileinfo[i].addedfileprovides)
+ {
+ for (j = 0; fileinfo[i].addedfileprovides[j]; j++)
+ data_addideof(&xd, needid[fileinfo[i].addedfileprovides[j]].need, fileinfo[i].addedfileprovides[j + 1] ? 0 : 1);
+ }
else
- data_addid(&xd, repodataschema_internal);
- /* key,type array + location, write idarray */
- for (j = 1; j < fileinfo[i].nkeys; j++)
{
- data_addideof(&xd, needid[fileinfo[i].keys[j].name].need, 0);
- data_addideof(&xd, needid[fileinfo[i].keys[j].type].need, j == fileinfo[i].nkeys - 1);
+ /* key,type array + location, write idarray */
+ for (j = 1; j < fileinfo[i].nkeys; j++)
+ {
+ data_addideof(&xd, needid[fileinfo[i].keys[j].name].need, 0);
+ data_addideof(&xd, needid[fileinfo[i].keys[j].type].need, j == fileinfo[i].nkeys - 1);
+ }
+ if (fileinfo[i].location)
+ data_addblob(&xd, (unsigned char *)fileinfo[i].location, strlen(fileinfo[i].location) + 1);
}
- if (fileinfo[i].location)
- data_addblob(&xd, (unsigned char *)fileinfo[i].location, strlen(fileinfo[i].location) + 1);
cur = xd.len - cur;
if (cur > max)
max = cur;
sat_free(cbdata.keymapstart);
sat_free(cbdata.dirused);
sat_free(repodataused);
+ sat_free(repodataschemata);
}
unsigned checksumtype;
struct _Repokey *keys;
unsigned int nkeys;
+ Id *addedfileprovides;
} Repodatafile;
void repo_write(Repo *repo, FILE *fp, int (*keyfilter)(Repo *repo, Repokey *key, void *kfdata), void *kfdata, Repodatafile *fileinfo, int nsubfiles);