Support for generating separate sub files and bugfixes in the reader
[platform/upstream/libsolv.git] / tools / repo_susetags.c
1 /*
2  * Copyright (c) 2007, Novell Inc.
3  *
4  * This program is licensed under the BSD license, read LICENSE.BSD
5  * for further information
6  */
7
8 #include <sys/types.h>
9 #include <limits.h>
10 #include <fcntl.h>
11 #include <stdio.h>
12 #include <stdlib.h>
13 #include <string.h>
14
15 #include "pool.h"
16 #include "repo.h"
17 #if 0
18 #include "attr_store.h"
19 #endif
20 #include "tools_util.h"
21 #include "repo_susetags.h"
22
23 struct parsedata {
24   solvable_kind kind;
25   Repo *repo;
26   Repodata *data;
27   struct parsedata_common common;
28   char **sources;
29   int nsources;
30   int last_found_source;
31   char **share_with;
32   int nshare;
33   Id (*dirs)[3]; // dirid, size, nfiles
34   int ndirs;
35 };
36
37 static char *flagtab[] = {
38   ">",
39   "=",
40   ">=",
41   "<",
42   "!=",
43   "<="
44 };
45
46
47 /*
48  * adddep
49  * create and add dependency
50  */
51
52 static unsigned int
53 adddep(Pool *pool, struct parsedata *pd, unsigned int olddeps, char *line, Id marker, solvable_kind kind)
54 {
55   int i, flags;
56   Id id, evrid;
57   char *sp[4];
58
59   i = split(line + 5, sp, 4); /* name, ?, evr, ? */
60   if (i != 1 && i != 3) /* expect either 'name' or 'name' '-' 'evr' */
61     {
62       fprintf(stderr, "Bad dependency line: %s\n", line);
63       exit(1);
64     }
65   if (kind)
66     id = str2id(pool, join2(kind_prefix(kind), sp[0], 0), 1);
67   else
68     id = str2id(pool, sp[0], 1);
69   if (i == 3)
70     {
71       evrid = makeevr(pool, sp[2]);
72       for (flags = 0; flags < 6; flags++)
73         if (!strcmp(sp[1], flagtab[flags]))
74           break;
75       if (flags == 6)
76         {
77           fprintf(stderr, "Unknown relation '%s'\n", sp[1]);
78           exit(1);
79         }
80       id = rel2id(pool, id, evrid, flags + 1, 1);
81     }
82   return repo_addid_dep(pd->repo, olddeps, id, marker);
83 }
84
85 #if 0
86 Attrstore *attr;
87 #endif
88
89 /*
90  * add_location
91  * 
92  */
93
94 static void
95 add_location(struct parsedata *pd, char *line, Solvable *s, unsigned entry)
96 {
97   Pool *pool = s->repo->pool;
98   char *sp[3];
99   int i;
100
101   i = split(line, sp, 3);
102   if (i != 2 && i != 3)
103     {
104       fprintf(stderr, "Bad location line: %s\n", line);
105       exit(1);
106     }
107   /* If we have a dirname, let's see if it's the same as arch.  In that
108      case don't store it.  */
109   if (i == 3 && !strcmp (sp[2], id2str (pool, s->arch)))
110     sp[2] = 0, i = 2;
111   if (i == 3 && sp[2])
112     {
113       /* medianr filename dir
114          don't optimize this one */
115 #if 0
116       add_attr_special_int (attr, entry, id_medianr, atoi (sp[0]));
117       add_attr_localids_id (attr, entry, id_mediadir, str2localid (attr, sp[2], 1));
118       add_attr_string (attr, entry, id_mediafile, sp[1]);
119 #else
120       repodata_set_constant(pd->data, entry, id_medianr, atoi(sp[0]));
121       repodata_set_poolstr(pd->data, entry, id_mediadir, sp[2]);
122       repodata_set_str(pd->data, entry, id_mediafile, sp[1]);
123 #endif
124       return;
125     }
126   else
127     {
128       /* Let's see if we can optimize this a bit.  If the media file name
129          can be formed by the base rpm information we don't store it, but
130          only a flag that we've seen it.  */
131       unsigned int medianr = atoi (sp[0]);
132       const char *n1 = sp[1];
133       const char *n2 = id2str (pool, s->name);
134       for (n2 = id2str (pool, s->name); *n2; n1++, n2++)
135         if (*n1 != *n2)
136           break;
137       if (*n2 || *n1 != '-')
138         goto nontrivial;
139
140       n1++;
141       for (n2 = id2str (pool, s->evr); *n2; n1++, n2++)
142         if (*n1 != *n2)
143           break;
144       if (*n2 || *n1 != '.')
145         goto nontrivial;
146       n1++;
147       for (n2 = id2str (pool, s->arch); *n2; n1++, n2++)
148         if (*n1 != *n2)
149           break;
150       if (*n2 || strcmp (n1, ".rpm"))
151         goto nontrivial;
152 #if 0
153       add_attr_special_int (attr, entry, id_medianr, medianr);
154       add_attr_void (attr, entry, id_mediafile);
155 #else
156       repodata_set_constant(pd->data, entry, id_medianr, medianr);
157       repodata_set_void(pd->data, entry, id_mediafile);
158 #endif
159       return;
160
161 nontrivial:
162 #if 0
163       add_attr_special_int (attr, entry, id_medianr, medianr);
164       add_attr_string (attr, entry, id_mediafile, sp[1]);
165 #else
166       repodata_set_constant(pd->data, entry, id_medianr, medianr);
167       repodata_set_str(pd->data, entry, id_mediafile, sp[1]);
168 #endif
169       return;
170     }
171 }
172
173 #if 0
174
175 /*
176  * add_source
177  * 
178  */
179
180 static void
181 add_source(struct parsedata *pd, char *line, Solvable *s, unsigned entry, int first)
182 {
183   Repo *repo = s->repo;
184   Pool *pool = repo->pool;
185   char *sp[5];
186
187   if (split(line, sp, 5) != 4)
188     {
189       fprintf(stderr, "Bad source line: %s\n", line);
190       exit(1);
191     }
192
193   Id name = str2id(pool, sp[0], 1);
194   Id evr = makeevr(pool, join(pd, sp[1], "-", sp[2]));
195   Id arch = str2id(pool, sp[3], 1);
196
197   /* Now, if the source of a package only differs in architecture
198      (src or nosrc), code only that fact.  */
199   if (s->name == name && s->evr == evr
200       && (arch == ARCH_SRC || arch == ARCH_NOSRC))
201     {
202       add_attr_void (attr, entry, arch == ARCH_SRC ? id_source : id_nosource);
203     }
204   else if (first)
205     {
206       if (entry >= pd->nsources)
207         {
208           if (pd->nsources)
209             {
210               pd->sources = realloc (pd->sources, (entry + 256) * sizeof (*pd->sources));
211               memset (pd->sources + pd->nsources, 0, (entry + 256 - pd->nsources) * sizeof (*pd->sources));
212             }
213           else
214             pd->sources = calloc (entry + 256, sizeof (*pd->sources));
215           pd->nsources = entry + 256;
216         }
217       /* Uarrr.  Unsplit.  */
218       sp[0][strlen (sp[0])] = ' ';
219       sp[1][strlen (sp[1])] = ' ';
220       sp[2][strlen (sp[2])] = ' ';
221       pd->sources[entry] = strdup (sp[0]);
222     }
223   else
224     {
225       unsigned n, nn;
226       Solvable *found = 0;
227       /* Otherwise we may find a solvable with exactly matching name, evr, arch
228          in the repository already.  In that case encode its ID.  */
229       for (n = repo->start, nn = repo->start + pd->last_found_source;
230            n < repo->end; n++, nn++)
231         {
232           if (nn >= repo->end)
233             nn = repo->start;
234           found = pool->solvables + nn;
235           if (found->repo == repo
236               && found->name == name
237               && found->evr == evr
238               && found->arch == arch)
239             {
240               pd->last_found_source = nn - repo->start;
241               break;
242             }
243         }
244       if (n != repo->end)
245         add_attr_int (attr, entry, id_sourceid, nn - repo->start);
246       else
247         {
248           add_attr_localids_id (attr, entry, id_source, str2localid (attr, sp[0], 1));
249           add_attr_localids_id (attr, entry, id_source, str2localid (attr, join (pd, sp[1], "-", sp[2]), 1));
250           add_attr_localids_id (attr, entry, id_source, str2localid (attr, sp[3], 1));
251         }
252     }
253 }
254 #endif
255
256 /*
257  * add_dirline
258  * add a line with directory information
259  * 
260  */
261
262 static void
263 add_dirline (struct parsedata *pd, char *line)
264 {
265   char *sp[6];
266   if (split (line, sp, 6) != 5)
267     return;
268   pd->dirs = sat_extend(pd->dirs, pd->ndirs, 1, sizeof(pd->dirs[0]), 31);
269   long filesz = strtol (sp[1], 0, 0);
270   filesz += strtol (sp[2], 0, 0);
271   long filenum = strtol (sp[3], 0, 0);
272   filenum += strtol (sp[4], 0, 0);
273   /* hack: we know that there's room for a / */
274   if (*sp[0] != '/')
275     *--sp[0] = '/';
276   unsigned dirid = repodata_str2dir(pd->data, sp[0], 1);
277 #if 0
278 fprintf(stderr, "%s -> %d\n", sp[0], dirid);
279 #endif
280   pd->dirs[pd->ndirs][0] = dirid;
281   pd->dirs[pd->ndirs][1] = filesz;
282   pd->dirs[pd->ndirs][2] = filenum;
283   pd->ndirs++;
284 }
285
286
287 /*
288  * id3_cmp
289  * compare 
290  * 
291  */
292
293 static int
294 id3_cmp (const void *v1, const void *v2)
295 {
296   Id *i1 = (Id*)v1;
297   Id *i2 = (Id*)v2;
298   return i1[0] - i2[0];
299 }
300
301
302 /*
303  * commit_diskusage
304  * 
305  */
306
307 static void
308 commit_diskusage (struct parsedata *pd, unsigned entry)
309 {
310   unsigned i;
311   Dirpool *dp = &pd->data->dirpool;
312   /* Now sort in dirid order.  This ensures that parents come before
313      their children.  */
314   if (pd->ndirs > 1)
315     qsort (pd->dirs, pd->ndirs, sizeof (pd->dirs[0]), id3_cmp);
316   /* Substract leaf numbers from all parents to make the numbers
317      non-cumulative.  This must be done post-order (i.e. all leafs
318      adjusted before parents).  We ensure this by starting at the end of
319      the array moving to the start, hence seeing leafs before parents.  */
320   for (i = pd->ndirs; i--;)
321     {
322       unsigned p = dirpool_parent(dp, pd->dirs[i][0]);
323       unsigned j = i;
324       for (; p; p = dirpool_parent(dp, p))
325         {
326           for (; j--;)
327             if (pd->dirs[j][0] == p)
328               break;
329           if (j < pd->ndirs)
330             {
331               if (pd->dirs[j][1] < pd->dirs[i][1])
332                 pd->dirs[j][1] = 0;
333               else
334                 pd->dirs[j][1] -= pd->dirs[i][1];
335               if (pd->dirs[j][2] < pd->dirs[i][2])
336                 pd->dirs[j][2] = 0;
337               else
338                 pd->dirs[j][2] -= pd->dirs[i][2];
339             }
340           else
341             /* Haven't found this parent in the list, look further if
342                we maybe find the parents parent.  */
343             j = i;
344         }
345     }
346 #if 0
347   char sbuf[1024];
348   char *buf = sbuf;
349   unsigned slen = sizeof (sbuf);
350   for (i = 0; i < pd->ndirs; i++)
351     {
352       dir2str (attr, pd->dirs[i][0], &buf, &slen);
353       fprintf (stderr, "have dir %d %d %d %s\n", pd->dirs[i][0], pd->dirs[i][1], pd->dirs[i][2], buf);
354     }
355   if (buf != sbuf)
356     free (buf);
357 #endif
358   for (i = 0; i < pd->ndirs; i++)
359     if (pd->dirs[i][1] || pd->dirs[i][2])
360       {
361         repodata_add_dirnumnum(pd->data, entry, id_diskusage, pd->dirs[i][0], pd->dirs[i][1], pd->dirs[i][2]);
362 #if 0
363         add_attr_intlist_int (attr, entry, id_diskusage, pd->dirs[i][0]);
364         add_attr_intlist_int (attr, entry, id_diskusage, pd->dirs[i][1]);
365         add_attr_intlist_int (attr, entry, id_diskusage, pd->dirs[i][2]);
366 #endif
367       }
368   pd->ndirs = 0;
369 }
370
371
372 /* Unfortunately "a"[0] is no constant expression in the C languages,
373    so we need to pass the four characters individually :-/  */
374 #define CTAG(a,b,c,d) ((unsigned)(((unsigned char)a) << 24) \
375  | ((unsigned char)b << 16) \
376  | ((unsigned char)c << 8) \
377  | ((unsigned char)d))
378
379 /*
380  * tag_from_string
381  * 
382  */
383
384 static inline unsigned
385 tag_from_string (char *cs)
386 {
387   unsigned char *s = (unsigned char*) cs;
388   return ((s[0] << 24) | (s[1] << 16) | (s[2] << 8) | s[3]);
389 }
390
391
392 /*
393  * repo_add_susetags
394  * Parse susetags file passed in fp, fill solvables into repo
395  * 
396  */
397
398 void
399 repo_add_susetags(Repo *repo, FILE *fp, Id vendor, int with_attr)
400 {
401   Pool *pool = repo->pool;
402   char *line, *linep;
403   int aline;
404   Solvable *s;
405   int intag = 0;
406   int cummulate = 0;
407   int indesc = 0;
408   int last_found_pack = 0;
409   char *sp[5];
410   struct parsedata pd;
411   Repodata *data = 0;
412
413 #if 1
414   if (with_attr)
415     {
416 #if 0
417       attr = new_store(pool);
418 #endif
419       data = repo_add_repodata(repo);
420       init_attr_ids(pool);
421     }
422 #endif
423
424   memset(&pd, 0, sizeof(pd));
425   line = malloc(1024);
426   aline = 1024;
427
428   pd.repo = pd.common.repo = repo;
429   pd.data = data;
430   pd.common.pool = pool;
431
432   linep = line;
433   s = 0;
434
435   for (;;)
436     {
437       unsigned tag;
438       if (linep - line + 16 > aline)
439         {
440           aline = linep - line;
441           line = realloc(line, aline + 512);
442           linep = line + aline;
443           aline += 512;
444         }
445       if (!fgets(linep, aline - (linep - line), fp))
446         break;
447       linep += strlen(linep);
448       if (linep == line || linep[-1] != '\n')
449         continue;
450       *--linep = 0;
451       if (intag)
452         {
453           int isend = linep[-intag - 2] == '-' && linep[-1] == ':' && !strncmp(linep - 1 - intag, line + 1, intag) && (linep == line + 1 + intag + 1 + 1 + 1 + intag + 1 || linep[-intag - 3] == '\n');
454           if (cummulate && !isend)
455             {
456               *linep++ = '\n';
457               continue;
458             }
459           if (cummulate && isend)
460             {
461               linep[-intag - 2] = 0;
462               if (linep[-intag - 3] == '\n')
463                 linep[-intag - 3] = 0;
464               linep = line;
465               intag = 0;
466             }
467           if (!cummulate && isend)
468             {
469               intag = 0;
470               linep = line;
471               continue;
472             }
473           if (!cummulate && !isend)
474             linep = line + intag + 3;
475         }
476       else
477         linep = line;
478       if (!intag && line[0] == '+' && line[1] && line[1] != ':')
479         {
480           char *tagend = strchr(line, ':');
481           if (!tagend)
482             {
483               fprintf(stderr, "bad line: %s\n", line);
484               exit(1);
485             }
486           intag = tagend - (line + 1);
487           cummulate = 0;
488           switch (tag_from_string (line))
489             {
490               case CTAG('+', 'D', 'e', 's'):
491               case CTAG('+', 'E', 'u', 'l'):
492               case CTAG('+', 'I', 'n', 's'):
493               case CTAG('+', 'D', 'e', 'l'):
494               case CTAG('+', 'A', 'u', 't'):
495                 if (line[4] == ':')
496                   cummulate = 1;
497             }
498           line[0] = '=';
499           line[intag + 2] = ' ';
500           linep = line + intag + 3;
501           continue;
502         }
503       if (*line == '#' || !*line)
504         continue;
505       if (! (line[0] && line[1] && line[2] && line[3] && line[4] == ':'))
506         continue;
507       tag = tag_from_string (line);
508
509
510       if ((tag == CTAG('=', 'P', 'k', 'g')
511            || tag == CTAG('=', 'P', 'a', 't')))
512         {
513           Id name, evr, arch;
514           /* If we have an old solvable, complete it by filling in some
515              default stuff.  */
516           if (s)
517             {
518               /* A self provide, except for source packages.  This is harmless
519                  to do twice (in case we see the same package twice).  */
520               if (s->arch != ARCH_SRC && s->arch != ARCH_NOSRC)
521                 s->provides = repo_addid_dep(repo, s->provides,
522                                              rel2id(pool, s->name, s->evr,
523                                                     REL_EQ, 1), 0);
524               /* XXX This uses repo_addid_dep internally, so should also be
525                  harmless to do twice.  */
526               s->supplements = repo_fix_legacy(repo, s->provides, s->supplements);
527               if (pd.ndirs)
528                 commit_diskusage (&pd, last_found_pack);
529             }
530
531           pd.kind = KIND_PACKAGE;
532           if (line[3] == 't')
533             pd.kind = KIND_PATTERN;
534           if (split(line + 5, sp, 5) != 4)
535             {
536               fprintf(stderr, "Bad line: %s\n", line);
537               exit(1);
538             }
539           /* Lookup (but don't construct) the name and arch.  */
540           if (pd.kind)
541             name = str2id(pool, join2(kind_prefix(pd.kind), sp[0], 0), 0);
542           else
543             name = str2id(pool, sp[0], 0);
544           arch = str2id(pool, sp[3], 0);
545           evr = makeevr(pool, join2(sp[1], "-", sp[2]));
546
547           s = 0;
548
549           /* Now see if we know this solvable already.  If we found neither
550              the name nor the arch at all in this repo
551              there's no chance of finding the exact solvable either.  */
552           if (indesc >= 2 && name && arch)
553             {
554               int n, nn;
555               /* Now look for a solvable with the given name,evr,arch.
556                  Our input is structured so, that the second set of =Pkg
557                  lines comes in roughly the same order as the first set, so we 
558                  have a hint at where to start our search, namely were we found
559                  the last entry.  */
560               for (n = repo->start, nn = n + last_found_pack; n < repo->end; n++, nn++)
561                 {
562                   if (nn >= repo->end)
563                     nn = repo->start;
564                   s = pool->solvables + nn;
565                   if (s->repo == repo && s->name == name && s->evr == evr && s->arch == arch)
566                     break;
567                 }
568               if (n == repo->end)
569                 s = 0;
570               else
571                 last_found_pack = nn - repo->start;
572             }
573
574           /* And if we still don't have a solvable, create a new one.  */
575           if (!s)
576             {
577               s = pool_id2solvable(pool, repo_add_solvable(repo));
578               last_found_pack = (s - pool->solvables) - repo->start;
579               if (data)
580                 repodata_extend(data, s - pool->solvables);
581               s->kind = pd.kind;
582               if (name)
583                 s->name = name;
584               else if (pd.kind)
585                 s->name = str2id(pool, join2(kind_prefix(pd.kind), sp[0], 0), 1);
586               else
587                 s->name = str2id(pool, sp[0], 1);
588               s->evr = evr;
589               if (arch)
590                 s->arch = arch;
591               else
592                 s->arch = str2id(pool, sp[3], 1);
593               s->vendor = vendor;
594             }
595         }
596
597       /* If we have no current solvable to add to, ignore all further lines
598          for it.  Probably invalid input data in the second set of
599          solvables.  */
600       if (indesc >= 2 && !s)
601         {
602           fprintf (stderr, "Huh?\n");
603           continue;
604         }
605       switch (tag)
606         {
607           case CTAG('=', 'P', 'r', 'v'):
608             s->provides = adddep(pool, &pd, s->provides, line, 0, pd.kind);
609             continue;
610           case CTAG('=', 'R', 'e', 'q'):
611             s->requires = adddep(pool, &pd, s->requires, line, -SOLVABLE_PREREQMARKER, pd.kind);
612             continue;
613           case CTAG('=', 'P', 'r', 'q'):
614             if (pd.kind)
615               s->requires = adddep(pool, &pd, s->requires, line, 0, 0); /* Huh? No PreReq for non-packages ? */
616             else
617               s->requires = adddep(pool, &pd, s->requires, line, SOLVABLE_PREREQMARKER, 0);
618             continue;
619           case CTAG('=', 'O', 'b', 's'):
620             s->obsoletes = adddep(pool, &pd, s->obsoletes, line, 0, pd.kind);
621             continue;
622           case CTAG('=', 'C', 'o', 'n'):
623             s->conflicts = adddep(pool, &pd, s->conflicts, line, 0, pd.kind);
624             continue;
625           case CTAG('=', 'R', 'e', 'c'):
626             s->recommends = adddep(pool, &pd, s->recommends, line, 0, pd.kind);
627             continue;
628           case CTAG('=', 'S', 'u', 'p'):
629             s->supplements = adddep(pool, &pd, s->supplements, line, 0, pd.kind);
630             continue;
631           case CTAG('=', 'E', 'n', 'h'):
632             s->enhances = adddep(pool, &pd, s->enhances, line, 0, pd.kind);
633             continue;
634           case CTAG('=', 'S', 'u', 'g'):
635             s->suggests = adddep(pool, &pd, s->suggests, line, 0, pd.kind);
636             continue;
637           case CTAG('=', 'F', 'r', 'e'):
638             s->freshens = adddep(pool, &pd, s->freshens, line, 0, pd.kind);
639             continue;
640           case CTAG('=', 'P', 'r', 'c'):
641             s->recommends = adddep(pool, &pd, s->recommends, line, 0, 0);
642             continue;
643           case CTAG('=', 'P', 's', 'g'):
644             s->suggests = adddep(pool, &pd, s->suggests, line, 0, 0);
645             continue;
646           case CTAG('=', 'V', 'e', 'r'):
647             last_found_pack = 0;
648             indesc++;
649             continue;
650         }
651       if (!with_attr)
652         continue;
653       switch (tag)
654         {
655           case CTAG('=', 'G', 'r', 'p'):
656             repodata_set_poolstr(data, last_found_pack, id_group, line + 6);
657             continue;
658           case CTAG('=', 'L', 'i', 'c'):
659             repodata_set_poolstr(data, last_found_pack, id_license, line + 6);
660             continue;
661           case CTAG('=', 'L', 'o', 'c'):
662             add_location(&pd, line + 6, s, last_found_pack);
663             continue;
664 #if 0
665           case CTAG('=', 'S', 'r', 'c'):
666             add_source(&pd, line + 6, s, last_found_pack, 1);
667             continue;
668 #endif
669           case CTAG('=', 'S', 'i', 'z'):
670             if (split (line + 6, sp, 3) == 2)
671               {
672                 repodata_set_num(data, last_found_pack, id_downloadsize, (atoi(sp[0]) + 1023) / 1024);
673                 repodata_set_num(data, last_found_pack, id_installsize, (atoi(sp[1]) + 1023) / 1024);
674               }
675             continue;
676           case CTAG('=', 'T', 'i', 'm'):
677             {
678               unsigned int t = atoi (line + 6);
679               if (t)
680                 {
681                   repodata_set_num(data, last_found_pack, id_time, t);
682                 }
683             }
684             continue;
685           case CTAG('=', 'K', 'w', 'd'):
686             repodata_set_poolstr(data, last_found_pack, id_keywords, line + 6);
687             continue;
688           case CTAG('=', 'A', 'u', 't'):
689             repodata_set_str(data, last_found_pack, id_authors, line + 6);
690             continue;
691           case CTAG('=', 'S', 'u', 'm'):
692             repodata_set_str(data, last_found_pack, id_summary, line + 6);
693             continue;
694           case CTAG('=', 'D', 'e', 's'):
695             repodata_set_str(data, last_found_pack, id_description, line + 6);
696             continue;
697           case CTAG('=', 'E', 'u', 'l'):
698             repodata_set_str(data, last_found_pack, id_eula, line + 6);
699             continue;
700           case CTAG('=', 'I', 'n', 's'):
701             repodata_set_str(data, last_found_pack, id_messageins, line + 6);
702             continue;
703           case CTAG('=', 'D', 'e', 'l'):
704             repodata_set_str(data, last_found_pack, id_messagedel, line + 6);
705             continue;
706           case CTAG('=', 'S', 'h', 'r'):
707             if (last_found_pack >= pd.nshare)
708               {
709                 if (pd.share_with)
710                   {
711                     pd.share_with = realloc (pd.share_with, (last_found_pack + 256) * sizeof (*pd.share_with));
712                     memset (pd.share_with + pd.nshare, 0, (last_found_pack + 256 - pd.nshare) * sizeof (*pd.share_with));
713                   }
714                 else
715                   pd.share_with = calloc (last_found_pack + 256, sizeof (*pd.share_with));
716                 pd.nshare = last_found_pack + 256;
717               }
718             pd.share_with[last_found_pack] = strdup (line + 6);
719             continue;
720           case CTAG('=', 'D', 'i', 'r'):
721             add_dirline (&pd, line + 6);
722             continue;
723         }
724     }
725   if (s && s->arch != ARCH_SRC && s->arch != ARCH_NOSRC)
726     s->provides = repo_addid_dep(repo, s->provides, rel2id(pool, s->name, s->evr, REL_EQ, 1), 0);
727   if (s)
728     s->supplements = repo_fix_legacy(repo, s->provides, s->supplements);
729
730   if (s && pd.ndirs)
731     commit_diskusage(&pd, last_found_pack);
732     
733 #if 0
734   if (pd.sources)
735     {
736       int i, last_found;
737       for (i = 0; i < pd.nsources; i++)
738         if (pd.sources[i])
739           {
740             add_source(&pd, pd.sources[i], pool->solvables + repo->start + i, i, 0);
741             free (pd.sources[i]);
742           }
743       free (pd.sources);
744     }
745 #endif
746
747   if (pd.nshare)
748     {
749       int i, last_found;
750       last_found = 0;
751       for (i = 0; i < pd.nshare; i++)
752         if (pd.share_with[i])
753           {
754             if (split(pd.share_with[i], sp, 5) != 4)
755               {
756                 fprintf(stderr, "Bad =Shr line: %s\n", pd.share_with[i]);
757                 exit(1);
758               }
759
760             Id name = str2id(pool, sp[0], 1);
761             Id evr = makeevr(pool, join2(sp[1], "-", sp[2]));
762             Id arch = str2id(pool, sp[3], 1);
763             unsigned n, nn;
764             Solvable *found = 0;
765             for (n = repo->start, nn = repo->start + last_found;
766                  n < repo->end; n++, nn++)
767               {
768                 if (nn >= repo->end)
769                   nn = repo->start;
770                 found = pool->solvables + nn;
771                 if (found->repo == repo
772                     && found->name == name
773                     && found->evr == evr
774                     && found->arch == arch)
775                   {
776                     last_found = nn - repo->start;
777                     break;
778                   }
779               }
780             if (n != repo->end)
781               repodata_merge_attrs (data, i, last_found);
782           }
783       free (pd.share_with);
784     }
785
786   if (data)
787     repodata_internalize(data);
788
789   if (pd.common.tmp)
790     free(pd.common.tmp);
791   free(line);
792 }