4 * Parses 'content' file into .solv
5 * See http://en.opensuse.org/Standards/YaST2_Repository_Metadata/content for a description
9 * Copyright (c) 2007, Novell Inc.
11 * This program is licensed under the BSD license, read LICENSE.BSD
12 * for further information
15 #include <sys/types.h>
26 #include "repo_content.h"
29 /* split off a word, return null terminated pointer to it.
30 * return NULL if there is no word left. */
36 while (*l == ' ' || *l == '\t')
39 while (*l && *l != ' ' && *l != '\t')
42 *l++ = 0; /* terminate word */
43 while (*l == ' ' || *l == '\t')
44 l++; /* convenience: advance to next word */
57 makeevr(Pool *pool, char *s)
59 if (!strncmp(s, "0:", 2) && s[2])
61 return str2id(pool, s, 1);
65 * dependency relations
68 static char *flagtab[] = {
79 * join up to three strings into one
83 join(struct parsedata *pd, const char *s1, const char *s2, const char *s3)
97 pd->tmp = sat_realloc(pd->tmp, pd->tmpl);
120 * add dependency to pool
121 * OBSOLETES product:SUSE_LINUX product:openSUSE < 11.0 package:openSUSE < 11.0
125 adddep(Pool *pool, struct parsedata *pd, unsigned int olddeps, char *line, Id marker)
130 while ((name = splitword(&line)) != 0)
132 /* Hack, as the content file adds 'package:' for package
133 dependencies sometimes. */
134 if (!strncmp (name, "package:", 8))
136 id = str2id(pool, name, 1);
137 if (strpbrk(line, "<>=") == line) /* next(!) word is rel */
139 char *rel = splitword(&line);
140 char *evr = splitword(&line);
145 fprintf(stderr, "bad relation '%s %s'\n", name, rel);
148 for (flags = 0; flags < 6; flags++)
149 if (!strcmp(rel, flagtab[flags]))
153 fprintf(stderr, "Unknown relation '%s'\n", rel);
156 id = rel2id(pool, id, str2id(pool, evr, 1), flags + 1, 1);
158 olddeps = repo_addid_dep(pd->repo, olddeps, id, marker);
165 * split value and add to pool
169 add_multiple_strings(Repodata *data, Id handle, Id name, char *value)
173 while ((str = splitword(&value)) != 0)
174 repodata_add_poolstr_array(data, handle, name, str);
178 * split value and add to pool
182 add_multiple_urls(Repodata *data, Id handle, char *value, Id type)
186 while ((url = splitword(&value)) != 0)
188 repodata_add_poolstr_array(data, handle, PRODUCT_URL, url);
189 repodata_add_idarray(data, handle, PRODUCT_URL_TYPE, type);
196 * add 'content' to repo
201 repo_add_content(Repo *repo, FILE *fp)
203 Pool *pool = repo->pool;
210 int contentstyle = 0;
215 we use the first architecture in BASEARCHS or noarch
216 for the product. At the end we create (clone) the product
217 for each one of the remaining architectures
220 unsigned int numotherarchs = 0;
223 memset(&pd, 0, sizeof(pd));
224 line = sat_malloc(1024);
228 /* use last repodata */
229 data = repo->repodata + repo->nrepodata - 1;
231 data = repo_add_repodata(repo, 0);
241 /* read line into big-enough buffer */
242 if (linep - line + 16 > aline)
244 aline = linep - line;
245 line = sat_realloc(line, aline + 512);
246 linep = line + aline;
249 if (!fgets(linep, aline - (linep - line), fp))
251 linep += strlen(linep);
252 if (linep == line || linep[-1] != '\n')
257 /* expect "key value" lines */
259 key = splitword(&value);
264 fprintf (stderr, "key %s, value %s\n", key, value);
267 #define istag(x) (!strcmp (key, x))
268 #define code10 (contentstyle == 10)
269 #define code11 (contentstyle == 11)
271 if (contentstyle == 0)
273 if (istag ("CONTENTSTYLE"))
275 contentstyle = atoi(value);
282 if ((code10 && istag ("PRODUCT"))
283 || (code11 && istag ("NAME")))
287 /* this solvable was created without seeing a
288 PRODUCT entry, just set the name and continue */
289 s->name = str2id(pool, join(&pd, "product", ":", value), 1);
294 /* finish old solvable */
296 s->arch = ARCH_NOARCH;
297 if (s->arch != ARCH_SRC && s->arch != ARCH_NOSRC)
298 s->provides = repo_addid_dep(repo, s->provides, rel2id(pool, s->name, s->evr, REL_EQ, 1), 0);
300 s->supplements = repo_fix_supplements(repo, s->provides, s->supplements, 0);
302 /* create new solvable */
303 s = pool_id2solvable(pool, repo_add_solvable(repo));
304 repodata_extend(data, s - pool->solvables);
305 handle = repodata_get_handle(data, s - pool->solvables - repo->start);
306 s->name = str2id(pool, join(&pd, "product", ":", value), 1);
310 /* Sometimes PRODUCT/NAME is not the first entry, but we need a solvable
314 s = pool_id2solvable(pool, repo_add_solvable(repo));
315 repodata_extend(data, s - pool->solvables);
316 handle = repodata_get_handle(data, s - pool->solvables - repo->start);
319 if (istag ("VERSION"))
320 s->evr = makeevr(pool, value);
321 else if (code11 && istag ("DISTRIBUTION"))
322 repo_set_str(repo, s - pool->solvables, SOLVABLE_DISTRIBUTION, value);
323 else if (istag ("DATADIR"))
324 repo_set_str(repo, s - pool->solvables, SUSETAGS_DATADIR, value);
325 else if (istag ("UPDATEURLS"))
326 add_multiple_urls(data, handle, value, str2id(pool, "update", 1));
327 else if (istag ("EXTRAURLS"))
328 add_multiple_urls(data, handle, value, str2id(pool, "extra", 1));
329 else if (istag ("OPTIONALURLS"))
330 add_multiple_urls(data, handle, value, str2id(pool, "optional", 1));
331 else if (istag ("RELNOTESURL"))
332 add_multiple_urls(data, handle, value, str2id(pool, "releasenotes", 1));
333 else if (istag ("SHORTLABEL"))
334 repo_set_str(repo, s - pool->solvables, PRODUCT_SHORTLABEL, value);
335 else if (istag ("LABEL")) /* LABEL is the products SUMMARY. */
336 repo_set_str(repo, s - pool->solvables, SOLVABLE_SUMMARY, value);
337 else if (!strncmp (key, "LABEL.", 6))
338 repo_set_str(repo, s - pool->solvables, pool_id2langid(pool, SOLVABLE_SUMMARY, key + 6, 1), value);
339 else if (istag ("FLAGS"))
340 add_multiple_strings(data, handle, PRODUCT_FLAGS, value);
341 else if (istag ("VENDOR"))
342 s->vendor = str2id(pool, value, 1);
343 else if (istag ("BASEARCHS"))
347 if ((arch = splitword(&value)) != 0)
349 s->arch = str2id(pool, arch, 1);
350 while ((arch = splitword(&value)) != 0)
352 otherarchs = sat_extend(otherarchs, numotherarchs, 1, sizeof(Id), 7);
353 otherarchs[numotherarchs++] = str2id(pool, arch, 1);
359 * Every tag below is Code10 only
363 else if (code10 && istag ("DISTPRODUCT"))
364 /* DISTPRODUCT is for registration and Yast, not for the solver. */
365 repo_set_str(repo, s - pool->solvables, PRODUCT_DISTPRODUCT, value);
366 else if (code10 && istag ("DISTVERSION"))
367 /* DISTVERSION is for registration and Yast, not for the solver. */
368 repo_set_str(repo, s - pool->solvables, PRODUCT_DISTVERSION, value);
369 else if (code10 && istag ("ARCH"))
370 /* Theoretically we want to have the best arch of the given
371 modifiers which still is compatible with the system
372 arch. We don't know the latter here, though. */
373 s->arch = ARCH_NOARCH;
374 else if (code10 && istag ("PREREQUIRES"))
375 s->requires = adddep(pool, &pd, s->requires, value, SOLVABLE_PREREQMARKER);
376 else if (code10 && istag ("REQUIRES"))
377 s->requires = adddep(pool, &pd, s->requires, value, -SOLVABLE_PREREQMARKER);
378 else if (code10 && istag ("PROVIDES"))
379 s->provides = adddep(pool, &pd, s->provides, value, 0);
380 else if (code10 && istag ("CONFLICTS"))
381 s->conflicts = adddep(pool, &pd, s->conflicts, value, 0);
382 else if (code10 && istag ("OBSOLETES"))
383 s->obsoletes = adddep(pool, &pd, s->obsoletes, value, 0);
384 else if (code10 && istag ("RECOMMENDS"))
385 s->recommends = adddep(pool, &pd, s->recommends, value, 0);
386 else if (code10 && istag ("SUGGESTS"))
387 s->suggests = adddep(pool, &pd, s->suggests, value, 0);
388 else if (code10 && istag ("SUPPLEMENTS"))
389 s->supplements = adddep(pool, &pd, s->supplements, value, 0);
390 else if (code10 && istag ("ENHANCES"))
391 s->enhances = adddep(pool, &pd, s->enhances, value, 0);
392 /* FRESHENS doesn't seem to exist. */
393 else if (code10 && istag ("TYPE"))
394 repo_set_str(repo, s - pool->solvables, PRODUCT_TYPE, value);
396 /* XXX do something about LINGUAS and ARCH?
397 * <ma>: Don't think so. zypp does not use or propagate them.
402 fprintf (stderr, "malformed line: %s\n", line);
407 fprintf(stderr, "No product solvable created !\n");
412 s->arch = ARCH_NOARCH;
413 if (s->arch != ARCH_SRC && s->arch != ARCH_NOSRC)
415 s->provides = repo_addid_dep(repo, s->provides, rel2id(pool, s->name, s->evr, REL_EQ, 1), 0);
417 s->supplements = repo_fix_supplements(repo, s->provides, s->supplements, 0);
420 /* now for every other arch, clone the product except the architecture */
421 for (i = 0; i < numotherarchs; ++i)
423 Solvable *p = pool_id2solvable(pool, repo_add_solvable(repo));
424 repodata_extend(data, p - pool->solvables);
425 /*handle = repodata_get_handle(data, p - pool->solvables - repo->start);*/
428 p->vendor = s->vendor;
429 p->arch = otherarchs[i];
432 if (p->arch != ARCH_SRC && p->arch != ARCH_NOSRC)
433 p->provides = repo_addid_dep(repo, p->provides, rel2id(pool, p->name, p->evr, REL_EQ, 1), 0);
435 /* now merge the attributes */
436 repodata_merge_attrs(data, p - pool->solvables - repo->start, s - pool->solvables- repo->start);
440 repodata_internalize(data);
445 sat_free(otherarchs);