2 * Copyright (c) 2007, Novell Inc.
4 * This program is licensed under the BSD license, read LICENSE.BSD
5 * for further information
17 #include "tools_util.h"
18 #include "repo_susetags.h"
24 struct parsedata_common common;
25 int last_found_source;
28 Id (*dirs)[3]; // dirid, size, nfiles
30 Id langcache[ID_NUM_INTERNAL];
34 static char *flagtab[] = {
45 langtag(struct parsedata *pd, Id tag, const char *language)
47 if (language && !language[0])
49 if (!language || tag >= ID_NUM_INTERNAL)
50 return pool_id2langid(pd->repo->pool, tag, language, 1);
51 return pool_id2langid(pd->repo->pool, tag, language, 1);
52 if (!pd->langcache[tag])
53 pd->langcache[tag] = pool_id2langid(pd->repo->pool, tag, language, 1);
54 return pd->langcache[tag];
59 * create and add dependency
63 adddep(Pool *pool, struct parsedata *pd, unsigned int olddeps, char *line, Id marker, char *kind)
69 i = split(line + 5, sp, 4); /* name, <op>, evr, ? */
70 if (i != 1 && i != 3) /* expect either 'name' or 'name' <op> 'evr' */
72 fprintf(stderr, "Bad dependency line: %d: %s\n", pd->lineno, line);
76 id = str2id(pool, join2(kind, ":", sp[0]), 1);
78 id = str2id(pool, sp[0], 1);
81 evrid = makeevr(pool, sp[2]);
82 for (flags = 0; flags < 6; flags++)
83 if (!strcmp(sp[1], flagtab[flags]))
87 fprintf(stderr, "Unknown relation %d: '%s'\n", pd->lineno, sp[1]);
90 id = rel2id(pool, id, evrid, flags + 1, 1);
92 return repo_addid_dep(pd->repo, olddeps, id, marker);
102 add_location(struct parsedata *pd, char *line, Solvable *s, unsigned handle)
104 Pool *pool = s->repo->pool;
108 i = split(line, sp, 3);
109 if (i != 2 && i != 3)
111 fprintf(stderr, "Bad location line: %d: %s\n", pd->lineno, line);
114 /* If we have a dirname, let's see if it's the same as arch. In that
115 case don't store it. */
116 if (i == 3 && !strcmp (sp[2], id2str (pool, s->arch)))
120 /* medianr filename dir
121 don't optimize this one */
122 repodata_set_constant(pd->data, handle, SOLVABLE_MEDIANR, atoi(sp[0]));
123 repodata_set_poolstr(pd->data, handle, SOLVABLE_MEDIADIR, sp[2]);
124 repodata_set_str(pd->data, handle, SOLVABLE_MEDIAFILE, sp[1]);
129 /* Let's see if we can optimize this a bit. If the media file name
130 can be formed by the base rpm information we don't store it, but
131 only a flag that we've seen it. */
132 unsigned int medianr = atoi (sp[0]);
133 const char *n1 = sp[1];
134 const char *n2 = id2str (pool, s->name);
135 for (n2 = id2str (pool, s->name); *n2; n1++, n2++)
138 if (*n2 || *n1 != '-')
142 for (n2 = id2str (pool, s->evr); *n2; n1++, n2++)
145 if (*n2 || *n1 != '.')
148 for (n2 = id2str (pool, s->arch); *n2; n1++, n2++)
151 if (*n2 || strcmp (n1, ".rpm"))
154 repodata_set_constant(pd->data, handle, SOLVABLE_MEDIANR, medianr);
155 repodata_set_void(pd->data, handle, SOLVABLE_MEDIADIR);
156 repodata_set_void(pd->data, handle, SOLVABLE_MEDIAFILE);
160 repodata_set_constant(pd->data, handle, SOLVABLE_MEDIANR, medianr);
161 repodata_set_void(pd->data, handle, SOLVABLE_MEDIADIR);
162 repodata_set_str(pd->data, handle, SOLVABLE_MEDIAFILE, sp[1]);
173 add_source(struct parsedata *pd, char *line, Solvable *s, unsigned handle)
175 Repo *repo = s->repo;
176 Pool *pool = repo->pool;
179 if (split(line, sp, 5) != 4)
181 fprintf(stderr, "Bad source line: %d: %s\n", pd->lineno, line);
185 Id name = str2id(pool, sp[0], 1);
186 Id evr = makeevr(pool, join2(sp[1], "-", sp[2]));
187 Id arch = str2id(pool, sp[3], 1);
188 /* XXX: could record a dep here, depends on where we want to store the data */
190 repodata_set_void(pd->data, handle, SOLVABLE_SOURCENAME);
192 repodata_set_id(pd->data, handle, SOLVABLE_SOURCENAME, name);
194 repodata_set_void(pd->data, handle, SOLVABLE_SOURCEEVR);
196 repodata_set_id(pd->data, handle, SOLVABLE_SOURCEEVR, evr);
197 repodata_set_constantid(pd->data, handle, SOLVABLE_SOURCEARCH, arch);
202 * add a line with directory information
207 add_dirline (struct parsedata *pd, char *line)
210 if (split(line, sp, 6) != 5)
212 pd->dirs = sat_extend(pd->dirs, pd->ndirs, 1, sizeof(pd->dirs[0]), 31);
213 long filesz = strtol (sp[1], 0, 0);
214 filesz += strtol (sp[2], 0, 0);
215 long filenum = strtol (sp[3], 0, 0);
216 filenum += strtol (sp[4], 0, 0);
217 /* hack: we know that there's room for a / */
220 unsigned dirid = repodata_str2dir(pd->data, sp[0], 1);
222 fprintf(stderr, "%s -> %d\n", sp[0], dirid);
224 pd->dirs[pd->ndirs][0] = dirid;
225 pd->dirs[pd->ndirs][1] = filesz;
226 pd->dirs[pd->ndirs][2] = filenum;
231 set_checksum(struct parsedata *pd, Repodata *data, int handle, Id keyname, char *line)
236 if (split(line, sp, 3) != 2)
238 fprintf(stderr, "Bad source line: %d: %s\n", pd->lineno, line);
241 if (!strcasecmp (sp[0], "sha1"))
242 l = SIZEOF_SHA1 * 2, type = REPOKEY_TYPE_SHA1;
243 else if (!strcasecmp (sp[0], "md5"))
244 l = SIZEOF_MD5 * 2, type = REPOKEY_TYPE_MD5;
247 fprintf(stderr, "Unknown checksum type: %d: %s\n", pd->lineno, sp[0]);
250 if (strlen(sp[1]) != l)
252 fprintf(stderr, "Invalid checksum length: %d: for %s: %s\n", pd->lineno, sp[0], sp[1]);
255 repodata_set_checksum(data, handle, keyname, type, sp[1]);
265 id3_cmp (const void *v1, const void *v2)
269 return i1[0] - i2[0];
279 commit_diskusage (struct parsedata *pd, unsigned handle)
282 Dirpool *dp = &pd->data->dirpool;
283 /* Now sort in dirid order. This ensures that parents come before
286 qsort(pd->dirs, pd->ndirs, sizeof (pd->dirs[0]), id3_cmp);
287 /* Substract leaf numbers from all parents to make the numbers
288 non-cumulative. This must be done post-order (i.e. all leafs
289 adjusted before parents). We ensure this by starting at the end of
290 the array moving to the start, hence seeing leafs before parents. */
291 for (i = pd->ndirs; i--;)
293 unsigned p = dirpool_parent(dp, pd->dirs[i][0]);
295 for (; p; p = dirpool_parent(dp, p))
298 if (pd->dirs[j][0] == p)
302 if (pd->dirs[j][1] < pd->dirs[i][1])
305 pd->dirs[j][1] -= pd->dirs[i][1];
306 if (pd->dirs[j][2] < pd->dirs[i][2])
309 pd->dirs[j][2] -= pd->dirs[i][2];
312 /* Haven't found this parent in the list, look further if
313 we maybe find the parents parent. */
320 unsigned slen = sizeof (sbuf);
321 for (i = 0; i < pd->ndirs; i++)
323 dir2str (attr, pd->dirs[i][0], &buf, &slen);
324 fprintf (stderr, "have dir %d %d %d %s\n", pd->dirs[i][0], pd->dirs[i][1], pd->dirs[i][2], buf);
329 for (i = 0; i < pd->ndirs; i++)
330 if (pd->dirs[i][1] || pd->dirs[i][2])
332 repodata_add_dirnumnum(pd->data, handle, SOLVABLE_DISKUSAGE, pd->dirs[i][0], pd->dirs[i][1], pd->dirs[i][2]);
338 /* Unfortunately "a"[0] is no constant expression in the C languages,
339 so we need to pass the four characters individually :-/ */
340 #define CTAG(a,b,c,d) ((unsigned)(((unsigned char)a) << 24) \
341 | ((unsigned char)b << 16) \
342 | ((unsigned char)c << 8) \
343 | ((unsigned char)d))
350 static inline unsigned
351 tag_from_string (char *cs)
353 unsigned char *s = (unsigned char*) cs;
354 return ((s[0] << 24) | (s[1] << 16) | (s[2] << 8) | s[3]);
360 * Parse susetags file passed in fp, fill solvables into repo
362 * susetags is key,value based
366 * for long (multi-line) values,
373 * See http://en.opensuse.org/Standards/YaST2_Repository_Metadata
374 * and http://en.opensuse.org/Standards/YaST2_Repository_Metadata/packages
375 * and http://en.opensuse.org/Standards/YaST2_Repository_Metadata/pattern
378 * All keys have 3 characters and end in ':'
382 finish_solvable(struct parsedata *pd, Solvable *s, int handle)
384 Pool *pool = pd->repo->pool;
387 /* move file provides to filelist */
388 /* relies on the fact that rpm inserts self-provides at the end */
391 Id *p, *lastreal, did;
392 const char *str, *sp;
393 lastreal = pd->repo->idarraydata + s->provides;
394 for (p = lastreal; *p; p++)
397 for (p = lastreal; *p; p++)
399 str = id2str(pool, *p);
405 for (p = lastreal; *p; p++)
409 str = id2str(pool, *p);
410 sp = strrchr(str, '/');
411 /* Need to copy filename now, before we add string that could
412 realloc the stringspace (and hence invalidate str). */
414 if (strlen(fname) >= 128)
415 fname = strdup(fname);
418 memcpy(fname_buf, fname, strlen(fname) + 1);
423 char *sdup = strdup(str);
425 did = repodata_str2dir(pd->data, sdup, 1);
431 strncpy(sdup, str, sp - str);
433 did = repodata_str2dir(pd->data, sdup, 1);
436 did = repodata_str2dir(pd->data, "/", 1);
437 repodata_add_dirstr(pd->data, handle, SOLVABLE_FILELIST, did, fname);
438 if (fname != fname_buf)
445 /* A self provide, except for source packages. This is harmless
446 to do twice (in case we see the same package twice). */
447 if (s->arch != ARCH_SRC && s->arch != ARCH_NOSRC)
448 s->provides = repo_addid_dep(pd->repo, s->provides,
449 rel2id(pool, s->name, s->evr, REL_EQ, 1), 0);
450 /* XXX This uses repo_addid_dep internally, so should also be
451 harmless to do twice. */
452 s->supplements = repo_fix_legacy(pd->repo, s->provides, s->supplements);
454 commit_diskusage (pd, handle);
458 repo_add_susetags(Repo *repo, FILE *fp, Id vendor, const char *language, int flags)
460 Pool *pool = repo->pool;
467 int last_found_pack = 0;
474 if ((flags & SUSETAGS_EXTEND) && repo->nrepodata)
477 /* use last repodata */
478 data = repo->repodata + repo->nrepodata - 1;
480 data = repo_add_repodata(repo, 0);
482 memset(&pd, 0, sizeof(pd));
486 pd.repo = pd.common.repo = repo;
488 pd.common.pool = pool;
493 /* XXX deactivate test code */
498 * collect values in 'struct parsedata pd'
499 * then build .solv (and .attr) file
505 char *olinep; /* old line pointer */
508 if (linep - line + 16 > aline) /* (re-)alloc buffer */
510 aline = linep - line;
511 line = realloc(line, aline + 512);
512 linep = line + aline;
515 if (!fgets(linep, aline - (linep - line), fp)) /* read line */
518 linep += strlen(linep);
519 if (linep == line || linep[-1] != '\n')
528 /* check for multi-line value tags (+Key:/-Key:) */
530 int is_end = (linep[-intag - keylen + 1] == '-')
531 && (linep[-1] == ':')
532 && (linep == line + 1 + intag + 1 + 1 + 1 + intag + 1 || linep[-intag - keylen] == '\n');
534 && strncmp(linep - 1 - intag, line + 1, intag))
536 fprintf(stderr, "Nonmatching multi-line tags: %d: '%s' '%s' %d\n", pd.lineno, linep - 1 - intag, line + 1, intag);
538 if (cummulate && !is_end)
543 if (cummulate && is_end)
545 linep[-intag - keylen + 1] = 0;
546 if (linep[-intag - keylen] == '\n')
547 linep[-intag - keylen] = 0;
551 if (!cummulate && is_end)
557 if (!cummulate && !is_end)
558 linep = line + intag + keylen;
563 if (!intag && line[0] == '+' && line[1] && line[1] != ':') /* start of +Key:/-Key: tag */
565 char *tagend = strchr(line, ':');
568 fprintf(stderr, "bad line: %d: %s\n", pd.lineno, line);
571 intag = tagend - (line + 1);
573 switch (tag_from_string (line)) /* check if accumulation is needed */
575 case CTAG('+', 'P', 'r', 'q'):
576 case CTAG('+', 'P', 'r', 'c'):
577 case CTAG('+', 'P', 's', 'g'):
578 if (!pd.kind || !(flags & SUSETAGS_KINDS_SEPARATELY))
580 case CTAG('+', 'D', 'e', 's'):
581 case CTAG('+', 'E', 'u', 'l'):
582 case CTAG('+', 'I', 'n', 's'):
583 case CTAG('+', 'D', 'e', 'l'):
584 case CTAG('+', 'A', 'u', 't'):
588 line[0] = '='; /* handle lines between +Key:/-Key: as =Key: */
589 line[intag + keylen - 1] = ' ';
590 linep = line + intag + keylen;
593 if (*line == '#' || !*line)
595 if (! (line[0] && line[1] && line[2] && line[3] && (line[4] == ':' || line[4] == '.')))
600 endlang = strchr(line + 5, ':');
603 keylen = endlang - line - 1;
604 strncpy(line_lang, line + 5, 5);
605 line_lang[endlang - line - 5] = 0;
610 tag = tag_from_string (line);
614 * start of (next) package or pattern
616 * =Pkg: <name> <version> <release> <architecture>
620 if ((tag == CTAG('=', 'P', 'k', 'g')
621 || tag == CTAG('=', 'P', 'a', 't')))
624 /* If we have an old solvable, complete it by filling in some
627 finish_solvable(&pd, s, handle);
641 if (split(line + 5, sp, 5) != 4)
643 fprintf(stderr, "Bad line: %d: %s\n", pd.lineno, line);
646 /* Lookup (but don't construct) the name and arch. */
648 name = str2id(pool, join2(pd.kind, ":", sp[0]), 0);
650 name = str2id(pool, sp[0], 0);
651 arch = str2id(pool, sp[3], 0);
652 evr = makeevr(pool, join2(sp[1], "-", sp[2]));
656 /* Now see if we know this solvable already. If we found neither
657 the name nor the arch at all in this repo
658 there's no chance of finding the exact solvable either. */
659 if (indesc >= 2 && name && arch)
662 /* Now look for a solvable with the given name,evr,arch.
663 Our input is structured so, that the second set of =Pkg
664 lines comes in roughly the same order as the first set, so we
665 have a hint at where to start our search, namely were we found
667 for (n = repo->start, nn = n + last_found_pack; n < repo->end; n++, nn++)
671 s = pool->solvables + nn;
672 if (s->repo == repo && s->name == name && s->evr == evr && s->arch == arch)
679 last_found_pack = nn - repo->start;
680 handle = repodata_get_handle(data, last_found_pack);
684 /* And if we still don't have a solvable, create a new one. */
687 s = pool_id2solvable(pool, repo_add_solvable(repo));
688 last_found_pack = (s - pool->solvables) - repo->start;
691 repodata_extend(data, s - pool->solvables);
692 handle = repodata_get_handle(data, last_found_pack);
697 s->name = str2id(pool, join2(pd.kind, ":", sp[0]), 1);
699 s->name = str2id(pool, sp[0], 1);
704 s->arch = str2id(pool, sp[3], 1);
709 /* If we have no current solvable to add to, ignore all further lines
710 for it. Probably invalid input data in the second set of
712 if (indesc >= 2 && !s)
714 fprintf (stderr, "Huh %d: %s?\n", pd.lineno, line);
719 case CTAG('=', 'P', 'r', 'v'): /* provides */
720 s->provides = adddep(pool, &pd, s->provides, line, 0, pd.kind);
722 case CTAG('=', 'R', 'e', 'q'): /* requires */
723 s->requires = adddep(pool, &pd, s->requires, line, -SOLVABLE_PREREQMARKER, pd.kind);
725 case CTAG('=', 'P', 'r', 'q'): /* pre-requires / packages required */
728 if (flags & SUSETAGS_KINDS_SEPARATELY)
729 repodata_set_poolstr(data, handle, str2id(pool, "solvable:must", 1), line + 6);
731 s->requires = adddep(pool, &pd, s->requires, line, 0, 0); /* patterns: a required package */
734 s->requires = adddep(pool, &pd, s->requires, line, SOLVABLE_PREREQMARKER, 0); /* package: pre-requires */
736 case CTAG('=', 'O', 'b', 's'): /* obsoletes */
737 s->obsoletes = adddep(pool, &pd, s->obsoletes, line, 0, pd.kind);
739 case CTAG('=', 'C', 'o', 'n'): /* conflicts */
740 s->conflicts = adddep(pool, &pd, s->conflicts, line, 0, pd.kind);
742 case CTAG('=', 'R', 'e', 'c'): /* recommends */
743 s->recommends = adddep(pool, &pd, s->recommends, line, 0, pd.kind);
745 case CTAG('=', 'S', 'u', 'p'): /* supplements */
746 s->supplements = adddep(pool, &pd, s->supplements, line, 0, pd.kind);
748 case CTAG('=', 'E', 'n', 'h'): /* enhances */
749 s->enhances = adddep(pool, &pd, s->enhances, line, 0, pd.kind);
751 case CTAG('=', 'S', 'u', 'g'): /* suggests */
752 s->suggests = adddep(pool, &pd, s->suggests, line, 0, pd.kind);
754 case CTAG('=', 'F', 'r', 'e'): /* freshens */
755 s->freshens = adddep(pool, &pd, s->freshens, line, 0, pd.kind);
757 case CTAG('=', 'P', 'r', 'c'): /* packages recommended */
758 if (flags & SUSETAGS_KINDS_SEPARATELY)
759 repodata_set_poolstr(data, handle, str2id(pool, "solvable:should", 1), line + 6);
761 s->recommends = adddep(pool, &pd, s->recommends, line, 0, 0);
763 case CTAG('=', 'P', 's', 'g'): /* packages suggested */
764 if (flags & SUSETAGS_KINDS_SEPARATELY)
765 repodata_set_poolstr(data, handle, str2id(pool, "solvable:may", 1), line + 6);
767 s->suggests = adddep(pool, &pd, s->suggests, line, 0, 0);
769 case CTAG('=', 'P', 'c', 'n'): /* pattern: package conflicts */
770 if (flags & SUSETAGS_KINDS_SEPARATELY)
771 fprintf (stderr, "Unsupported: pattern -> package conflicts\n");
773 s->conflicts = adddep(pool, &pd, s->conflicts, line, 0, 0);
775 case CTAG('=', 'P', 'o', 'b'): /* pattern: package obsoletes */
776 if (flags & SUSETAGS_KINDS_SEPARATELY)
777 fprintf (stderr, "Unsupported: pattern -> package obsoletes\n");
779 s->obsoletes = adddep(pool, &pd, s->obsoletes, line, 0, 0);
781 case CTAG('=', 'P', 'f', 'r'): /* pattern: package freshens */
782 if (flags & SUSETAGS_KINDS_SEPARATELY)
783 fprintf (stderr, "Unsupported: pattern -> package freshens\n");
785 s->freshens = adddep(pool, &pd, s->freshens, line, 0, 0);
787 case CTAG('=', 'P', 's', 'p'): /* pattern: package supplements */
788 if (flags & SUSETAGS_KINDS_SEPARATELY)
789 fprintf (stderr, "Unsupported: pattern -> package supplements\n");
791 s->supplements = adddep(pool, &pd, s->supplements, line, 0, 0);
793 case CTAG('=', 'P', 'e', 'n'): /* pattern: package enhances */
794 if (flags & SUSETAGS_KINDS_SEPARATELY)
795 fprintf (stderr, "Unsupported: pattern -> package enhances\n");
797 s->enhances = adddep(pool, &pd, s->enhances, line, 0, 0);
799 case CTAG('=', 'V', 'e', 'r'): /* - version - */
805 /* From here it's the attribute tags. */
806 case CTAG('=', 'G', 'r', 'p'):
807 repodata_set_poolstr(data, handle, SOLVABLE_GROUP, line + 6);
809 case CTAG('=', 'L', 'i', 'c'):
810 repodata_set_poolstr(data, handle, SOLVABLE_LICENSE, line + 6);
812 case CTAG('=', 'L', 'o', 'c'):
813 add_location(&pd, line + 6, s, handle);
815 case CTAG('=', 'S', 'r', 'c'):
816 add_source(&pd, line + 6, s, handle);
818 case CTAG('=', 'S', 'i', 'z'):
819 if (split (line + 6, sp, 3) == 2)
821 repodata_set_num(data, handle, SOLVABLE_DOWNLOADSIZE, (atoi(sp[0]) + 1023) / 1024);
822 repodata_set_num(data, handle, SOLVABLE_INSTALLSIZE, (atoi(sp[1]) + 1023) / 1024);
825 case CTAG('=', 'T', 'i', 'm'):
827 unsigned int t = atoi (line + 6);
829 repodata_set_num(data, handle, SOLVABLE_BUILDTIME, t);
832 case CTAG('=', 'K', 'w', 'd'):
833 repodata_add_poolstr_array(data, handle, SOLVABLE_KEYWORDS, line + 6);
835 case CTAG('=', 'A', 'u', 't'):
836 repodata_set_str(data, handle, SOLVABLE_AUTHORS, line + 6);
838 case CTAG('=', 'S', 'u', 'm'):
839 repodata_set_str(data, handle, langtag(&pd, SOLVABLE_SUMMARY, language ? language : line_lang), line + 3 + keylen );
841 case CTAG('=', 'D', 'e', 's'):
842 repodata_set_str(data, handle, langtag(&pd, SOLVABLE_DESCRIPTION, language ? language : line_lang), line + 3 + keylen );
844 case CTAG('=', 'E', 'u', 'l'):
845 repodata_set_str(data, handle, langtag(&pd, SOLVABLE_EULA, language), line + 6);
847 case CTAG('=', 'I', 'n', 's'):
848 repodata_set_str(data, handle, langtag(&pd, SOLVABLE_MESSAGEINS, language), line + 6);
852 repo_set_str(repo, blanr, SOLVABLE_MESSAGEINS, line + 6);
856 case CTAG('=', 'D', 'e', 'l'):
857 repodata_set_str(data, handle, langtag(&pd, SOLVABLE_MESSAGEDEL, language), line + 6);
859 case CTAG('=', 'V', 'i', 's'):
861 /* Accept numbers and textual bools. */
864 if (k || !strcasecmp (line + 6, "true"))
865 repodata_set_void(data, handle, SOLVABLE_ISVISIBLE );
868 case CTAG('=', 'S', 'h', 'r'):
869 if (last_found_pack >= pd.nshare)
873 pd.share_with = realloc (pd.share_with, (last_found_pack + 256) * sizeof (*pd.share_with));
874 memset (pd.share_with + pd.nshare, 0, (last_found_pack + 256 - pd.nshare) * sizeof (*pd.share_with));
877 pd.share_with = calloc (last_found_pack + 256, sizeof (*pd.share_with));
878 pd.nshare = last_found_pack + 256;
880 pd.share_with[last_found_pack] = strdup (line + 6);
882 case CTAG('=', 'D', 'i', 'r'):
883 add_dirline (&pd, line + 6);
885 case CTAG('=', 'C', 'a', 't'):
886 repodata_set_poolstr(data, handle, langtag(&pd, SOLVABLE_CATEGORY, line_lang), line + 3 + keylen);
888 case CTAG('=', 'O', 'r', 'd'):
889 /* Order is a string not a number, so we can retroactively insert
890 new patterns in the middle, i.e. 1 < 15 < 2. */
891 repodata_set_str(data, handle, SOLVABLE_ORDER, line + 6);
893 case CTAG('=', 'I', 'c', 'o'):
894 repodata_set_str(data, handle, SOLVABLE_ICON, line + 6);
896 case CTAG('=', 'E', 'x', 't'):
897 repodata_add_poolstr_array(data, handle, SOLVABLE_EXTENDS, join2("pattern", ":", line + 6));
899 case CTAG('=', 'I', 'n', 'c'):
900 repodata_add_poolstr_array(data, handle, SOLVABLE_INCLUDES, join2("pattern", ":", line + 6));
902 case CTAG('=', 'C', 'k', 's'):
903 set_checksum(&pd, data, handle, SOLVABLE_CHECKSUM, line + 6);
906 Id sub = repodata_create_struct(data, handle, str2id(pool, "solvable:komisch", 1));
907 repodata_set_poolstr(data, sub, str2id(pool, "sub:key1", 1), line + 6);
908 repodata_set_num(data, sub, str2id(pool, "sub:key2", 1), last_found_pack);
909 sub = repodata_create_struct(data, handle, str2id(pool, "solvable:komisch", 1));
910 repodata_set_poolstr(data, sub, str2id(pool, "sub:key1", 1), line + 7);
911 repodata_set_num(data, sub, str2id(pool, "sub:key2", 1), last_found_pack+1);
914 case CTAG('=', 'L', 'a', 'n'):
915 language = strdup(line + 6);
918 case CTAG('=', 'F', 'l', 's'):
920 char *p = strrchr(line + 6, '/');
922 if (p && p != line + 6 && !p[1])
925 p = strrchr(line + 6, '/');
930 did = repodata_str2dir(data, line + 6, 1);
938 did = repodata_str2dir(data, "/", 1);
939 repodata_add_dirstr(data, handle, SOLVABLE_FILELIST, did, p);
943 case CTAG('=', 'P', 'a', 't'):
944 case CTAG('=', 'P', 'k', 'g'):
948 fprintf(stderr,"unknown line %s\n", line);
955 finish_solvable(&pd, s, handle);
958 * (e.g. multiple binaries built from same source)
964 for (i = 0; i < pd.nshare; i++)
965 if (pd.share_with[i])
967 if (split(pd.share_with[i], sp, 5) != 4)
969 fprintf(stderr, "Bad =Shr line: %s\n", pd.share_with[i]);
973 Id name = str2id(pool, sp[0], 1);
974 Id evr = makeevr(pool, join2(sp[1], "-", sp[2]));
975 Id arch = str2id(pool, sp[3], 1);
978 for (n = repo->start, nn = repo->start + last_found;
979 n < repo->end; n++, nn++)
983 found = pool->solvables + nn;
984 if (found->repo == repo
985 && found->name == name
987 && found->arch == arch)
989 last_found = nn - repo->start;
994 repodata_merge_attrs(data, i, last_found);
996 free (pd.share_with);
1000 repodata_internalize(data);
1003 free(pd.common.tmp);