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;
210 we use the first architecture in BASEARCHS or noarch
211 for the product. At the end we create (clone) the product
212 for each one of the remaining architectures
215 unsigned int numotherarchs = 0;
218 if (!(flags & REPO_REUSE_REPODATA))
219 data = repo_add_repodata(repo, 0);
221 data = repo_last_repodata(repo);
223 memset(&pd, 0, sizeof(pd));
224 line = sat_malloc(1024);
228 /* use last repodata */
229 data = repo->repodata + repo->nrepodata - 1;
231 data = repo_add_repodata(repo, 0);
241 /* read line into big-enough buffer */
242 if (linep - line + 16 > aline)
244 aline = linep - line;
245 line = sat_realloc(line, aline + 512);
246 linep = line + aline;
249 if (!fgets(linep, aline - (linep - line), fp))
251 linep += strlen(linep);
252 if (linep == line || linep[-1] != '\n')
254 while ( --linep > line && ( linep[-1] == ' ' || linep[-1] == '\t' ) )
255 ; /* skip trailing ws */
259 /* expect "key value" lines */
261 key = splitword(&value);
266 fprintf (stderr, "key %s, value %s\n", key, value);
269 #define istag(x) (!strcmp (key, x))
270 #define code10 (contentstyle == 10)
271 #define code11 (contentstyle == 11)
273 if (contentstyle == 0)
275 if (istag ("CONTENTSTYLE"))
277 contentstyle = atoi(value);
284 if ((code10 && istag ("PRODUCT"))
285 || (code11 && istag ("NAME")))
289 /* this solvable was created without seeing a
290 PRODUCT entry, just set the name and continue */
291 s->name = str2id(pool, join(&pd, "product", ":", value), 1);
296 /* finish old solvable */
298 s->arch = ARCH_NOARCH;
299 if (s->arch != ARCH_SRC && s->arch != ARCH_NOSRC)
300 s->provides = repo_addid_dep(repo, s->provides, rel2id(pool, s->name, s->evr, REL_EQ, 1), 0);
302 s->supplements = repo_fix_supplements(repo, s->provides, s->supplements, 0);
304 /* create new solvable */
305 s = pool_id2solvable(pool, repo_add_solvable(repo));
306 repodata_extend(data, s - pool->solvables);
307 handle = s - pool->solvables;
308 s->name = str2id(pool, join(&pd, "product", ":", value), 1);
312 /* Sometimes PRODUCT/NAME is not the first entry, but we need a solvable
316 s = pool_id2solvable(pool, repo_add_solvable(repo));
317 repodata_extend(data, s - pool->solvables);
318 handle = s - pool->solvables;
321 if (istag ("VERSION"))
322 pd.tmpvers = strdup(value);
323 else if (istag ("RELEASE"))
324 pd.tmprel = strdup(value);
325 else if (code11 && istag ("DISTRIBUTION"))
326 repo_set_str(repo, s - pool->solvables, SOLVABLE_DISTRIBUTION, value);
327 else if (istag ("DATADIR"))
328 repo_set_str(repo, s - pool->solvables, SUSETAGS_DATADIR, value);
329 else if (istag ("UPDATEURLS"))
330 add_multiple_urls(data, handle, value, str2id(pool, "update", 1));
331 else if (istag ("EXTRAURLS"))
332 add_multiple_urls(data, handle, value, str2id(pool, "extra", 1));
333 else if (istag ("OPTIONALURLS"))
334 add_multiple_urls(data, handle, value, str2id(pool, "optional", 1));
335 else if (istag ("RELNOTESURL"))
336 add_multiple_urls(data, handle, value, str2id(pool, "releasenotes", 1));
337 else if (istag ("SHORTLABEL"))
338 repo_set_str(repo, s - pool->solvables, PRODUCT_SHORTLABEL, value);
339 else if (istag ("LABEL")) /* LABEL is the products SUMMARY. */
340 repo_set_str(repo, s - pool->solvables, SOLVABLE_SUMMARY, value);
341 else if (!strncmp (key, "LABEL.", 6))
342 repo_set_str(repo, s - pool->solvables, pool_id2langid(pool, SOLVABLE_SUMMARY, key + 6, 1), value);
343 else if (istag ("FLAGS"))
344 add_multiple_strings(data, handle, PRODUCT_FLAGS, value);
345 else if (istag ("VENDOR"))
346 s->vendor = str2id(pool, value, 1);
347 else if (istag ("BASEARCHS"))
351 if ((arch = splitword(&value)) != 0)
353 s->arch = str2id(pool, arch, 1);
354 while ((arch = splitword(&value)) != 0)
356 otherarchs = sat_extend(otherarchs, numotherarchs, 1, sizeof(Id), 7);
357 otherarchs[numotherarchs++] = str2id(pool, arch, 1);
363 * Every tag below is Code10 only
367 else if (code10 && istag ("CONTENTSTYLE"))
368 /* CONTENTSTYLE must be first line */
369 pool_debug(pool, SAT_ERROR, "repo_content: 'CONTENTSTYLE' must be first line of 'content'\n");
370 else if (code10 && istag ("DISTPRODUCT"))
371 /* DISTPRODUCT is for registration and Yast, not for the solver. */
372 repo_set_str(repo, s - pool->solvables, PRODUCT_DISTPRODUCT, value);
373 else if (code10 && istag ("DISTVERSION"))
374 /* DISTVERSION is for registration and Yast, not for the solver. */
375 repo_set_str(repo, s - pool->solvables, PRODUCT_DISTVERSION, value);
376 else if (code10 && istag ("ARCH"))
377 /* Theoretically we want to have the best arch of the given
378 modifiers which still is compatible with the system
379 arch. We don't know the latter here, though. */
380 s->arch = ARCH_NOARCH;
381 else if (code10 && istag ("PREREQUIRES"))
382 s->requires = adddep(pool, &pd, s->requires, value, SOLVABLE_PREREQMARKER);
383 else if (code10 && istag ("REQUIRES"))
384 s->requires = adddep(pool, &pd, s->requires, value, -SOLVABLE_PREREQMARKER);
385 else if (code10 && istag ("PROVIDES"))
386 s->provides = adddep(pool, &pd, s->provides, value, 0);
387 else if (code10 && istag ("CONFLICTS"))
388 s->conflicts = adddep(pool, &pd, s->conflicts, value, 0);
389 else if (code10 && istag ("OBSOLETES"))
390 s->obsoletes = adddep(pool, &pd, s->obsoletes, value, 0);
391 else if (code10 && istag ("RECOMMENDS"))
392 s->recommends = adddep(pool, &pd, s->recommends, value, 0);
393 else if (code10 && istag ("SUGGESTS"))
394 s->suggests = adddep(pool, &pd, s->suggests, value, 0);
395 else if (code10 && istag ("SUPPLEMENTS"))
396 s->supplements = adddep(pool, &pd, s->supplements, value, 0);
397 else if (code10 && istag ("ENHANCES"))
398 s->enhances = adddep(pool, &pd, s->enhances, value, 0);
399 /* FRESHENS doesn't seem to exist. */
400 else if (code10 && istag ("TYPE"))
401 repo_set_str(repo, s - pool->solvables, PRODUCT_TYPE, value);
403 /* XXX do something about LINGUAS and ARCH?
404 * <ma>: Don't think so. zypp does not use or propagate them.
409 pool_debug(pool, SAT_ERROR, "repo_content: malformed line: %s\n", line);
414 pool_debug(pool, SAT_FATAL, "repo_content: 'content' incomplete, no product solvable created !\n");
421 s->evr = makeevr(pool, join2(pd.tmpvers, "-", pd.tmprel));
423 s->evr = makeevr(pool, pd.tmpvers);
427 s->evr = makeevr(pool, join2("", "-", pd.tmprel));
429 pd.tmpvers = sat_free((void *)pd.tmpvers);
430 pd.tmprel = sat_free((void *)pd.tmprel);
433 s->arch = ARCH_NOARCH;
434 if (s->arch != ARCH_SRC && s->arch != ARCH_NOSRC)
436 s->provides = repo_addid_dep(repo, s->provides, rel2id(pool, s->name, s->evr, REL_EQ, 1), 0);
438 s->supplements = repo_fix_supplements(repo, s->provides, s->supplements, 0);
441 /* now for every other arch, clone the product except the architecture */
442 for (i = 0; i < numotherarchs; ++i)
444 Solvable *p = pool_id2solvable(pool, repo_add_solvable(repo));
445 repodata_extend(data, p - pool->solvables);
448 p->vendor = s->vendor;
449 p->arch = otherarchs[i];
452 if (p->arch != ARCH_SRC && p->arch != ARCH_NOSRC)
453 p->provides = repo_addid_dep(repo, p->provides, rel2id(pool, p->name, p->evr, REL_EQ, 1), 0);
455 /* now merge the attributes */
456 repodata_merge_attrs(data, p - pool->solvables, s - pool->solvables);
462 sat_free(otherarchs);
463 if (!(flags & REPO_NO_INTERNALIZE))
464 repodata_internalize(data);