Imported Upstream version 0.7.19
[platform/upstream/libsolv.git] / ext / repo_helix.c
1 /*
2  * Copyright (c) 2007, Novell Inc.
3  *
4  * This program is licensed under the BSD license, read LICENSE.BSD
5  * for further information
6  */
7
8 /*
9  * repo_helix.c
10  *
11  * Parse 'helix' XML representation
12  * and create 'repo'
13  *
14  * A bit of history: "Helix Code" was the name of the company that
15  * wrote Red Carpet. The company was later renamed to Ximian.
16  * The Red Carpet solver was merged into the ZYPP project, the
17  * library used both by ZENworks and YaST for package management.
18  * Red Carpet came with solver testcases in its own repository
19  * format, the 'helix' format.
20  *
21  */
22
23 #include <sys/types.h>
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <string.h>
27
28 #include "queue.h"
29 #include "solv_xmlparser.h"
30 #include "repo_helix.h"
31 #include "evr.h"
32
33
34 /* XML parser states */
35
36 enum state {
37   STATE_START,
38   STATE_CHANNEL,
39   STATE_SUBCHANNEL,
40   STATE_PACKAGE,
41   STATE_NAME,
42   STATE_VENDOR,
43   STATE_BUILDTIME,
44   STATE_HISTORY,
45   STATE_UPDATE,
46   STATE_EPOCH,
47   STATE_VERSION,
48   STATE_RELEASE,
49   STATE_ARCH,
50   STATE_PROVIDES,
51   STATE_PROVIDESENTRY,
52   STATE_REQUIRES,
53   STATE_REQUIRESENTRY,
54   STATE_PREREQUIRES,
55   STATE_PREREQUIRESENTRY,
56   STATE_OBSOLETES,
57   STATE_OBSOLETESENTRY,
58   STATE_CONFLICTS,
59   STATE_CONFLICTSENTRY,
60   STATE_RECOMMENDS,
61   STATE_RECOMMENDSENTRY,
62   STATE_SUPPLEMENTS,
63   STATE_SUPPLEMENTSENTRY,
64   STATE_SUGGESTS,
65   STATE_SUGGESTSENTRY,
66   STATE_ENHANCES,
67   STATE_ENHANCESENTRY,
68   STATE_FRESHENS,
69   STATE_FRESHENSENTRY,
70
71   STATE_SELECTTION,
72   STATE_PATTERN,
73   STATE_ATOM,
74   STATE_PATCH,
75   STATE_PRODUCT,
76
77   NUMSTATES
78 };
79
80 static struct solv_xmlparser_element stateswitches[] = {
81   { STATE_START,       "channel",         STATE_CHANNEL, 0 },
82   { STATE_CHANNEL,     "subchannel",      STATE_SUBCHANNEL, 0 },
83   { STATE_SUBCHANNEL,  "package",         STATE_PACKAGE, 0 },
84   { STATE_SUBCHANNEL,  "srcpackage",      STATE_PACKAGE, 0 },
85   { STATE_SUBCHANNEL,  "selection",       STATE_PACKAGE, 0 },
86   { STATE_SUBCHANNEL,  "pattern",         STATE_PACKAGE, 0 },
87   { STATE_SUBCHANNEL,  "atom",            STATE_PACKAGE, 0 },
88   { STATE_SUBCHANNEL,  "patch",           STATE_PACKAGE, 0 },
89   { STATE_SUBCHANNEL,  "product",         STATE_PACKAGE, 0 },
90   { STATE_SUBCHANNEL,  "application",     STATE_PACKAGE, 0 },
91   { STATE_PACKAGE,     "name",            STATE_NAME, 1 },
92   { STATE_PACKAGE,     "vendor",          STATE_VENDOR, 1 },
93   { STATE_PACKAGE,     "buildtime",       STATE_BUILDTIME, 1 },
94   { STATE_PACKAGE,     "epoch",           STATE_EPOCH, 1 },
95   { STATE_PACKAGE,     "version",         STATE_VERSION, 1 },
96   { STATE_PACKAGE,     "release",         STATE_RELEASE, 1 },
97   { STATE_PACKAGE,     "arch",            STATE_ARCH, 1 },
98   { STATE_PACKAGE,     "history",         STATE_HISTORY, 0 },
99   { STATE_PACKAGE,     "provides",        STATE_PROVIDES, 0 },
100   { STATE_PACKAGE,     "requires",        STATE_REQUIRES, 0 },
101   { STATE_PACKAGE,     "prerequires",     STATE_PREREQUIRES, 0 },
102   { STATE_PACKAGE,     "obsoletes",       STATE_OBSOLETES , 0 },
103   { STATE_PACKAGE,     "conflicts",       STATE_CONFLICTS , 0 },
104   { STATE_PACKAGE,     "recommends" ,     STATE_RECOMMENDS , 0 },
105   { STATE_PACKAGE,     "supplements",     STATE_SUPPLEMENTS, 0 },
106   { STATE_PACKAGE,     "suggests",        STATE_SUGGESTS, 0 },
107   { STATE_PACKAGE,     "enhances",        STATE_ENHANCES, 0 },
108   { STATE_PACKAGE,     "freshens",        STATE_FRESHENS, 0 },
109   { STATE_PACKAGE,     "deps",            STATE_PACKAGE, 0 },   /* ignore deps element */
110
111   { STATE_HISTORY,     "update",          STATE_UPDATE, 0 },
112   { STATE_UPDATE,      "epoch",           STATE_EPOCH, 1 },
113   { STATE_UPDATE,      "version",         STATE_VERSION, 1 },
114   { STATE_UPDATE,      "release",         STATE_RELEASE, 1 },
115   { STATE_UPDATE,      "arch",            STATE_ARCH, 1 },
116
117   { STATE_PROVIDES,    "dep",             STATE_PROVIDESENTRY, 0 },
118   { STATE_REQUIRES,    "dep",             STATE_REQUIRESENTRY, 0 },
119   { STATE_PREREQUIRES, "dep",             STATE_PREREQUIRESENTRY, 0 },
120   { STATE_OBSOLETES,   "dep",             STATE_OBSOLETESENTRY, 0 },
121   { STATE_CONFLICTS,   "dep",             STATE_CONFLICTSENTRY, 0 },
122   { STATE_RECOMMENDS,  "dep",             STATE_RECOMMENDSENTRY, 0 },
123   { STATE_SUPPLEMENTS, "dep",             STATE_SUPPLEMENTSENTRY, 0 },
124   { STATE_SUGGESTS,    "dep",             STATE_SUGGESTSENTRY, 0 },
125   { STATE_ENHANCES,    "dep",             STATE_ENHANCESENTRY, 0 },
126   { STATE_FRESHENS,    "dep",             STATE_FRESHENSENTRY, 0 },
127   { NUMSTATES }
128
129 };
130
131 /*
132  * parser data
133  */
134
135 struct parsedata {
136   int ret;
137   /* repo data */
138   Pool *pool;           /* current pool */
139   Repo *repo;           /* current repo */
140   Repodata *data;       /* current repo data */
141   Solvable *solvable;   /* current solvable */
142   Offset freshens;      /* current freshens vector */
143
144   /* package data */
145   int  srcpackage;      /* is srcpackage element */
146   int  epoch;           /* epoch (as offset into evrspace) */
147   int  version;         /* version (as offset into evrspace) */
148   int  release;         /* release (as offset into evrspace) */
149   char *evrspace;       /* buffer for evr */
150   int  aevrspace;       /* actual buffer space */
151   int  levrspace;       /* actual evr length */
152   char *kind;
153
154   struct solv_xmlparser xmlp;
155 };
156
157
158 /*------------------------------------------------------------------*/
159 /* E:V-R handling */
160
161 /* create Id from epoch:version-release */
162
163 static Id
164 evr2id(Pool *pool, struct parsedata *pd, const char *e, const char *v, const char *r)
165 {
166   char *c, *space;
167   int l;
168
169   /* treat explitcit 0 as NULL */
170   if (e && (!*e || !strcmp(e, "0")))
171     e = 0;
172
173   if (v && !e)
174     {
175       const char *v2;
176       /* scan version for ":" */
177       for (v2 = v; *v2 >= '0' && *v2 <= '9'; v2++)      /* skip leading digits */
178         ;
179       /* if version contains ":", set epoch to "0" */
180       if (v2 > v && *v2 == ':')
181         e = "0";
182     }
183
184   /* compute length of Id string */
185   l = 1;  /* for the \0 */
186   if (e)
187     l += strlen(e) + 1;  /* e: */
188   if (v)
189     l += strlen(v);      /* v */
190   if (r)
191     l += strlen(r) + 1;  /* -r */
192
193   /* get content space */
194   c = space = solv_xmlparser_contentspace(&pd->xmlp, l);
195
196   /* copy e-v-r */
197   if (e)
198     {
199       strcpy(c, e);
200       c += strlen(c);
201       *c++ = ':';
202     }
203   if (v)
204     {
205       strcpy(c, v);
206       c += strlen(c);
207     }
208   if (r)
209     {
210       *c++ = '-';
211       strcpy(c, r);
212       c += strlen(c);
213     }
214   *c = 0;
215   /* if nothing inserted, return Id 0 */
216   if (!*space)
217     return 0;
218 #if 0
219   fprintf(stderr, "evr: %s\n", space);
220 #endif
221   /* intern and create */
222   return pool_str2id(pool, space, 1);
223 }
224
225
226 /* create e:v-r from attributes
227  * atts is array of name,value pairs, NULL at end
228  *   even index into atts is name
229  *   odd index is value
230  */
231 static Id
232 evr_atts2id(Pool *pool, struct parsedata *pd, const char **atts)
233 {
234   const char *e, *v, *r;
235   e = v = r = 0;
236   for (; *atts; atts += 2)
237     {
238       if (!strcmp(*atts, "epoch"))
239         e = atts[1];
240       else if (!strcmp(*atts, "version"))
241         v = atts[1];
242       else if (!strcmp(*atts, "release"))
243         r = atts[1];
244     }
245   return evr2id(pool, pd, e, v, r);
246 }
247
248 /*------------------------------------------------------------------*/
249 /* rel operator handling */
250
251 struct flagtab {
252   char *from;
253   int to;
254 };
255
256 static struct flagtab flagtab[] = {
257   { ">",  REL_GT },
258   { "=",  REL_EQ },
259   { ">=", REL_GT|REL_EQ },
260   { "<",  REL_LT },
261   { "!=", REL_GT|REL_LT },
262   { "<=", REL_LT|REL_EQ },
263   { "(any)", REL_LT|REL_EQ|REL_GT },
264   { "==", REL_EQ },
265   { "gt", REL_GT },
266   { "eq", REL_EQ },
267   { "ge", REL_GT|REL_EQ },
268   { "lt", REL_LT },
269   { "ne", REL_GT|REL_LT },
270   { "le", REL_LT|REL_EQ },
271   { "gte", REL_GT|REL_EQ },
272   { "lte", REL_LT|REL_EQ },
273   { "GT", REL_GT },
274   { "EQ", REL_EQ },
275   { "GE", REL_GT|REL_EQ },
276   { "LT", REL_LT },
277   { "NE", REL_GT|REL_LT },
278   { "LE", REL_LT|REL_EQ }
279 };
280
281 /*
282  * process new dependency from parser
283  *  olddeps = already collected deps, this defines the 'kind' of dep
284  *  atts = array of name,value attributes of dep
285  *  isreq == 1 if its a requires
286  */
287
288 static unsigned int
289 adddep(Pool *pool, struct parsedata *pd, unsigned int olddeps, const char **atts, Id marker)
290 {
291   Id id, name;
292   const char *n, *f, *k;
293   const char **a;
294
295   n = f = k = NULL;
296
297   /* loop over name,value pairs */
298   for (a = atts; *a; a += 2)
299     {
300       if (!strcmp(*a, "name"))
301         n = a[1];
302       if (!strcmp(*a, "kind"))
303         k = a[1];
304       else if (!strcmp(*a, "op"))
305         f = a[1];
306       else if (marker && !strcmp(*a, "pre") && a[1][0] == '1')
307         marker = SOLVABLE_PREREQMARKER;
308     }
309   if (!n)                              /* quit if no name found */
310     return olddeps;
311
312   /* kind, name */
313   if (k && !strcmp(k, "package"))
314     k = NULL;                          /* package is default */
315
316   if (k)                               /* if kind!=package, intern <kind>:<name> */
317     {
318       int l = strlen(k) + 1 + strlen(n) + 1;
319       char *space = solv_xmlparser_contentspace(&pd->xmlp, l);
320       sprintf(space, "%s:%s", k, n);
321       name = pool_str2id(pool, space, 1);
322     }
323   else
324     {
325       name = pool_str2id(pool, n, 1);       /* package: just intern <name> */
326     }
327
328   if (f)                               /* operator ? */
329     {
330       /* intern e:v-r */
331       Id evr = evr_atts2id(pool, pd, atts);
332       /* parser operator to flags */
333       int flags;
334       for (flags = 0; flags < sizeof(flagtab)/sizeof(*flagtab); flags++)
335         if (!strcmp(f, flagtab[flags].from))
336           {
337             flags = flagtab[flags].to;
338             break;
339           }
340       if (flags > 7)
341         flags = 0;
342       /* intern rel */
343       id = pool_rel2id(pool, name, evr, flags, 1);
344     }
345   else
346     id = name;                         /* no operator */
347
348   /* add new dependency to repo */
349   return repo_addid_dep(pd->repo, olddeps, id, marker);
350 }
351
352
353 /*----------------------------------------------------------------*/
354
355 static void
356 startElement(struct solv_xmlparser *xmlp, int state, const char *name, const char **atts)
357 {
358   struct parsedata *pd = xmlp->userdata;
359   Pool *pool = pd->pool;
360   Solvable *s = pd->solvable;
361
362   switch (state)
363     {
364
365     case STATE_NAME:
366       if (pd->kind)                    /* if kind is set (non package) */
367         {
368           strcpy(xmlp->content, pd->kind);
369           xmlp->lcontent = strlen(xmlp->content);
370           xmlp->content[xmlp->lcontent++] = ':';   /* prefix name with '<kind>:' */
371           xmlp->content[xmlp->lcontent] = 0;
372         }
373       break;
374
375     case STATE_PACKAGE:                /* solvable name */
376       pd->solvable = pool_id2solvable(pool, repo_add_solvable(pd->repo));
377       pd->srcpackage = 0;
378       pd->kind = NULL;                 /* default is (src)package */
379       if (!strcmp(name, "selection"))
380         pd->kind = "selection";
381       else if (!strcmp(name, "pattern"))
382         pd->kind = "pattern";
383       else if (!strcmp(name, "atom"))
384         pd->kind = "atom";
385       else if (!strcmp(name, "product"))
386         pd->kind = "product";
387       else if (!strcmp(name, "patch"))
388         pd->kind = "patch";
389       else if (!strcmp(name, "application"))
390         pd->kind = "application";
391       else if (!strcmp(name, "srcpackage"))
392         pd->srcpackage = 1;
393       pd->levrspace = 1;
394       pd->epoch = 0;
395       pd->version = 0;
396       pd->release = 0;
397       pd->freshens = 0;
398 #if 0
399       fprintf(stderr, "package #%d\n", s - pool->solvables);
400 #endif
401       break;
402
403     case STATE_UPDATE:
404       pd->levrspace = 1;
405       pd->epoch = 0;
406       pd->version = 0;
407       pd->release = 0;
408       break;
409
410     case STATE_PROVIDES:               /* start of provides */
411       s->provides = 0;
412       break;
413     case STATE_PROVIDESENTRY:          /* entry within provides */
414       s->provides = adddep(pool, pd, s->provides, atts, 0);
415       break;
416     case STATE_REQUIRESENTRY:
417       s->requires = adddep(pool, pd, s->requires, atts, -SOLVABLE_PREREQMARKER);
418       break;
419     case STATE_PREREQUIRESENTRY:
420       s->requires = adddep(pool, pd, s->requires, atts, SOLVABLE_PREREQMARKER);
421       break;
422     case STATE_OBSOLETES:
423       s->obsoletes = 0;
424       break;
425     case STATE_OBSOLETESENTRY:
426       s->obsoletes = adddep(pool, pd, s->obsoletes, atts, 0);
427       break;
428     case STATE_CONFLICTS:
429       s->conflicts = 0;
430       break;
431     case STATE_CONFLICTSENTRY:
432       s->conflicts = adddep(pool, pd, s->conflicts, atts, 0);
433       break;
434     case STATE_RECOMMENDS:
435       s->recommends = 0;
436       break;
437     case STATE_RECOMMENDSENTRY:
438       s->recommends = adddep(pool, pd, s->recommends, atts, 0);
439       break;
440     case STATE_SUPPLEMENTS:
441       s->supplements= 0;
442       break;
443     case STATE_SUPPLEMENTSENTRY:
444       s->supplements = adddep(pool, pd, s->supplements, atts, 0);
445       break;
446     case STATE_SUGGESTS:
447       s->suggests = 0;
448       break;
449     case STATE_SUGGESTSENTRY:
450       s->suggests = adddep(pool, pd, s->suggests, atts, 0);
451       break;
452     case STATE_ENHANCES:
453       s->enhances = 0;
454       break;
455     case STATE_ENHANCESENTRY:
456       s->enhances = adddep(pool, pd, s->enhances, atts, 0);
457       break;
458     case STATE_FRESHENS:
459       pd->freshens = 0;
460       break;
461     case STATE_FRESHENSENTRY:
462       pd->freshens = adddep(pool, pd, pd->freshens, atts, 0);
463       break;
464     default:
465       break;
466     }
467 }
468
469 static const char *
470 findKernelFlavor(struct parsedata *pd, Solvable *s)
471 {
472   Pool *pool = pd->pool;
473   Id pid, *pidp;
474
475   if (s->provides)
476     {
477       pidp = pd->repo->idarraydata + s->provides;
478       while ((pid = *pidp++) != 0)
479         {
480           Reldep *prd;
481           const char *depname;
482
483           if (!ISRELDEP(pid))
484             continue;               /* wrong provides name */
485           prd = GETRELDEP(pool, pid);
486           depname = pool_id2str(pool, prd->name);
487           if (!strncmp(depname, "kernel-", 7))
488             return depname + 7;
489         }
490     }
491
492   if (s->requires)
493     {
494       pidp = pd->repo->idarraydata + s->requires;
495       while ((pid = *pidp++) != 0)
496         {
497           const char *depname;
498
499           if (!ISRELDEP(pid))
500             {
501               depname = pool_id2str(pool, pid);
502             }
503           else
504             {
505               Reldep *prd = GETRELDEP(pool, pid);
506               depname = pool_id2str(pool, prd->name);
507             }
508           if (!strncmp(depname, "kernel-", 7))
509             return depname + 7;
510         }
511     }
512
513   return 0;
514 }
515
516
517 static void
518 endElement(struct solv_xmlparser *xmlp, int state, char *content)
519 {
520   struct parsedata *pd = xmlp->userdata;
521   Pool *pool = pd->pool;
522   Solvable *s = pd->solvable;
523   Id evr;
524   unsigned int t = 0;
525   const char *flavor;
526
527   switch (state)
528     {
529
530     case STATE_PACKAGE:                /* package complete */
531       if (pd->srcpackage && s->arch != ARCH_SRC && s->arch != ARCH_NOSRC)
532         s->arch = ARCH_SRC;
533       if (!s->arch)                    /* default to "noarch" */
534         s->arch = ARCH_NOARCH;
535
536       if (!s->evr && pd->version)      /* set solvable evr */
537         s->evr = evr2id(pool, pd,
538                         pd->epoch   ? pd->evrspace + pd->epoch   : 0,
539                         pd->version ? pd->evrspace + pd->version : 0,
540                         pd->release ? pd->evrspace + pd->release : 0);
541       /* ensure self-provides */
542       if (s->name && s->arch != ARCH_SRC && s->arch != ARCH_NOSRC)
543         s->provides = repo_addid_dep(pd->repo, s->provides, pool_rel2id(pool, s->name, s->evr, REL_EQ, 1), 0);
544       repo_rewrite_suse_deps(s, pd->freshens);
545       pd->freshens = 0;
546
547       /* see bugzilla bnc#190163 */
548       flavor = findKernelFlavor(pd, s);
549       if (flavor)
550         {
551           char *cflavor = solv_strdup(flavor);  /* make pointer safe */
552
553           Id npr;
554           Id pid;
555
556           /* this is either a kernel package or a kmp */
557           if (s->provides)
558             {
559               Offset prov = s->provides;
560               npr = 0;
561               while ((pid = pd->repo->idarraydata[prov++]) != 0)
562                 {
563                   const char *depname = 0;
564                   Reldep *prd = 0;
565
566                   if (ISRELDEP(pid))
567                     {
568                       prd = GETRELDEP(pool, pid);
569                       depname = pool_id2str(pool, prd->name);
570                     }
571                   else
572                     {
573                       depname = pool_id2str(pool, pid);
574                     }
575
576
577                   if (!strncmp(depname, "kernel(", 7) && !strchr(depname, ':'))
578                     {
579                       char newdep[100];
580                       snprintf(newdep, sizeof(newdep), "kernel(%s:%s", cflavor, depname + 7);
581                       pid = pool_str2id(pool, newdep, 1);
582                       if (prd)
583                         pid = pool_rel2id(pool, pid, prd->evr, prd->flags, 1);
584                     }
585
586                   npr = repo_addid_dep(pd->repo, npr, pid, 0);
587                 }
588               s->provides = npr;
589             }
590 #if 1
591
592           if (s->requires)
593             {
594               Offset reqs = s->requires;
595               npr = 0;
596               while ((pid = pd->repo->idarraydata[reqs++]) != 0)
597                 {
598                   const char *depname = 0;
599                   Reldep *prd = 0;
600
601                   if (ISRELDEP(pid))
602                     {
603                       prd = GETRELDEP(pool, pid);
604                       depname = pool_id2str(pool, prd->name);
605                     }
606                   else
607                     {
608                       depname = pool_id2str(pool, pid);
609                     }
610
611                   if (!strncmp(depname, "kernel(", 7) && !strchr(depname, ':'))
612                     {
613                       char newdep[100];
614                       snprintf(newdep, sizeof(newdep), "kernel(%s:%s", cflavor, depname + 7);
615                       pid = pool_str2id(pool, newdep, 1);
616                       if (prd)
617                         pid = pool_rel2id(pool, pid, prd->evr, prd->flags, 1);
618                     }
619                   npr = repo_addid_dep(pd->repo, npr, pid, 0);
620                 }
621               s->requires = npr;
622             }
623 #endif
624           free(cflavor);
625         }
626       break;
627     case STATE_NAME:
628       s->name = pool_str2id(pool, content, 1);
629       break;
630     case STATE_VENDOR:
631       s->vendor = pool_str2id(pool, content, 1);
632       break;
633     case STATE_BUILDTIME:
634       t = atoi(content);
635       if (t)
636         repodata_set_num(pd->data, s - pool->solvables, SOLVABLE_BUILDTIME, t);
637       break;    
638     case STATE_UPDATE:                 /* new version, keeping all other metadata */
639       evr = evr2id(pool, pd,
640                    pd->epoch   ? pd->evrspace + pd->epoch   : 0,
641                    pd->version ? pd->evrspace + pd->version : 0,
642                    pd->release ? pd->evrspace + pd->release : 0);
643       pd->levrspace = 1;
644       pd->epoch = 0;
645       pd->version = 0;
646       pd->release = 0;
647       /* use highest evr */
648       if (!s->evr || pool_evrcmp(pool, s->evr, evr, EVRCMP_COMPARE) <= 0)
649         s->evr = evr;
650       break;
651     case STATE_EPOCH:
652     case STATE_VERSION:
653     case STATE_RELEASE:
654       /* ensure buffer space */
655       if (xmlp->lcontent + 1 + pd->levrspace > pd->aevrspace)
656         {
657           pd->aevrspace = xmlp->lcontent + 1 + pd->levrspace + 256;
658           pd->evrspace = (char *)solv_realloc(pd->evrspace, pd->aevrspace);
659         }
660       memcpy(pd->evrspace + pd->levrspace, xmlp->content, xmlp->lcontent + 1);
661       if (state == STATE_EPOCH)
662         pd->epoch = pd->levrspace;
663       else if (state == STATE_VERSION)
664         pd->version = pd->levrspace;
665       else
666         pd->release = pd->levrspace;
667       pd->levrspace += xmlp->lcontent + 1;
668       break;
669     case STATE_ARCH:
670       s->arch = pool_str2id(pool, content, 1);
671       break;
672     default:
673       break;
674     }
675 }
676
677 /*-------------------------------------------------------------------*/
678
679 /*
680  * read 'helix' type xml from fp
681  * add packages to pool/repo
682  *
683  */
684
685 int
686 repo_add_helix(Repo *repo, FILE *fp, int flags)
687 {
688   Pool *pool = repo->pool;
689   struct parsedata pd;
690   Repodata *data;
691   unsigned int now;
692
693   now = solv_timems(0);
694   data = repo_add_repodata(repo, flags);
695
696   /* prepare parsedata */
697   memset(&pd, 0, sizeof(pd));
698   pd.pool = pool;
699   pd.repo = repo;
700   pd.data = data;
701
702   pd.evrspace = (char *)solv_malloc(256);
703   pd.aevrspace = 256;
704   pd.levrspace = 1;
705
706   solv_xmlparser_init(&pd.xmlp, stateswitches, &pd, startElement, endElement);
707   if (solv_xmlparser_parse(&pd.xmlp, fp) != SOLV_XMLPARSER_OK)
708     pd.ret = pool_error(pd.pool, -1, "repo_helix: %s at line %u", pd.xmlp.errstr, pd.xmlp.line);
709   solv_xmlparser_free(&pd.xmlp);
710
711   solv_free(pd.evrspace);
712
713   if (!(flags & REPO_NO_INTERNALIZE))
714     repodata_internalize(data);
715   POOL_DEBUG(SOLV_DEBUG_STATS, "repo_add_helix took %d ms\n", solv_timems(now));
716   POOL_DEBUG(SOLV_DEBUG_STATS, "repo size: %d solvables\n", repo->nsolvables);
717   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)));
718   return pd.ret;
719 }