Pfeww. I'm tired, but now you can add refers from repo SOLV files to
authorMichael Matz <matz@suse.de>
Sat, 8 Dec 2007 04:58:04 +0000 (04:58 +0000)
committerMichael Matz <matz@suse.de>
Sat, 8 Dec 2007 04:58:04 +0000 (04:58 +0000)
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
...
)

src/pool.h
src/repo.c
src/repo.h
src/repo_solv.c
tools/CMakeLists.txt
tools/addstore.c [new file with mode: 0644]
tools/dumpsolv.c
tools/repo_write.c

index 027d49b..45e0813 100644 (file)
@@ -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
 
 //-----------------------------------------------
 
index f8f2d34..76d9e9f 100644 (file)
@@ -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
index 39e3c49..597287c 100644 (file)
@@ -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)
 {
index 7a9bda8..aebbb38 100644 (file)
@@ -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);
index 4ce98bd..f338e7b 100644 (file)
@@ -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 (file)
index 0000000..22d09bd
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2007, Novell Inc.
+ *
+ * This program is licensed under the BSD license, read LICENSE.BSD
+ * for further information
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+
+#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);
+}
index 8cbbc2f..c2b05f9 100644 (file)
@@ -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] : "<stdin>");
   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++)
     {
index 11eb7a9..ef36e61 100644 (file)
@@ -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)
     {