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;
212 we use the first architecture in BASEARCHS or noarch
213 for the product. At the end we create (clone) the product
214 for each one of the remaining architectures
217 unsigned int numotherarchs = 0;
220 if (!(flags & REPO_REUSE_REPODATA))
221 data = repo_add_repodata(repo, 0);
223 data = repo_last_repodata(repo);
225 memset(&pd, 0, sizeof(pd));
226 line = sat_malloc(1024);
230 /* use last repodata */
231 data = repo->repodata + repo->nrepodata - 1;
233 data = repo_add_repodata(repo, 0);
243 /* read line into big-enough buffer */
244 if (linep - line + 16 > aline)
246 aline = linep - line;
247 line = sat_realloc(line, aline + 512);
248 linep = line + aline;
251 if (!fgets(linep, aline - (linep - line), fp))
253 linep += strlen(linep);
254 if (linep == line || linep[-1] != '\n')
256 while ( --linep > line && ( linep[-1] == ' ' || linep[-1] == '\t' ) )
257 ; /* skip trailing ws */
261 /* expect "key value" lines */
263 key = splitword(&value);
268 fprintf (stderr, "key %s, value %s\n", key, value);
271 #define istag(x) (!strcmp (key, x))
272 #define code10 (contentstyle == 10)
273 #define code11 (contentstyle == 11)
275 if (istag ("CONTENTSTYLE"))
277 contentstyle = atoi(value);
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);
306 if (istag ("META") || istag ("HASH") || istag ("KEY"))
308 char *checksumtype, *checksum;
312 if ((checksumtype = splitword(&value)) == 0)
314 if ((checksum = splitword(&value)) == 0)
318 if (!strcasecmp(checksumtype, "sha") || !strcasecmp(checksumtype, "sha1"))
319 l = SIZEOF_SHA1 * 2, type = REPOKEY_TYPE_SHA1;
320 else if (!strcasecmp(checksumtype, "sha256"))
321 l = SIZEOF_SHA256 * 2, type = REPOKEY_TYPE_SHA256;
322 else if (!strcasecmp(checksumtype, "md5"))
323 l = SIZEOF_MD5 * 2, type = REPOKEY_TYPE_MD5;
326 fprintf(stderr, "Unknown checksum type: %s: %s\n", value, checksumtype);
329 if (strlen(checksum) != l)
331 fprintf(stderr, "Invalid checksum length: %s: for %s\n", value, checksum);
334 fh = repodata_new_handle(data);
335 repodata_set_poolstr(data, fh, SUSETAGS_FILE_TYPE, key);
336 repodata_set_str(data, fh, SUSETAGS_FILE_NAME, value);
337 repodata_set_checksum(data, fh, SUSETAGS_FILE_CHECKSUM, type, checksum);
338 repodata_add_flexarray(data, SOLVID_META, SUSETAGS_FILE, fh);
342 if ((code10 && istag ("PRODUCT"))
343 || (code11 && istag ("NAME")))
347 /* this solvable was created without seeing a
348 PRODUCT entry, just set the name and continue */
349 s->name = str2id(pool, join(&pd, "product", ":", value), 1);
354 /* finish old solvable */
356 s->arch = ARCH_NOARCH;
357 if (s->arch != ARCH_SRC && s->arch != ARCH_NOSRC)
358 s->provides = repo_addid_dep(repo, s->provides, rel2id(pool, s->name, s->evr, REL_EQ, 1), 0);
360 s->supplements = repo_fix_supplements(repo, s->provides, s->supplements, 0);
362 /* create new solvable */
363 s = pool_id2solvable(pool, repo_add_solvable(repo));
364 repodata_extend(data, s - pool->solvables);
365 handle = s - pool->solvables;
366 s->name = str2id(pool, join(&pd, "product", ":", value), 1);
368 repo_set_str(repo, s - pool->solvables, SUSETAGS_DATADIR, datadir);
370 repo_set_str(repo, s - pool->solvables, SUSETAGS_DESCRDIR, descrdir);
374 /* Sometimes PRODUCT/NAME is not the first entry, but we need a solvable
378 s = pool_id2solvable(pool, repo_add_solvable(repo));
379 repodata_extend(data, s - pool->solvables);
380 handle = s - pool->solvables;
383 if (istag ("VERSION"))
384 pd.tmpvers = strdup(value);
385 else if (istag ("RELEASE"))
386 pd.tmprel = strdup(value);
387 else if (code11 && istag ("DISTRIBUTION"))
388 repo_set_str(repo, s - pool->solvables, SOLVABLE_DISTRIBUTION, value);
389 else if (istag ("UPDATEURLS"))
390 add_multiple_urls(data, handle, value, str2id(pool, "update", 1));
391 else if (istag ("EXTRAURLS"))
392 add_multiple_urls(data, handle, value, str2id(pool, "extra", 1));
393 else if (istag ("OPTIONALURLS"))
394 add_multiple_urls(data, handle, value, str2id(pool, "optional", 1));
395 else if (istag ("RELNOTESURL"))
396 add_multiple_urls(data, handle, value, str2id(pool, "releasenotes", 1));
397 else if (istag ("SHORTLABEL"))
398 repo_set_str(repo, s - pool->solvables, PRODUCT_SHORTLABEL, value);
399 else if (istag ("LABEL")) /* LABEL is the products SUMMARY. */
400 repo_set_str(repo, s - pool->solvables, SOLVABLE_SUMMARY, value);
401 else if (!strncmp (key, "LABEL.", 6))
402 repo_set_str(repo, s - pool->solvables, pool_id2langid(pool, SOLVABLE_SUMMARY, key + 6, 1), value);
403 else if (istag ("FLAGS"))
404 add_multiple_strings(data, handle, PRODUCT_FLAGS, value);
405 else if (istag ("VENDOR"))
406 s->vendor = str2id(pool, value, 1);
407 else if (istag ("BASEARCHS"))
411 if ((arch = splitword(&value)) != 0)
413 s->arch = str2id(pool, arch, 1);
414 while ((arch = splitword(&value)) != 0)
416 otherarchs = sat_extend(otherarchs, numotherarchs, 1, sizeof(Id), 7);
417 otherarchs[numotherarchs++] = str2id(pool, arch, 1);
423 * Every tag below is Code10 only
427 else if (code10 && istag ("CONTENTSTYLE"))
428 /* CONTENTSTYLE must be first line */
429 pool_debug(pool, SAT_ERROR, "repo_content: 'CONTENTSTYLE' must be first line of 'content'\n");
430 else if (code10 && istag ("DISTPRODUCT"))
431 /* DISTPRODUCT is for registration and Yast, not for the solver. */
432 repo_set_str(repo, s - pool->solvables, PRODUCT_DISTPRODUCT, value);
433 else if (code10 && istag ("DISTVERSION"))
434 /* DISTVERSION is for registration and Yast, not for the solver. */
435 repo_set_str(repo, s - pool->solvables, PRODUCT_DISTVERSION, value);
436 else if (code10 && istag ("ARCH"))
437 /* Theoretically we want to have the best arch of the given
438 modifiers which still is compatible with the system
439 arch. We don't know the latter here, though. */
440 s->arch = ARCH_NOARCH;
441 else if (code10 && istag ("PREREQUIRES"))
442 s->requires = adddep(pool, &pd, s->requires, value, SOLVABLE_PREREQMARKER);
443 else if (code10 && istag ("REQUIRES"))
444 s->requires = adddep(pool, &pd, s->requires, value, -SOLVABLE_PREREQMARKER);
445 else if (code10 && istag ("PROVIDES"))
446 s->provides = adddep(pool, &pd, s->provides, value, 0);
447 else if (code10 && istag ("CONFLICTS"))
448 s->conflicts = adddep(pool, &pd, s->conflicts, value, 0);
449 else if (code10 && istag ("OBSOLETES"))
450 s->obsoletes = adddep(pool, &pd, s->obsoletes, value, 0);
451 else if (code10 && istag ("RECOMMENDS"))
452 s->recommends = adddep(pool, &pd, s->recommends, value, 0);
453 else if (code10 && istag ("SUGGESTS"))
454 s->suggests = adddep(pool, &pd, s->suggests, value, 0);
455 else if (code10 && istag ("SUPPLEMENTS"))
456 s->supplements = adddep(pool, &pd, s->supplements, value, 0);
457 else if (code10 && istag ("ENHANCES"))
458 s->enhances = adddep(pool, &pd, s->enhances, value, 0);
459 /* FRESHENS doesn't seem to exist. */
460 else if (code10 && istag ("TYPE"))
461 repo_set_str(repo, s - pool->solvables, PRODUCT_TYPE, value);
463 /* XXX do something about LINGUAS and ARCH?
464 * <ma>: Don't think so. zypp does not use or propagate them.
469 pool_debug(pool, SAT_ERROR, "repo_content: malformed line: %s\n", line);
479 pool_debug(pool, SAT_FATAL, "repo_content: 'content' incomplete, no product solvable created!\n");
486 s->evr = makeevr(pool, join2(pd.tmpvers, "-", pd.tmprel));
488 s->evr = makeevr(pool, pd.tmpvers);
492 s->evr = makeevr(pool, join2("", "-", pd.tmprel));
494 pd.tmpvers = sat_free((void *)pd.tmpvers);
495 pd.tmprel = sat_free((void *)pd.tmprel);
498 s->arch = ARCH_NOARCH;
499 if (s->arch != ARCH_SRC && s->arch != ARCH_NOSRC)
501 s->provides = repo_addid_dep(repo, s->provides, rel2id(pool, s->name, s->evr, REL_EQ, 1), 0);
503 s->supplements = repo_fix_supplements(repo, s->provides, s->supplements, 0);
506 /* now for every other arch, clone the product except the architecture */
507 for (i = 0; i < numotherarchs; ++i)
509 Solvable *p = pool_id2solvable(pool, repo_add_solvable(repo));
510 repodata_extend(data, p - pool->solvables);
513 p->vendor = s->vendor;
514 p->arch = otherarchs[i];
517 if (p->arch != ARCH_SRC && p->arch != ARCH_NOSRC)
518 p->provides = repo_addid_dep(repo, p->provides, rel2id(pool, p->name, p->evr, REL_EQ, 1), 0);
520 /* now merge the attributes */
521 repodata_merge_attrs(data, p - pool->solvables, s - pool->solvables);
527 sat_free(otherarchs);
529 if (!(flags & REPO_NO_INTERNALIZE))
530 repodata_internalize(data);