1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/librazor/transaction.c Fri Jun 20 22:26:41 2008 -0400
1.3 @@ -0,0 +1,912 @@
1.4 +/*
1.5 + * Copyright (C) 2008 Kristian Høgsberg <krh@redhat.com>
1.6 + * Copyright (C) 2008 Red Hat, Inc
1.7 + *
1.8 + * This program is free software; you can redistribute it and/or modify
1.9 + * it under the terms of the GNU General Public License as published by
1.10 + * the Free Software Foundation; either version 2 of the License, or
1.11 + * (at your option) any later version.
1.12 + *
1.13 + * This program is distributed in the hope that it will be useful,
1.14 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
1.15 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1.16 + * GNU General Public License for more details.
1.17 + *
1.18 + * You should have received a copy of the GNU General Public License along
1.19 + * with this program; if not, write to the Free Software Foundation, Inc.,
1.20 + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
1.21 + */
1.22 +
1.23 +#define _GNU_SOURCE
1.24 +
1.25 +#include <stdlib.h>
1.26 +#include <stddef.h>
1.27 +#include <stdint.h>
1.28 +#include <stdio.h>
1.29 +#include <string.h>
1.30 +#include <sys/types.h>
1.31 +#include <sys/stat.h>
1.32 +#include <sys/mman.h>
1.33 +#include <unistd.h>
1.34 +#include <fcntl.h>
1.35 +#include <errno.h>
1.36 +#include <ctype.h>
1.37 +#include <fnmatch.h>
1.38 +
1.39 +#include "razor-internal.h"
1.40 +#include "razor.h"
1.41 +
1.42 +static int
1.43 +provider_satisfies_requirement(struct razor_property *provider,
1.44 + const char *provider_strings,
1.45 + uint32_t flags,
1.46 + const char *required)
1.47 +{
1.48 + int cmp, len;
1.49 + const char *provided = &provider_strings[provider->version];
1.50 +
1.51 + if (!*required)
1.52 + return 1;
1.53 + if (!*provided) {
1.54 + if (flags & RAZOR_PROPERTY_LESS)
1.55 + return 0;
1.56 + else
1.57 + return 1;
1.58 + }
1.59 +
1.60 + cmp = razor_versioncmp(provided, required);
1.61 +
1.62 + switch (flags & RAZOR_PROPERTY_RELATION_MASK) {
1.63 + case RAZOR_PROPERTY_LESS:
1.64 + return cmp < 0;
1.65 +
1.66 + case RAZOR_PROPERTY_LESS | RAZOR_PROPERTY_EQUAL:
1.67 + if (cmp <= 0)
1.68 + return 1;
1.69 + /* fall through: FIXME, make sure this is correct */
1.70 +
1.71 + case RAZOR_PROPERTY_EQUAL:
1.72 + if (cmp == 0)
1.73 + return 1;
1.74 +
1.75 + /* "foo == 1.1" is satisfied by "foo 1.1-2" */
1.76 + len = strlen(required);
1.77 + if (!strncmp(required, provided, len) && provided[len] == '-')
1.78 + return 1;
1.79 + return 0;
1.80 +
1.81 + case RAZOR_PROPERTY_GREATER | RAZOR_PROPERTY_EQUAL:
1.82 + return cmp >= 0;
1.83 +
1.84 + case RAZOR_PROPERTY_GREATER:
1.85 + return cmp > 0;
1.86 + }
1.87 +
1.88 + /* shouldn't happen */
1.89 + return 0;
1.90 +}
1.91 +
1.92 +#define TRANS_PACKAGE_PRESENT 1
1.93 +#define TRANS_PACKAGE_UPDATE 2
1.94 +#define TRANS_PROPERTY_SATISFIED 0x80000000
1.95 +
1.96 +struct transaction_set {
1.97 + struct razor_set *set;
1.98 + uint32_t *packages;
1.99 + uint32_t *properties;
1.100 +};
1.101 +
1.102 +struct razor_transaction {
1.103 + int package_count, errors;
1.104 + struct transaction_set system, upstream;
1.105 + int changes;
1.106 +};
1.107 +
1.108 +static void
1.109 +transaction_set_init(struct transaction_set *ts, struct razor_set *set)
1.110 +{
1.111 + int count;
1.112 +
1.113 + ts->set = set;
1.114 + count = set->packages.size / sizeof (struct razor_package);
1.115 + ts->packages = zalloc(count * sizeof *ts->packages);
1.116 + count = set->properties.size / sizeof (struct razor_property);
1.117 + ts->properties = zalloc(count * sizeof *ts->properties);
1.118 +}
1.119 +
1.120 +static void
1.121 +transaction_set_release(struct transaction_set *ts)
1.122 +{
1.123 + free(ts->packages);
1.124 + free(ts->properties);
1.125 +}
1.126 +
1.127 +static void
1.128 +transaction_set_install_package(struct transaction_set *ts,
1.129 + struct razor_package *package)
1.130 +{
1.131 + struct razor_package *pkgs;
1.132 + struct list *prop;
1.133 + int i;
1.134 +
1.135 + pkgs = ts->set->packages.data;
1.136 + i = package - pkgs;
1.137 + if (ts->packages[i] == TRANS_PACKAGE_PRESENT)
1.138 + return;
1.139 +
1.140 + ts->packages[i] = TRANS_PACKAGE_PRESENT;
1.141 +
1.142 + prop = list_first(&package->properties, &ts->set->property_pool);
1.143 + while (prop) {
1.144 + ts->properties[prop->data]++;
1.145 + prop = list_next(prop);
1.146 + }
1.147 +}
1.148 +
1.149 +static void
1.150 +transaction_set_remove_package(struct transaction_set *ts,
1.151 + struct razor_package *package)
1.152 +{
1.153 + struct razor_package *pkgs;
1.154 + struct list *prop;
1.155 + int i;
1.156 +
1.157 + pkgs = ts->set->packages.data;
1.158 + i = package - pkgs;
1.159 + if (ts->packages[i] == 0)
1.160 + return;
1.161 +
1.162 + ts->packages[i] = 0;
1.163 +
1.164 + prop = list_first(&package->properties, &ts->set->property_pool);
1.165 + while (prop) {
1.166 + ts->properties[prop->data]--;
1.167 + prop = list_next(prop);
1.168 + }
1.169 +}
1.170 +
1.171 +struct razor_transaction *
1.172 +razor_transaction_create(struct razor_set *system, struct razor_set *upstream)
1.173 +{
1.174 + struct razor_transaction *trans;
1.175 + struct razor_package *p, *spkgs, *pend;
1.176 +
1.177 + trans = zalloc(sizeof *trans);
1.178 + transaction_set_init(&trans->system, system);
1.179 + transaction_set_init(&trans->upstream, upstream);
1.180 +
1.181 + spkgs = trans->system.set->packages.data;
1.182 + pend = trans->system.set->packages.data +
1.183 + trans->system.set->packages.size;
1.184 + for (p = spkgs; p < pend; p++)
1.185 + transaction_set_install_package(&trans->system, p);
1.186 +
1.187 + return trans;
1.188 +}
1.189 +
1.190 +void
1.191 +razor_transaction_install_package(struct razor_transaction *trans,
1.192 + struct razor_package *package)
1.193 +{
1.194 + transaction_set_install_package(&trans->upstream, package);
1.195 + trans->changes++;
1.196 +}
1.197 +
1.198 +void
1.199 +razor_transaction_remove_package(struct razor_transaction *trans,
1.200 + struct razor_package *package)
1.201 +{
1.202 + transaction_set_remove_package(&trans->system, package);
1.203 + trans->changes++;
1.204 +}
1.205 +
1.206 +void
1.207 +razor_transaction_update_package(struct razor_transaction *trans,
1.208 + struct razor_package *package)
1.209 +{
1.210 + struct razor_package *spkgs, *upkgs, *end;
1.211 +
1.212 + spkgs = trans->system.set->packages.data;
1.213 + upkgs = trans->upstream.set->packages.data;
1.214 + end = trans->system.set->packages.data +
1.215 + trans->system.set->packages.size;
1.216 + if (spkgs <= package && package < end)
1.217 + trans->system.packages[package - spkgs] |= TRANS_PACKAGE_UPDATE;
1.218 + else
1.219 + trans->upstream.packages[package - upkgs] |= TRANS_PACKAGE_UPDATE;
1.220 +}
1.221 +
1.222 +struct prop_iter {
1.223 + struct razor_property *p, *start, *end;
1.224 + const char *pool;
1.225 + uint32_t *present;
1.226 +};
1.227 +
1.228 +static void
1.229 +prop_iter_init(struct prop_iter *pi, struct transaction_set *ts)
1.230 +{
1.231 + pi->p = ts->set->properties.data;
1.232 + pi->start = ts->set->properties.data;
1.233 + pi->end = ts->set->properties.data + ts->set->properties.size;
1.234 + pi->pool = ts->set->string_pool.data;
1.235 + pi->present = ts->properties;
1.236 +}
1.237 +
1.238 +static int
1.239 +prop_iter_next(struct prop_iter *pi, uint32_t flags, struct razor_property **p)
1.240 +{
1.241 + while (pi->p < pi->end) {
1.242 + if ((pi->present[pi->p - pi->start] & ~TRANS_PROPERTY_SATISFIED) &&
1.243 + (pi->p->flags & RAZOR_PROPERTY_TYPE_MASK) == flags) {
1.244 + *p = pi->p++;
1.245 + return 1;
1.246 + }
1.247 + pi->p++;
1.248 + }
1.249 +
1.250 + return 0;
1.251 +}
1.252 +
1.253 +static struct razor_property *
1.254 +prop_iter_seek_to(struct prop_iter *pi,
1.255 + uint32_t flags, const char *match)
1.256 +{
1.257 + uint32_t name;
1.258 +
1.259 + while (pi->p < pi->end && strcmp(&pi->pool[pi->p->name], match) < 0)
1.260 + pi->p++;
1.261 +
1.262 + if (pi->p == pi->end || strcmp(&pi->pool[pi->p->name], match) > 0)
1.263 + return NULL;
1.264 +
1.265 + name = pi->p->name;
1.266 + while (pi->p < pi->end &&
1.267 + pi->p->name == name &&
1.268 + (pi->p->flags & RAZOR_PROPERTY_TYPE_MASK) != flags)
1.269 + pi->p++;
1.270 +
1.271 + if (pi->p == pi->end || pi->p->name != name)
1.272 + return NULL;
1.273 +
1.274 + return pi->p;
1.275 +}
1.276 +
1.277 +/* Remove packages from set that provide any of the matching (same
1.278 + * name and type) providers from ppi onwards that match the
1.279 + * requirement that rpi points to. */
1.280 +static void
1.281 +remove_matching_providers(struct razor_transaction *trans,
1.282 + struct prop_iter *ppi,
1.283 + uint32_t flags,
1.284 + const char *version)
1.285 +{
1.286 + struct razor_property *p;
1.287 + struct razor_package *pkg, *pkgs;
1.288 + struct razor_package_iterator pkg_iter;
1.289 + struct razor_set *set;
1.290 + const char *n, *v, *a;
1.291 + uint32_t type;
1.292 +
1.293 + if (ppi->present == trans->system.properties)
1.294 + set = trans->system.set;
1.295 + else
1.296 + set = trans->upstream.set;
1.297 +
1.298 + pkgs = (struct razor_package *) set->packages.data;
1.299 + type = ppi->p->flags & RAZOR_PROPERTY_TYPE_MASK;
1.300 + for (p = ppi->p;
1.301 + p < ppi->end &&
1.302 + p->name == ppi->p->name &&
1.303 + (p->flags & RAZOR_PROPERTY_TYPE_MASK) == type;
1.304 + p++) {
1.305 + if (!ppi->present[p - ppi->start])
1.306 + continue;
1.307 + if (!provider_satisfies_requirement(p, ppi->pool,
1.308 + flags, version))
1.309 + continue;
1.310 +
1.311 + razor_package_iterator_init_for_property(&pkg_iter, set, p);
1.312 + while (razor_package_iterator_next(&pkg_iter,
1.313 + &pkg, &n, &v, &a)) {
1.314 + fprintf(stderr, "removing %s-%s\n", n, v);
1.315 + razor_transaction_remove_package(trans, pkg);
1.316 + }
1.317 + }
1.318 +}
1.319 +
1.320 +static void
1.321 +flag_matching_providers(struct razor_transaction *trans,
1.322 + struct prop_iter *ppi,
1.323 + struct razor_property *r,
1.324 + struct prop_iter *rpi,
1.325 + unsigned int flag)
1.326 +{
1.327 + struct razor_property *p;
1.328 + struct razor_package *pkg, *pkgs;
1.329 + struct razor_package_iterator pkg_iter;
1.330 + struct razor_set *set;
1.331 + const char *name, *version, *arch;
1.332 + uint32_t *flags, type;
1.333 +
1.334 + if (ppi->present == trans->system.properties) {
1.335 + set = trans->system.set;
1.336 + flags = trans->system.packages;
1.337 + } else {
1.338 + set = trans->upstream.set;
1.339 + flags = trans->upstream.packages;
1.340 + }
1.341 +
1.342 + pkgs = (struct razor_package *) set->packages.data;
1.343 + type = ppi->p->flags & RAZOR_PROPERTY_TYPE_MASK;
1.344 + for (p = ppi->p;
1.345 + p < ppi->end &&
1.346 + p->name == ppi->p->name &&
1.347 + (p->flags & RAZOR_PROPERTY_TYPE_MASK) == type;
1.348 + p++) {
1.349 + if (!ppi->present[p - ppi->start])
1.350 + continue;
1.351 + if (!provider_satisfies_requirement(p, ppi->pool,
1.352 + r->flags,
1.353 + &rpi->pool[r->version]))
1.354 + continue;
1.355 +
1.356 + razor_package_iterator_init_for_property(&pkg_iter, set, p);
1.357 + while (razor_package_iterator_next(&pkg_iter, &pkg,
1.358 + &name, &version, &arch)) {
1.359 +
1.360 + fprintf(stderr, "flagging %s-%s for providing %s matching %s %s\n",
1.361 + name, version,
1.362 + ppi->pool + p->name,
1.363 + rpi->pool + r->name,
1.364 + rpi->pool + r->version);
1.365 + flags[pkg - pkgs] |= flag;
1.366 + }
1.367 + }
1.368 +}
1.369 +
1.370 +static struct razor_package *
1.371 +pick_matching_provider(struct razor_set *set,
1.372 + struct prop_iter *ppi,
1.373 + uint32_t flags,
1.374 + const char *version)
1.375 +{
1.376 + struct razor_property *p;
1.377 + struct razor_package *pkgs;
1.378 + struct list *i;
1.379 + uint32_t type;
1.380 +
1.381 + /* This is where we decide which pkgs to pull in to satisfy a
1.382 + * requirement. There may be several different providers
1.383 + * (different versions) and each version of a provider may
1.384 + * come from a number of packages. We pick the first package
1.385 + * from the first provider that matches. */
1.386 +
1.387 + pkgs = set->packages.data;
1.388 + type = ppi->p->flags & RAZOR_PROPERTY_TYPE_MASK;
1.389 + for (p = ppi->p;
1.390 + p < ppi->end &&
1.391 + p->name == ppi->p->name &&
1.392 + (p->flags & RAZOR_PROPERTY_TYPE_MASK) == type &&
1.393 + ppi->present[p - ppi->start] == 0;
1.394 + p++) {
1.395 + if (!provider_satisfies_requirement(p, ppi->pool,
1.396 + flags, version))
1.397 + continue;
1.398 +
1.399 + i = list_first(&p->packages, &set->package_pool);
1.400 +
1.401 + return &pkgs[i->data];
1.402 + }
1.403 +
1.404 + return NULL;
1.405 +}
1.406 +
1.407 +static void
1.408 +remove_obsoleted_packages(struct razor_transaction *trans)
1.409 +{
1.410 + struct razor_property *up;
1.411 + struct razor_package *spkgs;
1.412 + struct prop_iter spi, upi;
1.413 +
1.414 + spkgs = trans->system.set->packages.data;
1.415 + prop_iter_init(&spi, &trans->system);
1.416 + prop_iter_init(&upi, &trans->upstream);
1.417 +
1.418 + while (prop_iter_next(&upi, RAZOR_PROPERTY_OBSOLETES, &up)) {
1.419 + if (!prop_iter_seek_to(&spi, RAZOR_PROPERTY_PROVIDES,
1.420 + &upi.pool[up->name]))
1.421 + continue;
1.422 + remove_matching_providers(trans, &spi, up->flags,
1.423 + &upi.pool[up->version]);
1.424 + }
1.425 +}
1.426 +
1.427 +static int
1.428 +any_provider_satisfies_requirement(struct prop_iter *ppi,
1.429 + uint32_t flags,
1.430 + const char *version)
1.431 +{
1.432 + struct razor_property *p;
1.433 + uint32_t type;
1.434 +
1.435 + type = ppi->p->flags & RAZOR_PROPERTY_TYPE_MASK;
1.436 + for (p = ppi->p;
1.437 + p < ppi->end &&
1.438 + p->name == ppi->p->name &&
1.439 + (p->flags & RAZOR_PROPERTY_TYPE_MASK) == type;
1.440 + p++) {
1.441 + if (ppi->present[p - ppi->start] > 0 &&
1.442 + provider_satisfies_requirement(p, ppi->pool,
1.443 + flags, version))
1.444 + return 1;
1.445 + }
1.446 +
1.447 + return 0;
1.448 +}
1.449 +
1.450 +static void
1.451 +clear_requires_flags(struct transaction_set *ts)
1.452 +{
1.453 + struct razor_property *p;
1.454 + const char *pool;
1.455 + int i, count;
1.456 +
1.457 + count = ts->set->properties.size / sizeof *p;
1.458 + p = ts->set->properties.data;
1.459 + pool = ts->set->string_pool.data;
1.460 + for (i = 0; i < count; i++) {
1.461 + ts->properties[i] &= ~TRANS_PROPERTY_SATISFIED;
1.462 + if (strncmp(&pool[p[i].name], "rpmlib(", 7) == 0)
1.463 + ts->properties[i] |= TRANS_PROPERTY_SATISFIED;
1.464 + }
1.465 +}
1.466 +
1.467 +const char *
1.468 +razor_property_relation_to_string(struct razor_property *p)
1.469 +{
1.470 + switch (p->flags & RAZOR_PROPERTY_RELATION_MASK) {
1.471 + case RAZOR_PROPERTY_LESS:
1.472 + return "<";
1.473 +
1.474 + case RAZOR_PROPERTY_LESS | RAZOR_PROPERTY_EQUAL:
1.475 + return "<=";
1.476 +
1.477 + case RAZOR_PROPERTY_EQUAL:
1.478 + return "=";
1.479 +
1.480 + case RAZOR_PROPERTY_GREATER | RAZOR_PROPERTY_EQUAL:
1.481 + return ">=";
1.482 +
1.483 + case RAZOR_PROPERTY_GREATER:
1.484 + return ">";
1.485 +
1.486 + default:
1.487 + return "?";
1.488 + }
1.489 +}
1.490 +
1.491 +const char *
1.492 +razor_property_type_to_string(struct razor_property *p)
1.493 +{
1.494 + switch (p->flags & RAZOR_PROPERTY_TYPE_MASK) {
1.495 + case RAZOR_PROPERTY_REQUIRES:
1.496 + return "requires";
1.497 + case RAZOR_PROPERTY_PROVIDES:
1.498 + return "provides";
1.499 + case RAZOR_PROPERTY_CONFLICTS:
1.500 + return "conflicts";
1.501 + case RAZOR_PROPERTY_OBSOLETES:
1.502 + return "obsoletes";
1.503 + default:
1.504 + return NULL;
1.505 + }
1.506 +}
1.507 +
1.508 +static void
1.509 +mark_satisfied_requires(struct razor_transaction *trans,
1.510 + struct transaction_set *rts,
1.511 + struct transaction_set *pts)
1.512 +{
1.513 + struct prop_iter rpi, ppi;
1.514 + struct razor_property *rp;
1.515 +
1.516 + prop_iter_init(&rpi, rts);
1.517 + prop_iter_init(&ppi, pts);
1.518 +
1.519 + while (prop_iter_next(&rpi, RAZOR_PROPERTY_REQUIRES, &rp)) {
1.520 + if (!prop_iter_seek_to(&ppi, RAZOR_PROPERTY_PROVIDES,
1.521 + &rpi.pool[rp->name]))
1.522 + continue;
1.523 +
1.524 + if (any_provider_satisfies_requirement(&ppi, rp->flags,
1.525 + &rpi.pool[rp->version]))
1.526 + rpi.present[rp - rpi.start] |= TRANS_PROPERTY_SATISFIED;
1.527 + }
1.528 +}
1.529 +
1.530 +static void
1.531 +mark_all_satisfied_requires(struct razor_transaction *trans)
1.532 +{
1.533 + clear_requires_flags(&trans->system);
1.534 + clear_requires_flags(&trans->upstream);
1.535 + mark_satisfied_requires(trans, &trans->system, &trans->system);
1.536 + mark_satisfied_requires(trans, &trans->system, &trans->upstream);
1.537 + mark_satisfied_requires(trans, &trans->upstream, &trans->system);
1.538 + mark_satisfied_requires(trans, &trans->upstream, &trans->upstream);
1.539 +}
1.540 +
1.541 +static void
1.542 +update_unsatisfied_packages(struct razor_transaction *trans)
1.543 +{
1.544 + struct razor_package *spkgs, *pkg;
1.545 + struct razor_property *sp;
1.546 + struct prop_iter spi;
1.547 + struct razor_package_iterator pkg_iter;
1.548 + const char *name, *version, *arch;
1.549 +
1.550 + spkgs = trans->system.set->packages.data;
1.551 + prop_iter_init(&spi, &trans->system);
1.552 +
1.553 + while (prop_iter_next(&spi, RAZOR_PROPERTY_REQUIRES, &sp)) {
1.554 + if (spi.present[sp - spi.start] & TRANS_PROPERTY_SATISFIED)
1.555 + continue;
1.556 +
1.557 + razor_package_iterator_init_for_property(&pkg_iter,
1.558 + trans->system.set,
1.559 + sp);
1.560 + while (razor_package_iterator_next(&pkg_iter, &pkg,
1.561 + &name, &version, &arch)) {
1.562 + fprintf(stderr, "updating %s because %s %s %s "
1.563 + "isn't satisfied\n",
1.564 + name, spi.pool + sp->name,
1.565 + razor_property_relation_to_string(sp),
1.566 + spi.pool + sp->version);
1.567 + trans->system.packages[pkg - spkgs] |=
1.568 + TRANS_PACKAGE_UPDATE;
1.569 + }
1.570 + }
1.571 +}
1.572 +
1.573 +void
1.574 +razor_transaction_update_all(struct razor_transaction *trans)
1.575 +{
1.576 + struct razor_package *p;
1.577 + int i, count;
1.578 +
1.579 + count = trans->system.set->packages.size / sizeof *p;
1.580 + for (i = 0; i < count; i++)
1.581 + trans->system.packages[i] |= TRANS_PACKAGE_UPDATE;
1.582 +}
1.583 +
1.584 +static void
1.585 +update_conflicted_packages(struct razor_transaction *trans)
1.586 +{
1.587 + struct razor_package *pkg, *spkgs;
1.588 + struct razor_property *up, *sp;
1.589 + struct prop_iter spi, upi;
1.590 + struct razor_package_iterator pkg_iter;
1.591 + const char *name, *version, *arch;
1.592 +
1.593 + spkgs = trans->system.set->packages.data;
1.594 + prop_iter_init(&spi, &trans->system);
1.595 + prop_iter_init(&upi, &trans->upstream);
1.596 +
1.597 + while (prop_iter_next(&spi, RAZOR_PROPERTY_CONFLICTS, &sp)) {
1.598 + if (!prop_iter_seek_to(&upi, RAZOR_PROPERTY_PROVIDES,
1.599 + &spi.pool[sp->name]))
1.600 + continue;
1.601 +
1.602 + if (!any_provider_satisfies_requirement(&upi, sp->flags,
1.603 + &spi.pool[sp->version]))
1.604 + continue;
1.605 +
1.606 + razor_package_iterator_init_for_property(&pkg_iter,
1.607 + trans->system.set,
1.608 + sp);
1.609 + while (razor_package_iterator_next(&pkg_iter, &pkg,
1.610 + &name, &version, &arch)) {
1.611 + fprintf(stderr, "updating %s %s because it conflicts with %s",
1.612 + name, version, spi.pool + sp->name);
1.613 + trans->system.packages[pkg - spkgs] |=
1.614 + TRANS_PACKAGE_UPDATE;
1.615 + }
1.616 + }
1.617 +
1.618 + prop_iter_init(&spi, &trans->system);
1.619 + prop_iter_init(&upi, &trans->upstream);
1.620 +
1.621 + while (prop_iter_next(&upi, RAZOR_PROPERTY_CONFLICTS, &up)) {
1.622 + sp = prop_iter_seek_to(&spi, RAZOR_PROPERTY_PROVIDES,
1.623 + &upi.pool[upi.p->name]);
1.624 +
1.625 + if (sp)
1.626 + flag_matching_providers(trans, &spi, up, &upi,
1.627 + TRANS_PACKAGE_UPDATE);
1.628 + }
1.629 +}
1.630 +
1.631 +static void
1.632 +pull_in_requirements(struct razor_transaction *trans,
1.633 + struct prop_iter *rpi, struct prop_iter *ppi)
1.634 +{
1.635 + struct razor_property *rp, *pp;
1.636 + struct razor_package *pkg, *upkgs;
1.637 +
1.638 + upkgs = trans->upstream.set->packages.data;
1.639 + while (prop_iter_next(rpi, RAZOR_PROPERTY_REQUIRES, &rp)) {
1.640 + if (rpi->present[rp - rpi->start] & TRANS_PROPERTY_SATISFIED)
1.641 + continue;
1.642 +
1.643 + pp = prop_iter_seek_to(ppi, RAZOR_PROPERTY_PROVIDES,
1.644 + &rpi->pool[rp->name]);
1.645 + if (pp == NULL)
1.646 + continue;
1.647 + pkg = pick_matching_provider(trans->upstream.set,
1.648 + ppi, rp->flags,
1.649 + &rpi->pool[rp->version]);
1.650 + if (pkg == NULL)
1.651 + continue;
1.652 +
1.653 + rpi->present[rp - rpi->start] |= TRANS_PROPERTY_SATISFIED;
1.654 +
1.655 + fprintf(stderr, "pulling in %s which provides %s %s %s "
1.656 + "to satisfy %s %s %s\n",
1.657 + ppi->pool + pkg->name,
1.658 + ppi->pool + pp->name,
1.659 + razor_property_relation_to_string(pp),
1.660 + ppi->pool + pp->version,
1.661 + &rpi->pool[rp->name],
1.662 + razor_property_relation_to_string(rp),
1.663 + &rpi->pool[rp->version]);
1.664 +
1.665 + trans->upstream.packages[pkg - upkgs] |= TRANS_PACKAGE_UPDATE;
1.666 + }
1.667 +}
1.668 +
1.669 +static void
1.670 +pull_in_all_requirements(struct razor_transaction *trans)
1.671 +{
1.672 + struct prop_iter rpi, ppi;
1.673 +
1.674 + prop_iter_init(&rpi, &trans->system);
1.675 + prop_iter_init(&ppi, &trans->upstream);
1.676 + pull_in_requirements(trans, &rpi, &ppi);
1.677 +
1.678 + prop_iter_init(&rpi, &trans->upstream);
1.679 + prop_iter_init(&ppi, &trans->upstream);
1.680 + pull_in_requirements(trans, &rpi, &ppi);
1.681 +}
1.682 +
1.683 +static void
1.684 +flush_scheduled_system_updates(struct razor_transaction *trans)
1.685 +{
1.686 + struct razor_package_iterator *pi;
1.687 + struct razor_package *p, *pkg, *spkgs;
1.688 + struct prop_iter ppi;
1.689 + const char *name, *version, *arch;
1.690 +
1.691 + spkgs = trans->system.set->packages.data;
1.692 + pi = razor_package_iterator_create(trans->system.set);
1.693 + prop_iter_init(&ppi, &trans->upstream);
1.694 +
1.695 + while (razor_package_iterator_next(pi, &p, &name, &version, &arch)) {
1.696 + if (!(trans->system.packages[p - spkgs] & TRANS_PACKAGE_UPDATE))
1.697 + continue;
1.698 +
1.699 + if (!prop_iter_seek_to(&ppi, RAZOR_PROPERTY_PROVIDES, name))
1.700 + continue;
1.701 +
1.702 + pkg = pick_matching_provider(trans->upstream.set, &ppi,
1.703 + RAZOR_PROPERTY_GREATER, version);
1.704 + if (pkg == NULL)
1.705 + continue;
1.706 +
1.707 + fprintf(stderr, "updating %s-%s to %s-%s\n",
1.708 + name, version,
1.709 + &ppi.pool[pkg->name], &ppi.pool[pkg->version]);
1.710 +
1.711 + razor_transaction_remove_package(trans, p);
1.712 + razor_transaction_install_package(trans, pkg);
1.713 + }
1.714 +
1.715 + razor_package_iterator_destroy(pi);
1.716 +}
1.717 +
1.718 +static void
1.719 +flush_scheduled_upstream_updates(struct razor_transaction *trans)
1.720 +{
1.721 + struct razor_package_iterator *pi;
1.722 + struct razor_package *p, *upkgs;
1.723 + struct prop_iter spi;
1.724 + const char *name, *version, *arch;
1.725 +
1.726 + upkgs = trans->upstream.set->packages.data;
1.727 + pi = razor_package_iterator_create(trans->upstream.set);
1.728 + prop_iter_init(&spi, &trans->system);
1.729 +
1.730 + while (razor_package_iterator_next(pi, &p, &name, &version, &arch)) {
1.731 + if (!(trans->upstream.packages[p - upkgs] & TRANS_PACKAGE_UPDATE))
1.732 + continue;
1.733 +
1.734 + if (prop_iter_seek_to(&spi, RAZOR_PROPERTY_PROVIDES, name))
1.735 + remove_matching_providers(trans,
1.736 + &spi,
1.737 + RAZOR_PROPERTY_LESS,
1.738 + version);
1.739 + razor_transaction_install_package(trans, p);
1.740 + fprintf(stderr, "installing %s-%s\n", name, version);
1.741 + }
1.742 +}
1.743 +
1.744 +int
1.745 +razor_transaction_resolve(struct razor_transaction *trans)
1.746 +{
1.747 + int last = 0;
1.748 +
1.749 + flush_scheduled_system_updates(trans);
1.750 + flush_scheduled_upstream_updates(trans);
1.751 +
1.752 + while (last < trans->changes) {
1.753 + last = trans->changes;
1.754 + remove_obsoleted_packages(trans);
1.755 + mark_all_satisfied_requires(trans);
1.756 + update_unsatisfied_packages(trans);
1.757 + update_conflicted_packages(trans);
1.758 + pull_in_all_requirements(trans);
1.759 + flush_scheduled_system_updates(trans);
1.760 + flush_scheduled_upstream_updates(trans);
1.761 + }
1.762 +
1.763 + return trans->changes;
1.764 +}
1.765 +
1.766 +static void
1.767 +describe_unsatisfied(struct razor_set *set, struct razor_property *rp)
1.768 +{
1.769 + struct razor_package_iterator pi;
1.770 + struct razor_package *pkg;
1.771 + const char *name, *version, *arch, *pool;
1.772 +
1.773 + pool = set->string_pool.data;
1.774 + if (pool[rp->version] == '\0') {
1.775 + razor_package_iterator_init_for_property(&pi, set, rp);
1.776 + while (razor_package_iterator_next(&pi, &pkg,
1.777 + &name, &version, &arch))
1.778 + fprintf(stderr, "%s is needed by %s-%s.%s\n",
1.779 + &pool[rp->name],
1.780 + name, version, arch);
1.781 + } else {
1.782 + razor_package_iterator_init_for_property(&pi, set, rp);
1.783 + while (razor_package_iterator_next(&pi, &pkg,
1.784 + &name, &version, &arch))
1.785 + fprintf(stderr, "%s %s %s is needed by %s-%s.%s\n",
1.786 + &pool[rp->name],
1.787 + razor_property_relation_to_string(rp),
1.788 + &pool[rp->version],
1.789 + name, version, arch);
1.790 + }
1.791 +}
1.792 +
1.793 +int
1.794 +razor_transaction_describe(struct razor_transaction *trans)
1.795 +{
1.796 + struct prop_iter rpi;
1.797 + struct razor_property *rp;
1.798 + int unsatisfied;
1.799 +
1.800 + flush_scheduled_system_updates(trans);
1.801 + flush_scheduled_upstream_updates(trans);
1.802 + mark_all_satisfied_requires(trans);
1.803 +
1.804 + unsatisfied = 0;
1.805 + prop_iter_init(&rpi, &trans->system);
1.806 + while (prop_iter_next(&rpi, RAZOR_PROPERTY_REQUIRES, &rp)) {
1.807 + if (!(rpi.present[rp - rpi.start] & TRANS_PROPERTY_SATISFIED)) {
1.808 + describe_unsatisfied(trans->system.set, rp);
1.809 + unsatisfied++;
1.810 + }
1.811 + }
1.812 +
1.813 + prop_iter_init(&rpi, &trans->upstream);
1.814 + while (prop_iter_next(&rpi, RAZOR_PROPERTY_REQUIRES, &rp)) {
1.815 + if (!(rpi.present[rp - rpi.start] & TRANS_PROPERTY_SATISFIED)) {
1.816 + describe_unsatisfied(trans->upstream.set, rp);
1.817 + unsatisfied++;
1.818 + }
1.819 + }
1.820 +
1.821 + return unsatisfied;
1.822 +}
1.823 +
1.824 +int
1.825 +razor_transaction_unsatisfied_property(struct razor_transaction *trans,
1.826 + const char *name,
1.827 + uint32_t flags,
1.828 + const char *version)
1.829 +{
1.830 + struct prop_iter pi;
1.831 + struct razor_property *p;
1.832 +
1.833 + prop_iter_init(&pi, &trans->system);
1.834 + while (prop_iter_next(&pi, flags, &p)) {
1.835 + if (!(trans->system.properties[p - pi.start] & TRANS_PROPERTY_SATISFIED) &&
1.836 + p->flags == flags &&
1.837 + strcmp(&pi.pool[p->name], name) == 0 &&
1.838 + strcmp(&pi.pool[p->version], version) == 0)
1.839 +
1.840 + return 1;
1.841 + }
1.842 +
1.843 + prop_iter_init(&pi, &trans->upstream);
1.844 + while (prop_iter_next(&pi, flags, &p)) {
1.845 + if (!(trans->upstream.properties[p - pi.start] & TRANS_PROPERTY_SATISFIED) &&
1.846 + p->flags == flags &&
1.847 + strcmp(&pi.pool[p->name], name) == 0 &&
1.848 + strcmp(&pi.pool[p->version], version) == 0)
1.849 +
1.850 + return 1;
1.851 + }
1.852 +
1.853 + return 0;
1.854 +}
1.855 +
1.856 +struct razor_set *
1.857 +razor_transaction_finish(struct razor_transaction *trans)
1.858 +{
1.859 + struct razor_merger *merger;
1.860 + struct razor_package *u, *uend, *upkgs, *s, *send, *spkgs;
1.861 + char *upool, *spool;
1.862 + int cmp;
1.863 +
1.864 + s = trans->system.set->packages.data;
1.865 + spkgs = trans->system.set->packages.data;
1.866 + send = trans->system.set->packages.data +
1.867 + trans->system.set->packages.size;
1.868 + spool = trans->system.set->string_pool.data;
1.869 +
1.870 + u = trans->upstream.set->packages.data;
1.871 + upkgs = trans->upstream.set->packages.data;
1.872 + uend = trans->upstream.set->packages.data +
1.873 + trans->upstream.set->packages.size;
1.874 + upool = trans->upstream.set->string_pool.data;
1.875 +
1.876 + merger = razor_merger_create(trans->system.set, trans->upstream.set);
1.877 + while (s < send || u < uend) {
1.878 + if (s < send && u < uend)
1.879 + cmp = strcmp(&spool[s->name], &upool[u->name]);
1.880 + else if (s < send)
1.881 + cmp = -1;
1.882 + else
1.883 + cmp = 1;
1.884 +
1.885 + if (cmp < 0) {
1.886 + if (trans->system.packages[s - spkgs] & TRANS_PACKAGE_PRESENT)
1.887 + razor_merger_add_package(merger, s);
1.888 + s++;
1.889 + } else if (cmp == 0) {
1.890 + if (trans->system.packages[s - spkgs] & TRANS_PACKAGE_PRESENT)
1.891 + razor_merger_add_package(merger, s);
1.892 + if (trans->upstream.packages[u - upkgs] & TRANS_PACKAGE_PRESENT)
1.893 + razor_merger_add_package(merger, u);
1.894 +
1.895 + s++;
1.896 + u++;
1.897 + } else {
1.898 + if (trans->upstream.packages[u - upkgs] & TRANS_PACKAGE_PRESENT)
1.899 + razor_merger_add_package(merger, u);
1.900 + u++;
1.901 + }
1.902 + }
1.903 +
1.904 + razor_transaction_destroy(trans);
1.905 +
1.906 + return razor_merger_finish(merger);
1.907 +}
1.908 +
1.909 +void
1.910 +razor_transaction_destroy(struct razor_transaction *trans)
1.911 +{
1.912 + transaction_set_release(&trans->system);
1.913 + transaction_set_release(&trans->upstream);
1.914 + free(trans);
1.915 +}