From: Dan Winship Date: Fri, 7 Mar 2008 13:52:09 +0000 (-0500) Subject: another checkpoint... X-Git-Tag: 0.1~207 X-Git-Url: http://project.juiblex.co.uk/git/?a=commitdiff_plain;h=7b04f14809aa59e9a2dfdf193396a2275a510380;p=razor.git another checkpoint... there are a bunch of problems with doing things this way, and file provide removals are currently unhandled --- diff --git a/razor.c b/razor.c index e26c5d0..d02537b 100644 --- a/razor.c +++ b/razor.c @@ -1965,24 +1965,53 @@ find_uninstalled_package_for_file(struct razor_transaction_resolver *trans, return pkg; } +static struct razor_property * +skip_to_matching_property(struct razor_transaction_resolver *trans, + struct razor_property *match, + struct razor_property *prop) +{ + struct razor_set *mset, *pset; + const char *ppool, *mpool; + struct razor_property *prop_end; + + if (property_in_set(match, trans->system)) + mset = trans->system; + else + mset = trans->upstream; + + if (property_in_set(prop, trans->system)) + pset = trans->system; + else if (property_in_set(prop, trans->upstream)) + pset = trans->upstream; + else + return prop; + + prop_end = pset->properties.data + pset->properties.size; + ppool = pset->string_pool.data; + mpool = mset->string_pool.data; + + while (prop < prop_end && + strcmp(&ppool[prop->name], &mpool[match->name]) < 0) + prop++; + return prop; +} + static struct razor_package * find_package_matching(struct razor_transaction_resolver *trans, int installed, - struct razor_property **start_prop, + struct razor_property *prop, struct razor_property *req, struct razor_set *req_set) { struct razor_set *set; struct bitarray *pkgbits; struct razor_package *pkgs; - struct razor_property *prop, *props, *prop_end; + struct razor_property *props, *prop_end; enum razor_property_type match_type; const char *pool; - const char *rpool = req_set->string_pool.data; - int match_name = (req->type == RAZOR_PROPERTY_OBSOLETES || - req->type == RAZOR_PROPERTY_CONFLICTS); + const char *rpool; + int match_name = (req->type == RAZOR_PROPERTY_OBSOLETES); int match; - prop = *start_prop; if (property_in_set(prop, trans->system)) { set = trans->system; pkgbits = &trans->syspkgs; @@ -1992,6 +2021,14 @@ find_package_matching(struct razor_transaction_resolver *trans, int installed, } else return NULL; + if (!req_set) { + if (property_in_set(req, trans->system)) + req_set = trans->system; + else + req_set = trans->upstream; + } + rpool = req_set->string_pool.data; + if (req->type == RAZOR_PROPERTY_PROVIDES) match_type = RAZOR_PROPERTY_CONFLICTS; else @@ -2006,7 +2043,6 @@ find_package_matching(struct razor_transaction_resolver *trans, int installed, while (prop < prop_end && strcmp(&pool[prop->name], &rpool[req->name]) < 0) prop++; - *start_prop = prop; if (prop == prop_end || strcmp(&pool[prop->name], &rpool[req->name]) > 0) return NULL; @@ -2048,27 +2084,29 @@ find_package_matching(struct razor_transaction_resolver *trans, int installed, static struct razor_package * find_installed_package_for_property(struct razor_transaction_resolver *trans, - struct razor_property **sys_sp, + struct razor_property *sys_start, + struct razor_property *up_start, struct razor_property *req) { struct razor_package *pkg; - pkg = find_package_matching(trans, 1, sys_sp, req, trans->upstream); + pkg = find_package_matching(trans, 1, sys_start, req, NULL); if (!pkg) - pkg = find_package_matching(trans, 1, &req, req, trans->upstream); + pkg = find_package_matching(trans, 1, up_start, req, NULL); return pkg; } static struct razor_package * find_uninstalled_package_for_property(struct razor_transaction_resolver *trans, - struct razor_property **sys_sp, + struct razor_property *sys_start, + struct razor_property *up_start, struct razor_property *req) { struct razor_package *pkg; - pkg = find_package_matching(trans, 0, sys_sp, req, trans->upstream); + pkg = find_package_matching(trans, 0, up_start, req, NULL); if (!pkg) - pkg = find_package_matching(trans, 0, &req, req, trans->upstream); + pkg = find_package_matching(trans, 0, sys_start, req, NULL); return pkg; } @@ -2100,7 +2138,7 @@ find_upgrade(struct razor_transaction_resolver *trans, else req.relation = RAZOR_VERSION_GREATER; - return find_package_matching(trans, 0, &up, &req, set); + return find_package_matching(trans, 0, up, &req, set); } /* FIXME */ @@ -2256,7 +2294,9 @@ add_transaction_package(struct razor_transaction_resolver *trans, tp->state = state; if (state != RAZOR_PACKAGE_INSTALL && - state != RAZOR_PACKAGE_REMOVE) + state != RAZOR_PACKAGE_FORCED_UPDATE && + state != RAZOR_PACKAGE_REMOVE && + state != RAZOR_PACKAGE_OBSOLETED) trans->errors++; if (contradiction) { @@ -2291,26 +2331,6 @@ add_transaction_package(struct razor_transaction_resolver *trans, } /* FIXME: make this more efficient */ -static void -maybe_mark_upgraded(struct razor_transaction_resolver *trans, - struct razor_package *pkg) -{ - struct razor_package *spkgs, *sp, *send; - const char *spool, *upool; - - sp = spkgs = trans->system->packages.data; - send = trans->system->packages.data + trans->system->packages.size; - spool = trans->system->string_pool.data; - upool = trans->upstream->string_pool.data; - - while (sp < send && - strcmp(&spool[sp->name], &upool[pkg->name]) < 0) - sp++; - if (sp < send && strcmp(&spool[sp->name], &upool[pkg->name]) == 0) - bitarray_set(&trans->syspkgs, sp - spkgs, 0); -} - -/* FIXME: this too */ static struct razor_package * find_old_version(struct razor_transaction_resolver *trans, struct razor_package *pkg) @@ -2362,13 +2382,14 @@ razor_transaction_satisfy_installs(struct razor_transaction_resolver *trans) up++; if (up == uprop_end) break; + sp = skip_to_matching_property(trans, up, sp); switch (up->type) { case RAZOR_PROPERTY_REQUIRES: if (!strncmp(&upool[up->name], "rpmlib(", 7)) break; - if (find_installed_package_for_property(trans, &sp, up) || + if (find_installed_package_for_property(trans, sp, up, up) || find_installed_package_for_file(trans, &upool[up->name])) { /* Requires something that is either installed * or to-be-installed. @@ -2377,14 +2398,9 @@ razor_transaction_satisfy_installs(struct razor_transaction_resolver *trans) } /* See if we can install a new upstream provider */ - pkg = find_uninstalled_package_for_property(trans, &sp, up); - if (!pkg) { + pkg = find_uninstalled_package_for_property(trans, sp, up, up); + if (!pkg) pkg = find_uninstalled_package_for_file(trans, &upool[up->name]); - if (pkg) { - /* FIXME: find a way to do this more efficiently */ - maybe_mark_upgraded(trans, pkg); - } - } add_transaction_package(trans, pkg, find_old_version(trans, pkg), RAZOR_PACKAGE_INSTALL, NULL, up); @@ -2394,7 +2410,7 @@ razor_transaction_satisfy_installs(struct razor_transaction_resolver *trans) /* find_installed_package_for_property works backwards * here, finding a *conflicting* installed package. */ - pkg = find_installed_package_for_property(trans, &sp, up); + pkg = find_installed_package_for_property(trans, sp, up, up); if (!pkg) break; @@ -2404,7 +2420,6 @@ razor_transaction_satisfy_installs(struct razor_transaction_resolver *trans) */ upgrade = find_upgrade_for_installed_conflict(trans, pkg, up); if (upgrade) { - bitarray_set(&trans->syspkgs, pkg - spkgs, 0); add_transaction_package(trans, upgrade, pkg, RAZOR_PACKAGE_INSTALL, &spool[pkg->name], sp); @@ -2418,7 +2433,7 @@ razor_transaction_satisfy_installs(struct razor_transaction_resolver *trans) break; case RAZOR_PROPERTY_CONFLICTS: - pkg = find_installed_package_for_property(trans, &sp, up); + pkg = find_installed_package_for_property(trans, sp, up, up); if (!pkg) break; @@ -2428,7 +2443,6 @@ razor_transaction_satisfy_installs(struct razor_transaction_resolver *trans) */ upgrade = find_upgrade(trans, sp, up); if (upgrade) { - bitarray_set(&trans->syspkgs, pkg - spkgs, 0); add_transaction_package(trans, upgrade, pkg, RAZOR_PACKAGE_INSTALL, NULL, up); @@ -2442,13 +2456,13 @@ razor_transaction_satisfy_installs(struct razor_transaction_resolver *trans) break; case RAZOR_PROPERTY_OBSOLETES: - pkg = find_installed_package_for_property(trans, &sp, up); + pkg = find_installed_package_for_property(trans, sp, up, up); if (pkg) { /* If pkg is to-be-installed, this * will add a CONTRADICTION error as well. */ add_transaction_package(trans, NULL, pkg, - RAZOR_PACKAGE_REMOVE, + RAZOR_PACKAGE_OBSOLETED, NULL, up); } break; @@ -2461,6 +2475,7 @@ razor_transaction_satisfy_installs(struct razor_transaction_resolver *trans) } } +#if 0 /* Look through pkg's PROVIDES, and for each one that no other package * provides, add its property index to lost_provides. */ @@ -2571,7 +2586,9 @@ razor_transaction_satisfy_removes(struct razor_transaction_resolver *trans, for (r = start; r < end; r++) { if (!packages[r].old_package || (packages[r].state != RAZOR_PACKAGE_REMOVE && - packages[r].state != RAZOR_PACKAGE_INSTALL)) + packages[r].state != RAZOR_PACKAGE_INSTALL && + packages[r].state != RAZOR_PACKAGE_FORCED_UPDATE && + packages[r].state != RAZOR_PACKAGE_OBSOLETED) continue; gather_lost_provides(trans->system, packages[r].old_package, @@ -2624,6 +2641,196 @@ razor_transaction_satisfy_removes(struct razor_transaction_resolver *trans, } array_release(&lost_files); } +#endif + +static struct razor_package * +find_upgrade_for_lost_requirement(struct razor_transaction_resolver *trans, + struct razor_package *pkg, + struct razor_property *req) +{ + struct razor_package *upkgs, *up, *uend; + struct razor_property *uprops; + const char *spool, *upool; + struct list *prop; + + up = upkgs = trans->upstream->packages.data; + uend = trans->upstream->packages.data + trans->upstream->packages.size; + upool = trans->upstream->string_pool.data; + uprops = trans->upstream->properties.data; + spool = trans->system->string_pool.data; + + while (up < uend && + strcmp(&upool[up->name], &spool[pkg->name]) < 0) + up++; + if (up == uend || strcmp(&upool[up->name], &spool[pkg->name]) != 0) + return NULL; + + for (prop = list_first(&up->properties, &trans->system->property_pool); prop; prop = list_next(prop)) { + if (uprops[prop->data].type == RAZOR_PROPERTY_REQUIRES && + strcmp(&upool[uprops[prop->data].name], &spool[req->name]) == 0 && + uprops[prop->data].relation == req->relation && + strcmp(&upool[uprops[prop->data].version], &spool[req->version]) == 0) + return NULL; + } + return up; +} + +static int +prop_is_being_removed(struct razor_transaction_resolver *trans, + struct razor_property *prop) +{ + struct list *pkg; + + for (pkg = list_first(&prop->packages, &trans->system->package_pool); pkg; pkg = list_next(pkg)) { + if (bitarray_get(&trans->syspkgs, pkg->data)) + return 0; + } + return 1; +} + +static int +prop_is_being_updated(struct razor_transaction_resolver *trans, + struct razor_property *prop) +{ + struct razor_package *packages = trans->system->packages.data; + const char *pool = trans->system->string_pool.data; + struct razor_transaction_package *tp; + struct list *pkg; + + /* Assumes prop_is_being_removed returns true */ + + for (pkg = list_first(&prop->packages, &trans->system->package_pool); pkg; pkg = list_next(pkg)) { + tp = find_transaction_package(trans, &pool[packages[pkg->data].name]); + if (tp && tp->state == RAZOR_PACKAGE_REMOVE) + return 0; + } + return 1; +} + +static void +razor_transaction_satisfy_removes(struct razor_transaction_resolver *trans) +{ + struct razor_package *spkgs, *upkgs, *pkg, *upgrade; + struct razor_property *sp, *sprops, *sprop_end, *sr; + struct razor_property *up, *uprops, *uprop_end, *ur, *first_up; + const char *spool, *upool, *removed_package; + struct list *reqpkg; + + spkgs = trans->system->packages.data; + sprops = trans->system->properties.data; + sprop_end = trans->system->properties.data + trans->system->properties.size; + spool = trans->system->string_pool.data; + upkgs = trans->upstream->packages.data; + uprops = trans->upstream->properties.data; + uprop_end = trans->upstream->properties.data + trans->upstream->properties.size; + upool = trans->upstream->string_pool.data; + + up = uprops; + for (sp = sprops; sp < sprop_end; sp++) { + /* Skip 'sp' ahead to a PROVIDES of a package which is + * to-be-removed. + */ + while (sp < sprop_end && + (sp->type != RAZOR_PROPERTY_PROVIDES || + !prop_is_being_removed(trans, sp))) + sp++; + if (sp == sprop_end) + break; + + removed_package = &spool[spkgs[list_first(&sp->packages, &trans->system->package_pool)->data].name]; + + /* Skip 'up' to match */ + up = skip_to_matching_property(trans, sp, up); + ur = first_up = up; + + /* If the package is just being upgraded, we may + * already be installing an identical PROVIDES, so + * check for that. + */ + while (up < uprop_end && + strcmp(&spool[sp->name], &upool[up->name]) == 0 && + (up->type != RAZOR_PROPERTY_PROVIDES || + sp->relation != up->relation || + strcmp(&spool[sp->name], &upool[up->name]) != 0)) + up++; + if (up < uprop_end && + up->type == RAZOR_PROPERTY_PROVIDES && + strcmp(&spool[sp->name], &upool[up->name]) == 0 && + sp->relation == up->relation && + strcmp(&spool[sp->version], &upool[up->version]) == 0 && + prop_is_being_installed(trans, up)) { + up = first_up; + continue; + } + up = first_up; + + /* For all still-installed packages that require + * sp->name, see if they are satisfied by any other + * still-installed or to-be-installed property. If + * not, either remove or attempt to update the + * package, depending on why the required property has + * disappeared + */ + sr = sp; + while (sr > sprops + 1 && (sr - 1)->name == sr->name) + sr--; + for (; sr->type == RAZOR_PROPERTY_REQUIRES; sr++) { + if (prop_is_being_removed(trans, sr)) + continue; + if (find_installed_package_for_property(trans, sp, up, sr)) + continue; + + for (reqpkg = list_first(&sr->packages, &trans->system->package_pool); reqpkg; reqpkg = list_next(reqpkg)) { + if (!bitarray_get(&trans->syspkgs, reqpkg->data)) + continue; + pkg = &spkgs[reqpkg->data]; + if (prop_is_being_updated(trans, sp)) { + upgrade = find_upgrade_for_lost_requirement(trans, pkg, sr); + if (upgrade) { + add_transaction_package(trans, upgrade, pkg, + RAZOR_PACKAGE_FORCED_UPDATE, + removed_package, NULL); + } else { + /* This will cause a CONTRADICTION */ + add_transaction_package(trans, pkg, NULL, + RAZOR_PACKAGE_INSTALL, + removed_package, sr); + } + } else { + add_transaction_package(trans, NULL, pkg, + RAZOR_PACKAGE_REMOVE, + removed_package, sr); + } + } + } + +#if 0 + /* Likewise with to-be-installed packages (in this + * case we can't actually remove them, but + * add_transaction_package will handle creating the + * error entry). + */ + ur = first_up; + while (ur > uprops + 1 && (ur - 1)->name == ur->name) + ur--; + for (; ur->type == RAZOR_PROPERTY_REQUIRES; ur++) { + if (!prop_is_being_installed(trans, ur)) + continue; + if (find_installed_package_for_property(trans, sp, up, ur)) + continue; + + for (reqpkg = list_first(&ur->packages, &trans->upstream->package_pool); reqpkg; reqpkg = list_next(reqpkg)) { + if (!bitarray_get(&trans->uppkgs, reqpkg->data)) + continue; + pkg = &upkgs[reqpkg->data]; + add_transaction_package(trans, NULL, pkg, + RAZOR_PACKAGE_REMOVE, + NULL, sr); + } + } +#endif + } +} struct razor_transaction * razor_transaction_create(struct razor_set *system, struct razor_set *upstream, @@ -2653,7 +2860,7 @@ razor_transaction_create(struct razor_set *system, struct razor_set *upstream, while (!trans.errors && start != end) { razor_transaction_satisfy_installs(&trans); - razor_transaction_satisfy_removes(&trans, start, end); + razor_transaction_satisfy_removes(&trans); start = end; end = trans.packages.size / sizeof (struct razor_transaction_package); @@ -2721,20 +2928,34 @@ razor_transaction_describe(struct razor_transaction *trans) printf("\n"); break; + case RAZOR_PACKAGE_FORCED_UPDATE: + if (errors_only) + break; + + printf("Updating %s to %s due to update of %s\n", + p->name, p->new_version, p->dep_package); + break; + case RAZOR_PACKAGE_REMOVE: if (errors_only) break; printf("Removing %s %s", p->name, p->old_version); if (p->dep_package) { - if (p->dep_type == RAZOR_PROPERTY_OBSOLETES) { - printf(" which is obsoleted by %s", - p->dep_package); - } else { - printf(" which required %s", - p->dep_package); - if (strcmp(p->dep_property, p->name) != 0) - printf(" for %s", p->dep_property); - } + printf(" which required %s", + p->dep_package); + if (strcmp(p->dep_property, p->name) != 0) + printf(" for %s", p->dep_property); + } + printf("\n"); + break; + + case RAZOR_PACKAGE_OBSOLETED: + if (errors_only) + break; + printf("Removing %s %s", p->name, p->old_version); + if (p->dep_package) { + printf(" which is obsoleted by %s", + p->dep_package); } printf("\n"); break; diff --git a/razor.h b/razor.h index aa67ba6..a328430 100644 --- a/razor.h +++ b/razor.h @@ -77,7 +77,9 @@ razor_set_diff(struct razor_set *set, struct razor_set *upstream, enum razor_transaction_package_state { /* Basic states */ RAZOR_PACKAGE_INSTALL, + RAZOR_PACKAGE_FORCED_UPDATE, RAZOR_PACKAGE_REMOVE, + RAZOR_PACKAGE_OBSOLETED, /* Error states */ @@ -94,7 +96,7 @@ enum razor_transaction_package_state { /* Already-installed package has a conflict against this package */ RAZOR_PACKAGE_OLD_CONFLICT, /* Requirement of to-be-installed package can't be satisfied */ - RAZOR_PACKAGE_UNSATISFIABLE + RAZOR_PACKAGE_UNSATISFIABLE, }; struct razor_transaction_package { diff --git a/test-driver.c b/test-driver.c index 64b2d9d..3a99150 100644 --- a/test-driver.c +++ b/test-driver.c @@ -64,9 +64,9 @@ struct test_context { char *install_pkgs[3], *remove_pkgs[3]; int n_install_pkgs, n_remove_pkgs; - int in_result, result_errors; + int in_result; - int debug; + int debug, errors; }; static void @@ -214,7 +214,7 @@ check_unsatisfiable_property(struct test_context *ctx, enum razor_property_type fprintf(stderr, " didn't get unsatisfiable '%s %s %s'\n", name, razor_version_relations[rel], version); - exit(1); + ctx->errors++; } static void @@ -317,7 +317,7 @@ diff_callback(const char *name, { struct test_context *ctx = data; - ctx->result_errors++; + ctx->errors++; if (old_version) { fprintf(stderr, " result set should not contain %s %s\n", name, old_version); @@ -335,11 +335,8 @@ end_result(struct test_context *ctx) if (ctx->result_set) { if (!ctx->system_set) ctx->system_set = razor_set_create(); - ctx->result_errors = 0; razor_set_diff(ctx->system_set, ctx->result_set, diff_callback, ctx); - if (ctx->result_errors) - exit(1); } } @@ -443,5 +440,9 @@ int main(int argc, char *argv[]) parse_xml_file(test_file, start_test_element, end_test_element, &ctx); - return 0; + if (ctx.errors) { + fprintf(stderr, "\n%d errors\n", ctx.errors); + return 1; + } else + return 0; }