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 /* A file dependency. Do not try to parse it */
72 id = str2id(pool, line + 6, 1);
76 i = split(line + 6, sp, 4); /* name, <op>, evr, ? */
77 if (i != 1 && i != 3) /* expect either 'name' or 'name' <op> 'evr' */
79 pool_debug(pool, SAT_FATAL, "susetags: bad dependency line: %d: %s\n", pd->lineno, line);
83 id = str2id(pool, join2(kind, ":", sp[0]), 1);
85 id = str2id(pool, sp[0], 1);
88 evrid = makeevr(pool, sp[2]);
89 for (flags = 0; flags < 6; flags++)
90 if (!strcmp(sp[1], flagtab[flags]))
94 pool_debug(pool, SAT_FATAL, "susetags: unknown relation in %d: '%s'\n", pd->lineno, sp[1]);
97 id = rel2id(pool, id, evrid, flags + 1, 1);
100 return repo_addid_dep(pd->repo, olddeps, id, marker);
110 add_source(struct parsedata *pd, char *line, Solvable *s, Id handle)
112 Repo *repo = s->repo;
113 Pool *pool = repo->pool;
116 if (split(line, sp, 5) != 4)
118 pool_debug(pool, SAT_FATAL, "susetags: bad source line: %d: %s\n", pd->lineno, line);
122 Id name = str2id(pool, sp[0], 1);
123 Id evr = makeevr(pool, join2(sp[1], "-", sp[2]));
124 Id arch = str2id(pool, sp[3], 1);
125 /* XXX: could record a dep here, depends on where we want to store the data */
127 repodata_set_void(pd->data, handle, SOLVABLE_SOURCENAME);
129 repodata_set_id(pd->data, handle, SOLVABLE_SOURCENAME, name);
131 repodata_set_void(pd->data, handle, SOLVABLE_SOURCEEVR);
133 repodata_set_id(pd->data, handle, SOLVABLE_SOURCEEVR, evr);
134 repodata_set_constantid(pd->data, handle, SOLVABLE_SOURCEARCH, arch);
139 * add a line with directory information
144 add_dirline(struct parsedata *pd, char *line)
147 if (split(line, sp, 6) != 5)
149 pd->dirs = sat_extend(pd->dirs, pd->ndirs, 1, sizeof(pd->dirs[0]), 31);
150 long filesz = strtol(sp[1], 0, 0);
151 filesz += strtol(sp[2], 0, 0);
152 long filenum = strtol(sp[3], 0, 0);
153 filenum += strtol(sp[4], 0, 0);
154 /* hack: we know that there's room for a / */
157 unsigned dirid = repodata_str2dir(pd->data, sp[0], 1);
159 fprintf(stderr, "%s -> %d\n", sp[0], dirid);
161 pd->dirs[pd->ndirs][0] = dirid;
162 pd->dirs[pd->ndirs][1] = filesz;
163 pd->dirs[pd->ndirs][2] = filenum;
168 set_checksum(struct parsedata *pd, Repodata *data, Id handle, Id keyname, char *line)
173 if (split(line, sp, 3) != 2)
175 pool_debug(pd->repo->pool, SAT_FATAL, "susetags: bad checksum line: %d: %s\n", pd->lineno, line);
178 if (!strcasecmp(sp[0], "sha1"))
179 l = SIZEOF_SHA1 * 2, type = REPOKEY_TYPE_SHA1;
180 else if (!strcasecmp(sp[0], "sha256"))
181 l = SIZEOF_SHA256 * 2, type = REPOKEY_TYPE_SHA256;
182 else if (!strcasecmp(sp[0], "md5"))
183 l = SIZEOF_MD5 * 2, type = REPOKEY_TYPE_MD5;
186 pool_debug(pd->repo->pool, SAT_FATAL, "susetags: unknown checksum type: %d: %s\n", pd->lineno, sp[0]);
189 if (strlen(sp[1]) != l)
191 pool_debug(pd->repo->pool, SAT_FATAL, "susetags: bad checksum length: %d: for %s: %s\n", pd->lineno, sp[0], sp[1]);
194 repodata_set_checksum(data, handle, keyname, type, sp[1]);
204 id3_cmp(const void *v1, const void *v2, void *dp)
208 return i1[0] - i2[0];
218 commit_diskusage(struct parsedata *pd, Id handle)
221 Dirpool *dp = &pd->data->dirpool;
222 /* Now sort in dirid order. This ensures that parents come before
225 sat_sort(pd->dirs, pd->ndirs, sizeof(pd->dirs[0]), id3_cmp, 0);
226 /* Substract leaf numbers from all parents to make the numbers
227 non-cumulative. This must be done post-order (i.e. all leafs
228 adjusted before parents). We ensure this by starting at the end of
229 the array moving to the start, hence seeing leafs before parents. */
230 for (i = pd->ndirs; i--;)
232 unsigned p = dirpool_parent(dp, pd->dirs[i][0]);
234 for (; p; p = dirpool_parent(dp, p))
237 if (pd->dirs[j][0] == p)
241 if (pd->dirs[j][1] < pd->dirs[i][1])
244 pd->dirs[j][1] -= pd->dirs[i][1];
245 if (pd->dirs[j][2] < pd->dirs[i][2])
248 pd->dirs[j][2] -= pd->dirs[i][2];
251 /* Haven't found this parent in the list, look further if
252 we maybe find the parents parent. */
259 unsigned slen = sizeof(sbuf);
260 for (i = 0; i < pd->ndirs; i++)
262 dir2str(attr, pd->dirs[i][0], &buf, &slen);
263 fprintf(stderr, "have dir %d %d %d %s\n", pd->dirs[i][0], pd->dirs[i][1], pd->dirs[i][2], buf);
268 for (i = 0; i < pd->ndirs; i++)
269 if (pd->dirs[i][1] || pd->dirs[i][2])
271 repodata_add_dirnumnum(pd->data, handle, SOLVABLE_DISKUSAGE, pd->dirs[i][0], pd->dirs[i][1], pd->dirs[i][2]);
277 /* Unfortunately "a"[0] is no constant expression in the C languages,
278 so we need to pass the four characters individually :-/ */
279 #define CTAG(a,b,c,d) ((unsigned)(((unsigned char)a) << 24) \
280 | ((unsigned char)b << 16) \
281 | ((unsigned char)c << 8) \
282 | ((unsigned char)d))
289 static inline unsigned
290 tag_from_string(char *cs)
292 unsigned char *s = (unsigned char *)cs;
293 return ((s[0] << 24) | (s[1] << 16) | (s[2] << 8) | s[3]);
299 * Parse susetags file passed in fp, fill solvables into repo
301 * susetags is key,value based
305 * for long (multi-line) values,
312 * See http://en.opensuse.org/Standards/YaST2_Repository_Metadata
313 * and http://en.opensuse.org/Standards/YaST2_Repository_Metadata/packages
314 * and http://en.opensuse.org/Standards/YaST2_Repository_Metadata/pattern
317 * All keys have 3 characters and end in ':'
321 finish_solvable(struct parsedata *pd, Solvable *s, Id handle, Offset freshens)
323 Pool *pool = pd->repo->pool;
326 /* move file provides to filelist */
327 /* relies on the fact that rpm inserts self-provides at the end */
330 Id *p, *lastreal, did;
331 const char *str, *sp;
332 lastreal = pd->repo->idarraydata + s->provides;
333 for (p = lastreal; *p; p++)
336 for (p = lastreal; *p; p++)
338 str = id2str(pool, *p);
344 for (p = lastreal; *p; p++)
348 str = id2str(pool, *p);
349 sp = strrchr(str, '/');
350 /* Need to copy filename now, before we add string that could
351 realloc the stringspace (and hence invalidate str). */
353 if (strlen(fname) >= 128)
354 fname = strdup(fname);
357 memcpy(fname_buf, fname, strlen(fname) + 1);
362 char *sdup = strdup(str);
364 did = repodata_str2dir(pd->data, sdup, 1);
370 strncpy(sdup, str, sp - str);
372 did = repodata_str2dir(pd->data, sdup, 1);
375 did = repodata_str2dir(pd->data, "/", 1);
376 repodata_add_dirstr(pd->data, handle, SOLVABLE_FILELIST, did, fname);
377 if (fname != fname_buf)
384 /* A self provide, except for source packages. This is harmless
385 to do twice (in case we see the same package twice). */
386 if (s->arch != ARCH_SRC && s->arch != ARCH_NOSRC)
387 s->provides = repo_addid_dep(pd->repo, s->provides,
388 rel2id(pool, s->name, s->evr, REL_EQ, 1), 0);
389 /* XXX This uses repo_addid_dep internally, so should also be
390 harmless to do twice. */
391 s->supplements = repo_fix_supplements(pd->repo, s->provides, s->supplements, freshens);
392 s->conflicts = repo_fix_conflicts(pd->repo, s->conflicts);
394 commit_diskusage(pd, handle);
401 * fp: file to read from
402 * defvendor: default vendor (0 if none)
403 * language: current language (0 if none)
408 repo_add_susetags(Repo *repo, FILE *fp, Id defvendor, const char *language, int flags)
410 Pool *pool = repo->pool;
418 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);
432 memset(&pd, 0, sizeof(pd));
436 pd.repo = pd.common.repo = repo;
438 pd.common.pool = pool;
447 * collect values in 'struct parsedata pd'
448 * then build .solv (and .attr) file
454 char *olinep; /* old line pointer */
457 if (linep - line + 16 > aline) /* (re-)alloc buffer */
459 aline = linep - line;
460 line = realloc(line, aline + 512);
461 linep = line + aline;
464 if (!fgets(linep, aline - (linep - line), fp)) /* read line */
467 linep += strlen(linep);
468 if (linep == line || linep[-1] != '\n')
477 /* check for multi-line value tags (+Key:/-Key:) */
479 int is_end = (linep[-intag - keylen + 1] == '-')
480 && (linep[-1] == ':')
481 && (linep == line + 1 + intag + 1 + 1 + 1 + intag + 1 || linep[-intag - keylen] == '\n');
483 && strncmp(linep - 1 - intag, line + 1, intag))
485 pool_debug(pool, SAT_ERROR, "susetags: Nonmatching multi-line tags: %d: '%s' '%s' %d\n", pd.lineno, linep - 1 - intag, line + 1, intag);
487 if (cummulate && !is_end)
492 if (cummulate && is_end)
494 linep[-intag - keylen + 1] = 0;
495 if (linep[-intag - keylen] == '\n')
496 linep[-intag - keylen] = 0;
500 if (!cummulate && is_end)
506 if (!cummulate && !is_end)
507 linep = line + intag + keylen;
512 if (!intag && line[0] == '+' && line[1] && line[1] != ':') /* start of +Key:/-Key: tag */
514 char *tagend = strchr(line, ':');
517 pool_debug(pool, SAT_FATAL, "susetags: bad line: %d: %s\n", pd.lineno, line);
520 intag = tagend - (line + 1);
522 switch (tag_from_string(line)) /* check if accumulation is needed */
524 case CTAG('+', 'P', 'r', 'q'):
525 case CTAG('+', 'P', 'r', 'c'):
526 case CTAG('+', 'P', 's', 'g'):
527 if (!pd.kind || !(flags & SUSETAGS_KINDS_SEPARATELY))
529 case CTAG('+', 'D', 'e', 's'):
530 case CTAG('+', 'E', 'u', 'l'):
531 case CTAG('+', 'I', 'n', 's'):
532 case CTAG('+', 'D', 'e', 'l'):
533 case CTAG('+', 'A', 'u', 't'):
537 line[0] = '='; /* handle lines between +Key:/-Key: as =Key: */
538 line[intag + keylen - 1] = ' ';
539 linep = line + intag + keylen;
542 if (*line == '#' || !*line)
544 if (! (line[0] && line[1] && line[2] && line[3] && (line[4] == ':' || line[4] == '.')))
549 endlang = strchr(line + 5, ':');
552 keylen = endlang - line - 1;
553 strncpy(line_lang, line + 5, 5);
554 line_lang[endlang - line - 5] = 0;
559 tag = tag_from_string(line);
563 * start of (next) package or pattern
565 * =Pkg: <name> <version> <release> <architecture>
569 if ((tag == CTAG('=', 'P', 'k', 'g')
570 || tag == CTAG('=', 'P', 'a', 't')))
573 /* If we have an old solvable, complete it by filling in some
576 finish_solvable(&pd, s, handle, freshens);
590 if (split(line + 5, sp, 5) != 4)
592 pool_debug(pool, SAT_FATAL, "susetags: bad line: %d: %s\n", pd.lineno, line);
595 /* Lookup (but don't construct) the name and arch. */
597 name = str2id(pool, join2(pd.kind, ":", sp[0]), 0);
599 name = str2id(pool, sp[0], 0);
600 arch = str2id(pool, sp[3], 0);
601 evr = makeevr(pool, join2(sp[1], "-", sp[2]));
606 /* Now see if we know this solvable already. If we found neither
607 the name nor the arch at all in this repo
608 there's no chance of finding the exact solvable either. */
609 if (name && arch && (indesc >= 2))
612 /* Now look for a solvable with the given name,evr,arch.
613 Our input is structured so, that the second set of =Pkg
614 lines comes in roughly the same order as the first set, so we
615 have a hint at where to start our search, namely were we found
617 for (n = repo->start, nn = n + last_found_pack; n < repo->end; n++, nn++)
621 s = pool->solvables + nn;
622 if (s->repo == repo && s->name == name && s->evr == evr && s->arch == arch)
629 last_found_pack = nn - repo->start;
635 /* And if we still don't have a solvable, create a new one. */
638 s = pool_id2solvable(pool, repo_add_solvable(repo));
639 last_found_pack = (s - pool->solvables) - repo->start;
641 handle = s - pool->solvables;
645 s->name = str2id(pool, join2(pd.kind, ":", sp[0]), 1);
647 s->name = str2id(pool, sp[0], 1);
652 s->arch = str2id(pool, sp[3], 1);
653 s->vendor = defvendor;
657 /* If we have no current solvable to add to, ignore all further lines
658 for it. Probably invalid input data in the second set of
660 if (indesc >= 2 && !s)
662 pool_debug(pool, SAT_ERROR, "susetags: huh %d: %s?\n", pd.lineno, line);
667 case CTAG('=', 'P', 'r', 'v'): /* provides */
668 s->provides = adddep(pool, &pd, s->provides, line, 0, pd.kind);
670 case CTAG('=', 'R', 'e', 'q'): /* requires */
671 s->requires = adddep(pool, &pd, s->requires, line, -SOLVABLE_PREREQMARKER, pd.kind);
673 case CTAG('=', 'P', 'r', 'q'): /* pre-requires / packages required */
676 if (flags & SUSETAGS_KINDS_SEPARATELY)
677 repodata_set_poolstr(data, handle, str2id(pool, "solvable:must", 1), line + 6);
679 s->requires = adddep(pool, &pd, s->requires, line, 0, 0); /* patterns: a required package */
682 s->requires = adddep(pool, &pd, s->requires, line, SOLVABLE_PREREQMARKER, 0); /* package: pre-requires */
684 case CTAG('=', 'O', 'b', 's'): /* obsoletes */
685 s->obsoletes = adddep(pool, &pd, s->obsoletes, line, 0, pd.kind);
687 case CTAG('=', 'C', 'o', 'n'): /* conflicts */
688 s->conflicts = adddep(pool, &pd, s->conflicts, line, 0, pd.kind);
690 case CTAG('=', 'R', 'e', 'c'): /* recommends */
691 s->recommends = adddep(pool, &pd, s->recommends, line, 0, pd.kind);
693 case CTAG('=', 'S', 'u', 'p'): /* supplements */
694 s->supplements = adddep(pool, &pd, s->supplements, line, 0, pd.kind);
696 case CTAG('=', 'E', 'n', 'h'): /* enhances */
697 s->enhances = adddep(pool, &pd, s->enhances, line, 0, pd.kind);
699 case CTAG('=', 'S', 'u', 'g'): /* suggests */
700 s->suggests = adddep(pool, &pd, s->suggests, line, 0, pd.kind);
702 case CTAG('=', 'F', 'r', 'e'): /* freshens */
703 freshens = adddep(pool, &pd, freshens, line, 0, pd.kind);
705 case CTAG('=', 'P', 'r', 'c'): /* packages recommended */
706 if (flags & SUSETAGS_KINDS_SEPARATELY)
707 repodata_set_poolstr(data, handle, str2id(pool, "solvable:should", 1), line + 6);
709 s->recommends = adddep(pool, &pd, s->recommends, line, 0, 0);
711 case CTAG('=', 'P', 's', 'g'): /* packages suggested */
712 if (flags & SUSETAGS_KINDS_SEPARATELY)
713 repodata_set_poolstr(data, handle, str2id(pool, "solvable:may", 1), line + 6);
715 s->suggests = adddep(pool, &pd, s->suggests, line, 0, 0);
717 case CTAG('=', 'P', 'c', 'n'): /* pattern: package conflicts */
718 if (flags & SUSETAGS_KINDS_SEPARATELY)
719 fprintf(stderr, "Unsupported: pattern -> package conflicts\n");
721 s->conflicts = adddep(pool, &pd, s->conflicts, line, 0, 0);
723 case CTAG('=', 'P', 'o', 'b'): /* pattern: package obsoletes */
724 if (flags & SUSETAGS_KINDS_SEPARATELY)
725 fprintf(stderr, "Unsupported: pattern -> package obsoletes\n");
727 s->obsoletes = adddep(pool, &pd, s->obsoletes, line, 0, 0);
729 case CTAG('=', 'P', 'f', 'r'): /* pattern: package freshens */
730 if (flags & SUSETAGS_KINDS_SEPARATELY)
731 fprintf(stderr, "Unsupported: pattern -> package freshens\n");
733 freshens = adddep(pool, &pd, freshens, line, 0, 0);
735 case CTAG('=', 'P', 's', 'p'): /* pattern: package supplements */
736 if (flags & SUSETAGS_KINDS_SEPARATELY)
737 fprintf(stderr, "Unsupported: pattern -> package supplements\n");
739 s->supplements = adddep(pool, &pd, s->supplements, line, 0, 0);
741 case CTAG('=', 'P', 'e', 'n'): /* pattern: package enhances */
742 if (flags & SUSETAGS_KINDS_SEPARATELY)
743 fprintf(stderr, "Unsupported: pattern -> package enhances\n");
745 s->enhances = adddep(pool, &pd, s->enhances, line, 0, 0);
747 case CTAG('=', 'V', 'e', 'r'): /* - version - */
752 case CTAG('=', 'V', 'n', 'd'): /* vendor */
753 s->vendor = str2id(pool, line + 6, 1);
756 /* From here it's the attribute tags. */
757 case CTAG('=', 'G', 'r', 'p'):
758 repodata_set_poolstr(data, handle, SOLVABLE_GROUP, line + 6);
760 case CTAG('=', 'L', 'i', 'c'):
761 repodata_set_poolstr(data, handle, SOLVABLE_LICENSE, line + 6);
763 case CTAG('=', 'L', 'o', 'c'):
765 int i = split(line + 6, sp, 3);
766 if (i != 2 && i != 3)
768 pool_debug(pool, SAT_FATAL, "susetags: bad location line: %d: %s\n", pd.lineno, line);
771 repodata_set_location(data, handle, atoi(sp[0]), i == 3 ? sp[2] : id2str(pool, s->arch), sp[1]);
774 case CTAG('=', 'S', 'r', 'c'):
775 add_source(&pd, line + 6, s, handle);
777 case CTAG('=', 'S', 'i', 'z'):
778 if (split(line + 6, sp, 3) == 2)
780 repodata_set_num(data, handle, SOLVABLE_DOWNLOADSIZE, (unsigned int)(atoi(sp[0]) + 1023) / 1024);
781 repodata_set_num(data, handle, SOLVABLE_INSTALLSIZE, (unsigned int)(atoi(sp[1]) + 1023) / 1024);
784 case CTAG('=', 'T', 'i', 'm'):
786 unsigned int t = atoi(line + 6);
788 repodata_set_num(data, handle, SOLVABLE_BUILDTIME, t);
791 case CTAG('=', 'K', 'w', 'd'):
792 repodata_add_poolstr_array(data, handle, SOLVABLE_KEYWORDS, line + 6);
794 case CTAG('=', 'A', 'u', 't'):
795 repodata_set_str(data, handle, SOLVABLE_AUTHORS, line + 6);
797 case CTAG('=', 'S', 'u', 'm'):
798 repodata_set_str(data, handle, langtag(&pd, SOLVABLE_SUMMARY, language ? language : line_lang), line + 3 + keylen );
800 case CTAG('=', 'D', 'e', 's'):
801 repodata_set_str(data, handle, langtag(&pd, SOLVABLE_DESCRIPTION, language ? language : line_lang), line + 3 + keylen );
803 case CTAG('=', 'E', 'u', 'l'):
804 repodata_set_str(data, handle, langtag(&pd, SOLVABLE_EULA, language), line + 6);
806 case CTAG('=', 'I', 'n', 's'):
807 repodata_set_str(data, handle, langtag(&pd, SOLVABLE_MESSAGEINS, language), line + 6);
809 case CTAG('=', 'D', 'e', 'l'):
810 repodata_set_str(data, handle, langtag(&pd, SOLVABLE_MESSAGEDEL, language), line + 6);
812 case CTAG('=', 'V', 'i', 's'):
814 /* Accept numbers and textual bools. */
817 if (k || !strcasecmp(line + 6, "true"))
818 repodata_set_void(data, handle, SOLVABLE_ISVISIBLE );
821 case CTAG('=', 'S', 'h', 'r'):
822 if (last_found_pack >= pd.nshare)
824 pd.share_with = sat_realloc2(pd.share_with, last_found_pack + 256, sizeof(*pd.share_with));
825 memset(pd.share_with + pd.nshare, 0, (last_found_pack + 256 - pd.nshare) * sizeof(*pd.share_with));
826 pd.nshare = last_found_pack + 256;
828 pd.share_with[last_found_pack] = strdup(line + 6);
830 case CTAG('=', 'D', 'i', 'r'):
831 add_dirline(&pd, line + 6);
833 case CTAG('=', 'C', 'a', 't'):
834 repodata_set_poolstr(data, handle, langtag(&pd, SOLVABLE_CATEGORY, line_lang), line + 3 + keylen);
836 case CTAG('=', 'O', 'r', 'd'):
837 /* Order is a string not a number, so we can retroactively insert
838 new patterns in the middle, i.e. 1 < 15 < 2. */
839 repodata_set_str(data, handle, SOLVABLE_ORDER, line + 6);
841 case CTAG('=', 'I', 'c', 'o'):
842 repodata_set_str(data, handle, SOLVABLE_ICON, line + 6);
844 case CTAG('=', 'E', 'x', 't'):
845 repodata_add_poolstr_array(data, handle, SOLVABLE_EXTENDS, join2("pattern", ":", line + 6));
847 case CTAG('=', 'I', 'n', 'c'):
848 repodata_add_poolstr_array(data, handle, SOLVABLE_INCLUDES, join2("pattern", ":", line + 6));
850 case CTAG('=', 'C', 'k', 's'):
851 set_checksum(&pd, data, handle, SOLVABLE_CHECKSUM, line + 6);
853 case CTAG('=', 'L', 'a', 'n'):
854 language = strdup(line + 6);
857 case CTAG('=', 'F', 'l', 's'):
859 char *p = strrchr(line + 6, '/');
861 if (p && p != line + 6 && !p[1])
864 p = strrchr(line + 6, '/');
869 did = repodata_str2dir(data, line + 6, 1);
877 did = repodata_str2dir(data, "/", 1);
878 repodata_add_dirstr(data, handle, SOLVABLE_FILELIST, did, p);
881 case CTAG('=', 'H', 'd', 'r'):
882 /* rpm header range */
883 if (split(line + 6, sp, 3) == 2)
885 /* we ignore the start value */
886 unsigned int end = (unsigned int)atoi(sp[1]);
888 repodata_set_num(data, handle, SOLVABLE_HEADEREND, end);
892 case CTAG('=', 'P', 'a', 't'):
893 case CTAG('=', 'P', 'k', 'g'):
897 pool_debug(pool, SAT_ERROR, "susetags: unknown line: %d: %s\n", pd.lineno, line);
904 finish_solvable(&pd, s, handle, freshens);
907 * (e.g. multiple binaries built from same source)
913 for (i = 0; i < pd.nshare; i++)
914 if (pd.share_with[i])
916 if (split(pd.share_with[i], sp, 5) != 4)
918 pool_debug(pool, SAT_FATAL, "susetags: bad =Shr line: %s\n", pd.share_with[i]);
922 Id name = str2id(pool, sp[0], 1);
923 Id evr = makeevr(pool, join2(sp[1], "-", sp[2]));
924 Id arch = str2id(pool, sp[3], 1);
927 for (n = repo->start, nn = repo->start + last_found;
928 n < repo->end; n++, nn++)
932 found = pool->solvables + nn;
933 if (found->repo == repo
934 && found->name == name
936 && found->arch == arch)
938 last_found = nn - repo->start;
943 repodata_merge_attrs(data, repo->start + i, repo->start + last_found);
944 free(pd.share_with[i]);
949 if (!(flags & REPO_NO_INTERNALIZE))
950 repodata_internalize(data);