1.1 --- a/razor.c Fri Feb 29 15:09:44 2008 -0500
1.2 +++ b/razor.c Mon Mar 03 14:55:16 2008 -0500
1.3 @@ -1653,7 +1653,7 @@
1.4
1.5 static int
1.6 find_packages(struct razor_set *set, int count, const char **package_names,
1.7 - struct array *package_array,
1.8 + struct array *package_array, struct bitarray *pkgbits,
1.9 enum razor_transaction_package_state state)
1.10 {
1.11 struct razor_package_iterator *pi;
1.12 @@ -1676,6 +1676,8 @@
1.13 tp->name = name;
1.14 tp->version = version;
1.15 tp->state = state;
1.16 + bitarray_set(pkgbits, p - packages,
1.17 + state == RAZOR_PACKAGE_INSTALL);
1.18 break;
1.19 }
1.20 }
1.21 @@ -1698,20 +1700,21 @@
1.22 }
1.23
1.24 static void
1.25 -find_all_packages(struct razor_set *set,
1.26 - struct razor_set *upstream, struct array *package_array)
1.27 +find_all_packages(struct razor_set *set, struct razor_set *upstream,
1.28 + struct array *package_array, struct bitarray *pkgbits)
1.29 {
1.30 struct razor_transaction_package *tp;
1.31 - struct razor_package *p, *u, *pend, *uend;
1.32 + struct razor_package *p, *packages, *u, *pend, *uend;
1.33 char *pool, *upool;
1.34
1.35 + packages = set->packages.data;
1.36 pend = set->packages.data + set->packages.size;
1.37 pool = set->string_pool.data;
1.38 u = upstream->packages.data;
1.39 uend = upstream->packages.data + upstream->packages.size;
1.40 upool = upstream->string_pool.data;
1.41
1.42 - for (p = set->packages.data; p < pend; p++) {
1.43 + for (p = packages; p < pend; p++) {
1.44 while (u < uend && strcmp(&pool[p->name], &upool[u->name]) > 0)
1.45 u++;
1.46 if (strcmp(&pool[p->name], &upool[u->name]) == 0) {
1.47 @@ -1720,6 +1723,7 @@
1.48 tp->name = &upool[u->name];
1.49 tp->version = &upool[u->version];
1.50 tp->state = RAZOR_PACKAGE_INSTALL;
1.51 + bitarray_set(pkgbits, p - packages, 1);
1.52 }
1.53 }
1.54 }
1.55 @@ -1785,171 +1789,362 @@
1.56 }
1.57
1.58 static int
1.59 -find_property_provider(struct razor_set *set,
1.60 - struct razor_property *requirement,
1.61 - const char *requirement_strings)
1.62 +find_system_file(struct razor_transaction *trans,
1.63 + struct bitarray *syspkgs, int installed, int up)
1.64 {
1.65 - struct razor_property *props = set->properties.data;
1.66 - int p, hi, lo, cmp;
1.67 - char *pool = set->string_pool.data;
1.68 + struct razor_entry *entry;
1.69 + struct razor_property *uprops = trans->upstream->properties.data;
1.70 + const char *upool = trans->upstream->string_pool.data;
1.71 + const char *filename = &upool[uprops[up].name];
1.72 + struct list *p;
1.73
1.74 - lo = 0;
1.75 - hi = set->properties.size / sizeof *props;
1.76 - while (lo < hi) {
1.77 - p = (lo + hi) / 2;
1.78 - cmp = strcmp(&pool[props[p].name],
1.79 - &requirement_strings[requirement->name]);
1.80 - if (cmp < 0)
1.81 - lo = p + 1;
1.82 - else if (cmp > 0)
1.83 - hi = p;
1.84 - else
1.85 - break;
1.86 + if (filename[0] != '/')
1.87 + return 0;
1.88 +
1.89 + entry = find_entry(trans->system, trans->system->files.data, filename);
1.90 + if (!entry)
1.91 + return 0;
1.92 +
1.93 + for (p = list_first(&entry->packages, &trans->system->package_pool);
1.94 + p;
1.95 + p = list_next(p)) {
1.96 + if (bitarray_get(syspkgs, p->data) == installed)
1.97 + return 1;
1.98 }
1.99 - if (lo >= hi)
1.100 - return -1;
1.101 -
1.102 - /* Seek to the last (ie, highest version number) PROVIDES
1.103 - * entry for this name.
1.104 - */
1.105 - if (props[p].type < RAZOR_PROPERTY_PROVIDES) {
1.106 - while (p < hi &&
1.107 - props[p].type != RAZOR_PROPERTY_PROVIDES &&
1.108 - props[p + 1].name == props[p].name)
1.109 - p++;
1.110 - } else if (props[p].type > RAZOR_PROPERTY_PROVIDES) {
1.111 - while (p > lo &&
1.112 - props[p].type != RAZOR_PROPERTY_PROVIDES &&
1.113 - props[p - 1].name == props[p].name)
1.114 - p--;
1.115 - }
1.116 - while (p < hi &&
1.117 - props[p + 1].type == RAZOR_PROPERTY_PROVIDES &&
1.118 - props[p + 1].name == props[p].name)
1.119 - p++;
1.120 -
1.121 - if (props[p].type != RAZOR_PROPERTY_PROVIDES)
1.122 - return -1;
1.123 -
1.124 - do {
1.125 - if (provider_satisfies_requirement(&props[p], pool,
1.126 - requirement, requirement_strings))
1.127 - return list_first(&props[p].packages, &set->package_pool)->data;
1.128 -
1.129 - p--;
1.130 - } while (p > lo && props[p].name == props[p + 1].name &&
1.131 - props[p].type == RAZOR_PROPERTY_PROVIDES);
1.132 -
1.133 - return -1;
1.134 + return 0;
1.135 }
1.136
1.137 -static int
1.138 -find_file_provider(struct razor_set *set, const char *filename)
1.139 +static struct razor_package *
1.140 +find_system_provider(struct razor_transaction *trans, struct bitarray *syspkgs,
1.141 + int installed, int match_name,
1.142 + struct razor_property *req, int *sp)
1.143 {
1.144 - struct razor_entry *entry;
1.145 + struct razor_package *spkgs = trans->system->packages.data;
1.146 + struct razor_property *sprops = trans->system->properties.data;
1.147 + const char *spool = trans->system->string_pool.data;
1.148 + const char *upool = trans->upstream->string_pool.data;
1.149 + int scount = trans->system->properties.size / sizeof *sprops;
1.150
1.151 - entry = find_entry(set, set->files.data, filename);
1.152 - if (entry)
1.153 - return list_first(&entry->packages, &set->package_pool)->data;
1.154 - else
1.155 - return -1;
1.156 + /* Skip ahead to first matching PROVIDES */
1.157 + while (*sp < scount &&
1.158 + strcmp(&spool[sprops[*sp].name], &upool[req->name]) < 0)
1.159 + (*sp)++;
1.160 + while (*sp < scount &&
1.161 + sprops[*sp].type != RAZOR_PROPERTY_PROVIDES &&
1.162 + strcmp(&spool[sprops[*sp].name], &upool[req->name]) == 0)
1.163 + (*sp)++;
1.164 +
1.165 + /* Scan matching PROVIDES */
1.166 + while (*sp < scount &&
1.167 + sprops[*sp].type == RAZOR_PROPERTY_PROVIDES &&
1.168 + strcmp(&spool[sprops[*sp].name],
1.169 + &upool[req->name]) == 0) {
1.170 + if (provider_satisfies_requirement(&sprops[*sp], spool,
1.171 + req, upool)) {
1.172 + struct list *pkg;
1.173 +
1.174 + for (pkg = list_first(&sprops[*sp].packages, &trans->system->package_pool); pkg; pkg = list_next(pkg)) {
1.175 + if (bitarray_get(syspkgs, pkg->data) != installed)
1.176 + continue;
1.177 + if (!match_name ||
1.178 + strcmp(&spool[spkgs[pkg->data].name],
1.179 + &upool[req->name]) == 0)
1.180 + return &spkgs[pkg->data];
1.181 + }
1.182 + }
1.183 + (*sp)++;
1.184 + }
1.185 +
1.186 + return NULL;
1.187 }
1.188
1.189 -static int
1.190 -find_provider(struct razor_set *set, struct razor_property *requirement,
1.191 - const char *requirement_strings)
1.192 +static struct razor_package *
1.193 +find_upstream_provider(struct razor_transaction *trans,
1.194 + struct bitarray *uppkgs,
1.195 + int installed, int match_name,
1.196 + struct razor_property *req, int up)
1.197 {
1.198 - const char *name = &requirement_strings[requirement->name];
1.199 - if (*name == '/')
1.200 - return find_file_provider(set, name);
1.201 + struct razor_package *upkgs = trans->upstream->packages.data;
1.202 + struct razor_property *uprops = trans->upstream->properties.data;
1.203 + const char *upool = trans->upstream->string_pool.data;
1.204 + int ucount = trans->upstream->properties.size / sizeof *uprops;
1.205 +
1.206 + /* Skip to first matching provide */
1.207 + if (req->type < RAZOR_PROPERTY_PROVIDES) {
1.208 + while (up < ucount &&
1.209 + uprops[up].type != RAZOR_PROPERTY_PROVIDES)
1.210 + up++;
1.211 + } else {
1.212 + while (up >= 0 &&
1.213 + uprops[up].type != RAZOR_PROPERTY_PROVIDES)
1.214 + up--;
1.215 + while (up > 0 &&
1.216 + uprops[up - 1].type == RAZOR_PROPERTY_PROVIDES)
1.217 + up--;
1.218 + if (up < 0)
1.219 + return NULL;
1.220 + }
1.221 +
1.222 + /* Scan matching PROVIDES */
1.223 + while (up < ucount &&
1.224 + uprops[up].type == RAZOR_PROPERTY_PROVIDES &&
1.225 + uprops[up].name == req->name) {
1.226 + if (provider_satisfies_requirement(&uprops[up], upool,
1.227 + req, upool)) {
1.228 + struct list *pkg;
1.229 +
1.230 + for (pkg = list_first(&uprops[up].packages, &trans->upstream->package_pool); pkg; pkg = list_next(pkg)) {
1.231 + if (bitarray_get(uppkgs, pkg->data) != installed)
1.232 + continue;
1.233 + if (!match_name ||
1.234 + strcmp(&upool[upkgs[pkg->data].name],
1.235 + &upool[req->name]) == 0)
1.236 + return &upkgs[pkg->data];
1.237 + }
1.238 + }
1.239 + up++;
1.240 + }
1.241 + return NULL;
1.242 +}
1.243 +
1.244 +static struct razor_package *
1.245 +find_upgrade(struct razor_transaction *trans,
1.246 + struct bitarray *uppkgs, struct razor_property *obsolete,
1.247 + int up)
1.248 +{
1.249 + struct razor_property *uprops = trans->upstream->properties.data;
1.250 + const char *upool = trans->upstream->string_pool.data;
1.251 + struct razor_property req;
1.252 +
1.253 + if (uprops[up].relation > RAZOR_VERSION_EQUAL ||
1.254 + !upool[uprops[up].version])
1.255 + return NULL;
1.256 +
1.257 + memcpy(&req, obsolete, sizeof req);
1.258 + req.type = RAZOR_PROPERTY_REQUIRES;
1.259 + if (uprops[up].relation == RAZOR_VERSION_LESS)
1.260 + req.relation = RAZOR_VERSION_GREATER_OR_EQUAL;
1.261 else
1.262 - return find_property_provider(set, requirement, requirement_strings);
1.263 + req.relation = RAZOR_VERSION_GREATER;
1.264 +
1.265 + /* We need to rewind up, since OBSOLETES > PROVIDES, so we've
1.266 + * already gone past the possible upgrades.
1.267 + */
1.268 + while (up >= 0 &&
1.269 + uprops[up].type != RAZOR_PROPERTY_PROVIDES)
1.270 + up--;
1.271 + while (up > 0 &&
1.272 + uprops[up - 1].type == RAZOR_PROPERTY_PROVIDES)
1.273 + up--;
1.274 + if (up < 0)
1.275 + return NULL;
1.276 +
1.277 + return find_upstream_provider(trans, uppkgs, 0, 1, &req, up);
1.278 +}
1.279 +
1.280 +static struct razor_package *
1.281 +find_upstream_file(struct razor_transaction *trans,
1.282 + struct bitarray *uppkgs, int installed,
1.283 + int up)
1.284 +{
1.285 + struct razor_package *upkgs = trans->upstream->packages.data;
1.286 + struct razor_property *uprops = trans->upstream->properties.data;
1.287 + const char *upool = trans->upstream->string_pool.data;
1.288 + const char *filename = &upool[uprops[up].name];
1.289 + struct razor_entry *entry;
1.290 + struct list *pkg;
1.291 +
1.292 + if (filename[0] != '/')
1.293 + return NULL;
1.294 +
1.295 + entry = find_entry(trans->upstream, trans->upstream->files.data, filename);
1.296 + if (!entry)
1.297 + return NULL;
1.298 +
1.299 + for (pkg = list_first(&entry->packages, &trans->upstream->package_pool); pkg; pkg = list_next(pkg)) {
1.300 + if (bitarray_get(uppkgs, pkg->data) == installed)
1.301 + return &upkgs[pkg->data];
1.302 + }
1.303 + return NULL;
1.304 }
1.305
1.306 static void
1.307 -gather_new_requires(struct razor_set *system, struct razor_set *upstream,
1.308 - struct razor_package *pkg, struct array *new_requires)
1.309 +add_transaction_package(struct razor_transaction *trans,
1.310 + struct bitarray *syspkgs,
1.311 + struct bitarray *uppkgs,
1.312 + struct array *package_array,
1.313 + struct razor_package *package,
1.314 + struct razor_set *package_set,
1.315 + enum razor_transaction_package_state state,
1.316 + struct razor_property *req_prop,
1.317 + struct razor_set *req_set)
1.318 {
1.319 - struct razor_property *uprops = upstream->properties.data, *prop;
1.320 - char *upool = upstream->string_pool.data;
1.321 - struct list *p;
1.322 - uint32_t *new;
1.323 + struct razor_transaction_package *tp;
1.324 + const char *pool;
1.325 + struct razor_package *pkgs;
1.326 + struct list *pkg;
1.327
1.328 - for (p = list_first(&pkg->properties, &upstream->property_pool); p; p = list_next(p)) {
1.329 - prop = &uprops[p->data];
1.330 - if (prop->type != RAZOR_PROPERTY_REQUIRES)
1.331 - continue;
1.332 - if (!strncmp(&upool[prop->name], "rpmlib(", 7))
1.333 - continue;
1.334 + tp = array_add(package_array, sizeof *tp);
1.335 + memset(tp, 0, sizeof *tp);
1.336
1.337 - if (find_provider(system, prop, upool) == -1) {
1.338 - new = array_add(new_requires, sizeof *new);
1.339 - *new = p->data;
1.340 - }
1.341 + if (package) {
1.342 + tp->package = package;
1.343 + pool = package_set->string_pool.data;
1.344 + tp->name = &pool[package->name];
1.345 + tp->version = &pool[package->version];
1.346 + tp->state = state;
1.347 + } else
1.348 + tp->state = state | RAZOR_PACKAGE_UNSATISFIABLE;
1.349 +
1.350 + for (pkg = list_first(&req_prop->packages, &req_set->package_pool); pkg; pkg = list_next(pkg)) {
1.351 + if (bitarray_get(uppkgs, pkg->data))
1.352 + break;
1.353 }
1.354 + if (pkg) {
1.355 + pool = req_set->string_pool.data;
1.356 + pkgs = req_set->packages.data;
1.357 + tp->req_package = &pool[pkgs[pkg->data].name];
1.358 + }
1.359 + tp->req_type = req_prop->type;
1.360 + tp->req_property = &pool[req_prop->name];
1.361 + tp->req_relation = req_prop->relation;
1.362 + tp->req_version = &pool[req_prop->version];
1.363 +
1.364 + pkgs = package_set->packages.data;
1.365 + if (tp->state == RAZOR_PACKAGE_INSTALL)
1.366 + bitarray_set(uppkgs, package - pkgs, 1);
1.367 + else if (tp->state == RAZOR_PACKAGE_REMOVE)
1.368 + bitarray_set(uppkgs, package - pkgs, 0);
1.369 + else
1.370 + trans->errors++;
1.371 +}
1.372 +
1.373 +/* FIXME */
1.374 +static int
1.375 +prop_belongs_to_uppkgs(struct razor_set *set,
1.376 + struct razor_property *prop,
1.377 + struct bitarray *uppkgs)
1.378 +{
1.379 + struct list *pkg;
1.380 +
1.381 + for (pkg = list_first(&prop->packages, &set->package_pool); pkg; pkg = list_next(pkg)) {
1.382 + if (bitarray_get(uppkgs, pkg->data))
1.383 + return 1;
1.384 + }
1.385 + return 0;
1.386 }
1.387
1.388 static void
1.389 razor_transaction_satisfy_installs(struct razor_transaction *trans,
1.390 - struct array *package_array,
1.391 - int start, int end)
1.392 + struct bitarray *syspkgs,
1.393 + struct bitarray *uppkgs,
1.394 + struct array *package_array)
1.395 {
1.396 - struct razor_package *pkgs;
1.397 - struct razor_transaction_package *packages, *tp;
1.398 - int p, provider, already;
1.399 - uint32_t *new, *new_end;
1.400 - struct razor_property *props, *prop_end;
1.401 - struct array new_requires;
1.402 - char *pool;
1.403 + struct razor_package *spkgs, *upkgs, *pkg;
1.404 + struct razor_property *sprops, *uprops;
1.405 + int sp, up, ucount;
1.406 + const char *upool;
1.407
1.408 - pkgs = trans->upstream->packages.data;
1.409 - props = trans->upstream->properties.data;
1.410 - prop_end = trans->upstream->properties.data + trans->upstream->properties.size;
1.411 - pool = trans->upstream->string_pool.data;
1.412 + spkgs = trans->system->packages.data;
1.413 + sprops = trans->system->properties.data;
1.414 + upkgs = trans->upstream->packages.data;
1.415 + uprops = trans->upstream->properties.data;
1.416 + ucount = trans->upstream->properties.size / sizeof *uprops;
1.417 + upool = trans->upstream->string_pool.data;
1.418
1.419 - packages = package_array->data;
1.420 - for (p = start; p < end; p++) {
1.421 - if (packages[p].state != RAZOR_PACKAGE_INSTALL)
1.422 - continue;
1.423 + sp = up = 0;
1.424 + while (up < ucount) {
1.425 + /* Skip 'up' ahead to a property of a package which is
1.426 + * to-be-installed.
1.427 + */
1.428 + while (up < ucount &&
1.429 + (uprops[up].type == RAZOR_PROPERTY_PROVIDES ||
1.430 + !prop_belongs_to_uppkgs(trans->upstream, &uprops[up], uppkgs)))
1.431 + up++;
1.432 + if (up == ucount)
1.433 + break;
1.434
1.435 - array_init(&new_requires);
1.436 - gather_new_requires(trans->system, trans->upstream,
1.437 - packages[p].package, &new_requires);
1.438 + switch (uprops[up].type) {
1.439 + case RAZOR_PROPERTY_REQUIRES:
1.440 + if (!strncmp(&upool[uprops[up].name], "rpmlib(", 7))
1.441 + break;
1.442
1.443 - new_end = new_requires.data + new_requires.size;
1.444 - for (new = new_requires.data; new < new_end; new++) {
1.445 - provider = find_provider(trans->upstream,
1.446 - &props[*new], pool);
1.447 - already = find_transaction_package(package_array,
1.448 - &pkgs[provider]);
1.449 - if (already != -1 &&
1.450 - (packages[already].state & RAZOR_PACKAGE_INSTALL))
1.451 - continue;
1.452 -
1.453 - tp = array_add(package_array, sizeof *tp);
1.454 - memset(tp, 0, sizeof *tp);
1.455 - tp->req_package = packages[p].name;
1.456 - tp->req_property = &pool[props[*new].name];
1.457 - tp->req_relation = props[*new].relation;
1.458 - tp->req_version = &pool[props[*new].version];
1.459 -
1.460 - if (provider != -1) {
1.461 - tp->package = &pkgs[provider];
1.462 - tp->name = &pool[tp->package->name];
1.463 - tp->version = &pool[tp->package->version];
1.464 - if (already != -1) {
1.465 - tp->state = RAZOR_PACKAGE_INSTALL_BLOCKED;
1.466 - trans->errors++;
1.467 - } else
1.468 - tp->state = RAZOR_PACKAGE_INSTALL;
1.469 - } else {
1.470 - tp->state = RAZOR_PACKAGE_INSTALL_UNSATISFIABLE;
1.471 - trans->errors++;
1.472 + if (find_system_provider(trans, syspkgs, 1, 0, &uprops[up], &sp) ||
1.473 + find_upstream_provider(trans, uppkgs, 1, 0, &uprops[up], up) ||
1.474 + find_system_file(trans, syspkgs, 1, up) ||
1.475 + find_upstream_file(trans, uppkgs, 1, up)) {
1.476 + /* Requires something that is either installed
1.477 + * or to-be-installed.
1.478 + */
1.479 + break;
1.480 }
1.481
1.482 - packages = package_array->data;
1.483 + /* See if we can install a new upstream provider */
1.484 + pkg = find_upstream_provider(trans, uppkgs, 0, 0, &uprops[up], up);
1.485 + if (!pkg)
1.486 + pkg = find_upstream_file(trans, uppkgs, 0, up);
1.487 + add_transaction_package(trans, syspkgs, uppkgs,
1.488 + package_array,
1.489 + pkg, trans->upstream,
1.490 + RAZOR_PACKAGE_INSTALL,
1.491 + &uprops[up], trans->upstream);
1.492 + break;
1.493 +
1.494 + case RAZOR_PROPERTY_CONFLICTS:
1.495 + if ((pkg = find_system_provider(trans, syspkgs, 1, 1, &uprops[up], &sp))) {
1.496 + struct razor_package *upgrade;
1.497 +
1.498 + /* Conflicts with something already installed.
1.499 + * Try to upgrade out.
1.500 + */
1.501 + upgrade = find_upgrade(trans, uppkgs, &uprops[up], up);
1.502 + if (upgrade) {
1.503 + bitarray_set(syspkgs, pkg - spkgs, 0);
1.504 + add_transaction_package(trans, syspkgs, uppkgs,
1.505 + package_array,
1.506 + upgrade, trans->upstream,
1.507 + RAZOR_PACKAGE_INSTALL,
1.508 + &uprops[up], trans->upstream);
1.509 + } else {
1.510 + add_transaction_package(trans, syspkgs, uppkgs,
1.511 + package_array,
1.512 + pkg, trans->system,
1.513 + RAZOR_PACKAGE_INSTALL_CONFLICT,
1.514 + &uprops[up], trans->upstream);
1.515 + }
1.516 + } else if ((pkg = find_upstream_provider(trans, uppkgs, 1, 1, &uprops[up], up))) {
1.517 + /* Conflicts with something already to-be-installed */
1.518 + add_transaction_package(trans, syspkgs, uppkgs,
1.519 + package_array,
1.520 + pkg, trans->upstream,
1.521 + RAZOR_PACKAGE_INSTALL_CONFLICT,
1.522 + &uprops[up], trans->upstream);
1.523 + }
1.524 + break;
1.525 +
1.526 + case RAZOR_PROPERTY_OBSOLETES:
1.527 + if ((pkg = find_system_provider(trans, syspkgs, 1, 1, &uprops[up], &sp))) {
1.528 + /* Obsoletes something installed */
1.529 + add_transaction_package(trans, syspkgs, uppkgs,
1.530 + package_array,
1.531 + pkg, trans->system,
1.532 + RAZOR_PACKAGE_REMOVE,
1.533 + &uprops[up], trans->upstream);
1.534 + } else if ((pkg = find_upstream_provider(trans, uppkgs, 1, 1, &uprops[up], up))) {
1.535 + /* Obsoletes something that was to-be-installed */
1.536 + add_transaction_package(trans, syspkgs, uppkgs,
1.537 + package_array,
1.538 + pkg, trans->upstream,
1.539 + RAZOR_PACKAGE_REMOVE_CONFLICT,
1.540 + &uprops[up], trans->upstream);
1.541 + }
1.542 + break;
1.543 +
1.544 + default:
1.545 + /* can't happen */
1.546 + break;
1.547 }
1.548 - array_release(&new_requires);
1.549 + up++;
1.550 }
1.551 }
1.552
1.553 @@ -1995,7 +2190,7 @@
1.554 }
1.555
1.556 static void
1.557 -lose_required_package(struct razor_transaction *trans,
1.558 +lose_required_package(struct razor_transaction *trans, struct bitarray *syspkgs,
1.559 struct array *package_array,
1.560 struct razor_property *req,
1.561 struct list_head *lost_package_list)
1.562 @@ -2022,19 +2217,23 @@
1.563 tp->name = &pool[tp->package->name];
1.564 tp->version = &pool[tp->package->version];
1.565 tp->req_package = &pool[lost_package->name];
1.566 + tp->req_type = req->type;
1.567 tp->req_property = &pool[req->name];
1.568 tp->req_relation = req->relation;
1.569 tp->req_version = &pool[req->version];
1.570 if (already != -1) {
1.571 tp->state = RAZOR_PACKAGE_REMOVE_BLOCKED;
1.572 trans->errors++;
1.573 - } else
1.574 + } else {
1.575 tp->state = RAZOR_PACKAGE_REMOVE;
1.576 + bitarray_set(syspkgs, p->data, 0);
1.577 + }
1.578 }
1.579 }
1.580
1.581 static void
1.582 -lose_requirement(struct razor_transaction *trans, struct array *package_array,
1.583 +lose_requirement(struct razor_transaction *trans, struct bitarray *syspkgs,
1.584 + struct array *package_array,
1.585 struct razor_property *req,
1.586 struct razor_property *lost_provider,
1.587 struct razor_property *first_provider)
1.588 @@ -2055,12 +2254,13 @@
1.589 return;
1.590 }
1.591
1.592 - lose_required_package(trans, package_array, req,
1.593 + lose_required_package(trans, syspkgs, package_array, req,
1.594 &lost_provider->packages);
1.595 }
1.596
1.597 static void
1.598 razor_transaction_satisfy_removes(struct razor_transaction *trans,
1.599 + struct bitarray *syspkgs,
1.600 struct array *package_array,
1.601 int start, int end)
1.602 {
1.603 @@ -2101,7 +2301,7 @@
1.604 first_provider = req + 1;
1.605
1.606 while (req > props && req->name == props[*lost].name) {
1.607 - lose_requirement(trans, package_array, req,
1.608 + lose_requirement(trans, syspkgs, package_array, req,
1.609 &props[*lost], first_provider);
1.610 req--;
1.611 }
1.612 @@ -2113,7 +2313,7 @@
1.613
1.614 req = props;
1.615 /* Due to the sorting of props, this loop is likely a no-op */
1.616 - while (pool[req->name] != '/')
1.617 + while (req < prop_end && pool[req->name] != '/')
1.618 req++;
1.619
1.620 for (; req < prop_end && pool[req->name] == '/'; req++) {
1.621 @@ -2132,7 +2332,7 @@
1.622 if (lostf == lostf_end)
1.623 continue;
1.624
1.625 - lose_required_package(trans, package_array, req,
1.626 + lose_required_package(trans, syspkgs, package_array, req,
1.627 &(entry)->packages);
1.628 }
1.629 array_release(&lost_files);
1.630 @@ -2190,43 +2390,52 @@
1.631 int remove_count, const char **remove_packages)
1.632 {
1.633 struct razor_transaction *trans;
1.634 - struct array packages;
1.635 + struct array package_array;
1.636 + struct razor_package *spkgs, *upkgs;
1.637 + struct bitarray syspkgs, uppkgs;
1.638 int start, end;
1.639
1.640 trans = zalloc(sizeof *trans);
1.641 trans->system = system;
1.642 + spkgs = trans->system->packages.data;
1.643 trans->upstream = upstream ? upstream : razor_set_create();
1.644 - array_init(&packages);
1.645 + upkgs = trans->upstream->packages.data;
1.646 + array_init(&package_array);
1.647 + bitarray_init(&syspkgs, trans->system->packages.size / sizeof (struct razor_package), 1);
1.648 + bitarray_init(&uppkgs, trans->upstream->packages.size / sizeof (struct razor_package), 0);
1.649
1.650 /* Find initial upstream packages to be installed */
1.651 if (update_count > 0) {
1.652 trans->errors +=
1.653 find_packages(upstream, update_count, update_packages,
1.654 - &packages, RAZOR_PACKAGE_INSTALL);
1.655 + &package_array, &uppkgs,
1.656 + RAZOR_PACKAGE_INSTALL);
1.657 } else if (remove_count == 0)
1.658 - find_all_packages(system, upstream, &packages);
1.659 + find_all_packages(system, upstream, &package_array, &uppkgs);
1.660
1.661 /* Find initial installed packages to remove. */
1.662 if (remove_count > 0) {
1.663 trans->errors +=
1.664 find_packages(system, remove_count, remove_packages,
1.665 - &packages, RAZOR_PACKAGE_REMOVE);
1.666 + &package_array, &syspkgs,
1.667 + RAZOR_PACKAGE_REMOVE);
1.668 }
1.669
1.670 start = 0;
1.671 - end = packages.size / sizeof (struct razor_transaction_package);
1.672 + end = package_array.size / sizeof (struct razor_transaction_package);
1.673
1.674 while (!trans->errors && start != end) {
1.675 - if (upstream)
1.676 - razor_transaction_satisfy_installs(trans, &packages, start, end);
1.677 - razor_transaction_satisfy_removes(trans, &packages, start, end);
1.678 + razor_transaction_satisfy_installs(trans, &syspkgs, &uppkgs,
1.679 + &package_array);
1.680 + razor_transaction_satisfy_removes(trans, &syspkgs,
1.681 + &package_array, start, end);
1.682
1.683 start = end;
1.684 - end = packages.size / sizeof (struct razor_transaction_package);
1.685 + end = package_array.size / sizeof (struct razor_transaction_package);
1.686 }
1.687
1.688 - trans->packages = packages.data;
1.689 - trans->package_count = packages.size / sizeof (struct razor_transaction_package);
1.690 + trans->packages = package_array.data;
1.691 + trans->package_count = end;
1.692 return trans;
1.693 }
1.694
1.695 @@ -2235,6 +2444,16 @@
1.696 "<", "<=", "=", ">=", ">"
1.697 };
1.698
1.699 +const char * const razor_property_types[] = {
1.700 + /* same order as enum razor_property_type */
1.701 + "requires", "provides", "conflicts with", "obsoletes"
1.702 +};
1.703 +
1.704 +const char * const razor_property_types_removal[] = {
1.705 + /* same order as enum razor_property_type */
1.706 + "required", "provided", "conflicted with", "was obsoleted by"
1.707 +};
1.708 +
1.709 void
1.710 razor_transaction_describe(struct razor_transaction *trans)
1.711 {
1.712 @@ -2252,13 +2471,16 @@
1.713 printf ("Installing %s %s", p->name, p->version);
1.714 if (p->req_package) {
1.715 printf (" for %s", p->req_package);
1.716 + print_requirement:
1.717 if (*p->req_version) {
1.718 - printf (", which requires %s %s %s",
1.719 + printf (", which %s %s %s %s",
1.720 + razor_property_types[p->req_type],
1.721 p->req_property,
1.722 razor_version_relations[p->req_relation],
1.723 p->req_version);
1.724 } else if (strcmp(p->req_property, p->name) != 0) {
1.725 - printf (", which requires %s",
1.726 + printf (", which %s %s",
1.727 + razor_property_types[p->req_type],
1.728 p->req_property);
1.729 }
1.730 }
1.731 @@ -2288,10 +2510,10 @@
1.732 errors_only = 1;
1.733 break;
1.734
1.735 - case RAZOR_PACKAGE_INSTALL_BLOCKED:
1.736 - printf ("Cannot install %s, which is already marked for removal but is required by %s\n", p->name, p->req_package);
1.737 + case RAZOR_PACKAGE_INSTALL_CONFLICT:
1.738 + printf ("Cannot install %s", p->req_package);
1.739 errors_only = 1;
1.740 - break;
1.741 + goto print_requirement;
1.742
1.743 case RAZOR_PACKAGE_INSTALL_UNSATISFIABLE:
1.744 printf ("Cannot find package for %s", p->req_property);
1.745 @@ -2310,8 +2532,10 @@
1.746 break;
1.747 printf ("Removing %s %s", p->name, p->version);
1.748 if (p->req_package) {
1.749 - printf (" which required %s", p->req_package);
1.750 - if (strcmp(p->req_property, p->req_package) != 0)
1.751 + printf (" which %s %s",
1.752 + razor_property_types_removal[p->req_type],
1.753 + p->req_package);
1.754 + if (strcmp(p->req_property, p->name) != 0)
1.755 printf (" for %s", p->req_property);
1.756 }
1.757 printf("\n");
1.758 @@ -2327,6 +2551,11 @@
1.759 errors_only = 1;
1.760 break;
1.761
1.762 + case RAZOR_PACKAGE_REMOVE_CONFLICT:
1.763 + printf ("Cannot remove %s, which is marked for installation but is obsoleted by %s\n", p->name, p->req_package);
1.764 + errors_only = 1;
1.765 + break;
1.766 +
1.767 default:
1.768 /* Shouldn't actually happen */
1.769 break;