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->name && 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 data = repo_add_repodata(repo, flags);
429 memset(&pd, 0, sizeof(pd));
433 pd.repo = pd.common.repo = repo;
435 pd.common.pool = pool;
444 * collect values in 'struct parsedata pd'
445 * then build .solv (and .attr) file
451 char *olinep; /* old line pointer */
454 if (linep - line + 16 > aline) /* (re-)alloc buffer */
456 aline = linep - line;
457 line = realloc(line, aline + 512);
458 linep = line + aline;
461 if (!fgets(linep, aline - (linep - line), fp)) /* read line */
464 linep += strlen(linep);
465 if (linep == line || linep[-1] != '\n')
474 /* check for multi-line value tags (+Key:/-Key:) */
476 int is_end = (linep[-intag - keylen + 1] == '-')
477 && (linep[-1] == ':')
478 && (linep == line + 1 + intag + 1 + 1 + 1 + intag + 1 || linep[-intag - keylen] == '\n');
480 && strncmp(linep - 1 - intag, line + 1, intag))
482 pool_debug(pool, SAT_ERROR, "susetags: Nonmatching multi-line tags: %d: '%s' '%s' %d\n", pd.lineno, linep - 1 - intag, line + 1, intag);
484 if (cummulate && !is_end)
489 if (cummulate && is_end)
491 linep[-intag - keylen + 1] = 0;
492 if (linep[-intag - keylen] == '\n')
493 linep[-intag - keylen] = 0;
497 if (!cummulate && is_end)
503 if (!cummulate && !is_end)
504 linep = line + intag + keylen;
509 if (!intag && line[0] == '+' && line[1] && line[1] != ':') /* start of +Key:/-Key: tag */
511 char *tagend = strchr(line, ':');
514 pool_debug(pool, SAT_FATAL, "susetags: bad line: %d: %s\n", pd.lineno, line);
517 intag = tagend - (line + 1);
519 switch (tag_from_string(line)) /* check if accumulation is needed */
521 case CTAG('+', 'P', 'r', 'q'):
522 case CTAG('+', 'P', 'r', 'c'):
523 case CTAG('+', 'P', 's', 'g'):
524 if (!pd.kind || !(flags & SUSETAGS_KINDS_SEPARATELY))
526 case CTAG('+', 'D', 'e', 's'):
527 case CTAG('+', 'E', 'u', 'l'):
528 case CTAG('+', 'I', 'n', 's'):
529 case CTAG('+', 'D', 'e', 'l'):
530 case CTAG('+', 'A', 'u', 't'):
534 line[0] = '='; /* handle lines between +Key:/-Key: as =Key: */
535 line[intag + keylen - 1] = ' ';
536 linep = line + intag + keylen;
539 if (*line == '#' || !*line)
541 if (! (line[0] && line[1] && line[2] && line[3] && (line[4] == ':' || line[4] == '.')))
546 endlang = strchr(line + 5, ':');
549 keylen = endlang - line - 1;
550 strncpy(line_lang, line + 5, 5);
551 line_lang[endlang - line - 5] = 0;
556 tag = tag_from_string(line);
560 * start of (next) package or pattern
562 * =Pkg: <name> <version> <release> <architecture>
566 if ((tag == CTAG('=', 'P', 'k', 'g')
567 || tag == CTAG('=', 'P', 'a', 't')))
570 /* If we have an old solvable, complete it by filling in some
573 finish_solvable(&pd, s, handle, freshens);
587 if (split(line + 5, sp, 5) != 4)
589 pool_debug(pool, SAT_FATAL, "susetags: bad line: %d: %s\n", pd.lineno, line);
592 /* Lookup (but don't construct) the name and arch. */
594 name = str2id(pool, join2(pd.kind, ":", sp[0]), 0);
596 name = str2id(pool, sp[0], 0);
597 arch = str2id(pool, sp[3], 0);
598 evr = makeevr(pool, join2(sp[1], "-", sp[2]));
603 /* Now see if we know this solvable already. If we found neither
604 the name nor the arch at all in this repo
605 there's no chance of finding the exact solvable either. */
606 if (name && arch && (indesc >= 2))
609 /* Now look for a solvable with the given name,evr,arch.
610 Our input is structured so, that the second set of =Pkg
611 lines comes in roughly the same order as the first set, so we
612 have a hint at where to start our search, namely were we found
614 for (n = repo->start, nn = n + last_found_pack; n < repo->end; n++, nn++)
618 s = pool->solvables + nn;
619 if (s->repo == repo && s->name == name && s->evr == evr && s->arch == arch)
626 last_found_pack = nn - repo->start;
632 /* And if we still don't have a solvable, create a new one. */
635 s = pool_id2solvable(pool, repo_add_solvable(repo));
636 last_found_pack = (s - pool->solvables) - repo->start;
638 handle = s - pool->solvables;
642 s->name = str2id(pool, join2(pd.kind, ":", sp[0]), 1);
644 s->name = str2id(pool, sp[0], 1);
649 s->arch = str2id(pool, sp[3], 1);
650 s->vendor = defvendor;
654 /* If we have no current solvable to add to, ignore all further lines
655 for it. Probably invalid input data in the second set of
657 if (indesc >= 2 && !s)
659 pool_debug(pool, SAT_ERROR, "susetags: huh %d: %s?\n", pd.lineno, line);
664 case CTAG('=', 'P', 'r', 'v'): /* provides */
665 s->provides = adddep(pool, &pd, s->provides, line, 0, pd.kind);
667 case CTAG('=', 'R', 'e', 'q'): /* requires */
668 s->requires = adddep(pool, &pd, s->requires, line, -SOLVABLE_PREREQMARKER, pd.kind);
670 case CTAG('=', 'P', 'r', 'q'): /* pre-requires / packages required */
673 if (flags & SUSETAGS_KINDS_SEPARATELY)
674 repodata_set_poolstr(data, handle, str2id(pool, "solvable:must", 1), line + 6);
676 s->requires = adddep(pool, &pd, s->requires, line, 0, 0); /* patterns: a required package */
679 s->requires = adddep(pool, &pd, s->requires, line, SOLVABLE_PREREQMARKER, 0); /* package: pre-requires */
681 case CTAG('=', 'O', 'b', 's'): /* obsoletes */
682 s->obsoletes = adddep(pool, &pd, s->obsoletes, line, 0, pd.kind);
684 case CTAG('=', 'C', 'o', 'n'): /* conflicts */
685 s->conflicts = adddep(pool, &pd, s->conflicts, line, 0, pd.kind);
687 case CTAG('=', 'R', 'e', 'c'): /* recommends */
688 s->recommends = adddep(pool, &pd, s->recommends, line, 0, pd.kind);
690 case CTAG('=', 'S', 'u', 'p'): /* supplements */
691 s->supplements = adddep(pool, &pd, s->supplements, line, 0, pd.kind);
693 case CTAG('=', 'E', 'n', 'h'): /* enhances */
694 s->enhances = adddep(pool, &pd, s->enhances, line, 0, pd.kind);
696 case CTAG('=', 'S', 'u', 'g'): /* suggests */
697 s->suggests = adddep(pool, &pd, s->suggests, line, 0, pd.kind);
699 case CTAG('=', 'F', 'r', 'e'): /* freshens */
700 freshens = adddep(pool, &pd, freshens, line, 0, pd.kind);
702 case CTAG('=', 'P', 'r', 'c'): /* packages recommended */
703 if (flags & SUSETAGS_KINDS_SEPARATELY)
704 repodata_set_poolstr(data, handle, str2id(pool, "solvable:should", 1), line + 6);
706 s->recommends = adddep(pool, &pd, s->recommends, line, 0, 0);
708 case CTAG('=', 'P', 's', 'g'): /* packages suggested */
709 if (flags & SUSETAGS_KINDS_SEPARATELY)
710 repodata_set_poolstr(data, handle, str2id(pool, "solvable:may", 1), line + 6);
712 s->suggests = adddep(pool, &pd, s->suggests, line, 0, 0);
714 case CTAG('=', 'P', 'c', 'n'): /* pattern: package conflicts */
715 if (flags & SUSETAGS_KINDS_SEPARATELY)
716 fprintf(stderr, "Unsupported: pattern -> package conflicts\n");
718 s->conflicts = adddep(pool, &pd, s->conflicts, line, 0, 0);
720 case CTAG('=', 'P', 'o', 'b'): /* pattern: package obsoletes */
721 if (flags & SUSETAGS_KINDS_SEPARATELY)
722 fprintf(stderr, "Unsupported: pattern -> package obsoletes\n");
724 s->obsoletes = adddep(pool, &pd, s->obsoletes, line, 0, 0);
726 case CTAG('=', 'P', 'f', 'r'): /* pattern: package freshens */
727 if (flags & SUSETAGS_KINDS_SEPARATELY)
728 fprintf(stderr, "Unsupported: pattern -> package freshens\n");
730 freshens = adddep(pool, &pd, freshens, line, 0, 0);
732 case CTAG('=', 'P', 's', 'p'): /* pattern: package supplements */
733 if (flags & SUSETAGS_KINDS_SEPARATELY)
734 fprintf(stderr, "Unsupported: pattern -> package supplements\n");
736 s->supplements = adddep(pool, &pd, s->supplements, line, 0, 0);
738 case CTAG('=', 'P', 'e', 'n'): /* pattern: package enhances */
739 if (flags & SUSETAGS_KINDS_SEPARATELY)
740 fprintf(stderr, "Unsupported: pattern -> package enhances\n");
742 s->enhances = adddep(pool, &pd, s->enhances, line, 0, 0);
744 case CTAG('=', 'V', 'e', 'r'): /* - version - */
749 case CTAG('=', 'V', 'n', 'd'): /* vendor */
750 s->vendor = str2id(pool, line + 6, 1);
753 /* From here it's the attribute tags. */
754 case CTAG('=', 'G', 'r', 'p'):
755 repodata_set_poolstr(data, handle, SOLVABLE_GROUP, line + 6);
757 case CTAG('=', 'L', 'i', 'c'):
758 repodata_set_poolstr(data, handle, SOLVABLE_LICENSE, line + 6);
760 case CTAG('=', 'L', 'o', 'c'):
762 int i = split(line + 6, sp, 3);
763 if (i != 2 && i != 3)
765 pool_debug(pool, SAT_FATAL, "susetags: bad location line: %d: %s\n", pd.lineno, line);
768 repodata_set_location(data, handle, atoi(sp[0]), i == 3 ? sp[2] : id2str(pool, s->arch), sp[1]);
771 case CTAG('=', 'S', 'r', 'c'):
772 add_source(&pd, line + 6, s, handle);
774 case CTAG('=', 'S', 'i', 'z'):
775 if (split(line + 6, sp, 3) == 2)
777 repodata_set_num(data, handle, SOLVABLE_DOWNLOADSIZE, (unsigned int)(atoi(sp[0]) + 1023) / 1024);
778 repodata_set_num(data, handle, SOLVABLE_INSTALLSIZE, (unsigned int)(atoi(sp[1]) + 1023) / 1024);
781 case CTAG('=', 'T', 'i', 'm'):
783 unsigned int t = atoi(line + 6);
785 repodata_set_num(data, handle, SOLVABLE_BUILDTIME, t);
788 case CTAG('=', 'K', 'w', 'd'):
789 repodata_add_poolstr_array(data, handle, SOLVABLE_KEYWORDS, line + 6);
791 case CTAG('=', 'A', 'u', 't'):
792 repodata_set_str(data, handle, SOLVABLE_AUTHORS, line + 6);
794 case CTAG('=', 'S', 'u', 'm'):
795 repodata_set_str(data, handle, langtag(&pd, SOLVABLE_SUMMARY, language ? language : line_lang), line + 3 + keylen );
797 case CTAG('=', 'D', 'e', 's'):
798 repodata_set_str(data, handle, langtag(&pd, SOLVABLE_DESCRIPTION, language ? language : line_lang), line + 3 + keylen );
800 case CTAG('=', 'E', 'u', 'l'):
801 repodata_set_str(data, handle, langtag(&pd, SOLVABLE_EULA, language), line + 6);
803 case CTAG('=', 'I', 'n', 's'):
804 repodata_set_str(data, handle, langtag(&pd, SOLVABLE_MESSAGEINS, language), line + 6);
806 case CTAG('=', 'D', 'e', 'l'):
807 repodata_set_str(data, handle, langtag(&pd, SOLVABLE_MESSAGEDEL, language), line + 6);
809 case CTAG('=', 'V', 'i', 's'):
811 /* Accept numbers and textual bools. */
814 if (k || !strcasecmp(line + 6, "true"))
815 repodata_set_void(data, handle, SOLVABLE_ISVISIBLE );
818 case CTAG('=', 'S', 'h', 'r'):
819 if (last_found_pack >= pd.nshare)
821 pd.share_with = sat_realloc2(pd.share_with, last_found_pack + 256, sizeof(*pd.share_with));
822 memset(pd.share_with + pd.nshare, 0, (last_found_pack + 256 - pd.nshare) * sizeof(*pd.share_with));
823 pd.nshare = last_found_pack + 256;
825 pd.share_with[last_found_pack] = strdup(line + 6);
827 case CTAG('=', 'D', 'i', 'r'):
828 add_dirline(&pd, line + 6);
830 case CTAG('=', 'C', 'a', 't'):
831 repodata_set_poolstr(data, handle, langtag(&pd, SOLVABLE_CATEGORY, line_lang), line + 3 + keylen);
833 case CTAG('=', 'O', 'r', 'd'):
834 /* Order is a string not a number, so we can retroactively insert
835 new patterns in the middle, i.e. 1 < 15 < 2. */
836 repodata_set_str(data, handle, SOLVABLE_ORDER, line + 6);
838 case CTAG('=', 'I', 'c', 'o'):
839 repodata_set_str(data, handle, SOLVABLE_ICON, line + 6);
841 case CTAG('=', 'E', 'x', 't'):
842 repodata_add_poolstr_array(data, handle, SOLVABLE_EXTENDS, join2("pattern", ":", line + 6));
844 case CTAG('=', 'I', 'n', 'c'):
845 repodata_add_poolstr_array(data, handle, SOLVABLE_INCLUDES, join2("pattern", ":", line + 6));
847 case CTAG('=', 'C', 'k', 's'):
848 set_checksum(&pd, data, handle, SOLVABLE_CHECKSUM, line + 6);
850 case CTAG('=', 'L', 'a', 'n'):
851 language = strdup(line + 6);
854 case CTAG('=', 'F', 'l', 's'):
856 char *p = strrchr(line + 6, '/');
858 if (p && p != line + 6 && !p[1])
861 p = strrchr(line + 6, '/');
866 did = repodata_str2dir(data, line + 6, 1);
874 did = repodata_str2dir(data, "/", 1);
875 repodata_add_dirstr(data, handle, SOLVABLE_FILELIST, did, p);
878 case CTAG('=', 'H', 'd', 'r'):
879 /* rpm header range */
880 if (split(line + 6, sp, 3) == 2)
882 /* we ignore the start value */
883 unsigned int end = (unsigned int)atoi(sp[1]);
885 repodata_set_num(data, handle, SOLVABLE_HEADEREND, end);
889 case CTAG('=', 'P', 'a', 't'):
890 case CTAG('=', 'P', 'k', 'g'):
894 pool_debug(pool, SAT_ERROR, "susetags: unknown line: %d: %s\n", pd.lineno, line);
901 finish_solvable(&pd, s, handle, freshens);
904 * (e.g. multiple binaries built from same source)
910 for (i = 0; i < pd.nshare; i++)
911 if (pd.share_with[i])
913 if (split(pd.share_with[i], sp, 5) != 4)
915 pool_debug(pool, SAT_FATAL, "susetags: bad =Shr line: %s\n", pd.share_with[i]);
919 Id name = str2id(pool, sp[0], 1);
920 Id evr = makeevr(pool, join2(sp[1], "-", sp[2]));
921 Id arch = str2id(pool, sp[3], 1);
924 for (n = repo->start, nn = repo->start + last_found;
925 n < repo->end; n++, nn++)
929 found = pool->solvables + nn;
930 if (found->repo == repo
931 && found->name == name
933 && found->arch == arch)
935 last_found = nn - repo->start;
940 repodata_merge_attrs(data, repo->start + i, repo->start + last_found);
941 free(pd.share_with[i]);
946 if (!(flags & REPO_NO_INTERNALIZE))
947 repodata_internalize(data);