Imported Upstream version 0.6.8
[platform/upstream/libsolv.git] / ext / repo_helix.c
index 25148fd..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
+  /* 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)
 {
@@ -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,7 +554,7 @@ static const char *findKernelFlavor(Parsedata *pd, Solvable *s)
        {
          Reldep *prd;
          const char *depname;
-         
+
          if (!ISRELDEP(pid))
            continue;               /* wrong provides name */
          prd = GETRELDEP(pool, pid);
@@ -562,8 +574,8 @@ static const char *findKernelFlavor(Parsedata *pd, Solvable *s)
          if (!ISRELDEP(pid))
            {
              depname = pool_id2str(pool, pid);
-           } 
-         else 
+           }
+         else
            {
              Reldep *prd = GETRELDEP(pool, pid);
              depname = pool_id2str(pool, prd->name);
@@ -580,7 +592,7 @@ static const char *findKernelFlavor(Parsedata *pd, Solvable *s)
 /*
  * XML callback
  * </name>
- * 
+ *
  * create Solvable from collected data
  */
 
@@ -597,7 +609,7 @@ endElement(void *userData, const char *name)
   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;
     }
 
@@ -611,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;
 
@@ -618,7 +632,7 @@ 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, pool_rel2id(pool, s->name, s->evr, REL_EQ, 1), 0);
@@ -628,7 +642,7 @@ endElement(void *userData, const char *name)
 
       /* see bugzilla bnc#190163 */
       flavor = findKernelFlavor(pd, s);
-      if (flavor) 
+      if (flavor)
        {
          char *cflavor = solv_strdup(flavor);  /* make pointer safe */
 
@@ -727,7 +741,7 @@ endElement(void *userData, const char *name)
       pd->version = 0;
       pd->release = 0;
       /* use highest evr */
-      if (!s->evr || pool_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:
@@ -760,14 +774,14 @@ endElement(void *userData, const char *name)
     }
   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
@@ -777,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)
@@ -803,7 +817,7 @@ characterData(void *userData, const XML_Char *s, int len)
 /*
  * read 'helix' type xml from fp
  * add packages to pool/repo
- * 
+ *
  */
 
 int
@@ -820,7 +834,7 @@ repo_add_helix(Repo *repo, FILE *fp, int flags)
 
   now = solv_timems(0);
   data = repo_add_repodata(repo, flags);
-  
+
   /* prepare parsedata */
   memset(&pd, 0, sizeof(pd));
   for (i = 0, sw = stateswitches; sw->from != NUMSTATES; i++, sw++)
@@ -842,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 */
 
   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, SOLV_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;
@@ -870,5 +884,5 @@ repo_add_helix(Repo *repo, FILE *fp, int flags)
   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 0;
+  return pd.ret;
 }