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_dependency_array *world,
|
||||||
struct apk_package_array **solution,
|
struct apk_package_array **solution,
|
||||||
struct apk_changeset *changeset);
|
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,
|
int apk_solver_commit(struct apk_database *db,
|
||||||
unsigned short solver_flags,
|
unsigned short solver_flags,
|
||||||
struct apk_dependency_array *world);
|
struct apk_dependency_array *world);
|
||||||
|
|
147
src/del.c
147
src/del.c
|
@ -15,31 +15,159 @@
|
||||||
#include "apk_print.h"
|
#include "apk_print.h"
|
||||||
#include "apk_solver.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)
|
int optch, int optindex, const char *optarg)
|
||||||
{
|
{
|
||||||
|
struct del_ctx *ctx = (struct del_ctx *) pctx;
|
||||||
|
|
||||||
switch (optch) {
|
switch (optch) {
|
||||||
case 'r':
|
case 'r':
|
||||||
/* FIXME: Reimplement recursive delete. */
|
ctx->recursive_delete = 1;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
return 0;
|
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_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;
|
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++) {
|
for (i = 0; i < argc; i++) {
|
||||||
name = apk_db_get_name(db, APK_BLOB_STR(argv[i]));
|
name[i] = apk_db_get_name(db, APK_BLOB_STR(argv[i]));
|
||||||
apk_deps_del(&world, name);
|
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;
|
return r;
|
||||||
}
|
}
|
||||||
|
@ -54,6 +182,7 @@ static struct apk_applet apk_del = {
|
||||||
.help = "Remove PACKAGEs from the main dependencies and uninstall them.",
|
.help = "Remove PACKAGEs from the main dependencies and uninstall them.",
|
||||||
.arguments = "PACKAGE...",
|
.arguments = "PACKAGE...",
|
||||||
.open_flags = APK_OPENF_WRITE,
|
.open_flags = APK_OPENF_WRITE,
|
||||||
|
.context_size = sizeof(struct del_ctx),
|
||||||
.num_options = ARRAY_SIZE(del_options),
|
.num_options = ARRAY_SIZE(del_options),
|
||||||
.options = del_options,
|
.options = del_options,
|
||||||
.parse = del_parse,
|
.parse = del_parse,
|
||||||
|
|
15
src/solver.c
15
src/solver.c
|
@ -974,7 +974,7 @@ static int cmp_upgrade(struct apk_change *change)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int commit_changeset(struct apk_database *db,
|
int apk_solver_commit_changeset(struct apk_database *db,
|
||||||
struct apk_changeset *changeset,
|
struct apk_changeset *changeset,
|
||||||
struct apk_dependency_array *world)
|
struct apk_dependency_array *world)
|
||||||
{
|
{
|
||||||
|
@ -982,6 +982,9 @@ static int commit_changeset(struct apk_database *db,
|
||||||
struct apk_change *change;
|
struct apk_change *change;
|
||||||
int i, r = 0, size_diff = 0;
|
int i, r = 0, size_diff = 0;
|
||||||
|
|
||||||
|
if (changeset->changes == NULL)
|
||||||
|
goto all_done;
|
||||||
|
|
||||||
/* Count what needs to be done */
|
/* Count what needs to be done */
|
||||||
memset(&prog, 0, sizeof(prog));
|
memset(&prog, 0, sizeof(prog));
|
||||||
for (i = 0; i < changeset->changes->num; i++) {
|
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);
|
apk_db_run_triggers(db);
|
||||||
|
|
||||||
|
all_done:
|
||||||
apk_dependency_array_copy(&db->world, world);
|
apk_dependency_array_copy(&db->world, world);
|
||||||
apk_db_write_config(db);
|
apk_db_write_config(db);
|
||||||
|
|
||||||
|
@ -1085,7 +1089,7 @@ static void print_dep_errors(char *label, struct apk_dependency_array *deps)
|
||||||
printf("\n");
|
printf("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
static void print_errors(struct apk_database *db,
|
void apk_solver_print_errors(struct apk_database *db,
|
||||||
struct apk_package_array *solution,
|
struct apk_package_array *solution,
|
||||||
struct apk_dependency_array *world,
|
struct apk_dependency_array *world,
|
||||||
int unsatisfiable)
|
int unsatisfiable)
|
||||||
|
@ -1120,16 +1124,13 @@ int apk_solver_commit(struct apk_database *db,
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
if (changeset.changes == NULL)
|
|
||||||
apk_change_array_init(&changeset.changes);
|
|
||||||
|
|
||||||
if (r == 0 || (apk_flags & APK_FORCE)) {
|
if (r == 0 || (apk_flags & APK_FORCE)) {
|
||||||
/* Success -- or forced installation of bad graph */
|
/* Success -- or forced installation of bad graph */
|
||||||
commit_changeset(db, &changeset, world);
|
apk_solver_commit_changeset(db, &changeset, world);
|
||||||
r = 0;
|
r = 0;
|
||||||
} else {
|
} else {
|
||||||
/* Failure -- print errors */
|
/* Failure -- print errors */
|
||||||
print_errors(db, solution, world, r);
|
apk_solver_print_errors(db, solution, world, r);
|
||||||
}
|
}
|
||||||
apk_package_array_free(&solution);
|
apk_package_array_free(&solution);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue