solver: fix pinning+cache to work

Mistakenly allowed masked out package to be installed if it was
in cache.
cute-signatures
Timo Teräs 2013-06-20 14:08:16 +03:00
parent 7e18398781
commit 3f27da2ade
5 changed files with 32 additions and 24 deletions

View File

@ -93,8 +93,6 @@ struct apk_installed_package {
unsigned broken_script : 1;
};
#define APK_PKG_UNINSTALLABLE ((char*) -1)
struct apk_package {
apk_hash_node hash_node;
union {
@ -117,6 +115,7 @@ struct apk_package {
size_t installed_size, size;
time_t build_time;
unsigned marked : 1;
unsigned uninstallable : 1;
unsigned repos : APK_MAX_REPOS;
struct apk_checksum csum;
};

View File

@ -50,9 +50,10 @@ struct apk_solver_package_state {
unsigned solver_flags : 4;
unsigned solver_flags_inheritable : 4;
unsigned seen : 1;
unsigned pkg_available : 1;
unsigned pkg_selectable : 1;
unsigned tag_ok : 1;
unsigned tag_preferred : 1;
unsigned available : 1;
unsigned dependencies_used : 1;
unsigned dependencies_merged : 1;
unsigned in_changeset : 1;

View File

@ -1452,8 +1452,6 @@ static void apk_db_setup_repositories(struct apk_database *db)
db->local_repos |= BIT(APK_REPOSITORY_CACHED);
db->available_repos |= BIT(APK_REPOSITORY_CACHED);
/* Get first repository tag (the NULL tag) */
db->repo_tags[APK_DEFAULT_REPOSITORY_TAG].allowed_repos |= BIT(APK_REPOSITORY_CACHED);
db->num_repo_tags = 1;
}

View File

@ -802,7 +802,7 @@ int apk_pkg_add_info(struct apk_database *db, struct apk_package *pkg,
default:
/* lower case index entries are safe to be ignored */
if (!islower(field)) {
pkg->filename = APK_PKG_UNINSTALLABLE;
pkg->uninstallable = 1;
db->compat_notinstallable = 1;
}
db->compat_newfeatures = 1;
@ -914,8 +914,7 @@ int apk_pkg_read(struct apk_database *db, const char *file,
tar->close(tar);
if (r < 0 && r != -ECANCELED)
goto err;
if (ctx.pkg->name == NULL ||
ctx.pkg->filename == APK_PKG_UNINSTALLABLE) {
if (ctx.pkg->name == NULL || ctx.pkg->uninstallable) {
r = -ENOTSUP;
goto err;
}

View File

@ -164,7 +164,7 @@ static void disqualify_package(struct apk_solver_state *ss, struct apk_package *
struct apk_dependency *p;
dbg_printf("disqualify_package: " PKG_VER_FMT " (%s)\n", PKG_VER_PRINTF(pkg), reason);
pkg->ss.available = 0;
pkg->ss.pkg_selectable = 0;
reevaluate_reverse_deps(ss, pkg->name);
foreach_array_item(p, pkg->provides)
reevaluate_reverse_deps(ss, p->name);
@ -183,7 +183,7 @@ static int dependency_satisfiable(struct apk_solver_state *ss, struct apk_depend
return TRUE;
foreach_array_item(p, name->providers)
if (p->pkg->ss.available && apk_dep_is_provided(dep, p))
if (p->pkg->ss.pkg_selectable && apk_dep_is_provided(dep, p))
return TRUE;
return FALSE;
@ -205,14 +205,22 @@ static void discover_name(struct apk_solver_state *ss, struct apk_name *name)
struct apk_package *pkg = p->pkg;
if (pkg->ss.seen)
continue;
pkg->ss.seen = 1;
pkg->ss.available = pkg->ipkg || (pkg->repos & db->available_repos);
pkg->ss.pinning_allowed = APK_DEFAULT_PINNING_MASK;
pkg->ss.pinning_preferred = APK_DEFAULT_PINNING_MASK;
pkg->ss.pkg_available =
(pkg->filename != NULL) ||
(pkg->installed_size == 0) ||
(pkg->repos & db->available_repos);
pkg->ss.pkg_selectable = pkg->ss.pkg_available || pkg->ipkg;
repos = get_pkg_repos(db, pkg);
pkg->ss.tag_ok = !!(repos & ss->default_repos);
pkg->ss.tag_preferred = !!(repos & ss->default_repos);
pkg->ss.tag_preferred =
(pkg->filename != NULL) ||
(pkg->installed_size == 0) ||
!!(repos & ss->default_repos);
pkg->ss.tag_ok = pkg->ss.tag_preferred || pkg->ipkg;
foreach_array_item(dep, pkg->depends) {
discover_name(ss, dep->name);
@ -221,12 +229,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 available=%d\n",
dbg_printf("discover " PKG_VER_FMT ": tag_ok=%d, tag_pref=%d max_dep_chain=%d selectable=%d\n",
PKG_VER_PRINTF(pkg),
pkg->ss.tag_ok,
pkg->ss.tag_preferred,
pkg->ss.max_dep_chain,
pkg->ss.available);
pkg->ss.pkg_selectable);
}
foreach_array_item(pname0, name->rinstall_if)
discover_name(ss, *pname0);
@ -277,7 +285,7 @@ static void apply_constraint(struct apk_solver_state *ss, struct apk_package *pp
pkg0->name->name, BLOB_PRINTF(*p0->version), is_provided);
pkg0->ss.conflicts += !is_provided;
if (unlikely(pkg0->ss.available && pkg0->ss.conflicts))
if (unlikely(pkg0->ss.pkg_selectable && pkg0->ss.conflicts))
disqualify_package(ss, pkg0, "conflicting dependency");
if (is_provided) {
@ -298,6 +306,9 @@ static void exclude_non_providers(struct apk_solver_state *ss, struct apk_name *
struct apk_provider *p;
struct apk_dependency *d;
if (name == must_provide)
return;
dbg_printf("%s must provide %s\n", name->name, must_provide->name);
foreach_array_item(p, name->providers) {
@ -350,7 +361,7 @@ static void reconsider_name(struct apk_solver_state *ss, struct apk_name *name)
pkg = p->pkg;
pkg->ss.dependencies_merged = 0;
if (reevaluate_deps) {
if (!pkg->ss.available)
if (!pkg->ss.pkg_selectable)
continue;
foreach_array_item(dep, pkg->depends) {
if (!dependency_satisfiable(ss, dep)) {
@ -359,7 +370,7 @@ static void reconsider_name(struct apk_solver_state *ss, struct apk_name *name)
}
}
}
if (!pkg->ss.available)
if (!pkg->ss.pkg_selectable)
continue;
if (reevaluate_iif) {
@ -469,13 +480,13 @@ static int compare_providers(struct apk_solver_state *ss,
/* Prefer available */
if (solver_flags & (APK_SOLVERF_AVAILABLE | APK_SOLVERF_REINSTALL)) {
r = !!(pkgA->repos & db->available_repos) - !!(pkgB->repos & db->available_repos);
r = (int)pkgA->ss.pkg_available - (int)pkgB->ss.pkg_available;
if (r)
return r;
}
} else {
/* Prefer without errors */
r = (int)pkgA->ss.available - (int)pkgB->ss.available;
r = (int)pkgA->ss.pkg_selectable - (int)pkgB->ss.pkg_selectable;
if (r)
return r;
@ -501,7 +512,7 @@ static int compare_providers(struct apk_solver_state *ss,
/* Prefer available */
if (solver_flags & (APK_SOLVERF_AVAILABLE | APK_SOLVERF_REINSTALL)) {
r = !!(pkgA->repos & db->available_repos) - !!(pkgB->repos & db->available_repos);
r = (int)pkgA->ss.pkg_available - (int)pkgB->ss.pkg_available;
if (r)
return r;
}
@ -617,11 +628,11 @@ static void select_package(struct apk_solver_state *ss, struct apk_name *name)
pkg = chosen.pkg;
if (pkg) {
if (!pkg->ss.available || !pkg->ss.tag_ok) {
if (!pkg->ss.pkg_selectable || !pkg->ss.tag_ok) {
/* Selecting broken or unallowed package */
mark_error(ss, pkg);
}
dbg_printf("selecting: " PKG_VER_FMT ", available: %d\n", PKG_VER_PRINTF(pkg), pkg->ss.available);
dbg_printf("selecting: " PKG_VER_FMT ", available: %d\n", PKG_VER_PRINTF(pkg), pkg->ss.pkg_selectable);
assign_name(ss, pkg->name, APK_PROVIDER_FROM_PACKAGE(pkg));
foreach_array_item(d, pkg->provides)
@ -754,7 +765,7 @@ static void cset_gen_name_change(struct apk_solver_state *ss, struct apk_name *n
foreach_array_item(d, pkg->depends)
cset_gen_dep(ss, pkg, d);
dbg_printf("Selecting: "PKG_VER_FMT"%s\n", PKG_VER_PRINTF(pkg), pkg->ss.available ? "" : " [NOT AVAILABLE]");
dbg_printf("Selecting: "PKG_VER_FMT"%s\n", PKG_VER_PRINTF(pkg), pkg->ss.pkg_selectable ? "" : " [NOT SELECTABLE]");
record_change(ss, opkg, pkg);
foreach_array_item(pname, pkg->name->rinstall_if)