diff options
author | Timo Teräs <timo.teras@iki.fi> | 2012-02-29 08:53:43 +0200 |
---|---|---|
committer | Timo Teräs <timo.teras@iki.fi> | 2012-02-29 08:53:43 +0200 |
commit | f27f194d92c952da337205c0176f68a13f0cba7c (patch) | |
tree | ac6d7d92c024589003b7e30493ad0d3ff0662c0d /src/solver.c | |
parent | 2e8fe783a11bcd6ccc7f1a08d8b38eb76d87dc35 (diff) | |
download | apk-tools-f27f194d92c952da337205c0176f68a13f0cba7c.tar.gz apk-tools-f27f194d92c952da337205c0176f68a13f0cba7c.tar.bz2 apk-tools-f27f194d92c952da337205c0176f68a13f0cba7c.tar.xz apk-tools-f27f194d92c952da337205c0176f68a13f0cba7c.zip |
solver, test: make conflicts unconditional
Solver will now never report partial solution where a conflict
constraint is not satisfied. The is because with --force we might
install the partial solution; and if conflicted packages were to
be installed we might have extra trouble.
Diffstat (limited to 'src/solver.c')
-rw-r--r-- | src/solver.c | 49 |
1 files changed, 36 insertions, 13 deletions
diff --git a/src/solver.c b/src/solver.c index b50380b..7420359 100644 --- a/src/solver.c +++ b/src/solver.c @@ -96,7 +96,9 @@ struct apk_package_state { unsigned short inherited_upgrade; unsigned short inherited_reinstall; - unsigned short conflicts; + unsigned short must_not; + unsigned short incompat_dep; + unsigned char preference; unsigned handle_install_if : 1; unsigned allowed : 1; @@ -152,6 +154,7 @@ struct apk_solver_state { struct apk_score best_score; unsigned solver_flags : 4; + unsigned impossible_state : 1; }; typedef enum { @@ -367,7 +370,7 @@ static int get_topology_score( int score_locked = TRUE, sticky_installed = FALSE; score = (struct apk_score) { - .conflicts = ps->conflicts, + .conflicts = ps->incompat_dep, .preference = ps->preference, }; @@ -796,6 +799,7 @@ static solver_result_t apply_decision(struct apk_solver_state *ss, struct apk_score score; int i; + ss->impossible_state = 0; ns->name_touched = 1; if (pkg != NULL) { struct apk_package_state *ps = pkg_to_ps(pkg); @@ -855,6 +859,13 @@ static solver_result_t apply_decision(struct apk_solver_state *ss, } } + if (ss->impossible_state) { + dbg_printf("%s: %s impossible constraints\n", + name->name, + (d->type == DECISION_ASSIGN) ? "ASSIGN" : "EXCLUDE"); + return SOLVERR_PRUNED; + } + if (cmpscore(&ss->score, &ss->best_score) >= 0) { dbg_printf("%s: %s penalty too big: "SCORE_FMT">="SCORE_FMT"\n", name->name, @@ -1024,13 +1035,18 @@ static void apply_constraint(struct apk_solver_state *ss, struct apk_dependency else dbg_printf("%s: locked to empty\n", name->name); - if (!apk_dep_is_provided(dep, &ns->chosen)) + if (!apk_dep_is_provided(dep, &ns->chosen)) { + dbg_printf("%s: constraint violation %d\n", + name->name, strength); ss->score.conflicts += strength; + if (dep->conflict) + ss->impossible_state = 1; + } return; } if (name->providers->num == 0) { - if (!dep->optional) + if (!dep->conflict) ss->score.conflicts += strength; return; } @@ -1045,10 +1061,14 @@ static void apply_constraint(struct apk_solver_state *ss, struct apk_dependency continue; if (!apk_dep_is_provided(dep, p0)) { - ps0->conflicts++; + if (dep->conflict) + ps0->must_not++; + else + ps0->incompat_dep++; + dbg_printf(PKG_VER_FMT ": conflicts++ -> %d\n", PKG_VER_PRINTF(pkg0), - ps0->conflicts); + ps0->must_not); changed |= 1; } else if (requirer_pkg != NULL) { dbg_printf(PKG_VER_FMT ": inheriting flags and pinning from"PKG_VER_FMT"\n", @@ -1061,7 +1081,7 @@ static void apply_constraint(struct apk_solver_state *ss, struct apk_dependency if (changed) ns->last_touched_decision = ss->num_decisions; - if (!dep->optional) + if (!dep->conflict) ns->requirers += strength; promote_name(ss, name); @@ -1096,7 +1116,7 @@ static void undo_constraint(struct apk_solver_state *ss, struct apk_dependency * return; } if (name->providers->num == 0) { - if (!dep->optional) + if (!dep->conflict) ss->score.conflicts -= strength; return; } @@ -1111,10 +1131,13 @@ static void undo_constraint(struct apk_solver_state *ss, struct apk_dependency * continue; if (!apk_dep_is_provided(dep, p0)) { - ps0->conflicts--; + if (dep->conflict) + ps0->must_not--; + else + ps0->incompat_dep--; dbg_printf(PKG_VER_FMT ": conflicts-- -> %d\n", PKG_VER_PRINTF(pkg0), - ps0->conflicts); + ps0->must_not); } else if (requirer_pkg != NULL) { dbg_printf(PKG_VER_FMT ": uninheriting flags and pinning from "PKG_VER_FMT"\n", PKG_VER_PRINTF(pkg0), @@ -1130,7 +1153,7 @@ static void undo_constraint(struct apk_solver_state *ss, struct apk_dependency * if (ns->last_touched_decision > ss->num_decisions) ns->last_touched_decision = ss->num_decisions; - if (!dep->optional) + if (!dep->conflict) ns->requirers -= strength; demote_name(ss, name); @@ -1163,7 +1186,7 @@ static int reconsider_name(struct apk_solver_state *ss, struct apk_name *name) struct apk_package_state *ps0 = pkg_to_ps(pkg0); struct apk_score pkg0_score; - if (ps0 == NULL || ps0->locked || + if (ps0 == NULL || ps0->locked || ps0->must_not || ss->topology_position < pkg0->topology_hard || (pkg0->ipkg == NULL && (!ps0->allowed || !pkg_available(ss->db, pkg0)))) continue; @@ -1274,7 +1297,7 @@ static int expand_branch(struct apk_solver_state *ss) if (!ns->none_excluded) { struct apk_package_state *ps0 = pkg_to_ps(pkg0); - if (ps0->conflicts > ns->requirers) + if (ps0->incompat_dep > ns->requirers) primary_decision = DECISION_ASSIGN; else primary_decision = DECISION_EXCLUDE; |