1.1 --- a/main.c Fri Feb 29 11:51:58 2008 -0500
1.2 +++ b/main.c Fri Feb 29 11:53:15 2008 -0500
1.3 @@ -14,10 +14,6 @@
1.4 static const char *rawhide_repo_filename = "rawhide.repo";
1.5 static const char *updated_repo_filename = "system-updated.repo";
1.6
1.7 -static const char *relations[] = {
1.8 - "<", "<=", "=", ">=", ">"
1.9 -};
1.10 -
1.11 static int
1.12 command_list(int argc, const char *argv[])
1.13 {
1.14 @@ -67,8 +63,8 @@
1.15 if (version[0] == '\0')
1.16 printf("%s\n", name);
1.17 else
1.18 - printf("%s %s %s\n", name, relations[relation],
1.19 - version);
1.20 + printf("%s %s %s\n", name,
1.21 + razor_version_relations[relation], version);
1.22 }
1.23 razor_property_iterator_destroy(pi);
1.24
1.25 @@ -325,12 +321,19 @@
1.26 command_update(int argc, const char *argv[])
1.27 {
1.28 struct razor_set *set, *upstream;
1.29 + struct razor_transaction *trans;
1.30
1.31 set = razor_set_open(repo_filename);
1.32 upstream = razor_set_open(rawhide_repo_filename);
1.33 if (set == NULL || upstream == NULL)
1.34 return 1;
1.35 - set = razor_set_update(set, upstream, argc, argv);
1.36 + trans = razor_transaction_create(set, upstream, argc, argv, 0, NULL);
1.37 + razor_transaction_describe(trans);
1.38 + if (trans->errors)
1.39 + return 1;
1.40 +
1.41 + set = razor_transaction_run(trans);
1.42 + razor_transaction_destroy(trans);
1.43 razor_set_write(set, updated_repo_filename);
1.44 razor_set_destroy(set);
1.45 razor_set_destroy(upstream);
1.46 @@ -343,11 +346,18 @@
1.47 command_remove(int argc, const char *argv[])
1.48 {
1.49 struct razor_set *set;
1.50 + struct razor_transaction *trans;
1.51
1.52 set = razor_set_open(repo_filename);
1.53 if (set == NULL)
1.54 return 1;
1.55 - set = razor_set_remove(set, argc, argv);
1.56 + trans = razor_transaction_create(set, NULL, 0, NULL, argc, argv);
1.57 + razor_transaction_describe(trans);
1.58 + if (trans->errors)
1.59 + return 1;
1.60 +
1.61 + set = razor_transaction_run(trans);
1.62 + razor_transaction_destroy(trans);
1.63 razor_set_write(set, updated_repo_filename);
1.64 razor_set_destroy(set);
1.65 printf("wrote system-updated.repo\n");
2.1 --- a/razor.c Fri Feb 29 11:51:58 2008 -0500
2.2 +++ b/razor.c Fri Feb 29 11:53:15 2008 -0500
2.3 @@ -382,7 +382,7 @@
2.4 __qsort_with_data(end, right, mend, ctx);
2.5 }
2.6
2.7 -uint32_t *
2.8 +static uint32_t *
2.9 qsort_with_data(void *base, size_t nelem, size_t size,
2.10 compare_with_data_func_t compare, void *data)
2.11 {
2.12 @@ -758,7 +758,7 @@
2.13 struct list *index;
2.14 };
2.15
2.16 -struct razor_package_iterator *
2.17 +static struct razor_package_iterator *
2.18 razor_package_iterator_create_with_index(struct razor_set *set,
2.19 struct list *index)
2.20 {
2.21 @@ -1231,53 +1231,6 @@
2.22 }
2.23 }
2.24
2.25 -
2.26 -/* Build the new package list sorted by merging the two package lists.
2.27 - * Build new string pool as we go. */
2.28 -static void
2.29 -merge_packages(struct razor_merger *merger, struct array *packages)
2.30 -{
2.31 - struct razor_package *upstream_packages, *p, *s, *send;
2.32 - struct source *source1, *source2;
2.33 - char *spool, *upool;
2.34 - uint32_t *u, *uend;
2.35 - int cmp;
2.36 -
2.37 - source1 = &merger->source1;
2.38 - source2 = &merger->source2;
2.39 - upstream_packages = source2->set->packages.data;
2.40 -
2.41 - u = packages->data;
2.42 - uend = packages->data + packages->size;
2.43 - upool = source2->set->string_pool.data;
2.44 -
2.45 - s = source1->set->packages.data;
2.46 - send = source1->set->packages.data + source1->set->packages.size;
2.47 - spool = source1->set->string_pool.data;
2.48 -
2.49 - while (s < send || u < uend) {
2.50 - p = upstream_packages + *u;
2.51 -
2.52 - if (s < send && u < uend)
2.53 - cmp = strcmp(&spool[s->name], &upool[p->name]);
2.54 - else if (s < send)
2.55 - cmp = -1;
2.56 - else
2.57 - cmp = 1;
2.58 - if (cmp < 0) {
2.59 - add_package(merger, s, source1, 0);
2.60 - s++;
2.61 - } else if (cmp == 0) {
2.62 - add_package(merger, p, source2, UPSTREAM_SOURCE);
2.63 - s++;
2.64 - u++;
2.65 - } else {
2.66 - add_package(merger, p, source2, UPSTREAM_SOURCE);
2.67 - u++;
2.68 - }
2.69 - }
2.70 -}
2.71 -
2.72 static uint32_t
2.73 add_property(struct razor_merger *merger,
2.74 const char *name, enum razor_version_relation relation,
2.75 @@ -1648,7 +1601,7 @@
2.76 free(pkgs);
2.77 }
2.78
2.79 -struct razor_set *
2.80 +static struct razor_set *
2.81 razor_merger_finish(struct razor_merger *merger)
2.82 {
2.83 struct razor_set *result;
2.84 @@ -1698,112 +1651,58 @@
2.85 return result;
2.86 }
2.87
2.88 -/* Add packages from 'upstream' to 'set'. The packages to add are
2.89 - * specified by the 'packages' array, which is a sorted list of
2.90 - * package indexes. Returns a newly allocated package set. Does not
2.91 - * enforce validity of the resulting package set.
2.92 - *
2.93 - * This looks more complicated than it is. An easy way to merge two
2.94 - * package sets would be to just use a razor_importer, but that
2.95 - * requires resorting, and is thus O(n log n). We can do this in a
2.96 - * linear sweep, but it gets a little more complicated.
2.97 - */
2.98 -struct razor_set *
2.99 -razor_set_add(struct razor_set *set, struct razor_set *upstream,
2.100 - struct array *packages)
2.101 -{
2.102 - struct razor_merger *merger;
2.103 -
2.104 - merger = razor_merger_create(set, upstream);
2.105 -
2.106 - merge_packages(merger, packages);
2.107 -
2.108 - return razor_merger_finish(merger);
2.109 -}
2.110 -
2.111 -void
2.112 -razor_set_satisfy(struct razor_set *set, struct array *unsatisfied,
2.113 - struct razor_set *upstream, struct array *list)
2.114 -{
2.115 - struct razor_property *requires, *r;
2.116 - struct razor_property *p, *pend;
2.117 - uint32_t *u, *end, *pkg;
2.118 - struct array *package_pool;
2.119 - char *pool, *upool;
2.120 -
2.121 - end = unsatisfied->data + unsatisfied->size;
2.122 - requires = set->properties.data;
2.123 - pool = set->string_pool.data;
2.124 -
2.125 - p = upstream->properties.data;
2.126 - pend = upstream->properties.data + upstream->properties.size;
2.127 - upool = upstream->string_pool.data;
2.128 - package_pool = &upstream->package_pool;
2.129 -
2.130 - u = unsatisfied->data;
2.131 - while (u < end) {
2.132 - r = requires + *u;
2.133 -
2.134 - while (p < pend &&
2.135 - p->type != RAZOR_PROPERTY_PROVIDES &&
2.136 - strcmp(&pool[r->name], &upool[p->name]) > 0)
2.137 - p++;
2.138 - /* If there is more than one version of a provides,
2.139 - * seek to the end for the highest version. */
2.140 - while (p + 1 < pend && p->name == (p + 1)->name && p->type == (p + 1)->type)
2.141 - p++;
2.142 -
2.143 - if (p != pend &&
2.144 - p->type == RAZOR_PROPERTY_PROVIDES &&
2.145 - strcmp(&pool[r->name], &upool[p->name]) == 0 &&
2.146 - versioncmp(&pool[r->version], &upool[p->version]) <= 0) {
2.147 - pkg = array_add(list, sizeof *pkg);
2.148 - /* We just pull in the first package that provides */
2.149 - *pkg = list_first(&p->packages, package_pool)->data;
2.150 -
2.151 - /* Remove this from the unsatisfied list */
2.152 - memmove (u, u + 1, end - (u + 1));
2.153 - end--;
2.154 - } else {
2.155 - /* Leave this in the unsatisfied list */
2.156 - u++;
2.157 - }
2.158 - }
2.159 - unsatisfied->size = (void *)end - unsatisfied->data;
2.160 -}
2.161 -
2.162 -static void
2.163 -find_packages(struct razor_set *set,
2.164 - int count, const char **package_names, struct array *list)
2.165 +static int
2.166 +find_packages(struct razor_set *set, int count, const char **package_names,
2.167 + struct array *package_array,
2.168 + enum razor_transaction_package_state state)
2.169 {
2.170 struct razor_package_iterator *pi;
2.171 struct razor_package *p, *packages;
2.172 const char *name, *version;
2.173 - uint32_t *r;
2.174 - int i;
2.175 + struct razor_transaction_package *tp;
2.176 + int i, *found, errors = 0;
2.177
2.178 packages = (struct razor_package *) set->packages.data;
2.179 pi = razor_package_iterator_create(set);
2.180 + found = zalloc(count * sizeof (int));
2.181
2.182 while (razor_package_iterator_next(pi, &p, &name, &version)) {
2.183 for (i = 0; i < count; i++) {
2.184 if (strcmp(name, package_names[i]) == 0) {
2.185 - r = array_add(list, sizeof *r);
2.186 - *r = p - packages;
2.187 + found[i] = 1;
2.188 + tp = array_add(package_array, sizeof *tp);
2.189 + memset(tp, 0, sizeof *tp);
2.190 + tp->package = p;
2.191 + tp->name = name;
2.192 + tp->version = version;
2.193 + tp->state = state;
2.194 break;
2.195 }
2.196 }
2.197 }
2.198
2.199 + for (i = 0; i < count; i++) {
2.200 + if (!found[i]) {
2.201 + tp = array_add(package_array, sizeof *tp);
2.202 + memset(tp, 0, sizeof *tp);
2.203 + tp->name = strdup(package_names[i]);
2.204 + tp->state = state | RAZOR_PACKAGE_UNAVAILABLE;
2.205 + errors++;
2.206 + }
2.207 + }
2.208 +
2.209 razor_package_iterator_destroy(pi);
2.210 + free(found);
2.211 +
2.212 + return errors;
2.213 }
2.214
2.215 static void
2.216 find_all_packages(struct razor_set *set,
2.217 - struct razor_set *upstream, struct array *list)
2.218 + struct razor_set *upstream, struct array *package_array)
2.219 {
2.220 + struct razor_transaction_package *tp;
2.221 struct razor_package *p, *u, *pend, *uend;
2.222 - uint32_t *r;
2.223 char *pool, *upool;
2.224
2.225 pend = set->packages.data + set->packages.size;
2.226 @@ -1816,25 +1715,89 @@
2.227 while (u < uend && strcmp(&pool[p->name], &upool[u->name]) > 0)
2.228 u++;
2.229 if (strcmp(&pool[p->name], &upool[u->name]) == 0) {
2.230 - r = array_add(list, sizeof *r);
2.231 - *r = u - (struct razor_package *) upstream->packages.data;
2.232 + tp = array_add(package_array, sizeof *tp);
2.233 + memset(tp, 0, sizeof *tp);
2.234 + tp->name = &upool[u->name];
2.235 + tp->version = &upool[u->version];
2.236 + tp->state = RAZOR_PACKAGE_INSTALL;
2.237 }
2.238 }
2.239 }
2.240
2.241 +/* FIXME: wrong, need to compare names, not razor_package* */
2.242 static int
2.243 -find_provider(struct razor_set *set, const char *req_name,
2.244 - enum razor_version_relation relation, const char *version)
2.245 +find_transaction_package(struct array *package_array,
2.246 + struct razor_package *package)
2.247 +{
2.248 + struct razor_transaction_package *tps = package_array->data;
2.249 + int i, tpcount = package_array->size / sizeof *tps;
2.250 +
2.251 + for (i = 0; i < tpcount; i++) {
2.252 + if (tps[i].package == package)
2.253 + return i;
2.254 + }
2.255 + return -1;
2.256 +}
2.257 +
2.258 +static int
2.259 +provider_satisfies_requirement(struct razor_property *provider,
2.260 + const char *provider_strings,
2.261 + struct razor_property *requirement,
2.262 + const char *requirement_strings)
2.263 +{
2.264 + int cmp, len;
2.265 + const char *provided = &provider_strings[provider->version];
2.266 + const char *required = &requirement_strings[requirement->version];
2.267 +
2.268 + if (!*required)
2.269 + return 1;
2.270 +
2.271 + cmp = versioncmp(provided, required);
2.272 +
2.273 + switch (requirement->relation) {
2.274 + case RAZOR_VERSION_LESS:
2.275 + return cmp < 0;
2.276 +
2.277 + case RAZOR_VERSION_LESS_OR_EQUAL:
2.278 + if (cmp <= 0)
2.279 + return 1;
2.280 + /* fall through: FIXME, make sure this is correct */
2.281 +
2.282 + case RAZOR_VERSION_EQUAL:
2.283 + if (cmp == 0)
2.284 + return 1;
2.285 +
2.286 + /* "foo == 1.1" is satisfied by "foo 1.1-2" */
2.287 + len = strlen(required);
2.288 + if (!strncmp(required, provided, len) && provided[len] == '-')
2.289 + return 1;
2.290 + return 0;
2.291 +
2.292 + case RAZOR_VERSION_GREATER_OR_EQUAL:
2.293 + return cmp >= 0;
2.294 +
2.295 + case RAZOR_VERSION_GREATER:
2.296 + return cmp > 0;
2.297 + }
2.298 +
2.299 + /* shouldn't happen */
2.300 + return 0;
2.301 +}
2.302 +
2.303 +static int
2.304 +find_provider(struct razor_set *set, struct razor_property *requirement,
2.305 + const char *requirement_strings)
2.306 {
2.307 struct razor_property *props = set->properties.data;
2.308 - int p, hi, lo, cmp, pkg;
2.309 + int p, hi, lo, cmp;
2.310 char *pool = set->string_pool.data;
2.311
2.312 lo = 0;
2.313 hi = set->properties.size / sizeof *props;
2.314 while (lo < hi) {
2.315 p = (lo + hi) / 2;
2.316 - cmp = strcmp(&pool[props[p].name], req_name);
2.317 + cmp = strcmp(&pool[props[p].name],
2.318 + &requirement_strings[requirement->name]);
2.319 if (cmp < 0)
2.320 lo = p + 1;
2.321 else if (cmp > 0)
2.322 @@ -1868,35 +1831,9 @@
2.323 return -1;
2.324
2.325 do {
2.326 - pkg = list_first(&props[p].packages, &set->package_pool)->data;
2.327 - if (!*version)
2.328 - return pkg;
2.329 -
2.330 - cmp = versioncmp(&pool[props[p].version], version);
2.331 -
2.332 - switch (relation) {
2.333 - case RAZOR_VERSION_EQUAL:
2.334 - case RAZOR_VERSION_GREATER_OR_EQUAL:
2.335 - case RAZOR_VERSION_GREATER:
2.336 - if (cmp >= 0)
2.337 - return pkg;
2.338 - else {
2.339 - /* If the highest version doesn't pass,
2.340 - * none of the others will either.
2.341 - */
2.342 - return -1;
2.343 - }
2.344 -
2.345 - case RAZOR_VERSION_LESS_OR_EQUAL:
2.346 - if (cmp <= 0)
2.347 - return pkg;
2.348 - break;
2.349 -
2.350 - case RAZOR_VERSION_LESS:
2.351 - if (cmp < 0)
2.352 - return pkg;
2.353 - break;
2.354 - }
2.355 + if (provider_satisfies_requirement(&props[p], pool,
2.356 + requirement, requirement_strings))
2.357 + return list_first(&props[p].packages, &set->package_pool)->data;
2.358
2.359 p--;
2.360 } while (p > lo && props[p].name == props[p + 1].name &&
2.361 @@ -1921,78 +1858,79 @@
2.362 if (!strncmp(&upool[prop->name], "rpmlib(", 7))
2.363 continue;
2.364
2.365 - if (find_provider(system, &upool[prop->name],
2.366 - prop->relation, &upool[prop->version]) == -1) {
2.367 + if (find_provider(system, prop, upool) == -1) {
2.368 new = array_add(new_requires, sizeof *new);
2.369 *new = p->data;
2.370 }
2.371 }
2.372 }
2.373
2.374 -struct razor_set *
2.375 -razor_set_update(struct razor_set *set, struct razor_set *upstream,
2.376 - int count, const char **packages)
2.377 +static void
2.378 +razor_transaction_satisfy_installs(struct razor_transaction *trans,
2.379 + struct array *package_array,
2.380 + int start, int end)
2.381 {
2.382 - struct razor_set *new_set;
2.383 - struct array list;
2.384 struct razor_package *pkgs;
2.385 - int update_count, u, provider, already;
2.386 - uint32_t *update, *new, *new_end, *required;
2.387 + struct razor_transaction_package *packages, *tp;
2.388 + int p, provider, already;
2.389 + uint32_t *new, *new_end;
2.390 struct razor_property *props, *prop_end;
2.391 struct array new_requires;
2.392 char *pool;
2.393
2.394 - pkgs = upstream->packages.data;
2.395 - props = upstream->properties.data;
2.396 - prop_end = upstream->properties.data + set->properties.size;
2.397 - pool = upstream->string_pool.data;
2.398 + pkgs = trans->upstream->packages.data;
2.399 + props = trans->upstream->properties.data;
2.400 + prop_end = trans->upstream->properties.data + trans->upstream->properties.size;
2.401 + pool = trans->upstream->string_pool.data;
2.402
2.403 - array_init(&list);
2.404 - if (count > 0)
2.405 - find_packages(upstream, count, packages, &list);
2.406 - else
2.407 - find_all_packages(set, upstream, &list);
2.408 + packages = package_array->data;
2.409 + for (p = start; p < end; p++) {
2.410 + if (packages[p].state != RAZOR_PACKAGE_INSTALL)
2.411 + continue;
2.412
2.413 - update = list.data;
2.414 - update_count = list.size / sizeof (uint32_t);
2.415 - u = 0;
2.416 - while (u < update_count) {
2.417 array_init(&new_requires);
2.418 - for (; u < update_count; u++)
2.419 - gather_new_requires(set, upstream, &pkgs[update[u]], &new_requires);
2.420 + gather_new_requires(trans->system, trans->upstream,
2.421 + packages[p].package, &new_requires);
2.422
2.423 new_end = new_requires.data + new_requires.size;
2.424 for (new = new_requires.data; new < new_end; new++) {
2.425 - provider = find_provider(upstream, &pool[props[*new].name],
2.426 - props[*new].relation,
2.427 - &pool[props[*new].version]);
2.428 -
2.429 /* FIXME */
2.430 - if (provider == -1)
2.431 + if (pool[props[*new].name] == '/')
2.432 continue;
2.433
2.434 - update = list.data;
2.435 - update_count = list.size / sizeof (uint32_t);
2.436 - for (already = 0; already < update_count; already++) {
2.437 - if (provider == update[already])
2.438 - break;
2.439 - }
2.440 - if (already < update_count)
2.441 + provider = find_provider(trans->upstream,
2.442 + &props[*new], pool);
2.443 + already = find_transaction_package(package_array,
2.444 + &pkgs[provider]);
2.445 + if (already != -1 &&
2.446 + (packages[already].state & RAZOR_PACKAGE_INSTALL))
2.447 continue;
2.448
2.449 - required = array_add(&list, sizeof *required);
2.450 - *required = provider;
2.451 + tp = array_add(package_array, sizeof *tp);
2.452 + memset(tp, 0, sizeof *tp);
2.453 + tp->req_package = packages[p].name;
2.454 + tp->req_property = &pool[props[*new].name];
2.455 + tp->req_relation = props[*new].relation;
2.456 + tp->req_version = &pool[props[*new].version];
2.457 +
2.458 + if (provider != -1) {
2.459 + tp->package = &pkgs[provider];
2.460 + tp->name = &pool[tp->package->name];
2.461 + tp->version = &pool[tp->package->version];
2.462 + if (already != -1) {
2.463 + tp->state = RAZOR_PACKAGE_INSTALL_BLOCKED;
2.464 + trans->errors++;
2.465 + } else
2.466 + tp->state = RAZOR_PACKAGE_INSTALL;
2.467 + } else {
2.468 + tp->state = RAZOR_PACKAGE_INSTALL_UNSATISFIABLE;
2.469 + trans->errors++;
2.470 + }
2.471 +
2.472 + packages = package_array->data;
2.473 }
2.474 array_release(&new_requires);
2.475 -
2.476 - update = list.data;
2.477 - update_count = list.size / sizeof (uint32_t);
2.478 }
2.479 -
2.480 - new_set = razor_set_add(set, upstream, &list);
2.481 - array_release(&list);
2.482 - razor_set_destroy(set);
2.483 - return new_set;
2.484 }
2.485
2.486 /* Look through pkg's PROVIDES, and for each one that no other package
2.487 @@ -2019,101 +1957,102 @@
2.488 }
2.489 }
2.490
2.491 -/* Add the index of each package required by req that isn't already in
2.492 - * lost_requires, to lost_requires
2.493 - */
2.494 static void
2.495 -gather_lost_requires(struct razor_set *set, struct razor_property *req,
2.496 - struct array *lost_requires)
2.497 +lose_requirement(struct razor_transaction *trans, struct array *package_array,
2.498 + const char *req_package, struct razor_property *req,
2.499 + struct razor_property *lost_provider,
2.500 + struct razor_property *first_provider)
2.501 {
2.502 + struct razor_property *provider, *prop_end;
2.503 + struct razor_package *pkgs;
2.504 + char *pool = trans->system->string_pool.data;
2.505 struct list *p;
2.506 - uint32_t *lost, *already_lost, *already_end;
2.507 + struct razor_transaction_package *tp, *packages;;
2.508 + int already;
2.509
2.510 - for (p = list_first(&req->packages, &set->package_pool); p; p = list_next(p)) {
2.511 - already_end = lost_requires->data + lost_requires->size;
2.512 - for (already_lost = lost_requires->data; already_lost < already_end; already_lost++) {
2.513 - if (*already_lost == p->data)
2.514 - break;
2.515 - }
2.516 + pkgs = trans->system->packages.data;
2.517 + prop_end = trans->system->properties.data + trans->system->properties.size;
2.518
2.519 - if (already_lost == already_end) {
2.520 - lost = array_add(lost_requires, sizeof *lost);
2.521 - *lost = p->data;
2.522 - }
2.523 + /* See if any other provider satisfies req */
2.524 + for (provider = first_provider;
2.525 + provider < prop_end && provider->type == RAZOR_PROPERTY_PROVIDES && provider->name == lost_provider->name;
2.526 + provider++) {
2.527 + if (provider == lost_provider)
2.528 + continue;
2.529 +
2.530 + if (provider_satisfies_requirement(provider, pool, req, pool))
2.531 + return;
2.532 + }
2.533 +
2.534 + /* Remove each of the packages requiring req */
2.535 + for (p = list_first(&req->packages, &trans->system->package_pool); p; p = list_next(p)) {
2.536 + packages = package_array->data;
2.537 + already = find_transaction_package(package_array, &pkgs[p->data]);
2.538 + if (already != -1 &&
2.539 + (packages[already].state & RAZOR_PACKAGE_REMOVE))
2.540 + continue;
2.541 +
2.542 + tp = array_add(package_array, sizeof *tp);
2.543 + memset(tp, 0, sizeof *tp);
2.544 + tp->package = &pkgs[p->data];
2.545 + tp->name = &pool[tp->package->name];
2.546 + tp->version = &pool[tp->package->version];
2.547 + tp->req_package = req_package;
2.548 + tp->req_property = &pool[req->name];
2.549 + tp->req_relation = req->relation;
2.550 + tp->req_version = &pool[req->version];
2.551 + if (already != -1) {
2.552 + tp->state = RAZOR_PACKAGE_REMOVE_BLOCKED;
2.553 + trans->errors++;
2.554 + } else
2.555 + tp->state = RAZOR_PACKAGE_REMOVE;
2.556 }
2.557 }
2.558
2.559 -static struct razor_set *
2.560 -razor_set_remove_internal(struct razor_set *set, struct array *list)
2.561 +static void
2.562 +razor_transaction_satisfy_removes(struct razor_transaction *trans,
2.563 + struct array *package_array,
2.564 + int start, int end)
2.565 {
2.566 - struct razor_set *empty, *new;
2.567 - struct razor_merger *merger;
2.568 + struct razor_transaction_package *packages;
2.569 struct razor_package *pkgs;
2.570 - int pkg_count, remove_count, p, r;
2.571 - uint32_t *remove, *lost, *lost_end;
2.572 - struct razor_property *props, *prop_end, *req;
2.573 + int pkg_count, r;
2.574 + uint32_t *lost, *lost_end;
2.575 + struct razor_property *props, *prop_end, *req, *first_provider;
2.576 struct array lost_provides;
2.577 + const char *req_package;
2.578
2.579 - pkgs = set->packages.data;
2.580 - pkg_count = set->packages.size / sizeof (struct razor_package);
2.581 - props = set->properties.data;
2.582 - prop_end = set->properties.data + set->properties.size;
2.583 + pkgs = trans->system->packages.data;
2.584 + pkg_count = trans->system->packages.size / sizeof (struct razor_package);
2.585 + props = trans->system->properties.data;
2.586 + prop_end = trans->system->properties.data + trans->system->properties.size;
2.587
2.588 - remove = list->data;
2.589 - remove_count = list->size / sizeof (uint32_t);
2.590 - r = 0;
2.591 - while (r < remove_count) {
2.592 + for (r = start; r < end; r++) {
2.593 + packages = package_array->data;
2.594 + if (packages[r].state != RAZOR_PACKAGE_REMOVE)
2.595 + continue;
2.596 +
2.597 array_init(&lost_provides);
2.598 - for (; r < remove_count; r++)
2.599 - gather_lost_provides(set, &pkgs[remove[r]], &lost_provides);
2.600 + req_package = packages[r].name;
2.601 + gather_lost_provides(trans->system, packages[r].package,
2.602 + &lost_provides);
2.603
2.604 lost_end = lost_provides.data + lost_provides.size;
2.605 for (lost = lost_provides.data; lost < lost_end; lost++) {
2.606 /* Requires FOO will appear before Provides FOO */
2.607 for (req = &props[*lost]; req > props && req->name == props[*lost].name && req->type != RAZOR_PROPERTY_REQUIRES; req--)
2.608 ;
2.609 - /* FIXME: versioned deps... */
2.610 + first_provider = req + 1;
2.611 +
2.612 while (req > props && req->name == props[*lost].name) {
2.613 - gather_lost_requires(set, req, list);
2.614 + lose_requirement(trans, package_array,
2.615 + req_package, req,
2.616 + &props[*lost], first_provider);
2.617 req--;
2.618 }
2.619 }
2.620 array_release(&lost_provides);
2.621 -
2.622 - remove = list->data;
2.623 - remove_count = list->size / sizeof (uint32_t);
2.624 }
2.625 -
2.626 - empty = razor_set_create();
2.627 - merger = razor_merger_create(set, empty);
2.628 -
2.629 - for (p = 0; p < pkg_count; p++) {
2.630 - for (r = 0; r < remove_count; r++) {
2.631 - if (p == remove[r])
2.632 - goto skip;
2.633 - }
2.634 - add_package(merger, &pkgs[p], &merger->source1, 0);
2.635 - skip:
2.636 - ;
2.637 - }
2.638 -
2.639 - new = razor_merger_finish(merger);
2.640 - razor_set_destroy(empty);
2.641 - return new;
2.642 -}
2.643 -
2.644 -struct razor_set *
2.645 -razor_set_remove(struct razor_set *set, int count, const char **packages)
2.646 -{
2.647 - struct razor_set *new;
2.648 - struct array list;
2.649 -
2.650 - array_init(&list);
2.651 - find_packages(set, count, packages, &list);
2.652 - new = razor_set_remove_internal(set, &list);
2.653 - array_release(&list);
2.654 - razor_set_destroy(set);
2.655 - return new;
2.656 }
2.657
2.658 /* The diff order matters. We should sort the packages so that a
2.659 @@ -2161,3 +2100,258 @@
2.660 razor_package_iterator_destroy(pi1);
2.661 razor_package_iterator_destroy(pi2);
2.662 }
2.663 +
2.664 +struct razor_transaction *
2.665 +razor_transaction_create(struct razor_set *system, struct razor_set *upstream,
2.666 + int update_count, const char **update_packages,
2.667 + int remove_count, const char **remove_packages)
2.668 +{
2.669 + struct razor_transaction *trans;
2.670 + struct array packages;
2.671 + int start, end;
2.672 +
2.673 + trans = zalloc(sizeof *trans);
2.674 + trans->system = system;
2.675 + trans->upstream = upstream ? upstream : razor_set_create();
2.676 + array_init(&packages);
2.677 +
2.678 + /* Find initial upstream packages to be installed */
2.679 + if (update_count > 0) {
2.680 + trans->errors +=
2.681 + find_packages(upstream, update_count, update_packages,
2.682 + &packages, RAZOR_PACKAGE_INSTALL);
2.683 + } else if (remove_count == 0)
2.684 + find_all_packages(system, upstream, &packages);
2.685 +
2.686 + /* Find initial installed packages to remove. */
2.687 + if (remove_count > 0) {
2.688 + trans->errors +=
2.689 + find_packages(system, remove_count, remove_packages,
2.690 + &packages, RAZOR_PACKAGE_REMOVE);
2.691 + }
2.692 +
2.693 + start = 0;
2.694 + end = packages.size / sizeof (struct razor_transaction_package);
2.695 +
2.696 + while (!trans->errors && start != end) {
2.697 + if (upstream)
2.698 + razor_transaction_satisfy_installs(trans, &packages, start, end);
2.699 + razor_transaction_satisfy_removes(trans, &packages, start, end);
2.700 +
2.701 + start = end;
2.702 + end = packages.size / sizeof (struct razor_transaction_package);
2.703 + }
2.704 +
2.705 + trans->packages = packages.data;
2.706 + trans->package_count = packages.size / sizeof (struct razor_transaction_package);
2.707 + return trans;
2.708 +}
2.709 +
2.710 +const char * const razor_version_relations[] = {
2.711 + /* same order as enum razor_version_relation */
2.712 + "<", "<=", "=", ">=", ">"
2.713 +};
2.714 +
2.715 +void
2.716 +razor_transaction_describe(struct razor_transaction *trans)
2.717 +{
2.718 + struct razor_transaction_package *p, *pend, *tps;
2.719 + int errors_only = 0;
2.720 +
2.721 + tps = trans->packages;
2.722 + pend = trans->packages + trans->package_count;
2.723 + for (p = trans->packages; p < pend; p++) {
2.724 + switch (p->state) {
2.725 + case RAZOR_PACKAGE_INSTALL:
2.726 + if (errors_only)
2.727 + break;
2.728 +
2.729 + printf ("Installing %s %s", p->name, p->version);
2.730 + if (p->req_package) {
2.731 + printf (" for %s", p->req_package);
2.732 + if (*p->req_version) {
2.733 + printf (", which requires %s %s %s",
2.734 + p->req_property,
2.735 + razor_version_relations[p->req_relation],
2.736 + p->req_version);
2.737 + } else if (strcmp(p->req_property, p->name) != 0) {
2.738 + printf (", which requires %s",
2.739 + p->req_property);
2.740 + }
2.741 + }
2.742 + printf("\n");
2.743 + break;
2.744 +
2.745 + case RAZOR_PACKAGE_INSTALL_UNAVAILABLE:
2.746 + if (*p->req_version && strcmp(p->req_property, p->name) == 0) {
2.747 + printf ("Can't find %s %s %s, which is required by %s",
2.748 + p->name,
2.749 + razor_version_relations[p->req_relation],
2.750 + p->req_version,
2.751 + p->req_package);
2.752 + } else {
2.753 + printf ("Can't find %s", p->name);
2.754 + if (*p->version)
2.755 + printf (" %s", p->version);
2.756 +
2.757 + if (p->req_package) {
2.758 + printf (" which is required by %s",
2.759 + p->req_package);
2.760 + if (strcmp(p->req_property, p->name) != 0)
2.761 + printf (" for %s", p->req_property);
2.762 + }
2.763 + }
2.764 + printf("\n");
2.765 + errors_only = 1;
2.766 + break;
2.767 +
2.768 + case RAZOR_PACKAGE_INSTALL_BLOCKED:
2.769 + printf ("Cannot install %s, which is already marked for removal but is required by %s\n", p->name, p->req_package);
2.770 + errors_only = 1;
2.771 + break;
2.772 +
2.773 + case RAZOR_PACKAGE_INSTALL_UNSATISFIABLE:
2.774 + printf ("Cannot find package for %s", p->req_property);
2.775 + if (*p->req_version) {
2.776 + printf (" %s %s",
2.777 + razor_version_relations[p->req_relation],
2.778 + p->req_version);
2.779 + }
2.780 + printf (" which is required by %s\n",
2.781 + p->req_package);
2.782 + errors_only = 1;
2.783 + break;
2.784 +
2.785 + case RAZOR_PACKAGE_REMOVE:
2.786 + if (errors_only)
2.787 + break;
2.788 + printf ("Removing %s %s", p->name, p->version);
2.789 + if (p->req_package) {
2.790 + printf (" which required %s", p->req_package);
2.791 + if (strcmp(p->req_property, p->req_package) != 0)
2.792 + printf (" for %s", p->req_property);
2.793 + }
2.794 + printf("\n");
2.795 + break;
2.796 +
2.797 + case RAZOR_PACKAGE_REMOVE_NOT_INSTALLED:
2.798 + printf ("Package %s is not installed\n", p->name);
2.799 + errors_only = 1;
2.800 + break;
2.801 +
2.802 + case RAZOR_PACKAGE_REMOVE_BLOCKED:
2.803 + printf ("Cannot remove %s, which is marked for installation but requires %s\n", p->name, p->req_package);
2.804 + errors_only = 1;
2.805 + break;
2.806 +
2.807 + default:
2.808 + /* Shouldn't actually happen */
2.809 + break;
2.810 + }
2.811 + }
2.812 +}
2.813 +
2.814 +struct razor_set *
2.815 +razor_transaction_run(struct razor_transaction *trans)
2.816 +{
2.817 + struct array install_packages, remove_packages;
2.818 + struct razor_merger *merger;
2.819 + struct razor_package *pkg, *i, *iend, *r, *rend, *s, *send;
2.820 + struct source *source1, *source2;
2.821 + char *spool, *ipool, *rpool;
2.822 + uint32_t *map;
2.823 + int p, cmp;
2.824 +
2.825 + /* FIXME */
2.826 + if (trans->errors)
2.827 + return NULL;
2.828 +
2.829 + /* Sort the transaction packages into two arrays */
2.830 + array_init(&install_packages);
2.831 + array_init(&remove_packages);
2.832 + for (p = 0; p < trans->package_count; p++) {
2.833 + if (trans->packages[p].state & RAZOR_PACKAGE_INSTALL)
2.834 + pkg = array_add(&install_packages, sizeof *pkg);
2.835 + else
2.836 + pkg = array_add(&remove_packages, sizeof *pkg);
2.837 + *pkg = *trans->packages[p].package;
2.838 + }
2.839 + map = qsort_with_data(install_packages.data,
2.840 + install_packages.size / sizeof *pkg,
2.841 + sizeof *pkg,
2.842 + compare_packages,
2.843 + trans->upstream);
2.844 + free(map);
2.845 + map = qsort_with_data(remove_packages.data,
2.846 + remove_packages.size / sizeof *pkg,
2.847 + sizeof *pkg,
2.848 + compare_packages,
2.849 + trans->system);
2.850 + free(map);
2.851 +
2.852 + merger = razor_merger_create(trans->system, trans->upstream);
2.853 +
2.854 + source1 = &merger->source1;
2.855 + source2 = &merger->source2;
2.856 +
2.857 + i = install_packages.data;
2.858 + iend = install_packages.data + install_packages.size;
2.859 + ipool = trans->upstream->string_pool.data;
2.860 +
2.861 + r = remove_packages.data;
2.862 + rend = remove_packages.data + remove_packages.size;
2.863 + rpool = trans->system->string_pool.data;
2.864 +
2.865 + s = trans->system->packages.data;
2.866 + send = trans->system->packages.data + trans->system->packages.size;
2.867 + spool = trans->system->string_pool.data;
2.868 +
2.869 + while (s < send || i < iend) {
2.870 + /* Check if s is being removed */
2.871 + if (s < send && r < rend &&
2.872 + s->name == r->name && s->version && r->version) {
2.873 + s++;
2.874 + r++;
2.875 + continue;
2.876 + }
2.877 +
2.878 + if (s < send && i < iend)
2.879 + cmp = strcmp(&spool[s->name], &ipool[i->name]);
2.880 + else if (s < send)
2.881 + cmp = -1;
2.882 + else
2.883 + cmp = 1;
2.884 + if (cmp < 0) {
2.885 + add_package(merger, s, source1, 0);
2.886 + s++;
2.887 + } else if (cmp == 0) {
2.888 + add_package(merger, i, source2, UPSTREAM_SOURCE);
2.889 + s++;
2.890 + i++;
2.891 + } else {
2.892 + add_package(merger, i, source2, UPSTREAM_SOURCE);
2.893 + i++;
2.894 + }
2.895 + }
2.896 +
2.897 + array_release(&install_packages);
2.898 + array_release(&remove_packages);
2.899 +
2.900 + return razor_merger_finish(merger);
2.901 +}
2.902 +
2.903 +void
2.904 +razor_transaction_destroy(struct razor_transaction *trans)
2.905 +{
2.906 + int p;
2.907 +
2.908 + for (p = 0; p < trans->package_count; p++) {
2.909 + if (!trans->packages[p].req_package &&
2.910 + (trans->packages[p].state == RAZOR_PACKAGE_INSTALL_UNAVAILABLE ||
2.911 + trans->packages[p].state == RAZOR_PACKAGE_REMOVE_NOT_INSTALLED))
2.912 + free((char *)trans->packages[p].name);
2.913 + }
2.914 + free(trans);
2.915 +
2.916 + /* FIXME: free upstream if it was created as an empty set */
2.917 +}
3.1 --- a/razor.h Fri Feb 29 11:51:58 2008 -0500
3.2 +++ b/razor.h Fri Feb 29 11:53:15 2008 -0500
3.3 @@ -21,6 +21,7 @@
3.4 RAZOR_VERSION_GREATER_OR_EQUAL,
3.5 RAZOR_VERSION_GREATER
3.6 };
3.7 +extern const char * const razor_version_relations[];
3.8
3.9 struct razor_set *razor_set_create(void);
3.10 struct razor_set *razor_set_open(const char *filename);
3.11 @@ -62,11 +63,6 @@
3.12 void razor_set_list_package_files(struct razor_set *set, const char *name);
3.13
3.14 void razor_set_list_unsatisfied(struct razor_set *set);
3.15 -struct razor_set *razor_set_update(struct razor_set *set,
3.16 - struct razor_set *upstream,
3.17 - int count, const char **packages);
3.18 -struct razor_set *razor_set_remove(struct razor_set *set,
3.19 - int count, const char **packages);
3.20
3.21 typedef void (*razor_package_callback_t)(const char *name,
3.22 const char *old_version,
3.23 @@ -76,6 +72,51 @@
3.24 razor_set_diff(struct razor_set *set, struct razor_set *upstream,
3.25 razor_package_callback_t callback, void *data);
3.26
3.27 +/* Package transactions */
3.28 +
3.29 +enum razor_transaction_package_state {
3.30 + /* Basic states */
3.31 + RAZOR_PACKAGE_INSTALL = 0x01,
3.32 + RAZOR_PACKAGE_REMOVE = 0x02,
3.33 +
3.34 + /* (Flags used to define the error states) */
3.35 + RAZOR_PACKAGE_UNAVAILABLE = 0x04,
3.36 + RAZOR_PACKAGE_UNSATISFIABLE = 0x08,
3.37 + RAZOR_PACKAGE_BLOCKED = 0x10,
3.38 +
3.39 + /* Error states */
3.40 + RAZOR_PACKAGE_INSTALL_UNAVAILABLE = RAZOR_PACKAGE_INSTALL | RAZOR_PACKAGE_UNAVAILABLE,
3.41 + RAZOR_PACKAGE_INSTALL_UNSATISFIABLE = RAZOR_PACKAGE_INSTALL | RAZOR_PACKAGE_UNSATISFIABLE,
3.42 + RAZOR_PACKAGE_INSTALL_BLOCKED = RAZOR_PACKAGE_INSTALL | RAZOR_PACKAGE_BLOCKED,
3.43 + RAZOR_PACKAGE_REMOVE_NOT_INSTALLED = RAZOR_PACKAGE_REMOVE | RAZOR_PACKAGE_UNAVAILABLE,
3.44 + RAZOR_PACKAGE_REMOVE_BLOCKED = RAZOR_PACKAGE_REMOVE | RAZOR_PACKAGE_BLOCKED
3.45 +};
3.46 +
3.47 +struct razor_transaction_package {
3.48 + struct razor_package *package;
3.49 + const char *name, *version;
3.50 + enum razor_transaction_package_state state;
3.51 +
3.52 + const char *req_package;
3.53 + const char *req_property;
3.54 + enum razor_version_relation req_relation;
3.55 + const char *req_version;
3.56 +};
3.57 +
3.58 +struct razor_transaction {
3.59 + int package_count, errors;
3.60 + struct razor_transaction_package *packages;
3.61 +
3.62 + struct razor_set *system, *upstream;
3.63 +};
3.64 +
3.65 +struct razor_transaction *
3.66 +razor_transaction_create(struct razor_set *system, struct razor_set *upstream,
3.67 + int update_count, const char **update_packages,
3.68 + int remove_count, const char **remove_packages);
3.69 +void razor_transaction_describe(struct razor_transaction *trans);
3.70 +struct razor_set *razor_transaction_run(struct razor_transaction *trans);
3.71 +void razor_transaction_destroy(struct razor_transaction *trans);
3.72
3.73 /* Importer interface; for building a razor set from external sources,
3.74 * like yum, rpmdb or razor package files. */
4.1 --- a/test-driver.c Fri Feb 29 11:51:58 2008 -0500
4.2 +++ b/test-driver.c Fri Feb 29 11:53:15 2008 -0500
4.3 @@ -24,15 +24,17 @@
4.4 XML_SetElementHandler(parser, start, end);
4.5 XML_SetUserData(parser, data);
4.6
4.7 - buffer = XML_GetBuffer(parser, XML_BUFFER_SIZE);
4.8 -
4.9 fd = open(filename, O_RDONLY);
4.10 if (fd < 0) {
4.11 fprintf(stderr, "failed to open %s: %m\n", filename);
4.12 exit(-1);
4.13 }
4.14
4.15 - while (len = read(fd, buffer, XML_BUFFER_SIZE), len > 0) {
4.16 + while (1) {
4.17 + buffer = XML_GetBuffer(parser, XML_BUFFER_SIZE);
4.18 + len = read(fd, buffer, XML_BUFFER_SIZE);
4.19 + if (len == 0)
4.20 + break;
4.21 err = XML_ParseBuffer(parser, len, len == 0);
4.22 if (err == XML_STATUS_ERROR) {
4.23 fprintf(stderr, "parse error at line %lu:\n%s\n",
4.24 @@ -56,11 +58,15 @@
4.25 struct razor_importer *importer;
4.26 struct razor_set **importer_set;
4.27
4.28 + struct razor_transaction *trans;
4.29 + struct razor_transaction_package *unsat;
4.30 +
4.31 char *install_pkgs[3], *remove_pkgs[3];
4.32 int n_install_pkgs, n_remove_pkgs;
4.33
4.34 int in_result, result_errors;
4.35 - int in_unsatisfiable;
4.36 +
4.37 + int debug;
4.38 };
4.39
4.40 static void
4.41 @@ -87,11 +93,11 @@
4.42 {
4.43 if (!rel_str)
4.44 return -1;
4.45 - if (rel_str[0] == 'l')
4.46 - return rel_str[1] == 'e' ? RAZOR_VERSION_LESS_OR_EQUAL : RAZOR_VERSION_LESS;
4.47 - else if (rel_str[0] == 'g')
4.48 - return rel_str[1] == 'e' ? RAZOR_VERSION_GREATER_OR_EQUAL : RAZOR_VERSION_GREATER;
4.49 - else if (rel_str[0] == 'e' || rel_str[1] == 'q')
4.50 + if (rel_str[0] == 'L')
4.51 + return rel_str[1] == 'E' ? RAZOR_VERSION_LESS_OR_EQUAL : RAZOR_VERSION_LESS;
4.52 + else if (rel_str[0] == 'G')
4.53 + return rel_str[1] == 'E' ? RAZOR_VERSION_GREATER_OR_EQUAL : RAZOR_VERSION_GREATER;
4.54 + else if (rel_str[0] == 'E' || rel_str[1] == 'Q')
4.55 return RAZOR_VERSION_EQUAL;
4.56 else
4.57 return -1;
4.58 @@ -125,6 +131,10 @@
4.59 razor_set_destroy(ctx->result_set);
4.60 ctx->result_set = NULL;
4.61 }
4.62 + if (ctx->trans) {
4.63 + razor_transaction_destroy(ctx->trans);
4.64 + ctx->trans = NULL;
4.65 + }
4.66 }
4.67
4.68 static void
4.69 @@ -177,15 +187,43 @@
4.70 }
4.71
4.72 static void
4.73 +add_property(struct test_context *ctx, enum razor_property_type type, const char *name, enum razor_version_relation rel, const char *version)
4.74 +{
4.75 + razor_importer_add_property(ctx->importer, name,
4.76 + rel, version, type);
4.77 +}
4.78 +
4.79 +static void
4.80 +check_unsatisfiable_property(struct test_context *ctx, enum razor_property_type type, const char *name, enum razor_version_relation rel, const char *version)
4.81 +{
4.82 + if (!version)
4.83 + version = "";
4.84 +
4.85 + for (; ctx->unsat < ctx->trans->packages + ctx->trans->package_count; ctx->unsat++) {
4.86 + if (ctx->unsat->state != RAZOR_PACKAGE_INSTALL_UNSATISFIABLE)
4.87 + continue;
4.88 + if (strcmp(name, ctx->unsat->req_property) != 0 ||
4.89 + rel != ctx->unsat->req_relation ||
4.90 + strcmp(version, ctx->unsat->req_version) != 0)
4.91 + continue;
4.92 +
4.93 + /* OK, found it, so skip over it and continue */
4.94 + ctx->unsat++;
4.95 + return;
4.96 + }
4.97 +
4.98 + fprintf(stderr, " didn't get unsatisfiable '%s %s %s'\n",
4.99 + name, razor_version_relations[rel], version);
4.100 + exit(1);
4.101 +}
4.102 +
4.103 +static void
4.104 start_property(struct test_context *ctx, enum razor_property_type type, const char **atts)
4.105 {
4.106 const char *name = NULL, *rel_str = NULL, *version = NULL;
4.107 enum razor_version_relation rel;
4.108
4.109 - if (ctx->in_unsatisfiable)
4.110 - return;
4.111 -
4.112 - get_atts(atts, "name", &name, "rel", &rel_str, "version", &version, NULL);
4.113 + get_atts(atts, "name", &name, "relation", &rel_str, "version", &version, NULL);
4.114 if (name == NULL) {
4.115 fprintf(stderr, " no name specified for property\n");
4.116 exit(1);
4.117 @@ -199,8 +237,10 @@
4.118 } else
4.119 rel = RAZOR_VERSION_EQUAL;
4.120
4.121 - razor_importer_add_property(ctx->importer, name,
4.122 - rel, version, type);
4.123 + if (ctx->unsat)
4.124 + check_unsatisfiable_property(ctx, type, name, rel, version);
4.125 + else
4.126 + add_property(ctx, type, name, rel, version);
4.127 }
4.128
4.129 static void
4.130 @@ -213,22 +253,27 @@
4.131 static void
4.132 end_transaction(struct test_context *ctx)
4.133 {
4.134 - if (ctx->n_install_pkgs) {
4.135 - ctx->system_set = razor_set_update(ctx->system_set,
4.136 - ctx->repo_set,
4.137 - ctx->n_install_pkgs,
4.138 - (const char **)ctx->install_pkgs);
4.139 - }
4.140 - if (ctx->n_remove_pkgs && ctx->system_set) {
4.141 - ctx->system_set = razor_set_remove(ctx->system_set,
4.142 - ctx->n_remove_pkgs,
4.143 - (const char **)ctx->remove_pkgs);
4.144 + ctx->trans = razor_transaction_create(ctx->system_set, ctx->repo_set,
4.145 + ctx->n_install_pkgs,
4.146 + (const char **)ctx->install_pkgs,
4.147 + ctx->n_remove_pkgs,
4.148 + (const char **)ctx->remove_pkgs);
4.149 + if (ctx->debug) {
4.150 + razor_transaction_describe(ctx->trans);
4.151 + printf("\n");
4.152 }
4.153
4.154 while (ctx->n_install_pkgs--)
4.155 free(ctx->install_pkgs[ctx->n_install_pkgs]);
4.156 while (ctx->n_remove_pkgs--)
4.157 free(ctx->remove_pkgs[ctx->n_remove_pkgs]);
4.158 +
4.159 + if (!ctx->trans->errors) {
4.160 + struct razor_set *new;
4.161 + new = razor_transaction_run(ctx->trans);
4.162 + razor_set_destroy(ctx->system_set);
4.163 + ctx->system_set = new;
4.164 + }
4.165 }
4.166
4.167 static void
4.168 @@ -301,20 +346,18 @@
4.169 static void
4.170 start_unsatisfiable(struct test_context *ctx, const char **atts)
4.171 {
4.172 - if (ctx->system_set) {
4.173 + if (ctx->result_set) {
4.174 fprintf(stderr, "Expected to fail, but didn't\n");
4.175 exit(1);
4.176 }
4.177
4.178 - /* FIXME */
4.179 - fprintf(stderr, " Not actually checking <unsatisfiable>\n");
4.180 - ctx->in_unsatisfiable = 1;
4.181 + ctx->unsat = ctx->trans->packages;
4.182 }
4.183
4.184 static void
4.185 end_unsatisfiable(struct test_context *ctx)
4.186 {
4.187 - ctx->in_unsatisfiable = 0;
4.188 + ctx->unsat = NULL;
4.189 }
4.190
4.191 static void
4.192 @@ -379,14 +422,26 @@
4.193 int main(int argc, char *argv[])
4.194 {
4.195 struct test_context ctx;
4.196 + const char *test_file;
4.197
4.198 - if (argc != 2) {
4.199 - fprintf(stderr, "usage: %s TESTS-FILE\n", argv[0]);
4.200 + memset(&ctx, 0, sizeof ctx);
4.201 +
4.202 + if (argc > 3) {
4.203 + fprintf(stderr, "usage: %s [-d] [TESTS-FILE]\n", argv[0]);
4.204 exit(-1);
4.205 }
4.206
4.207 - memset(&ctx, 0, sizeof ctx);
4.208 - parse_xml_file(argv[1], start_test_element, end_test_element, &ctx);
4.209 + if (argc >= 2 && !strcmp (argv[1], "-d")) {
4.210 + ctx.debug = 1;
4.211 + argc--;
4.212 + argv++;
4.213 + }
4.214 + if (argc == 2)
4.215 + test_file = argv[1];
4.216 + else
4.217 + test_file = "test.xml";
4.218 +
4.219 + parse_xml_file(test_file, start_test_element, end_test_element, &ctx);
4.220
4.221 return 0;
4.222 }