diff options
-rw-r--r-- | src/commit.c | 80 | ||||
-rw-r--r-- | src/solver.c | 58 |
2 files changed, 95 insertions, 43 deletions
diff --git a/src/commit.c b/src/commit.c index 3476cd1..e5c0962 100644 --- a/src/commit.c +++ b/src/commit.c @@ -385,9 +385,10 @@ all_done: } enum { - STATE_SEEN = 0x80000000, - STATE_PRESENT = 0x40000000, - STATE_MISSING = 0x20000000, + STATE_PRESENT = 0x80000000, + STATE_MISSING = 0x40000000, + STATE_VIRTUAL_ONLY = 0x20000000, + STATE_INSTALLIF = 0x10000000, STATE_COUNT_MASK = 0x0000ffff, }; @@ -606,34 +607,71 @@ static void analyze_deps(struct print_state *ps, struct apk_dependency_array *de } static void discover_deps(struct apk_dependency_array *deps); +static void discover_name(struct apk_name *name, int pkg_state); -static void discover_name(struct apk_name *name) +static void discover_reverse_iif(struct apk_name *name) { + struct apk_name **pname0, *name0; + struct apk_dependency *d; struct apk_provider *p; + + foreach_array_item(pname0, name->rinstall_if) { + name0 = *pname0; + + foreach_array_item(p, name0->providers) { + int ok = 1; + if (!p->pkg->marked) continue; + if (p->pkg->install_if->num == 0) continue; + foreach_array_item(d, p->pkg->install_if) { + if (!!d->conflict == !!(d->name->state_int & STATE_PRESENT)) { + ok = 0; + break; + } + } + if (ok) { + discover_name(p->pkg->name, STATE_INSTALLIF); + foreach_array_item(d, p->pkg->provides) + discover_name(d->name, STATE_INSTALLIF); + } + } + } +} + +static int is_name_concrete(struct apk_package *pkg, struct apk_name *name) +{ struct apk_dependency *d; - int concrete; + if (pkg->name == name) return 1; + foreach_array_item(d, pkg->provides) { + if (d->name != name) continue; + if (d->version == &apk_atom_null) continue; + return 1; + } + return 0; +} - if (name->state_int & STATE_SEEN) return; - name->state_int |= STATE_SEEN; +static void discover_name(struct apk_name *name, int pkg_state) +{ + struct apk_provider *p; + struct apk_dependency *d; foreach_array_item(p, name->providers) { + int state = pkg_state; if (!p->pkg->marked) continue; + if (state == STATE_PRESENT && !is_name_concrete(p->pkg, name)) + state = STATE_VIRTUAL_ONLY; + if (p->pkg->state_int & state) continue; + p->pkg->state_int |= state; - concrete = p->pkg->name == name; - if (!concrete) { - foreach_array_item(d, p->pkg->provides) { - if (d->name != name) continue; - if (d->version == &apk_atom_null) continue; - concrete = 1; - break; - } - } - if (concrete) { - p->pkg->name->state_int |= STATE_PRESENT; + p->pkg->name->state_int |= state; + foreach_array_item(d, p->pkg->provides) + d->name->state_int |= state; + + discover_deps(p->pkg->depends); + if (state == STATE_PRESENT || state == STATE_INSTALLIF) { + discover_reverse_iif(p->pkg->name); foreach_array_item(d, p->pkg->provides) - d->name->state_int |= STATE_PRESENT; + discover_reverse_iif(d->name); } - discover_deps(p->pkg->depends); } } @@ -643,7 +681,7 @@ static void discover_deps(struct apk_dependency_array *deps) foreach_array_item(d, deps) { if (d->conflict) continue; - discover_name(d->name); + discover_name(d->name, STATE_PRESENT); } } diff --git a/src/solver.c b/src/solver.c index 1deaf50..d7386d2 100644 --- a/src/solver.c +++ b/src/solver.c @@ -118,8 +118,7 @@ static void reevaluate_reverse_deps(struct apk_solver_state *ss, struct apk_name foreach_array_item(pname0, name->rdepends) { name0 = *pname0; - if (!name0->ss.seen) - continue; + if (!name0->ss.seen) continue; name0->ss.reevaluate_deps = 1; queue_dirty(ss, name0); } @@ -131,15 +130,21 @@ static void reevaluate_reverse_installif(struct apk_solver_state *ss, struct apk foreach_array_item(pname0, name->rinstall_if) { name0 = *pname0; - if (!name0->ss.seen) - continue; - if (name0->ss.no_iif) - continue; + if (!name0->ss.seen) continue; + if (name0->ss.no_iif) continue; name0->ss.reevaluate_iif = 1; queue_dirty(ss, name0); } } +static void reevaluate_reverse_installif_pkg(struct apk_solver_state *ss, struct apk_package *pkg) +{ + struct apk_dependency *d; + reevaluate_reverse_installif(ss, pkg->name); + foreach_array_item(d, pkg->provides) + reevaluate_reverse_installif(ss, d->name); +} + static void disqualify_package(struct apk_solver_state *ss, struct apk_package *pkg, const char *reason) { struct apk_dependency *p; @@ -149,7 +154,7 @@ static void disqualify_package(struct apk_solver_state *ss, struct apk_package * reevaluate_reverse_deps(ss, pkg->name); foreach_array_item(p, pkg->provides) reevaluate_reverse_deps(ss, p->name); - reevaluate_reverse_installif(ss, pkg->name); + reevaluate_reverse_installif_pkg(ss, pkg); } static int dependency_satisfiable(struct apk_solver_state *ss, struct apk_dependency *dep) @@ -684,7 +689,10 @@ static void assign_name(struct apk_solver_state *ss, struct apk_name *name, stru } } reevaluate_reverse_deps(ss, name); - reevaluate_reverse_installif(ss, name); + if (p.pkg) + reevaluate_reverse_installif_pkg(ss, p.pkg); + else + reevaluate_reverse_installif(ss, name); } static void select_package(struct apk_solver_state *ss, struct apk_name *name) @@ -823,10 +831,8 @@ static void cset_check_install_by_iif(struct apk_solver_state *ss, struct apk_na foreach_array_item(dep0, pkg->install_if) { struct apk_name *name0 = dep0->name; - if (!name0->ss.in_changeset) - return; - if (!apk_dep_is_provided(dep0, &name0->ss.chosen)) - return; + if (!name0->ss.in_changeset) return; + if (!apk_dep_is_provided(dep0, &name0->ss.chosen)) return; } cset_gen_name_change(ss, name); } @@ -848,6 +854,19 @@ static void cset_check_removal_by_iif(struct apk_solver_state *ss, struct apk_na } } +static void cset_check_by_reverse_iif(struct apk_solver_state *ss, struct apk_package *pkg, void (*cb)(struct apk_solver_state *ss, struct apk_name *)) +{ + struct apk_name **pname; + struct apk_dependency *d; + + if (!pkg) return; + foreach_array_item(pname, pkg->name->rinstall_if) + cb(ss, *pname); + foreach_array_item(d, pkg->provides) + foreach_array_item(pname, d->name->rinstall_if) + cb(ss, *pname); +} + static void cset_gen_name_remove_orphan(struct apk_solver_state *ss, struct apk_name *name) { struct apk_package *pkg = name->ss.chosen.pkg; @@ -861,7 +880,6 @@ static void cset_gen_name_remove_orphan(struct apk_solver_state *ss, struct apk_ static void cset_gen_name_change(struct apk_solver_state *ss, struct apk_name *name) { - struct apk_name **pname; struct apk_package *pkg, *opkg; struct apk_dependency *d; @@ -878,10 +896,7 @@ static void cset_gen_name_change(struct apk_solver_state *ss, struct apk_name *n cset_gen_name_remove_orphan(ss, d->name); opkg = pkg->name->ss.installed_pkg; - if (opkg) { - foreach_array_item(pname, opkg->name->rinstall_if) - cset_check_removal_by_iif(ss, *pname); - } + cset_check_by_reverse_iif(ss, opkg, cset_check_removal_by_iif); foreach_array_item(d, pkg->depends) cset_gen_dep(ss, pkg, d); @@ -889,8 +904,7 @@ static void cset_gen_name_change(struct apk_solver_state *ss, struct apk_name *n dbg_printf("Selecting: "PKG_VER_FMT"%s\n", PKG_VER_PRINTF(pkg), pkg->ss.pkg_selectable ? "" : " [NOT SELECTABLE]"); record_change(ss, opkg, pkg); - foreach_array_item(pname, pkg->name->rinstall_if) - cset_check_install_by_iif(ss, *pname); + cset_check_by_reverse_iif(ss, pkg, cset_check_install_by_iif); cset_track_deps_added(pkg); if (opkg) @@ -904,7 +918,7 @@ static void cset_gen_name_remove0(struct apk_package *pkg0, struct apk_dependenc static void cset_gen_name_remove(struct apk_solver_state *ss, struct apk_package *pkg) { - struct apk_name *name = pkg->name, **pname; + struct apk_name *name = pkg->name; if (pkg->ss.in_changeset || (name->ss.chosen.pkg != NULL && @@ -914,8 +928,8 @@ static void cset_gen_name_remove(struct apk_solver_state *ss, struct apk_package name->ss.in_changeset = 1; pkg->ss.in_changeset = 1; apk_pkg_foreach_reverse_dependency(pkg, APK_FOREACH_INSTALLED|APK_DEP_SATISFIES, cset_gen_name_remove0, ss); - foreach_array_item(pname, pkg->name->rinstall_if) - cset_check_removal_by_iif(ss, *pname); + cset_check_by_reverse_iif(ss, pkg, cset_check_removal_by_iif); + record_change(ss, pkg, NULL); cset_track_deps_removed(ss, pkg); } |