- clean up ugly products handling
authorMichael Schroeder <mls@suse.de>
Sat, 20 Jun 2009 11:04:36 +0000 (13:04 +0200)
committerMichael Schroeder <mls@suse.de>
Sat, 20 Jun 2009 11:04:36 +0000 (13:04 +0200)
tools/CMakeLists.txt
tools/repo_products.c
tools/repo_products.h
tools/repo_releasefile_products.c [new file with mode: 0644]
tools/repo_releasefile_products.h [new file with mode: 0644]
tools/repo_zyppdb.c
tools/repo_zyppdb.h
tools/rpmdb2solv.c

index 741bb10..576dae4 100644 (file)
@@ -10,6 +10,7 @@ SET(rpmdb2solv_REPOS
   repo_rpmdb.c
   repo_products.c
   repo_zyppdb.c
+  repo_releasefile_products.c
 )
 
 ADD_EXECUTABLE( rpmdb2solv ${rpmdb2solv_REPOS} )
index a974f71..5cdcc19 100644 (file)
@@ -31,6 +31,7 @@
 #include "tools_util.h"
 #include "repo_content.h"
 #include "repo_zyppdb.h"
+#include "repo_releasefile_products.h"
 
 
 //#define DUMPOUT 0
@@ -385,7 +386,7 @@ characterData(void *userData, const XML_Char *s, int len)
  */
 
 static void
-repo_add_product(struct parsedata *pd, FILE *fp, int code11)
+add_code11_product(struct parsedata *pd, FILE *fp)
 {
   char buf[BUFF_SIZE];
   int l;
@@ -403,162 +404,101 @@ repo_add_product(struct parsedata *pd, FILE *fp, int code11)
       pd->ctime = 0;
     }
 
-  if (code11)
-    {
-      XML_Parser parser = XML_ParserCreate(NULL);
-      XML_SetUserData(parser, pd);
-      XML_SetElementHandler(parser, startElement, endElement);
-      XML_SetCharacterDataHandler(parser, characterData);
+  XML_Parser parser = XML_ParserCreate(NULL);
+  XML_SetUserData(parser, pd);
+  XML_SetElementHandler(parser, startElement, endElement);
+  XML_SetCharacterDataHandler(parser, characterData);
 
-      for (;;)
-       {
-         l = fread(buf, 1, sizeof(buf), fp);
-         if (XML_Parse(parser, buf, l, l == 0) == XML_STATUS_ERROR)
-           {
-             pool_debug(pd->pool, SAT_ERROR, "%s: %s at line %u:%u\n", pd->filename, XML_ErrorString(XML_GetErrorCode(parser)), (unsigned int)XML_GetCurrentLineNumber(parser), (unsigned int)XML_GetCurrentColumnNumber(parser));
-             pool_debug(pd->pool, SAT_ERROR, "Skipping this product\n");
-             XML_ParserFree(parser);
-             return;
-           }
-         if (l == 0)
-           break;
-       }
-      XML_ParserFree(parser);
-    }
-  else
+  for (;;)
     {
-      Id name = 0;
-      Id arch = 0;
-      Id version = 0;
-      int lnum = 0; /* line number */
-      char *ptr, *ptr1;
-      /* parse /etc/<xyz>-release file */
-      while (fgets(buf, sizeof(buf), fp))
-       {
-         /* remove trailing \n */
-         int l = strlen(buf);
-         if (*(buf + l - 1) == '\n')
-           {
-             --l;
-             *(buf + l) = 0;
-           }
-         ++lnum;
-
-         if (lnum == 1)
-           {
-             /* 1st line, <name> [(<arch>)] */
-             ptr = strchr(buf, '(');
-             if (ptr)
-               {
-                 ptr1 = ptr - 1;
-                 *ptr++ = 0;
-               }
-             else
-               ptr1 = buf + l - 1;
-
-             /* track back until non-blank, non-digit */
-             while (ptr1 > buf
-                    && (*ptr1 == ' ' || isdigit(*ptr1) || *ptr1 == '.'))
-               --ptr1;
-             *(++ptr1) = 0;
-             name = str2id(pd->pool, join2("product", ":", buf), 1);
-
-             if (ptr)
-               {
-                 /* have arch */
-                 char *ptr1 = strchr(ptr, ')');
-                 if (ptr1)
-                   {
-                     *ptr1 = 0;
-                     /* downcase arch */
-                     ptr1 = ptr;
-                     while (*ptr1)
-                       {
-                         if (isupper(*ptr1)) *ptr1 = tolower(*ptr1);
-                         ++ptr1;
-                       }
-                     arch = str2id(pd->pool, ptr, 1);
-                   }
-               }
-           }
-         else if (strncmp(buf, "VERSION", 7) == 0)
-           {
-             ptr = strchr(buf+7, '=');
-             if (ptr)
-               {
-                 while (*++ptr == ' ');
-                 version = makeevr(pd->pool, ptr);
-               }
-           }
-       }
-      if (name)
+      l = fread(buf, 1, sizeof(buf), fp);
+      if (XML_Parse(parser, buf, l, l == 0) == XML_STATUS_ERROR)
        {
-         Solvable *s = pd->solvable = pool_id2solvable(pd->pool, repo_add_solvable(pd->repo));
-         s->name = name;
-         if (version)
-           s->evr = version;
-         if (arch)
-           s->arch = arch;
-         if (s->arch != ARCH_SRC && s->arch != ARCH_NOSRC)
-           s->provides = repo_addid_dep(pd->repo, s->provides, rel2id(pd->pool, s->name, s->evr, REL_EQ, 1), 0);
+         pool_debug(pd->pool, SAT_ERROR, "%s: %s at line %u:%u\n", pd->filename, XML_ErrorString(XML_GetErrorCode(parser)), (unsigned int)XML_GetCurrentLineNumber(parser), (unsigned int)XML_GetCurrentColumnNumber(parser));
+         pool_debug(pd->pool, SAT_ERROR, "skipping this product\n");
+         XML_ParserFree(parser);
+         return;
        }
+      if (l == 0)
+       break;
     }
