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"
31 #include "tools_util.h"
33 /* split off a word, return null terminated pointer to it.
34 * return NULL if there is no word left. */
40 while (*l == ' ' || *l == '\t')
43 while (*l && *l != ' ' && *l != '\t')
46 *l++ = 0; /* terminate word */
47 while (*l == ' ' || *l == '\t')
48 l++; /* convenience: advance to next word */
63 * dependency relations
66 static char *flagtab[] = {
77 * join up to three strings into one
81 join(struct parsedata *pd, const char *s1, const char *s2, const char *s3)
95 pd->tmp = sat_realloc(pd->tmp, pd->tmpl);
119 * add dependency to pool
120 * OBSOLETES product:SUSE_LINUX product:openSUSE < 11.0 package:openSUSE < 11.0
124 adddep(Pool *pool, struct parsedata *pd, unsigned int olddeps, char *line, Id marker)
129 while ((name = splitword(&line)) != 0)
131 /* Hack, as the content file adds 'package:' for package
132 dependencies sometimes. */
133 if (!strncmp (name, "package:", 8))
135 id = str2id(pool, name, 1);
136 if (*line == '<' || *line == '>' || *line == '=') /* rel follows */
138 char *rel = splitword(&line);
139 char *evr = splitword(&line);
144 pool_debug(pool, SAT_FATAL, "repo_content: bad relation '%s %s'\n", name, rel);
147 for (flags = 0; flags < 6; flags++)
148 if (!strcmp(rel, flagtab[flags]))
152 pool_debug(pool, SAT_FATAL, "repo_content: unknown relation '%s'\n", rel);
155 id = rel2id(pool, id, str2id(pool, evr, 1), flags + 1, 1);
157 olddeps = repo_addid_dep(pd->repo, olddeps, id, marker);
164 * split value and add to pool
168 add_multiple_strings(Repodata *data, Id handle, Id name, char *value)
172 while ((str = splitword(&value)) != 0)
173 repodata_add_poolstr_array(data, handle, name, str);
177 * split value and add to pool
181 add_multiple_urls(Repodata *data, Id handle, char *value, Id type)
185 while ((url = splitword(&value)) != 0)
187 repodata_add_poolstr_array(data, handle, PRODUCT_URL, url);
188 repodata_add_idarray(data, handle, PRODUCT_URL_TYPE, type);
195 * add 'content' to repo
200 repo_add_content(Repo *repo, FILE *fp, int flags)
202 Pool *pool = repo->pool;
209 int contentstyle = 0;
217 we use the first architecture in BASEARCHS or noarch
218 for the product. At the end we create (clone) the product
219 for each one of the remaining architectures
222 unsigned int numotherarchs = 0;
225 memset(&pd, 0, sizeof(pd));
226 line = sat_malloc(1024);
233 data = repo_add_repodata(repo, flags);
239 /* read line into big-enough buffer */
240 if (linep - line + 16 > aline)
242 aline = linep - line;
243 line = sat_realloc(line, aline + 512);
244 linep = line + aline;
247 if (!fgets(linep, aline - (linep - line), fp))
249 linep += strlen(linep);
250 if (linep == line || linep[-1] != '\n')
252 while ( --linep > line && ( linep[-1] == ' ' || linep[-1] == '\t' ) )
253 ; /* skip trailing ws */
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)
272 if (istag ("CONTENTSTYLE"))
275 pool_debug(pool, SAT_ERROR, "repo_content: 'CONTENTSTYLE' must be first line of 'content'\n");
276 contentstyle = atoi(value);
282 /* repository tags */
283 /* we also replicate some of them into the product solvables
284 * to be backward compatible */
286 if (istag ("REPOID"))
288 repodata_add_poolstr_array(data, SOLVID_META, REPOSITORY_REPOID, value);
292 if (istag ("DESCRDIR"))
297 repodata_set_str(data, SOLVID_META, SUSETAGS_DESCRDIR, value);
299 repodata_set_str(data, s - pool->solvables, SUSETAGS_DESCRDIR, value);
300 descrdir = strdup(value);
303 if (istag ("DATADIR"))
308 repodata_set_str(data, SOLVID_META, SUSETAGS_DATADIR, value);
310 repodata_set_str(data, s - pool->solvables, SUSETAGS_DATADIR, value);
311 datadir = strdup(value);
314 if (istag ("VENDOR"))
319 repodata_set_poolstr(data, SOLVID_META, SUSETAGS_DEFAULTVENDOR, value);
321 s->vendor = str2id(pool, value, 1);
322 defvendor = strdup(value);
326 if (istag ("META") || istag ("HASH") || istag ("KEY"))
328 char *checksumtype, *checksum;
332 if ((checksumtype = splitword(&value)) == 0)
334 if ((checksum = splitword(&value)) == 0)
338 type = sat_chksum_str2type(checksumtype);
341 fprintf(stderr, "Unknown checksum type: %s: %s\n", value, checksumtype);
344 l = sat_chksum_len(type);
345 if (strlen(checksum) != 2 * l)
347 fprintf(stderr, "Invalid checksum length: %s: for %s\n", value, checksum);
350 fh = repodata_new_handle(data);
351 repodata_set_poolstr(data, fh, SUSETAGS_FILE_TYPE, key);
352 repodata_set_str(data, fh, SUSETAGS_FILE_NAME, value);
353 repodata_set_checksum(data, fh, SUSETAGS_FILE_CHECKSUM, type, checksum);
354 repodata_add_flexarray(data, SOLVID_META, SUSETAGS_FILE, fh);
360 if ((code10 && istag ("PRODUCT"))
361 || (code11 && istag ("NAME")))
365 /* this solvable was created without seeing a
366 PRODUCT entry, just set the name and continue */
367 s->name = str2id(pool, join(&pd, "product", ":", value), 1);
372 /* finish old solvable */
374 s->arch = ARCH_NOARCH;
377 if (s->name && s->arch != ARCH_SRC && s->arch != ARCH_NOSRC)
378 s->provides = repo_addid_dep(repo, s->provides, rel2id(pool, s->name, s->evr, REL_EQ, 1), 0);
380 s->supplements = repo_fix_supplements(repo, s->provides, s->supplements, 0);
382 /* create new solvable */
383 s = pool_id2solvable(pool, repo_add_solvable(repo));
384 repodata_extend(data, s - pool->solvables);
385 handle = s - pool->solvables;
386 s->name = str2id(pool, join(&pd, "product", ":", value), 1);
388 repodata_set_str(data, s - pool->solvables, SUSETAGS_DATADIR, datadir);
390 repodata_set_str(data, s - pool->solvables, SUSETAGS_DESCRDIR, descrdir);
392 s->vendor = str2id(pool, defvendor, 1);
396 /* Sometimes PRODUCT/NAME is not the first entry, but we need a solvable
400 s = pool_id2solvable(pool, repo_add_solvable(repo));
401 repodata_extend(data, s - pool->solvables);
402 handle = s - pool->solvables;
405 if (istag ("VERSION"))
406 pd.tmpvers = strdup(value);
407 else if (istag ("RELEASE"))
408 pd.tmprel = strdup(value);
409 else if (code11 && istag ("DISTRIBUTION"))
410 repodata_set_str(data, s - pool->solvables, SOLVABLE_DISTRIBUTION, value);
411 else if (istag ("UPDATEURLS"))
412 add_multiple_urls(data, handle, value, str2id(pool, "update", 1));
413 else if (istag ("EXTRAURLS"))
414 add_multiple_urls(data, handle, value, str2id(pool, "extra", 1));
415 else if (istag ("OPTIONALURLS"))
416 add_multiple_urls(data, handle, value, str2id(pool, "optional", 1));
417 else if (istag ("RELNOTESURL"))
418 add_multiple_urls(data, handle, value, str2id(pool, "releasenotes", 1));
419 else if (istag ("SHORTLABEL"))
420 repodata_set_str(data, s - pool->solvables, PRODUCT_SHORTLABEL, value);
421 else if (istag ("LABEL")) /* LABEL is the products SUMMARY. */
422 repodata_set_str(data, s - pool->solvables, SOLVABLE_SUMMARY, value);
423 else if (!strncmp (key, "LABEL.", 6))
424 repodata_set_str(data, s - pool->solvables, pool_id2langid(pool, SOLVABLE_SUMMARY, key + 6, 1), value);
425 else if (istag ("FLAGS"))
426 add_multiple_strings(data, handle, PRODUCT_FLAGS, value);
427 else if (istag ("VENDOR")) /* actually already handled above */
428 s->vendor = str2id(pool, value, 1);
429 else if (istag ("BASEARCHS"))
433 if ((arch = splitword(&value)) != 0)
435 s->arch = str2id(pool, arch, 1);
436 while ((arch = splitword(&value)) != 0)
438 otherarchs = sat_extend(otherarchs, numotherarchs, 1, sizeof(Id), 7);
439 otherarchs[numotherarchs++] = str2id(pool, arch, 1);
445 * Every tag below is Code10 only
449 if (code10 && istag ("DISTPRODUCT"))
450 /* DISTPRODUCT is for registration and Yast, not for the solver. */
451 repodata_set_str(data, s - pool->solvables, PRODUCT_DISTPRODUCT, value);
452 else if (code10 && istag ("DISTVERSION"))
453 /* DISTVERSION is for registration and Yast, not for the solver. */
454 repodata_set_str(data, s - pool->solvables, PRODUCT_DISTVERSION, value);
455 else if (code10 && istag ("ARCH"))
456 /* Theoretically we want to have the best arch of the given
457 modifiers which still is compatible with the system
458 arch. We don't know the latter here, though. */
459 s->arch = ARCH_NOARCH;
460 else if (code10 && istag ("PREREQUIRES"))
461 s->requires = adddep(pool, &pd, s->requires, value, SOLVABLE_PREREQMARKER);
462 else if (code10 && istag ("REQUIRES"))
463 s->requires = adddep(pool, &pd, s->requires, value, -SOLVABLE_PREREQMARKER);
464 else if (code10 && istag ("PROVIDES"))
465 s->provides = adddep(pool, &pd, s->provides, value, 0);
466 else if (code10 && istag ("CONFLICTS"))
467 s->conflicts = adddep(pool, &pd, s->conflicts, value, 0);
468 else if (code10 && istag ("OBSOLETES"))
469 s->obsoletes = adddep(pool, &pd, s->obsoletes, value, 0);
470 else if (code10 && istag ("RECOMMENDS"))
471 s->recommends = adddep(pool, &pd, s->recommends, value, 0);
472 else if (code10 && istag ("SUGGESTS"))
473 s->suggests = adddep(pool, &pd, s->suggests, value, 0);
474 else if (code10 && istag ("SUPPLEMENTS"))
475 s->supplements = adddep(pool, &pd, s->supplements, value, 0);
476 else if (code10 && istag ("ENHANCES"))
477 s->enhances = adddep(pool, &pd, s->enhances, value, 0);
478 /* FRESHENS doesn't seem to exist. */
479 else if (code10 && istag ("TYPE"))
480 repodata_set_str(data, s - pool->solvables, PRODUCT_TYPE, value);
482 /* XXX do something about LINGUAS and ARCH?
483 * <ma>: Don't think so. zypp does not use or propagate them.
488 pool_debug(pool, SAT_ERROR, "repo_content: malformed line: %s\n", line);
500 pool_debug(pool, SAT_FATAL, "repo_content: 'content' incomplete, no product solvable created!\n");
501 repo_free_solvable_block(repo, s - pool->solvables, 1, 1);
507 s->evr = makeevr(pool, join(&pd, pd.tmpvers, "-", pd.tmprel));
509 s->evr = makeevr(pool, pd.tmpvers);
510 pd.tmpvers = sat_free((void *)pd.tmpvers);
511 pd.tmprel = sat_free((void *)pd.tmprel);
514 s->arch = ARCH_NOARCH;
517 if (s->name && s->arch != ARCH_SRC && s->arch != ARCH_NOSRC)
518 s->provides = repo_addid_dep(repo, s->provides, rel2id(pool, s->name, s->evr, REL_EQ, 1), 0);
520 s->supplements = repo_fix_supplements(repo, s->provides, s->supplements, 0);
522 /* now for every other arch, clone the product except the architecture */
523 for (i = 0; i < numotherarchs; ++i)
525 Solvable *p = pool_id2solvable(pool, repo_add_solvable(repo));
526 repodata_extend(data, p - pool->solvables);
529 p->vendor = s->vendor;
530 p->arch = otherarchs[i];
533 if (s->name && p->arch != ARCH_SRC && p->arch != ARCH_NOSRC)
534 p->provides = repo_addid_dep(repo, p->provides, rel2id(pool, p->name, p->evr, REL_EQ, 1), 0);
536 /* now merge the attributes */
537 repodata_merge_attrs(data, p - pool->solvables, s - pool->solvables);
544 sat_free(otherarchs);
546 if (!(flags & REPO_NO_INTERNALIZE))
547 repodata_internalize(data);