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 (*line == '<' || *line == '>' || *line == '=') /* rel follows */
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, int flags)
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 if (!(flags & REPO_REUSE_REPODATA))
224 data = repo_add_repodata(repo, 0);
226 data = repo_last_repodata(repo);
228 memset(&pd, 0, sizeof(pd));
229 line = sat_malloc(1024);
233 /* use last repodata */
234 data = repo->repodata + repo->nrepodata - 1;
236 data = repo_add_repodata(repo, 0);
246 /* read line into big-enough buffer */
247 if (linep - line + 16 > aline)
249 aline = linep - line;
250 line = sat_realloc(line, aline + 512);
251 linep = line + aline;
254 if (!fgets(linep, aline - (linep - line), fp))
256 linep += strlen(linep);
257 if (linep == line || linep[-1] != '\n')
262 /* expect "key value" lines */
264 key = splitword(&value);
269 fprintf (stderr, "key %s, value %s\n", key, value);
272 #define istag(x) (!strcmp (key, x))
273 #define code10 (contentstyle == 10)
274 #define code11 (contentstyle == 11)
276 if (contentstyle == 0)
278 if (istag ("CONTENTSTYLE"))
280 contentstyle = atoi(value);
287 if ((code10 && istag ("PRODUCT"))
288 || (code11 && istag ("NAME")))
292 /* this solvable was created without seeing a
293 PRODUCT entry, just set the name and continue */
294 s->name = str2id(pool, join(&pd, "product", ":", value), 1);
299 /* finish old solvable */
301 s->arch = ARCH_NOARCH;
302 if (s->arch != ARCH_SRC && s->arch != ARCH_NOSRC)
303 s->provides = repo_addid_dep(repo, s->provides, rel2id(pool, s->name, s->evr, REL_EQ, 1), 0);
305 s->supplements = repo_fix_supplements(repo, s->provides, s->supplements, 0);
307 /* create new solvable */
308 s = pool_id2solvable(pool, repo_add_solvable(repo));
309 repodata_extend(data, s - pool->solvables);
310 handle = s - pool->solvables;
311 s->name = str2id(pool, join(&pd, "product", ":", value), 1);
315 /* Sometimes PRODUCT/NAME is not the first entry, but we need a solvable
319 s = pool_id2solvable(pool, repo_add_solvable(repo));
320 repodata_extend(data, s - pool->solvables);
321 handle = s - pool->solvables;
324 if (istag ("VERSION"))
325 s->evr = makeevr(pool, value);
326 else if (code11 && istag ("DISTRIBUTION"))
327 repo_set_str(repo, s - pool->solvables, SOLVABLE_DISTRIBUTION, value);
328 else if (istag ("DATADIR"))
329 repo_set_str(repo, s - pool->solvables, SUSETAGS_DATADIR, value);
330 else if (istag ("UPDATEURLS"))
331 add_multiple_urls(data, handle, value, str2id(pool, "update", 1));
332 else if (istag ("EXTRAURLS"))
333 add_multiple_urls(data, handle, value, str2id(pool, "extra", 1));
334 else if (istag ("OPTIONALURLS"))
335 add_multiple_urls(data, handle, value, str2id(pool, "optional", 1));
336 else if (istag ("RELNOTESURL"))
337 add_multiple_urls(data, handle, value, str2id(pool, "releasenotes", 1));
338 else if (istag ("SHORTLABEL"))
339 repo_set_str(repo, s - pool->solvables, PRODUCT_SHORTLABEL, value);
340 else if (istag ("LABEL")) /* LABEL is the products SUMMARY. */
341 repo_set_str(repo, s - pool->solvables, SOLVABLE_SUMMARY, value);
342 else if (!strncmp (key, "LABEL.", 6))
343 repo_set_str(repo, s - pool->solvables, pool_id2langid(pool, SOLVABLE_SUMMARY, key + 6, 1), value);
344 else if (istag ("FLAGS"))
345 add_multiple_strings(data, handle, PRODUCT_FLAGS, value);
346 else if (istag ("VENDOR"))
347 s->vendor = str2id(pool, value, 1);
348 else if (istag ("BASEARCHS"))
352 if ((arch = splitword(&value)) != 0)
354 s->arch = str2id(pool, arch, 1);
355 while ((arch = splitword(&value)) != 0)
357 otherarchs = sat_extend(otherarchs, numotherarchs, 1, sizeof(Id), 7);
358 otherarchs[numotherarchs++] = str2id(pool, arch, 1);
364 * Every tag below is Code10 only
368 else if (code10 && istag ("DISTPRODUCT"))
369 /* DISTPRODUCT is for registration and Yast, not for the solver. */
370 repo_set_str(repo, s - pool->solvables, PRODUCT_DISTPRODUCT, value);
371 else if (code10 && istag ("DISTVERSION"))
372 /* DISTVERSION is for registration and Yast, not for the solver. */
373 repo_set_str(repo, s - pool->solvables, PRODUCT_DISTVERSION, value);
374 else if (code10 && istag ("ARCH"))
375 /* Theoretically we want to have the best arch of the given
376 modifiers which still is compatible with the system
377 arch. We don't know the latter here, though. */
378 s->arch = ARCH_NOARCH;
379 else if (code10 && istag ("PREREQUIRES"))
380 s->requires = adddep(pool, &pd, s->requires, value, SOLVABLE_PREREQMARKER);
381 else if (code10 && istag ("REQUIRES"))
382 s->requires = adddep(pool, &pd, s->requires, value, -SOLVABLE_PREREQMARKER);
383 else if (code10 && istag ("PROVIDES"))
384 s->provides = adddep(pool, &pd, s->provides, value, 0);
385 else if (code10 && istag ("CONFLICTS"))
386 s->conflicts = adddep(pool, &pd, s->conflicts, value, 0);
387 else if (code10 && istag ("OBSOLETES"))
388 s->obsoletes = adddep(pool, &pd, s->obsoletes, value, 0);
389 else if (code10 && istag ("RECOMMENDS"))
390 s->recommends = adddep(pool, &pd, s->recommends, value, 0);
391 else if (code10 && istag ("SUGGESTS"))
392 s->suggests = adddep(pool, &pd, s->suggests, value, 0);
393 else if (code10 && istag ("SUPPLEMENTS"))
394 s->supplements = adddep(pool, &pd, s->supplements, value, 0);
395 else if (code10 && istag ("ENHANCES"))
396 s->enhances = adddep(pool, &pd, s->enhances, value, 0);
397 /* FRESHENS doesn't seem to exist. */
398 else if (code10 && istag ("TYPE"))
399 repo_set_str(repo, s - pool->solvables, PRODUCT_TYPE, value);
401 /* XXX do something about LINGUAS and ARCH?
402 * <ma>: Don't think so. zypp does not use or propagate them.
407 fprintf (stderr, "malformed line: %s\n", line);
412 fprintf(stderr, "No product solvable created !\n");
417 s->arch = ARCH_NOARCH;
418 if (s->arch != ARCH_SRC && s->arch != ARCH_NOSRC)
420 s->provides = repo_addid_dep(repo, s->provides, rel2id(pool, s->name, s->evr, REL_EQ, 1), 0);
422 s->supplements = repo_fix_supplements(repo, s->provides, s->supplements, 0);
425 /* now for every other arch, clone the product except the architecture */
426 for (i = 0; i < numotherarchs; ++i)
428 Solvable *p = pool_id2solvable(pool, repo_add_solvable(repo));
429 repodata_extend(data, p - pool->solvables);
432 p->vendor = s->vendor;
433 p->arch = otherarchs[i];
436 if (p->arch != ARCH_SRC && p->arch != ARCH_NOSRC)
437 p->provides = repo_addid_dep(repo, p->provides, rel2id(pool, p->name, p->evr, REL_EQ, 1), 0);
439 /* now merge the attributes */
440 repodata_merge_attrs(data, p - pool->solvables, s - pool->solvables);
446 sat_free(otherarchs);
447 if (!(flags & REPO_NO_INTERNALIZE))
448 repodata_internalize(data);