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 ("REPOID"))
285 repodata_add_poolstr_array(data, SOLVID_META, REPOSITORY_REPOID, value);
289 if (istag ("DESCRDIR"))
294 repo_set_str(repo, SOLVID_META, SUSETAGS_DESCRDIR, value);
296 repo_set_str(repo, s - pool->solvables, SUSETAGS_DESCRDIR, value);
297 descrdir = strdup(value);
300 if (istag ("DATADIR"))
305 repo_set_str(repo, SOLVID_META, SUSETAGS_DATADIR, value);
307 repo_set_str(repo, s - pool->solvables, SUSETAGS_DATADIR, value);
308 datadir = strdup(value);
311 if (istag ("VENDOR"))
316 repo_set_poolstr(repo, SOLVID_META, SUSETAGS_DEFAULTVENDOR, value);
318 s->vendor = str2id(pool, value, 1);
319 defvendor = strdup(value);
323 if (istag ("META") || istag ("HASH") || istag ("KEY"))
325 char *checksumtype, *checksum;
329 if ((checksumtype = splitword(&value)) == 0)
331 if ((checksum = splitword(&value)) == 0)
335 if (!strcasecmp(checksumtype, "sha") || !strcasecmp(checksumtype, "sha1"))
336 l = SIZEOF_SHA1 * 2, type = REPOKEY_TYPE_SHA1;
337 else if (!strcasecmp(checksumtype, "sha256"))
338 l = SIZEOF_SHA256 * 2, type = REPOKEY_TYPE_SHA256;
339 else if (!strcasecmp(checksumtype, "md5"))
340 l = SIZEOF_MD5 * 2, type = REPOKEY_TYPE_MD5;
343 fprintf(stderr, "Unknown checksum type: %s: %s\n", value, checksumtype);
346 if (strlen(checksum) != l)
348 fprintf(stderr, "Invalid checksum length: %s: for %s\n", value, checksum);
351 fh = repodata_new_handle(data);
352 repodata_set_poolstr(data, fh, SUSETAGS_FILE_TYPE, key);
353 repodata_set_str(data, fh, SUSETAGS_FILE_NAME, value);
354 repodata_set_checksum(data, fh, SUSETAGS_FILE_CHECKSUM, type, checksum);
355 repodata_add_flexarray(data, SOLVID_META, SUSETAGS_FILE, fh);
361 if ((code10 && istag ("PRODUCT"))
362 || (code11 && istag ("NAME")))
366 /* this solvable was created without seeing a
367 PRODUCT entry, just set the name and continue */
368 s->name = str2id(pool, join(&pd, "product", ":", value), 1);
373 /* finish old solvable */
375 s->arch = ARCH_NOARCH;
378 if (s->name && 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);
503 pool_debug(pool, SAT_FATAL, "repo_content: 'content' incomplete, no product solvable created!\n");
508 s->evr = makeevr(pool, join(&pd, pd.tmpvers, "-", pd.tmprel));
510 s->evr = makeevr(pool, pd.tmpvers);
511 pd.tmpvers = sat_free((void *)pd.tmpvers);
512 pd.tmprel = sat_free((void *)pd.tmprel);
515 s->arch = ARCH_NOARCH;
518 if (s->name && s->arch != ARCH_SRC && s->arch != ARCH_NOSRC)
519 s->provides = repo_addid_dep(repo, s->provides, rel2id(pool, s->name, s->evr, REL_EQ, 1), 0);
521 s->supplements = repo_fix_supplements(repo, s->provides, s->supplements, 0);
523 /* now for every other arch, clone the product except the architecture */
524 for (i = 0; i < numotherarchs; ++i)
526 Solvable *p = pool_id2solvable(pool, repo_add_solvable(repo));
527 repodata_extend(data, p - pool->solvables);
530 p->vendor = s->vendor;
531 p->arch = otherarchs[i];
534 if (s->name && p->arch != ARCH_SRC && p->arch != ARCH_NOSRC)
535 p->provides = repo_addid_dep(repo, p->provides, rel2id(pool, p->name, p->evr, REL_EQ, 1), 0);
537 /* now merge the attributes */
538 repodata_merge_attrs(data, p - pool->solvables, s - pool->solvables);
545 sat_free(otherarchs);
547 if (!(flags & REPO_NO_INTERNALIZE))
548 repodata_internalize(data);