solver: fix inherited flags/pinning for install_if packages

noticeable fixes upgrading of packages which get pulled in only
by install_if rule. this also simplifies the inheritance calculation
for packages, as well as the place where it is done for install_if
triggered packages.
cute-signatures
Timo Teräs 2014-04-04 13:05:52 +03:00
parent ec1a3d57ab
commit 06071700c5
1 changed files with 28 additions and 56 deletions

View File

@ -39,7 +39,6 @@ struct apk_solver_state {
unsigned int solver_flags_inherit;
unsigned int pinning_inherit;
unsigned int default_repos;
unsigned prefer_pinning : 1;
};
static struct apk_provider provider_none = {
@ -78,29 +77,6 @@ static unsigned int get_pkg_repos(struct apk_database *db, struct apk_package *p
return pkg->repos | (pkg->ipkg ? db->repo_tags[pkg->ipkg->repository_tag].allowed_repos : 0);
}
static void foreach_rinstall_if_pkg(
struct apk_solver_state *ss, struct apk_package *pkg,
void (*cb)(struct apk_solver_state *ss, struct apk_package *rinstall_if, struct apk_package *parent_pkg))
{
struct apk_name *name = pkg->name, *name0, **pname0;
struct apk_dependency *dep;
struct apk_provider *p0;
foreach_array_item(pname0, pkg->name->rinstall_if) {
name0 = *pname0;
dbg_printf(PKG_VER_FMT ": rinstall_if %s\n", PKG_VER_PRINTF(pkg), name0->name);
foreach_array_item(p0, name0->providers) {
foreach_array_item(dep, p0->pkg->install_if) {
if (dep->name == name && apk_dep_is_provided(dep, p0)) {
/* pkg depends (via install_if) on pkg0 */
cb(ss, p0->pkg, pkg);
break;
}
}
}
}
}
static void mark_error(struct apk_solver_state *ss, struct apk_package *pkg)
{
if (pkg == NULL || pkg->ss.error)
@ -257,24 +233,35 @@ static void name_requirers_changed(struct apk_solver_state *ss, struct apk_name
queue_dirty(ss, name);
}
static void inherit_pinning(struct apk_solver_state *ss, struct apk_package *pkg, unsigned int pinning, int prefer)
static void inherit_pinning_and_flags(
struct apk_solver_state *ss, struct apk_package *pkg, struct apk_package *ppkg)
{
unsigned int repo_mask = apk_db_get_pinning_mask_repos(ss->db, pinning);
unsigned int repos = get_pkg_repos(ss->db, pkg);
pkg->ss.pinning_allowed |= pinning;
pkg->ss.tag_ok |= !!(repos & repo_mask);
if (prefer) {
pkg->ss.pinning_preferred = pinning;
if (ppkg != NULL) {
/* inherited */
pkg->ss.solver_flags |= ppkg->ss.solver_flags_inheritable;
pkg->ss.solver_flags_inheritable |= ppkg->ss.solver_flags_inheritable;
pkg->ss.pinning_allowed |= ppkg->ss.pinning_allowed;
} else {
/* world dependency */
pkg->ss.solver_flags |= ss->solver_flags_inherit;
pkg->ss.solver_flags_inheritable |= ss->solver_flags_inherit;
pkg->ss.pinning_allowed |= ss->pinning_inherit;
/* also prefer main pinnings */
pkg->ss.pinning_preferred = ss->pinning_inherit;
pkg->ss.tag_preferred = !!(repos & apk_db_get_pinning_mask_repos(ss->db, pkg->ss.pinning_preferred));
}
pkg->ss.tag_ok |= !!(repos & apk_db_get_pinning_mask_repos(ss->db, pkg->ss.pinning_allowed));
dbg_printf(PKG_VER_FMT ": tag_ok=%d, tag_pref=%d\n",
PKG_VER_PRINTF(pkg), pkg->ss.tag_ok, pkg->ss.tag_preferred);
}
static void apply_constraint(struct apk_solver_state *ss, struct apk_package *ppkg, struct apk_dependency *dep)
{
struct apk_name *name = dep->name;
struct apk_provider *p0;
unsigned int solver_flags_inherit = ss->solver_flags_inherit;
int is_provided;
dbg_printf(" apply_constraint: %s%s%s" BLOB_FMT "\n",
@ -298,16 +285,8 @@ static void apply_constraint(struct apk_solver_state *ss, struct apk_package *pp
if (unlikely(pkg0->ss.pkg_selectable && pkg0->ss.conflicts))
disqualify_package(ss, pkg0, "conflicting dependency");
if (is_provided) {
pkg0->ss.solver_flags |= solver_flags_inherit;
pkg0->ss.solver_flags_inheritable |= solver_flags_inherit;
inherit_pinning(ss, pkg0, ss->pinning_inherit, ss->prefer_pinning);
dbg_printf(PKG_VER_FMT ": tag_ok=%d, tag_pref=%d\n",
PKG_VER_PRINTF(pkg0),
pkg0->ss.tag_ok,
pkg0->ss.tag_preferred);
}
if (is_provided)
inherit_pinning_and_flags(ss, pkg0, ppkg);
}
}
@ -401,6 +380,12 @@ static void reconsider_name(struct apk_solver_state *ss, struct apk_name *name)
}
}
}
if (reevaluate_iif && pkg->ss.iif_triggered) {
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;
@ -586,11 +571,6 @@ static int compare_providers(struct apk_solver_state *ss,
return ffs(pkgB->repos) - ffs(pkgA->repos);
}
static void inherit_pinning_from_pkg(struct apk_solver_state *ss, struct apk_package *rinstall_if, struct apk_package *parent_pkg)
{
inherit_pinning(ss, rinstall_if, parent_pkg->ss.pinning_allowed, 0);
}
static void assign_name(struct apk_solver_state *ss, struct apk_name *name, struct apk_provider p)
{
struct apk_provider *p0;
@ -616,10 +596,6 @@ static void assign_name(struct apk_solver_state *ss, struct apk_name *name, stru
if (list_hashed(&name->ss.dirty_list))
list_del(&name->ss.dirty_list);
/* propagate pinning to install_if candidates */
if (p.pkg)
foreach_rinstall_if_pkg(ss, p.pkg, inherit_pinning_from_pkg);
/* disqualify all conflicting packages */
foreach_array_item(p0, name->providers) {
if (p0->pkg == p.pkg)
@ -643,6 +619,8 @@ static void select_package(struct apk_solver_state *ss, struct apk_name *name)
if (name->ss.requirers || name->ss.has_iif) {
foreach_array_item(p, name->providers) {
dbg_printf(" consider "PKG_VER_FMT" iif_triggered=%d, tag_ok=%d\n",
PKG_VER_PRINTF(p->pkg), p->pkg->ss.iif_triggered, p->pkg->ss.tag_ok);
/* Ensure valid pinning and install-if trigger */
if (name->ss.requirers == 0 &&
(!p->pkg->ss.iif_triggered ||
@ -668,12 +646,8 @@ static void select_package(struct apk_solver_state *ss, struct apk_name *name)
foreach_array_item(d, pkg->provides)
assign_name(ss, d->name, APK_PROVIDER_FROM_PROVIDES(pkg, d));
ss->solver_flags_inherit = pkg->ss.solver_flags_inheritable;
ss->pinning_inherit = pkg->ss.pinning_allowed;
foreach_array_item(d, pkg->depends)
apply_constraint(ss, pkg, d);
ss->solver_flags_inherit = 0;
ss->pinning_inherit = 0;
} else {
dbg_printf("selecting: %s [unassigned]\n", name->name);
assign_name(ss, name, provider_none);
@ -913,7 +887,6 @@ restart:
list_init(&ss->unresolved_head);
dbg_printf("discovering world\n");
ss->prefer_pinning = 1;
ss->solver_flags_inherit = solver_flags;
foreach_array_item(d, world) {
if (!d->broken)
@ -928,7 +901,6 @@ restart:
}
ss->solver_flags_inherit = 0;
ss->pinning_inherit = 0;
ss->prefer_pinning = 0;
dbg_printf("applying world [finished]\n");
do {