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 * product: solvable representing the product (0 if none)
403 * language: current language (0 if none)
408 repo_add_susetags(Repo *repo, FILE *fp, Id product, const char *language, int flags)
410 Pool *pool = repo->pool;
418 int last_found_pack = 0;
425 if ((flags & SUSETAGS_EXTEND) && repo->nrepodata)
428 if (!(flags & REPO_REUSE_REPODATA))
429 data = repo_add_repodata(repo, 0);
431 data = repo_last_repodata(repo);
435 if (!strncmp(id2str(pool, pool->solvables[product].name), "product:", 8))
436 vendor = pool->solvables[product].vendor;
439 memset(&pd, 0, sizeof(pd));
443 pd.repo = pd.common.repo = repo;
445 pd.common.pool = pool;
454 * collect values in 'struct parsedata pd'
455 * then build .solv (and .attr) file
461 char *olinep; /* old line pointer */
464 if (linep - line + 16 > aline) /* (re-)alloc buffer */
466 aline = linep - line;
467 line = realloc(line, aline + 512);
468 linep = line + aline;
471 if (!fgets(linep, aline - (linep - line), fp)) /* read line */
474 linep += strlen(linep);
475 if (linep == line || linep[-1] != '\n')
484 /* check for multi-line value tags (+Key:/-Key:) */
486 int is_end = (linep[-intag - keylen + 1] == '-')
487 && (linep[-1] == ':')
488 && (linep == line + 1 + intag + 1 + 1 + 1 + intag + 1 || linep[-intag - keylen] == '\n');
490 && strncmp(linep - 1 - intag, line + 1, intag))
492 pool_debug(pool, SAT_ERROR, "susetags: Nonmatching multi-line tags: %d: '%s' '%s' %d\n", pd.lineno, linep - 1 - intag, line + 1, intag);
494 if (cummulate && !is_end)
499 if (cummulate && is_end)
501 linep[-intag - keylen + 1] = 0;
502 if (linep[-intag - keylen] == '\n')
503 linep[-intag - keylen] = 0;
507 if (!cummulate && is_end)
513 if (!cummulate && !is_end)
514 linep = line + intag + keylen;
519 if (!intag && line[0] == '+' && line[1] && line[1] != ':') /* start of +Key:/-Key: tag */
521 char *tagend = strchr(line, ':');
524 pool_debug(pool, SAT_FATAL, "susetags: bad line: %d: %s\n", pd.lineno, line);
527 intag = tagend - (line + 1);
529 switch (tag_from_string(line)) /* check if accumulation is needed */
531 case CTAG('+', 'P', 'r', 'q'):
532 case CTAG('+', 'P', 'r', 'c'):
533 case CTAG('+', 'P', 's', 'g'):
534 if (!pd.kind || !(flags & SUSETAGS_KINDS_SEPARATELY))
536 case CTAG('+', 'D', 'e', 's'):
537 case CTAG('+', 'E', 'u', 'l'):
538 case CTAG('+', 'I', 'n', 's'):
539 case CTAG('+', 'D', 'e', 'l'):
540 case CTAG('+', 'A', 'u', 't'):
544 line[0] = '='; /* handle lines between +Key:/-Key: as =Key: */
545 line[intag + keylen - 1] = ' ';
546 linep = line + intag + keylen;
549 if (*line == '#' || !*line)
551 if (! (line[0] && line[1] && line[2] && line[3] && (line[4] == ':' || line[4] == '.')))
556 endlang = strchr(line + 5, ':');
559 keylen = endlang - line - 1;
560 strncpy(line_lang, line + 5, 5);
561 line_lang[endlang - line - 5] = 0;
566 tag = tag_from_string(line);
570 * start of (next) package or pattern
572 * =Pkg: <name> <version> <release> <architecture>
576 if ((tag == CTAG('=', 'P', 'k', 'g')
577 || tag == CTAG('=', 'P', 'a', 't')))
580 /* If we have an old solvable, complete it by filling in some
583 finish_solvable(&pd, s, handle, freshens);
597 if (split(line + 5, sp, 5) != 4)
599 pool_debug(pool, SAT_FATAL, "susetags: bad line: %d: %s\n", pd.lineno, line);
602 /* Lookup (but don't construct) the name and arch. */
604 name = str2id(pool, join2(pd.kind, ":", sp[0]), 0);
606 name = str2id(pool, sp[0], 0);
607 arch = str2id(pool, sp[3], 0);
608 evr = makeevr(pool, join2(sp[1], "-", sp[2]));
613 /* Now see if we know this solvable already. If we found neither
614 the name nor the arch at all in this repo
615 there's no chance of finding the exact solvable either. */
616 if (name && arch && (indesc >= 2))
619 /* Now look for a solvable with the given name,evr,arch.
620 Our input is structured so, that the second set of =Pkg
621 lines comes in roughly the same order as the first set, so we
622 have a hint at where to start our search, namely were we found
624 for (n = repo->start, nn = n + last_found_pack; n < repo->end; n++, nn++)
628 s = pool->solvables + nn;
629 if (s->repo == repo && s->name == name && s->evr == evr && s->arch == arch)
636 last_found_pack = nn - repo->start;
642 /* And if we still don't have a solvable, create a new one. */
645 s = pool_id2solvable(pool, repo_add_solvable(repo));
646 last_found_pack = (s - pool->solvables) - repo->start;
648 handle = s - pool->solvables;
652 s->name = str2id(pool, join2(pd.kind, ":", sp[0]), 1);
654 s->name = str2id(pool, sp[0], 1);
659 s->arch = str2id(pool, sp[3], 1);
660 s->vendor = vendor; /* default to product vendor */
664 /* If we have no current solvable to add to, ignore all further lines
665 for it. Probably invalid input data in the second set of
667 if (indesc >= 2 && !s)
669 pool_debug(pool, SAT_ERROR, "susetags: huh %d: %s?\n", pd.lineno, line);
674 case CTAG('=', 'P', 'r', 'v'): /* provides */
675 s->provides = adddep(pool, &pd, s->provides, line, 0, pd.kind);
677 case CTAG('=', 'R', 'e', 'q'): /* requires */
678 s->requires = adddep(pool, &pd, s->requires, line, -SOLVABLE_PREREQMARKER, pd.kind);
680 case CTAG('=', 'P', 'r', 'q'): /* pre-requires / packages required */
683 if (flags & SUSETAGS_KINDS_SEPARATELY)
684 repodata_set_poolstr(data, handle, str2id(pool, "solvable:must", 1), line + 6);
686 s->requires = adddep(pool, &pd, s->requires, line, 0, 0); /* patterns: a required package */
689 s->requires = adddep(pool, &pd, s->requires, line, SOLVABLE_PREREQMARKER, 0); /* package: pre-requires */
691 case CTAG('=', 'O', 'b', 's'): /* obsoletes */
692 s->obsoletes = adddep(pool, &pd, s->obsoletes, line, 0, pd.kind);
694 case CTAG('=', 'C', 'o', 'n'): /* conflicts */
695 s->conflicts = adddep(pool, &pd, s->conflicts, line, 0, pd.kind);
697 case CTAG('=', 'R', 'e', 'c'): /* recommends */
698 s->recommends = adddep(pool, &pd, s->recommends, line, 0, pd.kind);
700 case CTAG('=', 'S', 'u', 'p'): /* supplements */
701 s->supplements = adddep(pool, &pd, s->supplements, line, 0, pd.kind);
703 case CTAG('=', 'E', 'n', 'h'): /* enhances */
704 s->enhances = adddep(pool, &pd, s->enhances, line, 0, pd.kind);
706 case CTAG('=', 'S', 'u', 'g'): /* suggests */
707 s->suggests = adddep(pool, &pd, s->suggests, line, 0, pd.kind);
709 case CTAG('=', 'F', 'r', 'e'): /* freshens */
710 freshens = adddep(pool, &pd, freshens, line, 0, pd.kind);
712 case CTAG('=', 'P', 'r', 'c'): /* packages recommended */
713 if (flags & SUSETAGS_KINDS_SEPARATELY)
714 repodata_set_poolstr(data, handle, str2id(pool, "solvable:should", 1), line + 6);
716 s->recommends = adddep(pool, &pd, s->recommends, line, 0, 0);
718 case CTAG('=', 'P', 's', 'g'): /* packages suggested */
719 if (flags & SUSETAGS_KINDS_SEPARATELY)
720 repodata_set_poolstr(data, handle, str2id(pool, "solvable:may", 1), line + 6);
722 s->suggests = adddep(pool, &pd, s->suggests, line, 0, 0);
724 case CTAG('=', 'P', 'c', 'n'): /* pattern: package conflicts */
725 if (flags & SUSETAGS_KINDS_SEPARATELY)
726 fprintf(stderr, "Unsupported: pattern -> package conflicts\n");
728 s->conflicts = adddep(pool, &pd, s->conflicts, line, 0, 0);
730 case CTAG('=', 'P', 'o', 'b'): /* pattern: package obsoletes */
731 if (flags & SUSETAGS_KINDS_SEPARATELY)
732 fprintf(stderr, "Unsupported: pattern -> package obsoletes\n");
734 s->obsoletes = adddep(pool, &pd, s->obsoletes, line, 0, 0);
736 case CTAG('=', 'P', 'f', 'r'): /* pattern: package freshens */
737 if (flags & SUSETAGS_KINDS_SEPARATELY)
738 fprintf(stderr, "Unsupported: pattern -> package freshens\n");
740 freshens = adddep(pool, &pd, freshens, line, 0, 0);
742 case CTAG('=', 'P', 's', 'p'): /* pattern: package supplements */
743 if (flags & SUSETAGS_KINDS_SEPARATELY)
744 fprintf(stderr, "Unsupported: pattern -> package supplements\n");
746 s->supplements = adddep(pool, &pd, s->supplements, line, 0, 0);
748 case CTAG('=', 'P', 'e', 'n'): /* pattern: package enhances */
749 if (flags & SUSETAGS_KINDS_SEPARATELY)
750 fprintf(stderr, "Unsupported: pattern -> package enhances\n");
752 s->enhances = adddep(pool, &pd, s->enhances, line, 0, 0);
754 case CTAG('=', 'V', 'e', 'r'): /* - version - */
759 case CTAG('=', 'V', 'n', 'd'): /* vendor */
760 s->vendor = str2id(pool, line + 6, 1);
763 /* From here it's the attribute tags. */
764 case CTAG('=', 'G', 'r', 'p'):
765 repodata_set_poolstr(data, handle, SOLVABLE_GROUP, line + 6);
767 case CTAG('=', 'L', 'i', 'c'):
768 repodata_set_poolstr(data, handle, SOLVABLE_LICENSE, line + 6);
770 case CTAG('=', 'L', 'o', 'c'):
772 int i = split(line + 6, sp, 3);
773 if (i != 2 && i != 3)
775 pool_debug(pool, SAT_FATAL, "susetags: bad location line: %d: %s\n", pd.lineno, line);
778 repodata_set_location(data, handle, atoi(sp[0]), i == 3 ? sp[2] : id2str(pool, s->arch), sp[1]);
781 case CTAG('=', 'S', 'r', 'c'):
782 add_source(&pd, line + 6, s, handle);
784 case CTAG('=', 'S', 'i', 'z'):
785 if (split(line + 6, sp, 3) == 2)
787 repodata_set_num(data, handle, SOLVABLE_DOWNLOADSIZE, (unsigned int)(atoi(sp[0]) + 1023) / 1024);
788 repodata_set_num(data, handle, SOLVABLE_INSTALLSIZE, (unsigned int)(atoi(sp[1]) + 1023) / 1024);
791 case CTAG('=', 'T', 'i', 'm'):
793 unsigned int t = atoi(line + 6);
795 repodata_set_num(data, handle, SOLVABLE_BUILDTIME, t);
798 case CTAG('=', 'K', 'w', 'd'):
799 repodata_add_poolstr_array(data, handle, SOLVABLE_KEYWORDS, line + 6);
801 case CTAG('=', 'A', 'u', 't'):
802 repodata_set_str(data, handle, SOLVABLE_AUTHORS, line + 6);
804 case CTAG('=', 'S', 'u', 'm'):
805 repodata_set_str(data, handle, langtag(&pd, SOLVABLE_SUMMARY, language ? language : line_lang), line + 3 + keylen );
807 case CTAG('=', 'D', 'e', 's'):
808 repodata_set_str(data, handle, langtag(&pd, SOLVABLE_DESCRIPTION, language ? language : line_lang), line + 3 + keylen );
810 case CTAG('=', 'E', 'u', 'l'):
811 repodata_set_str(data, handle, langtag(&pd, SOLVABLE_EULA, language), line + 6);
813 case CTAG('=', 'I', 'n', 's'):
814 repodata_set_str(data, handle, langtag(&pd, SOLVABLE_MESSAGEINS, language), line + 6);
816 case CTAG('=', 'D', 'e', 'l'):
817 repodata_set_str(data, handle, langtag(&pd, SOLVABLE_MESSAGEDEL, language), line + 6);
819 case CTAG('=', 'V', 'i', 's'):
821 /* Accept numbers and textual bools. */
824 if (k || !strcasecmp(line + 6, "true"))
825 repodata_set_void(data, handle, SOLVABLE_ISVISIBLE );
828 case CTAG('=', 'S', 'h', 'r'):
829 if (last_found_pack >= pd.nshare)
831 pd.share_with = sat_realloc2(pd.share_with, last_found_pack + 256, sizeof(*pd.share_with));
832 memset(pd.share_with + pd.nshare, 0, (last_found_pack + 256 - pd.nshare) * sizeof(*pd.share_with));
833 pd.nshare = last_found_pack + 256;
835 pd.share_with[last_found_pack] = strdup(line + 6);
837 case CTAG('=', 'D', 'i', 'r'):
838 add_dirline(&pd, line + 6);
840 case CTAG('=', 'C', 'a', 't'):
841 repodata_set_poolstr(data, handle, langtag(&pd, SOLVABLE_CATEGORY, line_lang), line + 3 + keylen);
843 case CTAG('=', 'O', 'r', 'd'):
844 /* Order is a string not a number, so we can retroactively insert
845 new patterns in the middle, i.e. 1 < 15 < 2. */
846 repodata_set_str(data, handle, SOLVABLE_ORDER, line + 6);
848 case CTAG('=', 'I', 'c', 'o'):
849 repodata_set_str(data, handle, SOLVABLE_ICON, line + 6);
851 case CTAG('=', 'E', 'x', 't'):
852 repodata_add_poolstr_array(data, handle, SOLVABLE_EXTENDS, join2("pattern", ":", line + 6));
854 case CTAG('=', 'I', 'n', 'c'):
855 repodata_add_poolstr_array(data, handle, SOLVABLE_INCLUDES, join2("pattern", ":", line + 6));
857 case CTAG('=', 'C', 'k', 's'):
858 set_checksum(&pd, data, handle, SOLVABLE_CHECKSUM, line + 6);
860 case CTAG('=', 'L', 'a', 'n'):
861 language = strdup(line + 6);
864 case CTAG('=', 'F', 'l', 's'):
866 char *p = strrchr(line + 6, '/');
868 if (p && p != line + 6 && !p[1])
871 p = strrchr(line + 6, '/');
876 did = repodata_str2dir(data, line + 6, 1);
884 did = repodata_str2dir(data, "/", 1);
885 repodata_add_dirstr(data, handle, SOLVABLE_FILELIST, did, p);
888 case CTAG('=', 'H', 'd', 'r'):
889 /* rpm header range */
890 if (split(line + 6, sp, 3) == 2)
892 /* we ignore the start value */
893 unsigned int end = (unsigned int)atoi(sp[1]);
895 repodata_set_num(data, handle, SOLVABLE_HEADEREND, end);
899 case CTAG('=', 'P', 'a', 't'):
900 case CTAG('=', 'P', 'k', 'g'):
904 pool_debug(pool, SAT_ERROR, "susetags: unknown line: %d: %s\n", pd.lineno, line);
911 finish_solvable(&pd, s, handle, freshens);
914 * (e.g. multiple binaries built from same source)
920 for (i = 0; i < pd.nshare; i++)
921 if (pd.share_with[i])
923 if (split(pd.share_with[i], sp, 5) != 4)
925 pool_debug(pool, SAT_FATAL, "susetags: bad =Shr line: %s\n", pd.share_with[i]);
929 Id name = str2id(pool, sp[0], 1);
930 Id evr = makeevr(pool, join2(sp[1], "-", sp[2]));
931 Id arch = str2id(pool, sp[3], 1);
934 for (n = repo->start, nn = repo->start + last_found;
935 n < repo->end; n++, nn++)
939 found = pool->solvables + nn;
940 if (found->repo == repo
941 && found->name == name
943 && found->arch == arch)
945 last_found = nn - repo->start;
950 repodata_merge_attrs(data, repo->start + i, repo->start + last_found);
951 free(pd.share_with[i]);
956 if (!(flags & REPO_NO_INTERNALIZE))
957 repodata_internalize(data);