- only add info block if there are file provides
[platform/upstream/libsolv.git] / tools / common_write.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 #include "repo_write.h"
18 #include "common_write.h"
19
20 static Id verticals[] = {
21   SOLVABLE_AUTHORS,
22   SOLVABLE_DESCRIPTION,
23   SOLVABLE_MESSAGEDEL,
24   SOLVABLE_MESSAGEINS,
25   SOLVABLE_EULA,
26   SOLVABLE_DISKUSAGE,
27   SOLVABLE_FILELIST,
28   0
29 };
30
31 static char *languagetags[] = {
32   "solvable:summary:",
33   "solvable:description:",
34   "solvable:messageins:",
35   "solvable:messagedel:",
36   0
37 };
38
39 static int test_separate = 0;
40
41 static int
42 keyfilter_solv(Repo *data, Repokey *key, void *kfdata)
43 {
44   int i;
45   if (test_separate && key->storage != KEY_STORAGE_SOLVABLE)
46     return KEY_STORAGE_DROPPED;
47   for (i = 0; verticals[i]; i++)
48     if (key->name == verticals[i])
49       return KEY_STORAGE_VERTICAL_OFFSET;
50   return KEY_STORAGE_INCORE;
51 }
52
53 static int
54 keyfilter_attr(Repo *data, Repokey *key, void *kfdata)
55 {
56   int i;
57   if (key->storage == KEY_STORAGE_SOLVABLE)
58     return KEY_STORAGE_DROPPED;
59   for (i = 0; verticals[i]; i++)
60     if (key->name == verticals[i])
61       return KEY_STORAGE_VERTICAL_OFFSET;
62   return KEY_STORAGE_INCORE;
63 }
64
65 static int
66 keyfilter_language(Repo *repo, Repokey *key, void *kfdata)
67 {
68   const char *name, *p;
69   char *lang = kfdata, *bname;
70   int i;
71   Id id;
72
73   name = id2str(repo->pool, key->name);
74   p = strrchr(name, ':');
75   if (!p || strcmp(p + 1, lang) != 0)
76     return KEY_STORAGE_DROPPED;
77   /* find base name id */
78   bname = strdup(name);
79   bname[p - name] = 0;
80   id = str2id(repo->pool, bname, 1);
81   for (i = 0; verticals[i]; i++)
82     if (id == verticals[i])
83       return KEY_STORAGE_VERTICAL_OFFSET;
84   return KEY_STORAGE_INCORE;
85 }
86
87 static int
88 keyfilter_DU(Repo *repo, Repokey *key, void *kfdata)
89 {
90   int i;
91   if (key->name != SOLVABLE_DISKUSAGE)
92     return KEY_STORAGE_DROPPED;
93   for (i = 0; verticals[i]; i++)
94     if (key->name == verticals[i])
95       return KEY_STORAGE_VERTICAL_OFFSET;
96   return KEY_STORAGE_INCORE;
97 }
98
99 static int
100 keyfilter_FL(Repo *repo, Repokey *key, void *kfdata)
101 {
102   int i;
103   if (key->name != SOLVABLE_FILELIST)
104     return KEY_STORAGE_DROPPED;
105   for (i = 0; verticals[i]; i++)
106     if (key->name == verticals[i])
107       return KEY_STORAGE_VERTICAL_OFFSET;
108   return KEY_STORAGE_INCORE;
109 }
110
111 struct keyfilter_other_data {
112   char **languages;
113   int nlanguages;
114 };
115
116 static int
117 keyfilter_other(Repo *repo, Repokey *key, void *kfdata)
118 {
119   const char *name, *p;
120   struct keyfilter_other_data *kd = kfdata;
121   int i;
122
123   if (key->name == SOLVABLE_FILELIST || key->name == SOLVABLE_DISKUSAGE)
124     return KEY_STORAGE_DROPPED;
125
126   name = id2str(repo->pool, key->name);
127   p = strrchr(name, ':');
128   if (p)
129     {
130       for (i = 0; i < kd->nlanguages; i++)
131         if (!strcmp(p + 1, kd->languages[i]))
132           return KEY_STORAGE_DROPPED;
133     }
134   for (i = 0; verticals[i]; i++)
135     if (key->name == verticals[i])
136       return KEY_STORAGE_VERTICAL_OFFSET;
137   return KEY_STORAGE_INCORE;
138 }
139
140 /*
141  * Write <repo> to stdout
142  * If <attrname> is given, write attributes to <attrname>
143  * If <basename> is given, split attributes
144  */
145
146 #define REPODATAFILE_BLOCK 15
147
148 int
149 tool_write(Repo *repo, const char *basename, const char *attrname)
150 {
151   Repodata *data;
152   Repokey *key;
153   Repodatafile *fileinfos = 0;
154   int nfileinfos = 0;
155   char **languages = 0;
156   int nlanguages = 0;
157   int i, j, k, l;
158
159   fileinfos = sat_zextend(fileinfos, nfileinfos, 1, sizeof(Repodatafile), REPODATAFILE_BLOCK);
160   pool_addfileprovides_ids(repo->pool, 0, &fileinfos[nfileinfos].addedfileprovides);
161   if (fileinfos[nfileinfos].addedfileprovides)
162     nfileinfos++;
163
164   if (basename)
165     {
166       struct keyfilter_other_data kd;
167       char fn[4096];
168       FILE *fp;
169       int has_DU = 0;
170       int has_FL = 0;
171
172       /* find languages and other info */
173       for (i = 0, data = repo->repodata; i < repo->nrepodata; i++, data++)
174         {
175           for (j = 1, key = data->keys + j; j < data->nkeys; j++, key++)
176             {
177               const char *keyname = id2str(repo->pool, key->name);
178               if (key->name == SOLVABLE_DISKUSAGE)
179                 has_DU = 1;
180               if (key->name == SOLVABLE_FILELIST)
181                 has_FL = 1;
182               for (k = 0; languagetags[k] != 0; k++)
183                 if (!strncmp(keyname, languagetags[k], strlen(languagetags[k])))
184                   break;
185               if (!languagetags[k])
186                 continue;
187               l = strlen(languagetags[k]);
188               if (strlen(keyname + l) > 5)
189                 continue;
190               for (k = 0; k < nlanguages; k++)
191                 if (!strcmp(languages[k], keyname + l))
192                   break;
193               if (k < nlanguages)
194                 continue;
195               languages = sat_realloc2(languages, nlanguages + 1, sizeof(char *));
196               languages[nlanguages++] = strdup(keyname + l);
197             }
198         }
199       fileinfos = sat_zextend(fileinfos, nfileinfos, nlanguages + 2, sizeof(Repodatafile), REPODATAFILE_BLOCK);
200       /* write language subfiles */
201       for (i = 0; i < nlanguages; i++)
202         {
203           sprintf(fn, "%s.%s.solv", basename, languages[i]);
204           if (!(fp = fopen(fn, "w")))
205             {
206               perror(fn);
207               exit(1);
208             }
209           repo_write(repo, fp, keyfilter_language, languages[i], fileinfos + nfileinfos, 0);
210           fileinfos[nfileinfos].location = strdup(fn);
211           fclose(fp);
212           nfileinfos++;
213         }
214       /* write DU subfile */
215       if (has_DU)
216         {
217           sprintf(fn, "%s.DU.solv", basename);
218           if (!(fp = fopen(fn, "w")))
219             {
220               perror(fn);
221               exit(1);
222             }
223           repo_write(repo, fp, keyfilter_DU, 0, fileinfos + nfileinfos, 0);
224           fileinfos[nfileinfos].location = strdup(fn);
225           fclose(fp);
226           nfileinfos++;
227         }
228       /* write filelist */
229       if (has_FL)
230         {
231           sprintf(fn, "%s.FL.solv", basename);
232           if (!(fp = fopen(fn, "w")))
233             {
234               perror(fn);
235               exit(1);
236             }
237           repo_write(repo, fp, keyfilter_FL, 0, fileinfos + nfileinfos, 0);
238           fileinfos[nfileinfos].location = strdup(fn);
239           fclose(fp);
240           nfileinfos++;
241         }
242       /* write everything else */
243       sprintf(fn, "%s.solv", basename);
244       if (!(fp = fopen(fn, "w")))
245         {
246           perror(fn);
247           exit(1);
248         }
249       kd.languages = languages;
250       kd.nlanguages = nlanguages;
251       repo_write(repo, fp, keyfilter_other, &kd, fileinfos, nfileinfos);
252       fclose(fp);
253       for (i = 0; i < nlanguages; i++)
254         free(languages[i]);
255       sat_free(languages);
256       for (i = 0; i < nfileinfos; i++)
257         {
258           sat_free(fileinfos[i].addedfileprovides);
259           sat_free(fileinfos[i].location);
260           sat_free(fileinfos[i].keys);
261         }
262       sat_free(fileinfos);
263       return 0;
264     }
265   if (attrname)
266     {
267       fileinfos = sat_zextend(fileinfos, nfileinfos, 1, sizeof(Repodatafile), REPODATAFILE_BLOCK);
268       test_separate = 1;
269       FILE *fp = fopen (attrname, "w");
270       repo_write(repo, fp, keyfilter_attr, 0, fileinfos + nfileinfos, 0);
271       fileinfos[nfileinfos].location = strdup(attrname);
272       fclose(fp);
273       nfileinfos++;
274     }
275   repo_write(repo, stdout, keyfilter_solv, 0, fileinfos, nfileinfos);
276   for (i = 0; i < nfileinfos; i++)
277     {
278       sat_free(fileinfos[i].addedfileprovides);
279       sat_free(fileinfos[i].location);
280       sat_free(fileinfos[i].keys);
281     }
282   sat_free(fileinfos);
283   return 0;
284 }