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
evr2id(Pool * pool,struct parsedata * pd,const char * e,const char * v,const char * r)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
evr_atts2id(Pool * pool,struct parsedata * pd,const char ** atts)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
adddep(Pool * pool,struct parsedata * pd,unsigned int olddeps,const char ** atts,Id marker)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
startElement(struct solv_xmlparser * xmlp,int state,const char * name,const char ** atts)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 *
findKernelFlavor(struct parsedata * pd,Solvable * s)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
endElement(struct solv_xmlparser * xmlp,int state,char * content)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
repo_add_helix(Repo * repo,FILE * fp,int flags)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 }
720