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;
379 if (s->arch != ARCH_SRC && s->arch != ARCH_NOSRC)
380 s->provides = repo_addid_dep(repo, s->provides, rel2id(pool, s->name, s->evr, REL_EQ, 1), 0);
382 s->supplements = repo_fix_supplements(repo, s->provides, s->supplements, 0);
384 /* create new solvable */
385 s = pool_id2solvable(pool, repo_add_solvable(repo));
386 repodata_extend(data, s - pool->solvables);
387 handle = s - pool->solvables;
388 s->name = str2id(pool, join(&pd, "product", ":", value), 1);
390 repo_set_str(repo, s - pool->solvables, SUSETAGS_DATADIR, datadir);
392 repo_set_str(repo, s - pool->solvables, SUSETAGS_DESCRDIR, descrdir);
394 s->vendor = str2id(pool, defvendor, 1);
398 /* Sometimes PRODUCT/NAME is not the first entry, but we need a solvable
402 s = pool_id2solvable(pool, repo_add_solvable(repo));
403 repodata_extend(data, s - pool->solvables);
404 handle = s - pool->solvables;
407 if (istag ("VERSION"))
408 pd.tmpvers = strdup(value);
409 else if (istag ("RELEASE"))
410 pd.tmprel = strdup(value);
411 else if (code11 && istag ("DISTRIBUTION"))
412 repo_set_str(repo, s - pool->solvables, SOLVABLE_DISTRIBUTION, value);
413 else if (istag ("UPDATEURLS"))
414 add_multiple_urls(data, handle, value, str2id(pool, "update", 1));
415 else if (istag ("EXTRAURLS"))
416 add_multiple_urls(data, handle, value, str2id(pool, "extra", 1));
417 else if (istag ("OPTIONALURLS"))
418 add_multiple_urls(data, handle, value, str2id(pool, "optional", 1));
419 else if (istag ("RELNOTESURL"))
420 add_multiple_urls(data, handle, value, str2id(pool, "releasenotes", 1));
421 else if (istag ("SHORTLABEL"))
422 repo_set_str(repo, s - pool->solvables, PRODUCT_SHORTLABEL, value);
423 else if (istag ("LABEL")) /* LABEL is the products SUMMARY. */
424 repo_set_str(repo, s - pool->solvables, SOLVABLE_SUMMARY, value);
425 else if (!strncmp (key, "LABEL.", 6))
426 repo_set_str(repo, s - pool->solvables, pool_id2langid(pool, SOLVABLE_SUMMARY, key + 6, 1), value);
427 else if (istag ("FLAGS"))
428 add_multiple_strings(data, handle, PRODUCT_FLAGS, value);
429 else if (istag ("VENDOR")) /* actually already handled above */
430 s->vendor = str2id(pool, value, 1);
431 else if (istag ("BASEARCHS"))
435 if ((arch = splitword(&value)) != 0)
437 s->arch = str2id(pool, arch, 1);
438 while ((arch = splitword(&value)) != 0)
440 otherarchs = sat_extend(otherarchs, numotherarchs, 1, sizeof(Id), 7);
441 otherarchs[numotherarchs++] = str2id(pool, arch, 1);
447 * Every tag below is Code10 only
451 if (code10 && istag ("DISTPRODUCT"))
452 /* DISTPRODUCT is for registration and Yast, not for the solver. */
453 repo_set_str(repo, s - pool->solvables, PRODUCT_DISTPRODUCT, value);
454 else if (code10 && istag ("DISTVERSION"))
455 /* DISTVERSION is for registration and Yast, not for the solver. */
456 repo_set_str(repo, s - pool->solvables, PRODUCT_DISTVERSION, value);
457 else if (code10 && istag ("ARCH"))
458 /* Theoretically we want to have the best arch of the given
459 modifiers which still is compatible with the system
460 arch. We don't know the latter here, though. */
461 s->arch = ARCH_NOARCH;
462 else if (code10 && istag ("PREREQUIRES"))
463 s->requires = adddep(pool, &pd, s->requires, value, SOLVABLE_PREREQMARKER);
464 else if (code10 && istag ("REQUIRES"))
465 s->requires = adddep(pool, &pd, s->requires, value, -SOLVABLE_PREREQMARKER);
466 else if (code10 && istag ("PROVIDES"))
467 s->provides = adddep(pool, &pd, s->provides, value, 0);
468 else if (code10 && istag ("CONFLICTS"))
469 s->conflicts = adddep(pool, &pd, s->conflicts, value, 0);
470 else if (code10 && istag ("OBSOLETES"))
471 s->obsoletes = adddep(pool, &pd, s->obsoletes, value, 0);
472 else if (code10 && istag ("RECOMMENDS"))
473 s->recommends = adddep(pool, &pd, s->recommends, value, 0);
474 else if (code10 && istag ("SUGGESTS"))
475 s->suggests = adddep(pool, &pd, s->suggests, value, 0);
476 else if (code10 && istag ("SUPPLEMENTS"))
477 s->supplements = adddep(pool, &pd, s->supplements, value, 0);
478 else if (code10 && istag ("ENHANCES"))
479 s->enhances = adddep(pool, &pd, s->enhances, value, 0);
480 /* FRESHENS doesn't seem to exist. */
481 else if (code10 && istag ("TYPE"))
482 repo_set_str(repo, s - pool->solvables, PRODUCT_TYPE, value);
484 /* XXX do something about LINGUAS and ARCH?
485 * <ma>: Don't think so. zypp does not use or propagate them.
490 pool_debug(pool, SAT_ERROR, "repo_content: malformed line: %s\n", line);
504 pool_debug(pool, SAT_FATAL, "repo_content: 'content' incomplete, no product solvable created!\n");
509 s->evr = makeevr(pool, join(&pd, pd.tmpvers, "-", pd.tmprel));
511 s->evr = makeevr(pool, pd.tmpvers);
512 pd.tmpvers = sat_free((void *)pd.tmpvers);
513 pd.tmprel = sat_free((void *)pd.tmprel);
516 s->arch = ARCH_NOARCH;
517 if (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 (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);