solver: add per-name specific flags, and fix the fix applet

cute-signatures
Timo Teräs 2011-09-13 11:47:34 +03:00
parent b42421722e
commit c6d9962d81
5 changed files with 51 additions and 48 deletions

View File

@ -19,7 +19,7 @@ $(error Build dependencies are not met)
endif
progs-y += apk
apk-objs := apk.o add.o del.o update.o info.o \
apk-objs := apk.o add.o del.o fix.o update.o info.o \
search.o upgrade.o cache.o ver.o index.o fetch.o \
audit.o verify.o dot.o

View File

@ -112,15 +112,19 @@ static int add_main(void *ctx, struct apk_database *db, int argc, char **argv)
return -1;
}
if (virtpkg)
apk_deps_add(&virtpkg->depends, &dep);
else
if (virtpkg == NULL) {
apk_deps_add(&world, &dep);
apk_solver_set_name_flags(dep.name, actx->solver_flags);
} else {
apk_deps_add(&virtpkg->depends, &dep);
}
}
if (virtpkg)
if (virtpkg) {
apk_deps_add(&world, &virtdep);
apk_solver_set_name_flags(virtdep.name, actx->solver_flags);
}
r = apk_solver_commit(db, actx->solver_flags, world);
r = apk_solver_commit(db, 0, world);
apk_dependency_array_free(&world);
return r;

View File

