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;
219 we use the first architecture in BASEARCHS or noarch
220 for the product. At the end we create (clone) the product
221 for each one of the remaining architectures
224 unsigned int numotherarchs = 0;
227 memset(&pd, 0, sizeof(pd));
228 line = solv_malloc(1024);
235 data = repo_add_repodata(repo, flags);
241 /* read line into big-enough buffer */
242 if (linep - line + 16 > aline)
244 aline = linep - line;
245 line = solv_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')
254 while ( --linep > line && ( linep[-1] == ' ' || linep[-1] == '\t' ) )
255 ; /* skip trailing ws */
259 /* expect "key value" lines */
261 key = splitword(&value);
266 fprintf (stderr, "key %s, value %s\n", key, value);
269 #define istag(x) (!strcmp (key, x))
270 #define code10 (contentstyle == 10)
271 #define code11 (contentstyle == 11)
274 if (istag ("CONTENTSTYLE"))
277 pool_debug(pool, SOLV_ERROR, "repo_content: 'CONTENTSTYLE' must be first line of 'content'\n");
278 contentstyle = atoi(value);
284 /* repository tags */
285 /* we also replicate some of them into the product solvables
286 * to be backward compatible */
288 if (istag ("REPOID"))
290 repodata_add_poolstr_array(data, SOLVID_META, REPOSITORY_REPOID, value);
294 if (istag ("DESCRDIR"))
299 repodata_set_str(data, SOLVID_META, SUSETAGS_DESCRDIR, value);
301 repodata_set_str(data, s - pool->solvables, SUSETAGS_DESCRDIR, value);
302 descrdir = solv_strdup(value);
305 if (istag ("DATADIR"))
310 repodata_set_str(data, SOLVID_META, SUSETAGS_DATADIR, value);
312 repodata_set_str(data, s - pool->solvables, SUSETAGS_DATADIR, value);
313 datadir = solv_strdup(value);
316 if (istag ("VENDOR"))
321 repodata_set_poolstr(data, SOLVID_META, SUSETAGS_DEFAULTVENDOR, value);
323 s->vendor = pool_str2id(pool, value, 1);
324 defvendor = solv_strdup(value);
328 if (istag ("META") || istag ("HASH") || istag ("KEY"))
330 char *checksumtype, *checksum;
334 if ((checksumtype = splitword(&value)) == 0)
336 if ((checksum = splitword(&value)) == 0)
340 type = solv_chksum_str2type(checksumtype);
343 pool_error(pool, -1, "%s: unknown checksum type '%s'", value, checksumtype);
347 l = solv_chksum_len(type);
348 if (strlen(checksum) != 2 * l)
350 pool_error(pool, -1, "%s: invalid checksum length for %s", value, checksumtype);
354 fh = repodata_new_handle(data);
355 repodata_set_poolstr(data, fh, SUSETAGS_FILE_TYPE, key);
356 repodata_set_str(data, fh, SUSETAGS_FILE_NAME, value);
357 repodata_set_checksum(data, fh, SUSETAGS_FILE_CHECKSUM, type, checksum);
358 repodata_add_flexarray(data, SOLVID_META, SUSETAGS_FILE, fh);
364 if ((code10 && istag ("PRODUCT"))
365 || (code11 && istag ("NAME")))
369 /* this solvable was created without seeing a
370 PRODUCT entry, just set the name and continue */
371 s->name = pool_str2id(pool, join(&pd, "product", ":", value), 1);
376 /* finish old solvable */
378 s->arch = ARCH_NOARCH;
381 if (s->name && s->arch != ARCH_SRC && s->arch != ARCH_NOSRC)
382 s->provides = repo_addid_dep(repo, s->provides, pool_rel2id(pool, s->name, s->evr, REL_EQ, 1), 0);
384 s->supplements = repo_fix_supplements(repo, s->provides, s->supplements, 0);
386 /* create new solvable */
387 s = pool_id2solvable(pool, repo_add_solvable(repo));
388 repodata_extend(data, s - pool->solvables);
389 handle = s - pool->solvables;
390 s->name = pool_str2id(pool, join(&pd, "product", ":", value), 1);
392 repodata_set_str(data, s - pool->solvables, SUSETAGS_DATADIR, datadir);
394 repodata_set_str(data, s - pool->solvables, SUSETAGS_DESCRDIR, descrdir);
396 s->vendor = pool_str2id(pool, defvendor, 1);
400 /* Sometimes PRODUCT/NAME is not the first entry, but we need a solvable
404 s = pool_id2solvable(pool, repo_add_solvable(repo));
405 repodata_extend(data, s - pool->solvables);
406 handle = s - pool->solvables;
409 if (istag ("VERSION"))
410 pd.tmpvers = solv_strdup(value);
411 else if (istag ("RELEASE"))
412 pd.tmprel = solv_strdup(value);
413 else if (code11 && istag ("DISTRIBUTION"))
414 repodata_set_poolstr(data, s - pool->solvables, SOLVABLE_DISTRIBUTION, value);
415 else if (istag ("UPDATEURLS"))
416 add_multiple_urls(data, handle, value, pool_str2id(pool, "update", 1));
417 else if (istag ("EXTRAURLS"))
418 add_multiple_urls(data, handle, value, pool_str2id(pool, "extra", 1));
419 else if (istag ("OPTIONALURLS"))
420 add_multiple_urls(data, handle, value, pool_str2id(pool, "optional", 1));
421 else if (istag ("RELNOTESURL"))
422 add_multiple_urls(data, handle, value, pool_str2id(pool, "releasenotes", 1));
423 else if (istag ("SHORTLABEL"))
424 repodata_set_str(data, s - pool->solvables, PRODUCT_SHORTLABEL, value);
425 else if (istag ("LABEL")) /* LABEL is the products SUMMARY. */
426 repodata_set_str(data, s - pool->solvables, SOLVABLE_SUMMARY, value);
427 else if (!strncmp (key, "LABEL.", 6))
428 repodata_set_str(data, s - pool->solvables, pool_id2langid(pool, SOLVABLE_SUMMARY, key + 6, 1), value);
429 else if (istag ("FLAGS"))
430 add_multiple_strings(data, handle, PRODUCT_FLAGS, value);
431 else if (istag ("VENDOR")) /* actually already handled above */
432 s->vendor = pool_str2id(pool, value, 1);
433 else if (istag ("BASEARCHS"))
437 if ((arch = splitword(&value)) != 0)
439 s->arch = pool_str2id(pool, arch, 1);
440 while ((arch = splitword(&value)) != 0)
442 otherarchs = solv_extend(otherarchs, numotherarchs, 1, sizeof(Id), 7);
443 otherarchs[numotherarchs++] = pool_str2id(pool, arch, 1);
449 * Every tag below is Code10 only
453 if (code10 && istag ("DISTPRODUCT"))
454 /* DISTPRODUCT is for registration and Yast, not for the solver. */
455 repodata_set_str(data, s - pool->solvables, PRODUCT_DISTPRODUCT, value);
456 else if (code10 && istag ("DISTVERSION"))
457 /* DISTVERSION is for registration and Yast, not for the solver. */
458 repodata_set_str(data, s - pool->solvables, PRODUCT_DISTVERSION, value);
459 else if (code10 && istag ("ARCH"))
460 /* Theoretically we want to have the best arch of the given
461 modifiers which still is compatible with the system
462 arch. We don't know the latter here, though. */
463 s->arch = ARCH_NOARCH;
464 else if (code10 && istag ("PREREQUIRES"))
465 s->requires = adddep(pool, &pd, s->requires, value, SOLVABLE_PREREQMARKER);
466 else if (code10 && istag ("REQUIRES"))
467 s->requires = adddep(pool, &pd, s->requires, value, -SOLVABLE_PREREQMARKER);
468 else if (code10 && istag ("PROVIDES"))
469 s->provides = adddep(pool, &pd, s->provides, value, 0);
470 else if (code10 && istag ("CONFLICTS"))
471 s->conflicts = adddep(pool, &pd, s->conflicts, value, 0);
472 else if (code10 && istag ("OBSOLETES"))
473 s->obsoletes = adddep(pool, &pd, s->obsoletes, value, 0);
474 else if (code10 && istag ("RECOMMENDS"))
475 s->recommends = adddep(pool, &pd, s->recommends, value, 0);
476 else if (code10 && istag ("SUGGESTS"))
477 s->suggests = adddep(pool, &pd, s->suggests, value, 0);
478 else if (code10 && istag ("SUPPLEMENTS"))
479 s->supplements = adddep(pool, &pd, s->supplements, value, 0);
480 else if (code10 && istag ("ENHANCES"))
481 s->enhances = adddep(pool, &pd, s->enhances, value, 0);
482 /* FRESHENS doesn't seem to exist. */
483 else if (code10 && istag ("TYPE"))
484 repodata_set_str(data, s - pool->solvables, PRODUCT_TYPE, value);
486 /* XXX do something about LINGUAS and ARCH?
487 * <ma>: Don't think so. zypp does not use or propagate them.
492 pool_debug(pool, SOLV_ERROR, "repo_content: malformed line: %s\n", line);
504 pool_debug(pool, SOLV_FATAL, "repo_content: 'content' incomplete, no product solvable created!\n");
505 repo_free_solvable(repo, s - pool->solvables, 1);
511 s->evr = makeevr(pool, join(&pd, pd.tmpvers, "-", pd.tmprel));
513 s->evr = makeevr(pool, pd.tmpvers);
514 pd.tmpvers = solv_free((void *)pd.tmpvers);
515 pd.tmprel = solv_free((void *)pd.tmprel);
518 s->arch = ARCH_NOARCH;
521 if (s->name && s->arch != ARCH_SRC && s->arch != ARCH_NOSRC)
522 s->provides = repo_addid_dep(repo, s->provides, pool_rel2id(pool, s->name, s->evr, REL_EQ, 1), 0);
524 s->supplements = repo_fix_supplements(repo, s->provides, s->supplements, 0);
526 /* now for every other arch, clone the product except the architecture */
527 for (i = 0; i < numotherarchs; ++i)
529 Solvable *p = pool_id2solvable(pool, repo_add_solvable(repo));
530 repodata_extend(data, p - pool->solvables);
533 p->vendor = s->vendor;
534 p->arch = otherarchs[i];
537 if (s->name && p->arch != ARCH_SRC && p->arch != ARCH_NOSRC)
538 p->provides = repo_addid_dep(repo, p->provides, pool_rel2id(pool, p->name, p->evr, REL_EQ, 1), 0);
540 /* now merge the attributes */
541 repodata_merge_attrs(data, p - pool->solvables, s - pool->solvables);
548 solv_free(otherarchs);
549 if (!(flags & REPO_NO_INTERNALIZE))
550 repodata_internalize(data);