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 if (!(flags & REPO_REUSE_REPODATA))
223 data = repo_add_repodata(repo, 0);
225 data = repo_last_repodata(repo);
227 memset(&pd, 0, sizeof(pd));
228 line = sat_malloc(1024);
232 /* use last repodata */
233 data = repo->repodata + repo->nrepodata - 1;
235 data = repo_add_repodata(repo, 0);
245 /* read line into big-enough buffer */
246 if (linep - line + 16 > aline)
248 aline = linep - line;
249 line = sat_realloc(line, aline + 512);
250 linep = line + aline;
253 if (!fgets(linep, aline - (linep - line), fp))
255 linep += strlen(linep);
256 if (linep == line || linep[-1] != '\n')
258 while ( --linep > line && ( linep[-1] == ' ' || linep[-1] == '\t' ) )
259 ; /* skip trailing ws */
263 /* expect "key value" lines */
265 key = splitword(&value);
270 fprintf (stderr, "key %s, value %s\n", key, value);
273 #define istag(x) (!strcmp (key, x))
274 #define code10 (contentstyle == 10)
275 #define code11 (contentstyle == 11)
278 if (istag ("CONTENTSTYLE"))
281 pool_debug(pool, SAT_ERROR, "repo_content: 'CONTENTSTYLE' must be first line of 'content'\n");
282 contentstyle = atoi(value);
288 /* repository tags */
289 /* we also replicate some of them into the product solvables
290 * to be backward compatible */
292 if (istag ("DESCRDIR"))
297 repo_set_str(repo, SOLVID_META, SUSETAGS_DESCRDIR, value);
299 repo_set_str(repo, s - pool->solvables, SUSETAGS_DESCRDIR, value);
300 descrdir = strdup(value);
303 if (istag ("DATADIR"))
308 repo_set_str(repo, SOLVID_META, SUSETAGS_DATADIR, value);
310 repo_set_str(repo, s - pool->solvables, SUSETAGS_DATADIR, value);
311 datadir = strdup(value);
314 if (istag ("VENDOR"))
319 repo_set_poolstr(repo, 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 if (!strcasecmp(checksumtype, "sha") || !strcasecmp(checksumtype, "sha1"))
339 l = SIZEOF_SHA1 * 2, type = REPOKEY_TYPE_SHA1;
340 else if (!strcasecmp(checksumtype, "sha256"))
341 l = SIZEOF_SHA256 * 2, type = REPOKEY_TYPE_SHA256;
342 else if (!strcasecmp(checksumtype, "md5"))
343 l = SIZEOF_MD5 * 2, type = REPOKEY_TYPE_MD5;
346 fprintf(stderr, "Unknown checksum type: %s: %s\n", value, checksumtype);
349 if (strlen(checksum) != l)
351 fprintf(stderr, "Invalid checksum length: %s: for %s\n", value, checksum);
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 = 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, 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 = str2id(pool, join(&pd, "product", ":", value), 1);
392 repo_set_str(repo, s - pool->solvables, SUSETAGS_DATADIR, datadir);
394 repo_set_str(repo, s - pool->solvables, SUSETAGS_DESCRDIR, descrdir);
396 s->vendor = 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 = strdup(value);
411 else if (istag ("RELEASE"))
412 pd.tmprel = strdup(value);
413 else if (code11 && istag ("DISTRIBUTION"))
414 repo_set_str(repo, s - pool->solvables, SOLVABLE_DISTRIBUTION, value);
415 else if (istag ("UPDATEURLS"))
416 add_multiple_urls(data, handle, value, str2id(pool, "update", 1));
417 else if (istag ("EXTRAURLS"))
418 add_multiple_urls(data, handle, value, str2id(pool, "extra", 1));
419 else if (istag ("OPTIONALURLS"))
420 add_multiple_urls(data, handle, value, str2id(pool, "optional", 1));
421 else if (istag ("RELNOTESURL"))
422 add_multiple_urls(data, handle, value, str2id(pool, "releasenotes", 1));
423 else if (istag ("SHORTLABEL"))
424 repo_set_str(repo, s - pool->solvables, PRODUCT_SHORTLABEL, value);
425 else if (istag ("LABEL")) /* LABEL is the products SUMMARY. */
426 repo_set_str(repo, s - pool->solvables, SOLVABLE_SUMMARY, value);
427 else if (!strncmp (key, "LABEL.", 6))
428 repo_set_str(repo, 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 = str2id(pool, value, 1);
433 else if (istag ("BASEARCHS"))
437 if ((arch = splitword(&value)) != 0)
439 s->arch = str2id(pool, arch, 1);
440 while ((arch = splitword(&value)) != 0)
442 otherarchs = sat_extend(otherarchs, numotherarchs, 1, sizeof(Id), 7);
443 otherarchs[numotherarchs++] = 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 repo_set_str(repo, s - pool->solvables, PRODUCT_DISTPRODUCT, value);
456 else if (code10 && istag ("DISTVERSION"))
457 /* DISTVERSION is for registration and Yast, not for the solver. */
458 repo_set_str(repo, 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 repo_set_str(repo, 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, SAT_ERROR, "repo_content: malformed line: %s\n", line);
506 pool_debug(pool, SAT_FATAL, "repo_content: 'content' incomplete, no product solvable created!\n");
511 s->evr = makeevr(pool, join(&pd, pd.tmpvers, "-", pd.tmprel));
513 s->evr = makeevr(pool, pd.tmpvers);
514 pd.tmpvers = sat_free((void *)pd.tmpvers);
515 pd.tmprel = sat_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, 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, 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 sat_free(otherarchs);
550 if (!(flags & REPO_NO_INTERNALIZE))
551 repodata_internalize(data);