solver: corner case fixes

- try harder to not change anything during self-upgrade
- also honor locking to packages that where earlier used in
  merging common dependencies
- clarify upgrade applet help messages
cute-signatures
Timo Teräs 2013-06-12 15:25:16 +03:00
parent e7fd4d03bf
commit 59678309ea
3 changed files with 27 additions and 8 deletions

View File

@ -45,6 +45,8 @@ struct apk_solver_package_state {
unsigned tag_ok : 1;
unsigned tag_preferred : 1;
unsigned available : 1;
unsigned dependencies_used : 1;
unsigned dependencies_merged : 1;
unsigned in_changeset : 1;
unsigned iif_triggered : 1;
};

View File

@ -329,6 +329,7 @@ static void reconsider_name(struct apk_solver_state *ss, struct apk_name *name)
struct apk_package *pkg = p0->pkg;
/* check if this pkg's dependencies have become unsatisfiable */
pkg->ss.dependencies_merged = 0;
if (reevaluate_deps) {
if (!pkg->ss.available)
continue;
@ -360,6 +361,7 @@ static void reconsider_name(struct apk_solver_state *ss, struct apk_name *name)
num_tag_not_ok += !pkg->ss.tag_ok;
/* merge common dependencies */
pkg->ss.dependencies_merged = 1;
if (first_candidate == -1)
first_candidate = i;
for (j = 0; j < pkg->depends->num; j++) {
@ -377,6 +379,10 @@ static void reconsider_name(struct apk_solver_state *ss, struct apk_name *name)
queue_unresolved(ss, name);
if (first_candidate != -1) {
for (i = 0; i < name->providers->num; i++) {
struct apk_package *pkg = name->providers->item[i].pkg;
pkg->ss.dependencies_used = pkg->ss.dependencies_merged;
}
/* TODO: could merge versioning bits too */
/* propagate down common dependencies */
pkg = name->providers->item[first_candidate].pkg;
@ -418,13 +424,25 @@ static int compare_providers(struct apk_solver_state *ss,
if (r)
return r;
/* Prefer those that were in last dependency merging group */
r = (int)pkgA->ss.dependencies_used - (int)pkgB->ss.dependencies_used;
if (r)
return r;
/* Prefer installed on self-upgrade */
solver_flags = pkgA->ss.solver_flags | pkgB->ss.solver_flags;
if (db->performing_self_update && !(solver_flags & APK_SOLVERF_UPGRADE)) {
r = (pkgA->ipkg != NULL) - (pkgB->ipkg != NULL);
if (r)
return r;
}
/* Prefer allowed pinning */
r = (int)pkgA->ss.tag_ok - (int)pkgB->ss.tag_ok;
if (r)
return r;
/* Prefer available */
solver_flags = pkgA->ss.solver_flags | pkgB->ss.solver_flags;
if (solver_flags & APK_SOLVERF_AVAILABLE) {
r = !!(pkgA->repos & db->available_repos) -
!!(pkgB->repos & db->available_repos);
@ -712,8 +730,6 @@ int apk_solver_solve(struct apk_database *db,
foreach_dependency(ss, world, discover_names);
/* FIXME: If filename specified, force to use it */
dbg_printf("applying world\n");
ss->prefer_pinning = 1;
ss->solver_flags_inherit = solver_flags;

View File

@ -60,7 +60,7 @@ int apk_do_self_upgrade(struct apk_database *db, unsigned short solver_flags)
goto ret;
}
if (changeset.num_install + changeset.num_remove + changeset.num_adjust == 0)
if (changeset.num_total_changes == 0)
goto ret;
if (apk_flags & APK_SIMULATE) {
@ -130,16 +130,17 @@ static int upgrade_main(void *ctx, struct apk_database *db, int argc, char **arg
static struct apk_option upgrade_options[] = {
{ 'a', "available",
"Re-install or downgrade if currently installed package is not "
"currently available from any repository" },
"Resets versioned world dependencies, and changes to prefer "
"replacing or downgrading packages (instead of holding them) "
"if the currently installed package is no longer available "
"from any repository" },
{ 0x10000, "no-self-upgrade",
"Do not do early upgrade of 'apk-tools' package" },
};
static struct apk_applet apk_upgrade = {
.name = "upgrade",
.help = "Upgrade (or downgrade with -a) the currently installed "
"packages to versions available in repositories.",
.help = "Upgrade currently installed packages to match repositories.",
.open_flags = APK_OPENF_WRITE,
.context_size = sizeof(struct upgrade_ctx),
.num_options = ARRAY_SIZE(upgrade_options),