4 * Parses 'content' file into .solv
5 * A 'content' file is the repomd.xml of the susetags format
7 * See http://en.opensuse.org/Standards/YaST2_Repository_Metadata/content for a description
11 * Copyright (c) 2007, Novell Inc.
13 * This program is licensed under the BSD license, read LICENSE.BSD
14 * for further information
17 #include <sys/types.h>
29 #include "repo_content.h"
32 #include "tools_util.h"
34 /* split off a word, return null terminated pointer to it.
35 * return NULL if there is no word left. */
41 while (*l == ' ' || *l == '\t')
44 while (*l && *l != ' ' && *l != '\t')
47 *l++ = 0; /* terminate word */
48 while (*l == ' ' || *l == '\t')
49 l++; /* convenience: advance to next word */
64 * dependency relations
67 static char *flagtab[] = {
78 * join up to three strings into one
82 join(struct parsedata *pd, const char *s1, const char *s2, const char *s3)
96 pd->tmp = solv_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 = pool_str2id(pool, name, 1);
137 if (*line == '<' || *line == '>' || *line == '=') /* rel follows */
139 char *rel = splitword(&line);
140 char *evr = splitword(&line);
145 pool_debug(pool, SOLV_FATAL, "repo_content: bad relation '%s %s'\n", name, rel);
148 for (flags = 0; flags < 6; flags++)
149 if (!strcmp(rel, flagtab[flags]))
153 pool_debug(pool, SOLV_FATAL, "repo_content: unknown relation '%s'\n", rel);
156 id = pool_rel2id(pool, id, pool_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;
218 we use the first architecture in BASEARCHS or noarch
219 for the product. At the end we create (clone) the product
220 for each one of the remaining architectures
223 unsigned int numotherarchs = 0;
226 memset(&pd, 0, sizeof(pd));
227 line = solv_malloc(1024);
234 data = repo_add_repodata(repo, flags);
240 /* read line into big-enough buffer */
241 if (linep - line + 16 > aline)
243 aline = linep - line;
244 line = solv_realloc(line, aline + 512);
245 linep = line + aline;
248 if (!fgets(linep, aline - (linep - line), fp))
250 linep += strlen(linep);
251 if (linep == line || linep[-1] != '\n')
253 while ( --linep > line && ( linep[-1] == ' ' || linep[-1] == '\t' ) )
254 ; /* skip trailing ws */
258 /* expect "key value" lines */
260 key = splitword(&value);
265 fprintf (stderr, "key %s, value %s\n", key, value);
268 #define istag(x) (!strcmp (key, x))
269 #define code10 (contentstyle == 10)
270 #define code11 (contentstyle == 11)
273 if (istag ("CONTENTSTYLE"))
276 pool_debug(pool, SOLV_ERROR, "repo_content: 'CONTENTSTYLE' must be first line of 'content'\n");
277 contentstyle = atoi(value);
283 /* repository tags */
284 /* we also replicate some of them into the product solvables
285 * to be backward compatible */
287 if (istag ("REPOID"))
289 repodata_add_poolstr_array(data, SOLVID_META, REPOSITORY_REPOID, value);
293 if (istag ("DESCRDIR"))
298 repodata_set_str(data, SOLVID_META, SUSETAGS_DESCRDIR, value);
300 repodata_set_str(data, s - pool->solvables, SUSETAGS_DESCRDIR, value);
301 descrdir = solv_strdup(value);
304 if (istag ("DATADIR"))
309 repodata_set_str(data, SOLVID_META, SUSETAGS_DATADIR, value);
311 repodata_set_str(data, s - pool->solvables, SUSETAGS_DATADIR, value);
312 datadir = solv_strdup(value);
315 if (istag ("VENDOR"))
320 repodata_set_poolstr(data, SOLVID_META, SUSETAGS_DEFAULTVENDOR, value);
322 s->vendor = pool_str2id(pool, value, 1);
323 defvendor = solv_strdup(value);
327 if (istag ("META") || istag ("HASH") || istag ("KEY"))
329 char *checksumtype, *checksum;
333 if ((checksumtype = splitword(&value)) == 0)
335 if ((checksum = splitword(&value)) == 0)
339 type = solv_chksum_str2type(checksumtype);
342 fprintf(stderr, "Unknown checksum type: %s: %s\n", value, checksumtype);
345 l = solv_chksum_len(type);
346 if (strlen(checksum) != 2 * l)
348 fprintf(stderr, "Invalid checksum length: %s: for %s\n", value, checksum);
351 fh = repodata_new_handle(data);
352 repodata_set_poolstr(data, fh, SUSETAGS_FILE_TYPE, key);
353 repodata_set_str(data, fh, SUSETAGS_FILE_NAME, value);
354 repodata_set_checksum(data, fh, SUSETAGS_FILE_CHECKSUM, type, checksum);
355 repodata_add_flexarray(data, SOLVID_META, SUSETAGS_FILE, fh);
361 if ((code10 && istag ("PRODUCT"))
362 || (code11 && istag ("NAME")))
366 /* this solvable was created without seeing a
367 PRODUCT entry, just set the name and continue */
368 s->name = pool_str2id(pool, join(&pd, "product", ":", value), 1);
373 /* finish old solvable */
375 s->arch = ARCH_NOARCH;
378 if (s->name && s->arch != ARCH_SRC && s->arch != ARCH_NOSRC)
379 s->provides = repo_addid_dep(repo, s->provides, pool_rel2id(pool, s->name, s->evr, REL_EQ, 1), 0);
381 s->supplements = repo_fix_supplements(repo, s->provides, s->supplements, 0);
383 /* create new solvable */
384 s = pool_id2solvable(pool, repo_add_solvable(repo));
385 repodata_extend(data, s - pool->solvables);
386 handle = s - pool->solvables;
387 s->name = pool_str2id(pool, join(&pd, "product", ":", value), 1);
389 repodata_set_str(data, s - pool->solvables, SUSETAGS_DATADIR, datadir);
391 repodata_set_str(data, s - pool->solvables, SUSETAGS_DESCRDIR, descrdir);
393 s->vendor = pool_str2id(pool, defvendor, 1);
397 /* Sometimes PRODUCT/NAME is not the first entry, but we need a solvable
401 s = pool_id2solvable(pool, repo_add_solvable(repo));
402 repodata_extend(data, s - pool->solvables);
403 handle = s - pool->solvables;
406 if (istag ("VERSION"))
407 pd.tmpvers = solv_strdup(value);
408 else if (istag ("RELEASE"))
409 pd.tmprel = solv_strdup(value);
410 else if (code11 && istag ("DISTRIBUTION"))
411 repodata_set_poolstr(data, s - pool->solvables, SOLVABLE_DISTRIBUTION, value);
412 else if (istag ("UPDATEURLS"))
413 add_multiple_urls(data, handle, value, pool_str2id(pool, "update", 1));
414 else if (istag ("EXTRAURLS"))
415 add_multiple_urls(data, handle, value, pool_str2id(pool, "extra", 1));
416 else if (istag ("OPTIONALURLS"))
417 add_multiple_urls(data, handle, value, pool_str2id(pool, "optional", 1));
418 else if (istag ("RELNOTESURL"))
419 add_multiple_urls(data, handle, value, pool_str2id(pool, "releasenotes", 1));
420 else if (istag ("SHORTLABEL"))
421 repodata_set_str(data, s - pool->solvables, PRODUCT_SHORTLABEL, value);
422 else if (istag ("LABEL")) /* LABEL is the products SUMMARY. */
423 repodata_set_str(data, s - pool->solvables, SOLVABLE_SUMMARY, value);
424 else if (!strncmp (key, "LABEL.", 6))
425 repodata_set_str(data, s - pool->solvables, pool_id2langid(pool, SOLVABLE_SUMMARY, key + 6, 1), value);
426 else if (istag ("FLAGS"))
427 add_multiple_strings(data, handle, PRODUCT_FLAGS, value);
428 else if (istag ("VENDOR")) /* actually already handled above */
429 s->vendor = pool_str2id(pool, value, 1);
430 else if (istag ("BASEARCHS"))
434 if ((arch = splitword(&value)) != 0)
436 s->arch = pool_str2id(pool, arch, 1);
437 while ((arch = splitword(&value)) != 0)
439 otherarchs = solv_extend(otherarchs, numotherarchs, 1, sizeof(Id), 7);
440 otherarchs[numotherarchs++] = pool_str2id(pool, arch, 1);
446 * Every tag below is Code10 only
450 if (code10 && istag ("DISTPRODUCT"))
451 /* DISTPRODUCT is for registration and Yast, not for the solver. */
452 repodata_set_str(data, s - pool->solvables, PRODUCT_DISTPRODUCT, value);
453 else if (code10 && istag ("DISTVERSION"))
454 /* DISTVERSION is for registration and Yast, not for the solver. */
455 repodata_set_str(data, s - pool->solvables, PRODUCT_DISTVERSION, value);
456 else if (code10 && istag ("ARCH"))
457 /* Theoretically we want to have the best arch of the given
458 modifiers which still is compatible with the system
459 arch. We don't know the latter here, though. */
460 s->arch = ARCH_NOARCH;
461 else if (code10 && istag ("PREREQUIRES"))
462 s->requires = adddep(pool, &pd, s->requires, value, SOLVABLE_PREREQMARKER);
463 else if (code10 && istag ("REQUIRES"))
464 s->requires = adddep(pool, &pd, s->requires, value, -SOLVABLE_PREREQMARKER);
465 else if (code10 && istag ("PROVIDES"))
466 s->provides = adddep(pool, &pd, s->provides, value, 0);
467 else if (code10 && istag ("CONFLICTS"))
468 s->conflicts = adddep(pool, &pd, s->conflicts, value, 0);
469 else if (code10 && istag ("OBSOLETES"))
470 s->obsoletes = adddep(pool, &pd, s->obsoletes, value, 0);
471 else if (code10 && istag ("RECOMMENDS"))
472 s->recommends = adddep(pool, &pd, s->recommends, value, 0);
473 else if (code10 && istag ("SUGGESTS"))
474 s->suggests = adddep(pool, &pd, s->suggests, value, 0);
475 else if (code10 && istag ("SUPPLEMENTS"))
476 s->supplements = adddep(pool, &pd, s->supplements, value, 0);
477 else if (code10 && istag ("ENHANCES"))
478 s->enhances = adddep(pool, &pd, s->enhances, value, 0);
479 /* FRESHENS doesn't seem to exist. */
480 else if (code10 && istag ("TYPE"))
481 repodata_set_str(data, s - pool->solvables, PRODUCT_TYPE, value);
483 /* XXX do something about LINGUAS and ARCH?
484 * <ma>: Don't think so. zypp does not use or propagate them.
489 pool_debug(pool, SOLV_ERROR, "repo_content: malformed line: %s\n", line);
501 pool_debug(pool, SOLV_FATAL, "repo_content: 'content' incomplete, no product solvable created!\n");
502 repo_free_solvable(repo, s - pool->solvables, 1);
508 s->evr = makeevr(pool, join(&pd, pd.tmpvers, "-", pd.tmprel));
510 s->evr = makeevr(pool, pd.tmpvers);
511 pd.tmpvers = solv_free((void *)pd.tmpvers);
512 pd.tmprel = solv_free((void *)pd.tmprel);
515 s->arch = ARCH_NOARCH;
518 if (s->name && s->arch != ARCH_SRC && s->arch != ARCH_NOSRC)
519 s->provides = repo_addid_dep(repo, s->provides, pool_rel2id(pool, s->name, s->evr, REL_EQ, 1), 0);
521 s->supplements = repo_fix_supplements(repo, s->provides, s->supplements, 0);
523 /* now for every other arch, clone the product except the architecture */
524 for (i = 0; i < numotherarchs; ++i)
526 Solvable *p = pool_id2solvable(pool, repo_add_solvable(repo));
527 repodata_extend(data, p - pool->solvables);
530 p->vendor = s->vendor;
531 p->arch = otherarchs[i];
534 if (s->name && p->arch != ARCH_SRC && p->arch != ARCH_NOSRC)
535 p->provides = repo_addid_dep(repo, p->provides, pool_rel2id(pool, p->name, p->evr, REL_EQ, 1), 0);
537 /* now merge the attributes */
538 repodata_merge_attrs(data, p - pool->solvables, s - pool->solvables);
545 solv_free(otherarchs);
546 if (!(flags & REPO_NO_INTERNALIZE))
547 repodata_internalize(data);