+  XML_ParserFree(parser);
 }
 
 
+void
+repo_add_code11_products(Repo *repo, const char *dirpath, int flags)
+{
+  Repodata *data;
+  struct parsedata pd;
+  struct stateswitch *sw;
+  DIR *dir;
+  int i;
 
-/*
- * parse dir looking for files ending in suffix
- */
+  if (!(flags & REPO_REUSE_REPODATA))
+    data = repo_add_repodata(repo, 0);
+  else
+    data = repo_last_repodata(repo);
 
-static void
-parse_dir(DIR *dir, const char *path, struct parsedata *pd, int code11)
-{
-  struct dirent *entry;
-  char *suffix = code11 ? ".prod" : "-release";
-  int slen = code11 ? 5 : 8;  /* strlen(".prod") : strlen("-release") */
-  struct stat st;
+  memset(&pd, 0, sizeof(pd));
+  pd.repo = repo;
+  pd.pool = repo->pool;
+  pd.data = data;
+
+  pd.content = sat_malloc(256);
+  pd.acontent = 256;
 
-  /* check for <productsdir>/baseproduct on code11 and remember its target inode */
-  if (code11
-      && stat(join2(path, "/", "baseproduct"), &st) == 0) /* follow symlink */
+  for (i = 0, sw = stateswitches; sw->from != NUMSTATES; i++, sw++)
     {
-      pd->baseproduct = st.st_ino;
+      if (!pd.swtab[sw->from])
+        pd.swtab[sw->from] = sw;
+      pd.sbtab[sw->to] = sw->from;
     }
-  else
-    pd->baseproduct = 0;
 
-  while ((entry = readdir(dir)))
+  dir = opendir(dirpath);
+  if (dir)
     {
-      int len;
-      len = strlen(entry->d_name);
+      struct dirent *entry;
+      struct stat st;
+      char *fullpath;
 
-      /* skip /etc/lsb-release, thats not a product per-se */
-      if (!code11
-         && strcmp(entry->d_name, "lsb-release") == 0)
-       {
-         continue;
-       }
+      /* check for <productsdir>/baseproduct on code11 and remember its target inode */
+      if (stat(join2(dirpath, "/", "baseproduct"), &st) == 0) /* follow symlink */
+       pd.baseproduct = st.st_ino;
+      else
+       pd.baseproduct = 0;
 
-      if (len > slen
-         && strcmp(entry->d_name + len - slen, suffix) == 0)
+      while ((entry = readdir(dir)))
        {
-         char *fullpath = join2(path, "/", entry->d_name);
+         int len = strlen(entry->d_name);
+         if (len <= 5 || strcmp(entry->d_name + len - 5, ".prod") != 0)
+           continue;
+         fullpath = join2(dirpath, "/", entry->d_name);
          FILE *fp = fopen(fullpath, "r");
          if (!fp)
            {
              perror(fullpath);
-             break;
+             continue;
            }
-         pd->filename = fullpath;
-         pd->basename = entry->d_name;
-         repo_add_product(pd, fp, code11);
+         pd.filename = fullpath;
+         pd.basename = entry->d_name;
+         add_code11_product(&pd, fp);
          fclose(fp);
        }
+      closedir(dir);
     }
+  sat_free((void *)pd.tmplang);
+  sat_free(pd.content);
+  join_freemem();
+
+  if (!(flags & REPO_NO_INTERNALIZE))
+    repodata_internalize(data);
 }
 
 
+/******************************************************************************************/
+
+
 /*
  * read all installed products
  *
@@ -573,70 +513,44 @@ parse_dir(DIR *dir, const char *path, struct parsedata *pd, int code11)
 void
 repo_add_products(Repo *repo, const char *proddir, const char *root, int flags)
 {
-  const char *fullpath = proddir;
+  const char *fullpath;
   DIR *dir;
-  int i;
-  struct parsedata pd;
-  struct stateswitch *sw;
-  Repodata *data;
-
-  if (!(flags & REPO_REUSE_REPODATA))
-    data = repo_add_repodata(repo, 0);
-  else
-    data = repo_last_repodata(repo);
 
-  memset(&pd, 0, sizeof(pd));
-  pd.repo = repo;
-  pd.pool = repo->pool;
-  pd.data = data;
-
-  pd.content = sat_malloc(256);
-  pd.acontent = 256;
-
-  for (i = 0, sw = stateswitches; sw->from != NUMSTATES; i++, sw++)
+  dir = opendir(proddir);
+  if (dir)
     {
-      if (!pd.swtab[sw->from])
-        pd.swtab[sw->from] = sw;
-      pd.sbtab[sw->to] = sw->from;
+      /* assume code11 stype products */
+      closedir(dir);
+      repo_add_code11_products(repo, proddir, flags);
+      return;
     }
 
