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.cute-signatures
parent
ee3740fcc6
commit
f18c708183
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)) {
|
||||
|
|
24
src/solver.c
24
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;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
C:Q1EyN5AdpAOBJWKMR89pp/C66o+OE=
|
||||
P:mailreadplus
|
||||
V:1
|
||||
S:1
|
||||
I:1
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
@ARGS
|
||||
--test-repo provides.repo
|
||||
--test-instdb provides-swap.installed
|
||||
--test-world mail-reader
|
||||
add mymailreader
|
||||
@EXPECT
|
||||
(1/2) Purging mailreadplus (1)
|
||||
(2/2) Installing mymailreader (1)
|
||||
OK: 0 MiB in 1 packages
|
|
@ -45,6 +45,7 @@ V:1
|
|||
S:1
|
||||
I:1
|
||||
p:mail-reader
|
||||
k:1
|
||||
|
||||
C:Q1EyN5AdpAOBJWKMR89pp/C77FFFF=
|
||||
P:server-a
|
||||
|
|
|
@ -2,7 +2,5 @@
|
|||
--test-repo provides.repo
|
||||
add mail-reader
|
||||
@EXPECT
|
||||
ERROR: unsatisfiable constraints:
|
||||
mail-reader (virtual):
|
||||
provided by: mymailreader-1 mailreadplus
|
||||
required by: world[mail-reader]
|
||||
(1/1) Installing mailreadplus (1)
|
||||
OK: 0 MiB in 0 packages
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
@ARGS
|
||||
--test-repo provides.repo
|
||||
add mail-reader mailreadplus
|
||||
@EXPECT
|
||||
(1/1) Installing mailreadplus (1)
|
||||
OK: 0 MiB in 0 packages
|
Loading…
Reference in New Issue