side. Try "susetags2solv -as" to play (e.g. with dumpsolv).
//-----------------------------------------------
struct _Repo;
+struct _Repodata;
struct _Pool {
struct _Stringpool ss;
int debugmask;
void (*debugcallback)(struct _Pool *, void *data, int type, const char *str);
void *debugcallbackdata;
+
+ /* load callback */
+ FILE * (*loadcallback)(struct _Pool *, struct _Repodata *, void *);
+ void *loadcallbackdata;
};
#define SAT_FATAL (1<<0)
pool->debugmask = mask;
}
+static inline void pool_setloadcallback(Pool *pool, FILE *(*cb)(struct _Pool *, struct _Repodata *, void *), void *loadcbdata)
+{
+ pool->loadcallback = cb;
+ pool->loadcallbackdata = loadcbdata;
+}
+
/* loop over all providers of d */
#define FOR_PROVIDES(v, vp, d) \
for (vp = pool_whatprovides(pool, d) ; (v = *vp++) != 0; )
return data;
}
-static Repodata *findrepodata(Repo *repo, Id p, Id keyname)
+static Repodata *
+findrepodata(Repo *repo, Id p, Id keyname)
{
int i;
Repodata *data;
skip_item(maindata, TYPE_IDVALUEARRAY, numid, numrel);
break;
}
- ida = sat_calloc(keys[key].size, sizeof(Id));
- ide = read_idarray(maindata, 0, 0, ida, ida + keys[key].size, 0);
+ /* 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, 0);
n = ide - ida - 1;
if (n & 1)
{
unsigned len = sizeof (buf);
char *filename = buf;
read_str(maindata, &filename, &len);
-#if 0
data->location = strdup(filename);
-#endif
if (filename != buf)
free(filename);
}
pool_debug(pool, SAT_ERROR, "relations are forbidden in a store\n");
return SOLV_ERROR_CORRUPT;
}
- if (numsolv)
+ if (parent->end - parent->start != numsolv)
{
- pool_debug(pool, SAT_ERROR, "solvables are forbidden in a store\n");
+ pool_debug(pool, SAT_ERROR, "unequal number of solvables in a store\n");
return SOLV_ERROR_CORRUPT;
}
if (numinfo)
spool = &pool->ss;
else
{
+ data.localpool = 1;
spool = &data.spool;
spool->stringspace = sat_malloc(7);
strcpy(spool->stringspace, "<NULL>");
{
/* no shared pool, thus no idmap and no unification */
idmap = 0;
- sp += 7;
- if (*sp)
+ if (0 && *sp)
{
pool_debug(pool, SAT_ERROR, "store strings don't start with ''\n");
return SOLV_ERROR_CORRUPT;
}
+ spool->nstrings = numid;
str[0] = 0;
for (i = 1; i < spool->nstrings; i++)
{
pool_debug(pool, SAT_ERROR, "not enough strings\n");
return SOLV_ERROR_OVERFLOW;
}
- str[i] = sp - strsp;
+ str[i] = sp - spool->stringspace;
sp += strlen(sp) + 1;
}
+ spool->sstrings = sp - spool->stringspace;
}
else
{
id = read_id(&data, numid);
if (idmap)
id = idmap[id];
+ else if (parent)
+ id = str2id(pool, stringpool_id2str(spool, id), 1);
keys[i].name = id;
keys[i].type = read_id(&data, 0);
keys[i].size = read_id(&data, 0);
+#if 0
+ fprintf (stderr, "key %d %s %d %d\n", i, id2str(pool,id), keys[i].type,
+ keys[i].size);
+#endif
if (solvversion >= SOLV_VERSION_5)
{
keys[i].storage = read_id(&data, 0);
{
schemata[i] = schemadatap - schemadata;
schemadatap = read_idarray(&data, numid, 0, schemadatap, schemadataend, 0);
+#if 0
+ Id *sp = schemadata + schemata[i];
+ fprintf (stderr, "schema %d:", i);
+ for (; *sp; sp++)
+ fprintf (stderr, " %d", *sp);
+ fprintf (stderr, "\n");
+#endif
}
data.schemata = schemata;
data.nschemata = numschemata;
}
/* read solvables */
- if (numsolv)
+ if (parent)
+ {
+ data.start = parent->start;
+ data.end = parent->end;
+ s = pool_id2solvable(pool, data.start);
+ }
+ else if (numsolv)
{
s = pool_id2solvable(pool, repo_add_solvable_block(repo, numsolv));
/* store start and end of our id block */
data.start = s - pool->solvables;
data.end = data.start + numsolv;
+ /* In case we have subfiles, make them refer to our part of the
+ repository now. */
+ for (i = 0; i < repo->nrepodata; i++)
+ {
+ repo->repodata[i].start = data.start;
+ repo->repodata[i].end = data.end;
+ }
}
else
s = 0;
repodata_load_solv(Repodata *data)
{
FILE *fp;
-#if 0
+#if 1
Pool *pool = data->repo->pool;
if (!pool->loadcallback)
{
data->state = REPODATA_ERROR;
return;
}
- fp = pool->loadcallback(pool->loadcallback_data, pool, data);
+ fp = pool->loadcallback(pool, data, pool->loadcallbackdata);
#else
fp = 0;
#endif
return 0;
}
+static inline int
+maybe_load_repodata(Repodata *data)
+{
+ if (data->state == REPODATA_STUB)
+ {
+ if (data->loadcallback)
+ data->loadcallback(data);
+ else
+ data->state = REPODATA_ERROR;
+ }
+ if (data->state == REPODATA_AVAILABLE)
+ return 1;
+ data->state = REPODATA_ERROR;
+ return 0;
+}
const char *
repodata_lookup_str(Repodata *data, Id entry, Id keyid)
Id id, *keyp;
unsigned char *dp;
+ if (!maybe_load_repodata (data))
+ return 0;
+
dp = data->incoredata + data->incoreoffset[entry];
dp = data_read_id(dp, &schema);
/* make sure the schema of this solvable contains the key */
unsigned char *dp;
*value = 0;
+
+ if (!maybe_load_repodata (data))
+ return 0;
+
dp = data->incoredata + data->incoreoffset[entry];
dp = data_read_id(dp, &schema);
/* make sure the schema of this solvable contains the key */
int stop;
KeyValue kv;
+ if (!maybe_load_repodata (data))
+ return;
+
dp = data->incoredata + data->incoreoffset[entry];
dp = data_read_id(dp, &schema);
keyp = data->schemadata + data->schemata[schema];
typedef struct _Repodata {
struct _Repo *repo; /* back pointer to repo */
+#define REPODATA_AVAILABLE 0
+#define REPODATA_STUB 1
+#define REPODATA_ERROR 2
+#define REPODATA_STORE 3
int state; /* available, stub or error */
void (*loadcallback)(struct _Repodata *);
+ char *location; /* E.g. filename or the like */
+ char *checksum; /* Checksum of the file */
+ unsigned nchecksum; /* Length of the checksum */
+ unsigned checksumtype; /* Type of checksum */
int start; /* start of solvables this repodata is valid for */
int end; /* last solvable + 1 of this repodata */
} Repodata;
-#define REPODATA_AVAILABLE 0
-#define REPODATA_STUB 1
-#define REPODATA_ERROR 2
-#define REPODATA_STORE 3
void repodata_search(Repodata *data, Id entry, Id keyname, int (*callback)(void *cbdata, Solvable *s, Repodata *data, struct _Repokey *key, struct _KeyValue *kv), void *cbdata);
const char *repodata_lookup_str(Repodata *data, Id entry, Id keyid);
Pool *pool = pool_create();
Repo *repo = repo_create(pool, "<stdin>");
repo_add_content(repo, stdin);
- repo_write(repo, stdout, 0, 0);
+ repo_write(repo, stdout, 0, 0, 0, 0);
pool_free(pool);
return 0;
}
dump_attrs_1 (s, entry);
}
}
+#endif
static void
dump_repodata (Repo *repo)
Repodata *data;
if (repo->nrepodata == 0)
return;
- printf("repo refers to %d attribute stores:\n", repo->nrepodata);
+ printf("repo refers to %d subfiles:\n", repo->nrepodata);
for (i = 0, data = repo->repodata; i < repo->nrepodata; i++, data++)
{
unsigned int j;
printf("%s has %d keys", data->location ? data->location : "**EMBED**", data->nkeys);
- for (j = 0; j < data->nkeys; j++)
+ for (j = 1; j < data->nkeys; j++)
printf("\n %s", id2str(repo->pool, data->keys[j].name));
printf("\n");
}
printf("\n");
}
-#endif
static void
printids(Repo *repo, char *kind, Offset ido)
}
}
+void
+dump_some_attrs(Repo *repo, Solvable *s)
+{
+ Id name = str2id (repo->pool, "summary", 0);
+ const char *summary = 0;
+ unsigned int medianr = -1, downloadsize = -1;
+ unsigned int time = -1;
+ if (name)
+ summary = repo_lookup_str (s, name);
+ if ((name = str2id (repo->pool, "medianr", 0)))
+ medianr = repo_lookup_num (s, name);
+ if ((name = str2id (repo->pool, "downloadsize", 0)))
+ downloadsize = repo_lookup_num (s, name);
+ if ((name = str2id (repo->pool, "time", 0)))
+ time = repo_lookup_num (s, name);
+
+ printf (" XXX %d %d %u %s\n", medianr, downloadsize, time, summary);
+}
+
+static FILE *
+loadcallback (Pool *pool, Repodata *data, void *vdata)
+{
+ FILE *fp;
+ fprintf (stderr, "Loading SOLV file %s\n", data->location);
+ fp = fopen ("test.attr", "r");
+ return fp;
+}
+
int main(int argc, char **argv)
{
Repo *repo;
}
pool = pool_create();
pool_setdebuglevel(pool, 1);
+ pool_setloadcallback(pool, loadcallback, 0);
repo = repo_create(pool, argc != 1 ? argv[1] : "<stdin>");
if (repo_add_solv(repo, stdin))
printf("could not read repository\n");
-#if 0
dump_repodata (repo);
-#endif
printf("repo contains %d solvables\n", repo->nsolvables);
for (i = repo->start, n = 1; i < repo->end; i++)
{
dump_attrs (repo, n - 1);
#endif
dump_repoattrs(repo, i);
+#if 1
+ dump_some_attrs(repo, s);
+#endif
n++;
}
pool_free(pool);
Pool *pool = pool_create();
Repo *repo = repo_create(pool, "<stdin>");
repo_add_helix(repo, stdin);
- repo_write(repo, stdout, 0, 0);
+ repo_write(repo, stdout, 0, 0, 0, 0);
pool_free(pool);
exit(0);
}
}
create_filter(pool);
- repo_write(repo, stdout, keyfilter, 0);
+ repo_write(repo, stdout, keyfilter, 0, 0, 0);
pool_free(pool);
return 0;
Pool *pool = pool_create();
Repo *repo = repo_create(pool, "<stdin>");
repo_add_patchxml(repo, stdin);
- repo_write(repo, stdout, 0, 0);
+ repo_write(repo, stdout, 0, 0, 0, 0);
pool_free(pool);
exit(0);
}
case CTAG('=', 'P', 's', 'g'):
s->suggests = adddep(pool, &pd, s->suggests, line, 0, 0);
continue;
+ case CTAG('=', 'V', 'e', 'r'):
+ last_found_pack = 0;
+ indesc++;
+ continue;
}
if (!with_attr)
continue;
case CTAG('=', 'D', 'i', 'r'):
add_dirline (&pd, line + 6);
continue;
- case CTAG('=', 'V', 'e', 'r'):
- last_found_pack = 0;
- indesc++;
- continue;
}
}
if (s && s->arch != ARCH_SRC && s->arch != ARCH_NOSRC)
}
}
+static unsigned id_bytes;
+
/*
* Id
*/
}
}
-#if 0
+#if 1
static void
write_str(FILE *fp, const char *str)
{
continue;
if (sib == 1 && parent == 1)
continue; /* already did that one above */
+assert (sib < dp->ndirs);
dirmap[n++] = sib;
}
lastn = n;
*/
void
-repo_write(Repo *repo, FILE *fp, int (*keyfilter)(Repo *repo, Repokey *key, void *kfdata), void *kfdata)
+repo_write(Repo *repo, FILE *fp, int (*keyfilter)(Repo *repo, Repokey *key, void *kfdata), void *kfdata, Repodatafile *fileinfo, int nsubfiles)
{
Pool *pool = repo->pool;
int i, j, k, n;
Stringpool ownspool, *spool;
Dirpool owndirpool, *dirpool;
+ int setfileinfo = 0;
+ Id repodataschema = 0;
+ Id repodataschema_internal = 0;
+
+ /* If we're given a fileinfo structure, but have no subfiles, then we're
+ writing a subfile and our callers wants info about it. */
+ if (fileinfo && nsubfiles == 0)
+ setfileinfo = 1;
+
memset(&cbdata, 0, sizeof(cbdata));
/* go through all repodata and find the keys we need */
}
cbdata.nmykeys = i;
+ /* If we store subfile info, generate the three necessary keys. */
+ if (nsubfiles)
+ {
+ key = cbdata.mykeys + cbdata.nmykeys;
+ key->name = REPODATA_EXTERNAL;
+ key->type = TYPE_VOID;
+ key->size = 0;
+ key->storage = KEY_STORAGE_SOLVABLE;
+ cbdata.keymap[key->name] = key - cbdata.mykeys;
+ key++;
+
+ key->name = REPODATA_KEYS;
+ key->type = TYPE_IDVALUEARRAY;
+ key->size = 0;
+ key->storage = KEY_STORAGE_SOLVABLE;
+ cbdata.keymap[key->name] = key - cbdata.mykeys;
+ key++;
+
+ key->name = REPODATA_LOCATION;
+ key->type = TYPE_STR;
+ key->size = 0;
+ key->storage = KEY_STORAGE_SOLVABLE;
+ cbdata.keymap[key->name] = key - cbdata.mykeys;
+ key++;
+
+ cbdata.nmykeys = key - cbdata.mykeys;
+ }
+
dirpoolusage = 0;
spool = 0;
reloff = needid[0].map;
+ /* If we have fileinfos to write, setup schemas and increment needid[]
+ of the right strings. */
+ for (i = 0; i < nsubfiles; i++)
+ {
+ int j;
+
+ 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);
+ }
+ 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);
+ }
+ if (2 * fileinfo[i].nkeys > cbdata.mykeys[cbdata.keymap[REPODATA_KEYS]].size)
+ cbdata.mykeys[cbdata.keymap[REPODATA_KEYS]].size = 2 * fileinfo[i].nkeys;
+ for (j = 1; j < fileinfo[i].nkeys; j++)
+ 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;
/********************************************************************/
write_u32(fp, repo->nsolvables);
write_u32(fp, cbdata.nmykeys);
write_u32(fp, cbdata.nmyschemata);
- write_u32(fp, 0); /* info blocks. */
+ write_u32(fp, nsubfiles); /* info blocks. */
solv_flags = 0;
solv_flags |= SOLV_FLAG_PREFIX_POOL;
#if 0
/*
* write keys
*/
+ if (setfileinfo)
+ {
+ fileinfo->nkeys = cbdata.nmykeys;
+ fileinfo->keys = sat_calloc (fileinfo->nkeys, sizeof (*fileinfo->keys));
+ }
for (i = 1; i < cbdata.nmykeys; i++)
{
write_id(fp, needid[cbdata.mykeys[i].name].need);
else
write_id(fp, cbdata.extdata[i].len);
write_id(fp, cbdata.mykeys[i].storage);
+ if (setfileinfo)
+ fileinfo->keys[i] = cbdata.mykeys[i];
}
/*
write_idarray(fp, pool, 0, cbdata.myschemadata + cbdata.myschemata[i]);
}
-#if 0
/*
* write info block
*/
- for (i = 0; i < repo->nrepodata; i++)
+ for (i = 0; i < nsubfiles; i++)
{
int j;
- if (repo->repodata[i].location)
+ if (fileinfo[i].location)
write_id(fp, repodataschema);
else
write_id(fp, repodataschema_internal);
/* keys + location, write idarray */
- for (j = 0; j < repo->repodata[i].nkeys; j++)
+ for (j = 1; j < fileinfo[i].nkeys; j++)
{
- Id id = needid[repo->repodata[i].keys[j].name].need;
- write_id_value(fp, id, repo->repodata[i].keys[j].type, j == repo->repodata[i].nkeys - 1);
+
+ Id id = needid[fileinfo[i].keys[j].name].need;
+#if 0
+ fprintf (stderr, "writing %d(%s) %d\n", id,
+ id2str(pool, needid[id].map),
+ fileinfo[i].keys[j].type);
+#endif
+ write_id_value(fp, id, fileinfo[i].keys[j].type, j == fileinfo[i].nkeys - 1);
}
- if (repo->repodata[i].location)
- write_str(fp, repo->repodata[i].location);
+ if (fileinfo[i].location)
+ write_str(fp, fileinfo[i].location);
}
-#endif
/********************************************************************/
{
if (s->repo != repo)
continue;
+ id_bytes = 0;
/* keep in sync with schema generation! */
write_id(fp, cbdata.solvschemata[n]);
#if 0
if (s->freshens && cbdata.keymap[SOLVABLE_FRESHENS])
write_idarray_sort(fp, pool, needid, idarraydata + s->freshens);
if (repo->rpmdbid && cbdata.keymap[RPM_RPMDBID])
- write_u32(fp, repo->rpmdbid[i - repo->start]);
+ write_u32(fp, repo->rpmdbid[i - repo->start]),id_bytes+=4;
if (cbdata.incorelen[n])
{
write_blob(fp, incoredata, cbdata.incorelen[n]);
incoredata += cbdata.incorelen[n];
+ id_bytes += cbdata.incorelen[n];
}
n++;
}
write_blob(fp, cbdata.extdata[i].buf, cbdata.extdata[i].len);
#endif
+ /* Fill fileinfo for our caller. */
+ if (setfileinfo)
+ {
+ fileinfo->checksum = 0;
+ fileinfo->nchecksum = 0;
+ fileinfo->checksumtype = 0;
+ fileinfo->location = 0;
+ }
+
for (i = 1; i < cbdata.nmykeys; i++)
sat_free(cbdata.extdata[i].buf);
sat_free(cbdata.myschemadata);
sat_free(cbdata.myschemata);
}
-
-// EOF
#include "pool.h"
#include "repo.h"
-void repo_write(Repo *repo, FILE *fp, int (*keyfilter)(Repo *repo, Repokey *key, void *kfdata), void *kfdata);
+/* Describes a repodata file */
+typedef struct _Repodatafile
+{
+ /* These have the same meaning as the equally named fields in
+ Repodata. */
+ char *location;
+ char *checksum;
+ unsigned nchecksum;
+ unsigned checksumtype;
+ struct _Repokey *keys;
+ unsigned int nkeys;
+} Repodatafile;
+
+void repo_write(Repo *repo, FILE *fp, int (*keyfilter)(Repo *repo, Repokey *key, void *kfdata), void *kfdata, Repodatafile *fileinfo, int nsubfiles);
#endif
ref = 0;
}
- repo_write(repo, stdout, 0, 0);
+ repo_write(repo, stdout, 0, 0, 0, 0);
pool_free(pool);
exit(0);
Pool *pool = pool_create();
Repo *repo = repo_create(pool, "<stdin>");
repo_add_rpmmd(repo, stdin);
- repo_write(repo, stdout, 0, 0);
+ repo_write(repo, stdout, 0, 0, 0, 0);
pool_free(pool);
exit(0);
}
}
}
+static int test_separate = 0;
+
static int
-keyfilter(Repo *data, Repokey *key, void *kfdata)
+keyfilter_solv(Repo *data, Repokey *key, void *kfdata)
{
+ if (test_separate && key->storage != KEY_STORAGE_SOLVABLE)
+ return KEY_STORAGE_DROPPED;
+ if (key->name < nfilter && filter[key->name])
+ return KEY_STORAGE_VERTICAL_OFFSET;
+ return KEY_STORAGE_INCORE;
+}
+
+static int
+keyfilter_attr(Repo *data, Repokey *key, void *kfdata)
+{
+ if (key->storage == KEY_STORAGE_SOLVABLE)
+ return KEY_STORAGE_DROPPED;
if (key->name < nfilter && filter[key->name])
return KEY_STORAGE_VERTICAL_OFFSET;
return KEY_STORAGE_INCORE;
int
main(int argc, char **argv)
{
+ Repodatafile fileinfoa[1];
+ Repodatafile *fileinfo = 0;
+ int nsubfiles = 0;
int with_attr = 0;
argv++;
argc--;
switch (*s++)
{
case 'a': with_attr = 1; break;
+ case 's': test_separate = 1; break;
default : break;
}
argv++;
Repo *repo = repo_create(pool, "<stdin>");
repo_add_susetags(repo, stdin, 0, with_attr);
create_filter(pool);
- repo_write(repo, stdout, keyfilter, 0);
+ memset (fileinfoa, 0, sizeof fileinfoa);
+ if (with_attr && test_separate)
+ {
+ fileinfo = fileinfoa;
+ FILE *fp = fopen ("test.attr", "w");
+ repo_write(repo, fp, keyfilter_attr, 0, fileinfo, 0);
+ fclose (fp);
+ fileinfo->location = strdup ("test.attr");
+ fileinfo++;
+
+ nsubfiles = fileinfo - fileinfoa;
+ fileinfo = fileinfoa;
+ }
+ repo_write(repo, stdout, keyfilter_solv, 0, fileinfo, nsubfiles);
#if 0
if (with_attr && attr)
{