Commit 56b623b9 authored by Timo Teräs's avatar Timo Teräs

solver: use array_foreach_item and clean ups

parent edf03b15
...@@ -51,10 +51,10 @@ void apk_solver_set_name_flags(struct apk_name *name, ...@@ -51,10 +51,10 @@ void apk_solver_set_name_flags(struct apk_name *name,
unsigned short solver_flags, unsigned short solver_flags,
unsigned short solver_flags_inheritable) unsigned short solver_flags_inheritable)
{ {
int i; struct apk_provider *p;
for (i = 0; i < name->providers->num; i++) { foreach_array_item(p, name->providers) {
struct apk_package *pkg = name->providers->item[i].pkg; struct apk_package *pkg = p->pkg;
pkg->ss.solver_flags |= solver_flags; pkg->ss.solver_flags |= solver_flags;
pkg->ss.solver_flags_inheritable |= solver_flags_inheritable; pkg->ss.solver_flags_inheritable |= solver_flags_inheritable;
} }
...@@ -78,50 +78,25 @@ static unsigned int get_pkg_repos(struct apk_database *db, struct apk_package *p ...@@ -78,50 +78,25 @@ static unsigned int get_pkg_repos(struct apk_database *db, struct apk_package *p
return pkg->repos | (pkg->ipkg ? db->repo_tags[pkg->ipkg->repository_tag].allowed_repos : 0); return pkg->repos | (pkg->ipkg ? db->repo_tags[pkg->ipkg->repository_tag].allowed_repos : 0);
} }
static void foreach_dependency(struct apk_solver_state *ss, struct apk_package *ppkg, struct apk_dependency_array *deps,
void (*func)(struct apk_solver_state *ss, struct apk_package *ppkg, struct apk_dependency *dep))
{
int i;
for (i = 0; i < deps->num; i++)
func(ss, ppkg, &deps->item[i]);
}
static void foreach_name(struct apk_solver_state *ss, struct apk_name_array *names,
void (*func)(struct apk_solver_state *ss, struct apk_name *name))
{
int i;
for (i = 0; i < names->num; i++)
if (names->item[i]->ss.seen)
func(ss, names->item[i]);
}
static void foreach_rinstall_if_pkg( static void foreach_rinstall_if_pkg(
struct apk_solver_state *ss, struct apk_package *pkg, struct apk_solver_state *ss, struct apk_package *pkg,
void (*cb)(struct apk_solver_state *ss, struct apk_package *rinstall_if, struct apk_package *parent_pkg)) void (*cb)(struct apk_solver_state *ss, struct apk_package *rinstall_if, struct apk_package *parent_pkg))
{ {
struct apk_name *name = pkg->name; struct apk_name *name = pkg->name, *name0, **pname0;
int i, j, k; struct apk_dependency *dep;
struct apk_provider *p0;
for (i = 0; i < pkg->name->rinstall_if->num; i++) {
struct apk_name *name0 = pkg->name->rinstall_if->item[i];
foreach_array_item(pname0, pkg->name->rinstall_if) {
name0 = *pname0;
dbg_printf(PKG_VER_FMT ": rinstall_if %s\n", PKG_VER_PRINTF(pkg), name0->name); dbg_printf(PKG_VER_FMT ": rinstall_if %s\n", PKG_VER_PRINTF(pkg), name0->name);
foreach_array_item(p0, name0->providers) {
for (j = 0; j < name0->providers->num; j++) { foreach_array_item(dep, p0->pkg->install_if) {
struct apk_provider *p0 = &name0->providers->item[j]; if (dep->name == name && apk_dep_is_provided(dep, p0)) {
/* pkg depends (via install_if) on pkg0 */
for (k = 0; k < p0->pkg->install_if->num; k++) { cb(ss, p0->pkg, pkg);
struct apk_dependency *dep = &p0->pkg->install_if->item[k];
if (dep->name == name &&
apk_dep_is_provided(dep, p0))
break; break;
}
} }
if (k >= p0->pkg->install_if->num)
continue;
/* pkg depends (via install_if) on pkg0 */
cb(ss, p0->pkg, pkg);
} }
} }
} }
...@@ -159,35 +134,48 @@ static void queue_unresolved(struct apk_solver_state *ss, struct apk_name *name) ...@@ -159,35 +134,48 @@ static void queue_unresolved(struct apk_solver_state *ss, struct apk_name *name)
list_del_init(&name->ss.unresolved_list); list_del_init(&name->ss.unresolved_list);
} }
static void reevaluate_deps(struct apk_solver_state *ss, struct apk_name *name) static void reevaluate_reverse_deps(struct apk_solver_state *ss, struct apk_name *name)
{ {
name->ss.reevaluate_deps = 1; struct apk_name **pname0, *name0;
queue_dirty(ss, name);
foreach_array_item(pname0, name->rdepends) {
name0 = *pname0;
if (!name0->ss.seen)
continue;
name0->ss.reevaluate_deps = 1;
queue_dirty(ss, name0);
}
} }
static void reevaluate_installif(struct apk_solver_state *ss, struct apk_name *name) static void reevaluate_reverse_installif(struct apk_solver_state *ss, struct apk_name *name)
{ {
name->ss.reevaluate_iif = 1; struct apk_name **pname0, *name0;
queue_dirty(ss, name);
foreach_array_item(pname0, name->rinstall_if) {
name0 = *pname0;
if (!name0->ss.seen)
continue;
name0->ss.reevaluate_iif = 1;
queue_dirty(ss, name0);
}
} }
static void disqualify_package(struct apk_solver_state *ss, struct apk_package *pkg, const char *reason) static void disqualify_package(struct apk_solver_state *ss, struct apk_package *pkg, const char *reason)
{ {
int i; struct apk_dependency *p;
dbg_printf("disqualify_package: " PKG_VER_FMT " (%s)\n", PKG_VER_PRINTF(pkg), reason); dbg_printf("disqualify_package: " PKG_VER_FMT " (%s)\n", PKG_VER_PRINTF(pkg), reason);
pkg->ss.available = 0; pkg->ss.available = 0;
reevaluate_reverse_deps(ss, pkg->name);
foreach_name(ss, pkg->name->rdepends, reevaluate_deps); foreach_array_item(p, pkg->provides)
for (i = 0; i < pkg->provides->num; i++) reevaluate_reverse_deps(ss, p->name);
foreach_name(ss, pkg->provides->item[i].name->rdepends, reevaluate_deps); reevaluate_reverse_installif(ss, pkg->name);
foreach_name(ss, pkg->name->rinstall_if, reevaluate_installif);
} }
static int dependency_satisfiable(struct apk_solver_state *ss, struct apk_dependency *dep) static int dependency_satisfiable(struct apk_solver_state *ss, struct apk_dependency *dep)
{ {
struct apk_name *name = dep->name; struct apk_name *name = dep->name;
int i; struct apk_provider *p;
if (name->ss.locked) if (name->ss.locked)
return apk_dep_is_provided(dep, &name->ss.chosen); return apk_dep_is_provided(dep, &name->ss.chosen);
...@@ -195,36 +183,27 @@ static int dependency_satisfiable(struct apk_solver_state *ss, struct apk_depend ...@@ -195,36 +183,27 @@ static int dependency_satisfiable(struct apk_solver_state *ss, struct apk_depend
if (name->ss.requirers == 0 && apk_dep_is_provided(dep, &provider_none)) if (name->ss.requirers == 0 && apk_dep_is_provided(dep, &provider_none))
return TRUE; return TRUE;
for (i = 0; i < name->providers->num; i++) { foreach_array_item(p, name->providers)
struct apk_package *pkg = name->providers->item[i].pkg; if (p->pkg->ss.available && apk_dep_is_provided(dep, p))
if (!pkg->ss.available)
continue;
if (apk_dep_is_provided(dep, &name->providers->item[i]))
return TRUE; return TRUE;
}
return FALSE; return FALSE;
} }
static void discover_name(struct apk_solver_state *ss, struct apk_name *name);
static void discover_names(struct apk_solver_state *ss, struct apk_package *ppkg, struct apk_dependency *dep)
{
discover_name(ss, dep->name);
}
static void discover_name(struct apk_solver_state *ss, struct apk_name *name) static void discover_name(struct apk_solver_state *ss, struct apk_name *name)
{ {
struct apk_database *db = ss->db; struct apk_database *db = ss->db;
struct apk_name **pname0;
struct apk_provider *p;
struct apk_dependency *dep;
unsigned int repos; unsigned int repos;
int i, j;
if (name->ss.seen) if (name->ss.seen)
return; return;
name->ss.seen = 1; name->ss.seen = 1;
for (i = 0; i < name->providers->num; i++) { foreach_array_item(p, name->providers) {
struct apk_package *pkg = name->providers->item[i].pkg; struct apk_package *pkg = p->pkg;
if (pkg->ss.seen) if (pkg->ss.seen)
continue; continue;
pkg->ss.seen = 1; pkg->ss.seen = 1;
...@@ -236,10 +215,11 @@ static void discover_name(struct apk_solver_state *ss, struct apk_name *name) ...@@ -236,10 +215,11 @@ static void discover_name(struct apk_solver_state *ss, struct apk_name *name)
pkg->ss.tag_ok = !!(repos & ss->default_repos); pkg->ss.tag_ok = !!(repos & ss->default_repos);
pkg->ss.tag_preferred = !!(repos & ss->default_repos); pkg->ss.tag_preferred = !!(repos & ss->default_repos);
foreach_dependency(ss, pkg, pkg->depends, discover_names); foreach_array_item(dep, pkg->depends) {
for (j = 0; j < pkg->depends->num; j++) discover_name(ss, dep->name);
pkg->ss.max_dep_chain = max(pkg->ss.max_dep_chain, pkg->ss.max_dep_chain = max(pkg->ss.max_dep_chain,
pkg->depends->item[j].name->ss.max_dep_chain+1); dep->name->ss.max_dep_chain+1);
}
name->ss.max_dep_chain = max(name->ss.max_dep_chain, pkg->ss.max_dep_chain); name->ss.max_dep_chain = max(name->ss.max_dep_chain, pkg->ss.max_dep_chain);
dbg_printf("discover " PKG_VER_FMT ": tag_ok=%d, tag_pref=%d max_dep_chain=%d\n", dbg_printf("discover " PKG_VER_FMT ": tag_ok=%d, tag_pref=%d max_dep_chain=%d\n",
...@@ -248,15 +228,14 @@ static void discover_name(struct apk_solver_state *ss, struct apk_name *name) ...@@ -248,15 +228,14 @@ static void discover_name(struct apk_solver_state *ss, struct apk_name *name)
pkg->ss.tag_preferred, pkg->ss.tag_preferred,
pkg->ss.max_dep_chain); pkg->ss.max_dep_chain);
} }
/* Can't use foreach_name, as it checks the seen flag */ foreach_array_item(pname0, name->rinstall_if)
for (i = 0; i < name->rinstall_if->num; i++) discover_name(ss, *pname0);
discover_name(ss, name->rinstall_if->item[i]);
} }
static void name_requirers_changed(struct apk_solver_state *ss, struct apk_name *name) static void name_requirers_changed(struct apk_solver_state *ss, struct apk_name *name)
{ {
queue_unresolved(ss, name); queue_unresolved(ss, name);
foreach_name(ss, name->rinstall_if, reevaluate_installif); reevaluate_reverse_installif(ss, name);
queue_dirty(ss, name); queue_dirty(ss, name);
} }
...@@ -276,8 +255,9 @@ static void inherit_pinning(struct apk_solver_state *ss, struct apk_package *pkg ...@@ -276,8 +255,9 @@ static void inherit_pinning(struct apk_solver_state *ss, struct apk_package *pkg
static void apply_constraint(struct apk_solver_state *ss, struct apk_package *ppkg, struct apk_dependency *dep) static void apply_constraint(struct apk_solver_state *ss, struct apk_package *ppkg, struct apk_dependency *dep)
{ {
struct apk_name *name = dep->name; struct apk_name *name = dep->name;
struct apk_provider *p0;
unsigned int solver_flags_inherit = ss->solver_flags_inherit; unsigned int solver_flags_inherit = ss->solver_flags_inherit;
int i; int is_provided;
dbg_printf("apply_constraint: %s%s%s" BLOB_FMT "\n", dbg_printf("apply_constraint: %s%s%s" BLOB_FMT "\n",
dep->conflict ? "!" : "", dep->conflict ? "!" : "",
...@@ -288,10 +268,8 @@ static void apply_constraint(struct apk_solver_state *ss, struct apk_package *pp ...@@ -288,10 +268,8 @@ static void apply_constraint(struct apk_solver_state *ss, struct apk_package *pp
name->ss.requirers += !dep->conflict; name->ss.requirers += !dep->conflict;
name_requirers_changed(ss, name); name_requirers_changed(ss, name);
for (i = 0; i < name->providers->num; i++) { foreach_array_item(p0, name->providers) {
struct apk_provider *p0 = &name->providers->item[i];
struct apk_package *pkg0 = p0->pkg; struct apk_package *pkg0 = p0->pkg;
int is_provided;
is_provided = apk_dep_is_provided(dep, p0); is_provided = apk_dep_is_provided(dep, p0);
dbg_printf("apply_constraint: provider: %s-" BLOB_FMT ": %d\n", dbg_printf("apply_constraint: provider: %s-" BLOB_FMT ": %d\n",
...@@ -318,32 +296,29 @@ static void reconsider_name(struct apk_solver_state *ss, struct apk_name *name) ...@@ -318,32 +296,29 @@ static void reconsider_name(struct apk_solver_state *ss, struct apk_name *name)
{ {
struct apk_name *name0; struct apk_name *name0;
struct apk_dependency *dep; struct apk_dependency *dep;
struct apk_package *pkg; struct apk_package *first_candidate = NULL;
int i, j, reevaluate_deps, reevaluate_iif; struct apk_provider *p;
int first_candidate = -1, last_candidate = 0; int reevaluate_deps, reevaluate_iif;
int num_options = 0, num_tag_not_ok = 0, has_iif = 0; int num_options = 0, num_tag_not_ok = 0, has_iif = 0;
dbg_printf("reconsider_name: %s\n", name->name); dbg_printf("reconsider_name: %s\n", name->name);
reevaluate_deps = name->ss.reevaluate_deps; reevaluate_deps = name->ss.reevaluate_deps;
name->ss.reevaluate_deps = 0;
reevaluate_iif = name->ss.reevaluate_iif; reevaluate_iif = name->ss.reevaluate_iif;
name->ss.reevaluate_deps = 0;
name->ss.reevaluate_iif = 0; name->ss.reevaluate_iif = 0;
/* propagate down by merging common dependencies and /* propagate down by merging common dependencies and
* applying new constraints */ * applying new constraints */
for (i = 0; i < name->providers->num; i++) { foreach_array_item(p, name->providers) {
struct apk_provider *p0 = &name->providers->item[i]; struct apk_package *pkg = p->pkg;
struct apk_package *pkg = p0->pkg;
/* check if this pkg's dependencies have become unsatisfiable */ /* check if this pkg's dependencies have become unsatisfiable */
pkg->ss.dependencies_merged = 0; pkg->ss.dependencies_merged = 0;
if (reevaluate_deps) { if (reevaluate_deps) {
if (!pkg->ss.available) if (!pkg->ss.available)
continue; continue;
for (j = 0; j < pkg->depends->num; j++) { foreach_array_item(dep, pkg->depends) {
dep = &pkg->depends->item[j];
if (!dependency_satisfiable(ss, dep)) { if (!dependency_satisfiable(ss, dep)) {
disqualify_package(ss, pkg, "dependency no longer satisfiable"); disqualify_package(ss, pkg, "dependency no longer satisfiable");
break; break;
...@@ -354,53 +329,50 @@ static void reconsider_name(struct apk_solver_state *ss, struct apk_name *name) ...@@ -354,53 +329,50 @@ static void reconsider_name(struct apk_solver_state *ss, struct apk_name *name)
continue; continue;
if (reevaluate_iif) { if (reevaluate_iif) {
for (j = 0; j < pkg->install_if->num; j++) { pkg->ss.iif_triggered = 1;
dep = &pkg->install_if->item[j]; foreach_array_item(dep, pkg->install_if) {
if (!dependency_satisfiable(ss, dep)) if (!dependency_satisfiable(ss, dep)) {
pkg->ss.iif_triggered = 0;
break; break;
}
} }
pkg->ss.iif_triggered = (j >= pkg->install_if->num);
has_iif |= pkg->ss.iif_triggered; has_iif |= pkg->ss.iif_triggered;
} }
if (name->ss.requirers == 0 && !pkg->ss.iif_triggered) if (name->ss.requirers == 0 && !pkg->ss.iif_triggered)
continue; continue;
num_options++;
num_tag_not_ok += !pkg->ss.tag_ok;
/* merge common dependencies */ /* merge common dependencies */
pkg->ss.dependencies_merged = 1; pkg->ss.dependencies_merged = 1;
if (first_candidate == -1) if (first_candidate == NULL)
first_candidate = i; first_candidate = pkg;
for (j = 0; j < pkg->depends->num; j++) { foreach_array_item(dep, pkg->depends) {
dep = &pkg->depends->item[j]; /* FIXME: can merge also conflicts */
if (dep->conflict /*&& dep->result_mask != APK_DEPMASK_ANY*/) if (dep->conflict)
continue; continue;
name0 = dep->name; name0 = dep->name;
if (name0->ss.merge_index == last_candidate) if (name0->ss.merge_index == num_options)
name0->ss.merge_index = i + 1; name0->ss.merge_index = num_options + 1;
} }
last_candidate = i + 1;
num_tag_not_ok += !pkg->ss.tag_ok;
num_options++;
} }
name->ss.has_options = (num_options > 1 || num_tag_not_ok > 0); name->ss.has_options = (num_options > 1 || num_tag_not_ok > 0);
name->ss.has_iif = has_iif; name->ss.has_iif = has_iif;
queue_unresolved(ss, name); queue_unresolved(ss, name);
if (first_candidate != -1) { if (first_candidate != NULL) {
for (i = 0; i < name->providers->num; i++) { foreach_array_item(p, name->providers)
struct apk_package *pkg = name->providers->item[i].pkg; p->pkg->ss.dependencies_used = p->pkg->ss.dependencies_merged;
pkg->ss.dependencies_used = pkg->ss.dependencies_merged;
}
/* TODO: could merge versioning bits too */ /* TODO: could merge versioning bits too */
/* propagate down common dependencies */ /* propagate down common dependencies */
pkg = name->providers->item[first_candidate].pkg; foreach_array_item(dep, first_candidate->depends) {
for (j = 0; j < pkg->depends->num; j++) { if (dep->conflict)
dep = &pkg->depends->item[j];
if (dep->conflict && dep->result_mask != APK_DEPMASK_ANY)
continue; continue;
name0 = dep->name; name0 = dep->name;
if (name0->ss.merge_index == last_candidate) { if (name0->ss.merge_index == num_options) {
/* common dependency name with all */ /* common dependency name with all */
if (name0->ss.requirers == 0) { if (name0->ss.requirers == 0) {
dbg_printf("%s common dependency: %s\n", dbg_printf("%s common dependency: %s\n",
...@@ -508,7 +480,7 @@ static void inherit_pinning_from_pkg(struct apk_solver_state *ss, struct apk_pac ...@@ -508,7 +480,7 @@ static void inherit_pinning_from_pkg(struct apk_solver_state *ss, struct apk_pac
static void assign_name(struct apk_solver_state *ss, struct apk_name *name, struct apk_provider p) static void assign_name(struct apk_solver_state *ss, struct apk_name *name, struct apk_provider p)
{ {
int i; struct apk_provider *p0;
if (name->ss.locked) { if (name->ss.locked) {
/* If both are providing this name without version, it's ok */ /* If both are providing this name without version, it's ok */
...@@ -536,35 +508,33 @@ static void assign_name(struct apk_solver_state *ss, struct apk_name *name, stru ...@@ -536,35 +508,33 @@ static void assign_name(struct apk_solver_state *ss, struct apk_name *name, stru
foreach_rinstall_if_pkg(ss, p.pkg, inherit_pinning_from_pkg); foreach_rinstall_if_pkg(ss, p.pkg, inherit_pinning_from_pkg);
/* disqualify all conflicting packages */ /* disqualify all conflicting packages */
for (i = 0; i < name->providers->num; i++) { foreach_array_item(p0, name->providers) {
if (name->providers->item[i].pkg == p.pkg) if (p0->pkg == p.pkg)
continue; continue;
if (p.version == &apk_null_blob && if (p.version == &apk_null_blob &&
name->providers->item[i].version == &apk_null_blob) p0->version == &apk_null_blob)
continue; continue;
disqualify_package(ss, name->providers->item[i].pkg, disqualify_package(ss, p0->pkg, "conflicting provides");
"conflicting provides");
} }
reevaluate_reverse_deps(ss, name);
foreach_name(ss, name->rdepends, reevaluate_deps);
} }
static void select_package(struct apk_solver_state *ss, struct apk_name *name) static void select_package(struct apk_solver_state *ss, struct apk_name *name)
{ {
struct apk_provider chosen = { NULL, &apk_null_blob }; struct apk_provider chosen = { NULL, &apk_null_blob }, *p;
struct apk_package *pkg = NULL; struct apk_package *pkg = NULL;
int i; struct apk_dependency *d;
dbg_printf("select_package: %s\n", name->name); dbg_printf("select_package: %s\n", name->name);
if (name->ss.requirers || name->ss.has_iif) { if (name->ss.requirers || name->ss.has_iif) {
for (i = 0; i < name->providers->num; i++) { foreach_array_item(p, name->providers) {
if (name->ss.requirers == 0 && if (name->ss.requirers == 0 &&
(!name->providers->item[i].pkg->ss.iif_triggered || (!p->pkg->ss.iif_triggered ||
!name->providers->item[i].pkg->ss.tag_ok)) !p->pkg->ss.tag_ok))
continue; continue;
if (compare_providers(ss, &name->providers->item[i], &chosen) > 0) if (compare_providers(ss, p, &chosen) > 0)
chosen = name->providers->item[i]; chosen = *p;
} }
} }
...@@ -581,16 +551,18 @@ static void select_package(struct apk_solver_state *ss, struct apk_name *name) ...@@ -581,16 +551,18 @@ static void select_package(struct apk_solver_state *ss, struct apk_name *name)
mark_error(ss, pkg); mark_error(ss, pkg);
} }
dbg_printf("selecting: " PKG_VER_FMT ", available: %d\n", PKG_VER_PRINTF(pkg), pkg->ss.available); dbg_printf("selecting: " PKG_VER_FMT ", available: %d\n", PKG_VER_PRINTF(pkg), pkg->ss.available);
assign_name(ss, pkg->name, APK_PROVIDER_FROM_PACKAGE(pkg)); assign_name(ss, pkg->name, APK_PROVIDER_FROM_PACKAGE(pkg));
for (i = 0; i < pkg->provides->num; i++) { foreach_array_item(d, pkg->provides)
struct apk_dependency *p = &pkg->provides->item[i]; assign_name(ss, d->name, APK_PROVIDER_FROM_PROVIDES(pkg, d));
assign_name(ss, p->name, APK_PROVIDER_FROM_PROVIDES(pkg, p));
}
ss->solver_flags_inherit = pkg->ss.solver_flags_inheritable; ss->solver_flags_inherit = pkg->ss.solver_flags_inheritable;
ss->pinning_inherit = pkg->ss.pinning_allowed; ss->pinning_inherit = pkg->ss.pinning_allowed;
foreach_dependency(ss, pkg, pkg->depends, apply_constraint); foreach_array_item(d, pkg->depends)
apply_constraint(ss, pkg, d);
ss->solver_flags_inherit = 0; ss->solver_flags_inherit = 0;
ss->pinning_inherit = 0; ss->pinning_inherit = 0;
ss->num_selections++; ss->num_selections++;
} else { } else {
dbg_printf("selecting: %s [unassigned]\n", name->name); dbg_printf("selecting: %s [unassigned]\n", name->name);
...@@ -604,9 +576,11 @@ static void generate_change_iif(struct apk_solver_state *ss, struct apk_name *na ...@@ -604,9 +576,11 @@ static void generate_change_iif(struct apk_solver_state *ss, struct apk_name *na
static void generate_change(struct apk_solver_state *ss, struct apk_name *name) static void generate_change(struct apk_solver_state *ss, struct apk_name *name)
{ {
struct apk_name **pname;
struct apk_package *pkg = name->ss.chosen.pkg, *opkg; struct apk_package *pkg = name->ss.chosen.pkg, *opkg;
struct apk_changeset *changeset = ss->changeset; struct apk_changeset *changeset = ss->changeset;
struct apk_change *change; struct apk_change *change;
struct apk_dependency *d;
if (pkg == NULL) if (pkg == NULL)
return; return;
...@@ -616,7 +590,8 @@ static void generate_change(struct apk_solver_state *ss, struct apk_name *name) ...@@ -616,7 +590,8 @@ static void generate_change(struct apk_solver_state *ss, struct apk_name *name)
pkg->ss.in_changeset = 1; pkg->ss.in_changeset = 1;
pkg->name->ss.in_changeset = 1; pkg->name->ss.in_changeset = 1;
foreach_dependency(ss, pkg, pkg->depends, generate_change_dep); foreach_array_item(d, pkg->depends)
generate_change_dep(ss, pkg, d);
change = &changeset->changes->item[ss->num_solution_entries++]; change = &changeset->changes->item[ss->num_solution_entries++];
dbg_printf("Selecting: "PKG_VER_FMT"%s\n", PKG_VER_PRINTF(pkg), pkg->ss.available ? "" : " [NOT AVAILABLE]"); dbg_printf("Selecting: "PKG_VER_FMT"%s\n", PKG_VER_PRINTF(pkg), pkg->ss.available ? "" : " [NOT AVAILABLE]");
...@@ -636,21 +611,20 @@ static void generate_change(struct apk_solver_state *ss, struct apk_name *name) ...@@ -636,21 +611,20 @@ static void generate_change(struct apk_solver_state *ss, struct apk_name *name)
change->new_repository_tag != change->old_repository_tag) change->new_repository_tag != change->old_repository_tag)
changeset->num_adjust++; changeset->num_adjust++;
foreach_name(ss, pkg->name->rinstall_if, generate_change_iif); foreach_array_item(pname, pkg->name->rinstall_if)
generate_change_iif(ss, *pname);
} }
static void generate_change_iif(struct apk_solver_state *ss, struct apk_name *name) static void generate_change_iif(struct apk_solver_state *ss, struct apk_name *name)
{ {
struct apk_package *pkg = name->ss.chosen.pkg; struct apk_package *pkg = name->ss.chosen.pkg;
int i; struct apk_dependency *dep0;
if (pkg == NULL) if (pkg == NULL || !name->ss.seen)
return; return;
for (i = 0; i < pkg->install_if->num; i++) { foreach_array_item(dep0, pkg->install_if) {
struct apk_dependency *dep0 = &pkg->install_if->item[i];
struct apk_name *name0 = dep0->name; struct apk_name *name0 = dep0->name;
if (!name0->ss.in_changeset) if (!name0->ss.in_changeset)
return; return;
if (!apk_dep_is_provided(dep0, &name0->ss.chosen)) if (!apk_dep_is_provided(dep0, &name0->ss.chosen))
...@@ -678,6 +652,7 @@ static void generate_changeset(struct apk_solver_state *ss, struct apk_dependenc ...@@ -678,6 +652,7 @@ static void generate_changeset(struct apk_solver_state *ss, struct apk_dependenc
{ {
struct apk_changeset *changeset = ss->changeset; struct apk_changeset *changeset = ss->changeset;
struct apk_installed_package *ipkg; struct apk_installed_package *ipkg;
struct apk_dependency *d;
list_for_each_entry(ipkg, &ss->db->installed.packages, installed_pkgs_list) { list_for_each_entry(ipkg, &ss->db->installed.packages, installed_pkgs_list) {
struct apk_name *name = ipkg->pkg->name; struct apk_name *name = ipkg->pkg->name;
...@@ -686,7 +661,8 @@ static void generate_changeset(struct apk_solver_state *ss, struct apk_dependenc ...@@ -686,7 +661,8 @@ static void generate_changeset(struct apk_solver_state *ss, struct apk_dependenc
} }
apk_change_array_resize(&ss->changeset->changes, ss->num_selections); apk_change_array_resize(&ss->changeset->changes, ss->num_selections);
foreach_dependency(ss, NULL, world, generate_change_dep); foreach_array_item(d, world)
generate_change_dep(ss, NULL, d);
/* FIXME: could order better the removals of unneeded packages */ /* FIXME: could order better the removals of unneeded packages */
list_for_each_entry(ipkg, &ss->db->installed.packages, installed_pkgs_list) { list_for_each_entry(ipkg, &ss->db->installed.packages, installed_pkgs_list) {
...@@ -736,8 +712,9 @@ int apk_solver_solve(struct apk_database *db, ...@@ -736,8 +712,9 @@ int apk_solver_solve(struct apk_database *db,
struct apk_changeset *changeset) struct apk_changeset *changeset)
{ {
struct apk_name *name, *name0; struct apk_name *name, *name0;
struct apk_package *pkg;
struct apk_solver_state ss_data, *ss = &ss_data; struct apk_solver_state ss_data, *ss = &ss_data;
int i; struct apk_dependency *d;
restart: restart:
memset(ss, 0, sizeof(*ss)); memset(ss, 0, sizeof(*ss));
...@@ -747,19 +724,17 @@ restart: ...@@ -747,19 +724,17 @@ restart:
list_init(&ss->dirty_head); list_init(&ss->dirty_head);
list_init(&ss->unresolved_head); list_init(&ss->unresolved_head);
foreach_dependency(ss, NULL, world, discover_names);
dbg_printf("applying world\n"); dbg_printf("applying world\n");
ss->prefer_pinning = 1; ss->prefer_pinning = 1;
ss->solver_flags_inherit = solver_flags; ss->solver_flags_inherit = solver_flags;
for (i = 0; i < world->num; i++) { foreach_array_item(d, world) {
struct apk_dependency *dep = &world->item[i]; if (d->broken)
if (dep->broken)
continue; continue;
name = dep->name; name = d->name;
name->ss.in_world_dependency = 1; name->ss.in_world_dependency = 1;
ss->pinning_inherit = BIT(dep->repository_tag); discover_name(ss, d->name);
apply_constraint(ss, NULL, dep); ss->pinning_inherit = BIT(d->repository_tag);
apply_constraint(ss, NULL, d);
} }
ss->solver_flags_inherit = 0;