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);
116 * add dependency to pool
117 * OBSOLETES product:SUSE_LINUX product:openSUSE < 11.0 package:openSUSE < 11.0
121 adddep(Pool *pool, struct parsedata *pd, unsigned int olddeps, char *line, Id marker)
126 while ((name = splitword(&line)) != 0)
128 /* Hack, as the content file adds 'package:' for package
129 dependencies sometimes. */
130 if (!strncmp (name, "package:", 8))
132 id = str2id(pool, name, 1);
133 if (*line == '<' || *line == '>' || *line == '=') /* rel follows */
135 char *rel = splitword(&line);
136 char *evr = splitword(&line);
141 pool_debug(pool, SAT_FATAL, "repo_content: bad relation '%s %s'\n", name, rel);
144 for (flags = 0; flags < 6; flags++)
145 if (!strcmp(rel, flagtab[flags]))
149 pool_debug(pool, SAT_FATAL, "repo_content: unknown relation '%s'\n", rel);
152 id = rel2id(pool, id, str2id(pool, evr, 1), flags + 1, 1);
154 olddeps = repo_addid_dep(pd->repo, olddeps, id, marker);
161 * split value and add to pool
165 add_multiple_strings(Repodata *data, Id handle, Id name, char *value)
169 while ((str = splitword(&value)) != 0)
170 repodata_add_poolstr_array(data, handle, name, str);
174 * split value and add to pool
178 add_multiple_urls(Repodata *data, Id handle, char *value, Id type)
182 while ((url = splitword(&value)) != 0)
184 repodata_add_poolstr_array(data, handle, PRODUCT_URL, url);
185 repodata_add_idarray(data, handle, PRODUCT_URL_TYPE, type);
192 * add 'content' to repo
197 repo_add_content(Repo *repo, FILE *fp, int flags)
199 Pool *pool = repo->pool;
206 int contentstyle = 0;
214 we use the first architecture in BASEARCHS or noarch
215 for the product. At the end we create (clone) the product
216 for each one of the remaining architectures
219 unsigned int numotherarchs = 0;
222 memset(&pd, 0, sizeof(pd));
223 line = sat_malloc(1024);
230 data = repo_add_repodata(repo, flags);
236 /* read line into big-enough buffer */
237 if (linep - line + 16 > aline)
239 aline = linep - line;
240 line = sat_realloc(line, aline + 512);
241 linep = line + aline;
244 if (!fgets(linep, aline - (linep - line), fp))
246 linep += strlen(linep);
247 if (linep == line || linep[-1] != '\n')
249 while ( --linep > line && ( linep[-1] == ' ' || linep[-1] == '\t' ) )
250 ; /* skip trailing ws */
254 /* expect "key value" lines */
256 key = splitword(&value);
261 fprintf (stderr, "key %s, value %s\n", key, value);
264 #define istag(x) (!strcmp (key, x))
265 #define code10 (contentstyle == 10)
266 #define code11 (contentstyle == 11)
269 if (istag ("CONTENTSTYLE"))
272 pool_debug(pool, SAT_ERROR, "repo_content: 'CONTENTSTYLE' must be first line of 'content'\n");
273 contentstyle = atoi(value);
279 /* repository tags */
280 /* we also replicate some of them into the product solvables
281 * to be backward compatible */
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);
305 if (istag ("VENDOR"))
310 repo_set_poolstr(repo, SOLVID_META, SUSETAGS_DEFAULTVENDOR, value);
312 s->vendor = str2id(pool, value, 1);
313 defvendor = strdup(value);
317 if (istag ("META") || istag ("HASH") || istag ("KEY"))
319 char *checksumtype, *checksum;
323 if ((checksumtype = splitword(&value)) == 0)
325 if ((checksum = splitword(&value)) == 0)
329 if (!strcasecmp(checksumtype, "sha") || !strcasecmp(checksumtype, "sha1"))
330 l = SIZEOF_SHA1 * 2, type = REPOKEY_TYPE_SHA1;
331 else if (!strcasecmp(checksumtype, "sha256"))
332 l = SIZEOF_SHA256 * 2, type = REPOKEY_TYPE_SHA256;
333 else if (!strcasecmp(checksumtype, "md5"))
334 l = SIZEOF_MD5 * 2, type = REPOKEY_TYPE_MD5;
337 fprintf(stderr, "Unknown checksum type: %s: %s\n", value, checksumtype);
340 if (strlen(checksum) != l)
342 fprintf(stderr, "Invalid checksum length: %s: for %s\n", value, checksum);
345 fh = repodata_new_handle(data);
346 repodata_set_poolstr(data, fh, SUSETAGS_FILE_TYPE, key);
347 repodata_set_str(data, fh, SUSETAGS_FILE_NAME, value);
348 repodata_set_checksum(data, fh, SUSETAGS_FILE_CHECKSUM, type, checksum);
349 repodata_add_flexarray(data, SOLVID_META, SUSETAGS_FILE, fh);
355 if ((code10 && istag ("PRODUCT"))
356 || (code11 && istag ("NAME")))
360 /* this solvable was created without seeing a
361 PRODUCT entry, just set the name and continue */
362 s->name = str2id(pool, join(&pd, "product", ":", value), 1);
367 /* finish old solvable */
369 s->arch = ARCH_NOARCH;
372 if (s->name && s->arch != ARCH_SRC && s->arch != ARCH_NOSRC)
373 s->provides = repo_addid_dep(repo, s->provides, rel2id(pool, s->name, s->evr, REL_EQ, 1), 0);
375 s->supplements = repo_fix_supplements(repo, s->provides, s->supplements, 0);
377 /* create new solvable */
378 s = pool_id2solvable(pool, repo_add_solvable(repo));
379 repodata_extend(data, s - pool->solvables);
380 handle = s - pool->solvables;
381 s->name = str2id(pool, join(&pd, "product", ":", value), 1);
383 repo_set_str(repo, s - pool->solvables, SUSETAGS_DATADIR, datadir);
385 repo_set_str(repo, s - pool->solvables, SUSETAGS_DESCRDIR, descrdir);
387 s->vendor = str2id(pool, defvendor, 1);
391 /* Sometimes PRODUCT/NAME is not the first entry, but we need a solvable
395 s = pool_id2solvable(pool, repo_add_solvable(repo));
396 repodata_extend(data, s - pool->solvables);
397 handle = s - pool->solvables;
400 if (istag ("VERSION"))
401 pd.tmpvers = strdup(value);
402 else if (istag ("RELEASE"))
403 pd.tmprel = strdup(value);
404 else if (code11 && istag ("DISTRIBUTION"))
405 repo_set_str(repo, s - pool->solvables, SOLVABLE_DISTRIBUTION, value);
406 else if (istag ("UPDATEURLS"))
407 add_multiple_urls(data, handle, value, str2id(pool, "update", 1));
408 else if (istag ("EXTRAURLS"))
409 add_multiple_urls(data, handle, value, str2id(pool, "extra", 1));
410 else if (istag ("OPTIONALURLS"))
411 add_multiple_urls(data, handle, value, str2id(pool, "optional", 1));
412 else if (istag ("RELNOTESURL"))
413 add_multiple_urls(data, handle, value, str2id(pool, "releasenotes", 1));
414 else if (istag ("SHORTLABEL"))
415 repo_set_str(repo, s - pool->solvables, PRODUCT_SHORTLABEL, value);
416 else if (istag ("LABEL")) /* LABEL is the products SUMMARY. */
417 repo_set_str(repo, s - pool->solvables, SOLVABLE_SUMMARY, value);
418 else if (!strncmp (key, "LABEL.", 6))
419 repo_set_str(repo, s - pool->solvables, pool_id2langid(pool, SOLVABLE_SUMMARY, key + 6, 1), value);
420 else if (istag ("FLAGS"))
421 add_multiple_strings(data, handle, PRODUCT_FLAGS, value);
422 else if (istag ("VENDOR")) /* actually already handled above */
423 s->vendor = str2id(pool, value, 1);
424 else if (istag ("BASEARCHS"))
428 if ((arch = splitword(&value)) != 0)
430 s->arch = str2id(pool, arch, 1);
431 while ((arch = splitword(&value)) != 0)
433 otherarchs = sat_extend(otherarchs, numotherarchs, 1, sizeof(Id), 7);
434 otherarchs[numotherarchs++] = str2id(pool, arch, 1);
440 * Every tag below is Code10 only
444 if (code10 && istag ("DISTPRODUCT"))
445 /* DISTPRODUCT is for registration and Yast, not for the solver. */
446 repo_set_str(repo, s - pool->solvables, PRODUCT_DISTPRODUCT, value);
447 else if (code10 && istag ("DISTVERSION"))
448 /* DISTVERSION is for registration and Yast, not for the solver. */
449 repo_set_str(repo, s - pool->solvables, PRODUCT_DISTVERSION, value);
450 else if (code10 && istag ("ARCH"))
451 /* Theoretically we want to have the best arch of the given
452 modifiers which still is compatible with the system
453 arch. We don't know the latter here, though. */
454 s->arch = ARCH_NOARCH;
455 else if (code10 && istag ("PREREQUIRES"))
456 s->requires = adddep(pool, &pd, s->requires, value, SOLVABLE_PREREQMARKER);
457 else if (code10 && istag ("REQUIRES"))
458 s->requires = adddep(pool, &pd, s->requires, value, -SOLVABLE_PREREQMARKER);
459 else if (code10 && istag ("PROVIDES"))
460 s->provides = adddep(pool, &pd, s->provides, value, 0);
461 else if (code10 && istag ("CONFLICTS"))
462 s->conflicts = adddep(pool, &pd, s->conflicts, value, 0);
463 else if (code10 && istag ("OBSOLETES"))
464 s->obsoletes = adddep(pool, &pd, s->obsoletes, value, 0);
465 else if (code10 && istag ("RECOMMENDS"))
466 s->recommends = adddep(pool, &pd, s->recommends, value, 0);
467 else if (code10 && istag ("SUGGESTS"))
468 s->suggests = adddep(pool, &pd, s->suggests, value, 0);
469 else if (code10 && istag ("SUPPLEMENTS"))
470 s->supplements = adddep(pool, &pd, s->supplements, value, 0);
471 else if (code10 && istag ("ENHANCES"))
472 s->enhances = adddep(pool, &pd, s->enhances, value, 0);
473 /* FRESHENS doesn't seem to exist. */
474 else if (code10 && istag ("TYPE"))
475 repo_set_str(repo, s - pool->solvables, PRODUCT_TYPE, value);
477 /* XXX do something about LINGUAS and ARCH?
478 * <ma>: Don't think so. zypp does not use or propagate them.
483 pool_debug(pool, SAT_ERROR, "repo_content: malformed line: %s\n", line);
497 pool_debug(pool, SAT_FATAL, "repo_content: 'content' incomplete, no product solvable created!\n");
502 s->evr = makeevr(pool, join(&pd, pd.tmpvers, "-", pd.tmprel));
504 s->evr = makeevr(pool, pd.tmpvers);
505 pd.tmpvers = sat_free((void *)pd.tmpvers);
506 pd.tmprel = sat_free((void *)pd.tmprel);
509 s->arch = ARCH_NOARCH;
512 if (s->name && s->arch != ARCH_SRC && s->arch != ARCH_NOSRC)
513 s->provides = repo_addid_dep(repo, s->provides, rel2id(pool, s->name, s->evr, REL_EQ, 1), 0);
515 s->supplements = repo_fix_supplements(repo, s->provides, s->supplements, 0);
517 /* now for every other arch, clone the product except the architecture */
518 for (i = 0; i < numotherarchs; ++i)
520 Solvable *p = pool_id2solvable(pool, repo_add_solvable(repo));
521 repodata_extend(data, p - pool->solvables);
524 p->vendor = s->vendor;
525 p->arch = otherarchs[i];
528 if (s->name && p->arch != ARCH_SRC && p->arch != ARCH_NOSRC)
529 p->provides = repo_addid_dep(repo, p->provides, rel2id(pool, p->name, p->evr, REL_EQ, 1), 0);
531 /* now merge the attributes */
532 repodata_merge_attrs(data, p - pool->solvables, s - pool->solvables);
539 sat_free(otherarchs);
541 if (!(flags & REPO_NO_INTERNALIZE))
542 repodata_internalize(data);