4 * Parses RedHat comps format
6 * Copyright (c) 2012, Novell Inc.
8 * This program is licensed under the BSD license, read LICENSE.BSD
9 * for further information
12 #include <sys/types.h>
23 #include "solv_xmlparser.h"
25 #include "tools_util.h"
26 #include "repo_comps.h"
31 * what's the difference between group/category?
33 * maybe handle REL_COND in solver recommends handling?
62 static struct solv_xmlparser_element stateswitches[] = {
63 { STATE_START, "comps", STATE_COMPS, 0 },
64 { STATE_COMPS, "group", STATE_GROUP, 0 },
65 { STATE_COMPS, "category", STATE_CATEGORY, 0 },
66 { STATE_COMPS, "environment", STATE_ENVIRONMENT, 0 },
67 { STATE_GROUP, "id", STATE_ID, 1 },
68 { STATE_GROUP, "name", STATE_NAME, 1 },
69 { STATE_GROUP, "description", STATE_DESCRIPTION, 1 },
70 { STATE_GROUP, "uservisible", STATE_USERVISIBLE, 1 },
71 { STATE_GROUP, "display_order", STATE_DISPLAY_ORDER, 1 },
72 { STATE_GROUP, "default", STATE_DEFAULT, 1 },
73 { STATE_GROUP, "langonly", STATE_LANGONLY, 1 },
74 { STATE_GROUP, "lang_only", STATE_LANG_ONLY, 1 },
75 { STATE_GROUP, "packagelist", STATE_PACKAGELIST, 0 },
76 { STATE_PACKAGELIST, "packagereq", STATE_PACKAGEREQ, 1 },
77 { STATE_CATEGORY, "id", STATE_ID, 1 },
78 { STATE_CATEGORY, "name", STATE_NAME, 1 },
79 { STATE_CATEGORY, "description", STATE_DESCRIPTION, 1 },
80 { STATE_CATEGORY , "grouplist", STATE_GROUPLIST, 0 },
81 { STATE_CATEGORY , "display_order", STATE_DISPLAY_ORDER, 1 },
82 { STATE_GROUPLIST, "groupid", STATE_GROUPID, 1 },
83 { STATE_ENVIRONMENT, "id", STATE_ID, 1 },
84 { STATE_ENVIRONMENT, "name", STATE_NAME, 1 },
85 { STATE_ENVIRONMENT, "description", STATE_DESCRIPTION, 1 },
86 { STATE_ENVIRONMENT, "grouplist", STATE_GROUPLIST, 0 },
87 { STATE_ENVIRONMENT, "optionlist", STATE_OPTIONLIST, 0 },
88 { STATE_ENVIRONMENT, "display_order", STATE_DISPLAY_ORDER, 1 },
89 { STATE_OPTIONLIST, "groupid", STATE_GROUPID, 1 },
100 struct solv_xmlparser xmlp;
115 #define COMPS_DEFAULT_ISVISIBLE 1
116 #define COMPS_DEFAULT_ISDEFAULT 0
118 /* Return true if "true", false if "false", default_value otherwise */
120 parse_boolean(char *content, int default_value)
122 if (!strcmp(content, "true"))
124 if (!strcmp(content, "false"))
126 return default_value;
131 startElement(struct solv_xmlparser *xmlp, int state, const char *name, const char **atts)
133 struct parsedata *pd = xmlp->userdata;
134 Pool *pool = pd->pool;
141 case STATE_ENVIRONMENT:
142 s = pd->solvable = pool_id2solvable(pool, repo_add_solvable(pd->repo));
143 pd->handle = s - pool->solvables;
144 if (state == STATE_GROUP)
146 else if (state == STATE_CATEGORY)
147 pd->kind = "category";
149 pd->kind = "environment";
150 pd->isvisible = COMPS_DEFAULT_ISVISIBLE;
151 pd->isdefault = COMPS_DEFAULT_ISDEFAULT;
156 case STATE_DESCRIPTION:
157 case STATE_CDESCRIPTION:
158 pd->tmplang = join_dup(&pd->jd, solv_xmlparser_find_attr("xml:lang", atts));
161 case STATE_PACKAGEREQ:
163 const char *type = solv_xmlparser_find_attr("type", atts);
165 pd->reqtype = SOLVABLE_RECOMMENDS;
166 if (type && !strcmp(type, "conditional"))
168 const char *requires = solv_xmlparser_find_attr("requires", atts);
169 if (requires && *requires)
170 pd->condreq = pool_str2id(pool, requires, 1);
172 else if (type && !strcmp(type, "mandatory"))
173 pd->reqtype = SOLVABLE_REQUIRES;
174 else if (type && !strcmp(type, "optional"))
175 pd->reqtype = SOLVABLE_SUGGESTS;
179 case STATE_GROUPLIST:
181 pd->reqtype = SOLVABLE_REQUIRES;
185 case STATE_OPTIONLIST:
187 pd->reqtype = SOLVABLE_SUGGESTS;
198 endElement(struct solv_xmlparser *xmlp, int state, char *content)
200 struct parsedata *pd = xmlp->userdata;
201 Solvable *s = pd->solvable;
208 case STATE_ENVIRONMENT:
210 s->arch = ARCH_NOARCH;
213 if (s->name && s->arch != ARCH_SRC && s->arch != ARCH_NOSRC)
214 s->provides = repo_addid_dep(pd->repo, s->provides, pool_rel2id(pd->pool, s->name, s->evr, REL_EQ, 1), 0);
216 repodata_set_void(pd->data, pd->handle, SOLVABLE_ISVISIBLE);
218 repodata_set_void(pd->data, pd->handle, SOLVABLE_ISDEFAULT);
223 s->name = pool_str2id(pd->pool, join2(&pd->jd, pd->kind, ":", content), 1);
227 repodata_set_str(pd->data, pd->handle, pool_id2langid(pd->pool, SOLVABLE_SUMMARY, pd->tmplang, 1), content);
230 case STATE_DESCRIPTION:
231 repodata_set_str(pd->data, pd->handle, pool_id2langid(pd->pool, SOLVABLE_DESCRIPTION, pd->tmplang, 1), content);
234 case STATE_PACKAGEREQ:
235 id = pool_str2id(pd->pool, content, 1);
237 id = pool_rel2id(pd->pool, id, pd->condreq, REL_COND, 1);
238 repo_add_idarray(pd->repo, pd->handle, pd->reqtype, id);
242 id = pool_str2id(pd->pool, join2(&pd->jd, "group", ":", content), 1);
243 repo_add_idarray(pd->repo, pd->handle, pd->reqtype, id);
246 case STATE_USERVISIBLE:
247 pd->isvisible = parse_boolean(content, COMPS_DEFAULT_ISVISIBLE);
251 pd->isdefault = parse_boolean(content, COMPS_DEFAULT_ISDEFAULT);
254 case STATE_LANG_ONLY:
255 repodata_set_str(pd->data, pd->handle, SOLVABLE_LANGONLY, content);
259 repodata_set_str(pd->data, pd->handle, SOLVABLE_LANGONLY, content);
262 case STATE_DISPLAY_ORDER:
263 repodata_set_str(pd->data, pd->handle, SOLVABLE_ORDER, content);
272 repo_add_comps(Repo *repo, FILE *fp, int flags)
277 data = repo_add_repodata(repo, flags);
279 memset(&pd, 0, sizeof(pd));
281 pd.pool = repo->pool;
283 solv_xmlparser_init(&pd.xmlp, stateswitches, &pd, startElement, endElement);
284 if (solv_xmlparser_parse(&pd.xmlp, fp) != SOLV_XMLPARSER_OK)
285 pool_debug(pd.pool, SOLV_ERROR, "repo_comps: %s at line %u:%u\n", pd.xmlp.errstr, pd.xmlp.line, pd.xmlp.column);
286 solv_xmlparser_free(&pd.xmlp);
287 join_freemem(&pd.jd);
289 if (!(flags & REPO_NO_INTERNALIZE))
290 repodata_internalize(data);