From 3f27da2adec968b1d8f83149b2b321e1050b4acb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timo=20Ter=C3=A4s?= Date: Thu, 20 Jun 2013 14:08:16 +0300 Subject: [PATCH] solver: fix pinning+cache to work Mistakenly allowed masked out package to be installed if it was in cache. --- src/apk_package.h | 3 +-- src/apk_solver_data.h | 3 ++- src/database.c | 2 -- src/package.c | 5 ++--- src/solver.c | 43 +++++++++++++++++++++++++++---------------- 5 files changed, 32 insertions(+), 24 deletions(-) diff --git a/src/apk_package.h b/src/apk_package.h index f743c3e..8945cd8 100644 --- a/src/apk_package.h +++ b/src/apk_package.h @@ -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; }; diff --git a/src/apk_solver_data.h b/src/apk_solver_data.h index 7853af5..0cff7b4 100644 --- a/src/apk_solver_data.h +++ b/src/apk_solver_data.h @@ -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; diff --git a/src/database.c b/src/database.c index ba13620..919335c 100644 --- a/src/database.c +++ b/src/database.c @@ -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; } diff --git a/src/package.c b/src/package.c index 6723de6..e211b63 100644 --- a/src/package.c +++ b/src/package.c @@ -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; } diff --git a/src/solver.c b/src/solver.c index 889cffd..e84a09a 100644 --- a/src/solver.c +++ b/src/solver.c @@ -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)