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_source(struct parsedata *pd, char *line, Solvable *s, Id handle)
113 Repo *repo = s->repo;
114 Pool *pool = repo->pool;
117 if (split(line, sp, 5) != 4)
119 pool_debug(pool, SAT_FATAL, "susetags: bad source line: %d: %s\n", pd->lineno, line);
123 Id name = str2id(pool, sp[0], 1);
124 Id evr = makeevr(pool, join2(sp[1], "-", sp[2]));
125 Id arch = str2id(pool, sp[3], 1);
126 /* XXX: could record a dep here, depends on where we want to store the data */
128 repodata_set_void(pd->data, handle, SOLVABLE_SOURCENAME);
130 repodata_set_id(pd->data, handle, SOLVABLE_SOURCENAME, name);
132 repodata_set_void(pd->data, handle, SOLVABLE_SOURCEEVR);
134 repodata_set_id(pd->data, handle, SOLVABLE_SOURCEEVR, evr);
135 repodata_set_constantid(pd->data, handle, SOLVABLE_SOURCEARCH, arch);
140 * add a line with directory information
145 add_dirline(struct parsedata *pd, char *line)
148 if (split(line, sp, 6) != 5)
150 pd->dirs = sat_extend(pd->dirs, pd->ndirs, 1, sizeof(pd->dirs[0]), 31);
151 long filesz = strtol(sp[1], 0, 0);
152 filesz += strtol(sp[2], 0, 0);
153 long filenum = strtol(sp[3], 0, 0);
154 filenum += strtol(sp[4], 0, 0);
155 /* hack: we know that there's room for a / */
158 unsigned dirid = repodata_str2dir(pd->data, sp[0], 1);
160 fprintf(stderr, "%s -> %d\n", sp[0], dirid);
162 pd->dirs[pd->ndirs][0] = dirid;
163 pd->dirs[pd->ndirs][1] = filesz;
164 pd->dirs[pd->ndirs][2] = filenum;
169 set_checksum(struct parsedata *pd, Repodata *data, Id handle, Id keyname, char *line)
174 if (split(line, sp, 3) != 2)
176 pool_debug(pd->repo->pool, SAT_FATAL, "susetags: bad checksum line: %d: %s\n", pd->lineno, line);
179 if (!strcasecmp(sp[0], "sha1"))
180 l = SIZEOF_SHA1 * 2, type = REPOKEY_TYPE_SHA1;
181 else if (!strcasecmp(sp[0], "md5"))
182 l = SIZEOF_MD5 * 2, type = REPOKEY_TYPE_MD5;
185 pool_debug(pd->repo->pool, SAT_FATAL, "susetags: unknown checksum type: %d: %s\n", pd->lineno, sp[0]);
188 if (strlen(sp[1]) != l)
190 pool_debug(pd->repo->pool, SAT_FATAL, "susetags: bad checksum length: %d: for %s: %s\n", pd->lineno, sp[0], sp[1]);
193 repodata_set_checksum(data, handle, keyname, type, sp[1]);
203 id3_cmp(const void *v1, const void *v2)
207 return i1[0] - i2[0];
217 commit_diskusage(struct parsedata *pd, Id handle)
220 Dirpool *dp = &pd->data->dirpool;
221 /* Now sort in dirid order. This ensures that parents come before
224 qsort(pd->dirs, pd->ndirs, sizeof(pd->dirs[0]), id3_cmp);
225 /* Substract leaf numbers from all parents to make the numbers
226 non-cumulative. This must be done post-order (i.e. all leafs
227 adjusted before parents). We ensure this by starting at the end of
228 the array moving to the start, hence seeing leafs before parents. */
229 for (i = pd->ndirs; i--;)
231 unsigned p = dirpool_parent(dp, pd->dirs[i][0]);
233 for (; p; p = dirpool_parent(dp, p))
236 if (pd->dirs[j][0] == p)
240 if (pd->dirs[j][1] < pd->dirs[i][1])
243 pd->dirs[j][1] -= pd->dirs[i][1];
244 if (pd->dirs[j][2] < pd->dirs[i][2])
247 pd->dirs[j][2] -= pd->dirs[i][2];
250 /* Haven't found this parent in the list, look further if
251 we maybe find the parents parent. */
258 unsigned slen = sizeof(sbuf);
259 for (i = 0; i < pd->ndirs; i++)
261 dir2str(attr, pd->dirs[i][0], &buf, &slen);
262 fprintf(stderr, "have dir %d %d %d %s\n", pd->dirs[i][0], pd->dirs[i][1], pd->dirs[i][2], buf);
267 for (i = 0; i < pd->ndirs; i++)
268 if (pd->dirs[i][1] || pd->dirs[i][2])
270 repodata_add_dirnumnum(pd->data, handle, SOLVABLE_DISKUSAGE, pd->dirs[i][0], pd->dirs[i][1], pd->dirs[i][2]);
276 /* Unfortunately "a"[0] is no constant expression in the C languages,
277 so we need to pass the four characters individually :-/ */
278 #define CTAG(a,b,c,d) ((unsigned)(((unsigned char)a) << 24) \
279 | ((unsigned char)b << 16) \
280 | ((unsigned char)c << 8) \
281 | ((unsigned char)d))
288 static inline unsigned
289 tag_from_string(char *cs)
291 unsigned char *s = (unsigned char *)cs;
292 return ((s[0] << 24) | (s[1] << 16) | (s[2] << 8) | s[3]);
298 * Parse susetags file passed in fp, fill solvables into repo
300 * susetags is key,value based
304 * for long (multi-line) values,
311 * See http://en.opensuse.org/Standards/YaST2_Repository_Metadata
312 * and http://en.opensuse.org/Standards/YaST2_Repository_Metadata/packages
313 * and http://en.opensuse.org/Standards/YaST2_Repository_Metadata/pattern
316 * All keys have 3 characters and end in ':'
320 finish_solvable(struct parsedata *pd, Solvable *s, Id handle, Offset freshens)
322 Pool *pool = pd->repo->pool;
325 /* move file provides to filelist */
326 /* relies on the fact that rpm inserts self-provides at the end */
329 Id *p, *lastreal, did;
330 const char *str, *sp;
331 lastreal = pd->repo->idarraydata + s->provides;
332 for (p = lastreal; *p; p++)
335 for (p = lastreal; *p; p++)
337 str = id2str(pool, *p);
343 for (p = lastreal; *p; p++)
347 str = id2str(pool, *p);
348 sp = strrchr(str, '/');
349 /* Need to copy filename now, before we add string that could
350 realloc the stringspace (and hence invalidate str). */
352 if (strlen(fname) >= 128)
353 fname = strdup(fname);
356 memcpy(fname_buf, fname, strlen(fname) + 1);
361 char *sdup = strdup(str);
363 did = repodata_str2dir(pd->data, sdup, 1);
369 strncpy(sdup, str, sp - str);
371 did = repodata_str2dir(pd->data, sdup, 1);
374 did = repodata_str2dir(pd->data, "/", 1);
375 repodata_add_dirstr(pd->data, handle, SOLVABLE_FILELIST, did, fname);
376 if (fname != fname_buf)
383 /* A self provide, except for source packages. This is harmless
384 to do twice (in case we see the same package twice). */
385 if (s->arch != ARCH_SRC && s->arch != ARCH_NOSRC)
386 s->provides = repo_addid_dep(pd->repo, s->provides,
387 rel2id(pool, s->name, s->evr, REL_EQ, 1), 0);
388 /* XXX This uses repo_addid_dep internally, so should also be
389 harmless to do twice. */
390 s->supplements = repo_fix_supplements(pd->repo, s->provides, s->supplements, freshens);
391 s->conflicts = repo_fix_conflicts(pd->repo, s->conflicts);
393 commit_diskusage(pd, handle);
400 * fp: file to read from
401 * product: solvable representing the product (0 if none)
402 * language: current language (0 if none)
407 repo_add_susetags(Repo *repo, FILE *fp, Id product, const char *language, int flags)
409 Pool *pool = repo->pool;
417 int last_found_pack = 0;
424 if ((flags & SUSETAGS_EXTEND) && repo->nrepodata)
427 if (!(flags & REPO_REUSE_REPODATA))
428 data = repo_add_repodata(repo, 0);
430 data = repo_last_repodata(repo);
434 if (!strncmp(id2str(pool, pool->solvables[product].name), "product:", 8))
435 vendor = pool->solvables[product].vendor;
438 memset(&pd, 0, sizeof(pd));
442 pd.repo = pd.common.repo = repo;
444 pd.common.pool = pool;
453 * collect values in 'struct parsedata pd'
454 * then build .solv (and .attr) file
460 char *olinep; /* old line pointer */
463 if (linep - line + 16 > aline) /* (re-)alloc buffer */
465 aline = linep - line;
466 line = realloc(line, aline + 512);
467 linep = line + aline;
470 if (!fgets(linep, aline - (linep - line), fp)) /* read line */
473 linep += strlen(linep);
474 if (linep == line || linep[-1] != '\n')
483 /* check for multi-line value tags (+Key:/-Key:) */
485 int is_end = (linep[-intag - keylen + 1] == '-')
486 && (linep[-1] == ':')
487 && (linep == line + 1 + intag + 1 + 1 + 1 + intag + 1 || linep[-intag - keylen] == '\n');
489 && strncmp(linep - 1 - intag, line + 1, intag))
491 pool_debug(pool, SAT_ERROR, "susetags: Nonmatching multi-line tags: %d: '%s' '%s' %d\n", pd.lineno, linep - 1 - intag, line + 1, intag);
493 if (cummulate && !is_end)
498 if (cummulate && is_end)
500 linep[-intag - keylen + 1] = 0;
501 if (linep[-intag - keylen] == '\n')
502 linep[-intag - keylen] = 0;
506 if (!cummulate && is_end)
512 if (!cummulate && !is_end)
513 linep = line + intag + keylen;
518 if (!intag && line[0] == '+' && line[1] && line[1] != ':') /* start of +Key:/-Key: tag */
520 char *tagend = strchr(line, ':');
523 pool_debug(pool, SAT_FATAL, "susetags: bad line: %d: %s\n", pd.lineno, line);
526 intag = tagend - (line + 1);
528 switch (tag_from_string(line)) /* check if accumulation is needed */
530 case CTAG('+', 'P', 'r', 'q'):
531 case CTAG('+', 'P', 'r', 'c'):
532 case CTAG('+', 'P', 's', 'g'):
533 if (!pd.kind || !(flags & SUSETAGS_KINDS_SEPARATELY))
535 case CTAG('+', 'D', 'e', 's'):
536 case CTAG('+', 'E', 'u', 'l'):
537 case CTAG('+', 'I', 'n', 's'):
538 case CTAG('+', 'D', 'e', 'l'):
539 case CTAG('+', 'A', 'u', 't'):
543 line[0] = '='; /* handle lines between +Key:/-Key: as =Key: */
544 line[intag + keylen - 1] = ' ';
545 linep = line + intag + keylen;
548 if (*line == '#' || !*line)
550 if (! (line[0] && line[1] && line[2] && line[3] && (line[4] == ':' || line[4] == '.')))
555 endlang = strchr(line + 5, ':');
558 keylen = endlang - line - 1;
559 strncpy(line_lang, line + 5, 5);
560 line_lang[endlang - line - 5] = 0;
565 tag = tag_from_string(line);
569 * start of (next) package or pattern
571 * =Pkg: <name> <version> <release> <architecture>
575 if ((tag == CTAG('=', 'P', 'k', 'g')
576 || tag == CTAG('=', 'P', 'a', 't')))
579 /* If we have an old solvable, complete it by filling in some
582 finish_solvable(&pd, s, handle, freshens);
596 if (split(line + 5, sp, 5) != 4)
598 pool_debug(pool, SAT_FATAL, "susetags: bad line: %d: %s\n", pd.lineno, line);
601 /* Lookup (but don't construct) the name and arch. */
603 name = str2id(pool, join2(pd.kind, ":", sp[0]), 0);
605 name = str2id(pool, sp[0], 0);
606 arch = str2id(pool, sp[3], 0);
607 evr = makeevr(pool, join2(sp[1], "-", sp[2]));
612 /* Now see if we know this solvable already. If we found neither
613 the name nor the arch at all in this repo
614 there's no chance of finding the exact solvable either. */
615 if (name && arch && (indesc >= 2))
618 /* Now look for a solvable with the given name,evr,arch.
619 Our input is structured so, that the second set of =Pkg
620 lines comes in roughly the same order as the first set, so we
621 have a hint at where to start our search, namely were we found
623 for (n = repo->start, nn = n + last_found_pack; n < repo->end; n++, nn++)
627 s = pool->solvables + nn;
628 if (s->repo == repo && s->name == name && s->evr == evr && s->arch == arch)
635 last_found_pack = nn - repo->start;
641 /* And if we still don't have a solvable, create a new one. */
644 s = pool_id2solvable(pool, repo_add_solvable(repo));
645 last_found_pack = (s - pool->solvables) - repo->start;
647 handle = s - pool->solvables;
651 s->name = str2id(pool, join2(pd.kind, ":", sp[0]), 1);
653 s->name = str2id(pool, sp[0], 1);
658 s->arch = str2id(pool, sp[3], 1);
659 s->vendor = vendor; /* default to product vendor */
663 /* If we have no current solvable to add to, ignore all further lines
664 for it. Probably invalid input data in the second set of
666 if (indesc >= 2 && !s)
668 pool_debug(pool, SAT_ERROR, "susetags: huh %d: %s?\n", pd.lineno, line);
673 case CTAG('=', 'P', 'r', 'v'): /* provides */
674 s->provides = adddep(pool, &pd, s->provides, line, 0, pd.kind);
676 case CTAG('=', 'R', 'e', 'q'): /* requires */
677 s->requires = adddep(pool, &pd, s->requires, line, -SOLVABLE_PREREQMARKER, pd.kind);
679 case CTAG('=', 'P', 'r', 'q'): /* pre-requires / packages required */
682 if (flags & SUSETAGS_KINDS_SEPARATELY)
683 repodata_set_poolstr(data, handle, str2id(pool, "solvable:must", 1), line + 6);
685 s->requires = adddep(pool, &pd, s->requires, line, 0, 0); /* patterns: a required package */
688 s->requires = adddep(pool, &pd, s->requires, line, SOLVABLE_PREREQMARKER, 0); /* package: pre-requires */
690 case CTAG('=', 'O', 'b', 's'): /* obsoletes */
691 s->obsoletes = adddep(pool, &pd, s->obsoletes, line, 0, pd.kind);
693 case CTAG('=', 'C', 'o', 'n'): /* conflicts */
694 s->conflicts = adddep(pool, &pd, s->conflicts, line, 0, pd.kind);
696 case CTAG('=', 'R', 'e', 'c'): /* recommends */
697 s->recommends = adddep(pool, &pd, s->recommends, line, 0, pd.kind);
699 case CTAG('=', 'S', 'u', 'p'): /* supplements */
700 s->supplements = adddep(pool, &pd, s->supplements, line, 0, pd.kind);
702 case CTAG('=', 'E', 'n', 'h'): /* enhances */
703 s->enhances = adddep(pool, &pd, s->enhances, line, 0, pd.kind);
705 case CTAG('=', 'S', 'u', 'g'): /* suggests */
706 s->suggests = adddep(pool, &pd, s->suggests, line, 0, pd.kind);
708 case CTAG('=', 'F', 'r', 'e'): /* freshens */
709 freshens = adddep(pool, &pd, freshens, line, 0, pd.kind);
711 case CTAG('=', 'P', 'r', 'c'): /* packages recommended */
712 if (flags & SUSETAGS_KINDS_SEPARATELY)
713 repodata_set_poolstr(data, handle, str2id(pool, "solvable:should", 1), line + 6);
715 s->recommends = adddep(pool, &pd, s->recommends, line, 0, 0);
717 case CTAG('=', 'P', 's', 'g'): /* packages suggested */
718 if (flags & SUSETAGS_KINDS_SEPARATELY)
719 repodata_set_poolstr(data, handle, str2id(pool, "solvable:may", 1), line + 6);
721 s->suggests = adddep(pool, &pd, s->suggests, line, 0, 0);
723 case CTAG('=', 'P', 'c', 'n'): /* pattern: package conflicts */
724 if (flags & SUSETAGS_KINDS_SEPARATELY)
725 fprintf(stderr, "Unsupported: pattern -> package conflicts\n");
727 s->conflicts = adddep(pool, &pd, s->conflicts, line, 0, 0);
729 case CTAG('=', 'P', 'o', 'b'): /* pattern: package obsoletes */
730 if (flags & SUSETAGS_KINDS_SEPARATELY)
731 fprintf(stderr, "Unsupported: pattern -> package obsoletes\n");
733 s->obsoletes = adddep(pool, &pd, s->obsoletes, line, 0, 0);
735 case CTAG('=', 'P', 'f', 'r'): /* pattern: package freshens */
736 if (flags & SUSETAGS_KINDS_SEPARATELY)
737 fprintf(stderr, "Unsupported: pattern -> package freshens\n");
739 freshens = adddep(pool, &pd, freshens, line, 0, 0);
741 case CTAG('=', 'P', 's', 'p'): /* pattern: package supplements */
742 if (flags & SUSETAGS_KINDS_SEPARATELY)
743 fprintf(stderr, "Unsupported: pattern -> package supplements\n");
745 s->supplements = adddep(pool, &pd, s->supplements, line, 0, 0);
747 case CTAG('=', 'P', 'e', 'n'): /* pattern: package enhances */
748 if (flags & SUSETAGS_KINDS_SEPARATELY)
749 fprintf(stderr, "Unsupported: pattern -> package enhances\n");
751 s->enhances = adddep(pool, &pd, s->enhances, line, 0, 0);
753 case CTAG('=', 'V', 'e', 'r'): /* - version - */
758 case CTAG('=', 'V', 'n', 'd'): /* vendor */
759 s->vendor = str2id(pool, line + 6, 1);
762 /* From here it's the attribute tags. */
763 case CTAG('=', 'G', 'r', 'p'):
764 repodata_set_poolstr(data, handle, SOLVABLE_GROUP, line + 6);
766 case CTAG('=', 'L', 'i', 'c'):
767 repodata_set_poolstr(data, handle, SOLVABLE_LICENSE, line + 6);
769 case CTAG('=', 'L', 'o', 'c'):
771 int i = split(line + 6, sp, 3);
772 if (i != 2 && i != 3)
774 pool_debug(pool, SAT_FATAL, "susetags: bad location line: %d: %s\n", pd.lineno, line);
777 repodata_set_location(data, handle, atoi(sp[0]), i == 3 ? sp[2] : id2str(pool, s->arch), sp[1]);
780 case CTAG('=', 'S', 'r', 'c'):
781 add_source(&pd, line + 6, s, handle);
783 case CTAG('=', 'S', 'i', 'z'):
784 if (split(line + 6, sp, 3) == 2)
786 repodata_set_num(data, handle, SOLVABLE_DOWNLOADSIZE, (unsigned int)(atoi(sp[0]) + 1023) / 1024);
787 repodata_set_num(data, handle, SOLVABLE_INSTALLSIZE, (unsigned int)(atoi(sp[1]) + 1023) / 1024);
790 case CTAG('=', 'T', 'i', 'm'):
792 unsigned int t = atoi(line + 6);
794 repodata_set_num(data, handle, SOLVABLE_BUILDTIME, t);
797 case CTAG('=', 'K', 'w', 'd'):
798 repodata_add_poolstr_array(data, handle, SOLVABLE_KEYWORDS, line + 6);
800 case CTAG('=', 'A', 'u', 't'):
801 repodata_set_str(data, handle, SOLVABLE_AUTHORS, line + 6);
803 case CTAG('=', 'S', 'u', 'm'):
804 repodata_set_str(data, handle, langtag(&pd, SOLVABLE_SUMMARY, language ? language : line_lang), line + 3 + keylen );
806 case CTAG('=', 'D', 'e', 's'):
807 repodata_set_str(data, handle, langtag(&pd, SOLVABLE_DESCRIPTION, language ? language : line_lang), line + 3 + keylen );
809 case CTAG('=', 'E', 'u', 'l'):
810 repodata_set_str(data, handle, langtag(&pd, SOLVABLE_EULA, language), line + 6);
812 case CTAG('=', 'I', 'n', 's'):
813 repodata_set_str(data, handle, langtag(&pd, SOLVABLE_MESSAGEINS, language), line + 6);
815 case CTAG('=', 'D', 'e', 'l'):
816 repodata_set_str(data, handle, langtag(&pd, SOLVABLE_MESSAGEDEL, language), line + 6);
818 case CTAG('=', 'V', 'i', 's'):
820 /* Accept numbers and textual bools. */
823 if (k || !strcasecmp(line + 6, "true"))
824 repodata_set_void(data, handle, SOLVABLE_ISVISIBLE );
827 case CTAG('=', 'S', 'h', 'r'):
828 if (last_found_pack >= pd.nshare)
830 pd.share_with = sat_realloc2(pd.share_with, last_found_pack + 256, sizeof(*pd.share_with));
831 memset(pd.share_with + pd.nshare, 0, (last_found_pack + 256 - pd.nshare) * sizeof(*pd.share_with));
832 pd.nshare = last_found_pack + 256;
834 pd.share_with[last_found_pack] = strdup(line + 6);
836 case CTAG('=', 'D', 'i', 'r'):
837 add_dirline(&pd, line + 6);
839 case CTAG('=', 'C', 'a', 't'):
840 repodata_set_poolstr(data, handle, langtag(&pd, SOLVABLE_CATEGORY, line_lang), line + 3 + keylen);
842 case CTAG('=', 'O', 'r', 'd'):
843 /* Order is a string not a number, so we can retroactively insert
844 new patterns in the middle, i.e. 1 < 15 < 2. */
845 repodata_set_str(data, handle, SOLVABLE_ORDER, line + 6);
847 case CTAG('=', 'I', 'c', 'o'):
848 repodata_set_str(data, handle, SOLVABLE_ICON, line + 6);
850 case CTAG('=', 'E', 'x', 't'):
851 repodata_add_poolstr_array(data, handle, SOLVABLE_EXTENDS, join2("pattern", ":", line + 6));
853 case CTAG('=', 'I', 'n', 'c'):
854 repodata_add_poolstr_array(data, handle, SOLVABLE_INCLUDES, join2("pattern", ":", line + 6));
856 case CTAG('=', 'C', 'k', 's'):
857 set_checksum(&pd, data, handle, SOLVABLE_CHECKSUM, line + 6);
859 case CTAG('=', 'L', 'a', 'n'):
860 language = strdup(line + 6);
863 case CTAG('=', 'F', 'l', 's'):
865 char *p = strrchr(line + 6, '/');
867 if (p && p != line + 6 && !p[1])
870 p = strrchr(line + 6, '/');
875 did = repodata_str2dir(data, line + 6, 1);
883 did = repodata_str2dir(data, "/", 1);
884 repodata_add_dirstr(data, handle, SOLVABLE_FILELIST, did, p);
887 case CTAG('=', 'H', 'd', 'r'):
888 /* rpm header range */
889 if (split(line + 6, sp, 3) == 2)
891 /* we ignore the start value */
892 unsigned int end = (unsigned int)atoi(sp[1]);
894 repodata_set_num(data, handle, SOLVABLE_HEADEREND, end);
898 case CTAG('=', 'P', 'a', 't'):
899 case CTAG('=', 'P', 'k', 'g'):
903 pool_debug(pool, SAT_ERROR, "susetags: unknown line: %d: %s\n", pd.lineno, line);
910 finish_solvable(&pd, s, handle, freshens);
913 * (e.g. multiple binaries built from same source)
919 for (i = 0; i < pd.nshare; i++)
920 if (pd.share_with[i])
922 if (split(pd.share_with[i], sp, 5) != 4)
924 pool_debug(pool, SAT_FATAL, "susetags: bad =Shr line: %s\n", pd.share_with[i]);
928 Id name = str2id(pool, sp[0], 1);
929 Id evr = makeevr(pool, join2(sp[1], "-", sp[2]));
930 Id arch = str2id(pool, sp[3], 1);
933 for (n = repo->start, nn = repo->start + last_found;
934 n < repo->end; n++, nn++)
938 found = pool->solvables + nn;
939 if (found->repo == repo
940 && found->name == name
942 && found->arch == arch)
944 last_found = nn - repo->start;
949 repodata_merge_attrs(data, repo->start + i, repo->start + last_found);
950 free(pd.share_with[i]);
955 if (!(flags & REPO_NO_INTERNALIZE))
956 repodata_internalize(data);