summaryrefslogtreecommitdiff
path: root/src/solver.c
diff options
context:
space:
mode:
authorTimo Teräs <timo.teras@iki.fi>2012-02-27 10:26:30 +0200
committerTimo Teräs <timo.teras@iki.fi>2012-02-27 10:26:30 +0200
commit1074c4d32680e2a80dc2e2266f8499bbba6acbc0 (patch)
tree12046ae21c6fe45a98b5f39fc33e0ca5977eedce /src/solver.c
parentf0f2029eb1b20b8515fd45fac5ff07d58c76632e (diff)
downloadapk-tools-1074c4d32680e2a80dc2e2266f8499bbba6acbc0.tar.gz
apk-tools-1074c4d32680e2a80dc2e2266f8499bbba6acbc0.tar.bz2
apk-tools-1074c4d32680e2a80dc2e2266f8499bbba6acbc0.tar.xz
apk-tools-1074c4d32680e2a80dc2e2266f8499bbba6acbc0.zip
solver: have most inherited things per-package and clean ups
Required for provides support as package might be pulled in via non-primary package name. This allows relatively easily to pass through inherited flags via the provided names. ref #574.
Diffstat (limited to 'src/solver.c')
-rw-r--r--src/solver.c324
1 files changed, 168 insertions, 156 deletions
diff --git a/src/solver.c b/src/solver.c
index 2c33a67..11c1862 100644
--- a/src/solver.c
+++ b/src/solver.c
@@ -86,38 +86,40 @@ struct apk_decision {
};
struct apk_package_state {
+ /* set on startup */
unsigned int topology_soft;
+ unsigned short allowed_pinning_maybe;
+
+ /* dynamic */
+ unsigned short allowed_pinning;
+ unsigned short inherited_pinning[APK_MAX_TAGS];
+ unsigned short inherited_upgrade;
+ unsigned short inherited_reinstall;
+
unsigned short conflicts;
unsigned char preference;
unsigned handle_install_if : 1;
unsigned locked : 1;
+
+ unsigned solver_flags_maybe : 4;
};
#define CHOSEN_NONE (struct apk_provider) { .pkg = NULL, .version = NULL }
struct apk_name_state {
+ /* dynamic */
struct list_head unsolved_list;
struct apk_name *name;
struct apk_provider chosen;
+ unsigned int last_touched_decision;
unsigned short requirers;
unsigned short install_ifs;
-
- /* set on startup */
unsigned short preferred_pinning;
- unsigned short maybe_pinning;
-
- /* dynamic */
- unsigned int last_touched_decision;
- unsigned short allowed_pinning;
- unsigned short inherited_pinning[APK_MAX_TAGS];
- unsigned short inherited_upgrade;
- unsigned short inherited_reinstall;
/* one time prepare/finish flags */
unsigned solver_flags_local : 4;
- unsigned solver_flags_local_mask : 4;
- unsigned solver_flags_maybe : 4;
+ unsigned solver_flags_inheritable : 4;
unsigned decision_counted : 1;
unsigned originally_installed : 1;
@@ -173,6 +175,7 @@ static void addscore(struct apk_score *a, struct apk_score *b)
a->score += b->score;
ASSERT(a->conflicts >= orig.conflicts, "Conflict overflow");
ASSERT(a->non_preferred_actions >= orig.non_preferred_actions, "Preferred action overflow");
+ ASSERT(a->non_preferred_pinnings >= orig.non_preferred_pinnings, "Preferred pinning overflow");
ASSERT(a->preference >= orig.preference, "Preference overflow");
}
@@ -182,6 +185,7 @@ static void subscore(struct apk_score *a, struct apk_score *b)
a->score -= b->score;
ASSERT(a->conflicts <= orig.conflicts, "Conflict underflow");
ASSERT(a->non_preferred_actions <= orig.non_preferred_actions, "Preferred action underflow");
+ ASSERT(a->non_preferred_pinnings <= orig.non_preferred_pinnings, "Preferred pinning overflow");
ASSERT(a->preference <= orig.preference, "Preference underflow");
}
#else
@@ -231,6 +235,13 @@ static struct apk_package_state *pkg_to_ps(struct apk_package *pkg)
return (struct apk_package_state*) pkg->state_ptr;
}
+static struct apk_package_state *pkg_to_ps_alloc(struct apk_package *pkg)
+{
+ if (pkg->state_ptr == NULL)
+ pkg->state_ptr = calloc(1, sizeof(struct apk_package_state));
+ return pkg_to_ps(pkg);
+}
+
static struct apk_name_state *name_to_ns(struct apk_name *name)
{
return (struct apk_name_state*) name->state_ptr;
@@ -272,8 +283,8 @@ static inline int pkg_available(struct apk_database *db, struct apk_package *pkg
}
static void foreach_dependency_pkg(
- struct apk_solver_state *ss, struct apk_dependency_array *depends,
- void (*cb)(struct apk_solver_state *ss, struct apk_package *dependency))
+ struct apk_solver_state *ss, struct apk_package *parent_package, struct apk_dependency_array *depends,
+ void (*cb)(struct apk_solver_state *ss, struct apk_package *dependency, struct apk_package *parent_package))
{
int i, j;
@@ -289,14 +300,14 @@ static void foreach_dependency_pkg(
if (!apk_dep_is_provided(dep, p0))
continue;
- cb(ss, p0->pkg);
+ cb(ss, p0->pkg, parent_package);
}
}
}
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))
+ void (*cb)(struct apk_solver_state *ss, struct apk_package *rinstall_if, struct apk_package *parent_pkg))
{
struct apk_name *name = pkg->name;
int i, j, k;
@@ -321,7 +332,7 @@ static void foreach_rinstall_if_pkg(
continue;
/* pkg depends (via install_if) on pkg0 */
- cb(ss, p0->pkg);
+ cb(ss, p0->pkg, pkg);
}
}
}
@@ -362,17 +373,17 @@ static int get_topology_score(
/* available preferred */
if ((pkg->repos == 0) && ns->has_available_pkgs)
score.non_preferred_actions++;
- } else if (ns->inherited_reinstall ||
+ } else if (ps->inherited_reinstall ||
(((ns->solver_flags_local|ss->solver_flags) & APK_SOLVERF_REINSTALL))) {
/* reinstall requested, but not available */
if (!pkg_available(ss->db, pkg))
score.non_preferred_actions++;
- } else if (ns->inherited_upgrade ||
+ } else if (ps->inherited_upgrade ||
((ns->solver_flags_local|ss->solver_flags) & APK_SOLVERF_UPGRADE)) {
/* upgrading - score is just locked here */
- } else if ((ns->inherited_upgrade == 0) &&
+ } else if ((ps->inherited_upgrade == 0) &&
((ns->solver_flags_local|ss->solver_flags) & APK_SOLVERF_UPGRADE) == 0 &&
- ((ns->solver_flags_maybe & APK_SOLVERF_UPGRADE) == 0 || (ps->locked))) {
+ ((ps->solver_flags_maybe & APK_SOLVERF_UPGRADE) == 0 || (ps->locked))) {
/* not upgrading: it is not preferred to change package */
if (pkg->ipkg == NULL && ns->originally_installed)
score.non_preferred_actions++;
@@ -389,8 +400,8 @@ static int get_topology_score(
if (!(repos & preferred_repos))
score.non_preferred_pinnings++;
- if (ps->locked || (ns->allowed_pinning | ns->maybe_pinning) == ns->allowed_pinning) {
- allowed_pinning = ns->allowed_pinning | preferred_pinning | APK_DEFAULT_PINNING_MASK;
+ if (ps->locked || (ps->allowed_pinning | ps->allowed_pinning_maybe) == ps->allowed_pinning) {
+ allowed_pinning = ps->allowed_pinning | preferred_pinning | APK_DEFAULT_PINNING_MASK;
allowed_repos = get_pinning_mask_repos(ss->db, allowed_pinning);
if (!(repos & allowed_repos)) {
if (sticky_installed)
@@ -493,24 +504,24 @@ static void count_name(struct apk_solver_state *ss, struct apk_name *name)
}
}
-static void sort_hard_dependencies(struct apk_solver_state *ss, struct apk_package *pkg)
+static void sort_hard_dependencies(struct apk_solver_state *ss,
+ struct apk_package *pkg,
+ struct apk_package *parent_pkg)
{
struct apk_package_state *ps;
int i;
- if (pkg->state_ptr == NULL)
- pkg->state_ptr = calloc(1, sizeof(struct apk_package_state));
-
- ps = pkg_to_ps(pkg);
+ ps = pkg_to_ps_alloc(pkg);
if (ps->topology_soft)
return;
pkg->topology_hard = -1;
ps->topology_soft = -1;
calculate_pkg_preference(pkg);
+
/* Consider hard dependencies only */
- foreach_dependency_pkg(ss, pkg->depends, sort_hard_dependencies);
- foreach_dependency_pkg(ss, pkg->install_if, sort_hard_dependencies);
+ foreach_dependency_pkg(ss, pkg, pkg->depends, sort_hard_dependencies);
+ foreach_dependency_pkg(ss, pkg, pkg->install_if, sort_hard_dependencies);
ss->max_decisions++;
count_name(ss, pkg->name);
@@ -522,20 +533,28 @@ static void sort_hard_dependencies(struct apk_solver_state *ss, struct apk_packa
PKG_VER_PRINTF(pkg), pkg->topology_hard);
}
-static void sort_soft_dependencies(struct apk_solver_state *ss, struct apk_package *pkg)
+static void sort_soft_dependencies(struct apk_solver_state *ss,
+ struct apk_package *pkg,
+ struct apk_package *parent_pkg)
{
struct apk_package_state *ps;
+ struct apk_package_state *parent_ps;
- sort_hard_dependencies(ss, pkg);
+ sort_hard_dependencies(ss, pkg, parent_pkg);
ps = pkg_to_ps(pkg);
if (ps->topology_soft != pkg->topology_hard)
return;
ps->topology_soft = -1;
+ /* Update state */
+ parent_ps = pkg_to_ps(parent_pkg);
+ ps->allowed_pinning_maybe |= parent_ps->allowed_pinning_maybe;
+ ps->solver_flags_maybe |= parent_ps->solver_flags_maybe;
+
/* Soft reverse dependencies aka. install_if */
foreach_rinstall_if_pkg(ss, pkg, sort_hard_dependencies);
- foreach_dependency_pkg(ss, pkg->depends, sort_soft_dependencies);
+ foreach_dependency_pkg(ss, pkg, pkg->depends, sort_soft_dependencies);
/* Assign a topology sorting order */
ps->topology_soft = ++ss->num_topology_positions;
@@ -543,54 +562,33 @@ static void sort_soft_dependencies(struct apk_solver_state *ss, struct apk_packa
PKG_VER_PRINTF(pkg), ps->topology_soft);
}
-static void recalculate_maybe(struct apk_solver_state *ss, struct apk_name *name,
- unsigned short flags, unsigned short pinning)
+static void sort_name(struct apk_solver_state *ss, struct apk_name *name)
{
struct apk_name_state *ns = name_to_ns_alloc(name);
- int propagate = FALSE;
int i, j;
- if ((ns->maybe_pinning & pinning) != pinning) {
- ns->maybe_pinning |= pinning;
- propagate = TRUE;
- }
- if ((ns->solver_flags_maybe & flags) != flags) {
- ns->solver_flags_maybe |= flags;
- propagate = TRUE;
- }
- if (!propagate)
- return;
+ count_name(ss, name);
for (i = 0; i < name->providers->num; i++) {
struct apk_package *pkg = name->providers->item[i].pkg;
+ struct apk_package_state *ps = pkg_to_ps_alloc(pkg);
+ unsigned short allowed_pinning;
- for (j = 0; j < pkg->depends->num; j++) {
- struct apk_dependency *dep = &pkg->depends->item[j];
- struct apk_name *name0 = dep->name;
- recalculate_maybe(ss, name0, flags, pinning);
+ ps->allowed_pinning |= ns->preferred_pinning;
+ ps->allowed_pinning_maybe |= ns->preferred_pinning;
+
+ allowed_pinning = ps->allowed_pinning;
+ for (j = 0; allowed_pinning; j++) {
+ if (!(allowed_pinning & BIT(j)))
+ continue;
+ allowed_pinning &= ~BIT(j);
+ ps->inherited_pinning[j]++;
}
- }
- for (i = 0; i < name->rinstall_if->num; i++) {
- struct apk_name *name0 = name->rinstall_if->item[i];
- recalculate_maybe(ss, name0, flags, pinning);
+ sort_soft_dependencies(ss, name->providers->item[i].pkg, pkg);
}
}
-static void sort_name(struct apk_solver_state *ss, struct apk_name *name)
-{
- struct apk_name_state *ns = name_to_ns_alloc(name);
- int i;
-
- for (i = 0; i < name->providers->num; i++)
- sort_soft_dependencies(ss, name->providers->item[i].pkg);
-
- count_name(ss, name);
- recalculate_maybe(ss, name,
- ns->solver_flags_local & ns->solver_flags_local_mask,
- ns->maybe_pinning);
-}
-
static void foreach_dependency(struct apk_solver_state *ss, struct apk_dependency_array *deps,
void (*func)(struct apk_solver_state *ss, struct apk_dependency *dep))
{
@@ -668,80 +666,94 @@ static void demote_name(struct apk_solver_state *ss, struct apk_name *name)
}
}
-static void inherit_name_state(struct apk_database *db, struct apk_name *to, struct apk_name *from)
+static int inherit_package_state(struct apk_database *db, struct apk_package *to, struct apk_package *from)
{
- struct apk_name_state *tns = name_to_ns(to);
- struct apk_name_state *fns = name_to_ns(from);
- int i;
+ struct apk_package_state *tps = pkg_to_ps(to);
+ struct apk_name_state *fns = name_to_ns(from->name);
+ struct apk_package_state *fps = pkg_to_ps(from);
+ int i, changed = 0;
- if ((fns->solver_flags_local & fns->solver_flags_local_mask & APK_SOLVERF_REINSTALL) ||
- fns->inherited_reinstall)
- tns->inherited_reinstall++;
+ if ((fns->solver_flags_inheritable & APK_SOLVERF_REINSTALL) ||
+ fps->inherited_reinstall) {
+ tps->inherited_reinstall++;
+ changed = 1;
+ }
- if ((fns->solver_flags_local & fns->solver_flags_local_mask & APK_SOLVERF_UPGRADE) ||
- fns->inherited_upgrade)
- tns->inherited_upgrade++;
+ if ((fns->solver_flags_inheritable & APK_SOLVERF_UPGRADE) ||
+ fps->inherited_upgrade) {
+ tps->inherited_upgrade++;
+ changed = 1;
+ }
- if (fns->allowed_pinning) {
- for (i = 0; i < db->num_repo_tags; i++) {
- if (!(fns->allowed_pinning & BIT(i)))
+ if (fps->allowed_pinning) {
+ unsigned short allowed_pinning = fps->allowed_pinning;
+ for (i = 0; allowed_pinning && i < db->num_repo_tags; i++) {
+ if (!(allowed_pinning & BIT(i)))
continue;
- if (tns->inherited_pinning[i]++ == 0)
- tns->allowed_pinning |= BIT(i);
+ allowed_pinning &= ~BIT(i);
+ if (tps->inherited_pinning[i]++ == 0) {
+ tps->allowed_pinning |= BIT(i);
+ changed = 1;
+ }
}
}
+
+ return changed;
}
-static void uninherit_name_state(struct apk_database *db, struct apk_name *to, struct apk_name *from)
+static void uninherit_package_state(struct apk_database *db, struct apk_package *to, struct apk_package *from)
{
- struct apk_name_state *tns = name_to_ns(to);
- struct apk_name_state *fns = name_to_ns(from);
+ struct apk_package_state *tps = pkg_to_ps(to);
+ struct apk_name_state *fns = name_to_ns(from->name);
+ struct apk_package_state *fps = pkg_to_ps(from);
int i;
- if ((fns->solver_flags_local & fns->solver_flags_local_mask & APK_SOLVERF_REINSTALL) ||
- fns->inherited_reinstall)
- tns->inherited_reinstall--;
+ if ((fns->solver_flags_inheritable & APK_SOLVERF_REINSTALL) ||
+ fps->inherited_reinstall)
+ tps->inherited_reinstall--;
- if ((fns->solver_flags_local & fns->solver_flags_local_mask & APK_SOLVERF_UPGRADE) ||
- fns->inherited_upgrade)
- tns->inherited_upgrade--;
+ if ((fns->solver_flags_inheritable & APK_SOLVERF_UPGRADE) ||
+ fps->inherited_upgrade)
+ tps->inherited_upgrade--;
- if (fns->allowed_pinning) {
- for (i = 0; i < db->num_repo_tags; i++) {
- if (!(fns->allowed_pinning & BIT(i)))
+ if (fps->allowed_pinning) {
+ unsigned short allowed_pinning = fps->allowed_pinning;
+ for (i = 0; allowed_pinning && i < db->num_repo_tags; i++) {
+ if (!(allowed_pinning & BIT(i)))
continue;
- if (--tns->inherited_pinning[i] == 0)
- tns->allowed_pinning &= ~BIT(i);
+ allowed_pinning &= ~BIT(i);
+ if (--tps->inherited_pinning[i] == 0)
+ tps->allowed_pinning &= ~BIT(i);
}
}
}
static void trigger_install_if(struct apk_solver_state *ss,
- struct apk_package *pkg)
+ struct apk_package *pkg,
+ struct apk_package *parent_pkg)
{
if (install_if_missing(ss, pkg) == 0) {
- struct apk_name *name0 = decision_to_name(&ss->decisions[ss->num_decisions]);
struct apk_name_state *ns = name_to_ns(pkg->name);
dbg_printf("trigger_install_if: " PKG_VER_FMT " triggered\n",
PKG_VER_PRINTF(pkg));
ns->install_ifs++;
- inherit_name_state(ss->db, pkg->name, name0);
+ inherit_package_state(ss->db, pkg, parent_pkg);
promote_name(ss, pkg->name);
}
}
static void untrigger_install_if(struct apk_solver_state *ss,
- struct apk_package *pkg)
+ struct apk_package *pkg,
+ struct apk_package *parent_pkg)
{
if (install_if_missing(ss, pkg) != 1) {
- struct apk_name *name0 = decision_to_name(&ss->decisions[ss->num_decisions]);
struct apk_name_state *ns = name_to_ns(pkg->name);
dbg_printf("untrigger_install_if: " PKG_VER_FMT " no longer triggered\n",
PKG_VER_PRINTF(pkg));
ns->install_ifs--;
- uninherit_name_state(ss->db, pkg->name, name0);
+ uninherit_package_state(ss->db, pkg, parent_pkg);
demote_name(ss, pkg->name);
}
}
@@ -983,14 +995,16 @@ static int next_branch(struct apk_solver_state *ss)
static void apply_constraint(struct apk_solver_state *ss, struct apk_dependency *dep)
{
- struct apk_name *name = dep->name;
- struct apk_name_state *ns = name_to_ns(name);
- int i, strength;
+ struct apk_package *requirer_pkg = NULL;
+ struct apk_name *name = dep->name, *requirer_name = NULL;
+ struct apk_name_state *ns = name_to_ns(name), *requirer_ns = NULL;
+ int i, strength, changed = 0;
if (ss->num_decisions > 0) {
- struct apk_name *name0 = decision_to_name(&ss->decisions[ss->num_decisions]);
- struct apk_name_state *ns0 = name_to_ns(name0);
- strength = ns0->requirers ?: 1;
+ requirer_name = decision_to_name(&ss->decisions[ss->num_decisions]);
+ requirer_pkg = decision_to_pkg(&ss->decisions[ss->num_decisions]);
+ requirer_ns = name_to_ns(requirer_name);
+ strength = requirer_ns->requirers ?: 1;
} else {
strength = 1;
}
@@ -1006,29 +1020,13 @@ static void apply_constraint(struct apk_solver_state *ss, struct apk_dependency
ss->score.conflicts += strength;
return;
}
+
if (name->providers->num == 0) {
if (!dep->optional)
ss->score.conflicts += strength;
return;
}
- if (dep->repository_tag) {
- dbg_printf("%s: adding pinnings %d\n",
- dep->name->name, dep->repository_tag);
- ns->preferred_pinning = BIT(dep->repository_tag);
- ns->allowed_pinning |= BIT(dep->repository_tag);
- ns->inherited_pinning[dep->repository_tag]++;
- recalculate_maybe(ss, name, 0, ns->allowed_pinning);
- }
-
- if (ss->num_decisions > 0) {
- struct apk_name *name0 = decision_to_name(&ss->decisions[ss->num_decisions]);
- dbg_printf("%s: inheriting flags and pinning from %s\n",
- name->name, name0->name);
- inherit_name_state(ss->db, name, name0);
- ns->last_touched_decision = ss->num_decisions;
- }
-
for (i = 0; i < name->providers->num; i++) {
struct apk_provider *p0 = &name->providers->item[i];
struct apk_package *pkg0 = p0->pkg;
@@ -1043,9 +1041,17 @@ static void apply_constraint(struct apk_solver_state *ss, struct apk_dependency
dbg_printf(PKG_VER_FMT ": conflicts++ -> %d\n",
PKG_VER_PRINTF(pkg0),
ps0->conflicts);
+ changed |= 1;
+ } else if (requirer_pkg != NULL) {
+ dbg_printf("%s: inheriting flags and pinning from %s\n",
+ name->name, name0->name);
+ changed |= inherit_package_state(ss->db, pkg0, requirer_pkg);
}
}
+ if (changed)
+ ns->last_touched_decision = ss->num_decisions;
+
if (!dep->optional)
ns->requirers += strength;
@@ -1054,14 +1060,16 @@ static void apply_constraint(struct apk_solver_state *ss, struct apk_dependency
static void undo_constraint(struct apk_solver_state *ss, struct apk_dependency *dep)
{
- struct apk_name *name = dep->name;
- struct apk_name_state *ns = name_to_ns(name);
+ struct apk_name *name = dep->name, *requirer_name = NULL;
+ struct apk_name_state *ns = name_to_ns(name), *requirer_ns = NULL;
+ struct apk_package *requirer_pkg = NULL;
int i, strength;
if (ss->num_decisions > 0) {
- struct apk_name *name0 = decision_to_name(&ss->decisions[ss->num_decisions]);
- struct apk_name_state *ns0 = name_to_ns(name0);
- strength = ns0->requirers ?: 1;
+ requirer_name = decision_to_name(&ss->decisions[ss->num_decisions]);
+ requirer_pkg = decision_to_pkg(&ss->decisions[ss->num_decisions]);
+ requirer_ns = name_to_ns(requirer_name);
+ strength = requirer_ns->requirers ?: 1;
} else {
strength = 1;
}
@@ -1084,19 +1092,6 @@ static void undo_constraint(struct apk_solver_state *ss, struct apk_dependency *
return;
}
- if (ss->num_decisions > 0) {
- struct apk_name *name0 = decision_to_name(&ss->decisions[ss->num_decisions]);
- dbg_printf("%s: uninheriting flags and pinning from %s\n",
- name->name, name0->name);
- uninherit_name_state(ss->db, name, name0);
- /* note: for perfection, we should revert here to the
- * *previous* value, but that'd require keeping track
- * of it which would require dynamic memory allocations.
- * in practice this is good enough. */
- if (ns->last_touched_decision > ss->num_decisions)
- ns->last_touched_decision = ss->num_decisions;
- }
-
for (i = 0; i < name->providers->num; i++) {
struct apk_provider *p0 = &name->providers->item[i];
struct apk_package *pkg0 = p0->pkg;
@@ -1111,9 +1106,20 @@ static void undo_constraint(struct apk_solver_state *ss, struct apk_dependency *
dbg_printf(PKG_VER_FMT ": conflicts-- -> %d\n",
PKG_VER_PRINTF(pkg0),
ps0->conflicts);
+ } else if (requirer_pkg != NULL) {
+ dbg_printf("%s: uninheriting flags and pinning from %s\n",
+ name->name, name0->name);
+ uninherit_package_state(ss->db, pkg0, requirer_pkg);
}
}
+ /* note: for perfection, we should revert here to the
+ * *previous* value, but that'd require keeping track
+ * of it which would require dynamic memory allocations.
+ * in practice this is good enough. */
+ if (ns->last_touched_decision > ss->num_decisions)
+ ns->last_touched_decision = ss->num_decisions;
+
if (!dep->optional)
ns->requirers -= strength;
@@ -1193,6 +1199,7 @@ static int expand_branch(struct apk_solver_state *ss)
struct apk_name *name;
struct apk_name_state *ns;
struct apk_package *pkg0 = NULL;
+ struct apk_package_state *ps0;
unsigned int r, topology0 = 0;
unsigned short allowed_pinning, preferred_pinning;
unsigned int allowed_repos;
@@ -1222,6 +1229,7 @@ static int expand_branch(struct apk_solver_state *ss)
/* someone needs to provide this name -- find next eligible
* provider candidate */
+ ps0 = pkg_to_ps(pkg0);
name = pkg0->name;
ns = name_to_ns(name);
@@ -1241,7 +1249,7 @@ static int expand_branch(struct apk_solver_state *ss)
SCORE_PRINTF(&ss->best_score));
preferred_pinning = ns->preferred_pinning ?: APK_DEFAULT_PINNING_MASK;
- allowed_pinning = ns->allowed_pinning | preferred_pinning | APK_DEFAULT_PINNING_MASK;
+ allowed_pinning = ps0->allowed_pinning | preferred_pinning | APK_DEFAULT_PINNING_MASK;
allowed_repos = get_pinning_mask_repos(ss->db, allowed_pinning);
if ((pkg0->repos != 0) && !(pkg0->repos & allowed_repos)) {
@@ -1295,6 +1303,7 @@ static void record_solution(struct apk_solver_state *ss)
for (i = ss->num_decisions; i > 0; i--) {
struct apk_decision *d = &ss->decisions[i];
struct apk_package *pkg = decision_to_pkg(d);
+ struct apk_package_state *ps;
unsigned short pinning;
unsigned int repos;
@@ -1314,13 +1323,14 @@ static void record_solution(struct apk_solver_state *ss)
continue;
ns = name_to_ns(pkg->name);
- pinning = ns->allowed_pinning | ns->preferred_pinning | APK_DEFAULT_PINNING_MASK;
+ ps = pkg_to_ps(pkg);
+ pinning = ps->allowed_pinning | ns->preferred_pinning | APK_DEFAULT_PINNING_MASK;
repos = pkg->repos | (pkg->ipkg ? db->repo_tags[pkg->ipkg->repository_tag].allowed_repos : 0);
ASSERT(n < ss->assigned_names, "Name assignment overflow\n");
ss->best_solution->item[n++] = (struct apk_solution_entry){
.pkg = pkg,
- .reinstall = ns->inherited_reinstall ||
+ .reinstall = ps->inherited_reinstall ||
((ns->solver_flags_local | ss->solver_flags) & APK_SOLVERF_REINSTALL),
.repository_tag = get_tag(db, pinning, repos),
};
@@ -1453,7 +1463,7 @@ void apk_solver_set_name_flags(struct apk_name *name,
{
struct apk_name_state *ns = name_to_ns_alloc(name);
ns->solver_flags_local = solver_flags;
- ns->solver_flags_local_mask = solver_flags_inheritable;
+ ns->solver_flags_inheritable = solver_flags & solver_flags_inheritable;
}
static void apk_solver_free(struct apk_database *db)
@@ -1481,19 +1491,21 @@ int apk_solver_solve(struct apk_database *db,
list_init(&ss->unsolved_list_head);
for (i = 0; i < world->num; i++) {
- sort_name(ss, world->item[i].name);
- name_to_ns(world->item[i].name)->in_world_dependency = 1;
+ struct apk_dependency *dep = &world->item[i];
+ struct apk_name *name = dep->name;
+ struct apk_name_state *ns = name_to_ns_alloc(name);
+
+ ns->in_world_dependency = 1;
+
+ dbg_printf("%s: adding pinnings %d\n", name->name, dep->repository_tag);
+ ns->preferred_pinning = BIT(dep->repository_tag);
+
+ sort_name(ss, name);
}
list_for_each_entry(ipkg, &db->installed.packages, installed_pkgs_list) {
sort_name(ss, ipkg->pkg->name);
name_to_ns(ipkg->pkg->name)->originally_installed = 1;
}
-#if 0
- for (i = 0; i < world->num; i++)
- prepare_name(ss, world->item[i].name);
- list_for_each_entry(ipkg, &db->installed.packages, installed_pkgs_list)
- prepare_name(ss, ipkg->pkg->name);
-#endif
ss->max_decisions ++;
ss->decisions = calloc(1, sizeof(struct apk_decision[ss->max_decisions]));