- repo_helix does not belong to sat solver core
authorDuncan Mac-Vicar P <dmacvicar@suse.de>
Fri, 1 Aug 2008 12:13:09 +0000 (12:13 +0000)
committerDuncan Mac-Vicar P <dmacvicar@suse.de>
Fri, 1 Aug 2008 12:13:09 +0000 (12:13 +0000)
- adapt deptestomatic compilation to find it in tools/

src/CMakeLists.txt
src/repo_helix.c [deleted file]
src/repo_helix.h [deleted file]
tools/CMakeLists.txt
tools/repo_helix.c [new file with mode: 0644]
tools/repo_helix.h [new file with mode: 0644]

index 3609ff3922388668fc3ddfab041904cebd54242a..da4b1467f5e29c6d3603765c8192c87dd57b7df6 100644 (file)
@@ -1,7 +1,7 @@
 
 SET(libsatsolver_SRCS
     bitmap.c poolarch.c poolvendor.c poolid.c strpool.c dirpool.c
-    solver.c solverdebug.c repo_solv.c repo_helix.c evr.c pool.c
+    solver.c solverdebug.c repo_solv.c evr.c pool.c
     queue.c repo.c repodata.c util.c policy.c fastlz.c solvable.c)
 
 ADD_LIBRARY(satsolver STATIC ${libsatsolver_SRCS})
@@ -9,7 +9,7 @@ ADD_LIBRARY(satsolver STATIC ${libsatsolver_SRCS})
 SET(libsatsolver_HEADERS
     bitmap.h evr.h hash.h policy.h poolarch.h poolvendor.h pool.h
     poolid.h pooltypes.h queue.h solvable.h solver.h solverdebug.h
-    repo.h repodata.h repo_solv.h repo_helix.h util.h
+    repo.h repodata.h repo_solv.h util.h
     strpool.h dirpool.h knownid.h)
 
 SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIC")
