From: Michael Matz Date: Sat, 8 Dec 2007 04:58:04 +0000 (+0000) Subject: Pfeww. I'm tired, but now you can add refers from repo SOLV files to X-Git-Tag: BASE-SuSE-Code-12_1-Branch~1062 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=d531ff2799ea9cbd4fa2817988054cb0e8a66f18;p=platform%2Fupstream%2Flibsolv.git Pfeww. I'm tired, but now you can add refers from repo SOLV files to attribute store files. Good night. (Like so: % addstore bla.solv ding.attr dong.attr > bla2.solv % dumpsolv bla2.solv repo refers to 2 attribute stores: ding.attr has 4 keys authors group keywords license dong.attr has 4 keys authors keywords license ... ) --- diff --git a/src/pool.h b/src/pool.h index 027d49b..45e0813 100644 --- a/src/pool.h +++ b/src/pool.h @@ -134,7 +134,8 @@ struct _Pool { #define TYPE_ATTR_LOCALIDS 10 #define TYPE_COUNT_NAMED 11 -#define TYPE_ATTR_TYPE_MAX 11 +#define TYPE_COUNTED 12 +#define TYPE_ATTR_TYPE_MAX 12 //----------------------------------------------- diff --git a/src/repo.c b/src/repo.c index f8f2d34..76d9e9f 100644 --- a/src/repo.c +++ b/src/repo.c @@ -554,26 +554,43 @@ key_cmp (const void *pa, const void *pb) } void -repo_add_attrstore (Repo *repo, Attrstore *s) +repo_add_attrstore (Repo *repo, Attrstore *s, const char *name) { unsigned i; Repodata *data; + /* If this is meant to be the embedded attributes, make sure we don't + have them already. */ + if (!name) + { + for (i = 0; i < repo->nrepodata; i++) + if (repo->repodata[i].name == 0) + break; + if (i != repo->nrepodata) + { + pool_debug (repo->pool, SAT_FATAL, "embedded attribs added twice\n"); + exit (1); + } + } repo->nrepodata++; repo->repodata = xrealloc (repo->repodata, repo->nrepodata * sizeof (*data)); data = repo->repodata + repo->nrepodata - 1; memset (data, 0, sizeof (*data)); data->s = s; data->nkeys = s->nkeys; - if (s->nkeys) + /* Don't store the first key, it's {0,0,0}. */ + data->nkeys--; + if (data->nkeys) { data->keys = xmalloc (data->nkeys * sizeof (data->keys[0])); for (i = 0; i < data->nkeys; i++) { - data->keys[i].name = s->keys[i].name; - data->keys[i].type = s->keys[i].type; + data->keys[i].name = s->keys[i + 1].name; + data->keys[i].type = s->keys[i + 1].type; } qsort (data->keys, data->nkeys, sizeof (data->keys[0]), key_cmp); } + if (name) + data->name = strdup (name); } // EOF diff --git a/src/repo.h b/src/repo.h index 39e3c49..597287c 100644 --- a/src/repo.h +++ b/src/repo.h @@ -32,8 +32,9 @@ typedef struct _Repodata { /* The attribute store itself. */ Attrstore *s; /* A filename where to find this attribute store, or where to store - it. May be NULL, in which case we can't load it on demand or store - into it. */ + it. May be "", in which case we can't load it on demand or store + into it. It may also be NULL for at most one of the repodata per + repo, in which case these are the embedded attributes. */ const char *name; /* The SHA1 checksum of the file. */ unsigned char checksum[20]; @@ -69,7 +70,7 @@ extern Offset repo_addid_dep(Repo *repo, Offset olddeps, Id id, int isreq); extern Offset repo_reserve_ids(Repo *repo, Offset olddeps, int num); extern Offset repo_fix_legacy(Repo *repo, Offset provides, Offset supplements); -extern void repo_add_attrstore (Repo *repo, Attrstore *s); +extern void repo_add_attrstore (Repo *repo, Attrstore *s, const char *name); static inline const char *repo_name(const Repo *repo) { diff --git a/src/repo_solv.c b/src/repo_solv.c index 7a9bda8..aebbb38 100644 --- a/src/repo_solv.c +++ b/src/repo_solv.c @@ -183,6 +183,42 @@ read_idarray(FILE *fp, Id max, Id *map, Id *store, Id *end, int relative) } } +static void +read_str (FILE *fp, char **inbuf, unsigned *len) +{ + unsigned char *buf = (unsigned char*)*inbuf; + if (!buf) + { + buf = xmalloc (1024); + *len = 1024; + } + int c; + unsigned ofs = 0; + while((c = getc (fp)) != 0) + { + if (c == EOF) + { + pool_debug (mypool, SAT_FATAL, "unexpected EOF\n"); + exit (1); + } + /* Plus 1 as we also want to add the 0. */ + if (ofs + 1 >= *len) + { + *len += 256; + /* Don't realloc on the inbuf, it might be on the stack. */ + if (buf == (unsigned char*)*inbuf) + { + buf = xmalloc (*len); + memcpy (buf, *inbuf, *len - 256); + } + else + buf = xrealloc (buf, *len); + } + buf[ofs++] = c; + } + buf[ofs++] = 0; + *inbuf = (char*)buf; +} static void skip_item (FILE *fp, unsigned type, Id *idmap, unsigned numid, unsigned numrel) @@ -216,6 +252,14 @@ skip_item (FILE *fp, unsigned type, Id *idmap, unsigned numid, unsigned numrel) } } break; + case TYPE_COUNTED: + { + unsigned count = read_id (fp, 0); + unsigned t = read_id (fp, TYPE_ATTR_TYPE_MAX + 1); + while (count--) + skip_item (fp, t, idmap, numid, numrel); + } + break; case TYPE_ATTR_CHUNK: read_id(fp, 0); /* Fallthrough. */ @@ -233,6 +277,89 @@ skip_item (FILE *fp, unsigned type, Id *idmap, unsigned numid, unsigned numrel) } } +static int +key_cmp (const void *pa, const void *pb) +{ + struct key { Id name; unsigned type; }; + struct key *a = (struct key*)pa; + struct key *b = (struct key*)pb; + return a->name - b->name; +} + +static void +parse_repodata (FILE *fp, Id *idmap, unsigned numid, unsigned numrel, Repo *repo) +{ + unsigned count = read_id (fp, 0); + + while (count--) + { + Repodata *data; + read_id (fp, numid); /* no name */ + unsigned type = read_id (fp, TYPE_ATTR_TYPE_MAX + 1); + if (type != TYPE_COUNT_NAMED) + { + skip_item (fp, type, idmap, numid, numrel); + continue; + } + unsigned c = read_id (fp, 0); + if (c == 0) + continue; + if (c != 2) + { + pool_debug (mypool, SAT_FATAL, "invalid attribute data\n"); + exit (1); + } + read_id (fp, numid); /* no name */ + if (read_id (fp, TYPE_ATTR_TYPE_MAX + 1) != TYPE_STR) + { + pool_debug (mypool, SAT_FATAL, "invalid attribute data\n"); + exit (1); + } + char buf[1024]; + unsigned len = sizeof (buf); + char *filename = buf; + read_str (fp, &filename, &len); + + read_id (fp, numid); /* no name */ + if (read_id (fp, TYPE_ATTR_TYPE_MAX + 1) != TYPE_COUNTED) + { + pool_debug (mypool, SAT_FATAL, "invalid attribute data\n"); + exit (1); + } + + unsigned nkeys = read_id (fp, 0); + if ((nkeys & 1) != 0 + || read_id (fp, TYPE_ATTR_TYPE_MAX + 1) != TYPE_ID) + { + pool_debug (mypool, SAT_FATAL, "invalid attribute data\n"); + exit (1); + } + nkeys >>= 1; + + repo->nrepodata++; + data = xrealloc (repo->repodata, repo->nrepodata * sizeof (*data)); + repo->repodata = data; + data += repo->nrepodata - 1; + memset (data, 0, sizeof (*data)); + data->nkeys = nkeys; + if (data->nkeys) + { + unsigned i; + data->keys = xmalloc (data->nkeys * sizeof (data->keys[0])); + for (i = 0; i < data->nkeys; i++) + { + data->keys[i].name = idmap[read_id (fp, numid)]; + data->keys[i].type = read_id (fp, 0); + } + qsort (data->keys, data->nkeys, sizeof (data->keys[0]), key_cmp); + } + data->name = strdup (filename); + + if (filename != buf) + xfree (filename); + } +} + /*-----------------------------------------------------------------*/ struct key { @@ -572,7 +699,7 @@ repo_add_solv(Repo *repo, FILE *fp) unsigned type = read_id (fp, TYPE_ATTR_TYPE_MAX + 1); if (type == TYPE_COUNT_NAMED && !strcmp (id2str (pool, name), "repodata")) - skip_item (fp, type, idmap, numid, numrel); + parse_repodata (fp, idmap, numid, numrel, repo); else skip_item (fp, type, idmap, numid, numrel); } @@ -814,7 +941,8 @@ repo_add_solv(Repo *repo, FILE *fp) attr_store_pack (embedded_store); /* If we have any attributes we also have pages. */ read_or_setup_pages (fp, embedded_store); - repo_add_attrstore (repo, embedded_store); + /* The NULL name here means embedded attributes. */ + repo_add_attrstore (repo, embedded_store, NULL); } xfree(idmap); xfree(schemata); diff --git a/tools/CMakeLists.txt b/tools/CMakeLists.txt index 4ce98bd..f338e7b 100644 --- a/tools/CMakeLists.txt +++ b/tools/CMakeLists.txt @@ -47,6 +47,9 @@ SET(dumpattr_REPOS dumpattr.c) ADD_EXECUTABLE( dumpattr ${dumpattr_REPOS} ) TARGET_LINK_LIBRARIES( dumpattr satsolver) +ADD_EXECUTABLE( addstore addstore.c repo_write.c ) +TARGET_LINK_LIBRARIES( addstore satsolver ) + install(TARGETS dumpattr mergesolv dumpsolv @@ -55,6 +58,7 @@ install(TARGETS dumpattr helix2solv rpmmd2solv rpmdb2solv + addstore DESTINATION ${BIN_INSTALL_DIR} ) install(PROGRAMS repo2solv.sh DESTINATION ${BIN_INSTALL_DIR} ) diff --git a/tools/addstore.c b/tools/addstore.c new file mode 100644 index 0000000..22d09bd --- /dev/null +++ b/tools/addstore.c @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2007, Novell Inc. + * + * This program is licensed under the BSD license, read LICENSE.BSD + * for further information + */ + +#include +#include +#include +#include + +#include "pool.h" +#include "repo_solv.h" +#include "repo_write.h" +#include "attr_store.h" +#include "attr_store_p.h" + +int +main(int argc, char **argv) +{ + Repo *repo; + Pool *pool; + int i; + FILE *fp; + + if (argc == 1) + { + printf ("%s repo.solv one.attr [more.attr ...] > out.solv\n", argv[0]); + exit (1); + } + if ((fp = fopen (argv[1], "r")) == 0) + { + perror (argv[1]); + exit (1); + } + pool = pool_create (); + repo = repo_create (pool, argv[1]); + repo_add_solv (repo, fp); + fclose (fp); + for (i = 2; i < argc; i++) + { + if ((fp = fopen (argv[i], "r")) == 0) + { + perror (argv[1]); + exit (1); + } + Attrstore *s = attr_store_read (fp, pool); + fclose (fp); + /* XXX We should probably use the basename here. + And calculate the SHA1 sum of the file and store it. */ + repo_add_attrstore (repo, s, argv[i]); + } + repo_write(repo, stdout); + pool_free(pool); + exit(0); +} diff --git a/tools/dumpsolv.c b/tools/dumpsolv.c index 8cbbc2f..c2b05f9 100644 --- a/tools/dumpsolv.c +++ b/tools/dumpsolv.c @@ -86,6 +86,25 @@ dump_attrs (Repo *repo, unsigned int entry) } static void +dump_repodata (Repo *repo) +{ + unsigned i; + Repodata *d; + if (repo->nrepodata == 0) + return; + printf ("repo refers to %d attribute stores:\n", repo->nrepodata); + for (i = 0, d = repo->repodata; i < repo->nrepodata; i++, d++) + { + unsigned j; + printf ("%s has %d keys", d->name ? d->name : "**EMBED**", d->nkeys); + for (j = 0; j < d->nkeys; j++) + printf ("\n %s", id2str (repo->pool, d->keys[j].name)); + printf ("\n"); + } + printf ("\n"); +} + +static void printids(Repo *repo, char *kind, Offset ido) { Pool *pool = repo->pool; @@ -116,6 +135,7 @@ int main(int argc, char **argv) pool = pool_create(); repo = repo_create(pool, argc != 1 ? argv[1] : ""); repo_add_solv(repo, stdin); + dump_repodata (repo); printf("repo contains %d solvables\n", repo->nsolvables); for (i = repo->start, n = 1; i < repo->end; i++) { diff --git a/tools/repo_write.c b/tools/repo_write.c index 11eb7a9..ef36e61 100644 --- a/tools/repo_write.c +++ b/tools/repo_write.c @@ -185,6 +185,16 @@ write_id(FILE *fp, Id x) } } +static void +write_str(FILE *fp, const char *str) +{ + if (fputs (str, fp) == EOF + || putc (0, fp) == EOF) + { + perror("write error"); + exit(1); + } +} /* * Array of Ids @@ -321,11 +331,26 @@ repo_write(Repo *repo, FILE *fp) Id lastschema[256]; Id lastschemakey[256]; + /* For the info block. */ + Id repodata_id, hello_id; + + repodata_id = str2id (pool, "repodata", 1); + hello_id = str2id (pool, "hello", 1); + nsolvables = 0; idarraydata = repo->idarraydata; needid = (NeedId *)xcalloc(pool->ss.nstrings + pool->nrels, sizeof(*needid)); + needid[repodata_id].need++; + needid[hello_id].need++; + for (i = 0; i < repo->nrepodata; i++) + { + int j; + for (j = 0; j < repo->repodata[i].nkeys; j++) + needid[repo->repodata[i].keys[j].name].need++; + } + memset(idsizes, 0, sizeof(idsizes)); for (i = repo->start, s = pool->solvables + i; i < repo->end; i++, s++) @@ -506,7 +531,7 @@ repo_write(Repo *repo, FILE *fp) /* write file header */ write_u32(fp, 'S' << 24 | 'O' << 16 | 'L' << 8 | 'V'); - write_u32(fp, SOLV_VERSION_2); + write_u32(fp, SOLV_VERSION_3); /* write counts */ write_u32(fp, nstrings); @@ -514,7 +539,7 @@ repo_write(Repo *repo, FILE *fp) write_u32(fp, nsolvables); write_u32(fp, nkeys); write_u32(fp, nschemata); - write_u32(fp, 0); /* no info block */ + write_u32(fp, 2); /* Info block. */ solv_flags = 0; solv_flags |= SOLV_FLAG_PREFIX_POOL; #if 0 @@ -596,7 +621,49 @@ repo_write(Repo *repo, FILE *fp) while (*sp++) ; } - + + /* + * write info block + */ + write_id (fp, needid[hello_id].need); + write_id (fp, TYPE_COUNT_NAMED); + write_id (fp, 1); + write_id (fp, 0); //name + write_id (fp, TYPE_STR); + write_str (fp, "doll"); + + write_id (fp, needid[repodata_id].need); + write_id (fp, TYPE_COUNT_NAMED); + write_id (fp, repo->nrepodata); + for (i = 0; i < repo->nrepodata; i++) + { + int j; + write_id (fp, 0); /* no name, isn't important here */ + write_id (fp, TYPE_COUNT_NAMED); + /* Don't emit the embedded attributes. */ + if (repo->repodata[i].name == 0) + { + write_id (fp, 0); /* count */ + continue; + } + write_id (fp, 2); /* 2 items, the filename and the keys */ + /* 1 filename */ + write_id (fp, 0); /* no name */ + write_id (fp, TYPE_STR); + write_str (fp, repo->repodata[i].name); + + /* 2 keys */ + write_id (fp, 0); /* no name */ + write_id (fp, TYPE_COUNTED); + write_id (fp, repo->repodata[i].nkeys * 2); + write_id (fp, TYPE_ID); + for (j = 0; j < repo->repodata[i].nkeys; j++) + { + write_id (fp, needid[repo->repodata[i].keys[j].name].need); + write_id (fp, repo->repodata[i].keys[j].type); + } + } + #if 0 if (1) {