+  /* code11 didn't work, try old zyppdb */
+  fullpath = root ? join2(root, "", "/var/lib/zypp/db/products") : "/var/lib/zypp/db/products";
   dir = opendir(fullpath);
   if (dir)
     {
-      parse_dir(dir, fullpath, &pd, 1); /* assume 'code11' products */
       closedir(dir);
+      /* assume code10 style products */
+      repo_add_zyppdb_products(repo, fullpath, flags);
+      join_freemem();
+      return;
     }
-  else
+  
+  /* code11 didn't work, try -release files parsing */
+  fullpath = root ? join2(root, "", "/etc") : "/etc";
+  dir = opendir(fullpath);
+  if (dir)
     {
-      fullpath = root ? join2(root, "", "/var/lib/zypp/db/products") : "/var/lib/zypp/db/products";
-      dir = opendir(fullpath);
-      if (dir)
-       {
-         repo_add_zyppdb_products(repo, data, fullpath, dir);      /* assume 'code10' zypp-style products */
-         closedir(dir);
-       }
-      else
-       {
-         fullpath = root ? join2(root, "", "/etc") : "/etc";
-         dir = opendir(fullpath);
-         if (dir)
-           {
-             parse_dir(dir, fullpath, &pd, 0); /* fall back to /etc/<xyz>-release parsing */
-             closedir(dir);
-           }
-         else
-           {
-             perror(fullpath);
-           }
-       }
+      closedir(dir);
+      repo_add_releasefile_products(repo, fullpath, flags);
+      join_freemem();
+      return;
     }
 
-  sat_free((void *)pd.tmplang);
-  sat_free(pd.content);
+  /* no luck. print an error message in case the root argument is wrong */
+  perror(fullpath);
   join_freemem();
-
-  if (!(flags & REPO_NO_INTERNALIZE))
-    repodata_internalize(data);
 }
 
 /* EOF */
index aa0c2d9..6f4ce85 100644 (file)
@@ -1,8 +1,9 @@
 /*
- * Copyright (c) 2007, Novell Inc.
+ * Copyright (c) 2007-2009, Novell Inc.
  *
  * This program is licensed under the BSD license, read LICENSE.BSD
  * for further information
  */
 
+void repo_add_code11_products(Repo *repo, const char *dirpath, int flags);
 void repo_add_products(Repo *repo, const char *proddir, const char *root, int flags);
