summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/apk_defines.h1
-rw-r--r--src/del.c20
-rw-r--r--src/state.c36
3 files changed, 46 insertions, 11 deletions
diff --git a/src/apk_defines.h b/src/apk_defines.h
index 0dc0c20..27d4ee4 100644
--- a/src/apk_defines.h
+++ b/src/apk_defines.h
@@ -62,6 +62,7 @@ extern unsigned int apk_flags;
#define APK_ALLOW_UNTRUSTED 0x0100
#define APK_PURGE 0x0200
#define APK_INTERACTIVE 0x0400
+#define APK_RECURSIVE_DELETE 0x0800
#define apk_error(args...) do { apk_log("ERROR: ", args); } while (0)
#define apk_warning(args...) do { if (apk_verbosity > 0) { apk_log("WARNING: ", args); } } while (0)
diff --git a/src/del.c b/src/del.c
index b7f2ce5..7d4a443 100644
--- a/src/del.c
+++ b/src/del.c
@@ -14,6 +14,18 @@
#include "apk_state.h"
#include "apk_database.h"
+static int del_parse(void *ctx, int optch, int optindex, const char *optarg)
+{
+ switch (optch) {
+ case 'r':
+ apk_flags |= APK_RECURSIVE_DELETE;
+ break;
+ default:
+ return -1;
+ }
+ return 0;
+}
+
static int del_main(void *ctx, int argc, char **argv)
{
struct apk_database db;
@@ -58,10 +70,18 @@ out:
return r;
}
+static struct apk_option del_options[] = {
+ { 'r', "rdepends", "Recursively delete all top-level reverse "
+ "dependencies too." },
+};
+
static struct apk_applet apk_del = {
.name = "del",
.help = "Remove PACKAGEs from the main dependencies and uninstall them.",
.arguments = "PACKAGE...",
+ .num_options = ARRAY_SIZE(del_options),
+ .options = del_options,
+ .parse = del_parse,
.main = del_main,
};
diff --git a/src/state.c b/src/state.c
index c539b02..82e3f17 100644
--- a/src/state.c
+++ b/src/state.c
@@ -406,14 +406,6 @@ int apk_state_lock_name(struct apk_state *state,
if (name->id >= state->num_names)
return -1;
- if (newpkg == NULL &&
- (name->flags & APK_NAME_TOPLEVEL) &&
- !(apk_flags & APK_FORCE)) {
- apk_error("Not deleting top level dependency '%s'. "
- "Use -f to override.", name->name);
- return -1;
- }
-
ns_free(state->name[name->id]);
state->name[name->id] = ns_from_pkg(newpkg);
@@ -651,14 +643,17 @@ int apk_state_commit(struct apk_state *state,
{
struct progress prog;
struct apk_change *change;
- int size_diff = 0;
- int r;
+ int r = 0, size_diff = 0, toplevel = FALSE, deleteonly = TRUE;
/* Count what needs to be done */
memset(&prog, 0, sizeof(prog));
list_for_each_entry(change, &state->change_list_head, change_list) {
- if (change->newpkg == NULL)
+ if (change->newpkg == NULL) {
apk_state_autoclean(state, change->oldpkg);
+ if (change->oldpkg->name->flags & APK_NAME_TOPLEVEL)
+ toplevel = TRUE;
+ } else
+ deleteonly = FALSE;
apk_count_change(change, &prog.total);
if (change->newpkg)
size_diff += change->newpkg->installed_size;
@@ -667,6 +662,17 @@ int apk_state_commit(struct apk_state *state,
}
size_diff /= 1024;
+ if (toplevel &&
+ (apk_flags & (APK_INTERACTIVE | APK_RECURSIVE_DELETE)) == 0) {
+ if (!deleteonly)
+ return -1;
+
+ dump_packages(state, cmp_remove,
+ "The top-level dependencies have been updated "
+ "but the following packages are not removed");
+ goto update_state;
+ }
+
if (apk_verbosity > 1 || (apk_flags & APK_INTERACTIVE)) {
r = dump_packages(state, cmp_remove,
"The following packages will be REMOVED");
@@ -704,6 +710,13 @@ int apk_state_commit(struct apk_state *state,
&prog);
if (r != 0)
break;
+
+ if (change->oldpkg != NULL &&
+ change->newpkg == NULL &&
+ change->oldpkg->name->flags & APK_NAME_TOPLEVEL) {
+ change->oldpkg->name->flags &= ~APK_NAME_TOPLEVEL;
+ apk_deps_del(&db->world, change->oldpkg->name);
+ }
}
apk_count_change(change, &prog.done);
@@ -711,6 +724,7 @@ int apk_state_commit(struct apk_state *state,
if (apk_flags & APK_PROGRESS)
apk_draw_progress(20, 1);
+update_state:
if (!(apk_flags & APK_SIMULATE))
apk_db_write_config(db);