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], "md5"))
181 l = SIZEOF_MD5 * 2, type = REPOKEY_TYPE_MD5;
184 pool_debug(pd->repo->pool, SAT_FATAL, "susetags: unknown checksum type: %d: %s\n", pd->lineno, sp[0]);
187 if (strlen(sp[1]) != l)
189 pool_debug(pd->repo->pool, SAT_FATAL, "susetags: bad checksum length: %d: for %s: %s\n", pd->lineno, sp[0], sp[1]);
192 repodata_set_checksum(data, handle, keyname, type, sp[1]);
202 id3_cmp(const void *v1, const void *v2)
206 return i1[0] - i2[0];
216 commit_diskusage(struct parsedata *pd, Id handle)
219 Dirpool *dp = &pd->data->dirpool;
220 /* Now sort in dirid order. This ensures that parents come before
223 qsort(pd->dirs, pd->ndirs, sizeof(pd->dirs[0]), id3_cmp);
224 /* Substract leaf numbers from all parents to make the numbers
225 non-cumulative. This must be done post-order (i.e. all leafs
226 adjusted before parents). We ensure this by starting at the end of
227 the array moving to the start, hence seeing leafs before parents. */
228 for (i = pd->ndirs; i--;)
230 unsigned p = dirpool_parent(dp, pd->dirs[i][0]);
232 for (; p; p = dirpool_parent(dp, p))
235 if (pd->dirs[j][0] == p)
239 if (pd->dirs[j][1] < pd->dirs[i][1])
242 pd->dirs[j][1] -= pd->dirs[i][1];
243 if (pd->dirs[j][2] < pd->dirs[i][2])
246 pd->dirs[j][2] -= pd->dirs[i][2];
249 /* Haven't found this parent in the list, look further if
250 we maybe find the parents parent. */
257 unsigned slen = sizeof(sbuf);
258 for (i = 0; i < pd->ndirs; i++)
260 dir2str(attr, pd->dirs[i][0], &buf, &slen);
261 fprintf(stderr, "have dir %d %d %d %s\n", pd->dirs[i][0], pd->dirs[i][1], pd->dirs[i][2], buf);
266 for (i = 0; i < pd->ndirs; i++)
267 if (pd->dirs[i][1] || pd->dirs[i][2])
269 repodata_add_dirnumnum(pd->data, handle, SOLVABLE_DISKUSAGE, pd->dirs[i][0], pd->dirs[i][1], pd->dirs[i][2]);
275 /* Unfortunately "a"[0] is no constant expression in the C languages,
276 so we need to pass the four characters individually :-/ */
277 #define CTAG(a,b,c,d) ((unsigned)(((unsigned char)a) << 24) \
278 | ((unsigned char)b << 16) \
279 | ((unsigned char)c << 8) \
280 | ((unsigned char)d))
287 static inline unsigned
288 tag_from_string(char *cs)
290 unsigned char *s = (unsigned char *)cs;
291 return ((s[0] << 24) | (s[1] << 16) | (s[2] << 8) | s[3]);
297 * Parse susetags file passed in fp, fill solvables into repo
299 * susetags is key,value based
303 * for long (multi-line) values,
310 * See http://en.opensuse.org/Standards/YaST2_Repository_Metadata
311 * and http://en.opensuse.org/Standards/YaST2_Repository_Metadata/packages
312 * and http://en.opensuse.org/Standards/YaST2_Repository_Metadata/pattern
315 * All keys have 3 characters and end in ':'
319 finish_solvable(struct parsedata *pd, Solvable *s, Id handle, Offset freshens)
321 Pool *pool = pd->repo->pool;
324 /* move file provides to filelist */
325 /* relies on the fact that rpm inserts self-provides at the end */
328 Id *p, *lastreal, did;
329 const char *str, *sp;
330 lastreal = pd->repo->idarraydata + s->provides;
331 for (p = lastreal; *p; p++)
334 for (p = lastreal; *p; p++)
336 str = id2str(pool, *p);
342 for (p = lastreal; *p; p++)
346 str = id2str(pool, *p);
347 sp = strrchr(str, '/');
348 /* Need to copy filename now, before we add string that could
349 realloc the stringspace (and hence invalidate str). */
351 if (strlen(fname) >= 128)
352 fname = strdup(fname);
355 memcpy(fname_buf, fname, strlen(fname) + 1);
360 char *sdup = strdup(str);
362 did = repodata_str2dir(pd->data, sdup, 1);
368 strncpy(sdup, str, sp - str);
370 did = repodata_str2dir(pd->data, sdup, 1);
373 did = repodata_str2dir(pd->data, "/", 1);
374 repodata_add_dirstr(pd->data, handle, SOLVABLE_FILELIST, did, fname);
375 if (fname != fname_buf)
382 /* A self provide, except for source packages. This is harmless
383 to do twice (in case we see the same package twice). */
384 if (s->arch != ARCH_SRC && s->arch != ARCH_NOSRC)
385 s->provides = repo_addid_dep(pd->repo, s->provides,
386 rel2id(pool, s->name, s->evr, REL_EQ, 1), 0);
387 /* XXX This uses repo_addid_dep internally, so should also be
388 harmless to do twice. */
389 s->supplements = repo_fix_supplements(pd->repo, s->provides, s->supplements, freshens);
390 s->conflicts = repo_fix_conflicts(pd->repo, s->conflicts);
392 commit_diskusage(pd, handle);
399 * fp: file to read from
400 * product: solvable representing the product (0 if none)
401 * language: current language (0 if none)
406 repo_add_susetags(Repo *repo, FILE *fp, Id product, const char *language, int flags)
408 Pool *pool = repo->pool;
416 int last_found_pack = 0;
423 if ((flags & SUSETAGS_EXTEND) && repo->nrepodata)
426 if (!(flags & REPO_REUSE_REPODATA))
427 data = repo_add_repodata(repo, 0);
429 data = repo_last_repodata(repo);
433 if (!strncmp(id2str(pool, pool->solvables[product].name), "product:", 8))
434 vendor = pool->solvables[product].vendor;
437 memset(&pd, 0, sizeof(pd));
441 pd.repo = pd.common.repo = repo;
443 pd.common.pool = pool;
452 * collect values in 'struct parsedata pd'
453 * then build .solv (and .attr) file
459 char *olinep; /* old line pointer */
462 if (linep - line + 16 > aline) /* (re-)alloc buffer */
464 aline = linep - line;
465 line = realloc(line, aline + 512);
466 linep = line + aline;
469 if (!fgets(linep, aline - (linep - line), fp)) /* read line */
472 linep += strlen(linep);
473 if (linep == line || linep[-1] != '\n')
482 /* check for multi-line value tags (+Key:/-Key:) */
484 int is_end = (linep[-intag - keylen + 1] == '-')
485 && (linep[-1] == ':')
486 && (linep == line + 1 + intag + 1 + 1 + 1 + intag + 1 || linep[-intag - keylen] == '\n');
488 && strncmp(linep - 1 - intag, line + 1, intag))
490 pool_debug(pool, SAT_ERROR, "susetags: Nonmatching multi-line tags: %d: '%s' '%s' %d\n", pd.lineno, linep - 1 - intag, line + 1, intag);
492 if (cummulate && !is_end)
497 if (cummulate && is_end)
499 linep[-intag - keylen + 1] = 0;
500 if (linep[-intag - keylen] == '\n')
501 linep[-intag - keylen] = 0;
505 if (!cummulate && is_end)
511 if (!cummulate && !is_end)
512 linep = line + intag + keylen;
517 if (!intag && line[0] == '+' && line[1] && line[1] != ':') /* start of +Key:/-Key: tag */
519 char *tagend = strchr(line, ':');
522 pool_debug(pool, SAT_FATAL, "susetags: bad line: %d: %s\n", pd.lineno, line);
525 intag = tagend - (line + 1);
527 switch (tag_from_string(line)) /* check if accumulation is needed */
529 case CTAG('+', 'P', 'r', 'q'):
530 case CTAG('+', 'P', 'r', 'c'):
531 case CTAG('+', 'P', 's', 'g'):
532 if (!pd.kind || !(flags & SUSETAGS_KINDS_SEPARATELY))
534 case CTAG('+', 'D', 'e', 's'):
535 case CTAG('+', 'E', 'u', 'l'):
536 case CTAG('+', 'I', 'n', 's'):
537 case CTAG('+', 'D', 'e', 'l'):
538 case CTAG('+', 'A', 'u', 't'):
542 line[0] = '='; /* handle lines between +Key:/-Key: as =Key: */
543 line[intag + keylen - 1] = ' ';
544 linep = line + intag + keylen;
547 if (*line == '#' || !*line)
549 if (! (line[0] && line[1] && line[2] && line[3] && (line[4] == ':' || line[4] == '.')))
554 endlang = strchr(line + 5, ':');
557 keylen = endlang - line - 1;
558 strncpy(line_lang, line + 5, 5);
559 line_lang[endlang - line - 5] = 0;
564 tag = tag_from_string(line);
568 * start of (next) package or pattern
570 * =Pkg: <name> <version> <release> <architecture>
574 if ((tag == CTAG('=', 'P', 'k', 'g')
575 || tag == CTAG('=', 'P', 'a', 't')))
578 /* If we have an old solvable, complete it by filling in some
581 finish_solvable(&pd, s, handle, freshens);
595 if (split(line + 5, sp, 5) != 4)
597 pool_debug(pool, SAT_FATAL, "susetags: bad line: %d: %s\n", pd.lineno, line);
600 /* Lookup (but don't construct) the name and arch. */
602 name = str2id(pool, join2(pd.kind, ":", sp[0]), 0);
604 name = str2id(pool, sp[0], 0);
605 arch = str2id(pool, sp[3], 0);
606 evr = makeevr(pool, join2(sp[1], "-", sp[2]));
611 /* Now see if we know this solvable already. If we found neither
612 the name nor the arch at all in this repo
613 there's no chance of finding the exact solvable either. */
614 if (name && arch && (indesc >= 2))
617 /* Now look for a solvable with the given name,evr,arch.
618 Our input is structured so, that the second set of =Pkg
619 lines comes in roughly the same order as the first set, so we
620 have a hint at where to start our search, namely were we found
622 for (n = repo->start, nn = n + last_found_pack; n < repo->end; n++, nn++)
626 s = pool->solvables + nn;
627 if (s->repo == repo && s->name == name && s->evr == evr && s->arch == arch)
634 last_found_pack = nn - repo->start;
640 /* And if we still don't have a solvable, create a new one. */
643 s = pool_id2solvable(pool, repo_add_solvable(repo));
644 last_found_pack = (s - pool->solvables) - repo->start;
646 handle = s - pool->solvables;
650 s->name = str2id(pool, join2(pd.kind, ":", sp[0]), 1);
652 s->name = str2id(pool, sp[0], 1);
657 s->arch = str2id(pool, sp[3], 1);
658 s->vendor = vendor; /* default to product vendor */
662 /* If we have no current solvable to add to, ignore all further lines
663 for it. Probably invalid input data in the second set of
665 if (indesc >= 2 && !s)
667 pool_debug(pool, SAT_ERROR, "susetags: huh %d: %s?\n", pd.lineno, line);
672 case CTAG('=', 'P', 'r', 'v'): /* provides */
673 s->provides = adddep(pool, &pd, s->provides, line, 0, pd.kind);
675 case CTAG('=', 'R', 'e', 'q'): /* requires */
676 s->requires = adddep(pool, &pd, s->requires, line, -SOLVABLE_PREREQMARKER, pd.kind);
678 case CTAG('=', 'P', 'r', 'q'): /* pre-requires / packages required */
681 if (flags & SUSETAGS_KINDS_SEPARATELY)
682 repodata_set_poolstr(data, handle, str2id(pool, "solvable:must", 1), line + 6);
684 s->requires = adddep(pool, &pd, s->requires, line, 0, 0); /* patterns: a required package */
687 s->requires = adddep(pool, &pd, s->requires, line, SOLVABLE_PREREQMARKER, 0); /* package: pre-requires */
689 case CTAG('=', 'O', 'b', 's'): /* obsoletes */
690 s->obsoletes = adddep(pool, &pd, s->obsoletes, line, 0, pd.kind);
692 case CTAG('=', 'C', 'o', 'n'): /* conflicts */
693 s->conflicts = adddep(pool, &pd, s->conflicts, line, 0, pd.kind);
695 case CTAG('=', 'R', 'e', 'c'): /* recommends */
696 s->recommends = adddep(pool, &pd, s->recommends, line, 0, pd.kind);
698 case CTAG('=', 'S', 'u', 'p'): /* supplements */
699 s->supplements = adddep(pool, &pd, s->supplements, line, 0, pd.kind);
701 case CTAG('=', 'E', 'n', 'h'): /* enhances */
702 s->enhances = adddep(pool, &pd, s->enhances, line, 0, pd.kind);
704 case CTAG('=', 'S', 'u', 'g'): /* suggests */
705 s->suggests = adddep(pool, &pd, s->suggests, line, 0, pd.kind);
707 case CTAG('=', 'F', 'r', 'e'): /* freshens */
708 freshens = adddep(pool, &pd, freshens, line, 0, pd.kind);
710 case CTAG('=', 'P', 'r', 'c'): /* packages recommended */
711 if (flags & SUSETAGS_KINDS_SEPARATELY)
712 repodata_set_poolstr(data, handle, str2id(pool, "solvable:should", 1), line + 6);
714 s->recommends = adddep(pool, &pd, s->recommends, line, 0, 0);
716 case CTAG('=', 'P', 's', 'g'): /* packages suggested */
717 if (flags & SUSETAGS_KINDS_SEPARATELY)
718 repodata_set_poolstr(data, handle, str2id(pool, "solvable:may", 1), line + 6);
720 s->suggests = adddep(pool, &pd, s->suggests, line, 0, 0);
722 case CTAG('=', 'P', 'c', 'n'): /* pattern: package conflicts */
723 if (flags & SUSETAGS_KINDS_SEPARATELY)
724 fprintf(stderr, "Unsupported: pattern -> package conflicts\n");
726 s->conflicts = adddep(pool, &pd, s->conflicts, line, 0, 0);
728 case CTAG('=', 'P', 'o', 'b'): /* pattern: package obsoletes */
729 if (flags & SUSETAGS_KINDS_SEPARATELY)
730 fprintf(stderr, "Unsupported: pattern -> package obsoletes\n");
732 s->obsoletes = adddep(pool, &pd, s->obsoletes, line, 0, 0);
734 case CTAG('=', 'P', 'f', 'r'): /* pattern: package freshens */
735 if (flags & SUSETAGS_KINDS_SEPARATELY)
736 fprintf(stderr, "Unsupported: pattern -> package freshens\n");
738 freshens = adddep(pool, &pd, freshens, line, 0, 0);
740 case CTAG('=', 'P', 's', 'p'): /* pattern: package supplements */
741 if (flags & SUSETAGS_KINDS_SEPARATELY)
742 fprintf(stderr, "Unsupported: pattern -> package supplements\n");
744 s->supplements = adddep(pool, &pd, s->supplements, line, 0, 0);
746 case CTAG('=', 'P', 'e', 'n'): /* pattern: package enhances */
747 if (flags & SUSETAGS_KINDS_SEPARATELY)
748 fprintf(stderr, "Unsupported: pattern -> package enhances\n");
750 s->enhances = adddep(pool, &pd, s->enhances, line, 0, 0);
752 case CTAG('=', 'V', 'e', 'r'): /* - version - */
757 case CTAG('=', 'V', 'n', 'd'): /* vendor */
758 s->vendor = str2id(pool, line + 6, 1);
761 /* From here it's the attribute tags. */
762 case CTAG('=', 'G', 'r', 'p'):
763 repodata_set_poolstr(data, handle, SOLVABLE_GROUP, line + 6);
765 case CTAG('=', 'L', 'i', 'c'):
766 repodata_set_poolstr(data, handle, SOLVABLE_LICENSE, line + 6);
768 case CTAG('=', 'L', 'o', 'c'):
770 int i = split(line + 6, sp, 3);
771 if (i != 2 && i != 3)
773 pool_debug(pool, SAT_FATAL, "susetags: bad location line: %d: %s\n", pd.lineno, line);
776 repodata_set_location(data, handle, atoi(sp[0]), i == 3 ? sp[2] : id2str(pool, s->arch), sp[1]);
779 case CTAG('=', 'S', 'r', 'c'):
780 add_source(&pd, line + 6, s, handle);
782 case CTAG('=', 'S', 'i', 'z'):
783 if (split(line + 6, sp, 3) == 2)
785 repodata_set_num(data, handle, SOLVABLE_DOWNLOADSIZE, (unsigned int)(atoi(sp[0]) + 1023) / 1024);
786 repodata_set_num(data, handle, SOLVABLE_INSTALLSIZE, (unsigned int)(atoi(sp[1]) + 1023) / 1024);
789 case CTAG('=', 'T', 'i', 'm'):
791 unsigned int t = atoi(line + 6);
793 repodata_set_num(data, handle, SOLVABLE_BUILDTIME, t);
796 case CTAG('=', 'K', 'w', 'd'):
797 repodata_add_poolstr_array(data, handle, SOLVABLE_KEYWORDS, line + 6);
799 case CTAG('=', 'A', 'u', 't'):
800 repodata_set_str(data, handle, SOLVABLE_AUTHORS, line + 6);
802 case CTAG('=', 'S', 'u', 'm'):
803 repodata_set_str(data, handle, langtag(&pd, SOLVABLE_SUMMARY, language ? language : line_lang), line + 3 + keylen );
805 case CTAG('=', 'D', 'e', 's'):
806 repodata_set_str(data, handle, langtag(&pd, SOLVABLE_DESCRIPTION, language ? language : line_lang), line + 3 + keylen );
808 case CTAG('=', 'E', 'u', 'l'):
809 repodata_set_str(data, handle, langtag(&pd, SOLVABLE_EULA, language), line + 6);
811 case CTAG('=', 'I', 'n', 's'):
812 repodata_set_str(data, handle, langtag(&pd, SOLVABLE_MESSAGEINS, language), line + 6);
814 case CTAG('=', 'D', 'e', 'l'):
815 repodata_set_str(data, handle, langtag(&pd, SOLVABLE_MESSAGEDEL, language), line + 6);
817 case CTAG('=', 'V', 'i', 's'):
819 /* Accept numbers and textual bools. */
822 if (k || !strcasecmp(line + 6, "true"))
823 repodata_set_void(data, handle, SOLVABLE_ISVISIBLE );
826 case CTAG('=', 'S', 'h', 'r'):
827 if (last_found_pack >= pd.nshare)
829 pd.share_with = sat_realloc2(pd.share_with, last_found_pack + 256, sizeof(*pd.share_with));
830 memset(pd.share_with + pd.nshare, 0, (last_found_pack + 256 - pd.nshare) * sizeof(*pd.share_with));
831 pd.nshare = last_found_pack + 256;
833 pd.share_with[last_found_pack] = strdup(line + 6);
835 case CTAG('=', 'D', 'i', 'r'):
836 add_dirline(&pd, line + 6);
838 case CTAG('=', 'C', 'a', 't'):
839 repodata_set_poolstr(data, handle, langtag(&pd, SOLVABLE_CATEGORY, line_lang), line + 3 + keylen);
841 case CTAG('=', 'O', 'r', 'd'):
842 /* Order is a string not a number, so we can retroactively insert
843 new patterns in the middle, i.e. 1 < 15 < 2. */
844 repodata_set_str(data, handle, SOLVABLE_ORDER, line + 6);
846 case CTAG('=', 'I', 'c', 'o'):
847 repodata_set_str(data, handle, SOLVABLE_ICON, line + 6);
849 case CTAG('=', 'E', 'x', 't'):
850 repodata_add_poolstr_array(data, handle, SOLVABLE_EXTENDS, join2("pattern", ":", line + 6));
852 case CTAG('=', 'I', 'n', 'c'):
853 repodata_add_poolstr_array(data, handle, SOLVABLE_INCLUDES, join2("pattern", ":", line + 6));
855 case CTAG('=', 'C', 'k', 's'):
856 set_checksum(&pd, data, handle, SOLVABLE_CHECKSUM, line + 6);
858 case CTAG('=', 'L', 'a', 'n'):
859 language = strdup(line + 6);
862 case CTAG('=', 'F', 'l', 's'):
864 char *p = strrchr(line + 6, '/');
866 if (p && p != line + 6 && !p[1])
869 p = strrchr(line + 6, '/');
874 did = repodata_str2dir(data, line + 6, 1);
882 did = repodata_str2dir(data, "/", 1);
883 repodata_add_dirstr(data, handle, SOLVABLE_FILELIST, did, p);
886 case CTAG('=', 'H', 'd', 'r'):
887 /* rpm header range */
888 if (split(line + 6, sp, 3) == 2)
890 /* we ignore the start value */
891 unsigned int end = (unsigned int)atoi(sp[1]);
893 repodata_set_num(data, handle, SOLVABLE_HEADEREND, end);
897 case CTAG('=', 'P', 'a', 't'):
898 case CTAG('=', 'P', 'k', 'g'):
902 pool_debug(pool, SAT_ERROR, "susetags: unknown line: %d: %s\n", pd.lineno, line);
909 finish_solvable(&pd, s, handle, freshens);
912 * (e.g. multiple binaries built from same source)
918 for (i = 0; i < pd.nshare; i++)
919 if (pd.share_with[i])
921 if (split(pd.share_with[i], sp, 5) != 4)
923 pool_debug(pool, SAT_FATAL, "susetags: bad =Shr line: %s\n", pd.share_with[i]);
927 Id name = str2id(pool, sp[0], 1);
928 Id evr = makeevr(pool, join2(sp[1], "-", sp[2]));
929 Id arch = str2id(pool, sp[3], 1);
932 for (n = repo->start, nn = repo->start + last_found;
933 n < repo->end; n++, nn++)
937 found = pool->solvables + nn;
938 if (found->repo == repo
939 && found->name == name
941 && found->arch == arch)
943 last_found = nn - repo->start;
948 repodata_merge_attrs(data, repo->start + i, repo->start + last_found);
949 free(pd.share_with[i]);
954 if (!(flags & REPO_NO_INTERNALIZE))
955 repodata_internalize(data);