diff --git a/tools/repo_releasefile_products.c b/tools/repo_releasefile_products.c
new file mode 100644 (file)
index 0000000..2413d20
--- /dev/null
@@ -0,0 +1,156 @@
+/*
+ * repo_products.c
+ *
+ * Parses all files below 'proddir'
+ * See http://en.opensuse.org/Product_Management/Code11
+ *
+ *
+ * Copyright (c) 2008, Novell Inc.
+ *
+ * This program is licensed under the BSD license, read LICENSE.BSD
+ * for further information
+ */
+
+#include <sys/types.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <dirent.h>
+#include <ctype.h>
+
+#include "pool.h"
+#include "repo.h"
+#include "util.h"
+#define DISABLE_SPLIT
+#include "tools_util.h"
+#include "repo_releasefile_products.h"
+
+#define BUFF_SIZE 8192
+
+static void
+add_releasefile_product(Repo *repo, FILE *fp)
+{
+  Pool *pool = repo->pool;
+  char buf[BUFF_SIZE];
+  Id name = 0;
+  Id arch = 0;
+  Id version = 0;
+  int lnum = 0; /* line number */
+  char *ptr, *ptr1;
+
+  /* parse /etc/<xyz>-release file */
+  while (fgets(buf, sizeof(buf), fp))
+    {
+      /* remove trailing \n */
+      int l = strlen(buf);
+      if (l && buf[l - 1] == '\n')
+       buf[--l] = 0;
+      ++lnum;
+
+      if (lnum == 1)
+       {
+         /* 1st line, <name> [(<arch>)] */
+         ptr = strchr(buf, '(');
+         if (ptr)
+           {
+             ptr1 = ptr - 1;
+             *ptr++ = 0;
+           }
+         else
+           ptr1 = buf + l - 1;
+
+         /* track back until non-blank, non-digit */
+         while (ptr1 > buf
+                && (*ptr1 == ' ' || isdigit(*ptr1) || *ptr1 == '.'))
+           --ptr1;
+         *(++ptr1) = 0;
+         name = str2id(pool, join2("product", ":", buf), 1);
+
+         if (ptr)
+           {
+             /* have arch */
+             char *ptr1 = strchr(ptr, ')');
+             if (ptr1)
+               {
+                 *ptr1 = 0;
+                 /* downcase arch */
+                 ptr1 = ptr;
+                 while (*ptr1)
+                   {
+                     if (isupper(*ptr1))
+                        *ptr1 = tolower(*ptr1);
+                     ++ptr1;
+                   }
+                 arch = str2id(pool, ptr, 1);
+               }
+           }
+       }
+      else if (strncmp(buf, "VERSION", 7) == 0)
+       {
+         ptr = strchr(buf + 7, '=');
+         if (ptr)
+           {
+             while (*++ptr == ' ')
+               ;
+             version = makeevr(pool, ptr);
+           }
+       }
+    }
+  if (name)
+    {
+      Solvable *s = pool_id2solvable(pool, repo_add_solvable(repo));
+      s->name = name;
+      if (version)
+       s->evr = version;
+      if (arch)
+       s->arch = arch;
+      if (s->arch != ARCH_SRC && s->arch != ARCH_NOSRC)
+       s->provides = repo_addid_dep(repo, s->provides, rel2id(pool, s->name, s->evr, REL_EQ, 1), 0);
+    }
+}
+
+
+void
+repo_add_releasefile_products(Repo *repo, const char *dirpath, int flags)
+{
+  DIR *dir;
+  struct dirent *entry;
+  FILE *fp;
+  char *fullpath;
+
+  dir = opendir(dirpath);
+  if (!dir)
+    return;
+
+  while ((entry = readdir(dir)))
+    {
+      int len = strlen(entry->d_name);
+      if (len > 8 && !strcmp(entry->d_name + len - 8, "-release"))
+        {
+         /* skip /etc/lsb-release, thats not a product per-se */
+         if (strcmp(entry->d_name, "lsb-release") == 0)
+           continue;
+         fullpath = join2(dirpath, "/", entry->d_name);
+         if ((fp = fopen(fullpath, "r")) == 0)
+           {
+             perror(fullpath);
+             continue;
+           }
+         add_releasefile_product(repo, fp);
+       }
+    }
+  closedir(dir);
+  join_freemem();
+
+  if (!(flags & REPO_NO_INTERNALIZE))
+    {
+      if (!(flags & REPO_REUSE_REPODATA))
+       {
+         Repodata *data = repo_add_repodata(repo, 0);
+         repodata_internalize(data);
+       }
+    }
+}
+
diff --git a/tools/repo_releasefile_products.h b/tools/repo_releasefile_products.h
new file mode 100644 (file)
index 0000000..34311ac
--- /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_releasefile_products(Repo *repo, const char *dirpath, int flags);
index dc94281..13086d9 100644 (file)
@@ -1,8 +1,8 @@
 /*
  * repo_zyppdb.c
  *
- * Parses /var/lib/zypp/db/products/...
- * The are old (pre Code11) products. See bnc#429177
+ * Parses legacy /var/lib/zypp/db/products/... files.
+ * They are old (pre Code11) product descriptions. See bnc#429177
  *
  *
  * Copyright (c) 2008, Novell Inc.
@@ -302,7 +302,7 @@ characterData(void *userData, const XML_Char *s, int len)
  */
 
 static void
