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?
60 static struct solv_xmlparser_element stateswitches[] = {
61 { STATE_START, "comps", STATE_COMPS, 0 },
62 { STATE_COMPS, "group", STATE_GROUP, 0 },
63 { STATE_COMPS, "category", STATE_CATEGORY, 0 },
64 { STATE_GROUP, "id", STATE_ID, 1 },
65 { STATE_GROUP, "name", STATE_NAME, 1 },
66 { STATE_GROUP, "description", STATE_DESCRIPTION, 1 },
67 { STATE_GROUP, "uservisible", STATE_USERVISIBLE, 1 },
68 { STATE_GROUP, "display_order", STATE_DISPLAY_ORDER, 1 },
69 { STATE_GROUP, "default", STATE_DEFAULT, 1 },
70 { STATE_GROUP, "langonly", STATE_LANGONLY, 1 },
71 { STATE_GROUP, "lang_only", STATE_LANG_ONLY, 1 },
72 { STATE_GROUP, "packagelist", STATE_PACKAGELIST, 0 },
73 { STATE_PACKAGELIST, "packagereq", STATE_PACKAGEREQ, 1 },
74 { STATE_CATEGORY, "id", STATE_ID, 1 },
75 { STATE_CATEGORY, "name", STATE_NAME, 1 },
76 { STATE_CATEGORY, "description", STATE_DESCRIPTION, 1 },
77 { STATE_CATEGORY , "grouplist", STATE_GROUPLIST, 0 },
78 { STATE_CATEGORY , "display_order", STATE_DISPLAY_ORDER, 1 },
79 { STATE_GROUPLIST, "groupid", STATE_GROUPID, 1 },
90 struct solv_xmlparser xmlp;
105 #define COMPS_DEFAULT_ISVISIBLE 1
106 #define COMPS_DEFAULT_ISDEFAULT 0
108 /* Return true if "true", false if "false", default_value otherwise */
110 parse_boolean(char *content, int default_value)
112 if (!strcmp(content, "true"))
114 if (!strcmp(content, "false"))
116 return default_value;
121 startElement(struct solv_xmlparser *xmlp, int state, const char *name, const char **atts)
123 struct parsedata *pd = xmlp->userdata;
124 Pool *pool = pd->pool;
131 s = pd->solvable = pool_id2solvable(pool, repo_add_solvable(pd->repo));
132 pd->handle = s - pool->solvables;
133 pd->kind = state == STATE_GROUP ? "group" : "category";
134 pd->isvisible = COMPS_DEFAULT_ISVISIBLE;
135 pd->isdefault = COMPS_DEFAULT_ISDEFAULT;
140 case STATE_DESCRIPTION:
141 case STATE_CDESCRIPTION:
142 pd->tmplang = join_dup(&pd->jd, solv_xmlparser_find_attr("xml:lang", atts));
145 case STATE_PACKAGEREQ:
147 const char *type = solv_xmlparser_find_attr("type", atts);
149 pd->reqtype = SOLVABLE_RECOMMENDS;
150 if (type && !strcmp(type, "conditional"))
152 const char *requires = solv_xmlparser_find_attr("requires", atts);
153 if (requires && *requires)
154 pd->condreq = pool_str2id(pool, requires, 1);
156 else if (type && !strcmp(type, "mandatory"))
157 pd->reqtype = SOLVABLE_REQUIRES;
158 else if (type && !strcmp(type, "optional"))
159 pd->reqtype = SOLVABLE_SUGGESTS;
170 endElement(struct solv_xmlparser *xmlp, int state, char *content)
172 struct parsedata *pd = xmlp->userdata;
173 Solvable *s = pd->solvable;
181 s->arch = ARCH_NOARCH;
184 if (s->name && s->arch != ARCH_SRC && s->arch != ARCH_NOSRC)
185 s->provides = repo_addid_dep(pd->repo, s->provides, pool_rel2id(pd->pool, s->name, s->evr, REL_EQ, 1), 0);
187 repodata_set_void(pd->data, pd->handle, SOLVABLE_ISVISIBLE);
189 repodata_set_void(pd->data, pd->handle, SOLVABLE_ISDEFAULT);
194 s->name = pool_str2id(pd->pool, join2(&pd->jd, pd->kind, ":", content), 1);
198 repodata_set_str(pd->data, pd->handle, pool_id2langid(pd->pool, SOLVABLE_SUMMARY, pd->tmplang, 1), content);
201 case STATE_DESCRIPTION:
202 repodata_set_str(pd->data, pd->handle, pool_id2langid(pd->pool, SOLVABLE_DESCRIPTION, pd->tmplang, 1), content);
205 case STATE_PACKAGEREQ:
206 id = pool_str2id(pd->pool, content, 1);
208 id = pool_rel2id(pd->pool, id, pd->condreq, REL_COND, 1);
209 repo_add_idarray(pd->repo, pd->handle, pd->reqtype, id);
213 id = pool_str2id(pd->pool, join2(&pd->jd, "group", ":", content), 1);
214 s->requires = repo_addid_dep(pd->repo, s->requires, id, 0);
217 case STATE_USERVISIBLE:
218 pd->isvisible = parse_boolean(content, COMPS_DEFAULT_ISVISIBLE);
222 pd->isdefault = parse_boolean(content, COMPS_DEFAULT_ISDEFAULT);
225 case STATE_LANG_ONLY:
226 repodata_set_str(pd->data, pd->handle, SOLVABLE_LANGONLY, content);
230 repodata_set_str(pd->data, pd->handle, SOLVABLE_LANGONLY, content);
233 case STATE_DISPLAY_ORDER:
234 repodata_set_str(pd->data, pd->handle, SOLVABLE_ORDER, content);
243 repo_add_comps(Repo *repo, FILE *fp, int flags)
248 data = repo_add_repodata(repo, flags);
250 memset(&pd, 0, sizeof(pd));
252 pd.pool = repo->pool;
254 solv_xmlparser_init(&pd.xmlp, stateswitches, &pd, startElement, endElement);
255 if (solv_xmlparser_parse(&pd.xmlp, fp) != SOLV_XMLPARSER_OK)
256 pool_debug(pd.pool, SOLV_ERROR, "repo_comps: %s at line %u:%u\n", pd.xmlp.errstr, pd.xmlp.line, pd.xmlp.column);
257 solv_xmlparser_free(&pd.xmlp);
258 join_freemem(&pd.jd);
260 if (!(flags & REPO_NO_INTERNALIZE))
261 repodata_internalize(data);