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 pool_debug(pool, SAT_FATAL, "susetags: 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 pool_debug(pool, SAT_FATAL, "susetags: unknown relation in %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, Id handle)
113 Pool *pool = s->repo->pool;
117 i = split(line, sp, 3);
118 if (i != 2 && i != 3)
120 pool_debug(pool, SAT_FATAL, "susetags: 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, Id handle)
184 Repo *repo = s->repo;
185 Pool *pool = repo->pool;
188 if (split(line, sp, 5) != 4)
190 pool_debug(pool, SAT_FATAL, "susetags: 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, Id handle, Id keyname, char *line)
245 if (split(line, sp, 3) != 2)
247 pool_debug(pd->repo->pool, SAT_FATAL, "susetags: bad checksum 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 pool_debug(pd->repo->pool, SAT_FATAL, "susetags: unknown checksum type: %d: %s\n", pd->lineno, sp[0]);
259 if (strlen(sp[1]) != l)
261 pool_debug(pd->repo->pool, SAT_FATAL, "susetags: bad 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, Id 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, Id 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;
495 if ((flags & SUSETAGS_EXTEND) && repo->nrepodata)
498 if (!(flags & REPO_REUSE_REPODATA))
499 data = repo_add_repodata(repo, 0);
501 data = repo_last_repodata(repo);
505 if (!strncmp(id2str(pool, pool->solvables[product].name), "product:", 8))
506 vendor = pool->solvables[product].vendor;
509 memset(&pd, 0, sizeof(pd));
513 pd.repo = pd.common.repo = repo;
515 pd.common.pool = pool;
524 * collect values in 'struct parsedata pd'
525 * then build .solv (and .attr) file
531 char *olinep; /* old line pointer */
534 if (linep - line + 16 > aline) /* (re-)alloc buffer */
536 aline = linep - line;
537 line = realloc(line, aline + 512);
538 linep = line + aline;
541 if (!fgets(linep, aline - (linep - line), fp)) /* read line */
544 linep += strlen(linep);
545 if (linep == line || linep[-1] != '\n')
554 /* check for multi-line value tags (+Key:/-Key:) */
556 int is_end = (linep[-intag - keylen + 1] == '-')
557 && (linep[-1] == ':')
558 && (linep == line + 1 + intag + 1 + 1 + 1 + intag + 1 || linep[-intag - keylen] == '\n');
560 && strncmp(linep - 1 - intag, line + 1, intag))
562 pool_debug(pool, SAT_ERROR, "susetags: Nonmatching multi-line tags: %d: '%s' '%s' %d\n", pd.lineno, linep - 1 - intag, line + 1, intag);
564 if (cummulate && !is_end)
569 if (cummulate && is_end)
571 linep[-intag - keylen + 1] = 0;
572 if (linep[-intag - keylen] == '\n')
573 linep[-intag - keylen] = 0;
577 if (!cummulate && is_end)
583 if (!cummulate && !is_end)
584 linep = line + intag + keylen;
589 if (!intag && line[0] == '+' && line[1] && line[1] != ':') /* start of +Key:/-Key: tag */
591 char *tagend = strchr(line, ':');
594 pool_debug(pool, SAT_FATAL, "susetags: bad line: %d: %s\n", pd.lineno, line);
597 intag = tagend - (line + 1);
599 switch (tag_from_string (line)) /* check if accumulation is needed */
601 case CTAG('+', 'P', 'r', 'q'):
602 case CTAG('+', 'P', 'r', 'c'):
603 case CTAG('+', 'P', 's', 'g'):
604 if (!pd.kind || !(flags & SUSETAGS_KINDS_SEPARATELY))
606 case CTAG('+', 'D', 'e', 's'):
607 case CTAG('+', 'E', 'u', 'l'):
608 case CTAG('+', 'I', 'n', 's'):
609 case CTAG('+', 'D', 'e', 'l'):
610 case CTAG('+', 'A', 'u', 't'):
614 line[0] = '='; /* handle lines between +Key:/-Key: as =Key: */
615 line[intag + keylen - 1] = ' ';
616 linep = line + intag + keylen;
619 if (*line == '#' || !*line)
621 if (! (line[0] && line[1] && line[2] && line[3] && (line[4] == ':' || line[4] == '.')))
626 endlang = strchr(line + 5, ':');
629 keylen = endlang - line - 1;
630 strncpy(line_lang, line + 5, 5);
631 line_lang[endlang - line - 5] = 0;
636 tag = tag_from_string (line);
640 * start of (next) package or pattern
642 * =Pkg: <name> <version> <release> <architecture>
646 if ((tag == CTAG('=', 'P', 'k', 'g')
647 || tag == CTAG('=', 'P', 'a', 't')))
650 /* If we have an old solvable, complete it by filling in some
653 finish_solvable(&pd, s, handle, freshens);
667 if (split(line + 5, sp, 5) != 4)
669 pool_debug(pool, SAT_FATAL, "susetags: bad line: %d: %s\n", pd.lineno, line);
672 /* Lookup (but don't construct) the name and arch. */
674 name = str2id(pool, join2(pd.kind, ":", sp[0]), 0);
676 name = str2id(pool, sp[0], 0);
677 arch = str2id(pool, sp[3], 0);
678 evr = makeevr(pool, join2(sp[1], "-", sp[2]));
683 /* Now see if we know this solvable already. If we found neither
684 the name nor the arch at all in this repo
685 there's no chance of finding the exact solvable either. */
686 if (name && arch && (indesc >= 2))
689 /* Now look for a solvable with the given name,evr,arch.
690 Our input is structured so, that the second set of =Pkg
691 lines comes in roughly the same order as the first set, so we
692 have a hint at where to start our search, namely were we found
694 for (n = repo->start, nn = n + last_found_pack; n < repo->end; n++, nn++)
698 s = pool->solvables + nn;
699 if (s->repo == repo && s->name == name && s->evr == evr && s->arch == arch)
706 last_found_pack = nn - repo->start;
712 /* And if we still don't have a solvable, create a new one. */
715 s = pool_id2solvable(pool, repo_add_solvable(repo));
716 last_found_pack = (s - pool->solvables) - repo->start;
718 handle = s - pool->solvables;
722 s->name = str2id(pool, join2(pd.kind, ":", sp[0]), 1);
724 s->name = str2id(pool, sp[0], 1);
729 s->arch = str2id(pool, sp[3], 1);
730 s->vendor = vendor; /* default to product vendor */
734 /* If we have no current solvable to add to, ignore all further lines
735 for it. Probably invalid input data in the second set of
737 if (indesc >= 2 && !s)
739 fprintf (stderr, "Huh %d: %s?\n", pd.lineno, line);
744 case CTAG('=', 'P', 'r', 'v'): /* provides */
745 s->provides = adddep(pool, &pd, s->provides, line, 0, pd.kind);
747 case CTAG('=', 'R', 'e', 'q'): /* requires */
748 s->requires = adddep(pool, &pd, s->requires, line, -SOLVABLE_PREREQMARKER, pd.kind);
750 case CTAG('=', 'P', 'r', 'q'): /* pre-requires / packages required */
753 if (flags & SUSETAGS_KINDS_SEPARATELY)
754 repodata_set_poolstr(data, handle, str2id(pool, "solvable:must", 1), line + 6);
756 s->requires = adddep(pool, &pd, s->requires, line, 0, 0); /* patterns: a required package */
759 s->requires = adddep(pool, &pd, s->requires, line, SOLVABLE_PREREQMARKER, 0); /* package: pre-requires */
761 case CTAG('=', 'O', 'b', 's'): /* obsoletes */
762 s->obsoletes = adddep(pool, &pd, s->obsoletes, line, 0, pd.kind);
764 case CTAG('=', 'C', 'o', 'n'): /* conflicts */
765 s->conflicts = adddep(pool, &pd, s->conflicts, line, 0, pd.kind);
767 case CTAG('=', 'R', 'e', 'c'): /* recommends */
768 s->recommends = adddep(pool, &pd, s->recommends, line, 0, pd.kind);
770 case CTAG('=', 'S', 'u', 'p'): /* supplements */
771 s->supplements = adddep(pool, &pd, s->supplements, line, 0, pd.kind);
773 case CTAG('=', 'E', 'n', 'h'): /* enhances */
774 s->enhances = adddep(pool, &pd, s->enhances, line, 0, pd.kind);
776 case CTAG('=', 'S', 'u', 'g'): /* suggests */
777 s->suggests = adddep(pool, &pd, s->suggests, line, 0, pd.kind);
779 case CTAG('=', 'F', 'r', 'e'): /* freshens */
780 freshens = adddep(pool, &pd, freshens, line, 0, pd.kind);
782 case CTAG('=', 'P', 'r', 'c'): /* packages recommended */
783 if (flags & SUSETAGS_KINDS_SEPARATELY)
784 repodata_set_poolstr(data, handle, str2id(pool, "solvable:should", 1), line + 6);
786 s->recommends = adddep(pool, &pd, s->recommends, line, 0, 0);
788 case CTAG('=', 'P', 's', 'g'): /* packages suggested */
789 if (flags & SUSETAGS_KINDS_SEPARATELY)
790 repodata_set_poolstr(data, handle, str2id(pool, "solvable:may", 1), line + 6);
792 s->suggests = adddep(pool, &pd, s->suggests, line, 0, 0);
794 case CTAG('=', 'P', 'c', 'n'): /* pattern: package conflicts */
795 if (flags & SUSETAGS_KINDS_SEPARATELY)
796 fprintf (stderr, "Unsupported: pattern -> package conflicts\n");
798 s->conflicts = adddep(pool, &pd, s->conflicts, line, 0, 0);
800 case CTAG('=', 'P', 'o', 'b'): /* pattern: package obsoletes */
801 if (flags & SUSETAGS_KINDS_SEPARATELY)
802 fprintf (stderr, "Unsupported: pattern -> package obsoletes\n");
804 s->obsoletes = adddep(pool, &pd, s->obsoletes, line, 0, 0);
806 case CTAG('=', 'P', 'f', 'r'): /* pattern: package freshens */
807 if (flags & SUSETAGS_KINDS_SEPARATELY)
808 fprintf (stderr, "Unsupported: pattern -> package freshens\n");
810 freshens = adddep(pool, &pd, freshens, line, 0, 0);
812 case CTAG('=', 'P', 's', 'p'): /* pattern: package supplements */
813 if (flags & SUSETAGS_KINDS_SEPARATELY)
814 fprintf (stderr, "Unsupported: pattern -> package supplements\n");
816 s->supplements = adddep(pool, &pd, s->supplements, line, 0, 0);
818 case CTAG('=', 'P', 'e', 'n'): /* pattern: package enhances */
819 if (flags & SUSETAGS_KINDS_SEPARATELY)
820 fprintf (stderr, "Unsupported: pattern -> package enhances\n");
822 s->enhances = adddep(pool, &pd, s->enhances, line, 0, 0);
824 case CTAG('=', 'V', 'e', 'r'): /* - version - */
829 case CTAG('=', 'V', 'n', 'd'): /* vendor */
830 s->vendor = str2id(pool, line + 6, 1);
833 /* From here it's the attribute tags. */
834 case CTAG('=', 'G', 'r', 'p'):
835 repodata_set_poolstr(data, handle, SOLVABLE_GROUP, line + 6);
837 case CTAG('=', 'L', 'i', 'c'):
838 repodata_set_poolstr(data, handle, SOLVABLE_LICENSE, line + 6);
840 case CTAG('=', 'L', 'o', 'c'):
841 add_location(&pd, line + 6, s, handle);
843 case CTAG('=', 'S', 'r', 'c'):
844 add_source(&pd, line + 6, s, handle);
846 case CTAG('=', 'S', 'i', 'z'):
847 if (split (line + 6, sp, 3) == 2)
849 repodata_set_num(data, handle, SOLVABLE_DOWNLOADSIZE, (unsigned int)(atoi(sp[0]) + 1023) / 1024);
850 repodata_set_num(data, handle, SOLVABLE_INSTALLSIZE, (unsigned int)(atoi(sp[1]) + 1023) / 1024);
853 case CTAG('=', 'T', 'i', 'm'):
855 unsigned int t = atoi (line + 6);
857 repodata_set_num(data, handle, SOLVABLE_BUILDTIME, t);
860 case CTAG('=', 'K', 'w', 'd'):
861 repodata_add_poolstr_array(data, handle, SOLVABLE_KEYWORDS, line + 6);
863 case CTAG('=', 'A', 'u', 't'):
864 repodata_set_str(data, handle, SOLVABLE_AUTHORS, line + 6);
866 case CTAG('=', 'S', 'u', 'm'):
867 repodata_set_str(data, handle, langtag(&pd, SOLVABLE_SUMMARY, language ? language : line_lang), line + 3 + keylen );
869 case CTAG('=', 'D', 'e', 's'):
870 repodata_set_str(data, handle, langtag(&pd, SOLVABLE_DESCRIPTION, language ? language : line_lang), line + 3 + keylen );
872 case CTAG('=', 'E', 'u', 'l'):
873 repodata_set_str(data, handle, langtag(&pd, SOLVABLE_EULA, language), line + 6);
875 case CTAG('=', 'I', 'n', 's'):
876 repodata_set_str(data, handle, langtag(&pd, SOLVABLE_MESSAGEINS, language), line + 6);
878 case CTAG('=', 'D', 'e', 'l'):
879 repodata_set_str(data, handle, langtag(&pd, SOLVABLE_MESSAGEDEL, language), line + 6);
881 case CTAG('=', 'V', 'i', 's'):
883 /* Accept numbers and textual bools. */
886 if (k || !strcasecmp (line + 6, "true"))
887 repodata_set_void(data, handle, SOLVABLE_ISVISIBLE );
890 case CTAG('=', 'S', 'h', 'r'):
891 if (last_found_pack >= pd.nshare)
893 pd.share_with = sat_realloc2(pd.share_with, last_found_pack + 256, sizeof (*pd.share_with));
894 memset(pd.share_with + pd.nshare, 0, (last_found_pack + 256 - pd.nshare) * sizeof (*pd.share_with));
895 pd.nshare = last_found_pack + 256;
897 pd.share_with[last_found_pack] = strdup(line + 6);
899 case CTAG('=', 'D', 'i', 'r'):
900 add_dirline (&pd, line + 6);
902 case CTAG('=', 'C', 'a', 't'):
903 repodata_set_poolstr(data, handle, langtag(&pd, SOLVABLE_CATEGORY, line_lang), line + 3 + keylen);
905 case CTAG('=', 'O', 'r', 'd'):
906 /* Order is a string not a number, so we can retroactively insert
907 new patterns in the middle, i.e. 1 < 15 < 2. */
908 repodata_set_str(data, handle, SOLVABLE_ORDER, line + 6);
910 case CTAG('=', 'I', 'c', 'o'):
911 repodata_set_str(data, handle, SOLVABLE_ICON, line + 6);
913 case CTAG('=', 'E', 'x', 't'):
914 repodata_add_poolstr_array(data, handle, SOLVABLE_EXTENDS, join2("pattern", ":", line + 6));
916 case CTAG('=', 'I', 'n', 'c'):
917 repodata_add_poolstr_array(data, handle, SOLVABLE_INCLUDES, join2("pattern", ":", line + 6));
919 case CTAG('=', 'C', 'k', 's'):
920 set_checksum(&pd, data, handle, SOLVABLE_CHECKSUM, line + 6);
924 Id sub = repodata_create_struct(data, handle, str2id(pool, "solvable:komisch", 1));
925 repodata_set_poolstr(data, sub, str2id(pool, "sub:key1", 1), line + 6);
926 repodata_set_num(data, sub, str2id(pool, "sub:key2", 1), last_found_pack);
927 sub = repodata_create_struct(data, handle, str2id(pool, "solvable:komisch", 1));
928 repodata_set_poolstr(data, sub, str2id(pool, "sub:key1", 1), line + 7);
929 repodata_set_num(data, sub, str2id(pool, "sub:key2", 1), last_found_pack+1);
933 case CTAG('=', 'L', 'a', 'n'):
934 language = strdup(line + 6);
937 case CTAG('=', 'F', 'l', 's'):
939 char *p = strrchr(line + 6, '/');
941 if (p && p != line + 6 && !p[1])
944 p = strrchr(line + 6, '/');
949 did = repodata_str2dir(data, line + 6, 1);
957 did = repodata_str2dir(data, "/", 1);
958 repodata_add_dirstr(data, handle, SOLVABLE_FILELIST, did, p);
962 case CTAG('=', 'P', 'a', 't'):
963 case CTAG('=', 'P', 'k', 'g'):
967 pool_debug(pool, SAT_ERROR, "susetags: unknown line: %d: %s\n", pd.lineno, line);
974 finish_solvable(&pd, s, handle, freshens);
977 * (e.g. multiple binaries built from same source)
983 for (i = 0; i < pd.nshare; i++)
984 if (pd.share_with[i])
986 if (split(pd.share_with[i], sp, 5) != 4)
988 pool_debug(pool, SAT_FATAL, "susetags: bad =Shr line: %s\n", pd.share_with[i]);
992 Id name = str2id(pool, sp[0], 1);
993 Id evr = makeevr(pool, join2(sp[1], "-", sp[2]));
994 Id arch = str2id(pool, sp[3], 1);
997 for (n = repo->start, nn = repo->start + last_found;
998 n < repo->end; n++, nn++)
1000 if (nn >= repo->end)
1002 found = pool->solvables + nn;
1003 if (found->repo == repo
1004 && found->name == name
1005 && found->evr == evr
1006 && found->arch == arch)
1008 last_found = nn - repo->start;
1013 repodata_merge_attrs(data, repo->start + i, repo->start + last_found);
1014 free(pd.share_with[i]);
1016 free(pd.share_with);
1019 if (!(flags & REPO_NO_INTERNALIZE))
1020 repodata_internalize(data);
1023 free(pd.common.tmp);