1.1 --- a/razor.c Tue Feb 26 16:39:01 2008 -0500
1.2 +++ b/razor.c Fri Feb 29 11:53:15 2008 -0500
1.3 @@ -382,7 +382,7 @@
1.4 __qsort_with_data(end, right, mend, ctx);
1.5 }
1.6
1.7 -uint32_t *
1.8 +static uint32_t *
1.9 qsort_with_data(void *base, size_t nelem, size_t size,
1.10 compare_with_data_func_t compare, void *data)
1.11 {
1.12 @@ -758,7 +758,7 @@
1.13 struct list *index;
1.14 };
1.15
1.16 -struct razor_package_iterator *
1.17 +static struct razor_package_iterator *
1.18 razor_package_iterator_create_with_index(struct razor_set *set,
1.19 struct list *index)
1.20 {
1.21 @@ -1231,53 +1231,6 @@
1.22 }
1.23 }
1.24
1.25 -
1.26 -/* Build the new package list sorted by merging the two package lists.
1.27 - * Build new string pool as we go. */
1.28 -static void
1.29 -merge_packages(struct razor_merger *merger, struct array *packages)
1.30 -{
1.31 - struct razor_package *upstream_packages, *p, *s, *send;
1.32 - struct source *source1, *source2;
1.33 - char *spool, *upool;
1.34 - uint32_t *u, *uend;
1.35 - int cmp;
1.36 -
1.37 - source1 = &merger->source1;
1.38 - source2 = &merger->source2;
1.39 - upstream_packages = source2->set->packages.data;
1.40 -
1.41 - u = packages->data;
1.42 - uend = packages->data + packages->size;
1.43 - upool = source2->set->string_pool.data;
1.44 -
1.45 - s = source1->set->packages.data;
1.46 - send = source1->set->packages.data + source1->set->packages.size;
1.47 - spool = source1->set->string_pool.data;
1.48 -
1.49 - while (s < send || u < uend) {
1.50 - p = upstream_packages + *u;
1.51 -
1.52 - if (s < send && u < uend)
1.53 - cmp = strcmp(&spool[s->name], &upool[p->name]);
1.54 - else if (s < send)
1.55 - cmp = -1;
1.56 - else
1.57 - cmp = 1;
1.58 - if (cmp < 0) {
1.59 - add_package(merger, s, source1, 0);
1.60 - s++;
1.61 - } else if (cmp == 0) {
1.62 - add_package(merger, p, source2, UPSTREAM_SOURCE);
1.63 - s++;
1.64 - u++;
1.65 - } else {
1.66 - add_package(merger, p, source2, UPSTREAM_SOURCE);
1.67 - u++;
1.68 - }
1.69 - }
1.70 -}
1.71 -
1.72 static uint32_t
1.73 add_property(struct razor_merger *merger,
1.74 const char *name, enum razor_version_relation relation,
1.75 @@ -1648,7 +1601,7 @@
1.76 free(pkgs);
1.77 }
1.78
1.79 -struct razor_set *
1.80 +static struct razor_set *
1.81 razor_merger_finish(struct razor_merger *merger)
1.82 {
1.83 struct razor_set *result;
1.84 @@ -1698,112 +1651,58 @@
1.85 return result;
1.86 }
1.87
1.88 -/* Add packages from 'upstream' to 'set'. The packages to add are
1.89 - * specified by the 'packages' array, which is a sorted list of
1.90 - * package indexes. Returns a newly allocated package set. Does not
1.91 - * enforce validity of the resulting package set.
1.92 - *
1.93 - * This looks more complicated than it is. An easy way to merge two
1.94 - * package sets would be to just use a razor_importer, but that
1.95 - * requires resorting, and is thus O(n log n). We can do this in a
1.96 - * linear sweep, but it gets a little more complicated.
1.97 - */
1.98 -struct razor_set *
1.99 -razor_set_add(struct razor_set *set, struct razor_set *upstream,
1.100 - struct array *packages)
1.101 -{
1.102 - struct razor_merger *merger;
1.103 -
1.104 - merger = razor_merger_create(set, upstream);
1.105 -
1.106 - merge_packages(merger, packages);
1.107 -
1.108 - return razor_merger_finish(merger);
1.109 -}
1.110 -
1.111 -void
1.112 -razor_set_satisfy(struct razor_set *set, struct array *unsatisfied,
1.113 - struct razor_set *upstream, struct array *list)
1.114 -{
1.115 - struct razor_property *requires, *r;
1.116 - struct razor_property *p, *pend;
1.117 - uint32_t *u, *end, *pkg;
1.118 - struct array *package_pool;
1.119 - char *pool, *upool;
1.120 -
1.121 - end = unsatisfied->data + unsatisfied->size;
1.122 - requires = set->properties.data;
1.123 - pool = set->string_pool.data;
1.124 -
1.125 - p = upstream->properties.data;
1.126 - pend = upstream->properties.data + upstream->properties.size;
1.127 - upool = upstream->string_pool.data;
1.128 - package_pool = &upstream->package_pool;
1.129 -
1.130 - u = unsatisfied->data;
1.131 - while (u < end) {
1.132 - r = requires + *u;
1.133 -
1.134 - while (p < pend &&
1.135 - p->type != RAZOR_PROPERTY_PROVIDES &&
1.136 - strcmp(&pool[r->name], &upool[p->name]) > 0)
1.137 - p++;
1.138 - /* If there is more than one version of a provides,
1.139 - * seek to the end for the highest version. */
1.140 - while (p + 1 < pend && p->name == (p + 1)->name && p->type == (p + 1)->type)
1.141 - p++;
1.142 -
1.143 - if (p != pend &&
1.144 - p->type == RAZOR_PROPERTY_PROVIDES &&
1.145 - strcmp(&pool[r->name], &upool[p->name]) == 0 &&
1.146 - versioncmp(&pool[r->version], &upool[p->version]) <= 0) {
1.147 - pkg = array_add(list, sizeof *pkg);
1.148 - /* We just pull in the first package that provides */
1.149 - *pkg = list_first(&p->packages, package_pool)->data;
1.150 -
1.151 - /* Remove this from the unsatisfied list */
1.152 - memmove (u, u + 1, end - (u + 1));
1.153 - end--;
1.154 - } else {
1.155 - /* Leave this in the unsatisfied list */
1.156 - u++;
1.157 - }
1.158 - }
1.159 - unsatisfied->size = (void *)end - unsatisfied->data;
1.160 -}
1.161 -
1.162 -static void
1.163 -find_packages(struct razor_set *set,
1.164 - int count, const char **package_names, struct array *list)
1.165 +static int
1.166 +find_packages(struct razor_set *set, int count, const char **package_names,
1.167 + struct array *package_array,
1.168 + enum razor_transaction_package_state state)
1.169 {
1.170 struct razor_package_iterator *pi;
1.171 struct razor_package *p, *packages;
1.172 const char *name, *version;
1.173 - uint32_t *r;
1.174 - int i;
1.175 + struct razor_transaction_package *tp;
1.176 + int i, *found, errors = 0;
1.177
1.178 packages = (struct razor_package *) set->packages.data;
1.179 pi = razor_package_iterator_create(set);
1.180 + found = zalloc(count * sizeof (int));
1.181
1.182 while (razor_package_iterator_next(pi, &p, &name, &version)) {
1.183 for (i = 0; i < count; i++) {
1.184 if (strcmp(name, package_names[i]) == 0) {
1.185 - r = array_add(list, sizeof *r);
1.186 - *r = p - packages;
1.187 + found[i] = 1;
1.188 + tp = array_add(package_array, sizeof *tp);
1.189 + memset(tp, 0, sizeof *tp);
1.190 + tp->package = p;
1.191 + tp->name = name;
1.192 + tp->version = version;
1.193 + tp->state = state;
1.194 break;
1.195 }
1.196 }
1.197 }
1.198
1.199 + for (i = 0; i < count; i++) {
1.200 + if (!found[i]) {
1.201 + tp = array_add(package_array, sizeof *tp);
1.202 + memset(tp, 0, sizeof *tp);
1.203 + tp->name = strdup(package_names[i]);
1.204 + tp->state = state | RAZOR_PACKAGE_UNAVAILABLE;
1.205 + errors++;
1.206 + }
1.207 + }
1.208 +
1.209 razor_package_iterator_destroy(pi);
1.210 + free(found);
1.211 +
1.212 + return errors;
1.213 }
1.214
1.215 static void
1.216 find_all_packages(struct razor_set *set,
1.217 - struct razor_set *upstream, struct array *list)
1.218 + struct razor_set *upstream, struct array *package_array)
1.219 {
1.220 + struct razor_transaction_package *tp;
1.221 struct razor_package *p, *u, *pend, *uend;
1.222 - uint32_t *r;
1.223 char *pool, *upool;
1.224
1.225 pend = set->packages.data + set->packages.size;
1.226 @@ -1816,25 +1715,89 @@
1.227 while (u < uend && strcmp(&pool[p->name], &upool[u->name]) > 0)
1.228 u++;
1.229 if (strcmp(&pool[p->name], &upool[u->name]) == 0) {
1.230 - r = array_add(list, sizeof *r);
1.231 - *r = u - (struct razor_package *) upstream->packages.data;
1.232 + tp = array_add(package_array, sizeof *tp);
1.233 + memset(tp, 0, sizeof *tp);
1.234 + tp->name = &upool[u->name];
1.235 + tp->version = &upool[u->version];
1.236 + tp->state = RAZOR_PACKAGE_INSTALL;
1.237 }
1.238 }
1.239 }
1.240
1.241 +/* FIXME: wrong, need to compare names, not razor_package* */
1.242 static int
1.243 -find_provider(struct razor_set *set, const char *req_name,
1.244 - enum razor_version_relation relation, const char *version)
1.245 +find_transaction_package(struct array *package_array,
1.246 + struct razor_package *package)
1.247 +{
1.248 + struct razor_transaction_package *tps = package_array->data;
1.249 + int i, tpcount = package_array->size / sizeof *tps;
1.250 +
1.251 + for (i = 0; i < tpcount; i++) {
1.252 + if (tps[i].package == package)
1.253 + return i;
1.254 + }
1.255 + return -1;
1.256 +}
1.257 +
1.258 +static int
1.259 +provider_satisfies_requirement(struct razor_property *provider,
1.260 + const char *provider_strings,
1.261 + struct razor_property *requirement,
1.262 + const char *requirement_strings)
1.263 +{
1.264 + int cmp, len;
1.265 + const char *provided = &provider_strings[provider->version];
1.266 + const char *required = &requirement_strings[requirement->version];
1.267 +
1.268 + if (!*required)
1.269 + return 1;
1.270 +
1.271 + cmp = versioncmp(provided, required);
1.272 +
1.273 + switch (requirement->relation) {
1.274 + case RAZOR_VERSION_LESS:
1.275 + return cmp < 0;
1.276 +
1.277 + case RAZOR_VERSION_LESS_OR_EQUAL:
1.278 + if (cmp <= 0)
1.279 + return 1;
1.280 + /* fall through: FIXME, make sure this is correct */
1.281 +
1.282 + case RAZOR_VERSION_EQUAL:
1.283 + if (cmp == 0)
1.284 + return 1;
1.285 +
1.286 + /* "foo == 1.1" is satisfied by "foo 1.1-2" */
1.287 + len = strlen(required);
1.288 + if (!strncmp(required, provided, len) && provided[len] == '-')
1.289 + return 1;
1.290 + return 0;
1.291 +
1.292 + case RAZOR_VERSION_GREATER_OR_EQUAL:
1.293 + return cmp >= 0;
1.294 +
1.295 + case RAZOR_VERSION_GREATER:
1.296 + return cmp > 0;
1.297 + }
1.298 +
1.299 + /* shouldn't happen */
1.300 + return 0;
1.301 +}
1.302 +
1.303 +static int
1.304 +find_provider(struct razor_set *set, struct razor_property *requirement,
1.305 + const char *requirement_strings)
1.306 {
1.307 struct razor_property *props = set->properties.data;
1.308 - int p, hi, lo, cmp, pkg;
1.309 + int p, hi, lo, cmp;
1.310 char *pool = set->string_pool.data;
1.311
1.312 lo = 0;
1.313 hi = set->properties.size / sizeof *props;
1.314 while (lo < hi) {
1.315 p = (lo + hi) / 2;
1.316 - cmp = strcmp(&pool[props[p].name], req_name);
1.317 + cmp = strcmp(&pool[props[p].name],
1.318 + &requirement_strings[requirement->name]);
1.319 if (cmp < 0)
1.320 lo = p + 1;
1.321 else if (cmp > 0)
1.322 @@ -1868,35 +1831,9 @@
1.323 return -1;
1.324
1.325 do {
1.326 - pkg = list_first(&props[p].packages, &set->package_pool)->data;
1.327 - if (!*version)
1.328 - return pkg;
1.329 -
1.330 - cmp = versioncmp(&pool[props[p].version], version);
1.331 -
1.332 - switch (relation) {
1.333 - case RAZOR_VERSION_EQUAL:
1.334 - case RAZOR_VERSION_GREATER_OR_EQUAL:
1.335 - case RAZOR_VERSION_GREATER:
1.336 - if (cmp >= 0)
1.337 - return pkg;
1.338 - else {
1.339 - /* If the highest version doesn't pass,
1.340 - * none of the others will either.
1.341 - */
1.342 - return -1;
1.343 - }
1.344 -
1.345 - case RAZOR_VERSION_LESS_OR_EQUAL:
1.346 - if (cmp <= 0)
1.347 - return pkg;
1.348 - break;
1.349 -
1.350 - case RAZOR_VERSION_LESS:
1.351 - if (cmp < 0)
1.352 - return pkg;
1.353 - break;
1.354 - }
1.355 + if (provider_satisfies_requirement(&props[p], pool,
1.356 + requirement, requirement_strings))
1.357 + return list_first(&props[p].packages, &set->package_pool)->data;
1.358
1.359 p--;
1.360 } while (p > lo && props[p].name == props[p + 1].name &&
1.361 @@ -1921,78 +1858,79 @@
1.362 if (!strncmp(&upool[prop->name], "rpmlib(", 7))
1.363 continue;
1.364
1.365 - if (find_provider(system, &upool[prop->name],
1.366 - prop->relation, &upool[prop->version]) == -1) {
1.367 + if (find_provider(system, prop, upool) == -1) {
1.368 new = array_add(new_requires, sizeof *new);
1.369 *new = p->data;
1.370 }
1.371 }
1.372 }
1.373
1.374 -struct razor_set *
1.375 -razor_set_update(struct razor_set *set, struct razor_set *upstream,
1.376 - int count, const char **packages)
1.377 +static void
1.378 +razor_transaction_satisfy_installs(struct razor_transaction *trans,
1.379 + struct array *package_array,
1.380 + int start, int end)
1.381 {
1.382 - struct razor_set *new_set;
1.383 - struct array list;
1.384 struct razor_package *pkgs;
1.385 - int update_count, u, provider, already;
1.386 - uint32_t *update, *new, *new_end, *required;
1.387 + struct razor_transaction_package *packages, *tp;
1.388 + int p, provider, already;
1.389 + uint32_t *new, *new_end;
1.390 struct razor_property *props, *prop_end;
1.391 struct array new_requires;
1.392 char *pool;
1.393
1.394 - pkgs = upstream->packages.data;
1.395 - props = upstream->properties.data;
1.396 - prop_end = upstream->properties.data + set->properties.size;
1.397 - pool = upstream->string_pool.data;
1.398 + pkgs = trans->upstream->packages.data;
1.399 + props = trans->upstream->properties.data;
1.400 + prop_end = trans->upstream->properties.data + trans->upstream->properties.size;
1.401 + pool = trans->upstream->string_pool.data;
1.402
1.403 - array_init(&list);
1.404 - if (count > 0)
1.405 - find_packages(upstream, count, packages, &list);
1.406 - else
1.407 - find_all_packages(set, upstream, &list);
1.408 + packages = package_array->data;
1.409 + for (p = start; p < end; p++) {
1.410 + if (packages[p].state != RAZOR_PACKAGE_INSTALL)
1.411 + continue;
1.412
1.413 - update = list.data;
1.414 - update_count = list.size / sizeof (uint32_t);
1.415 - u = 0;
1.416 - while (u < update_count) {
1.417 array_init(&new_requires);
1.418 - for (; u < update_count; u++)
1.419 - gather_new_requires(set, upstream, &pkgs[update[u]], &new_requires);
1.420 + gather_new_requires(trans->system, trans->upstream,
1.421 + packages[p].package, &new_requires);
1.422
1.423 new_end = new_requires.data + new_requires.size;
1.424 for (new = new_requires.data; new < new_end; new++) {
1.425 - provider = find_provider(upstream, &pool[props[*new].name],
1.426 - props[*new].relation,
1.427 - &pool[props[*new].version]);
1.428 -
1.429 /* FIXME */
1.430 - if (provider == -1)
1.431 + if (pool[props[*new].name] == '/')
1.432 continue;
1.433
1.434 - update = list.data;
1.435 - update_count = list.size / sizeof (uint32_t);
1.436 - for (already = 0; already < update_count; already++) {
1.437 - if (provider == update[already])
1.438 - break;
1.439 - }
1.440 - if (already < update_count)
1.441 + provider = find_provider(trans->upstream,
1.442 + &props[*new], pool);
1.443 + already = find_transaction_package(package_array,
1.444 + &pkgs[provider]);
1.445 + if (already != -1 &&
1.446 + (packages[already].state & RAZOR_PACKAGE_INSTALL))
1.447 continue;
1.448
1.449 - required = array_add(&list, sizeof *required);
1.450 - *required = provider;
1.451 + tp = array_add(package_array, sizeof *tp);
1.452 + memset(tp, 0, sizeof *tp);
1.453 + tp->req_package = packages[p].name;
1.454 + tp->req_property = &pool[props[*new].name];
1.455 + tp->req_relation = props[*new].relation;
1.456 + tp->req_version = &pool[props[*new].version];
1.457 +
1.458 + if (provider != -1) {
1.459 + tp->package = &pkgs[provider];
1.460 + tp->name = &pool[tp->package->name];
1.461 + tp->version = &pool[tp->package->version];
1.462 + if (already != -1) {
1.463 + tp->state = RAZOR_PACKAGE_INSTALL_BLOCKED;
1.464 + trans->errors++;
1.465 + } else
1.466 + tp->state = RAZOR_PACKAGE_INSTALL;
1.467 + } else {
1.468 + tp->state = RAZOR_PACKAGE_INSTALL_UNSATISFIABLE;
1.469 + trans->errors++;
1.470 + }
1.471 +
1.472 + packages = package_array->data;
1.473 }
1.474 array_release(&new_requires);
1.475 -
1.476 - update = list.data;
1.477 - update_count = list.size / sizeof (uint32_t);
1.478 }
1.479 -
1.480 - new_set = razor_set_add(set, upstream, &list);
1.481 - array_release(&list);
1.482 - razor_set_destroy(set);
1.483 - return new_set;
1.484 }
1.485
1.486 /* Look through pkg's PROVIDES, and for each one that no other package
1.487 @@ -2019,101 +1957,102 @@
1.488 }
1.489 }
1.490
1.491 -/* Add the index of each package required by req that isn't already in
1.492 - * lost_requires, to lost_requires
1.493 - */
1.494 static void
1.495 -gather_lost_requires(struct razor_set *set, struct razor_property *req,
1.496 - struct array *lost_requires)
1.497 +lose_requirement(struct razor_transaction *trans, struct array *package_array,
1.498 + const char *req_package, struct razor_property *req,
1.499 + struct razor_property *lost_provider,
1.500 + struct razor_property *first_provider)
1.501 {
1.502 + struct razor_property *provider, *prop_end;
1.503 + struct razor_package *pkgs;
1.504 + char *pool = trans->system->string_pool.data;
1.505 struct list *p;
1.506 - uint32_t *lost, *already_lost, *already_end;
1.507 + struct razor_transaction_package *tp, *packages;;
1.508 + int already;
1.509
1.510 - for (p = list_first(&req->packages, &set->package_pool); p; p = list_next(p)) {
1.511 - already_end = lost_requires->data + lost_requires->size;
1.512 - for (already_lost = lost_requires->data; already_lost < already_end; already_lost++) {
1.513 - if (*already_lost == p->data)
1.514 - break;
1.515 - }
1.516 + pkgs = trans->system->packages.data;
1.517 + prop_end = trans->system->properties.data + trans->system->properties.size;
1.518
1.519 - if (already_lost == already_end) {
1.520 - lost = array_add(lost_requires, sizeof *lost);
1.521 - *lost = p->data;
1.522 - }
1.523 + /* See if any other provider satisfies req */
1.524 + for (provider = first_provider;
1.525 + provider < prop_end && provider->type == RAZOR_PROPERTY_PROVIDES && provider->name == lost_provider->name;
1.526 + provider++) {
1.527 + if (provider == lost_provider)
1.528 + continue;
1.529 +
1.530 + if (provider_satisfies_requirement(provider, pool, req, pool))
1.531 + return;
1.532 + }
1.533 +
1.534 + /* Remove each of the packages requiring req */
1.535 + for (p = list_first(&req->packages, &trans->system->package_pool); p; p = list_next(p)) {
1.536 + packages = package_array->data;
1.537 + already = find_transaction_package(package_array, &pkgs[p->data]);
1.538 + if (already != -1 &&
1.539 + (packages[already].state & RAZOR_PACKAGE_REMOVE))
1.540 + continue;
1.541 +
1.542 + tp = array_add(package_array, sizeof *tp);
1.543 + memset(tp, 0, sizeof *tp);
1.544 + tp->package = &pkgs[p->data];
1.545 + tp->name = &pool[tp->package->name];
1.546 + tp->version = &pool[tp->package->version];
1.547 + tp->req_package = req_package;
1.548 + tp->req_property = &pool[req->name];
1.549 + tp->req_relation = req->relation;
1.550 + tp->req_version = &pool[req->version];
1.551 + if (already != -1) {
1.552 + tp->state = RAZOR_PACKAGE_REMOVE_BLOCKED;
1.553 + trans->errors++;
1.554 + } else
1.555 + tp->state = RAZOR_PACKAGE_REMOVE;
1.556 }
1.557 }
1.558
1.559 -static struct razor_set *
1.560 -razor_set_remove_internal(struct razor_set *set, struct array *list)
1.561 +static void
1.562 +razor_transaction_satisfy_removes(struct razor_transaction *trans,
1.563 + struct array *package_array,
1.564 + int start, int end)
1.565 {
1.566 - struct razor_set *empty, *new;
1.567 - struct razor_merger *merger;
1.568 + struct razor_transaction_package *packages;
1.569 struct razor_package *pkgs;
1.570 - int pkg_count, remove_count, p, r;
1.571 - uint32_t *remove, *lost, *lost_end;
1.572 - struct razor_property *props, *prop_end, *req;
1.573 + int pkg_count, r;
1.574 + uint32_t *lost, *lost_end;
1.575 + struct razor_property *props, *prop_end, *req, *first_provider;
1.576 struct array lost_provides;
1.577 + const char *req_package;
1.578
1.579 - pkgs = set->packages.data;
1.580 - pkg_count = set->packages.size / sizeof (struct razor_package);
1.581 - props = set->properties.data;
1.582 - prop_end = set->properties.data + set->properties.size;
1.583 + pkgs = trans->system->packages.data;
1.584 + pkg_count = trans->system->packages.size / sizeof (struct razor_package);
1.585 + props = trans->system->properties.data;
1.586 + prop_end = trans->system->properties.data + trans->system->properties.size;
1.587
1.588 - remove = list->data;
1.589 - remove_count = list->size / sizeof (uint32_t);
1.590 - r = 0;
1.591 - while (r < remove_count) {
1.592 + for (r = start; r < end; r++) {
1.593 + packages = package_array->data;
1.594 + if (packages[r].state != RAZOR_PACKAGE_REMOVE)
1.595 + continue;
1.596 +
1.597 array_init(&lost_provides);
1.598 - for (; r < remove_count; r++)
1.599 - gather_lost_provides(set, &pkgs[remove[r]], &lost_provides);
1.600 + req_package = packages[r].name;
1.601 + gather_lost_provides(trans->system, packages[r].package,
1.602 + &lost_provides);
1.603
1.604 lost_end = lost_provides.data + lost_provides.size;
1.605 for (lost = lost_provides.data; lost < lost_end; lost++) {
1.606 /* Requires FOO will appear before Provides FOO */
1.607 for (req = &props[*lost]; req > props && req->name == props[*lost].name && req->type != RAZOR_PROPERTY_REQUIRES; req--)
1.608 ;
1.609 - /* FIXME: versioned deps... */
1.610 + first_provider = req + 1;
1.611 +
1.612 while (req > props && req->name == props[*lost].name) {
1.613 - gather_lost_requires(set, req, list);
1.614 + lose_requirement(trans, package_array,
1.615 + req_package, req,
1.616 + &props[*lost], first_provider);
1.617 req--;
1.618 }
1.619 }
1.620 array_release(&lost_provides);
1.621 -
1.622 - remove = list->data;
1.623 - remove_count = list->size / sizeof (uint32_t);
1.624 }
1.625 -
1.626 - empty = razor_set_create();
1.627 - merger = razor_merger_create(set, empty);
1.628 -
1.629 - for (p = 0; p < pkg_count; p++) {
1.630 - for (r = 0; r < remove_count; r++) {
1.631 - if (p == remove[r])
1.632 - goto skip;
1.633 - }
1.634 - add_package(merger, &pkgs[p], &merger->source1, 0);
1.635 - skip:
1.636 - ;
1.637 - }
1.638 -
1.639 - new = razor_merger_finish(merger);
1.640 - razor_set_destroy(empty);
1.641 - return new;
1.642 -}
1.643 -
1.644 -struct razor_set *
1.645 -razor_set_remove(struct razor_set *set, int count, const char **packages)
1.646 -{
1.647 - struct razor_set *new;
1.648 - struct array list;
1.649 -
1.650 - array_init(&list);
1.651 - find_packages(set, count, packages, &list);
1.652 - new = razor_set_remove_internal(set, &list);
1.653 - array_release(&list);
1.654 - razor_set_destroy(set);
1.655 - return new;
1.656 }
1.657
1.658 /* The diff order matters. We should sort the packages so that a
1.659 @@ -2161,3 +2100,258 @@
1.660 razor_package_iterator_destroy(pi1);
1.661 razor_package_iterator_destroy(pi2);
1.662 }
1.663 +
1.664 +struct razor_transaction *
1.665 +razor_transaction_create(struct razor_set *system, struct razor_set *upstream,
1.666 + int update_count, const char **update_packages,
1.667 + int remove_count, const char **remove_packages)
1.668 +{
1.669 + struct razor_transaction *trans;
1.670 + struct array packages;
1.671 + int start, end;
1.672 +
1.673 + trans = zalloc(sizeof *trans);
1.674 + trans->system = system;
1.675 + trans->upstream = upstream ? upstream : razor_set_create();
1.676 + array_init(&packages);
1.677 +
1.678 + /* Find initial upstream packages to be installed */
1.679 + if (update_count > 0) {
1.680 + trans->errors +=
1.681 + find_packages(upstream, update_count, update_packages,
1.682 + &packages, RAZOR_PACKAGE_INSTALL);
1.683 + } else if (remove_count == 0)
1.684 + find_all_packages(system, upstream, &packages);
1.685 +
1.686 + /* Find initial installed packages to remove. */
1.687 + if (remove_count > 0) {
1.688 + trans->errors +=
1.689 + find_packages(system, remove_count, remove_packages,
1.690 + &packages, RAZOR_PACKAGE_REMOVE);
1.691 + }
1.692 +
1.693 + start = 0;
1.694 + end = packages.size / sizeof (struct razor_transaction_package);
1.695 +
1.696 + while (!trans->errors && start != end) {
1.697 + if (upstream)
1.698 + razor_transaction_satisfy_installs(trans, &packages, start, end);
1.699 + razor_transaction_satisfy_removes(trans, &packages, start, end);
1.700 +
1.701 + start = end;
1.702 + end = packages.size / sizeof (struct razor_transaction_package);
1.703 + }
1.704 +
1.705 + trans->packages = packages.data;
1.706 + trans->package_count = packages.size / sizeof (struct razor_transaction_package);
1.707 + return trans;
1.708 +}
1.709 +
1.710 +const char * const razor_version_relations[] = {
1.711 + /* same order as enum razor_version_relation */
1.712 + "<", "<=", "=", ">=", ">"
1.713 +};
1.714 +
1.715 +void
1.716 +razor_transaction_describe(struct razor_transaction *trans)
1.717 +{
1.718 + struct razor_transaction_package *p, *pend, *tps;
1.719 + int errors_only = 0;
1.720 +
1.721 + tps = trans->packages;
1.722 + pend = trans->packages + trans->package_count;
1.723 + for (p = trans->packages; p < pend; p++) {
1.724 + switch (p->state) {
1.725 + case RAZOR_PACKAGE_INSTALL:
1.726 + if (errors_only)
1.727 + break;
1.728 +
1.729 + printf ("Installing %s %s", p->name, p->version);
1.730 + if (p->req_package) {
1.731 + printf (" for %s", p->req_package);
1.732 + if (*p->req_version) {
1.733 + printf (", which requires %s %s %s",
1.734 + p->req_property,
1.735 + razor_version_relations[p->req_relation],
1.736 + p->req_version);
1.737 + } else if (strcmp(p->req_property, p->name) != 0) {
1.738 + printf (", which requires %s",
1.739 + p->req_property);
1.740 + }
1.741 + }
1.742 + printf("\n");
1.743 + break;
1.744 +
1.745 + case RAZOR_PACKAGE_INSTALL_UNAVAILABLE:
1.746 + if (*p->req_version && strcmp(p->req_property, p->name) == 0) {
1.747 + printf ("Can't find %s %s %s, which is required by %s",
1.748 + p->name,
1.749 + razor_version_relations[p->req_relation],
1.750 + p->req_version,
1.751 + p->req_package);
1.752 + } else {
1.753 + printf ("Can't find %s", p->name);
1.754 + if (*p->version)
1.755 + printf (" %s", p->version);
1.756 +
1.757 + if (p->req_package) {
1.758 + printf (" which is required by %s",
1.759 + p->req_package);
1.760 + if (strcmp(p->req_property, p->name) != 0)
1.761 + printf (" for %s", p->req_property);
1.762 + }
1.763 + }
1.764 + printf("\n");
1.765 + errors_only = 1;
1.766 + break;
1.767 +
1.768 + case RAZOR_PACKAGE_INSTALL_BLOCKED:
1.769 + printf ("Cannot install %s, which is already marked for removal but is required by %s\n", p->name, p->req_package);
1.770 + errors_only = 1;
1.771 + break;
1.772 +
1.773 + case RAZOR_PACKAGE_INSTALL_UNSATISFIABLE:
1.774 + printf ("Cannot find package for %s", p->req_property);
1.775 + if (*p->req_version) {
1.776 + printf (" %s %s",
1.777 + razor_version_relations[p->req_relation],
1.778 + p->req_version);
1.779 + }
1.780 + printf (" which is required by %s\n",
1.781 + p->req_package);
1.782 + errors_only = 1;
1.783 + break;
1.784 +
1.785 + case RAZOR_PACKAGE_REMOVE:
1.786 + if (errors_only)
1.787 + break;
1.788 + printf ("Removing %s %s", p->name, p->version);
1.789 + if (p->req_package) {
1.790 + printf (" which required %s", p->req_package);
1.791 + if (strcmp(p->req_property, p->req_package) != 0)
1.792 + printf (" for %s", p->req_property);
1.793 + }
1.794 + printf("\n");
1.795 + break;
1.796 +
1.797 + case RAZOR_PACKAGE_REMOVE_NOT_INSTALLED:
1.798 + printf ("Package %s is not installed\n", p->name);
1.799 + errors_only = 1;
1.800 + break;
1.801 +
1.802 + case RAZOR_PACKAGE_REMOVE_BLOCKED:
1.803 + printf ("Cannot remove %s, which is marked for installation but requires %s\n", p->name, p->req_package);
1.804 + errors_only = 1;
1.805 + break;
1.806 +
1.807 + default:
1.808 + /* Shouldn't actually happen */
1.809 + break;
1.810 + }
1.811 + }
1.812 +}
1.813 +
1.814 +struct razor_set *
1.815 +razor_transaction_run(struct razor_transaction *trans)
1.816 +{
1.817 + struct array install_packages, remove_packages;
1.818 + struct razor_merger *merger;
1.819 + struct razor_package *pkg, *i, *iend, *r, *rend, *s, *send;
1.820 + struct source *source1, *source2;
1.821 + char *spool, *ipool, *rpool;
1.822 + uint32_t *map;
1.823 + int p, cmp;
1.824 +
1.825 + /* FIXME */
1.826 + if (trans->errors)
1.827 + return NULL;
1.828 +
1.829 + /* Sort the transaction packages into two arrays */
1.830 + array_init(&install_packages);
1.831 + array_init(&remove_packages);
1.832 + for (p = 0; p < trans->package_count; p++) {
1.833 + if (trans->packages[p].state & RAZOR_PACKAGE_INSTALL)
1.834 + pkg = array_add(&install_packages, sizeof *pkg);
1.835 + else
1.836 + pkg = array_add(&remove_packages, sizeof *pkg);
1.837 + *pkg = *trans->packages[p].package;
1.838 + }
1.839 + map = qsort_with_data(install_packages.data,
1.840 + install_packages.size / sizeof *pkg,
1.841 + sizeof *pkg,
1.842 + compare_packages,
1.843 + trans->upstream);
1.844 + free(map);
1.845 + map = qsort_with_data(remove_packages.data,
1.846 + remove_packages.size / sizeof *pkg,
1.847 + sizeof *pkg,
1.848 + compare_packages,
1.849 + trans->system);
1.850 + free(map);
1.851 +
1.852 + merger = razor_merger_create(trans->system, trans->upstream);
1.853 +
1.854 + source1 = &merger->source1;
1.855 + source2 = &merger->source2;
1.856 +
1.857 + i = install_packages.data;
1.858 + iend = install_packages.data + install_packages.size;
1.859 + ipool = trans->upstream->string_pool.data;
1.860 +
1.861 + r = remove_packages.data;
1.862 + rend = remove_packages.data + remove_packages.size;
1.863 + rpool = trans->system->string_pool.data;
1.864 +
1.865 + s = trans->system->packages.data;
1.866 + send = trans->system->packages.data + trans->system->packages.size;
1.867 + spool = trans->system->string_pool.data;
1.868 +
1.869 + while (s < send || i < iend) {
1.870 + /* Check if s is being removed */
1.871 + if (s < send && r < rend &&
1.872 + s->name == r->name && s->version && r->version) {
1.873 + s++;
1.874 + r++;
1.875 + continue;
1.876 + }
1.877 +
1.878 + if (s < send && i < iend)
1.879 + cmp = strcmp(&spool[s->name], &ipool[i->name]);
1.880 + else if (s < send)
1.881 + cmp = -1;
1.882 + else
1.883 + cmp = 1;
1.884 + if (cmp < 0) {
1.885 + add_package(merger, s, source1, 0);
1.886 + s++;
1.887 + } else if (cmp == 0) {
1.888 + add_package(merger, i, source2, UPSTREAM_SOURCE);
1.889 + s++;
1.890 + i++;
1.891 + } else {
1.892 + add_package(merger, i, source2, UPSTREAM_SOURCE);
1.893 + i++;
1.894 + }
1.895 + }
1.896 +
1.897 + array_release(&install_packages);
1.898 + array_release(&remove_packages);
1.899 +
1.900 + return razor_merger_finish(merger);
1.901 +}
1.902 +
1.903 +void
1.904 +razor_transaction_destroy(struct razor_transaction *trans)
1.905 +{
1.906 + int p;
1.907 +
1.908 + for (p = 0; p < trans->package_count; p++) {
1.909 + if (!trans->packages[p].req_package &&
1.910 + (trans->packages[p].state == RAZOR_PACKAGE_INSTALL_UNAVAILABLE ||
1.911 + trans->packages[p].state == RAZOR_PACKAGE_REMOVE_NOT_INSTALLED))
1.912 + free((char *)trans->packages[p].name);
1.913 + }
1.914 + free(trans);
1.915 +
1.916 + /* FIXME: free upstream if it was created as an empty set */
1.917 +}