diff options
author | Timo Teräs <timo.teras@iki.fi> | 2017-12-12 15:14:25 +0200 |
---|---|---|
committer | Timo Teräs <timo.teras@iki.fi> | 2017-12-12 15:16:52 +0200 |
commit | 8e7fd3e06f300bd76b659db1164da1ee12f16870 (patch) | |
tree | 1ca6d6f34264d69026ae44f38cb5f41824a584fa /src | |
parent | 0700e8318fc5c88c5965320f6085f973e25dbeda (diff) | |
download | apk-tools-8e7fd3e06f300bd76b659db1164da1ee12f16870.tar.gz apk-tools-8e7fd3e06f300bd76b659db1164da1ee12f16870.tar.bz2 apk-tools-8e7fd3e06f300bd76b659db1164da1ee12f16870.tar.xz apk-tools-8e7fd3e06f300bd76b659db1164da1ee12f16870.zip |
solver: fix potential install_if processing failure, fixes #8237
In discovery phase, there was logic to not process packages
multiple times. However, that logic failed to account the package's
depth and install_if state for the name being processed. This
caused install_if processing failure in certain topologies of the
dependency graph. Adds also a test case that should catch this
issue reliably.
Diffstat (limited to 'src')
-rw-r--r-- | src/solver.c | 95 |
1 files changed, 49 insertions, 46 deletions
diff --git a/src/solver.c b/src/solver.c index 5698215..851e77e 100644 --- a/src/solver.c +++ b/src/solver.c @@ -184,55 +184,57 @@ static void discover_name(struct apk_solver_state *ss, struct apk_name *name) name->ss.no_iif = 1; foreach_array_item(p, name->providers) { struct apk_package *pkg = p->pkg; - if (pkg->ss.seen) - continue; + if (!pkg->ss.seen) { + pkg->ss.seen = 1; + pkg->ss.pinning_allowed = APK_DEFAULT_PINNING_MASK; + pkg->ss.pinning_preferred = APK_DEFAULT_PINNING_MASK; + pkg->ss.pkg_available = + (pkg->filename != NULL) || + (pkg->repos & db->available_repos & ~BIT(APK_REPOSITORY_CACHED)); + /* Package is in 'cached' repository if filename is provided, + * or it's a 'virtual' package with install_size zero */ + pkg->ss.pkg_selectable = + (pkg->repos & db->available_repos) || + pkg->cached_non_repository || + pkg->ipkg; + + /* Prune install_if packages that are no longer available, + * currently works only if SOLVERF_AVAILABLE is set in the + * global solver flags. */ + pkg->ss.iif_failed = + (pkg->install_if->num == 0) || + ((ss->solver_flags_inherit & APK_SOLVERF_AVAILABLE) && + !pkg->ss.pkg_available); + + repos = get_pkg_repos(db, pkg); + pkg->ss.tag_preferred = + (pkg->filename != NULL) || + (pkg->installed_size == 0) || + (repos & ss->default_repos); + pkg->ss.tag_ok = + pkg->ss.tag_preferred || + pkg->cached_non_repository || + pkg->ipkg; - pkg->ss.seen = 1; - - pkg->ss.pinning_allowed = APK_DEFAULT_PINNING_MASK; - pkg->ss.pinning_preferred = APK_DEFAULT_PINNING_MASK; - pkg->ss.pkg_available = - (pkg->filename != NULL) || - (pkg->repos & db->available_repos & ~BIT(APK_REPOSITORY_CACHED)); - /* Package is in 'cached' repository if filename is provided, - * or it's a 'virtual' package with install_size zero */ - pkg->ss.pkg_selectable = - (pkg->repos & db->available_repos) || - pkg->cached_non_repository || - pkg->ipkg; - - /* Prune install_if packages that are no longer available, - * currently works only if SOLVERF_AVAILABLE is set in the - * global solver flags. */ - pkg->ss.iif_failed = - (pkg->install_if->num == 0) || - ((ss->solver_flags_inherit & APK_SOLVERF_AVAILABLE) && - !pkg->ss.pkg_available); - name->ss.no_iif &= pkg->ss.iif_failed; + foreach_array_item(dep, pkg->depends) { + discover_name(ss, dep->name); + pkg->ss.max_dep_chain = max(pkg->ss.max_dep_chain, + dep->name->ss.max_dep_chain+1); + } - repos = get_pkg_repos(db, pkg); - pkg->ss.tag_preferred = - (pkg->filename != NULL) || - (pkg->installed_size == 0) || - (repos & ss->default_repos); - pkg->ss.tag_ok = - pkg->ss.tag_preferred || - pkg->cached_non_repository || - pkg->ipkg; - - foreach_array_item(dep, pkg->depends) { - discover_name(ss, dep->name); - pkg->ss.max_dep_chain = max(pkg->ss.max_dep_chain, - dep->name->ss.max_dep_chain+1); + dbg_printf("discover " PKG_VER_FMT ": tag_ok=%d, tag_pref=%d max_dep_chain=%d selectable=%d\n", + PKG_VER_PRINTF(pkg), + pkg->ss.tag_ok, + pkg->ss.tag_preferred, + pkg->ss.max_dep_chain, + pkg->ss.pkg_selectable); } + + name->ss.no_iif &= pkg->ss.iif_failed; 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 selectable=%d\n", - PKG_VER_PRINTF(pkg), - pkg->ss.tag_ok, - pkg->ss.tag_preferred, - pkg->ss.max_dep_chain, - pkg->ss.pkg_selectable); + dbg_printf("discover %s: max_dep_chain=%d no_iif=%d\n", + name->name, name->ss.max_dep_chain, name->ss.no_iif); } foreach_array_item(pname0, name->rinstall_if) discover_name(ss, *pname0); @@ -398,10 +400,11 @@ static void reconsider_name(struct apk_solver_state *ss, struct apk_name *name) foreach_array_item(dep, pkg->install_if) inherit_pinning_and_flags(ss, pkg, dep->name->ss.chosen.pkg); } - dbg_printf(" "PKG_VER_FMT": iif_triggered=%d iif_failed=%d\n", - PKG_VER_PRINTF(pkg), pkg->ss.iif_triggered, pkg->ss.iif_failed); has_iif |= pkg->ss.iif_triggered; no_iif &= pkg->ss.iif_failed; + dbg_printf(" "PKG_VER_FMT": iif_triggered=%d iif_failed=%d, no_iif=%d\n", + PKG_VER_PRINTF(pkg), pkg->ss.iif_triggered, pkg->ss.iif_failed, + no_iif); if (name->ss.requirers == 0) continue; |