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.
cute-signatures
Timo Teräs 2017-12-12 15:14:25 +02:00
parent 0700e8318f
commit 8e7fd3e06f
3 changed files with 75 additions and 44 deletions

View File

@ -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;

View File

@ -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

8
test/installif5.test Normal file
View File

@ -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