summaryrefslogtreecommitdiff
path: root/src/solver.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/solver.c')
-rw-r--r--src/solver.c143
1 files changed, 87 insertions, 56 deletions
diff --git a/src/solver.c b/src/solver.c
index b1a078c..914baf1 100644
--- a/src/solver.c
+++ b/src/solver.c
@@ -222,11 +222,12 @@ static void discover_name(struct apk_solver_state *ss, struct apk_name *name)
}
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\n",
+ dbg_printf("discover " PKG_VER_FMT ": tag_ok=%d, tag_pref=%d max_dep_chain=%d available=%d\n",
PKG_VER_PRINTF(pkg),
pkg->ss.tag_ok,
pkg->ss.tag_preferred,
- pkg->ss.max_dep_chain);
+ pkg->ss.max_dep_chain,
+ pkg->ss.available);
}
foreach_array_item(pname0, name->rinstall_if)
discover_name(ss, *pname0);
@@ -266,7 +267,8 @@ static void apply_constraint(struct apk_solver_state *ss, struct apk_package *pp
BLOB_PRINTF(*dep->version));
name->ss.requirers += !dep->conflict;
- name_requirers_changed(ss, name);
+ if (name->ss.requirers == 1 && !dep->conflict)
+ name_requirers_changed(ss, name);
foreach_array_item(p0, name->providers) {
struct apk_package *pkg0 = p0->pkg;
@@ -294,7 +296,7 @@ static void apply_constraint(struct apk_solver_state *ss, struct apk_package *pp
static void reconsider_name(struct apk_solver_state *ss, struct apk_name *name)
{
- struct apk_name *name0;
+ struct apk_name *name0, **pname0;
struct apk_dependency *dep;
struct apk_package *first_candidate = NULL;
struct apk_provider *p;
@@ -366,26 +368,41 @@ static void reconsider_name(struct apk_solver_state *ss, struct apk_name *name)
foreach_array_item(p, name->providers)
p->pkg->ss.dependencies_used = p->pkg->ss.dependencies_merged;
- /* TODO: could merge versioning bits too */
/* propagate down common dependencies */
- foreach_array_item(dep, first_candidate->depends) {
- if (dep->conflict)
- continue;
- name0 = dep->name;
- if (name0->ss.merge_index == num_options) {
- /* common dependency name with all */
- if (name0->ss.requirers == 0) {
- dbg_printf("%s common dependency: %s\n",
- name->name, name0->name);
- name0->ss.requirers++;
- name_requirers_changed(ss, name0);
+ if (num_options == 1) {
+ /* FIXME: keeps increasing counts, use bit fields instead? */
+ foreach_array_item(dep, first_candidate->depends)
+ apply_constraint(ss, first_candidate, dep);
+ } else {
+ /* FIXME: could merge versioning bits too */
+ foreach_array_item(dep, first_candidate->depends) {
+ if (dep->conflict)
+ continue;
+ name0 = dep->name;
+ if (name0->ss.merge_index == num_options) {
+ /* common dependency name with all */
+ if (name0->ss.requirers == 0) {
+ dbg_printf("%s common dependency: %s\n",
+ name->name, name0->name);
+ name0->ss.requirers++;
+ name_requirers_changed(ss, name0);
+ }
}
+ name0->ss.merge_index = 0;
}
- name0->ss.merge_index = 0;
}
}
- dbg_printf("reconsider_name: %s [finished], has_options=%d\n",
- name->name, name->ss.has_options);
+ name->ss.reverse_deps_done = 1;
+ foreach_array_item(pname0, name->rdepends) {
+ name0 = *pname0;
+ if (name0->ss.seen && !name0->ss.locked) {
+ name->ss.reverse_deps_done = 0;
+ break;
+ }
+ }
+
+ dbg_printf("reconsider_name: %s [finished], has_options=%d, reverse_deps_done=%d\n",
+ name->name, name->ss.has_options, name->ss.reverse_deps_done);
}
static int compare_providers(struct apk_solver_state *ss,
@@ -400,50 +417,66 @@ static int compare_providers(struct apk_solver_state *ss,
if (pkgA == NULL || pkgB == NULL)
return (pkgA != NULL) - (pkgB != NULL);
- /* Prefer without errors */
- r = (int)pkgA->ss.available - (int)pkgB->ss.available;
- if (r)
- return r;
+ /* Latest version required? */
+ solver_flags = pkgA->ss.solver_flags | pkgB->ss.solver_flags;
+ if ((solver_flags & APK_SOLVERF_LATEST) &&
+ (pkgA->ss.pinning_allowed == APK_DEFAULT_PINNING_MASK) &&
+ (pkgB->ss.pinning_allowed == APK_DEFAULT_PINNING_MASK)) {
+ /* Prefer allowed pinning */
+ r = (int)pkgA->ss.tag_ok - (int)pkgB->ss.tag_ok;
+ if (r)
+ return r;
- /* Prefer those that were in last dependency merging group */
- r = (int)pkgA->ss.dependencies_used - (int)pkgB->ss.dependencies_used;
- if (r)
- return r;
- r = pkgB->ss.conflicts - pkgA->ss.conflicts;
- if (r)
- return r;
+ /* Prefer available */
+ if (solver_flags & (APK_SOLVERF_AVAILABLE | APK_SOLVERF_REINSTALL)) {
+ r = !!(pkgA->repos & db->available_repos) - !!(pkgB->repos & db->available_repos);
+ if (r)
+ return r;
+ }
+ } else {
+ /* Prefer without errors */
+ r = (int)pkgA->ss.available - (int)pkgB->ss.available;
+ if (r)
+ return r;
- /* Prefer installed on self-upgrade */
- solver_flags = pkgA->ss.solver_flags | pkgB->ss.solver_flags;
- if (db->performing_self_update && !(solver_flags & APK_SOLVERF_UPGRADE)) {
- r = (pkgA->ipkg != NULL) - (pkgB->ipkg != NULL);
+ /* Prefer those that were in last dependency merging group */
+ r = (int)pkgA->ss.dependencies_used - (int)pkgB->ss.dependencies_used;
+ if (r)
+ return r;
+ r = pkgB->ss.conflicts - pkgA->ss.conflicts;
if (r)
return r;
- }
- /* Prefer allowed pinning */
- r = (int)pkgA->ss.tag_ok - (int)pkgB->ss.tag_ok;
- if (r)
- return r;
+ /* Prefer installed on self-upgrade */
+ if (db->performing_self_update && !(solver_flags & APK_SOLVERF_UPGRADE)) {
+ r = (pkgA->ipkg != NULL) - (pkgB->ipkg != NULL);
+ if (r)
+ return r;
+ }
- /* Prefer available */
- if (solver_flags & (APK_SOLVERF_AVAILABLE | APK_SOLVERF_REINSTALL)) {
- r = !!(pkgA->repos & db->available_repos) -
- !!(pkgB->repos & db->available_repos);
+ /* Prefer allowed pinning */
+ r = (int)pkgA->ss.tag_ok - (int)pkgB->ss.tag_ok;
if (r)
return r;
- }
- /* Prefer preferred pinning */
- r = (int)pkgA->ss.tag_preferred - (int)pkgB->ss.tag_preferred;
- if (r)
- return r;
+ /* Prefer available */
+ if (solver_flags & (APK_SOLVERF_AVAILABLE | APK_SOLVERF_REINSTALL)) {
+ r = !!(pkgA->repos & db->available_repos) - !!(pkgB->repos & db->available_repos);
+ if (r)
+ return r;
+ }
- /* Prefer installed */
- if (!(solver_flags & APK_SOLVERF_UPGRADE)) {
- r = (pkgA->ipkg != NULL) - (pkgB->ipkg != NULL);
+ /* Prefer preferred pinning */
+ r = (int)pkgA->ss.tag_preferred - (int)pkgB->ss.tag_preferred;
if (r)
return r;
+
+ /* Prefer installed */
+ if (!(solver_flags & APK_SOLVERF_UPGRADE)) {
+ r = (pkgA->ipkg != NULL) - (pkgB->ipkg != NULL);
+ if (r)
+ return r;
+ }
}
/* Select latest by requested name */
@@ -747,17 +780,15 @@ restart:
name = NULL;
list_for_each_entry(name0, &ss->unresolved_head, ss.unresolved_list) {
- if ((!name0->ss.has_options) && name0->ss.requirers > 0) {
+ if (name0->ss.reverse_deps_done && name0->ss.requirers && !name0->ss.has_options) {
name = name0;
break;
}
if (name == NULL)
goto prefer;
- if (name0->ss.requirers == 0 && name->ss.requirers > 0)
+ if ((!!name0->ss.requirers) - (!!name->ss.requirers) < 0)
continue;
- if (name0->ss.requirers > 0 && name->ss.requirers == 0)
- goto prefer;
- if (name0->ss.max_dep_chain < name->ss.max_dep_chain)
+ if (name0->ss.max_dep_chain - name->ss.max_dep_chain < 0)
continue;
prefer:
name = name0;