diff --git a/src/repo_helix.c b/src/repo_helix.c
deleted file mode 100644 (file)
index c995545..0000000
+++ /dev/null
@@ -1,877 +0,0 @@
-/*
- * Copyright (c) 2007, Novell Inc.
- *
- * This program is licensed under the BSD license, read LICENSE.BSD
- * for further information
- */
-
-/*
- * repo_helix.c
- * 
- * Parse 'helix' XML representation
- * and create 'repo'
- * 
- */
-
-#include <sys/types.h>
-#include <limits.h>
-#include <fcntl.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <expat.h>
-
-#include "repo_helix.h"
-#include "evr.h"
-
-
-/* XML parser states */
-
-enum state {
-  STATE_START,
-  STATE_CHANNEL,
-  STATE_SUBCHANNEL,
-  STATE_PACKAGE,
-  STATE_NAME,
-  STATE_VENDOR,
-  STATE_BUILDTIME,
-  STATE_HISTORY,
-  STATE_UPDATE,
-  STATE_EPOCH,
-  STATE_VERSION,
-  STATE_RELEASE,
-  STATE_ARCH,
-  STATE_PROVIDES,
-  STATE_PROVIDESENTRY,
-  STATE_REQUIRES,
-  STATE_REQUIRESENTRY,
-  STATE_OBSOLETES,
-  STATE_OBSOLETESENTRY,
-  STATE_CONFLICTS,
-  STATE_CONFLICTSENTRY,
-  STATE_RECOMMENDS,
-  STATE_RECOMMENDSENTRY,
-  STATE_SUPPLEMENTS,
-  STATE_SUPPLEMENTSENTRY,
-  STATE_SUGGESTS,
-  STATE_SUGGESTSENTRY,
-  STATE_ENHANCES,
-  STATE_ENHANCESENTRY,
-  STATE_FRESHENS,
-  STATE_FRESHENSENTRY,
-
-  STATE_SELECTTION,
-  STATE_PATTERN,
-  STATE_ATOM,
-  STATE_PATCH,
-  STATE_PRODUCT,
-
-  STATE_PEPOCH,
-  STATE_PVERSION,
-  STATE_PRELEASE,
-  STATE_PARCH,
-
-  NUMSTATES
-};
-
-struct stateswitch {
-  enum state from;
-  char *ename;
-  enum state to;
-  int docontent;
-};
-
-static struct stateswitch stateswitches[] = {
-  { STATE_START,       "channel",         STATE_CHANNEL, 0 },
-  { STATE_CHANNEL,     "subchannel",      STATE_SUBCHANNEL, 0 },
-  { STATE_SUBCHANNEL,  "package",         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_PACKAGE,     "name",            STATE_NAME, 1 },
-  { STATE_PACKAGE,     "vendor",          STATE_VENDOR, 1 },
-  { STATE_PACKAGE,     "buildtime",       STATE_BUILDTIME, 1 },
-  { STATE_PACKAGE,     "epoch",           STATE_PEPOCH, 1 },
-  { STATE_PACKAGE,     "version",         STATE_PVERSION, 1 },
-  { STATE_PACKAGE,     "release",         STATE_PRELEASE, 1 },
-  { STATE_PACKAGE,     "arch",            STATE_PARCH, 1 },
-  { STATE_PACKAGE,     "history",         STATE_HISTORY, 0 },
-  { STATE_PACKAGE,     "provides",        STATE_PROVIDES, 0 },
-  { STATE_PACKAGE,     "requires",        STATE_REQUIRES, 0 },
-  { STATE_PACKAGE,     "obsoletes",       STATE_OBSOLETES , 0 },
-  { STATE_PACKAGE,     "conflicts",       STATE_CONFLICTS , 0 },
-  { STATE_PACKAGE,     "recommends" ,     STATE_RECOMMENDS , 0 },
-  { STATE_PACKAGE,     "supplements",     STATE_SUPPLEMENTS, 0 },
-  { STATE_PACKAGE,     "suggests",        STATE_SUGGESTS, 0 },
-  { STATE_PACKAGE,     "enhances",        STATE_ENHANCES, 0 },
-  { STATE_PACKAGE,     "freshens",        STATE_FRESHENS, 0 },
-
-  { STATE_HISTORY,     "update",          STATE_UPDATE, 0 },
-  { STATE_UPDATE,      "epoch",           STATE_EPOCH, 1 },
-  { STATE_UPDATE,      "version",         STATE_VERSION, 1 },
-  { STATE_UPDATE,      "release",         STATE_RELEASE, 1 },
-  { STATE_UPDATE,      "arch",            STATE_ARCH, 1 },
-
-  { STATE_PROVIDES,    "dep",             STATE_PROVIDESENTRY, 0 },
-  { STATE_REQUIRES,    "dep",             STATE_REQUIRESENTRY, 0 },
-  { STATE_OBSOLETES,   "dep",             STATE_OBSOLETESENTRY, 0 },
-  { STATE_CONFLICTS,   "dep",             STATE_CONFLICTSENTRY, 0 },
-  { STATE_RECOMMENDS,  "dep",             STATE_RECOMMENDSENTRY, 0 },
-  { STATE_SUPPLEMENTS, "dep",             STATE_SUPPLEMENTSENTRY, 0 },
-  { STATE_SUGGESTS,    "dep",             STATE_SUGGESTSENTRY, 0 },
-  { STATE_ENHANCES,    "dep",             STATE_ENHANCESENTRY, 0 },
-  { STATE_FRESHENS,    "dep",             STATE_FRESHENSENTRY, 0 },
-  { NUMSTATES }
-
-};
-
-/*
- * parser data
- */
-
-typedef struct _parsedata {
-  // XML parser data
-  int depth;
-  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 *kind;
-
-  struct stateswitch *swtab[NUMSTATES];
-  enum state sbtab[NUMSTATES];
-} Parsedata;
-
-
-/*------------------------------------------------------------------*/
-/* E:V-R handling */
-
-// create Id from epoch:version-release
-
-static Id
-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;
-
-  if (v && !e)
-    {
-      const char *v2;
-      // scan version for ":"
-      for (v2 = v; *v2 >= '0' && *v2 <= '9'; v2++)     // skip leading digits
-        ;
-      // if version contains ":", set epoch to "0"
-      if (v2 > v && *v2 == ':')
-       e = "0";
-    }
-  
-  // compute length of Id string
-  l = 1;  // for the \0
-  if (e)
-    l += strlen(e) + 1;  // e:
-  if (v)
-    l += strlen(v);      // v
-  if (r)
-    l += strlen(r) + 1;  // -r
-
-  // 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
-  c = pd->content;
-  if (e)
-    {
-      strcpy(c, e);
-      c += strlen(c);
-      *c++ = ':';
-    }
-  if (v)
-    {
-      strcpy(c, v);
-      c += strlen(c);
-    }
-  if (r)
-    {
-      *c++ = '-';
-      strcpy(c, r);
-      c += strlen(c);
-    }
-  *c = 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);
-}
-
-
-// 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)
-{
-  const char *e, *v, *r;
-  e = v = r = 0;
-  for (; *atts; atts += 2)
-    {
-      if (!strcmp(*atts, "epoch"))
-       e = atts[1];
-      else if (!strcmp(*atts, "version"))
-       v = atts[1];
-      else if (!strcmp(*atts, "release"))
-       r = atts[1];
-    }
-  return evr2id(pool, pd, e, v, r);
-}
-
-/*------------------------------------------------------------------*/
-/* rel operator handling */
-
-struct flagtab {
-  char *from;
-  int to;
-};
-
-static struct flagtab flagtab[] = {
-  { ">",  REL_GT },
-  { "=",  REL_EQ },
-  { ">=", REL_GT|REL_EQ },
-  { "<",  REL_LT },
-  { "!=", REL_GT|REL_LT },
-  { "<=", REL_LT|REL_EQ },
-  { "(any)", REL_LT|REL_EQ|REL_GT },
-  { "==", REL_EQ },
-  { "gt", REL_GT },
-  { "eq", REL_EQ },
-  { "ge", REL_GT|REL_EQ },
-  { "lt", REL_LT },
-  { "ne", REL_GT|REL_LT },
-  { "le", REL_LT|REL_EQ },
-  { "gte", REL_GT|REL_EQ },
-  { "lte", REL_LT|REL_EQ },
-  { "GT", REL_GT },
-  { "EQ", REL_EQ },
-  { "GE", REL_GT|REL_EQ },
-  { "LT", REL_LT },
-  { "NE", REL_GT|REL_LT },
-  { "LE", REL_LT|REL_EQ }
-};
-
-/*
- * process new dependency from parser
- *  olddeps = already collected deps, this defines the 'kind' of dep
- *  atts = array of name,value attributes of dep
- *  isreq == 1 if its a requires
- */
-
-static unsigned int
-adddep(Pool *pool, Parsedata *pd, unsigned int olddeps, const char **atts, int isreq)
-{
-  Id id, name, marker;
-  const char *n, *f, *k;
-  const char **a;
-
-  n = f = k = NULL;
-  marker = isreq ? -SOLVABLE_PREREQMARKER : 0;
-
-  /* loop over name,value pairs */
-  for (a = atts; *a; a += 2)
-    {
-      if (!strcmp(*a, "name"))
-       n = a[1];
-      if (!strcmp(*a, "kind"))
-       k = a[1];
-      else if (!strcmp(*a, "op"))
-       f = a[1];
-      else if (isreq && !strcmp(*a, "pre") && a[1][0] == '1')
-        marker = SOLVABLE_PREREQMARKER;
-    }
-  if (!n)                             /* quit if no name found */
-    return olddeps;
-
-  /* kind, name */
-  if (k && !strcmp(k, "package"))
-    k = NULL;                         /* package is default */
-
-  if (k)                              /* if kind!=package, intern <kind>:<name> */
-    {
-      int l = strlen(k) + 1 + strlen(n) + 1;
-      if (l > pd->acontent)           /* extend buffer if needed */
-       {
-         pd->content = (char *)realloc(pd->content, l + 256);
-         pd->acontent = l + 256;
-       }
-      sprintf(pd->content, "%s:%s", k, n);
-      name = str2id(pool, pd->content, 1);
-    }
-  else
-    {
-      name = str2id(pool, n, 1);       /* package: just intern <name> */
-    }
-
-  if (f)                              /* operator ? */
-    {
-      /* intern e:v-r */
-      Id evr = evr_atts2id(pool, pd, atts);
-      /* parser operator to flags */
-      int flags;
-      for (flags = 0; flags < sizeof(flagtab)/sizeof(*flagtab); flags++)
-       if (!strcmp(f, flagtab[flags].from))
-         {
-           flags = flagtab[flags].to;
-           break;
-         }
-      if (flags > 7)
-       flags = 0;
-      /* intern rel */
-      id = rel2id(pool, name, evr, flags, 1);
-    }
-  else
-    id = name;                        /* no operator */
-
-  /* add new dependency to repo */
-  return repo_addid_dep(pd->repo, olddeps, id, marker);
-}
-
-
-/*----------------------------------------------------------------*/
-
-/*
- * XML callback
- * <name>
- * 
- */
-
-static void XMLCALL
-startElement(void *userData, const char *name, const char **atts)
-{
-  Parsedata *pd = (Parsedata *)userData;
-  struct stateswitch *sw;
-  Pool *pool = pd->pool;
-  Solvable *s = pd->solvable;
-
-  if (pd->depth != pd->statedepth)
-    {
-      pd->depth++;
-      return;
-    }
-
-  /* ignore deps element */
-  if (pd->state == STATE_PACKAGE && !strcmp(name, "deps"))
-    return;
-
-  pd->depth++;
-
-  /* find node name in stateswitch */
-  for (sw = pd->swtab[pd->state]; sw->from == pd->state; sw++)
-  {
-    if (!strcmp(sw->ename, name))
-      break;
-  }
-
-  /* check if we're at the right level */
-  if (sw->from != pd->state)
-    {
-#if 0
-      fprintf(stderr, "into unknown: %s\n", name);
-#endif
-      return;
-    }
-  
-  // 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
-  pd->lcontent = 0;
-  *pd->content = 0;
-
-  switch (pd->state)
-    {
-
-    case STATE_NAME:
-      if (pd->kind)                   /* if kind is set (non package) */
-        {
-          strcpy(pd->content, pd->kind);
-          pd->lcontent = strlen(pd->content);
-         pd->content[pd->lcontent++] = ':';   /* prefix name with '<kind>:' */
-         pd->content[pd->lcontent] = 0;
-       }
-      break;
-
-    case STATE_PACKAGE:                       /* solvable name */
-      pd->solvable = pool_id2solvable(pool, repo_add_solvable(pd->repo));
-      if (pd->data)
-       repodata_extend(pd->data, pd->solvable - pool->solvables);
-      
-      if (!strcmp(name, "selection"))
-        pd->kind = "selection";
-      else if (!strcmp(name, "pattern"))
-        pd->kind = "pattern";
-      else if (!strcmp(name, "atom"))
-        pd->kind = "atom";
-      else if (!strcmp(name, "product"))
-        pd->kind = "product";
-      else if (!strcmp(name, "patch"))
-        pd->kind = "patch";
-      else
-        pd->kind = NULL;              /* default is package */
-      pd->levrspace = 1;
-      pd->epoch = 0;
-      pd->version = 0;
-      pd->release = 0;
-      pd->freshens = 0;
-#if 0
-      fprintf(stderr, "package #%d\n", s - pool->solvables);
-#endif
-      break;
-
-    case STATE_UPDATE:
-      pd->levrspace = 1;
-      pd->epoch = 0;
-      pd->version = 0;
-      pd->release = 0;
-      break;
-
-    case STATE_PROVIDES:              /* start of provides */
-      s->provides = 0;
-      break;
-    case STATE_PROVIDESENTRY:         /* entry within provides */
-      s->provides = adddep(pool, pd, s->provides, atts, 0);
-      break;
-    case STATE_REQUIRES:
-      s->requires = 0;
-      break;
-    case STATE_REQUIRESENTRY:
-      s->requires = adddep(pool, pd, s->requires, atts, 1);
-      break;
-    case STATE_OBSOLETES:
-      s->obsoletes = 0;
-      break;
-    case STATE_OBSOLETESENTRY:
-      s->obsoletes = adddep(pool, pd, s->obsoletes, atts, 0);
-      break;
-    case STATE_CONFLICTS:
-      s->conflicts = 0;
-      break;
-    case STATE_CONFLICTSENTRY:
-      s->conflicts = adddep(pool, pd, s->conflicts, atts, 0);
-      break;
-    case STATE_RECOMMENDS:
-      s->recommends = 0;
-      break;
-    case STATE_RECOMMENDSENTRY:
-      s->recommends = adddep(pool, pd, s->recommends, atts, 0);
-      break;
-    case STATE_SUPPLEMENTS:
-      s->supplements= 0;
-      break;
-    case STATE_SUPPLEMENTSENTRY:
-      s->supplements = adddep(pool, pd, s->supplements, atts, 0);
-      break;
-    case STATE_SUGGESTS:
-      s->suggests = 0;
-      break;
-    case STATE_SUGGESTSENTRY:
-      s->suggests = adddep(pool, pd, s->suggests, atts, 0);
-      break;
-    case STATE_ENHANCES:
-      s->enhances = 0;
-      break;
-    case STATE_ENHANCESENTRY:
-      s->enhances = adddep(pool, pd, s->enhances, atts, 0);
-      break;
-    case STATE_FRESHENS:
-      pd->freshens = 0;
-      break;
-    case STATE_FRESHENSENTRY:
-      pd->freshens = adddep(pool, pd, pd->freshens, atts, 0);
-      break;
-    default:
-      break;
-    }
-}
-
-static const char* findKernelFlavor(Parsedata *pd, Solvable *s)
-{
-  Pool *pool = pd->pool;
-
-  Id pid, *pidp = 0;
-  
-  if (s->provides)
-    {
-      for (pidp = pd->repo->idarraydata + s->provides; pidp && (pid = *pidp++) != 0; )
-       {
-         Reldep *prd;
-         const char *depname;
-         
-         if (!ISRELDEP(pid))
-           continue;               /* wrong provides name */
-         prd = GETRELDEP(pool, pid);
-         depname = id2str(pool, prd->name);
-         if (!strncmp(depname, "kernel-", strlen("kernel-")))
-           {
-             return depname + strlen("kernel-");
-           }
-       }
-    }
-
-  if (!s->requires)
-    return 0;
-
-  for (pidp = pd->repo->idarraydata + s->requires ; pidp && (pid = *pidp++) != 0; )
-    {
-      const char *depname = 0;
-
-      if (!ISRELDEP(pid))
-       {
-         depname = id2str(pool, pid);
-       } 
-      else 
-       {
-         Reldep *prd = GETRELDEP(pool, pid);
-         depname = id2str(pool, prd->name);
-       }
-      if (!strncmp(depname, "kernel-", strlen("kernel-")))
-       {
-         return depname + strlen("kernel-");
-       }
-    }
-
-  return 0;
-}
-
-
-/*
- * XML callback
- * </name>
- * 
- * create Solvable from collected data
- */
-
-static void XMLCALL
-endElement(void *userData, const char *name)
-{
-  Parsedata *pd = (Parsedata *)userData;
-  Pool *pool = pd->pool;
-  Solvable *s = pd->solvable;
-  Id evr;
-  unsigned int t=0;
-
-  if (pd->depth != pd->statedepth)
-    {
-      pd->depth--;
-      // printf("back from unknown %d %d %d\n", pd->state, pd->depth, pd->statedepth);
-      return;
-    }
-
-  /* ignore deps element */
-  if (pd->state == STATE_PACKAGE && !strcmp(name, "deps"))
-    return;
-
-  pd->depth--;
-  pd->statedepth--;
-  switch (pd->state)
-    {
-
-    case STATE_PACKAGE:                       /* package complete */
-      if (!s->arch)                    /* default to "noarch" */
-       s->arch = ARCH_NOARCH;
-
-      if (!s->evr && pd->version)      /* set solvable evr */
-        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);
-      /* ensure self-provides */
-      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);
-      s->supplements = repo_fix_legacy(pd->repo, s->provides, s->supplements, pd->freshens);
-      pd->freshens = 0;
-
-      /* see bugzilla bnc#190163 */
-      const char *flavor = findKernelFlavor(pd, s);
-      if (flavor) 
-       {
-         char *cflavor = strdup(flavor);       /* make pointer safe */
-
-         Id npr;
-         Id pid;
-
-         /* this is either a kernel package or a kmp */
-         if (s->provides)
-           {
-             Offset prov = s->provides;
-             npr = 0;
-             while ((pid = pd->repo->idarraydata[prov++]) != 0)
-               {
-                 const char *depname = 0;
-                 Reldep *prd = 0;
-
-                 if (ISRELDEP(pid))
-                   {
-                     prd = GETRELDEP(pool, pid);
-                     depname = id2str(pool, prd->name);
-                   }
-                 else
-                   {
-                     depname = id2str(pool, pid);
-                   }
-
-
-                 if (!strncmp(depname, "kernel(", strlen("kernel(")) && !strchr(depname, ':'))
-                   {
-                     char newdep[100];
-                     strcpy(newdep, "kernel(");
-                     strncat(newdep, cflavor, sizeof(newdep) - 1);
-                     strncat(newdep, ":", sizeof(newdep) - 1);
-                     strncat(newdep, depname + strlen("kernel("), sizeof(newdep) - 1);
-                     pid = str2id(pool, newdep, 1);
-                     if (prd)
-                       pid = rel2id(pool, pid, prd->evr, prd->flags, 1);
-                   }
-
-                 npr = repo_addid_dep(pd->repo, npr, pid, 0);
-               }
-             s->provides = npr;
-           }
-#if 1
-
-         if (s->requires)
-           {
-             Offset reqs = s->requires;
-             npr = 0;
-             while ((pid = pd->repo->idarraydata[reqs++]) != 0)
-               {
-                 const char *depname = 0;
-                 Reldep *prd = 0;
-
-                 if (ISRELDEP(pid))
-                   {
-                     prd = GETRELDEP(pool, pid);
-                     depname = id2str(pool, prd->name);
-                   }
-                 else
-                   {
-                     depname = id2str(pool, pid);
-                   }
-
-                 if (!strncmp(depname, "kernel(", strlen("kernel(")) && !strchr(depname, ':'))
-                   {
-                     char newdep[100];
-                     strcpy(newdep, "kernel(");
-                     strncat(newdep, cflavor, sizeof(newdep) - 1);
-                     strncat(newdep, ":", sizeof(newdep) - 1);
-                     strncat(newdep, depname + strlen("kernel("), sizeof(newdep) - 1);
-                     pid = str2id(pool, newdep, 1);
-                     if (prd)
-                       pid = rel2id(pool, pid, prd->evr, prd->flags, 1);
-                   }
-                 npr = repo_addid_dep(pd->repo, npr, pid, 0);
-               }
-             s->requires = npr;
-           }
-#endif
-         free(cflavor);
-       }
-      break;
-    case STATE_NAME:
-      s->name = str2id(pool, pd->content, 1);
-      break;
-    case STATE_VENDOR:
-      s->vendor = str2id(pool, pd->content, 1);
-      break;
-    case STATE_BUILDTIME:
-      t = atoi (pd->content);
-      if (t)
-       repodata_set_num(pd->data, repodata_get_handle(pd->data, (s - pool->solvables) - pd->repo->start), SOLVABLE_BUILDTIME, t);
-      break;   
-    case STATE_UPDATE:                /* new version, keeping all other metadata */
-      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->levrspace = 1;
-      pd->epoch = 0;
-      pd->version = 0;
-      pd->release = 0;
-      /* use highest evr */
-      if (!s->evr || evrcmp(pool, s->evr, evr, EVRCMP_MATCH_RELEASE) <= 0)
-       s->evr = evr;
-      break;
-    case STATE_EPOCH:
-    case STATE_VERSION:
-    case STATE_RELEASE:
-    case STATE_PEPOCH:
-    case STATE_PVERSION:
-    case STATE_PRELEASE:
-      /* ensure buffer space */
-      if (pd->lcontent + 1 + pd->levrspace > pd->aevrspace)
-       {
-         pd->evrspace = (char *)realloc(pd->evrspace, pd->lcontent + 1 + pd->levrspace + 256);
-         pd->aevrspace = pd->lcontent + 1 + pd->levrspace + 256;
-       }
-      memcpy(pd->evrspace + pd->levrspace, pd->content, pd->lcontent + 1);
-      if (pd->state == STATE_EPOCH || pd->state == STATE_PEPOCH)
-       pd->epoch = pd->levrspace;
-      else if (pd->state == STATE_VERSION || pd->state == STATE_PVERSION)
-       pd->version = pd->levrspace;
-      else
-       pd->release = pd->levrspace;
-      pd->levrspace += pd->lcontent + 1;
-      break;
-    case STATE_ARCH:
-    case STATE_PARCH:
-      s->arch = 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);
-}
-
-
-/*
- * XML callback
- * character data
- * 
- */
-
-static void XMLCALL
-characterData(void *userData, const XML_Char *s, int len)
-{
-  Parsedata *pd = (Parsedata *)userData;
-  int l;
-  char *c;
-
-  // check if current nodes content is interesting
-  if (!pd->docontent)
-    return;
-
-  // 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
-  c = pd->content + pd->lcontent;
-  pd->lcontent += len;
-  while (len-- > 0)
-    *c++ = *s++;
-  *c = 0;
-}
-
-/*-------------------------------------------------------------------*/
-
-#define BUFF_SIZE 8192
-
-/*
- * read 'helix' type xml from fp
- * add packages to pool/repo
- * 
- */
-
-void
-repo_add_helix(Repo *repo, FILE *fp)
-{
-  Pool *pool = repo->pool;
-  Parsedata pd;
-  Repodata *data = 0;
-  char buf[BUFF_SIZE];
-  int i, l;
-  struct stateswitch *sw;
-
-  if (repo->nrepodata)
-    /* use last repodata */
-    data = repo->repodata + repo->nrepodata - 1;
-  else
-    data = repo_add_repodata(repo, 0);
-  
-  /* prepare parsedata */
-  memset(&pd, 0, sizeof(pd));
-  for (i = 0, sw = stateswitches; sw->from != NUMSTATES; i++, sw++)
-    {
-      if (!pd.swtab[sw->from])
-        pd.swtab[sw->from] = sw;
-      pd.sbtab[sw->to] = sw->from;
-    }
-
-  pd.pool = pool;
-  pd.repo = repo;
-
-  pd.content = (char *)malloc(256);    /* must hold all solvable kinds! */
-  pd.acontent = 256;
-  pd.lcontent = 0;
-
-  pd.evrspace = (char *)malloc(256);
-  pd.aevrspace= 256;
-  pd.levrspace = 1;
-  pd.data = data;
-
-  // set up XML parser
-
-  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
-  for (;;)
-    {
-      l = fread(buf, 1, sizeof(buf), fp);
-      if (XML_Parse(parser, buf, l, l == 0) == XML_STATUS_ERROR)
-       {
-         fprintf(stderr, "%s at line %u\n", XML_ErrorString(XML_GetErrorCode(parser)), (unsigned int)XML_GetCurrentLineNumber(parser));
-         exit(1);
-       }
-      if (l == 0)
-       break;
-    }
-  XML_ParserFree(parser);
-
-  if (pd.data)
-    repodata_internalize(pd.data);
-
-  free(pd.content);
-  free(pd.evrspace);
-}
diff --git a/src/repo_helix.h b/src/repo_helix.h
deleted file mode 100644 (file)
index 4ab0862..0000000
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright (c) 2007, Novell Inc.
- *
- * This program is licensed under the BSD license, read LICENSE.BSD
- * for further information
- */
-
-/*
- * repo_helix.h
- * 
- */
-
-#ifndef SATSOLVER_REPO_HELIX_H
-#define SATSOLVER_REPO_HELIX_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include <stdio.h>
-#include "pool.h"
-#include "repo.h"
-
-extern void repo_add_helix(Repo *repo, FILE *fp);
-
-#ifdef __cplusplus
-}
-#endif
-    
-
-#endif /* SATSOLVER_REPO_HELIX_H */
index 5299d7009300be40b9f770f965e9d445d287107a..54c4ccac4dc41b19417c7e321175db7e29d4f4ca 100644 (file)
@@ -25,7 +25,7 @@ SET(rpmmd2solv_REPOS rpmmd2solv.c repo_rpmmd.h repo_rpmmd.c repo_write.c common_
 ADD_EXECUTABLE( rpmmd2solv ${rpmmd2solv_REPOS} )
 TARGET_LINK_LIBRARIES( rpmmd2solv satsolver ${EXPAT_LIBRARY} ${ZLIB_LIBRARY})
 
-SET(helix2solv_REPOS helix2solv.c repo_write.c common_write.c )
+SET(helix2solv_REPOS helix2solv.c repo_helix.c repo_helix.h repo_write.c common_write.c )
 ADD_EXECUTABLE( helix2solv ${helix2solv_REPOS} )
 TARGET_LINK_LIBRARIES( helix2solv satsolver ${EXPAT_LIBRARY})
 
diff --git a/tools/repo_helix.c b/tools/repo_helix.c
new file mode 100644 (file)
index 0000000..c995545
--- /dev/null
@@ -0,0 +1,877 @@
+/*
+ * Copyright (c) 2007, Novell Inc.
+ *
+ * This program is licensed under the BSD license, read LICENSE.BSD
+ * for further information
+ */
+
+/*
+ * repo_helix.c
+ * 
+ * Parse 'helix' XML representation
+ * and create 'repo'
+ * 
+ */
+
+#include <sys/types.h>
+#include <limits.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <expat.h>
+
+#include "repo_helix.h"
+#include "evr.h"
+
+
+/* XML parser states */
+
+enum state {
+  STATE_START,
+  STATE_CHANNEL,
+  STATE_SUBCHANNEL,
+  STATE_PACKAGE,
+  STATE_NAME,
+  STATE_VENDOR,
+  STATE_BUILDTIME,
+  STATE_HISTORY,
+  STATE_UPDATE,
+  STATE_EPOCH,
+  STATE_VERSION,
+  STATE_RELEASE,
+  STATE_ARCH,
+  STATE_PROVIDES,
+  STATE_PROVIDESENTRY,
+  STATE_REQUIRES,
+  STATE_REQUIRESENTRY,
+  STATE_OBSOLETES,
+  STATE_OBSOLETESENTRY,
+  STATE_CONFLICTS,
+  STATE_CONFLICTSENTRY,
+  STATE_RECOMMENDS,
+  STATE_RECOMMENDSENTRY,
+  STATE_SUPPLEMENTS,
+  STATE_SUPPLEMENTSENTRY,
+  STATE_SUGGESTS,
+  STATE_SUGGESTSENTRY,
+  STATE_ENHANCES,
+  STATE_ENHANCESENTRY,
+  STATE_FRESHENS,
+  STATE_FRESHENSENTRY,
+
+  STATE_SELECTTION,
+  STATE_PATTERN,
+  STATE_ATOM,
+  STATE_PATCH,
+  STATE_PRODUCT,
+
+  STATE_PEPOCH,
+  STATE_PVERSION,
+  STATE_PRELEASE,
+  STATE_PARCH,
+
+  NUMSTATES
+};
+
+struct stateswitch {
+  enum state from;
+  char *ename;
+  enum state to;
+  int docontent;
+};
+
+static struct stateswitch stateswitches[] = {
+  { STATE_START,       "channel",         STATE_CHANNEL, 0 },
+  { STATE_CHANNEL,     "subchannel",      STATE_SUBCHANNEL, 0 },
+  { STATE_SUBCHANNEL,  "package",         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_PACKAGE,     "name",            STATE_NAME, 1 },
+  { STATE_PACKAGE,     "vendor",          STATE_VENDOR, 1 },
+  { STATE_PACKAGE,     "buildtime",       STATE_BUILDTIME, 1 },
+  { STATE_PACKAGE,     "epoch",           STATE_PEPOCH, 1 },
+  { STATE_PACKAGE,     "version",         STATE_PVERSION, 1 },
+  { STATE_PACKAGE,     "release",         STATE_PRELEASE, 1 },
+  { STATE_PACKAGE,     "arch",            STATE_PARCH, 1 },
+  { STATE_PACKAGE,     "history",         STATE_HISTORY, 0 },
+  { STATE_PACKAGE,     "provides",        STATE_PROVIDES, 0 },
+  { STATE_PACKAGE,     "requires",        STATE_REQUIRES, 0 },
+  { STATE_PACKAGE,     "obsoletes",       STATE_OBSOLETES , 0 },
+  { STATE_PACKAGE,     "conflicts",       STATE_CONFLICTS , 0 },
+  { STATE_PACKAGE,     "recommends" ,     STATE_RECOMMENDS , 0 },
+  { STATE_PACKAGE,     "supplements",     STATE_SUPPLEMENTS, 0 },
+  { STATE_PACKAGE,     "suggests",        STATE_SUGGESTS, 0 },
+  { STATE_PACKAGE,     "enhances",        STATE_ENHANCES, 0 },
+  { STATE_PACKAGE,     "freshens",        STATE_FRESHENS, 0 },
+
+  { STATE_HISTORY,     "update",          STATE_UPDATE, 0 },
+  { STATE_UPDATE,      "epoch",           STATE_EPOCH, 1 },
+  { STATE_UPDATE,      "version",         STATE_VERSION, 1 },
+  { STATE_UPDATE,      "release",         STATE_RELEASE, 1 },
+  { STATE_UPDATE,      "arch",            STATE_ARCH, 1 },
+
+  { STATE_PROVIDES,    "dep",             STATE_PROVIDESENTRY, 0 },
+  { STATE_REQUIRES,    "dep",             STATE_REQUIRESENTRY, 0 },
+  { STATE_OBSOLETES,   "dep",             STATE_OBSOLETESENTRY, 0 },
+  { STATE_CONFLICTS,   "dep",             STATE_CONFLICTSENTRY, 0 },
+  { STATE_RECOMMENDS,  "dep",             STATE_RECOMMENDSENTRY, 0 },
+  { STATE_SUPPLEMENTS, "dep",             STATE_SUPPLEMENTSENTRY, 0 },
+  { STATE_SUGGESTS,    "dep",             STATE_SUGGESTSENTRY, 0 },
+  { STATE_ENHANCES,    "dep",             STATE_ENHANCESENTRY, 0 },
+  { STATE_FRESHENS,    "dep",             STATE_FRESHENSENTRY, 0 },
+  { NUMSTATES }
+
+};
+
+/*
+ * parser data
+ */
+
+typedef struct _parsedata {
+  // XML parser data
+  int depth;
+  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 *kind;
+
+  struct stateswitch *swtab[NUMSTATES];
+  enum state sbtab[NUMSTATES];
+} Parsedata;
+
+
+/*------------------------------------------------------------------*/
+/* E:V-R handling */
+
+// create Id from epoch:version-release
+
+static Id
+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;
+
+  if (v && !e)
+    {
+      const char *v2;
+      // scan version for ":"
+      for (v2 = v; *v2 >= '0' && *v2 <= '9'; v2++)     // skip leading digits
+        ;
+      // if version contains ":", set epoch to "0"
+      if (v2 > v && *v2 == ':')
+       e = "0";
+    }
+  
+  // compute length of Id string
+  l = 1;  // for the \0
+  if (e)
+    l += strlen(e) + 1;  // e:
+  if (v)
+    l += strlen(v);      // v
+  if (r)
+    l += strlen(r) + 1;  // -r
+
+  // 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
+  c = pd->content;
+  if (e)
+    {
+      strcpy(c, e);
+      c += strlen(c);
+      *c++ = ':';
+    }
+  if (v)
+    {
+      strcpy(c, v);
+      c += strlen(c);
+    }
+  if (r)
+    {
+      *c++ = '-';
+      strcpy(c, r);
+      c += strlen(c);
+    }
+  *c = 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);
+}
+
+
+// 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)
+{
+  const char *e, *v, *r;
+  e = v = r = 0;
+  for (; *atts; atts += 2)
+    {
+      if (!strcmp(*atts, "epoch"))
+       e = atts[1];
+      else if (!strcmp(*atts, "version"))
+       v = atts[1];
+      else if (!strcmp(*atts, "release"))
+       r = atts[1];
+    }
+  return evr2id(pool, pd, e, v, r);
+}
+
+/*------------------------------------------------------------------*/
+/* rel operator handling */
+
+struct flagtab {
+  char *from;
+  int to;
+};
+
+static struct flagtab flagtab[] = {
+  { ">",  REL_GT },
+  { "=",  REL_EQ },
+  { ">=", REL_GT|REL_EQ },
+  { "<",  REL_LT },
+  { "!=", REL_GT|REL_LT },
+  { "<=", REL_LT|REL_EQ },
+  { "(any)", REL_LT|REL_EQ|REL_GT },
+  { "==", REL_EQ },
+  { "gt", REL_GT },
+  { "eq", REL_EQ },
+  { "ge", REL_GT|REL_EQ },
+  { "lt", REL_LT },
+  { "ne", REL_GT|REL_LT },
+  { "le", REL_LT|REL_EQ },
+  { "gte", REL_GT|REL_EQ },
+  { "lte", REL_LT|REL_EQ },
+  { "GT", REL_GT },
+  { "EQ", REL_EQ },
+  { "GE", REL_GT|REL_EQ },
+  { "LT", REL_LT },
+  { "NE", REL_GT|REL_LT },
+  { "LE", REL_LT|REL_EQ }
+};
+
+/*
+ * process new dependency from parser
+ *  olddeps = already collected deps, this defines the 'kind' of dep
+ *  atts = array of name,value attributes of dep
+ *  isreq == 1 if its a requires
+ */
+
+static unsigned int
+adddep(Pool *pool, Parsedata *pd, unsigned int olddeps, const char **atts, int isreq)
+{
+  Id id, name, marker;
+  const char *n, *f, *k;
+  const char **a;
+
+  n = f = k = NULL;
+  marker = isreq ? -SOLVABLE_PREREQMARKER : 0;
+
+  /* loop over name,value pairs */
+  for (a = atts; *a; a += 2)
+    {
+      if (!strcmp(*a, "name"))
+       n = a[1];
+      if (!strcmp(*a, "kind"))
+       k = a[1];
+      else if (!strcmp(*a, "op"))
+       f = a[1];
+      else if (isreq && !strcmp(*a, "pre") && a[1][0] == '1')
+        marker = SOLVABLE_PREREQMARKER;
+    }
+  if (!n)                             /* quit if no name found */
+    return olddeps;
+
+  /* kind, name */
+  if (k && !strcmp(k, "package"))
+    k = NULL;                         /* package is default */
+
+  if (k)                              /* if kind!=package, intern <kind>:<name> */
+    {
+      int l = strlen(k) + 1 + strlen(n) + 1;
+      if (l > pd->acontent)           /* extend buffer if needed */
+       {
+         pd->content = (char *)realloc(pd->content, l + 256);
+         pd->acontent = l + 256;
+       }
+      sprintf(pd->content, "%s:%s", k, n);
+      name = str2id(pool, pd->content, 1);
+    }
+  else
+    {
+      name = str2id(pool, n, 1);       /* package: just intern <name> */
+    }
+
+  if (f)                              /* operator ? */
+    {
+      /* intern e:v-r */
+      Id evr = evr_atts2id(pool, pd, atts);
+      /* parser operator to flags */
+      int flags;
+      for (flags = 0; flags < sizeof(flagtab)/sizeof(*flagtab); flags++)
+       if (!strcmp(f, flagtab[flags].from))
+         {
+           flags = flagtab[flags].to;
+           break;
+         }
+      if (flags > 7)
+       flags = 0;
+      /* intern rel */
+      id = rel2id(pool, name, evr, flags, 1);
+    }
+  else
+    id = name;                        /* no operator */
+
+  /* add new dependency to repo */
+  return repo_addid_dep(pd->repo, olddeps, id, marker);
+}
+
+
+/*----------------------------------------------------------------*/
+
+/*
+ * XML callback
+ * <name>
+ * 
+ */
+
+static void XMLCALL
+startElement(void *userData, const char *name, const char **atts)
+{
+  Parsedata *pd = (Parsedata *)userData;
+  struct stateswitch *sw;
+  Pool *pool = pd->pool;
+  Solvable *s = pd->solvable;
+
+  if (pd->depth != pd->statedepth)
+    {
+      pd->depth++;
+      return;
+    }
+
+  /* ignore deps element */
+  if (pd->state == STATE_PACKAGE && !strcmp(name, "deps"))
+    return;
+
+  pd->depth++;
+
+  /* find node name in stateswitch */
+  for (sw = pd->swtab[pd->state]; sw->from == pd->state; sw++)
+  {
+    if (!strcmp(sw->ename, name))
+      break;
+  }
+
+  /* check if we're at the right level */
+  if (sw->from != pd->state)
+    {
+#if 0
+      fprintf(stderr, "into unknown: %s\n", name);
+#endif
+      return;
+    }
+  
+  // 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
+  pd->lcontent = 0;
+  *pd->content = 0;
+
+  switch (pd->state)
+    {
+
+    case STATE_NAME:
+      if (pd->kind)                   /* if kind is set (non package) */
+        {
+          strcpy(pd->content, pd->kind);
+          pd->lcontent = strlen(pd->content);
+         pd->content[pd->lcontent++] = ':';   /* prefix name with '<kind>:' */
+         pd->content[pd->lcontent] = 0;
+       }
+      break;
+
+    case STATE_PACKAGE:                       /* solvable name */
+      pd->solvable = pool_id2solvable(pool, repo_add_solvable(pd->repo));
+      if (pd->data)
+       repodata_extend(pd->data, pd->solvable - pool->solvables);
+      
+      if (!strcmp(name, "selection"))
+        pd->kind = "selection";
+      else if (!strcmp(name, "pattern"))
+        pd->kind = "pattern";
+      else if (!strcmp(name, "atom"))
+        pd->kind = "atom";
+      else if (!strcmp(name, "product"))
+        pd->kind = "product";
+      else if (!strcmp(name, "patch"))
+        pd->kind = "patch";
+      else
+        pd->kind = NULL;              /* default is package */
+      pd->levrspace = 1;
+      pd->epoch = 0;
+      pd->version = 0;
+      pd->release = 0;
+      pd->freshens = 0;
+#if 0
+      fprintf(stderr, "package #%d\n", s - pool->solvables);
+#endif
+      break;
+
+    case STATE_UPDATE:
+      pd->levrspace = 1;
+      pd->epoch = 0;
+      pd->version = 0;
+      pd->release = 0;
+      break;
+
+    case STATE_PROVIDES:              /* start of provides */
+      s->provides = 0;
+      break;
+    case STATE_PROVIDESENTRY:         /* entry within provides */
+      s->provides = adddep(pool, pd, s->provides, atts, 0);
+      break;
+    case STATE_REQUIRES:
+      s->requires = 0;
+      break;
+    case STATE_REQUIRESENTRY:
+      s->requires = adddep(pool, pd, s->requires, atts, 1);
+      break;
+    case STATE_OBSOLETES:
+      s->obsoletes = 0;
+      break;
+    case STATE_OBSOLETESENTRY:
+      s->obsoletes = adddep(pool, pd, s->obsoletes, atts, 0);
+      break;
+    case STATE_CONFLICTS:
+      s->conflicts = 0;
+      break;
+    case STATE_CONFLICTSENTRY:
+      s->conflicts = adddep(pool, pd, s->conflicts, atts, 0);
+      break;
+    case STATE_RECOMMENDS:
+      s->recommends = 0;
+      break;
+    case STATE_RECOMMENDSENTRY:
+      s->recommends = adddep(pool, pd, s->recommends, atts, 0);
+      break;
+    case STATE_SUPPLEMENTS:
+      s->supplements= 0;
+      break;
+    case STATE_SUPPLEMENTSENTRY:
+      s->supplements = adddep(pool, pd, s->supplements, atts, 0);
+      break;
+    case STATE_SUGGESTS:
+      s->suggests = 0;
+      break;
+    case STATE_SUGGESTSENTRY:
+      s->suggests = adddep(pool, pd, s->suggests, atts, 0);
+      break;
+    case STATE_ENHANCES:
+      s->enhances = 0;
+      break;
+    case STATE_ENHANCESENTRY:
+      s->enhances = adddep(pool, pd, s->enhances, atts, 0);
+      break;
+    case STATE_FRESHENS:
+      pd->freshens = 0;
+      break;
+    case STATE_FRESHENSENTRY:
+      pd->freshens = adddep(pool, pd, pd->freshens, atts, 0);
+      break;
+    default:
+      break;
+    }
+}
+
+static const char* findKernelFlavor(Parsedata *pd, Solvable *s)
+{
+  Pool *pool = pd->pool;
+
+  Id pid, *pidp = 0;
+  
+  if (s->provides)
+    {
+      for (pidp = pd->repo->idarraydata + s->provides; pidp && (pid = *pidp++) != 0; )
+       {
+         Reldep *prd;
+         const char *depname;
+         
+         if (!ISRELDEP(pid))
+           continue;               /* wrong provides name */
+         prd = GETRELDEP(pool, pid);
+         depname = id2str(pool, prd->name);
+         if (!strncmp(depname, "kernel-", strlen("kernel-")))
+           {
+             return depname + strlen("kernel-");
+           }
+       }
+    }
+
+  if (!s->requires)
+    return 0;
+
+  for (pidp = pd->repo->idarraydata + s->requires ; pidp && (pid = *pidp++) != 0; )
+    {
+      const char *depname = 0;
+
+      if (!ISRELDEP(pid))
+       {
+         depname = id2str(pool, pid);
+       } 
+      else 
+       {
+         Reldep *prd = GETRELDEP(pool, pid);
+         depname = id2str(pool, prd->name);
+       }
+      if (!strncmp(depname, "kernel-", strlen("kernel-")))
+       {
+         return depname + strlen("kernel-");
+       }
+    }
+
+  return 0;
+}
+
+
+/*
+ * XML callback
+ * </name>
+ * 
+ * create Solvable from collected data
+ */
+
+static void XMLCALL
+endElement(void *userData, const char *name)
+{
+  Parsedata *pd = (Parsedata *)userData;
+  Pool *pool = pd->pool;
+  Solvable *s = pd->solvable;
+  Id evr;
+  unsigned int t=0;
+
+  if (pd->depth != pd->statedepth)
+    {
+      pd->depth--;
+      // printf("back from unknown %d %d %d\n", pd->state, pd->depth, pd->statedepth);
+      return;
+    }
+
+  /* ignore deps element */
+  if (pd->state == STATE_PACKAGE && !strcmp(name, "deps"))
+    return;
+
+  pd->depth--;
+  pd->statedepth--;
+  switch (pd->state)
+    {
+
+    case STATE_PACKAGE:                       /* package complete */
+      if (!s->arch)                    /* default to "noarch" */
+       s->arch = ARCH_NOARCH;
+
+      if (!s->evr && pd->version)      /* set solvable evr */
+        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);
+      /* ensure self-provides */
+      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);
+      s->supplements = repo_fix_legacy(pd->repo, s->provides, s->supplements, pd->freshens);
+      pd->freshens = 0;
+
+      /* see bugzilla bnc#190163 */
+      const char *flavor = findKernelFlavor(pd, s);
+      if (flavor) 
+       {
+         char *cflavor = strdup(flavor);       /* make pointer safe */
+
+         Id npr;
+         Id pid;
+
+         /* this is either a kernel package or a kmp */
+         if (s->provides)
+           {
+             Offset prov = s->provides;
+             npr = 0;
+             while ((pid = pd->repo->idarraydata[prov++]) != 0)
+               {
+                 const char *depname = 0;
+                 Reldep *prd = 0;
+
+                 if (ISRELDEP(pid))
+                   {
+                     prd = GETRELDEP(pool, pid);
+                     depname = id2str(pool, prd->name);
+                   }
+                 else
+                   {
+                     depname = id2str(pool, pid);
+                   }
+
+
+                 if (!strncmp(depname, "kernel(", strlen("kernel(")) && !strchr(depname, ':'))
+                   {
+                     char newdep[100];
+                     strcpy(newdep, "kernel(");
+                     strncat(newdep, cflavor, sizeof(newdep) - 1);
+                     strncat(newdep, ":", sizeof(newdep) - 1);
+                     strncat(newdep, depname + strlen("kernel("), sizeof(newdep) - 1);
+                     pid = str2id(pool, newdep, 1);
+                     if (prd)
+                       pid = rel2id(pool, pid, prd->evr, prd->flags, 1);
+                   }
+
+                 npr = repo_addid_dep(pd->repo, npr, pid, 0);
+               }
+             s->provides = npr;
+           }
+#if 1
+
+         if (s->requires)
+           {
+             Offset reqs = s->requires;
+             npr = 0;
+             while ((pid = pd->repo->idarraydata[reqs++]) != 0)
+               {
+                 const char *depname = 0;
+                 Reldep *prd = 0;
+
+                 if (ISRELDEP(pid))
+                   {
+                     prd = GETRELDEP(pool, pid);
+                     depname = id2str(pool, prd->name);
+                   }
+                 else
+                   {
+                     depname = id2str(pool, pid);
+                   }
+
+                 if (!strncmp(depname, "kernel(", strlen("kernel(")) && !strchr(depname, ':'))
+                   {
+                     char newdep[100];
+                     strcpy(newdep, "kernel(");
+                     strncat(newdep, cflavor, sizeof(newdep) - 1);
+                     strncat(newdep, ":", sizeof(newdep) - 1);
+                     strncat(newdep, depname + strlen("kernel("), sizeof(newdep) - 1);
+                     pid = str2id(pool, newdep, 1);
+                     if (prd)
+                       pid = rel2id(pool, pid, prd->evr, prd->flags, 1);
+                   }
+                 npr = repo_addid_dep(pd->repo, npr, pid, 0);
+               }
+             s->requires = npr;
+           }
+#endif
+         free(cflavor);
+       }
+      break;
+    case STATE_NAME:
+      s->name = str2id(pool, pd->content, 1);
+      break;
+    case STATE_VENDOR:
+      s->vendor = str2id(pool, pd->content, 1);
+      break;
+    case STATE_BUILDTIME:
+      t = atoi (pd->content);
+      if (t)
+       repodata_set_num(pd->data, repodata_get_handle(pd->data, (s - pool->solvables) - pd->repo->start), SOLVABLE_BUILDTIME, t);
+      break;   
+    case STATE_UPDATE:                /* new version, keeping all other metadata */
+      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->levrspace = 1;
+      pd->epoch = 0;
+      pd->version = 0;
+      pd->release = 0;
+      /* use highest evr */
+      if (!s->evr || evrcmp(pool, s->evr, evr, EVRCMP_MATCH_RELEASE) <= 0)
+       s->evr = evr;
+      break;
+    case STATE_EPOCH:
+    case STATE_VERSION:
+    case STATE_RELEASE:
+    case STATE_PEPOCH:
+    case STATE_PVERSION:
+    case STATE_PRELEASE:
+      /* ensure buffer space */
+      if (pd->lcontent + 1 + pd->levrspace > pd->aevrspace)
+       {
+         pd->evrspace = (char *)realloc(pd->evrspace, pd->lcontent + 1 + pd->levrspace + 256);
+         pd->aevrspace = pd->lcontent + 1 + pd->levrspace + 256;
+       }
+      memcpy(pd->evrspace + pd->levrspace, pd->content, pd->lcontent + 1);
+      if (pd->state == STATE_EPOCH || pd->state == STATE_PEPOCH)
+       pd->epoch = pd->levrspace;
+      else if (pd->state == STATE_VERSION || pd->state == STATE_PVERSION)
+       pd->version = pd->levrspace;
+      else
+       pd->release = pd->levrspace;
+      pd->levrspace += pd->lcontent + 1;
+      break;
+    case STATE_ARCH:
+    case STATE_PARCH:
+      s->arch = 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);
+}
+
+
+/*
+ * XML callback
+ * character data
+ * 
+ */
+
+static void XMLCALL
+characterData(void *userData, const XML_Char *s, int len)
+{
+  Parsedata *pd = (Parsedata *)userData;
+  int l;
+  char *c;
+
+  // check if current nodes content is interesting
+  if (!pd->docontent)
+    return;
+
+  // 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
+  c = pd->content + pd->lcontent;
+  pd->lcontent += len;
+  while (len-- > 0)
+    *c++ = *s++;
+  *c = 0;
+}
+
+/*-------------------------------------------------------------------*/
+
+#define BUFF_SIZE 8192
+
+/*
+ * read 'helix' type xml from fp
+ * add packages to pool/repo
+ * 
+ */
+
+void
+repo_add_helix(Repo *repo, FILE *fp)
+{
+  Pool *pool = repo->pool;
+  Parsedata pd;
+  Repodata *data = 0;
+  char buf[BUFF_SIZE];
+  int i, l;
+  struct stateswitch *sw;
+
+  if (repo->nrepodata)
+    /* use last repodata */
+    data = repo->repodata + repo->nrepodata - 1;
+  else
+    data = repo_add_repodata(repo, 0);
+  
+  /* prepare parsedata */
+  memset(&pd, 0, sizeof(pd));
+  for (i = 0, sw = stateswitches; sw->from != NUMSTATES; i++, sw++)
+    {
+      if (!pd.swtab[sw->from])
+        pd.swtab[sw->from] = sw;
+      pd.sbtab[sw->to] = sw->from;
+    }
+
+  pd.pool = pool;
+  pd.repo = repo;
+
+  pd.content = (char *)malloc(256);    /* must hold all solvable kinds! */
+  pd.acontent = 256;
+  pd.lcontent = 0;
+
+  pd.evrspace = (char *)malloc(256);
+  pd.aevrspace= 256;
+  pd.levrspace = 1;
+  pd.data = data;
+
+  // set up XML parser
+
+  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
+  for (;;)
+    {
+      l = fread(buf, 1, sizeof(buf), fp);
+      if (XML_Parse(parser, buf, l, l == 0) == XML_STATUS_ERROR)
+       {
+         fprintf(stderr, "%s at line %u\n", XML_ErrorString(XML_GetErrorCode(parser)), (unsigned int)XML_GetCurrentLineNumber(parser));
+         exit(1);
+       }
+      if (l == 0)
+       break;
+    }
+  XML_ParserFree(parser);
+
+  if (pd.data)
+    repodata_internalize(pd.data);
+
+  free(pd.content);
+  free(pd.evrspace);
+}
diff --git a/tools/repo_helix.h b/tools/repo_helix.h
new file mode 100644 (file)
index 0000000..4ab0862
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2007, Novell Inc.
+ *
+ * This program is licensed under the BSD license, read LICENSE.BSD
+ * for further information
+ */
+
+/*
+ * repo_helix.h
+ * 
+ */
+
+#ifndef SATSOLVER_REPO_HELIX_H
+#define SATSOLVER_REPO_HELIX_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdio.h>
+#include "pool.h"
+#include "repo.h"
+
+extern void repo_add_helix(Repo *repo, FILE *fp);
+
+#ifdef __cplusplus
+}
+#endif
+    
+
+#endif /* SATSOLVER_REPO_HELIX_H */