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;
213 we use the first architecture in BASEARCHS or noarch
214 for the product. At the end we create (clone) the product
215 for each one of the remaining architectures
218 unsigned int numotherarchs = 0;
221 if (!(flags & REPO_REUSE_REPODATA))
222 data = repo_add_repodata(repo, 0);
224 data = repo_last_repodata(repo);
226 memset(&pd, 0, sizeof(pd));
227 line = sat_malloc(1024);
231 /* use last repodata */
232 data = repo->repodata + repo->nrepodata - 1;
234 data = repo_add_repodata(repo, 0);
244 /* read line into big-enough buffer */
245 if (linep - line + 16 > aline)
247 aline = linep - line;
248 line = sat_realloc(line, aline + 512);
249 linep = line + aline;
252 if (!fgets(linep, aline - (linep - line), fp))
254 linep += strlen(linep);
255 if (linep == line || linep[-1] != '\n')
257 while ( --linep > line && ( linep[-1] == ' ' || linep[-1] == '\t' ) )
258 ; /* skip trailing ws */
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)
277 if (istag ("CONTENTSTYLE"))
280 pool_debug(pool, SAT_ERROR, "repo_content: 'CONTENTSTYLE' must be first line of 'content'\n");
281 contentstyle = atoi(value);
287 /* repository tags */
288 /* we also replicate some of them into the product solvables
289 * to be backward compatible */
291 if (istag ("DESCRDIR"))
296 repo_set_str(repo, SOLVID_META, SUSETAGS_DESCRDIR, value);
298 repo_set_str(repo, s - pool->solvables, SUSETAGS_DESCRDIR, value);
299 descrdir = strdup(value);
302 if (istag ("DATADIR"))
307 repo_set_str(repo, SOLVID_META, SUSETAGS_DATADIR, value);
309 repo_set_str(repo, s - pool->solvables, SUSETAGS_DATADIR, value);
310 datadir = strdup(value);
313 if (istag ("VENDOR"))
318 repo_set_poolstr(repo, SOLVID_META, SUSETAGS_DEFAULTVENDOR, value);
320 s->vendor = str2id(pool, value, 1);
321 defvendor = strdup(value);
325 if (istag ("META") || istag ("HASH") || istag ("KEY"))
327 char *checksumtype, *checksum;
331 if ((checksumtype = splitword(&value)) == 0)
333 if ((checksum = splitword(&value)) == 0)
337 if (!strcasecmp(checksumtype, "sha") || !strcasecmp(checksumtype, "sha1"))
338 l = SIZEOF_SHA1 * 2, type = REPOKEY_TYPE_SHA1;
339 else if (!strcasecmp(checksumtype, "sha256"))
340 l = SIZEOF_SHA256 * 2, type = REPOKEY_TYPE_SHA256;
341 else if (!strcasecmp(checksumtype, "md5"))
342 l = SIZEOF_MD5 * 2, type = REPOKEY_TYPE_MD5;
345 fprintf(stderr, "Unknown checksum type: %s: %s\n", value, checksumtype);
348 if (strlen(checksum) != l)
350 fprintf(stderr, "Invalid checksum length: %s: for %s\n", value, checksum);
353 fh = repodata_new_handle(data);
354 repodata_set_poolstr(data, fh, SUSETAGS_FILE_TYPE, key);
355 repodata_set_str(data, fh, SUSETAGS_FILE_NAME, value);
356 repodata_set_checksum(data, fh, SUSETAGS_FILE_CHECKSUM, type, checksum);
357 repodata_add_flexarray(data, SOLVID_META, SUSETAGS_FILE, fh);
363 if ((code10 && istag ("PRODUCT"))
364 || (code11 && istag ("NAME")))
368 /* this solvable was created without seeing a
369 PRODUCT entry, just set the name and continue */
370 s->name = str2id(pool, join(&pd, "product", ":", value), 1);
375 /* finish old solvable */
377 s->arch = ARCH_NOARCH;
378 if (s->arch != ARCH_SRC && s->arch != ARCH_NOSRC)
379 s->provides = repo_addid_dep(repo, s->provides, 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 = str2id(pool, join(&pd, "product", ":", value), 1);
389 repo_set_str(repo, s - pool->solvables, SUSETAGS_DATADIR, datadir);
391 repo_set_str(repo, s - pool->solvables, SUSETAGS_DESCRDIR, descrdir);
393 s->vendor = 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 = strdup(value);
408 else if (istag ("RELEASE"))
409 pd.tmprel = strdup(value);
410 else if (code11 && istag ("DISTRIBUTION"))
411 repo_set_str(repo, s - pool->solvables, SOLVABLE_DISTRIBUTION, value);
412 else if (istag ("UPDATEURLS"))
413 add_multiple_urls(data, handle, value, str2id(pool, "update", 1));
414 else if (istag ("EXTRAURLS"))
415 add_multiple_urls(data, handle, value, str2id(pool, "extra", 1));
416 else if (istag ("OPTIONALURLS"))
417 add_multiple_urls(data, handle, value, str2id(pool, "optional", 1));
418 else if (istag ("RELNOTESURL"))
419 add_multiple_urls(data, handle, value, str2id(pool, "releasenotes", 1));
420 else if (istag ("SHORTLABEL"))
421 repo_set_str(repo, s - pool->solvables, PRODUCT_SHORTLABEL, value);
422 else if (istag ("LABEL")) /* LABEL is the products SUMMARY. */
423 repo_set_str(repo, s - pool->solvables, SOLVABLE_SUMMARY, value);
424 else if (!strncmp (key, "LABEL.", 6))
425 repo_set_str(repo, 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 = str2id(pool, value, 1);
430 else if (istag ("BASEARCHS"))
434 if ((arch = splitword(&value)) != 0)
436 s->arch = str2id(pool, arch, 1);
437 while ((arch = splitword(&value)) != 0)
439 otherarchs = sat_extend(otherarchs, numotherarchs, 1, sizeof(Id), 7);
440 otherarchs[numotherarchs++] = 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 repo_set_str(repo, s - pool->solvables, PRODUCT_DISTPRODUCT, value);
453 else if (code10 && istag ("DISTVERSION"))
454 /* DISTVERSION is for registration and Yast, not for the solver. */
455 repo_set_str(repo, 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 repo_set_str(repo, 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, SAT_ERROR, "repo_content: malformed line: %s\n", line);
501 pool_debug(pool, SAT_FATAL, "repo_content: 'content' incomplete, no product solvable created!\n");
508 s->evr = makeevr(pool, join2(pd.tmpvers, "-", pd.tmprel));
510 s->evr = makeevr(pool, pd.tmpvers);
514 s->evr = makeevr(pool, join2("", "-", pd.tmprel));
516 pd.tmpvers = sat_free((void *)pd.tmpvers);
517 pd.tmprel = sat_free((void *)pd.tmprel);
520 s->arch = ARCH_NOARCH;
521 if (s->arch != ARCH_SRC && s->arch != ARCH_NOSRC)
523 s->provides = repo_addid_dep(repo, s->provides, rel2id(pool, s->name, s->evr, REL_EQ, 1), 0);
525 s->supplements = repo_fix_supplements(repo, s->provides, s->supplements, 0);
528 /* now for every other arch, clone the product except the architecture */
529 for (i = 0; i < numotherarchs; ++i)
531 Solvable *p = pool_id2solvable(pool, repo_add_solvable(repo));
532 repodata_extend(data, p - pool->solvables);
535 p->vendor = s->vendor;
536 p->arch = otherarchs[i];
539 if (p->arch != ARCH_SRC && p->arch != ARCH_NOSRC)
540 p->provides = repo_addid_dep(repo, p->provides, rel2id(pool, p->name, p->evr, REL_EQ, 1), 0);
542 /* now merge the attributes */
543 repodata_merge_attrs(data, p - pool->solvables, s - pool->solvables);
549 sat_free(otherarchs);
551 if (!(flags & REPO_NO_INTERNALIZE))
552 repodata_internalize(data);