diff --git a/bin/xbps-bin/defs.h b/bin/xbps-bin/defs.h index 940f7318..b94f2e6e 100644 --- a/bin/xbps-bin/defs.h +++ b/bin/xbps-bin/defs.h @@ -43,7 +43,7 @@ struct list_pkgver_cb { size_t pkgver_len; }; -/* from install.c */ +/* from transaction.c */ int install_new_pkg(const char *); int update_pkg(const char *); int autoupdate_pkgs(bool, bool); diff --git a/bin/xbps-bin/remove.c b/bin/xbps-bin/remove.c index 5e406b41..0727000f 100644 --- a/bin/xbps-bin/remove.c +++ b/bin/xbps-bin/remove.c @@ -48,65 +48,6 @@ pkg_remove_and_purge(const char *pkgname, const char *version, bool purge) return rv; } -int -autoremove_pkgs(bool yes, bool purge) -{ - prop_array_t orphans = NULL; - prop_object_t obj = NULL; - prop_object_iterator_t iter = NULL; - const char *pkgver, *pkgname, *version; - int rv = 0; - - /* - * Removes orphan pkgs. These packages were installed - * as dependency and any installed package does not depend - * on it currently. - */ - orphans = xbps_find_pkg_orphans(NULL); - if (orphans == NULL) - return errno; - - if (prop_array_count(orphans) == 0) { - printf("There are not orphaned packages currently.\n"); - goto out; - } - - iter = prop_array_iterator(orphans); - if (iter == NULL) { - rv = errno; - goto out; - } - - printf("The following packages were installed automatically\n" - "(as dependencies) and aren't needed anymore:\n\n"); - while ((obj = prop_object_iterator_next(iter)) != NULL) { - prop_dictionary_get_cstring_nocopy(obj, "pkgver", &pkgver); - print_package_line(pkgver, false); - } - prop_object_iterator_reset(iter); - printf("\n\n"); - - if (!yes && !noyes("Do you want to continue?")) { - printf("Cancelled!\n"); - goto out; - } - - while ((obj = prop_object_iterator_next(iter)) != NULL) { - prop_dictionary_get_cstring_nocopy(obj, "pkgname", &pkgname); - prop_dictionary_get_cstring_nocopy(obj, "version", &version); - if ((rv = pkg_remove_and_purge(pkgname, version, purge)) != 0) - goto out; - } - -out: - if (iter) - prop_object_iterator_release(iter); - if (orphans) - prop_object_release(orphans); - - return rv; -} - int remove_installed_pkgs(int argc, char **argv, bool yes, bool purge, bool force_rm_with_deps, bool recursive_rm) diff --git a/bin/xbps-bin/transaction.c b/bin/xbps-bin/transaction.c index db25842c..80ca7e20 100644 --- a/bin/xbps-bin/transaction.c +++ b/bin/xbps-bin/transaction.c @@ -207,6 +207,24 @@ autoupdate_pkgs(bool yes, bool show_download_pkglist_url) return exec_transaction(yes, show_download_pkglist_url); } +int +autoremove_pkgs(bool yes, bool purge) +{ + int rv = 0; + + if ((rv = xbps_transaction_autoremove_pkgs(purge)) != 0) { + if (rv == ENOENT) { + printf("No package orphans were found.\n"); + return 0; + } else { + printf("Failed to autoremove packages: %s\n", + strerror(rv)); + return rv; + } + } + return exec_transaction(yes, false); +} + int install_new_pkg(const char *pkg) { diff --git a/include/xbps_api.h b/include/xbps_api.h index b839d27c..f634e962 100644 --- a/include/xbps_api.h +++ b/include/xbps_api.h @@ -55,7 +55,7 @@ */ #define XBPS_PKGINDEX_VERSION "1.3" -#define XBPS_API_VERSION "20111125-1" +#define XBPS_API_VERSION "20111125-2" #define XBPS_VERSION "0.11.0" /** @@ -1176,6 +1176,17 @@ int xbps_transaction_update_pkg(const char *pkgname); */ int xbps_transaction_update_packages(void); +/** + * Finds all package orphans currently installed and adds them into + * the transaction dictionary. + * + * @param[in] purge If true packages will also be purged. + * + * @return 0 on succcess, ENOENT if no package orphans were found, ENXIO + * or EINVAL if a problem ocurred in the process. + */ +int xbps_transaction_autoremove_pkgs(bool purge); + /** * Returns the transaction dictionary, as shown above in the image. * Before returning the package list is sorted in the correct order diff --git a/lib/transaction_commit.c b/lib/transaction_commit.c index fce79807..9b3e7cb2 100644 --- a/lib/transaction_commit.c +++ b/lib/transaction_commit.c @@ -169,10 +169,11 @@ xbps_transaction_commit(prop_dictionary_t transd) prop_object_iterator_t iter; const char *pkgname, *version, *pkgver, *tract; int rv = 0; - bool update; + bool update, install, purge; assert(prop_object_type(transd) == PROP_TYPE_DICTIONARY); + update = install = purge = false; xhp = xbps_handle_get(); iter = xbps_array_iter_from_dict(transd, "packages"); if (iter == NULL) @@ -203,15 +204,18 @@ xbps_transaction_commit(prop_dictionary_t transd) prop_dictionary_get_cstring_nocopy(obj, "pkgver", &pkgver); if (strcmp(tract, "remove") == 0) { + purge = update = false; /* - * Remove a package. + * Remove and optionally also purge package. */ prop_dictionary_get_bool(obj, "remove-and-update", &update); + prop_dictionary_get_bool(obj, "remove-and-purge", + &purge); rv = xbps_remove_pkg(pkgname, version, update); if (rv != 0) goto out; - if (update) + if (update || !purge) continue; if ((rv = xbps_purge_pkg(pkgname, false)) != 0) @@ -229,6 +233,8 @@ xbps_transaction_commit(prop_dictionary_t transd) */ if (strcmp(tract, "update") == 0) update = true; + else + install = true; if (update) { /* @@ -265,6 +271,10 @@ xbps_transaction_commit(prop_dictionary_t transd) } } prop_object_iterator_reset(iter); + + /* if there are no packages to install or update we are done */ + if (!update && !install) + goto out; /* * Configure all unpacked packages. */ diff --git a/lib/transaction_ops.c b/lib/transaction_ops.c index 87253259..ae534e37 100644 --- a/lib/transaction_ops.c +++ b/lib/transaction_ops.c @@ -236,3 +236,55 @@ xbps_transaction_install_pkg(const char *pkgpattern) { return transaction_find_pkg(pkgpattern, "install"); } + +int +xbps_transaction_autoremove_pkgs(bool purge) +{ + prop_dictionary_t transd; + prop_array_t orphans, mdeps, unsorted; + prop_object_t obj; + const char *pkgver; + size_t count; + int rv = 0; + + orphans = xbps_find_pkg_orphans(NULL); + if (prop_object_type(orphans) != PROP_TYPE_ARRAY) + return EINVAL; + + count = prop_array_count(orphans); + if (count == 0) { + /* no orphans? we are done */ + rv = ENOENT; + goto out; + } + /* + * Prepare transaction dictionary and missing deps array. + */ + if ((transd = xbps_transaction_dictionary_get()) == NULL) { + rv = ENXIO; + goto out; + } + if ((mdeps = xbps_transaction_missingdeps_get()) == NULL) { + rv = ENXIO; + goto out; + } + /* + * Add pkg orphan dictionary into the unsorted_deps array. + */ + unsorted = prop_dictionary_get(transd, "unsorted_deps"); + while (count--) { + obj = prop_array_get(orphans, count); + prop_dictionary_get_cstring_nocopy(obj, "pkgver", &pkgver); + prop_dictionary_set_cstring_nocopy(obj, + "transaction", "remove"); + if (purge) + prop_dictionary_set_bool(obj, "remove-and-purge", true); + prop_array_add(unsorted, obj); + xbps_dbg_printf("%s: added into transaction (remove).\n", + pkgver); + } +out: + if (prop_object_type(orphans) == PROP_TYPE_ARRAY) + prop_object_release(orphans); + return rv; +}