prepare for parsing 'installed' products
authorKlaus Kaempf <kkaempf@suse.de>
Mon, 11 Aug 2008 10:13:30 +0000 (10:13 +0000)
committerKlaus Kaempf <kkaempf@suse.de>
Mon, 11 Aug 2008 10:13:30 +0000 (10:13 +0000)
tools/CMakeLists.txt
tools/repo_products.c [new file with mode: 0644]
tools/repo_products.h [new file with mode: 0644]
tools/rpmdb2solv.c

index 5299d70..d7c67a4 100644 (file)
@@ -10,6 +10,8 @@ SET(rpmdb2solv_REPOS
   rpmdb2solv.c
   repo_rpmdb.h
   repo_rpmdb.c
+  repo_products.c
+  repo_products.h
   repo_write.c
   common_write.c
 )
diff --git a/tools/repo_products.c b/tools/repo_products.c
new file mode 100644 (file)
index 0000000..76937d4
--- /dev/null
@@ -0,0 +1,326 @@
+/*
+ * repo_products.c
+ * 
+ * Parses all files below 'proddir'
+ * See http://en.opensuse.org/Product_Management/Code11
+ * 
+ * 
+ * Copyright (c) 2007, Novell Inc.
+ *
+ * This program is licensed under the BSD license, read LICENSE.BSD
+ * for further information
+ */
+
+#include <sys/types.h>
+#include <limits.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <dirent.h>
+
+#include "pool.h"
+#include "repo.h"
+#include "util.h"
+#include "repo_content.h"
+
+struct parsedata {
+  Repo *repo;
+  char *tmp;
+  int tmpl;
+};
+
+
+
+#if 0
+/*
+ * split l into m parts, store to sp[]
+ *  split at whitespace
+ */
+
+static int
+split(char *l, char **sp, int m)
+{
+  int i;
+  for (i = 0; i < m;)
+    {
+      while (*l == ' ' || *l == '\t')
+       l++;
+      if (!*l)
+       break;
+      sp[i++] = l;
+      if (i == m)
+        break;
+      while (*l && !(*l == ' ' || *l == '\t'))
+       l++;
+      if (!*l)
+       break;
+      *l++ = 0;
+    }
+  return i;
+}
+
+
+static Id
+makeevr(Pool *pool, char *s)
+{
+  if (!strncmp(s, "0:", 2) && s[2])
+    s += 2;
+  return str2id(pool, s, 1);
+}
+
+/*
+ * dependency relations
+ */
+
+static char *flagtab[] = {
+  ">",
+  "=",
+  ">=",
+  "<",
+  "!=",
+  "<="
+};
+#endif
+
+/*
+ * join up to three strings into one
+ */
+
+static char *
+join(struct parsedata *pd, const char *s1, const char *s2, const char *s3)
+{
+  int l = 1;
+  char *p;
+
+  if (s1)
+    l += strlen(s1);
+  if (s2)
+    l += strlen(s2);
+  if (s3)
+    l += strlen(s3);
+  if (l > pd->tmpl)
+    {
+      pd->tmpl = l + 256;
+      pd->tmp = sat_realloc(pd->tmp, pd->tmpl);
+    }
+  p = pd->tmp;
+  if (s1)
+    {
+      strcpy(p, s1);
+      p += strlen(s1);
+    }
+  if (s2)
+    {
+      strcpy(p, s2);
+      p += strlen(s2);
+    }
+  if (s3)
+    {
+      strcpy(p, s3);
+      p += strlen(s3);
+    }
+  return pd->tmp;
+}
+
+
+#if 0
+/*
+ * add dependency to pool
+ */
+
+static unsigned int
+adddep(Pool *pool, struct parsedata *pd, unsigned int olddeps, char *line, Id marker)
+{
+  int flags, words;
+  Id id, evrid;
+  char *sp[4];
+
+  words = 0;
+  while (1)
+    {
+      /* Name [relop evr] [rest] --> 1, 2, 3 or 4 fields.  */
+      if ( line )
+        {
+          words += split(line, sp + words, 4 - words);
+          line = 0;
+        }
+      /* Hack, as the content file adds 'package:' for package
+         dependencies sometimes.  */
+      if (!strncmp (sp[0], "package:", 8))
+        sp[0] += 8;
+      id = str2id(pool, sp[0], 1);
+      if (words >= 3 && strpbrk (sp[1], "<>="))
+       {
+         evrid = makeevr(pool, sp[2]);
+         for (flags = 0; flags < 6; flags++)
+           if (!strcmp(sp[1], flagtab[flags]))
+             break;
+         if (flags == 6)
+           {
+             fprintf(stderr, "Unknown relation '%s'\n", sp[1]);
+             exit(1);
+           }
+         id = rel2id(pool, id, evrid, flags + 1, 1);
+         /* Consume three words, there's nothing to move to front.  */
+         if (words == 4)
+           line = sp[3];
+          words = 0;
+       }
+      else
+        {
+         int j;
+         /* Consume one word.  If we had more move them to front.  */
+         words--;
+         for (j = 0; j < words; j++)
+           sp[j] = sp[j+1];
+         if (words == 3)
+           line = sp[2], words = 2;
+       }
+      olddeps = repo_addid_dep(pd->repo, olddeps, id, marker);
+      if (! ( line || words > 0 ) )
+        break;
+    }
+  return olddeps;
+}
+
+
+/*
+ * split value and add to pool
+ */
+
+static void
+add_multiple_strings(Repodata *data, Id handle, Id name, char *value)
+{
+  char *sp[2];
+  while (value)
+    {
+      int words = split(value, sp, 2);
+      if (!words)
+       break;
+      repodata_add_poolstr_array(data, handle, name, sp[0]);
+      if (words == 1)
+       break;
+      value = sp[1];
+    }
+}
+#endif
+
+/*
+ * add single product to repo
+ *
+ */
+
+static void
+repo_add_product(struct parsedata *pd, FILE *fp)
+{
+#if 0
+  Pool *pool = pd->repo->pool;
+  char *line, *linep;
+  int aline;
+  Solvable *s, *firsts = 0;
+  Id handle = 0;
+  
+  line = sat_malloc(1024);
+  aline = 1024;
+
+  linep = line;
+  s = 0;
+
+  for (;;)
+    {
+/*      char *fields[2]; */
+      
+      /* read line into big-enough buffer */
+      if (linep - line + 16 > aline)
+       {
+         aline = linep - line;
+         line = sat_realloc(line, aline + 512);
+         linep = line + aline;
+         aline += 512;
+       }
+      if (!fgets(linep, aline - (linep - line), fp))
+       break;
+      linep += strlen(linep);
+      if (linep == line || linep[-1] != '\n')
+        continue;
+      *--linep = 0;
+      linep = line;
+      /* expect "key value" lines */
+      if (split (line, fields, 2) == 2)
+        {
+         char *key = fields[0];
+         char *value = fields[1];
+       }
+      else
+       fprintf (stderr, "malformed line: %s\n", line);
+    }
+
+  if (!s)
+    {
+      fprintf(stderr, "No product solvable created !\n");
+      exit(1);
+    }
+
+  if (!s->arch)
+    s->arch = ARCH_NOARCH;
+  if (s->arch != ARCH_SRC && s->arch != ARCH_NOSRC)
+    {
+      s->provides = repo_addid_dep(pd->repo, s->provides, rel2id(pool, s->name, s->evr, REL_EQ, 1), 0);
+    }
+  
+  sat_free(line);
+#endif
+}
+
+
+/*
+ * read all .prod files from directory
+ * parse each one as a product
+ */
+
+void
+repo_add_products(Repo *repo, const char *proddir)
+{
+  DIR *dir = opendir(proddir);
+  struct dirent *entry;
+  struct parsedata pd;
+  Repodata *data;
+  
+  memset(&pd, 0, sizeof(pd));
+  if (repo->nrepodata)
+    /* use last repodata */
+    data = repo->repodata + repo->nrepodata - 1;
+  else
+    data = repo_add_repodata(repo, 0);
+
+  pd.repo = repo;
+
+  if (!dir)
+    {
+      perror(proddir);
+      return;
+    }
+  
+  while ((entry = readdir(dir)))
+    {
+      const char *dot;
+      dot = strrchr( entry->d_name, '.' );
+      if (dot && strcmp(dot, ".prod") == 0)
+       {
+         char *fullpath = join(&pd, proddir, "/", entry->d_name);
+         FILE *fp = fopen(fullpath, "r");
+         if (!fp)
+           {
+             perror(fullpath);
+             break;
+           }
+         repo_add_product(&pd, fp);
+         fclose(fp);
+       }
+    }
+  if (pd.tmp)
+    sat_free(pd.tmp);
+  closedir(dir);
+}
diff --git a/tools/repo_products.h b/tools/repo_products.h
new file mode 100644 (file)
index 0000000..8b607ae
--- /dev/null
@@ -0,0 +1,8 @@
+/*
+ * Copyright (c) 2007, Novell Inc.
+ *
+ * This program is licensed under the BSD license, read LICENSE.BSD
+ * for further information
+ */
+
+void repo_add_products(Repo *repo, const char *proddir);
index f46b30f..b2301f3 100644 (file)
@@ -8,6 +8,9 @@
 /*
  * rpmdb2solv
  * 
+ * Reads rpm database (and evtl. more, like product metadata) to build
+ * a .solv file of 'installed' solvables.
+ * 
  */
 
 #include <sys/types.h>