@ -26,6 +26,8 @@ struct apk_changeset {
#define APK_SOLVERF_AVAILABLE 0x0002
#define APK_SOLVERF_REINSTALL 0x0004
void apk_solver_set_name_flags(struct apk_name *name,
unsigned short solver_flags);
int apk_solver_solve(struct apk_database *db,
unsigned short solver_flags,
struct apk_dependency_array *world,

View File

@ -13,13 +13,13 @@
#include <stdio.h>
#include "apk_applet.h"
#include "apk_database.h"
#include "apk_state.h"
#include "apk_print.h"
#include "apk_solver.h"
/* FIXME: reimplement fix applet */
struct fix_ctx {
unsigned int reinstall : 1;
unsigned short solver_flags;
};
static int fix_parse(void *pctx, struct apk_db_options *dbopts,
@ -28,10 +28,10 @@ static int fix_parse(void *pctx, struct apk_db_options *dbopts,
struct fix_ctx *ctx = (struct fix_ctx *) pctx;
switch (optch) {
case 'u':
apk_flags |= APK_UPGRADE;
ctx->solver_flags |= APK_SOLVERF_UPGRADE;
break;
case 'r':
ctx->reinstall = 1;
ctx->solver_flags |= APK_SOLVERF_REINSTALL;
break;
default:
return -1;
@ -42,17 +42,13 @@ static int fix_parse(void *pctx, struct apk_db_options *dbopts,
static int fix_main(void *pctx, struct apk_database *db, int argc, char **argv)
{
struct fix_ctx *ctx = (struct fix_ctx *) pctx;
struct apk_state *state = NULL;
struct apk_name *name;
struct apk_package *pkg;
struct apk_dependency *deps;
int r = 0, i, j;
state = apk_state_new(db);
if (state == NULL)
return -1;
if (!ctx->solver_flags)
ctx->solver_flags = APK_SOLVERF_REINSTALL;
deps = alloca(sizeof(struct apk_dependency) * argc);
for (i = 0; i < argc; i++) {
pkg = NULL;
if (strstr(argv[i], ".apk") != NULL) {
@ -66,12 +62,9 @@ static int fix_main(void *pctx, struct apk_database *db, int argc, char **argv)
apk_error("%s: %s", argv[i], apk_error_str(r));
goto err;
}
apk_dep_from_pkg(&deps[i], db, pkg);
name = deps[i].name;
name = pkg->name;
} else {
apk_dep_from_blob(&deps[i], db, APK_BLOB_STR(argv[i]));
name = deps[i].name;
name = apk_db_get_name(db, APK_BLOB_STR(argv[i]));
for (j = 0; j < name->pkgs->num; j++) {
if (name->pkgs->item[j]->ipkg != NULL) {
pkg = name->pkgs->item[j];
@ -83,22 +76,11 @@ static int fix_main(void *pctx, struct apk_database *db, int argc, char **argv)
apk_error("%s is not installed", name->name);
goto err;
}
if (ctx->reinstall)
name->flags |= APK_NAME_REINSTALL;
apk_solver_set_name_flags(name, ctx->solver_flags);
}
for (i = 0; i < argc; i++)
r |= apk_state_lock_dependency(state, &deps[i]);
if (r == 0 || (apk_flags & APK_FORCE))
r = apk_state_commit(state);
else
apk_state_print_errors(state);
r = apk_solver_commit(db, 0, db->world);
err:
if (r != 0 && i < argc)
apk_error("Error while processing '%s'", argv[i]);
if (state != NULL)
apk_state_unref(state);
return r;
}

View File

@ -215,10 +215,10 @@ static void prepare_name(struct apk_solver_state *ss, struct apk_name *name,
/* if package is needed for (re-)install */
if ((pkg->ipkg == NULL) ||
(ns->solver_flags & APK_SOLVERF_REINSTALL)) {
((ns->solver_flags | ss->solver_flags) & APK_SOLVERF_REINSTALL)) {
/* and it's not available, we can't use it */
if (!pkg_available(ss->db, pkg))
ps->conflicts++;
ps->conflicts = 1024;
}
}
@ -236,6 +236,7 @@ static void foreach_dependency(struct apk_solver_state *ss, struct apk_dependenc
static int get_pkg_expansion_flags(struct apk_solver_state *ss, struct apk_package *pkg)
{
struct apk_name *name = pkg->name;
struct apk_name_state *ns = name_to_ns(name);
int i, options = 0;
/* check if the suggested package is the most preferred one of
@ -250,7 +251,9 @@ static int get_pkg_expansion_flags(struct apk_solver_state *ss, struct apk_packa
ps0->conflicts != 0)
continue;
if (ss->solver_flags & APK_SOLVERF_AVAILABLE) {
options++;
if ((ns->solver_flags | ss->solver_flags) & APK_SOLVERF_AVAILABLE) {
/* pkg available, pkg0 not */
if (pkg->repos != 0 && pkg0->repos == 0)
continue;
@ -259,16 +262,19 @@ static int get_pkg_expansion_flags(struct apk_solver_state *ss, struct apk_packa
return APK_PKGSTF_NOINSTALL | APK_PKGSTF_BRANCH;
}
if (!(ss->solver_flags & APK_SOLVERF_UPGRADE)) {
/* not upgrading, prefer the installed package */
if (pkg->ipkg == NULL && pkg0->ipkg != NULL)
if ((ns->solver_flags | ss->solver_flags) & APK_SOLVERF_UPGRADE) {
/* upgrading, or neither of the package is installed, so
* we just fall back comparing to versions */
switch (apk_pkg_version_compare(pkg0, pkg)) {
case APK_VERSION_GREATER:
return APK_PKGSTF_NOINSTALL | APK_PKGSTF_BRANCH;
case APK_VERSION_LESS:
continue;
}
}
/* upgrading, or neither of the package is installed, so
* we just fall back comparing to versions */
options++;
if (apk_pkg_version_compare(pkg0, pkg) == APK_VERSION_GREATER)
/* not upgrading, prefer the installed package */
if (pkg->ipkg == NULL && pkg0->ipkg != NULL)
return APK_PKGSTF_NOINSTALL | APK_PKGSTF_BRANCH;
}
@ -670,7 +676,8 @@ static int compare_change(const void *p1, const void *p2)
static int generate_changeset(struct apk_database *db,
struct apk_package_array *solution,
struct apk_changeset *changeset)
struct apk_changeset *changeset,
unsigned short solver_flags)
{
struct apk_name *name;
struct apk_name_state *ns;
@ -682,7 +689,7 @@ static int generate_changeset(struct apk_database *db,
for (i = 0; i < solution->num; i++) {
pkg = solution->item[i];
if ((pkg->ipkg == NULL) ||
(name_to_ns(pkg->name)->solver_flags & APK_SOLVERF_REINSTALL))
((solver_flags | name_to_ns(pkg->name)->solver_flags) & APK_SOLVERF_REINSTALL))
num_installs++;
}
list_for_each_entry(ipkg, &db->installed.packages, installed_pkgs_list) {
@ -707,7 +714,7 @@ static int generate_changeset(struct apk_database *db,
name = pkg->name;
if ((pkg->ipkg == NULL) ||
(name_to_ns(name)->solver_flags & APK_SOLVERF_REINSTALL)) {
((solver_flags | name_to_ns(name)->solver_flags) & APK_SOLVERF_REINSTALL)) {
for (j = 0; j < name->pkgs->num; j++) {
pkg0 = name->pkgs->item[j];
if (pkg0->ipkg == NULL)
@ -738,6 +745,13 @@ static int free_state(apk_hash_item item, void *ctx)
return 0;
}
void apk_solver_set_name_flags(struct apk_name *name,
unsigned short solver_flags)
{
struct apk_name_state *ns = name_to_ns(name);
ns->solver_flags = solver_flags;
}
int apk_solver_solve(struct apk_database *db,
unsigned short solver_flags,
struct apk_dependency_array *world,
@ -787,7 +801,8 @@ int apk_solver_solve(struct apk_database *db,
if (r == 0 && ss->cur_unsatisfiable == 0) {
record_solution(ss);
if (changeset != NULL)
generate_changeset(db, ss->best_solution, changeset);
generate_changeset(db, ss->best_solution, changeset,
ss->solver_flags);
r = 0;
} else {
qsort(ss->best_solution->item, ss->best_solution->num,