Imported Upstream version 0.6.8
[platform/upstream/libsolv.git] / ext / repo_helix.c
index e62b810..95dac35 100644 (file)
@@ -7,10 +7,17 @@
 
 /*
  * repo_helix.c
- * 
+ *
  * Parse 'helix' XML representation
  * and create 'repo'
- * 
+ *
+ * A bit of history: "Helix Code" was the name of the company that
+ * wrote Red Carpet. The company was later renamed to Ximian.
+ * The Red Carpet solver was merged into the ZYPP project, the
+ * library used both by ZENworks and YaST for package management.
+ * Red Carpet came with solver testcases in its own repository
+ * format, the 'helix' format.
+ *
  */
 
 #include <sys/types.h>
@@ -87,11 +94,13 @@ static struct stateswitch stateswitches[] = {
   { STATE_START,       "channel",         STATE_CHANNEL, 0 },
   { STATE_CHANNEL,     "subchannel",      STATE_SUBCHANNEL, 0 },
   { STATE_SUBCHANNEL,  "package",         STATE_PACKAGE, 0 },
+  { STATE_SUBCHANNEL,  "srcpackage",      STATE_PACKAGE, 0 },
   { STATE_SUBCHANNEL,  "selection",       STATE_PACKAGE, 0 },
   { STATE_SUBCHANNEL,  "pattern",         STATE_PACKAGE, 0 },
   { STATE_SUBCHANNEL,  "atom",            STATE_PACKAGE, 0 },
   { STATE_SUBCHANNEL,  "patch",           STATE_PACKAGE, 0 },
   { STATE_SUBCHANNEL,  "product",         STATE_PACKAGE, 0 },
+  { STATE_SUBCHANNEL,  "application",     STATE_PACKAGE, 0 },
   { STATE_PACKAGE,     "name",            STATE_NAME, 1 },
   { STATE_PACKAGE,     "vendor",          STATE_VENDOR, 1 },
   { STATE_PACKAGE,     "buildtime",       STATE_BUILDTIME, 1 },
@@ -136,29 +145,30 @@ static struct stateswitch stateswitches[] = {
  */
 
 typedef struct _parsedata {
-  // XML parser data
+  int ret;
+  /* XML parser data */
   int depth;
-  enum state state;    // current state
+  enum state state;    /* current state */
   int statedepth;
-  char *content;       // buffer for content of node
-  int lcontent;                // actual length of current content
-  int acontent;                // actual buffer size
-  int docontent;       // handle content
-
-  // repo data
-  Pool *pool;          // current pool
-  Repo *repo;          // current repo
-  Repodata *data;       // current repo data
-  Solvable *solvable;  // current solvable
-  Offset freshens;     // current freshens vector
-
-  // package data
-  int  epoch;          // epoch (as offset into evrspace)
-  int  version;                // version (as offset into evrspace)
-  int  release;                // release (as offset into evrspace)
-  char *evrspace;      // buffer for evr
-  int  aevrspace;      // actual buffer space
-  int  levrspace;      // actual evr length
+  char *content;       /* buffer for content of node */
+  int lcontent;                /* actual length of current content */
+  int acontent;                /* actual buffer size */
+  int docontent;       /* handle content */
+
+  /* repo data */
+  Pool *pool;          /* current pool */
+  Repo *repo;          /* current repo */
+  Repodata *data;       /* current repo data */
+  Solvable *solvable;  /* current solvable */
+  Offset freshens;     /* current freshens vector */
+
+  /* package data */
+  int  epoch;          /* epoch (as offset into evrspace) */
+  int  version;                /* version (as offset into evrspace) */
+  int  release;                /* release (as offset into evrspace) */
+  char *evrspace;      /* buffer for evr */
+  int  aevrspace;      /* actual buffer space */
+  int  levrspace;      /* actual evr length */
   char *kind;
 
   struct stateswitch *swtab[NUMSTATES];
@@ -169,7 +179,7 @@ typedef struct _parsedata {
 /*------------------------------------------------------------------*/
 /* E:V-R handling */
 
-// create Id from epoch:version-release
+/* create Id from epoch:version-release */
 
 static Id
 evr2id(Pool *pool, Parsedata *pd, const char *e, const char *v, const char *r)
@@ -177,38 +187,38 @@ evr2id(Pool *pool, Parsedata *pd, const char *e, const char *v, const char *r)
   char *c;
   int l;
 
-  // treat explitcit 0 as NULL
-  if (e && !strcmp(e, "0"))
-    e = NULL;
+  /* treat explitcit 0 as NULL */
+  if (e && (!*e || !strcmp(e, "0")))
+    e = 0;
 
   if (v && !e)
     {
       const char *v2;
-      // scan version for ":"
-      for (v2 = v; *v2 >= '0' && *v2 <= '9'; v2++)     // skip leading digits
+      /* scan version for ":" */
+      for (v2 = v; *v2 >= '0' && *v2 <= '9'; v2++)     /* skip leading digits */
         ;
-      // if version contains ":", set epoch to "0"
+      /* if version contains ":", set epoch to "0" */
       if (v2 > v && *v2 == ':')
        e = "0";
     }
-  
-  // compute length of Id string
-  l = 1;  // for the \0
+
+  /* compute length of Id string */
+  l = 1;  /* for the \0 */
   if (e)
-    l += strlen(e) + 1;  // e:
+    l += strlen(e) + 1;  /* e: */
   if (v)
-    l += strlen(v);      // v
+    l += strlen(v);      /* v */
   if (r)
-    l += strlen(r) + 1;  // -r
+    l += strlen(r) + 1;  /* -r */
 
-  // extend content if not sufficient
+  /* extend content if not sufficient */
   if (l > pd->acontent)
     {
       pd->content = (char *)realloc(pd->content, l + 256);
       pd->acontent = l + 256;
     }
 
-  // copy e-v-r to content
+  /* copy e-v-r to content */
   c = pd->content;
   if (e)
     {
@@ -228,22 +238,22 @@ evr2id(Pool *pool, Parsedata *pd, const char *e, const char *v, const char *r)
       c += strlen(c);
     }
   *c = 0;
-  // if nothing inserted, return Id 0
+  /* if nothing inserted, return Id 0 */
   if (!*pd->content)
     return ID_NULL;
 #if 0
   fprintf(stderr, "evr: %s\n", pd->content);
 #endif
-  // intern and create
-  return str2id(pool, pd->content, 1);
+  /* intern and create */
+  return pool_str2id(pool, pd->content, 1);
 }
 
 
-// create e:v-r from attributes
-// atts is array of name,value pairs, NULL at end
-//   even index into atts is name
-//   odd index is value
-//
+/* create e:v-r from attributes
+ * atts is array of name,value pairs, NULL at end
+ *   even index into atts is name
+ *   odd index is value
+ */
 static Id
 evr_atts2id(Pool *pool, Parsedata *pd, const char **atts)
 {
@@ -338,11 +348,11 @@ adddep(Pool *pool, Parsedata *pd, unsigned int olddeps, const char **atts, Id ma
          pd->acontent = l + 256;
        }
       sprintf(pd->content, "%s:%s", k, n);
-      name = str2id(pool, pd->content, 1);
+      name = pool_str2id(pool, pd->content, 1);
     }
   else
     {
-      name = str2id(pool, n, 1);       /* package: just intern <name> */
+      name = pool_str2id(pool, n, 1);       /* package: just intern <name> */
     }
 
   if (f)                              /* operator ? */
@@ -360,7 +370,7 @@ adddep(Pool *pool, Parsedata *pd, unsigned int olddeps, const char **atts, Id ma
       if (flags > 7)
        flags = 0;
       /* intern rel */
-      id = rel2id(pool, name, evr, flags, 1);
+      id = pool_rel2id(pool, name, evr, flags, 1);
     }
   else
     id = name;                        /* no operator */
@@ -375,7 +385,7 @@ adddep(Pool *pool, Parsedata *pd, unsigned int olddeps, const char **atts, Id ma
 /*
  * XML callback
  * <name>
- * 
+ *
  */
 
 static void XMLCALL
@@ -415,15 +425,15 @@ startElement(void *userData, const char *name, const char **atts)
 #endif
       return;
     }
-  
-  // set new state
+
+  /* set new state */
   pd->state = sw->to;
 
   pd->docontent = sw->docontent;
   pd->statedepth = pd->depth;
 
-  // start with empty content
-  // (will collect data until end element
+  /* start with empty content */
+  /* (will collect data until end element) */
   pd->lcontent = 0;
   *pd->content = 0;
 
@@ -452,6 +462,8 @@ startElement(void *userData, const char *name, const char **atts)
         pd->kind = "product";
       else if (!strcmp(name, "patch"))
         pd->kind = "patch";
+      else if (!strcmp(name, "application"))
+        pd->kind = "application";
       else
         pd->kind = NULL;              /* default is package */
       pd->levrspace = 1;
@@ -534,7 +546,7 @@ static const char *findKernelFlavor(Parsedata *pd, Solvable *s)
 {
   Pool *pool = pd->pool;
   Id pid, *pidp;
-  
+
   if (s->provides)
     {
       pidp = pd->repo->idarraydata + s->provides;
@@ -542,11 +554,11 @@ static const char *findKernelFlavor(Parsedata *pd, Solvable *s)
        {
          Reldep *prd;
          const char *depname;
-         
+
          if (!ISRELDEP(pid))
            continue;               /* wrong provides name */
          prd = GETRELDEP(pool, pid);
-         depname = id2str(pool, prd->name);
+         depname = pool_id2str(pool, prd->name);
          if (!strncmp(depname, "kernel-", 7))
            return depname + 7;
        }
@@ -561,12 +573,12 @@ static const char *findKernelFlavor(Parsedata *pd, Solvable *s)
 
          if (!ISRELDEP(pid))
            {
-             depname = id2str(pool, pid);
-           } 
-         else 
+             depname = pool_id2str(pool, pid);
+           }
+         else
            {
              Reldep *prd = GETRELDEP(pool, pid);
-             depname = id2str(pool, prd->name);
+             depname = pool_id2str(pool, prd->name);
            }
          if (!strncmp(depname, "kernel-", 7))
            return depname + 7;
@@ -580,7 +592,7 @@ static const char *findKernelFlavor(Parsedata *pd, Solvable *s)
 /*
  * XML callback
  * </name>
- * 
+ *
  * create Solvable from collected data
  */
 
@@ -592,11 +604,12 @@ endElement(void *userData, const char *name)
   Solvable *s = pd->solvable;
   Id evr;
   unsigned int t = 0;
+  const char *flavor;
 
   if (pd->depth != pd->statedepth)
     {
       pd->depth--;
-      // printf("back from unknown %d %d %d\n", pd->state, pd->depth, pd->statedepth);
+      /* printf("back from unknown %d %d %d\n", pd->state, pd->depth, pd->statedepth); */
       return;
     }
 
@@ -610,6 +623,8 @@ endElement(void *userData, const char *name)
     {
 
     case STATE_PACKAGE:                       /* package complete */
+      if (name[0] == 's' && name[1] == 'r' && name[2] == 'c' && s->arch != ARCH_SRC && s->arch != ARCH_NOSRC)
+       s->arch = ARCH_SRC;
       if (!s->arch)                    /* default to "noarch" */
        s->arch = ARCH_NOARCH;
 
@@ -617,19 +632,19 @@ endElement(void *userData, const char *name)
         s->evr = evr2id(pool, pd,
                         pd->epoch   ? pd->evrspace + pd->epoch   : 0,
                         pd->version ? pd->evrspace + pd->version : 0,
-                        pd->release ? pd->evrspace + pd->release : 0);
+                        pd->release ? pd->evrspace + pd->release : "");
       /* ensure self-provides */
       if (s->name && 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);
+        s->provides = repo_addid_dep(pd->repo, s->provides, pool_rel2id(pool, s->name, s->evr, REL_EQ, 1), 0);
       s->supplements = repo_fix_supplements(pd->repo, s->provides, s->supplements, pd->freshens);
       s->conflicts = repo_fix_conflicts(pd->repo, s->conflicts);
       pd->freshens = 0;
 
       /* see bugzilla bnc#190163 */
-      const char *flavor = findKernelFlavor(pd, s);
-      if (flavor) 
+      flavor = findKernelFlavor(pd, s);
+      if (flavor)
        {
-         char *cflavor = strdup(flavor);       /* make pointer safe */
+         char *cflavor = solv_strdup(flavor);  /* make pointer safe */
 
          Id npr;
          Id pid;
@@ -647,11 +662,11 @@ endElement(void *userData, const char *name)
                  if (ISRELDEP(pid))
                    {
                      prd = GETRELDEP(pool, pid);
-                     depname = id2str(pool, prd->name);
+                     depname = pool_id2str(pool, prd->name);
                    }
                  else
                    {
-                     depname = id2str(pool, pid);
+                     depname = pool_id2str(pool, pid);
                    }
 
 
@@ -659,9 +674,9 @@ endElement(void *userData, const char *name)
                    {
                      char newdep[100];
                      snprintf(newdep, sizeof(newdep), "kernel(%s:%s", cflavor, depname + 7);
-                     pid = str2id(pool, newdep, 1);
+                     pid = pool_str2id(pool, newdep, 1);
                      if (prd)
-                       pid = rel2id(pool, pid, prd->evr, prd->flags, 1);
+                       pid = pool_rel2id(pool, pid, prd->evr, prd->flags, 1);
                    }
 
                  npr = repo_addid_dep(pd->repo, npr, pid, 0);
@@ -682,20 +697,20 @@ endElement(void *userData, const char *name)
                  if (ISRELDEP(pid))
                    {
                      prd = GETRELDEP(pool, pid);
-                     depname = id2str(pool, prd->name);
+                     depname = pool_id2str(pool, prd->name);
                    }
                  else
                    {
-                     depname = id2str(pool, pid);
+                     depname = pool_id2str(pool, pid);
                    }
 
                  if (!strncmp(depname, "kernel(", 7) && !strchr(depname, ':'))
                    {
                      char newdep[100];
                      snprintf(newdep, sizeof(newdep), "kernel(%s:%s", cflavor, depname + 7);
-                     pid = str2id(pool, newdep, 1);
+                     pid = pool_str2id(pool, newdep, 1);
                      if (prd)
-                       pid = rel2id(pool, pid, prd->evr, prd->flags, 1);
+                       pid = pool_rel2id(pool, pid, prd->evr, prd->flags, 1);
                    }
                  npr = repo_addid_dep(pd->repo, npr, pid, 0);
                }
@@ -706,10 +721,10 @@ endElement(void *userData, const char *name)
        }
       break;
     case STATE_NAME:
-      s->name = str2id(pool, pd->content, 1);
+      s->name = pool_str2id(pool, pd->content, 1);
       break;
     case STATE_VENDOR:
-      s->vendor = str2id(pool, pd->content, 1);
+      s->vendor = pool_str2id(pool, pd->content, 1);
       break;
     case STATE_BUILDTIME:
       t = atoi (pd->content);
@@ -726,7 +741,7 @@ endElement(void *userData, const char *name)
       pd->version = 0;
       pd->release = 0;
       /* use highest evr */
-      if (!s->evr || evrcmp(pool, s->evr, evr, EVRCMP_MATCH_RELEASE) <= 0)
+      if (!s->evr || pool_evrcmp(pool, s->evr, evr, EVRCMP_COMPARE) <= 0)
        s->evr = evr;
       break;
     case STATE_EPOCH:
@@ -752,21 +767,21 @@ endElement(void *userData, const char *name)
       break;
     case STATE_ARCH:
     case STATE_PARCH:
-      s->arch = str2id(pool, pd->content, 1);
+      s->arch = pool_str2id(pool, pd->content, 1);
       break;
     default:
       break;
     }
   pd->state = pd->sbtab[pd->state];
   pd->docontent = 0;
-  // printf("back from known %d %d %d\n", pd->state, pd->depth, pd->statedepth);
+  /* printf("back from known %d %d %d\n", pd->state, pd->depth, pd->statedepth); */
 }
 
 
 /*
  * XML callback
  * character data
- * 
+ *
  */
 
 static void XMLCALL
@@ -776,18 +791,18 @@ characterData(void *userData, const XML_Char *s, int len)
   int l;
   char *c;
 
-  // check if current nodes content is interesting
+  /* check if current nodes content is interesting */
   if (!pd->docontent)
     return;
 
-  // adapt content buffer
+  /* adapt content buffer */
   l = pd->lcontent + len + 1;
   if (l > pd->acontent)
     {
       pd->content = (char *)realloc(pd->content, l + 256);
       pd->acontent = l + 256;
     }
-  // append new content to buffer
+  /* append new content to buffer */
   c = pd->content + pd->lcontent;
   pd->lcontent += len;
   while (len-- > 0)
@@ -802,10 +817,10 @@ characterData(void *userData, const XML_Char *s, int len)
 /*
  * read 'helix' type xml from fp
  * add packages to pool/repo
- * 
+ *
  */
 
-void
+int
 repo_add_helix(Repo *repo, FILE *fp, int flags)
 {
   Pool *pool = repo->pool;
@@ -815,13 +830,11 @@ repo_add_helix(Repo *repo, FILE *fp, int flags)
   int i, l;
   struct stateswitch *sw;
   unsigned int now;
+  XML_Parser parser;
+
+  now = solv_timems(0);
+  data = repo_add_repodata(repo, flags);
 
-  now = sat_timems(0);
-  if (!(flags & REPO_REUSE_REPODATA))
-    data = repo_add_repodata(repo, 0);
-  else
-    data = repo_last_repodata(repo);
-  
   /* prepare parsedata */
   memset(&pd, 0, sizeof(pd));
   for (i = 0, sw = stateswitches; sw->from != NUMSTATES; i++, sw++)
@@ -843,21 +856,21 @@ repo_add_helix(Repo *repo, FILE *fp, int flags)
   pd.levrspace = 1;
   pd.data = data;
 
-  // set up XML parser
+  /* set up XML parser */
 
-  XML_Parser parser = XML_ParserCreate(NULL);
+  parser = XML_ParserCreate(NULL);
   XML_SetUserData(parser, &pd);       /* make parserdata available to XML callbacks */
   XML_SetElementHandler(parser, startElement, endElement);
   XML_SetCharacterDataHandler(parser, characterData);
 
-  // read/parse XML file
+  /* read/parse XML file */
   for (;;)
     {
       l = fread(buf, 1, sizeof(buf), fp);
       if (XML_Parse(parser, buf, l, l == 0) == XML_STATUS_ERROR)
        {
-         pool_debug(pool, SAT_FATAL, "%s at line %u\n", XML_ErrorString(XML_GetErrorCode(parser)), (unsigned int)XML_GetCurrentLineNumber(parser));
-         exit(1);
+         pd.ret = pool_error(pool, -1, "%s at line %u", XML_ErrorString(XML_GetErrorCode(parser)), (unsigned int)XML_GetCurrentLineNumber(parser));
+         break;
        }
       if (l == 0)
        break;
@@ -868,7 +881,8 @@ repo_add_helix(Repo *repo, FILE *fp, int flags)
 
   if (!(flags & REPO_NO_INTERNALIZE))
     repodata_internalize(data);
-  POOL_DEBUG(SAT_DEBUG_STATS, "repo_add_helix took %d ms\n", sat_timems(now));
-  POOL_DEBUG(SAT_DEBUG_STATS, "repo size: %d solvables\n", repo->nsolvables);
-  POOL_DEBUG(SAT_DEBUG_STATS, "repo memory used: %d K incore, %d K idarray\n", data->incoredatalen/1024, repo->idarraysize / (int)(1024/sizeof(Id)));
+  POOL_DEBUG(SOLV_DEBUG_STATS, "repo_add_helix took %d ms\n", solv_timems(now));
+  POOL_DEBUG(SOLV_DEBUG_STATS, "repo size: %d solvables\n", repo->nsolvables);
+  POOL_DEBUG(SOLV_DEBUG_STATS, "repo memory used: %d K incore, %d K idarray\n", repodata_memused(data)/1024, repo->idarraysize / (int)(1024/sizeof(Id)));
+  return pd.ret;
 }