From 8e7fd3e06f300bd76b659db1164da1ee12f16870 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timo=20Ter=C3=A4s?= Date: Tue, 12 Dec 2017 15:14:25 +0200 Subject: [PATCH] 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. --- src/solver.c | 91 +++++++++++++++++++++++--------------------- test/installif1.repo | 20 ++++++++++ test/installif5.test | 8 ++++ 3 files changed, 75 insertions(+), 44 deletions(-) create mode 100644 test/installif5.test 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; - pkg->ss.seen = 1; + /* 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); - 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; + 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; - /* 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; diff --git a/test/installif1.repo b/test/installif1.repo index 09b6760..3990209 100644 --- a/test/installif1.repo +++ b/test/installif1.repo @@ -46,3 +46,23 @@ I:1 D:app i:app bar +C:Q1/hQ3fH2AzuTwJVGOz+keypXhXKY= +P:dam +V:1 +S:1 +I:1 + +C:Q1/hQ3fH2AzuTwJVGfz+keypXhXKY= +P:dam-babel +V:1 +S:1 +I:1 +p:cmd:babel + +C:Q1/hQ3fH2AguTwJVGOz+keypXhXKY= +P:dam1-babel +V:1 +S:1 +I:1 +i:dam dam-babel +p:cmd:babel diff --git a/test/installif5.test b/test/installif5.test new file mode 100644 index 0000000..a0c707b --- /dev/null +++ b/test/installif5.test @@ -0,0 +1,8 @@ +@ARGS +--test-repo installif1.repo +add dam dam-babel cmd:babel +@EXPECT +(1/3) Installing dam-babel (1) +(2/3) Installing dam (1) +(3/3) Installing dam1-babel (1) +OK: 0 MiB in 0 packages