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;
|
struct apk_dependency_array *depends, *install_if, *provides;
|
||||||
size_t installed_size, size;
|
size_t installed_size, size;
|
||||||
time_t build_time;
|
time_t build_time;
|
||||||
|
unsigned short provider_priority;
|
||||||
unsigned repos : APK_MAX_REPOS;
|
unsigned repos : APK_MAX_REPOS;
|
||||||
unsigned marked : 1;
|
unsigned marked : 1;
|
||||||
unsigned uninstallable : 1;
|
unsigned uninstallable : 1;
|
||||||
|
|
|
@ -54,6 +54,7 @@ struct apk_solver_package_state {
|
||||||
unsigned seen : 1;
|
unsigned seen : 1;
|
||||||
unsigned pkg_available : 1;
|
unsigned pkg_available : 1;
|
||||||
unsigned pkg_selectable : 1;
|
unsigned pkg_selectable : 1;
|
||||||
|
unsigned pkg_selected : 1;
|
||||||
unsigned tag_ok : 1;
|
unsigned tag_ok : 1;
|
||||||
unsigned tag_preferred : 1;
|
unsigned tag_preferred : 1;
|
||||||
unsigned dependencies_used : 1;
|
unsigned dependencies_used : 1;
|
||||||
|
|
|
@ -812,6 +812,9 @@ int apk_pkg_add_info(struct apk_database *db, struct apk_package *pkg,
|
||||||
case 'c':
|
case 'c':
|
||||||
pkg->commit = apk_blob_cstr(value);
|
pkg->commit = apk_blob_cstr(value);
|
||||||
break;
|
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 'F': case 'M': case 'R': case 'Z': case 'r': case 'q':
|
||||||
case 'a': case 's': case 'f':
|
case 'a': case 's': case 'f':
|
||||||
/* installed db entries which are handled in database.c */
|
/* 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' },
|
{ "maintainer", 'm' },
|
||||||
{ "builddate", 't' },
|
{ "builddate", 't' },
|
||||||
{ "commit", 'c' },
|
{ "commit", 'c' },
|
||||||
|
{ "provider_priority", 'k' },
|
||||||
};
|
};
|
||||||
struct read_info_ctx *ri = (struct read_info_ctx *) ctx;
|
struct read_info_ctx *ri = (struct read_info_ctx *) ctx;
|
||||||
apk_blob_t l, r;
|
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("\nc:"));
|
||||||
apk_blob_push_blob(&bbuf, APK_BLOB_STR(info->commit));
|
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"));
|
apk_blob_push_blob(&bbuf, APK_BLOB_STR("\n"));
|
||||||
|
|
||||||
if (APK_BLOB_IS_NULL(bbuf)) {
|
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)
|
if (is_provided)
|
||||||
inherit_pinning_and_flags(ss, pkg0, ppkg);
|
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)
|
if (r)
|
||||||
return 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 */
|
/* Prefer lowest available repository */
|
||||||
return ffs(pkgB->repos) - ffs(pkgA->repos);
|
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) {
|
if (name->ss.requirers || name->ss.has_iif) {
|
||||||
foreach_array_item(p, name->providers) {
|
foreach_array_item(p, name->providers) {
|
||||||
dbg_printf(" consider "PKG_VER_FMT" iif_triggered=%d, tag_ok=%d, selectable=%d\n",
|
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);
|
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 */
|
/* Ensure valid pinning and install-if trigger */
|
||||||
if (name->ss.requirers == 0 &&
|
if (name->ss.requirers == 0 &&
|
||||||
(!p->pkg->ss.iif_triggered ||
|
(!p->pkg->ss.iif_triggered ||
|
||||||
!p->pkg->ss.tag_ok))
|
!p->pkg->ss.tag_ok))
|
||||||
continue;
|
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)
|
if (compare_providers(ss, p, &chosen) > 0)
|
||||||
chosen = *p;
|
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
|
S:1
|
||||||
I:1
|
I:1
|
||||||
p:mail-reader
|
p:mail-reader
|
||||||
|
k:1
|
||||||
|
|
||||||
C:Q1EyN5AdpAOBJWKMR89pp/C77FFFF=
|
C:Q1EyN5AdpAOBJWKMR89pp/C77FFFF=
|
||||||
P:server-a
|
P:server-a
|
||||||
|
|
|
@ -2,7 +2,5 @@
|
||||||
--test-repo provides.repo
|
--test-repo provides.repo
|
||||||
add mail-reader
|
add mail-reader
|
||||||
@EXPECT
|
@EXPECT
|
||||||
ERROR: unsatisfiable constraints:
|
(1/1) Installing mailreadplus (1)
|
||||||
mail-reader (virtual):
|
OK: 0 MiB in 0 packages
|
||||||
provided by: mymailreader-1 mailreadplus
|
|
||||||
required by: world[mail-reader]
|
|
||||||
|
|
|
@ -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