summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorWilliam Pitcock <nenolod@dereferenced.org>2017-11-02 02:55:17 +0000
committerWilliam Pitcock <nenolod@dereferenced.org>2017-11-02 03:08:24 +0000
commitf18c708183ac735d1787ff5b450d36f6596a10b9 (patch)
tree2a8cbb76760ae075b675f15a751d207059a20b56 /src
parentee3740fcc681b8585b3d8d363453585cae4257aa (diff)
downloadapk-tools-f18c708183ac735d1787ff5b450d36f6596a10b9.tar.gz
apk-tools-f18c708183ac735d1787ff5b450d36f6596a10b9.tar.bz2
apk-tools-f18c708183ac735d1787ff5b450d36f6596a10b9.tar.xz
apk-tools-f18c708183ac735d1787ff5b450d36f6596a10b9.zip
solver: implement support for choosing default virtuals
By introducing a new package metadata field, `provider_priority` (index letter `k`), we can specify default packages to satisfy a virtual. If a user wishes to select an alternative provider for the virtual, a changeset swapping the default provider for the selected provider will be generated by the dependency resolver.
Diffstat (limited to 'src')
-rw-r--r--src/apk_package.h1
-rw-r--r--src/apk_solver_data.h1
-rw-r--r--src/package.c8
-rw-r--r--src/solver.c24
4 files changed, 27 insertions, 7 deletions
diff --git a/src/apk_package.h b/src/apk_package.h
index c561fc1..87635a9 100644
--- a/src/apk_package.h
+++ b/src/apk_package.h
@@ -117,6 +117,7 @@ struct apk_package {
struct apk_dependency_array *depends, *install_if, *provides;
size_t installed_size, size;
time_t build_time;
+ unsigned short provider_priority;
unsigned repos : APK_MAX_REPOS;
unsigned marked : 1;
unsigned uninstallable : 1;
diff --git a/src/apk_solver_data.h b/src/apk_solver_data.h
index 43b7a1b..73c2753 100644
--- a/src/apk_solver_data.h
+++ b/src/apk_solver_data.h
@@ -54,6 +54,7 @@ struct apk_solver_package_state {
unsigned seen : 1;
unsigned pkg_available : 1;
unsigned pkg_selectable : 1;
+ unsigned pkg_selected : 1;
unsigned tag_ok : 1;
unsigned tag_preferred : 1;
unsigned dependencies_used : 1;
diff --git a/src/package.c b/src/package.c
index be7f269..d851ff0 100644
--- a/src/package.c
+++ b/src/package.c
@@ -812,6 +812,9 @@ int apk_pkg_add_info(struct apk_database *db, struct apk_package *pkg,
case 'c':
pkg->commit = apk_blob_cstr(value);
break;
+ case 'k':
+ pkg->provider_priority = apk_blob_pull_uint(&value, 10);
+ break;
case 'F': case 'M': case 'R': case 'Z': case 'r': case 'q':
case 'a': case 's': case 'f':
/* installed db entries which are handled in database.c */
@@ -850,6 +853,7 @@ static int read_info_line(void *ctx, apk_blob_t line)
{ "maintainer", 'm' },
{ "builddate", 't' },
{ "commit", 'c' },
+ { "provider_priority", 'k' },
};
struct read_info_ctx *ri = (struct read_info_ctx *) ctx;
apk_blob_t l, r;
@@ -1125,6 +1129,10 @@ int apk_pkg_write_index_entry(struct apk_package *info,
apk_blob_push_blob(&bbuf, APK_BLOB_STR("\nc:"));
apk_blob_push_blob(&bbuf, APK_BLOB_STR(info->commit));
}
+ if (info->provider_priority) {
+ apk_blob_push_blob(&bbuf, APK_BLOB_STR("\nk:"));
+ apk_blob_push_uint(&bbuf, info->provider_priority, 10);
+ }
apk_blob_push_blob(&bbuf, APK_BLOB_STR("\n"));
if (APK_BLOB_IS_NULL(bbuf)) {
diff --git a/src/solver.c b/src/solver.c
index 1db8a69..11ccfc9 100644
--- a/src/solver.c
+++ b/src/solver.c
@@ -299,6 +299,10 @@ static void apply_constraint(struct apk_solver_state *ss, struct apk_package *pp
if (is_provided)
inherit_pinning_and_flags(ss, pkg0, ppkg);
+
+ /* if a world-dependency is non-virtual, then the provider is going to be selected */
+ if (ppkg == NULL && dep->name == pkg0->name && pkg0->ss.pkg_selectable)
+ pkg0->ss.pkg_selected = 1;
}
}
@@ -587,6 +591,16 @@ static int compare_providers(struct apk_solver_state *ss,
if (r)
return r;
+ /* Prefer already selected package. */
+ r = pkgA->ss.pkg_selected - pkgB->ss.pkg_selected;
+ if (r)
+ return r;
+
+ /* Prefer highest declared provider priority. */
+ r = pkgA->provider_priority - pkgB->provider_priority;
+ if (r)
+ return r;
+
/* Prefer lowest available repository */
return ffs(pkgB->repos) - ffs(pkgA->repos);
}
@@ -639,18 +653,14 @@ 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, selectable=%d\n",
- PKG_VER_PRINTF(p->pkg), p->pkg->ss.iif_triggered, p->pkg->ss.tag_ok, p->pkg->ss.pkg_selectable);
+ dbg_printf(" consider "PKG_VER_FMT" iif_triggered=%d, tag_ok=%d, selectable=%d, selected=%d, provider_priority=%d\n",
+ PKG_VER_PRINTF(p->pkg), p->pkg->ss.iif_triggered, p->pkg->ss.tag_ok, p->pkg->ss.pkg_selectable,
+ p->pkg->ss.pkg_selected, p->pkg->provider_priority);
/* Ensure valid pinning and install-if trigger */
if (name->ss.requirers == 0 &&
(!p->pkg->ss.iif_triggered ||
!p->pkg->ss.tag_ok))
continue;
- /* Virtual packages cannot be autoselected */
- if (p->version == &apk_null_blob &&
- p->pkg->name->auto_select_virtual == 0 &&
- p->pkg->name->ss.requirers == 0)
- continue;
if (compare_providers(ss, p, &chosen) > 0)
chosen = *p;
}