diff --git a/bin/xbps-bin/main.c b/bin/xbps-bin/main.c index 6901d53901f..9ea6431a848 100644 --- a/bin/xbps-bin/main.c +++ b/bin/xbps-bin/main.c @@ -38,6 +38,7 @@ static void usage(void); static void show_missing_deps(prop_dictionary_t, const char *); static int show_missing_dep_cb(prop_object_t, void *, bool *); +static int show_reqby_pkgs(prop_object_t, void *, bool *); static int list_pkgs_in_dict(prop_object_t, void *, bool *); static void @@ -54,15 +55,18 @@ usage(void) " Options shared by all targets:\n" " -r\t\t\n" " -v\t\t\n" - " Option used by the files target:\n" + " Options used by the files target:\n" " -C\t\tTo check the SHA256 hash for any listed file.\n" + " Options used by the remove target:\n" + " -f\t\tForce removal, even if package is required by other\n" + " \t\tpackages that are currently installed.\n" "\n" " Examples:\n" " $ xbps-bin install klibc\n" " $ xbps-bin -r /path/to/root install klibc\n" " $ xbps-bin -C files klibc\n" " $ xbps-bin list\n" - " $ xbps-bin remove klibc\n" + " $ xbps-bin -f remove klibc\n" " $ xbps-bin show klibc\n"); exit(EXIT_FAILURE); } @@ -114,19 +118,43 @@ show_missing_dep_cb(prop_object_t obj, void *arg, bool *loop_done) return EINVAL; } +static int +show_reqby_pkgs(prop_object_t obj, void *arg, bool *loop_done) +{ + static size_t count; + (void)arg; + (void)loop_done; + + if (count == 0) + printf("\n\t"); + else if (count == 4) { + printf("\n\t"); + count = 0; + } + + printf("%s ", prop_string_cstring_nocopy(obj)); + count++; + + return 0; +} + int main(int argc, char **argv) { prop_dictionary_t dict; + prop_array_t reqby; char *plist, *root = NULL; int c, flags = 0, rv = 0; - bool chkhash = false; + bool chkhash = false, forcerm = false; - while ((c = getopt(argc, argv, "Cr:v")) != -1) { + while ((c = getopt(argc, argv, "Cfr:v")) != -1) { switch (c) { case 'C': chkhash = true; break; + case 'f': + forcerm = true; + break; case 'r': /* To specify the root directory */ root = optarg; @@ -198,6 +226,31 @@ main(int argc, char **argv) if (argc != 2) usage(); + /* + * First check if package is required by other packages. + */ + dict = xbps_find_pkg_installed_from_plist(argv[1]); + if (dict == NULL) { + printf("Package %s is not installed.\n", argv[1]); + exit(EXIT_FAILURE); + } + + reqby = prop_dictionary_get(dict, "requiredby"); + if (reqby != NULL && prop_array_count(reqby) > 0) { + printf("WARNING! %s is required by the following " + "packages:\n", argv[1]); + (void)xbps_callback_array_iter_in_dict(dict, + "requiredby", show_reqby_pkgs, NULL); + prop_object_release(dict); + if (!forcerm) { + printf("\n\nIf you are sure about this, use " + "-f to force deletion for this package.\n"); + exit(EXIT_FAILURE); + } else + printf("\n\nForcing %s for deletion!\n", + argv[1]); + } + rv = xbps_remove_binary_pkg(argv[1], root, flags); if (rv != 0) { if (errno == ENOENT) diff --git a/doc/TODO b/doc/TODO index a7bcc0aa03d..fcaae6b2b09 100644 --- a/doc/TODO +++ b/doc/TODO @@ -27,8 +27,6 @@ xbps-bin: * Add support to update packages. * While installing a package, check if version that is going to be installed is already installed. - * While removing a package, abort if pkg is required by others - (looking at its requiredby array object). xbps-repo: * Replace binpkg-genindex.sh with a target for xbps-repo to generate the