diff options
author | Timo Teräs <timo.teras@iki.fi> | 2022-12-20 21:50:37 +0200 |
---|---|---|
committer | Timo Teräs <timo.teras@iki.fi> | 2022-12-20 22:41:14 +0200 |
commit | 0726606de2db6a0e75bc4ebe1a010122d0367f0f (patch) | |
tree | 4f28f6c973f317b5142f307f775192619fb8d614 | |
parent | 8d0962ca0cb076b3a5dafacc10c6a411b1e2d444 (diff) | |
download | apk-tools-0726606de2db6a0e75bc4ebe1a010122d0367f0f.tar.gz apk-tools-0726606de2db6a0e75bc4ebe1a010122d0367f0f.tar.bz2 apk-tools-0726606de2db6a0e75bc4ebe1a010122d0367f0f.tar.xz apk-tools-0726606de2db6a0e75bc4ebe1a010122d0367f0f.zip |
solver, commit: handle install_if via provided names correctly
Correctly trigger install_ifs for provided names also. And fix the
construction of error messages concerning such install_if packages.
ref #10843
-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 4b4f588..7ca39d3 100644 --- a/src/commit.c +++ b/src/commit.c @@ -383,9 +383,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, }; @@ -608,34 +609,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); } } @@ -645,7 +683,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 06dfb6b..3a8f6e6 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) @@ -683,7 +688,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) @@ -822,10 +830,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); } @@ -847,6 +853,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; @@ -860,7 +879,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; @@ -877,10 +895,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); @@ -888,8 +903,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) @@ -903,7 +917,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 && @@ -913,8 +927,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); } |