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"
28 #include "tools_util.h"
30 /* split off a word, return null terminated pointer to it.
31 * return NULL if there is no word left. */
37 while (*l == ' ' || *l == '\t')
40 while (*l && *l != ' ' && *l != '\t')
43 *l++ = 0; /* terminate word */
44 while (*l == ' ' || *l == '\t')
45 l++; /* convenience: advance to next word */
60 * dependency relations
63 static char *flagtab[] = {
74 * join up to three strings into one
78 join(struct parsedata *pd, const char *s1, const char *s2, const char *s3)
92 pd->tmp = sat_realloc(pd->tmp, pd->tmpl);
115 * add dependency to pool
116 * OBSOLETES product:SUSE_LINUX product:openSUSE < 11.0 package:openSUSE < 11.0
120 adddep(Pool *pool, struct parsedata *pd, unsigned int olddeps, char *line, Id marker)
125 while ((name = splitword(&line)) != 0)
127 /* Hack, as the content file adds 'package:' for package
128 dependencies sometimes. */
129 if (!strncmp (name, "package:", 8))
131 id = str2id(pool, name, 1);
132 if (*line == '<' || *line == '>' || *line == '=') /* rel follows */
134 char *rel = splitword(&line);
135 char *evr = splitword(&line);
140 pool_debug(pool, SAT_FATAL, "repo_content: bad relation '%s %s'\n", name, rel);
143 for (flags = 0; flags < 6; flags++)
144 if (!strcmp(rel, flagtab[flags]))
148 pool_debug(pool, SAT_FATAL, "repo_content: unknown relation '%s'\n", rel);
151 id = rel2id(pool, id, str2id(pool, evr, 1), flags + 1, 1);
153 olddeps = repo_addid_dep(pd->repo, olddeps, id, marker);
160 * split value and add to pool
164 add_multiple_strings(Repodata *data, Id handle, Id name, char *value)
168 while ((str = splitword(&value)) != 0)
169 repodata_add_poolstr_array(data, handle, name, str);
173 * split value and add to pool
177 add_multiple_urls(Repodata *data, Id handle, char *value, Id type)
181 while ((url = splitword(&value)) != 0)
183 repodata_add_poolstr_array(data, handle, PRODUCT_URL, url);
184 repodata_add_idarray(data, handle, PRODUCT_URL_TYPE, type);
191 * add 'content' to repo
196 repo_add_content(Repo *repo, FILE *fp, int flags)
198 Pool *pool = repo->pool;
205 int contentstyle = 0;
212 we use the first architecture in BASEARCHS or noarch
213 for the product. At the end we create (clone) the product
214 for each one of the remaining architectures
217 unsigned int numotherarchs = 0;
220 if (!(flags & REPO_REUSE_REPODATA))
221 data = repo_add_repodata(repo, 0);
223 data = repo_last_repodata(repo);
225 memset(&pd, 0, sizeof(pd));
226 line = sat_malloc(1024);
230 /* use last repodata */
231 data = repo->repodata + repo->nrepodata - 1;
233 data = repo_add_repodata(repo, 0);
243 /* read line into big-enough buffer */
244 if (linep - line + 16 > aline)
246 aline = linep - line;
247 line = sat_realloc(line, aline + 512);
248 linep = line + aline;
251 if (!fgets(linep, aline - (linep - line), fp))
253 linep += strlen(linep);
254 if (linep == line || linep[-1] != '\n')
256 while ( --linep > line && ( linep[-1] == ' ' || linep[-1] == '\t' ) )
257 ; /* skip trailing ws */
261 /* expect "key value" lines */
263 key = splitword(&value);
268 fprintf (stderr, "key %s, value %s\n", key, value);
271 #define istag(x) (!strcmp (key, x))
272 #define code10 (contentstyle == 10)
273 #define code11 (contentstyle == 11)
275 if (istag ("CONTENTSTYLE"))
277 contentstyle = atoi(value);
283 if (istag ("DESCRDIR"))
288 repo_set_str(repo, SOLVID_META, SUSETAGS_DESCRDIR, value);
290 repo_set_str(repo, s - pool->solvables, SUSETAGS_DESCRDIR, value);
291 descrdir = strdup(value);
294 if (istag ("DATADIR"))
299 repo_set_str(repo, SOLVID_META, SUSETAGS_DATADIR, value);
301 repo_set_str(repo, s - pool->solvables, SUSETAGS_DATADIR, value);
302 datadir = strdup(value);
306 /* XXX: add those to SOLVID_META, too */
314 if ((code10 && istag ("PRODUCT"))
315 || (code11 && istag ("NAME")))
319 /* this solvable was created without seeing a
320 PRODUCT entry, just set the name and continue */
321 s->name = str2id(pool, join(&pd, "product", ":", value), 1);
326 /* finish old solvable */
328 s->arch = ARCH_NOARCH;
329 if (s->arch != ARCH_SRC && s->arch != ARCH_NOSRC)
330 s->provides = repo_addid_dep(repo, s->provides, rel2id(pool, s->name, s->evr, REL_EQ, 1), 0);
332 s->supplements = repo_fix_supplements(repo, s->provides, s->supplements, 0);
334 /* create new solvable */
335 s = pool_id2solvable(pool, repo_add_solvable(repo));
336 repodata_extend(data, s - pool->solvables);
337 handle = s - pool->solvables;
338 s->name = str2id(pool, join(&pd, "product", ":", value), 1);
340 repo_set_str(repo, s - pool->solvables, SUSETAGS_DATADIR, datadir);
342 repo_set_str(repo, s - pool->solvables, SUSETAGS_DESCRDIR, descrdir);
346 /* Sometimes PRODUCT/NAME is not the first entry, but we need a solvable
350 s = pool_id2solvable(pool, repo_add_solvable(repo));
351 repodata_extend(data, s - pool->solvables);
352 handle = s - pool->solvables;
355 if (istag ("VERSION"))
356 pd.tmpvers = strdup(value);
357 else if (istag ("RELEASE"))
358 pd.tmprel = strdup(value);
359 else if (code11 && istag ("DISTRIBUTION"))
360 repo_set_str(repo, s - pool->solvables, SOLVABLE_DISTRIBUTION, value);
361 else if (istag ("UPDATEURLS"))
362 add_multiple_urls(data, handle, value, str2id(pool, "update", 1));
363 else if (istag ("EXTRAURLS"))
364 add_multiple_urls(data, handle, value, str2id(pool, "extra", 1));
365 else if (istag ("OPTIONALURLS"))
366 add_multiple_urls(data, handle, value, str2id(pool, "optional", 1));
367 else if (istag ("RELNOTESURL"))
368 add_multiple_urls(data, handle, value, str2id(pool, "releasenotes", 1));
369 else if (istag ("SHORTLABEL"))
370 repo_set_str(repo, s - pool->solvables, PRODUCT_SHORTLABEL, value);
371 else if (istag ("LABEL")) /* LABEL is the products SUMMARY. */
372 repo_set_str(repo, s - pool->solvables, SOLVABLE_SUMMARY, value);
373 else if (!strncmp (key, "LABEL.", 6))
374 repo_set_str(repo, s - pool->solvables, pool_id2langid(pool, SOLVABLE_SUMMARY, key + 6, 1), value);
375 else if (istag ("FLAGS"))
376 add_multiple_strings(data, handle, PRODUCT_FLAGS, value);
377 else if (istag ("VENDOR"))
378 s->vendor = str2id(pool, value, 1);
379 else if (istag ("BASEARCHS"))
383 if ((arch = splitword(&value)) != 0)
385 s->arch = str2id(pool, arch, 1);
386 while ((arch = splitword(&value)) != 0)
388 otherarchs = sat_extend(otherarchs, numotherarchs, 1, sizeof(Id), 7);
389 otherarchs[numotherarchs++] = str2id(pool, arch, 1);
395 * Every tag below is Code10 only
399 else if (code10 && istag ("CONTENTSTYLE"))
400 /* CONTENTSTYLE must be first line */
401 pool_debug(pool, SAT_ERROR, "repo_content: 'CONTENTSTYLE' must be first line of 'content'\n");
402 else if (code10 && istag ("DISTPRODUCT"))
403 /* DISTPRODUCT is for registration and Yast, not for the solver. */
404 repo_set_str(repo, s - pool->solvables, PRODUCT_DISTPRODUCT, value);
405 else if (code10 && istag ("DISTVERSION"))
406 /* DISTVERSION is for registration and Yast, not for the solver. */
407 repo_set_str(repo, s - pool->solvables, PRODUCT_DISTVERSION, value);
408 else if (code10 && istag ("ARCH"))
409 /* Theoretically we want to have the best arch of the given
410 modifiers which still is compatible with the system
411 arch. We don't know the latter here, though. */
412 s->arch = ARCH_NOARCH;
413 else if (code10 && istag ("PREREQUIRES"))
414 s->requires = adddep(pool, &pd, s->requires, value, SOLVABLE_PREREQMARKER);
415 else if (code10 && istag ("REQUIRES"))
416 s->requires = adddep(pool, &pd, s->requires, value, -SOLVABLE_PREREQMARKER);
417 else if (code10 && istag ("PROVIDES"))
418 s->provides = adddep(pool, &pd, s->provides, value, 0);
419 else if (code10 && istag ("CONFLICTS"))
420 s->conflicts = adddep(pool, &pd, s->conflicts, value, 0);
421 else if (code10 && istag ("OBSOLETES"))
422 s->obsoletes = adddep(pool, &pd, s->obsoletes, value, 0);
423 else if (code10 && istag ("RECOMMENDS"))
424 s->recommends = adddep(pool, &pd, s->recommends, value, 0);
425 else if (code10 && istag ("SUGGESTS"))
426 s->suggests = adddep(pool, &pd, s->suggests, value, 0);
427 else if (code10 && istag ("SUPPLEMENTS"))
428 s->supplements = adddep(pool, &pd, s->supplements, value, 0);
429 else if (code10 && istag ("ENHANCES"))
430 s->enhances = adddep(pool, &pd, s->enhances, value, 0);
431 /* FRESHENS doesn't seem to exist. */
432 else if (code10 && istag ("TYPE"))
433 repo_set_str(repo, s - pool->solvables, PRODUCT_TYPE, value);
435 /* XXX do something about LINGUAS and ARCH?
436 * <ma>: Don't think so. zypp does not use or propagate them.
441 pool_debug(pool, SAT_ERROR, "repo_content: malformed line: %s\n", line);
451 pool_debug(pool, SAT_FATAL, "repo_content: 'content' incomplete, no product solvable created!\n");
458 s->evr = makeevr(pool, join2(pd.tmpvers, "-", pd.tmprel));
460 s->evr = makeevr(pool, pd.tmpvers);
464 s->evr = makeevr(pool, join2("", "-", pd.tmprel));
466 pd.tmpvers = sat_free((void *)pd.tmpvers);
467 pd.tmprel = sat_free((void *)pd.tmprel);
470 s->arch = ARCH_NOARCH;
471 if (s->arch != ARCH_SRC && s->arch != ARCH_NOSRC)
473 s->provides = repo_addid_dep(repo, s->provides, rel2id(pool, s->name, s->evr, REL_EQ, 1), 0);
475 s->supplements = repo_fix_supplements(repo, s->provides, s->supplements, 0);
478 /* now for every other arch, clone the product except the architecture */
479 for (i = 0; i < numotherarchs; ++i)
481 Solvable *p = pool_id2solvable(pool, repo_add_solvable(repo));
482 repodata_extend(data, p - pool->solvables);
485 p->vendor = s->vendor;
486 p->arch = otherarchs[i];
489 if (p->arch != ARCH_SRC && p->arch != ARCH_NOSRC)
490 p->provides = repo_addid_dep(repo, p->provides, rel2id(pool, p->name, p->evr, REL_EQ, 1), 0);
492 /* now merge the attributes */
493 repodata_merge_attrs(data, p - pool->solvables, s - pool->solvables);
499 sat_free(otherarchs);
501 if (!(flags & REPO_NO_INTERNALIZE))
502 repodata_internalize(data);