del: fix recursive deletion and messages (after solver merge)
Deduce the world dependencies to remove locally, and same for the additional messages about packages not deleted.cute-signatures
parent
31e4f58894
commit
4bf13c3d9a
|
@ -31,7 +31,13 @@ int apk_solver_solve(struct apk_database *db,
|
|||
struct apk_dependency_array *world,
|
||||
struct apk_package_array **solution,
|
||||
struct apk_changeset *changeset);
|
||||
|
||||
int apk_solver_commit_changeset(struct apk_database *db,
|
||||
struct apk_changeset *changeset,
|
||||
struct apk_dependency_array *world);
|
||||
void apk_solver_print_errors(struct apk_database *db,
|
||||
struct apk_package_array *solution,
|
||||
struct apk_dependency_array *world,
|
||||
int unsatisfiable);
|
||||
int apk_solver_commit(struct apk_database *db,
|
||||
unsigned short solver_flags,
|
||||
struct apk_dependency_array *world);
|
||||
|
|
147
src/del.c
147
src/del.c
|
@ -15,31 +15,159 @@
|
|||
#include "apk_print.h"
|
||||
#include "apk_solver.h"
|
||||
|
||||
static int del_parse(void *ctx, struct apk_db_options *db,
|
||||
struct del_ctx {
|
||||
int recursive_delete : 1;
|
||||
struct apk_dependency_array *world;
|
||||
};
|
||||
|
||||
static int del_parse(void *pctx, struct apk_db_options *db,
|
||||
int optch, int optindex, const char *optarg)
|
||||
{
|
||||
struct del_ctx *ctx = (struct del_ctx *) pctx;
|
||||
|
||||
switch (optch) {
|
||||
case 'r':
|
||||
/* FIXME: Reimplement recursive delete. */
|
||||
ctx->recursive_delete = 1;
|
||||
break;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int del_main(void *ctx, struct apk_database *db, int argc, char **argv)
|
||||
static void foreach_installed_reverse_dependency(
|
||||
struct apk_package *pkg,
|
||||
void (*cb)(struct apk_package *rdepend, void *ctx), void *ctx)
|
||||
{
|
||||
struct apk_name *name;
|
||||
struct apk_dependency_array *world = NULL;
|
||||
int i, j, k;
|
||||
|
||||
if (pkg == NULL)
|
||||
return;
|
||||
|
||||
name = pkg->name;
|
||||
for (i = 0; i < pkg->name->rdepends->num; i++) {
|
||||
struct apk_name *name0 = pkg->name->rdepends->item[i];
|
||||
|
||||
for (j = 0; j < name0->pkgs->num; j++) {
|
||||
struct apk_package *pkg0 = name0->pkgs->item[j];
|
||||
|
||||
if (pkg0->ipkg == NULL)
|
||||
continue;
|
||||
|
||||
for (k = 0; k < pkg0->depends->num; k++) {
|
||||
struct apk_dependency *dep = &pkg0->depends->item[k];
|
||||
if (dep->name == name &&
|
||||
(dep->result_mask == APK_DEPMASK_CONFLICT ||
|
||||
apk_dep_is_satisfied(dep, pkg)))
|
||||
break;
|
||||
}
|
||||
if (k >= pkg0->depends->num)
|
||||
continue;
|
||||
|
||||
cb(pkg0, ctx);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct not_deleted_ctx {
|
||||
struct apk_indent indent;
|
||||
struct apk_package *pkg;
|
||||
int header;
|
||||
};
|
||||
|
||||
static void print_not_deleted_message(struct apk_package *pkg,
|
||||
void *pctx)
|
||||
{
|
||||
struct not_deleted_ctx *ctx = (struct not_deleted_ctx *) pctx;
|
||||
|
||||
if (pkg == NULL)
|
||||
return;
|
||||
|
||||
if (pkg->state_ptr == ctx->pkg)
|
||||
return;
|
||||
pkg->state_ptr = ctx->pkg;
|
||||
|
||||
if (!ctx->header) {
|
||||
apk_message("World updated, but the following packages are not removed due to:");
|
||||
ctx->header = 1;
|
||||
}
|
||||
if (!ctx->indent.indent) {
|
||||
ctx->indent.x = printf(" %s:", ctx->pkg->name->name);
|
||||
ctx->indent.indent = ctx->indent.x + 1;
|
||||
}
|
||||
|
||||
apk_print_indented(&ctx->indent, APK_BLOB_STR(pkg->name->name));
|
||||
foreach_installed_reverse_dependency(pkg, print_not_deleted_message, pctx);
|
||||
}
|
||||
|
||||
static struct apk_package *name_to_pkg(struct apk_name *name)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < name->pkgs->num; i++) {
|
||||
if (name->pkgs->item[i]->ipkg != NULL)
|
||||
return name->pkgs->item[i];
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void delete_from_world(struct apk_package *pkg, void *pctx)
|
||||
{
|
||||
struct del_ctx *ctx = (struct del_ctx *) pctx;
|
||||
|
||||
apk_deps_del(&ctx->world, pkg->name);
|
||||
foreach_installed_reverse_dependency(pkg, delete_from_world, pctx);
|
||||
}
|
||||
|
||||
static int del_main(void *pctx, struct apk_database *db, int argc, char **argv)
|
||||
{
|
||||
struct del_ctx *ctx = (struct del_ctx *) pctx;
|
||||
struct apk_name **name;
|
||||
struct apk_changeset changeset = {};
|
||||
struct apk_package_array *solution = NULL;
|
||||
struct not_deleted_ctx ndctx = {};
|
||||
int i, r = 0;
|
||||
|
||||
apk_dependency_array_copy(&world, db->world);
|
||||
apk_dependency_array_copy(&ctx->world, db->world);
|
||||
|
||||
name = alloca(argc * sizeof(struct apk_name*));
|
||||
for (i = 0; i < argc; i++) {
|
||||
name = apk_db_get_name(db, APK_BLOB_STR(argv[i]));
|
||||
apk_deps_del(&world, name);
|
||||
name[i] = apk_db_get_name(db, APK_BLOB_STR(argv[i]));
|
||||
apk_deps_del(&ctx->world, name[i]);
|
||||
if (ctx->recursive_delete)
|
||||
foreach_installed_reverse_dependency(
|
||||
name_to_pkg(name[i]),
|
||||
delete_from_world, ctx);
|
||||
}
|
||||
r = apk_solver_commit(db, 0, world);
|
||||
apk_dependency_array_free(&world);
|
||||
|
||||
r = apk_solver_solve(db, 0, ctx->world, &solution, &changeset);
|
||||
if (r == 0 || (apk_flags & APK_FORCE)) {
|
||||
/* check for non-deleted package names */
|
||||
for (i = 0; i < solution->num; i++) {
|
||||
struct apk_package *pkg = solution->item[i];
|
||||
pkg->name->state_ptr = pkg;
|
||||
pkg->state_int = 0;
|
||||
}
|
||||
for (i = 0; i < argc; i++) {
|
||||
ndctx.pkg = name[i]->state_ptr;
|
||||
ndctx.indent.indent = 0;
|
||||
foreach_installed_reverse_dependency(
|
||||
name[i]->state_ptr,
|
||||
print_not_deleted_message, &ndctx);
|
||||
if (ndctx.indent.indent)
|
||||
printf("\n");
|
||||
}
|
||||
if (ndctx.header)
|
||||
printf("\n");
|
||||
apk_solver_commit_changeset(db, &changeset, ctx->world);
|
||||
r = 0;
|
||||
} else {
|
||||
apk_solver_print_errors(db, solution, ctx->world, r);
|
||||
}
|
||||
apk_package_array_free(&solution);
|
||||
apk_dependency_array_free(&ctx->world);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
@ -54,6 +182,7 @@ static struct apk_applet apk_del = {
|
|||
.help = "Remove PACKAGEs from the main dependencies and uninstall them.",
|
||||
.arguments = "PACKAGE...",
|
||||
.open_flags = APK_OPENF_WRITE,
|
||||
.context_size = sizeof(struct del_ctx),
|
||||
.num_options = ARRAY_SIZE(del_options),
|
||||
.options = del_options,
|
||||
.parse = del_parse,
|
||||
|
|
25
src/solver.c
25
src/solver.c
|
@ -974,14 +974,17 @@ static int cmp_upgrade(struct apk_change *change)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int commit_changeset(struct apk_database *db,
|
||||
struct apk_changeset *changeset,
|
||||
struct apk_dependency_array *world)
|
||||
int apk_solver_commit_changeset(struct apk_database *db,
|
||||
struct apk_changeset *changeset,
|
||||
struct apk_dependency_array *world)
|
||||
{
|
||||
struct progress prog;
|
||||
struct apk_change *change;
|
||||
int i, r = 0, size_diff = 0;
|
||||
|
||||
if (changeset->changes == NULL)
|
||||
goto all_done;
|
||||
|
||||
/* Count what needs to be done */
|
||||
memset(&prog, 0, sizeof(prog));
|
||||
for (i = 0; i < changeset->changes->num; i++) {
|
||||
|
@ -1044,6 +1047,7 @@ static int commit_changeset(struct apk_database *db,
|
|||
|
||||
apk_db_run_triggers(db);
|
||||
|
||||
all_done:
|
||||
apk_dependency_array_copy(&db->world, world);
|
||||
apk_db_write_config(db);
|
||||
|
||||
|
@ -1085,10 +1089,10 @@ static void print_dep_errors(char *label, struct apk_dependency_array *deps)
|
|||
printf("\n");
|
||||
}
|
||||
|
||||
static void print_errors(struct apk_database *db,
|
||||
struct apk_package_array *solution,
|
||||
struct apk_dependency_array *world,
|
||||
int unsatisfiable)
|
||||
void apk_solver_print_errors(struct apk_database *db,
|
||||
struct apk_package_array *solution,
|
||||
struct apk_dependency_array *world,
|
||||
int unsatisfiable)
|
||||
{
|
||||
int i;
|
||||
|
||||
|
@ -1120,16 +1124,13 @@ int apk_solver_commit(struct apk_database *db,
|
|||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (changeset.changes == NULL)
|
||||
apk_change_array_init(&changeset.changes);
|
||||
|
||||
if (r == 0 || (apk_flags & APK_FORCE)) {
|
||||
/* Success -- or forced installation of bad graph */
|
||||
commit_changeset(db, &changeset, world);
|
||||
apk_solver_commit_changeset(db, &changeset, world);
|
||||
r = 0;
|
||||
} else {
|
||||
/* Failure -- print errors */
|
||||
print_errors(db, solution, world, r);
|
||||
apk_solver_print_errors(db, solution, world, r);
|
||||
}
|
||||
apk_package_array_free(&solution);
|
||||
|
||||
|
|
Loading…
Reference in New Issue