aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/apk_solver.h1
-rw-r--r--src/apk_solver_data.h1
-rw-r--r--src/commit.c17
-rw-r--r--src/solver.c143
-rw-r--r--src/upgrade.c6
-rw-r--r--test/basic12.test15
-rw-r--r--test/basic13.test10
-rw-r--r--test/error5.test6
8 files changed, 134 insertions, 65 deletions
diff --git a/src/apk_solver.h b/src/apk_solver.h
index 15620e9796..b6067e2eee 100644
--- a/src/apk_solver.h
+++ b/src/apk_solver.h
@@ -33,6 +33,7 @@ struct apk_changeset {
#define APK_SOLVERF_UPGRADE 0x0001
#define APK_SOLVERF_AVAILABLE 0x0002
#define APK_SOLVERF_REINSTALL 0x0004
+#define APK_SOLVERF_LATEST 0x0008
void apk_solver_set_name_flags(struct apk_name *name,
unsigned short solver_flags,
diff --git a/src/apk_solver_data.h b/src/apk_solver_data.h
index cc41f6d1fd..7a5e275a3d 100644
--- a/src/apk_solver_data.h
+++ b/src/apk_solver_data.h
@@ -32,6 +32,7 @@ struct apk_solver_name_state {
unsigned locked : 1;
unsigned has_iif : 1;
unsigned has_options : 1;
+ unsigned reverse_deps_done : 1;
};
struct apk_solver_package_state {
diff --git a/src/commit.c b/src/commit.c
index 7136627fea..6a2580d3d2 100644
--- a/src/commit.c
+++ b/src/commit.c
@@ -370,13 +370,18 @@ static void print_pinning_errors(struct print_state *ps, struct apk_package *pkg
if (pkg->ipkg != NULL)
return;
- if (pkg->repos & apk_db_get_pinning_mask_repos(db, APK_DEFAULT_PINNING_MASK | BIT(tag)))
- return;
- for (i = 0; i < db->num_repo_tags; i++) {
- if (pkg->repos & db->repo_tags[i].allowed_repos) {
- label_start(ps, "masked in:");
- apk_print_indented(&ps->i, db->repo_tags[i].tag);
+ if (!(pkg->repos & db->available_repos)) {
+ label_start(ps, "masked in:");
+ apk_print_indented_fmt(&ps->i, "--no-network");
+ } else {
+ if (pkg->repos & apk_db_get_pinning_mask_repos(db, APK_DEFAULT_PINNING_MASK | BIT(tag)))
+ return;
+ for (i = 0; i < db->num_repo_tags; i++) {
+ if (pkg->repos & db->repo_tags[i].allowed_repos) {
+ label_start(ps, "masked in:");
+ apk_print_indented(&ps->i, db->repo_tags[i].tag);
+ }
}
}
label_end(ps);
diff --git a/src/solver.c b/src/solver.c
index b1a078c289..914baf1c4a 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;
diff --git a/src/upgrade.c b/src/upgrade.c
index 41d3cf7f28..f23ea917f2 100644
--- a/src/upgrade.c
+++ b/src/upgrade.c
@@ -35,6 +35,9 @@ static int upgrade_parse(void *ctx, struct apk_db_options *dbopts,
case 'a':
uctx->solver_flags |= APK_SOLVERF_AVAILABLE;
break;
+ case 'l':
+ uctx->solver_flags |= APK_SOLVERF_LATEST;
+ break;
default:
return -1;
}
@@ -131,6 +134,9 @@ static struct apk_option upgrade_options[] = {
"replacing or downgrading packages (instead of holding them) "
"if the currently installed package is no longer available "
"from any repository" },
+ { 'l', "latest",
+ "Select latest version of package (if it is not pinned), and "
+ "print error if it cannot be installed due to other dependencies" },
{ 0x10000, "no-self-upgrade",
"Do not do early upgrade of 'apk-tools' package" },
};
diff --git a/test/basic12.test b/test/basic12.test
new file mode 100644
index 0000000000..f43b8cef61
--- /dev/null
+++ b/test/basic12.test
@@ -0,0 +1,15 @@
+@ARGS
+--no-network
+--test-repo basic.repo
+--test-instdb basic.installed
+--test-world a
+--latest
+upgrade
+@EXPECT
+ERROR: unsatisfiable constraints:
+ b-2:
+ masked in: --no-network
+ satisfies: a-2[b]
+ a-2:
+ masked in: --no-network
+ satisfies: world[a]
diff --git a/test/basic13.test b/test/basic13.test
new file mode 100644
index 0000000000..40f5bb6508
--- /dev/null
+++ b/test/basic13.test
@@ -0,0 +1,10 @@
+@ARGS
+--test-repo basic.repo
+--test-instdb basic.installed
+--test-world a<2
+--latest
+upgrade
+@EXPECT
+ERROR: unsatisfiable constraints:
+ a-2:
+ breaks: world[a<2]
diff --git a/test/error5.test b/test/error5.test
index 949fbe8c49..4becb3d920 100644
--- a/test/error5.test
+++ b/test/error5.test
@@ -3,6 +3,6 @@
add a>2
@EXPECT
ERROR: unsatisfiable constraints:
- d-1.5:
- breaks: a-3[d>1.5]
- satisfies: b-1[d<2.0] c-1[d>1.0]
+ d-2.0:
+ breaks: b-1[d<2.0]
+ satisfies: a-3[d>1.5] c-1[d>1.0]