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)
71 /* Allow spaces in file dependencies. Autobuild may generate
72 such filedeps into the provides list. */
73 id = str2id(pool, line, 1);
77 i = split(line + 5, sp, 4); /* name, <op>, evr, ? */
78 if (i != 1 && i != 3) /* expect either 'name' or 'name' <op> 'evr' */
80 fprintf(stderr, "Bad dependency line: %d: %s\n", pd->lineno, line);
84 id = str2id(pool, join2(kind, ":", sp[0]), 1);
86 id = str2id(pool, sp[0], 1);
89 evrid = makeevr(pool, sp[2]);
90 for (flags = 0; flags < 6; flags++)
91 if (!strcmp(sp[1], flagtab[flags]))
95 fprintf(stderr, "Unknown relation %d: '%s'\n", pd->lineno, sp[1]);
98 id = rel2id(pool, id, evrid, flags + 1, 1);
101 return repo_addid_dep(pd->repo, olddeps, id, marker);
111 add_location(struct parsedata *pd, char *line, Solvable *s, unsigned handle)
113 Pool *pool = s->repo->pool;
117 i = split(line, sp, 3);
118 if (i != 2 && i != 3)
120 fprintf(stderr, "Bad location line: %d: %s\n", pd->lineno, line);
123 /* If we have a dirname, let's see if it's the same as arch. In that
124 case don't store it. */
125 if (i == 3 && !strcmp (sp[2], id2str (pool, s->arch)))
129 /* medianr filename dir
130 don't optimize this one */
131 repodata_set_constant(pd->data, handle, SOLVABLE_MEDIANR, atoi(sp[0]));
132 repodata_set_poolstr(pd->data, handle, SOLVABLE_MEDIADIR, sp[2]);
133 repodata_set_str(pd->data, handle, SOLVABLE_MEDIAFILE, sp[1]);
138 /* Let's see if we can optimize this a bit. If the media file name
139 can be formed by the base rpm information we don't store it, but
140 only a flag that we've seen it. */
141 unsigned int medianr = atoi (sp[0]);
142 const char *n1 = sp[1];
143 const char *n2 = id2str (pool, s->name);
144 for (n2 = id2str (pool, s->name); *n2; n1++, n2++)
147 if (*n2 || *n1 != '-')
151 for (n2 = id2str (pool, s->evr); *n2; n1++, n2++)
154 if (*n2 || *n1 != '.')
157 for (n2 = id2str (pool, s->arch); *n2; n1++, n2++)
160 if (*n2 || strcmp (n1, ".rpm"))
163 repodata_set_constant(pd->data, handle, SOLVABLE_MEDIANR, medianr);
164 repodata_set_void(pd->data, handle, SOLVABLE_MEDIADIR);
165 repodata_set_void(pd->data, handle, SOLVABLE_MEDIAFILE);
169 repodata_set_constant(pd->data, handle, SOLVABLE_MEDIANR, medianr);
170 repodata_set_void(pd->data, handle, SOLVABLE_MEDIADIR);
171 repodata_set_str(pd->data, handle, SOLVABLE_MEDIAFILE, sp[1]);
182 add_source(struct parsedata *pd, char *line, Solvable *s, unsigned handle)
184 Repo *repo = s->repo;
185 Pool *pool = repo->pool;
188 if (split(line, sp, 5) != 4)
190 fprintf(stderr, "Bad source line: %d: %s\n", pd->lineno, line);
194 Id name = str2id(pool, sp[0], 1);
195 Id evr = makeevr(pool, join2(sp[1], "-", sp[2]));
196 Id arch = str2id(pool, sp[3], 1);
197 /* XXX: could record a dep here, depends on where we want to store the data */
199 repodata_set_void(pd->data, handle, SOLVABLE_SOURCENAME);
201 repodata_set_id(pd->data, handle, SOLVABLE_SOURCENAME, name);
203 repodata_set_void(pd->data, handle, SOLVABLE_SOURCEEVR);
205 repodata_set_id(pd->data, handle, SOLVABLE_SOURCEEVR, evr);
206 repodata_set_constantid(pd->data, handle, SOLVABLE_SOURCEARCH, arch);
211 * add a line with directory information
216 add_dirline (struct parsedata *pd, char *line)
219 if (split(line, sp, 6) != 5)
221 pd->dirs = sat_extend(pd->dirs, pd->ndirs, 1, sizeof(pd->dirs[0]), 31);
222 long filesz = strtol (sp[1], 0, 0);
223 filesz += strtol (sp[2], 0, 0);
224 long filenum = strtol (sp[3], 0, 0);
225 filenum += strtol (sp[4], 0, 0);
226 /* hack: we know that there's room for a / */
229 unsigned dirid = repodata_str2dir(pd->data, sp[0], 1);
231 fprintf(stderr, "%s -> %d\n", sp[0], dirid);
233 pd->dirs[pd->ndirs][0] = dirid;
234 pd->dirs[pd->ndirs][1] = filesz;
235 pd->dirs[pd->ndirs][2] = filenum;
240 set_checksum(struct parsedata *pd, Repodata *data, int handle, Id keyname, char *line)
245 if (split(line, sp, 3) != 2)
247 fprintf(stderr, "Bad source line: %d: %s\n", pd->lineno, line);
250 if (!strcasecmp (sp[0], "sha1"))
251 l = SIZEOF_SHA1 * 2, type = REPOKEY_TYPE_SHA1;
252 else if (!strcasecmp (sp[0], "md5"))
253 l = SIZEOF_MD5 * 2, type = REPOKEY_TYPE_MD5;
256 fprintf(stderr, "Unknown checksum type: %d: %s\n", pd->lineno, sp[0]);
259 if (strlen(sp[1]) != l)
261 fprintf(stderr, "Invalid checksum length: %d: for %s: %s\n", pd->lineno, sp[0], sp[1]);
264 repodata_set_checksum(data, handle, keyname, type, sp[1]);
274 id3_cmp (const void *v1, const void *v2)
278 return i1[0] - i2[0];
288 commit_diskusage (struct parsedata *pd, unsigned handle)
291 Dirpool *dp = &pd->data->dirpool;
292 /* Now sort in dirid order. This ensures that parents come before
295 qsort(pd->dirs, pd->ndirs, sizeof (pd->dirs[0]), id3_cmp);
296 /* Substract leaf numbers from all parents to make the numbers
297 non-cumulative. This must be done post-order (i.e. all leafs
298 adjusted before parents). We ensure this by starting at the end of
299 the array moving to the start, hence seeing leafs before parents. */
300 for (i = pd->ndirs; i--;)
302 unsigned p = dirpool_parent(dp, pd->dirs[i][0]);
304 for (; p; p = dirpool_parent(dp, p))
307 if (pd->dirs[j][0] == p)
311 if (pd->dirs[j][1] < pd->dirs[i][1])
314 pd->dirs[j][1] -= pd->dirs[i][1];
315 if (pd->dirs[j][2] < pd->dirs[i][2])
318 pd->dirs[j][2] -= pd->dirs[i][2];
321 /* Haven't found this parent in the list, look further if
322 we maybe find the parents parent. */
329 unsigned slen = sizeof (sbuf);
330 for (i = 0; i < pd->ndirs; i++)
332 dir2str (attr, pd->dirs[i][0], &buf, &slen);
333 fprintf (stderr, "have dir %d %d %d %s\n", pd->dirs[i][0], pd->dirs[i][1], pd->dirs[i][2], buf);
338 for (i = 0; i < pd->ndirs; i++)
339 if (pd->dirs[i][1] || pd->dirs[i][2])
341 repodata_add_dirnumnum(pd->data, handle, SOLVABLE_DISKUSAGE, pd->dirs[i][0], pd->dirs[i][1], pd->dirs[i][2]);
347 /* Unfortunately "a"[0] is no constant expression in the C languages,
348 so we need to pass the four characters individually :-/ */
349 #define CTAG(a,b,c,d) ((unsigned)(((unsigned char)a) << 24) \
350 | ((unsigned char)b << 16) \
351 | ((unsigned char)c << 8) \
352 | ((unsigned char)d))
359 static inline unsigned
360 tag_from_string (char *cs)
362 unsigned char *s = (unsigned char*) cs;
363 return ((s[0] << 24) | (s[1] << 16) | (s[2] << 8) | s[3]);
369 * Parse susetags file passed in fp, fill solvables into repo
371 * susetags is key,value based
375 * for long (multi-line) values,
382 * See http://en.opensuse.org/Standards/YaST2_Repository_Metadata
383 * and http://en.opensuse.org/Standards/YaST2_Repository_Metadata/packages
384 * and http://en.opensuse.org/Standards/YaST2_Repository_Metadata/pattern
387 * All keys have 3 characters and end in ':'
391 finish_solvable(struct parsedata *pd, Solvable *s, int handle, Offset freshens)
393 Pool *pool = pd->repo->pool;
396 /* move file provides to filelist */
397 /* relies on the fact that rpm inserts self-provides at the end */
400 Id *p, *lastreal, did;
401 const char *str, *sp;
402 lastreal = pd->repo->idarraydata + s->provides;
403 for (p = lastreal; *p; p++)
406 for (p = lastreal; *p; p++)
408 str = id2str(pool, *p);
414 for (p = lastreal; *p; p++)
418 str = id2str(pool, *p);
419 sp = strrchr(str, '/');
420 /* Need to copy filename now, before we add string that could
421 realloc the stringspace (and hence invalidate str). */
423 if (strlen(fname) >= 128)
424 fname = strdup(fname);
427 memcpy(fname_buf, fname, strlen(fname) + 1);
432 char *sdup = strdup(str);
434 did = repodata_str2dir(pd->data, sdup, 1);
440 strncpy(sdup, str, sp - str);
442 did = repodata_str2dir(pd->data, sdup, 1);
445 did = repodata_str2dir(pd->data, "/", 1);
446 repodata_add_dirstr(pd->data, handle, SOLVABLE_FILELIST, did, fname);
447 if (fname != fname_buf)
454 /* A self provide, except for source packages. This is harmless
455 to do twice (in case we see the same package twice). */
456 if (s->arch != ARCH_SRC && s->arch != ARCH_NOSRC)
457 s->provides = repo_addid_dep(pd->repo, s->provides,
458 rel2id(pool, s->name, s->evr, REL_EQ, 1), 0);
459 /* XXX This uses repo_addid_dep internally, so should also be
460 harmless to do twice. */
461 s->supplements = repo_fix_supplements(pd->repo, s->provides, s->supplements, freshens);
462 s->conflicts = repo_fix_conflicts(pd->repo, s->conflicts);
464 commit_diskusage (pd, handle);
471 * fp: file to read from
472 * product: solvable representing the product (0 if none)
473 * language: current language (0 if none)
478 repo_add_susetags(Repo *repo, FILE *fp, Id product, const char *language, int flags)
480 Pool *pool = repo->pool;
488 int last_found_pack = 0;
496 if ((flags & SUSETAGS_EXTEND) && repo->nrepodata)
499 /* use last repodata */
500 data = repo->repodata + repo->nrepodata - 1;
502 data = repo_add_repodata(repo, 0);
506 if (!strncmp (id2str(pool, pool->solvables[product].name), "product:", 8))
507 vendor = pool->solvables[product].vendor;
510 memset(&pd, 0, sizeof(pd));
514 pd.repo = pd.common.repo = repo;
516 pd.common.pool = pool;
522 /* XXX deactivate test code */
527 * collect values in 'struct parsedata pd'
528 * then build .solv (and .attr) file
534 char *olinep; /* old line pointer */
537 if (linep - line + 16 > aline) /* (re-)alloc buffer */
539 aline = linep - line;
540 line = realloc(line, aline + 512);
541 linep = line + aline;
544 if (!fgets(linep, aline - (linep - line), fp)) /* read line */
547 linep += strlen(linep);
548 if (linep == line || linep[-1] != '\n')
557 /* check for multi-line value tags (+Key:/-Key:) */
559 int is_end = (linep[-intag - keylen + 1] == '-')
560 && (linep[-1] == ':')
561 && (linep == line + 1 + intag + 1 + 1 + 1 + intag + 1 || linep[-intag - keylen] == '\n');
563 && strncmp(linep - 1 - intag, line + 1, intag))
565 fprintf(stderr, "Nonmatching multi-line tags: %d: '%s' '%s' %d\n", pd.lineno, linep - 1 - intag, line + 1, intag);
567 if (cummulate && !is_end)
572 if (cummulate && is_end)
574 linep[-intag - keylen + 1] = 0;
575 if (linep[-intag - keylen] == '\n')
576 linep[-intag - keylen] = 0;
580 if (!cummulate && is_end)
586 if (!cummulate && !is_end)
587 linep = line + intag + keylen;
592 if (!intag && line[0] == '+' && line[1] && line[1] != ':') /* start of +Key:/-Key: tag */
594 char *tagend = strchr(line, ':');
597 fprintf(stderr, "bad line: %d: %s\n", pd.lineno, line);
600 intag = tagend - (line + 1);
602 switch (tag_from_string (line)) /* check if accumulation is needed */
604 case CTAG('+', 'P', 'r', 'q'):
605 case CTAG('+', 'P', 'r', 'c'):
606 case CTAG('+', 'P', 's', 'g'):
607 if (!pd.kind || !(flags & SUSETAGS_KINDS_SEPARATELY))
609 case CTAG('+', 'D', 'e', 's'):
610 case CTAG('+', 'E', 'u', 'l'):
611 case CTAG('+', 'I', 'n', 's'):
612 case CTAG('+', 'D', 'e', 'l'):
613 case CTAG('+', 'A', 'u', 't'):
617 line[0] = '='; /* handle lines between +Key:/-Key: as =Key: */
618 line[intag + keylen - 1] = ' ';
619 linep = line + intag + keylen;
622 if (*line == '#' || !*line)
624 if (! (line[0] && line[1] && line[2] && line[3] && (line[4] == ':' || line[4] == '.')))
629 endlang = strchr(line + 5, ':');
632 keylen = endlang - line - 1;
633 strncpy(line_lang, line + 5, 5);
634 line_lang[endlang - line - 5] = 0;
639 tag = tag_from_string (line);
643 * start of (next) package or pattern
645 * =Pkg: <name> <version> <release> <architecture>
649 if ((tag == CTAG('=', 'P', 'k', 'g')
650 || tag == CTAG('=', 'P', 'a', 't')))
653 /* If we have an old solvable, complete it by filling in some
656 finish_solvable(&pd, s, handle, freshens);
670 if (split(line + 5, sp, 5) != 4)
672 fprintf(stderr, "Bad line: %d: %s\n", pd.lineno, line);
675 /* Lookup (but don't construct) the name and arch. */
677 name = str2id(pool, join2(pd.kind, ":", sp[0]), 0);
679 name = str2id(pool, sp[0], 0);
680 arch = str2id(pool, sp[3], 0);
681 evr = makeevr(pool, join2(sp[1], "-", sp[2]));
686 /* Now see if we know this solvable already. If we found neither
687 the name nor the arch at all in this repo
688 there's no chance of finding the exact solvable either. */
689 if (name && arch && (indesc >= 2))
692 /* Now look for a solvable with the given name,evr,arch.
693 Our input is structured so, that the second set of =Pkg
694 lines comes in roughly the same order as the first set, so we
695 have a hint at where to start our search, namely were we found
697 for (n = repo->start, nn = n + last_found_pack; n < repo->end; n++, nn++)
701 s = pool->solvables + nn;
702 if (s->repo == repo && s->name == name && s->evr == evr && s->arch == arch)
709 last_found_pack = nn - repo->start;
710 handle = repodata_get_handle(data, last_found_pack);
715 /* And if we still don't have a solvable, create a new one. */
718 s = pool_id2solvable(pool, repo_add_solvable(repo));
719 last_found_pack = (s - pool->solvables) - repo->start;
722 repodata_extend(data, s - pool->solvables);
723 handle = repodata_get_handle(data, last_found_pack);
728 s->name = str2id(pool, join2(pd.kind, ":", sp[0]), 1);
730 s->name = str2id(pool, sp[0], 1);
735 s->arch = str2id(pool, sp[3], 1);
736 s->vendor = vendor; /* default to product vendor */
740 /* If we have no current solvable to add to, ignore all further lines
741 for it. Probably invalid input data in the second set of
743 if (indesc >= 2 && !s)
745 fprintf (stderr, "Huh %d: %s?\n", pd.lineno, line);
750 case CTAG('=', 'P', 'r', 'v'): /* provides */
751 s->provides = adddep(pool, &pd, s->provides, line, 0, pd.kind);
753 case CTAG('=', 'R', 'e', 'q'): /* requires */
754 s->requires = adddep(pool, &pd, s->requires, line, -SOLVABLE_PREREQMARKER, pd.kind);
756 case CTAG('=', 'P', 'r', 'q'): /* pre-requires / packages required */
759 if (flags & SUSETAGS_KINDS_SEPARATELY)
760 repodata_set_poolstr(data, handle, str2id(pool, "solvable:must", 1), line + 6);
762 s->requires = adddep(pool, &pd, s->requires, line, 0, 0); /* patterns: a required package */
765 s->requires = adddep(pool, &pd, s->requires, line, SOLVABLE_PREREQMARKER, 0); /* package: pre-requires */
767 case CTAG('=', 'O', 'b', 's'): /* obsoletes */
768 s->obsoletes = adddep(pool, &pd, s->obsoletes, line, 0, pd.kind);
770 case CTAG('=', 'C', 'o', 'n'): /* conflicts */
771 s->conflicts = adddep(pool, &pd, s->conflicts, line, 0, pd.kind);
773 case CTAG('=', 'R', 'e', 'c'): /* recommends */
774 s->recommends = adddep(pool, &pd, s->recommends, line, 0, pd.kind);
776 case CTAG('=', 'S', 'u', 'p'): /* supplements */
777 s->supplements = adddep(pool, &pd, s->supplements, line, 0, pd.kind);
779 case CTAG('=', 'E', 'n', 'h'): /* enhances */
780 s->enhances = adddep(pool, &pd, s->enhances, line, 0, pd.kind);
782 case CTAG('=', 'S', 'u', 'g'): /* suggests */
783 s->suggests = adddep(pool, &pd, s->suggests, line, 0, pd.kind);
785 case CTAG('=', 'F', 'r', 'e'): /* freshens */
786 freshens = adddep(pool, &pd, freshens, line, 0, pd.kind);
788 case CTAG('=', 'P', 'r', 'c'): /* packages recommended */
789 if (flags & SUSETAGS_KINDS_SEPARATELY)
790 repodata_set_poolstr(data, handle, str2id(pool, "solvable:should", 1), line + 6);
792 s->recommends = adddep(pool, &pd, s->recommends, line, 0, 0);
794 case CTAG('=', 'P', 's', 'g'): /* packages suggested */
795 if (flags & SUSETAGS_KINDS_SEPARATELY)
796 repodata_set_poolstr(data, handle, str2id(pool, "solvable:may", 1), line + 6);
798 s->suggests = adddep(pool, &pd, s->suggests, line, 0, 0);
800 case CTAG('=', 'P', 'c', 'n'): /* pattern: package conflicts */
801 if (flags & SUSETAGS_KINDS_SEPARATELY)
802 fprintf (stderr, "Unsupported: pattern -> package conflicts\n");
804 s->conflicts = adddep(pool, &pd, s->conflicts, line, 0, 0);
806 case CTAG('=', 'P', 'o', 'b'): /* pattern: package obsoletes */
807 if (flags & SUSETAGS_KINDS_SEPARATELY)
808 fprintf (stderr, "Unsupported: pattern -> package obsoletes\n");
810 s->obsoletes = adddep(pool, &pd, s->obsoletes, line, 0, 0);
812 case CTAG('=', 'P', 'f', 'r'): /* pattern: package freshens */
813 if (flags & SUSETAGS_KINDS_SEPARATELY)
814 fprintf (stderr, "Unsupported: pattern -> package freshens\n");
816 freshens = adddep(pool, &pd, freshens, line, 0, 0);
818 case CTAG('=', 'P', 's', 'p'): /* pattern: package supplements */
819 if (flags & SUSETAGS_KINDS_SEPARATELY)
820 fprintf (stderr, "Unsupported: pattern -> package supplements\n");
822 s->supplements = adddep(pool, &pd, s->supplements, line, 0, 0);
824 case CTAG('=', 'P', 'e', 'n'): /* pattern: package enhances */
825 if (flags & SUSETAGS_KINDS_SEPARATELY)
826 fprintf (stderr, "Unsupported: pattern -> package enhances\n");
828 s->enhances = adddep(pool, &pd, s->enhances, line, 0, 0);
830 case CTAG('=', 'V', 'e', 'r'): /* - version - */
835 case CTAG('=', 'V', 'n', 'd'): /* vendor */
836 s->vendor = str2id(pool, line + 6, 1);
839 /* From here it's the attribute tags. */
840 case CTAG('=', 'G', 'r', 'p'):
841 repodata_set_poolstr(data, handle, SOLVABLE_GROUP, line + 6);
843 case CTAG('=', 'L', 'i', 'c'):
844 repodata_set_poolstr(data, handle, SOLVABLE_LICENSE, line + 6);
846 case CTAG('=', 'L', 'o', 'c'):
847 add_location(&pd, line + 6, s, handle);
849 case CTAG('=', 'S', 'r', 'c'):
850 add_source(&pd, line + 6, s, handle);
852 case CTAG('=', 'S', 'i', 'z'):
853 if (split (line + 6, sp, 3) == 2)
855 repodata_set_num(data, handle, SOLVABLE_DOWNLOADSIZE, (atoi(sp[0]) + 1023) / 1024);
856 repodata_set_num(data, handle, SOLVABLE_INSTALLSIZE, (atoi(sp[1]) + 1023) / 1024);
859 case CTAG('=', 'T', 'i', 'm'):
861 unsigned int t = atoi (line + 6);
863 repodata_set_num(data, handle, SOLVABLE_BUILDTIME, t);
866 case CTAG('=', 'K', 'w', 'd'):
867 repodata_add_poolstr_array(data, handle, SOLVABLE_KEYWORDS, line + 6);
869 case CTAG('=', 'A', 'u', 't'):
870 repodata_set_str(data, handle, SOLVABLE_AUTHORS, line + 6);
872 case CTAG('=', 'S', 'u', 'm'):
873 repodata_set_str(data, handle, langtag(&pd, SOLVABLE_SUMMARY, language ? language : line_lang), line + 3 + keylen );
875 case CTAG('=', 'D', 'e', 's'):
876 repodata_set_str(data, handle, langtag(&pd, SOLVABLE_DESCRIPTION, language ? language : line_lang), line + 3 + keylen );
878 case CTAG('=', 'E', 'u', 'l'):
879 repodata_set_str(data, handle, langtag(&pd, SOLVABLE_EULA, language), line + 6);
881 case CTAG('=', 'I', 'n', 's'):
882 repodata_set_str(data, handle, langtag(&pd, SOLVABLE_MESSAGEINS, language), line + 6);
886 repo_set_str(repo, blanr, SOLVABLE_MESSAGEINS, line + 6);
890 case CTAG('=', 'D', 'e', 'l'):
891 repodata_set_str(data, handle, langtag(&pd, SOLVABLE_MESSAGEDEL, language), line + 6);
893 case CTAG('=', 'V', 'i', 's'):
895 /* Accept numbers and textual bools. */
898 if (k || !strcasecmp (line + 6, "true"))
899 repodata_set_void(data, handle, SOLVABLE_ISVISIBLE );
902 case CTAG('=', 'S', 'h', 'r'):
903 if (last_found_pack >= pd.nshare)
907 pd.share_with = realloc (pd.share_with, (last_found_pack + 256) * sizeof (*pd.share_with));
908 memset (pd.share_with + pd.nshare, 0, (last_found_pack + 256 - pd.nshare) * sizeof (*pd.share_with));
911 pd.share_with = calloc (last_found_pack + 256, sizeof (*pd.share_with));
912 pd.nshare = last_found_pack + 256;
914 pd.share_with[last_found_pack] = strdup (line + 6);
916 case CTAG('=', 'D', 'i', 'r'):
917 add_dirline (&pd, line + 6);
919 case CTAG('=', 'C', 'a', 't'):
920 repodata_set_poolstr(data, handle, langtag(&pd, SOLVABLE_CATEGORY, line_lang), line + 3 + keylen);
922 case CTAG('=', 'O', 'r', 'd'):
923 /* Order is a string not a number, so we can retroactively insert
924 new patterns in the middle, i.e. 1 < 15 < 2. */
925 repodata_set_str(data, handle, SOLVABLE_ORDER, line + 6);
927 case CTAG('=', 'I', 'c', 'o'):
928 repodata_set_str(data, handle, SOLVABLE_ICON, line + 6);
930 case CTAG('=', 'E', 'x', 't'):
931 repodata_add_poolstr_array(data, handle, SOLVABLE_EXTENDS, join2("pattern", ":", line + 6));
933 case CTAG('=', 'I', 'n', 'c'):
934 repodata_add_poolstr_array(data, handle, SOLVABLE_INCLUDES, join2("pattern", ":", line + 6));
936 case CTAG('=', 'C', 'k', 's'):
937 set_checksum(&pd, data, handle, SOLVABLE_CHECKSUM, line + 6);
940 Id sub = repodata_create_struct(data, handle, str2id(pool, "solvable:komisch", 1));
941 repodata_set_poolstr(data, sub, str2id(pool, "sub:key1", 1), line + 6);
942 repodata_set_num(data, sub, str2id(pool, "sub:key2", 1), last_found_pack);
943 sub = repodata_create_struct(data, handle, str2id(pool, "solvable:komisch", 1));
944 repodata_set_poolstr(data, sub, str2id(pool, "sub:key1", 1), line + 7);
945 repodata_set_num(data, sub, str2id(pool, "sub:key2", 1), last_found_pack+1);
948 case CTAG('=', 'L', 'a', 'n'):
949 language = strdup(line + 6);
952 case CTAG('=', 'F', 'l', 's'):
954 char *p = strrchr(line + 6, '/');
956 if (p && p != line + 6 && !p[1])
959 p = strrchr(line + 6, '/');
964 did = repodata_str2dir(data, line + 6, 1);
972 did = repodata_str2dir(data, "/", 1);
973 repodata_add_dirstr(data, handle, SOLVABLE_FILELIST, did, p);
977 case CTAG('=', 'P', 'a', 't'):
978 case CTAG('=', 'P', 'k', 'g'):
982 fprintf(stderr,"unknown line %s\n", line);
989 finish_solvable(&pd, s, handle, freshens);
992 * (e.g. multiple binaries built from same source)
998 for (i = 0; i < pd.nshare; i++)
999 if (pd.share_with[i])
1001 if (split(pd.share_with[i], sp, 5) != 4)
1003 fprintf(stderr, "Bad =Shr line: %s\n", pd.share_with[i]);
1007 Id name = str2id(pool, sp[0], 1);
1008 Id evr = makeevr(pool, join2(sp[1], "-", sp[2]));
1009 Id arch = str2id(pool, sp[3], 1);
1011 Solvable *found = 0;
1012 for (n = repo->start, nn = repo->start + last_found;
1013 n < repo->end; n++, nn++)
1015 if (nn >= repo->end)
1017 found = pool->solvables + nn;
1018 if (found->repo == repo
1019 && found->name == name
1020 && found->evr == evr
1021 && found->arch == arch)
1023 last_found = nn - repo->start;
1028 repodata_merge_attrs(data, i, last_found);
1030 free (pd.share_with);
1034 repodata_internalize(data);
1037 free(pd.common.tmp);