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 endif
progs-y += apk 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 \ search.o upgrade.o cache.o ver.o index.o fetch.o \
audit.o verify.o dot.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; return -1;
} }
if (virtpkg) if (virtpkg == NULL) {
apk_deps_add(&virtpkg->depends, &dep);
else
apk_deps_add(&world, &dep); 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_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); apk_dependency_array_free(&world);
return r; return r;

View File

@ -26,6 +26,8 @@ struct apk_changeset {
#define APK_SOLVERF_AVAILABLE 0x0002 #define APK_SOLVERF_AVAILABLE 0x0002
#define APK_SOLVERF_REINSTALL 0x0004 #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, int apk_solver_solve(struct apk_database *db,
unsigned short solver_flags, unsigned short solver_flags,
struct apk_dependency_array *world, struct apk_dependency_array *world,

View File

@ -13,13 +13,13 @@
#include <stdio.h> #include <stdio.h>
#include "apk_applet.h" #include "apk_applet.h"
#include "apk_database.h" #include "apk_database.h"
#include "apk_state.h"
#include "apk_print.h" #include "apk_print.h"
#include "apk_solver.h"
/* FIXME: reimplement fix applet */ /* FIXME: reimplement fix applet */
struct fix_ctx { struct fix_ctx {
unsigned int reinstall : 1; unsigned short solver_flags;
}; };
static int fix_parse(void *pctx, struct apk_db_options *dbopts, 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; struct fix_ctx *ctx = (struct fix_ctx *) pctx;
switch (optch) { switch (optch) {
case 'u': case 'u':
apk_flags |= APK_UPGRADE; ctx->solver_flags |= APK_SOLVERF_UPGRADE;
break; break;
case 'r': case 'r':
ctx->reinstall = 1; ctx->solver_flags |= APK_SOLVERF_REINSTALL;
break; break;
default: default:
return -1; 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) static int fix_main(void *pctx, struct apk_database *db, int argc, char **argv)
{ {
struct fix_ctx *ctx = (struct fix_ctx *) pctx; struct fix_ctx *ctx = (struct fix_ctx *) pctx;
struct apk_state *state = NULL;
struct apk_name *name; struct apk_name *name;
struct apk_package *pkg; struct apk_package *pkg;
struct apk_dependency *deps;
int r = 0, i, j; int r = 0, i, j;
state = apk_state_new(db); if (!ctx->solver_flags)
if (state == NULL) ctx->solver_flags = APK_SOLVERF_REINSTALL;
return -1;
deps = alloca(sizeof(struct apk_dependency) * argc);
for (i = 0; i < argc; i++) { for (i = 0; i < argc; i++) {
pkg = NULL; pkg = NULL;
if (strstr(argv[i], ".apk") != 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)); apk_error("%s: %s", argv[i], apk_error_str(r));
goto err; goto err;
} }
apk_dep_from_pkg(&deps[i], db, pkg); name = pkg->name;
name = deps[i].name;
} else { } else {
apk_dep_from_blob(&deps[i], db, APK_BLOB_STR(argv[i])); name = apk_db_get_name(db, APK_BLOB_STR(argv[i]));
name = deps[i].name;
for (j = 0; j < name->pkgs->num; j++) { for (j = 0; j < name->pkgs->num; j++) {
if (name->pkgs->item[j]->ipkg != NULL) { if (name->pkgs->item[j]->ipkg != NULL) {
pkg = name->pkgs->item[j]; 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); apk_error("%s is not installed", name->name);
goto err; goto err;
} }
if (ctx->reinstall) apk_solver_set_name_flags(name, ctx->solver_flags);
name->flags |= APK_NAME_REINSTALL;
} }
for (i = 0; i < argc; i++) r = apk_solver_commit(db, 0, db->world);
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);
err: err:
if (r != 0 && i < argc)
apk_error("Error while processing '%s'", argv[i]);
if (state != NULL)
apk_state_unref(state);
return r; 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 package is needed for (re-)install */
if ((pkg->ipkg == NULL) || 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 */ /* and it's not available, we can't use it */
if (!pkg_available(ss->db, pkg)) 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) static int get_pkg_expansion_flags(struct apk_solver_state *ss, struct apk_package *pkg)
{ {
struct apk_name *name = pkg->name; struct apk_name *name = pkg->name;
struct apk_name_state *ns = name_to_ns(name);
int i, options = 0; int i, options = 0;
/* check if the suggested package is the most preferred one of /* 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) ps0->conflicts != 0)
continue; continue;
if (ss->solver_flags & APK_SOLVERF_AVAILABLE) { options++;
if ((ns->solver_flags | ss->solver_flags) & APK_SOLVERF_AVAILABLE) {
/* pkg available, pkg0 not */ /* pkg available, pkg0 not */
if (pkg->repos != 0 && pkg0->repos == 0) if (pkg->repos != 0 && pkg0->repos == 0)
continue; 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; return APK_PKGSTF_NOINSTALL | APK_PKGSTF_BRANCH;
} }
if (!(ss->solver_flags & APK_SOLVERF_UPGRADE)) { if ((ns->solver_flags | ss->solver_flags) & APK_SOLVERF_UPGRADE) {
/* not upgrading, prefer the installed package */ /* upgrading, or neither of the package is installed, so
if (pkg->ipkg == NULL && pkg0->ipkg != NULL) * 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; return APK_PKGSTF_NOINSTALL | APK_PKGSTF_BRANCH;
case APK_VERSION_LESS:
continue;
}
} }
/* upgrading, or neither of the package is installed, so /* not upgrading, prefer the installed package */
* we just fall back comparing to versions */ if (pkg->ipkg == NULL && pkg0->ipkg != NULL)
options++;
if (apk_pkg_version_compare(pkg0, pkg) == APK_VERSION_GREATER)
return APK_PKGSTF_NOINSTALL | APK_PKGSTF_BRANCH; 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, static int generate_changeset(struct apk_database *db,
struct apk_package_array *solution, struct apk_package_array *solution,
struct apk_changeset *changeset) struct apk_changeset *changeset,
unsigned short solver_flags)
{ {
struct apk_name *name; struct apk_name *name;
struct apk_name_state *ns; struct apk_name_state *ns;
@ -682,7 +689,7 @@ static int generate_changeset(struct apk_database *db,
for (i = 0; i < solution->num; i++) { for (i = 0; i < solution->num; i++) {
pkg = solution->item[i]; pkg = solution->item[i];
if ((pkg->ipkg == NULL) || 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++; num_installs++;
} }
list_for_each_entry(ipkg, &db->installed.packages, installed_pkgs_list) { 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; name = pkg->name;
if ((pkg->ipkg == NULL) || 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++) { for (j = 0; j < name->pkgs->num; j++) {
pkg0 = name->pkgs->item[j]; pkg0 = name->pkgs->item[j];
if (pkg0->ipkg == NULL) if (pkg0->ipkg == NULL)
@ -738,6 +745,13 @@ static int free_state(apk_hash_item item, void *ctx)
return 0; 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, int apk_solver_solve(struct apk_database *db,
unsigned short solver_flags, unsigned short solver_flags,
struct apk_dependency_array *world, struct apk_dependency_array *world,
@ -787,7 +801,8 @@ int apk_solver_solve(struct apk_database *db,
if (r == 0 && ss->cur_unsatisfiable == 0) { if (r == 0 && ss->cur_unsatisfiable == 0) {
record_solution(ss); record_solution(ss);
if (changeset != NULL) if (changeset != NULL)
generate_changeset(db, ss->best_solution, changeset); generate_changeset(db, ss->best_solution, changeset,
ss->solver_flags);
r = 0; r = 0;
} else { } else {
qsort(ss->best_solution->item, ss->best_solution->num, qsort(ss->best_solution->item, ss->best_solution->num,