-repo_add_product(struct parsedata *pd, Repodata *data, FILE *fp)
+add_zyppdb_product(struct parsedata *pd, FILE *fp)
 {
   char buf[BUFF_SIZE];
   int l;
@@ -327,34 +327,6 @@ repo_add_product(struct parsedata *pd, Repodata *data, FILE *fp)
 }
 
 
-
-/*
- * parse dir for products
- */
-
-static void
-parse_dir(DIR *dir, const char *path, struct parsedata *pd, Repodata *repodata)
-{
-  struct dirent *entry;
-
-  while ((entry = readdir(dir)))
-    {
-      int len = strlen(entry->d_name);
-      if (len < 3)   /* skip '.' and '..' */
-       continue;
-      char *fullpath = join2(path, "/", entry->d_name);
-      FILE *fp = fopen(fullpath, "r");
-      if (!fp)
-       {
-         perror(fullpath);
-         break;
-       }
-      repo_add_product(pd, repodata, fp);
-      fclose(fp);
-    }
-}
-
-
 /*
  * read all installed products
  *
@@ -362,16 +334,26 @@ parse_dir(DIR *dir, const char *path, struct parsedata *pd, Repodata *repodata)
  */
 
 void
-repo_add_zyppdb_products(Repo *repo, Repodata *repodata, const char *fullpath, DIR *dir)
+repo_add_zyppdb_products(Repo *repo, const char *dirpath, int flags)
 {
   int i;
   struct parsedata pd;
   struct stateswitch *sw;
+  struct dirent *entry;
+  char *fullpath;
+  DIR *dir;
+  FILE *fp;
+  Repodata *data;
+  
+  if (!(flags & REPO_REUSE_REPODATA))
+    data = repo_add_repodata(repo, 0);
+  else
+    data = repo_last_repodata(repo);
 
   memset(&pd, 0, sizeof(pd));
   pd.repo = repo;
   pd.pool = repo->pool;
-  pd.data = repodata;
+  pd.data = data;
 
   pd.content = malloc(256);
   pd.acontent = 256;
@@ -383,11 +365,30 @@ repo_add_zyppdb_products(Repo *repo, Repodata *repodata, const char *fullpath, D
       pd.sbtab[sw->to] = sw->from;
     }
 
-  parse_dir(dir, fullpath, &pd, repodata);
+  dir = opendir(dirpath);
+  if (dir)
+    {
+      while ((entry = readdir(dir)))
+       {
+         if (strlen(entry->d_name) < 3)
+           continue;   /* skip '.' and '..' */
+         fullpath = join2(dirpath, "/", entry->d_name);
+         if ((fp = fopen(fullpath, "r")) == 0)
+           {
+             perror(fullpath);
+             continue;
+           }
+         add_zyppdb_product(&pd, fp);
+         fclose(fp);
+       }
+    }
+  closedir(dir);
 
   sat_free((void *)pd.tmplang);
   free(pd.content);
   join_freemem();
+  if (!(flags & REPO_NO_INTERNALIZE))
+    repodata_internalize(data);
 }
 
 /* EOF */
index 1e2ac1e..8c4a5da 100644 (file)
@@ -5,4 +5,4 @@
  * for further information
  */
 
-void repo_add_zyppdb_products(Repo *repo, Repodata *repodata, const char *fullpath, DIR *dir);
+void repo_add_zyppdb_products(Repo *repo, const char *dirpath, int flags);
index f4bea47..515a8e7 100644 (file)
@@ -159,7 +159,7 @@ main(int argc, char **argv)
              strcpy(buf + rootlen, proddir);
            }
        }
-      repo_add_products(repo, proddir, root, REPO_REUSE_REPODATA | REPO_NO_INTERNALIZE);
+      repo_add_products(repo, buf, root, REPO_REUSE_REPODATA | REPO_NO_INTERNALIZE);
       if (buf != proddir)
        sat_free(buf);
     }