@@ -21,6 +24,7 @@
 #include "pool.h"
 #include "repo.h"
 #include "repo_rpmdb.h"
+#include "repo_products.h"
 #include "repo_solv.h"
 #include "common_write.h"
 
@@ -35,8 +39,13 @@ main(int argc, char **argv)
   int extrapool = 0;
   const char *root = 0;
   const char *basefile = 0;
+  const char *proddir = 0;
 
-  while ((c = getopt (argc, argv, "xb:r:")) >= 0)
+  /*
+   * parse arguments
+   */
+  
+  while ((c = getopt (argc, argv, "xb:r:p:")) >= 0)
     switch (c)
       {
       case 'r':
@@ -45,6 +54,9 @@ main(int argc, char **argv)
       case 'b':
         basefile = optarg;
         break;
+      case 'p':
+       proddir = optarg;
+       break;
       case 'x':
         extrapool = 1;
         break;
@@ -52,6 +64,10 @@ main(int argc, char **argv)
        exit(1);
       }
   
+  /*
+   * ???
+   */
+  
   if (optind < argc)
     {
       if (extrapool)
@@ -69,7 +85,19 @@ main(int argc, char **argv)
       fclose(fp);
     }
 
+  /*
+   * create 'installed' repository
+   * add products
+   * add rpmdb
+   * write .solv
+   */
+
   repo = repo_create(pool, "installed");
+  if (proddir)
+    {
+      repo_add_products(repo, proddir);
+    }
+
   repo_add_rpmdb(repo, ref, root);
   if (ref)
     {