Use strings to identify section types in the on-disk repo format.
Previously, a given razor file type had a fixed number of sections in a
fixed order, identified by an integer type. Now, sections are identified
by a named string (stored in a string pool after the section lists).
This will allow for razor files to contain arbitrary sections.
For bonus points, also drop the 4k section alignment and change the
magic byte string to "RZDB".
committer: Kristian H?gsberg <krh@redhat.com>
2 * Copyright (C) 2008 Kristian Høgsberg <krh@redhat.com>
3 * Copyright (C) 2008 Red Hat, Inc
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
30 #define XML_BUFFER_SIZE 4096
33 parse_xml_file(const char *filename,
34 XML_StartElementHandler start,
35 XML_EndElementHandler end,
42 parser = XML_ParserCreate(NULL);
43 XML_SetElementHandler(parser, start, end);
44 XML_SetUserData(parser, data);
46 fd = open(filename, O_RDONLY);
48 fprintf(stderr, "failed to open %s: %m\n", filename);
53 buffer = XML_GetBuffer(parser, XML_BUFFER_SIZE);
54 len = read(fd, buffer, XML_BUFFER_SIZE);
57 err = XML_ParseBuffer(parser, len, len == 0);
58 if (err == XML_STATUS_ERROR) {
59 fprintf(stderr, "parse error at line %lu:\n%s\n",
60 XML_GetCurrentLineNumber(parser),
61 XML_ErrorString(XML_GetErrorCode(parser)));
67 fprintf(stderr, "read: %m\n");
75 struct razor_set *system_set, *repo_set, *result_set;
77 struct razor_importer *importer;
78 struct razor_set **importer_set;
80 struct razor_transaction *trans;
82 char *install_pkgs[3], *remove_pkgs[3];
83 int n_install_pkgs, n_remove_pkgs;
92 get_atts(const char **atts, ...)
95 const char *name, **ptr;
99 while (name = va_arg(ap, const char *), name != NULL) {
100 ptr = va_arg(ap, const char **);
102 for (i = 0; atts[i]; i += 2) {
103 if (strcmp(atts[i], name) == 0)
110 static enum razor_property_flags
111 parse_relation (const char *rel_str)
115 if (rel_str[0] == 'L')
116 return rel_str[1] == 'E' ? RAZOR_PROPERTY_LESS | RAZOR_PROPERTY_EQUAL : RAZOR_PROPERTY_LESS;
117 else if (rel_str[0] == 'G')
118 return rel_str[1] == 'E' ? RAZOR_PROPERTY_GREATER | RAZOR_PROPERTY_EQUAL : RAZOR_PROPERTY_GREATER;
119 else if (rel_str[0] == 'E' || rel_str[1] == 'Q')
120 return RAZOR_PROPERTY_EQUAL;
126 start_test(struct test_context *ctx, const char **atts)
128 const char *name = NULL;
130 get_atts(atts, "name", &name, NULL);
132 fprintf(stderr, "Test with no name\n");
135 printf("%s\n", name);
139 end_test(struct test_context *ctx)
141 if (ctx->system_set) {
142 razor_set_destroy(ctx->system_set);
143 ctx->system_set = NULL;
146 razor_set_destroy(ctx->repo_set);
147 ctx->repo_set = NULL;
149 if (ctx->result_set) {
150 razor_set_destroy(ctx->result_set);
151 ctx->result_set = NULL;
154 razor_transaction_destroy(ctx->trans);
160 start_set(struct test_context *ctx, const char **atts)
162 const char *name = NULL;
164 ctx->importer = razor_importer_create();
165 get_atts(atts, "name", &name, NULL);
167 ctx->importer_set = &ctx->result_set;
168 else if (!strcmp(name, "system"))
169 ctx->importer_set = &ctx->system_set;
170 else if (!strcmp(name, "repo"))
171 ctx->importer_set = &ctx->repo_set;
173 fprintf(stderr, " bad set name '%s'\n", name);
179 end_set(struct test_context *ctx)
181 *ctx->importer_set = razor_importer_finish(ctx->importer);
182 ctx->importer = NULL;
186 start_package(struct test_context *ctx, const char **atts)
188 const char *name = NULL, *version = NULL, *arch = NULL;
190 get_atts(atts, "name", &name,
196 fprintf(stderr, " package with no name\n");
200 razor_importer_begin_package(ctx->importer, name, version, arch);
201 razor_importer_add_property(ctx->importer, name,
202 RAZOR_PROPERTY_EQUAL | RAZOR_PROPERTY_PROVIDES,
207 end_package(struct test_context *ctx)
209 razor_importer_finish_package(ctx->importer);
213 add_property(struct test_context *ctx, enum razor_property_flags type, const char *name, enum razor_property_flags rel, const char *version)
215 razor_importer_add_property(ctx->importer, name,
216 rel | type, version);
220 razor_property_flags_relation_to_string(enum razor_property_flags rel)
222 if (rel == RAZOR_PROPERTY_LESS)
224 if (rel == (RAZOR_PROPERTY_EQUAL | RAZOR_PROPERTY_LESS))
226 if (rel == RAZOR_PROPERTY_EQUAL)
228 if (rel == (RAZOR_PROPERTY_EQUAL | RAZOR_PROPERTY_GREATER))
230 if (rel == RAZOR_PROPERTY_GREATER)
237 check_unsatisfiable_property(struct test_context *ctx,
238 enum razor_property_flags type,
240 enum razor_property_flags rel,
246 if (razor_transaction_unsatisfied_property(ctx->trans,
247 name, rel | type, version))
250 fprintf(stderr, " didn't get unsatisfiable '%s %s %s'\n",
251 name, razor_property_flags_relation_to_string(rel), version);
256 start_property(struct test_context *ctx, enum razor_property_flags type, const char **atts)
258 const char *name = NULL, *rel_str = NULL, *version = NULL;
259 enum razor_property_flags rel;
261 get_atts(atts, "name", &name, "relation", &rel_str, "version", &version, NULL);
263 fprintf(stderr, " no name specified for property\n");
267 rel = parse_relation(rel_str);
269 fprintf(stderr, " bad or missing version relation for property %s\n", name);
273 rel = RAZOR_PROPERTY_EQUAL;
276 check_unsatisfiable_property(ctx, type, name, rel, version);
278 add_property(ctx, type, name, rel, version);
282 start_transaction(struct test_context *ctx, const char **atts)
284 ctx->n_install_pkgs = 0;
285 ctx->n_remove_pkgs = 0;
288 static struct razor_package *
289 get_package(struct razor_set *set, const char *package)
291 struct razor_package_iterator *pi;
292 struct razor_package *p;
293 const char *name, *version, *arch;
295 pi = razor_package_iterator_create(set);
296 while (razor_package_iterator_next(pi, &p, RAZOR_DETAIL_NAME, &name,
297 RAZOR_DETAIL_VERSION, &version,
298 RAZOR_DETAIL_ARCH, &arch,
299 RAZOR_DETAIL_LAST)) {
300 if (strcmp(package, name) == 0)
303 razor_package_iterator_destroy(pi);
309 end_transaction(struct test_context *ctx)
311 struct razor_package *pkg;
314 ctx->trans = razor_transaction_create(ctx->system_set, ctx->repo_set);
315 for (i = 0; i < ctx->n_install_pkgs; i++) {
316 pkg = get_package(ctx->repo_set, ctx->install_pkgs[i]);
317 razor_transaction_install_package(ctx->trans, pkg);
319 for (i = 0; i < ctx->n_remove_pkgs; i++) {
320 pkg = get_package(ctx->system_set, ctx->remove_pkgs[i]);
322 pkg = get_package(ctx->repo_set, ctx->remove_pkgs[i]);
324 razor_transaction_remove_package(ctx->trans, pkg);
327 razor_transaction_resolve(ctx->trans);
328 errors = razor_transaction_describe(ctx->trans);
331 while (ctx->n_install_pkgs--)
332 free(ctx->install_pkgs[ctx->n_install_pkgs]);
333 while (ctx->n_remove_pkgs--)
334 free(ctx->remove_pkgs[ctx->n_remove_pkgs]);
337 struct razor_set *new;
338 new = razor_transaction_finish(ctx->trans);
340 ctx->system_set = new;
345 start_install_or_update(struct test_context *ctx, const char **atts)
347 const char *name = NULL;
349 get_atts(atts, "name", &name, NULL);
351 fprintf(stderr, " install/update with no name\n");
355 ctx->install_pkgs[ctx->n_install_pkgs++] = strdup(name);
359 start_remove(struct test_context *ctx, const char **atts)
361 const char *name = NULL;
363 get_atts(atts, "name", &name, NULL);
365 fprintf(stderr, " remove with no name\n");
369 ctx->remove_pkgs[ctx->n_remove_pkgs++] = strdup(name);
373 start_result(struct test_context *ctx, const char **atts)
379 diff_callback(enum razor_diff_action action,
380 struct razor_package *package,
386 struct test_context *ctx = data;
389 if (action == RAZOR_DIFF_ACTION_REMOVE) {
390 fprintf(stderr, " result set should not contain %s %s\n",
393 fprintf(stderr, " result set should contain %s %s\n",
399 end_result(struct test_context *ctx)
403 if (ctx->result_set) {
404 if (!ctx->system_set)
405 ctx->system_set = razor_set_create();
406 razor_set_diff(ctx->system_set, ctx->result_set,
412 start_unsatisfiable(struct test_context *ctx, const char **atts)
414 if (ctx->result_set) {
415 fprintf(stderr, "Expected to fail, but didn't\n");
423 end_unsatisfiable(struct test_context *ctx)
429 start_test_element(void *data, const char *element, const char **atts)
431 struct test_context *ctx = data;
433 if (strcmp(element, "tests") == 0) {
435 } else if (strcmp(element, "test") == 0) {
436 start_test(ctx, atts);
437 } else if (strcmp(element, "set") == 0) {
438 start_set(ctx, atts);
439 } else if (strcmp(element, "transaction") == 0) {
440 start_transaction(ctx, atts);
441 } else if (strcmp(element, "install") == 0) {
442 start_install_or_update(ctx, atts);
443 } else if (strcmp(element, "install") == 0) {
444 start_install_or_update(ctx, atts);
445 } else if (strcmp(element, "remove") == 0) {
446 start_remove(ctx, atts);
447 } else if (strcmp(element, "result") == 0) {
448 start_result(ctx, atts);
449 } else if (strcmp(element, "unsatisfiable") == 0) {
450 start_unsatisfiable(ctx, atts);
451 } else if (strcmp(element, "package") == 0) {
452 start_package(ctx, atts);
453 } else if (strcmp(element, "requires") == 0) {
454 start_property(ctx, RAZOR_PROPERTY_REQUIRES, atts);
455 } else if (strcmp(element, "provides") == 0) {
456 start_property(ctx, RAZOR_PROPERTY_PROVIDES, atts);
457 } else if (strcmp(element, "conflicts") == 0) {
458 start_property(ctx, RAZOR_PROPERTY_CONFLICTS, atts);
459 } else if (strcmp(element, "obsoletes") == 0) {
460 start_property(ctx, RAZOR_PROPERTY_OBSOLETES, atts);
462 fprintf(stderr, "Unrecognized element '%s'\n", element);
468 end_test_element (void *data, const char *element)
470 struct test_context *ctx = data;
472 if (strcmp(element, "test") == 0) {
474 } else if (strcmp(element, "set") == 0) {
476 } else if (strcmp(element, "package") == 0) {
478 } else if (strcmp(element, "transaction") == 0) {
479 end_transaction(ctx);
480 } else if (strcmp(element, "result") == 0) {
482 } else if (strcmp(element, "unsatisfiable") == 0) {
483 end_unsatisfiable(ctx);
487 int main(int argc, char *argv[])
489 struct test_context ctx;
490 const char *test_file;
492 memset(&ctx, 0, sizeof ctx);
495 fprintf(stderr, "usage: %s [-d] [TESTS-FILE]\n", argv[0]);
499 if (argc >= 2 && !strcmp (argv[1], "-d")) {
507 test_file = "test.xml";
509 parse_xml_file(test_file, start_test_element, end_test_element, &ctx);
512 fprintf(stderr, "\n%d errors\n", ctx.errors);