From 0e950156fc046da707480d1e19995bc9fe50afda Mon Sep 17 00:00:00 2001 From: Duncaen Date: Tue, 2 Jul 2019 15:22:58 +0200 Subject: [PATCH] lib/transaction_{revdeps,prepare}.c: try to update packages if necessary `xbps_transaction_revdeps` will now try to add updates for packages to the transaction if the dependency is not satisified anymore due to a package install/update. `xbps_transaction_prepare` will now check the return value of `xbps_transaction_revdeps` and repeat the dependency resolution, until `xbps_transaction_revdeps` returns 0, which means that it didn't add any new packages to the transaction. --- include/xbps_api_impl.h | 2 +- lib/transaction_prepare.c | 111 ++++++++++++++++++++++---------------- lib/transaction_revdeps.c | 21 +++++++- 3 files changed, 87 insertions(+), 47 deletions(-) diff --git a/include/xbps_api_impl.h b/include/xbps_api_impl.h index 7dab942c..391dabbe 100644 --- a/include/xbps_api_impl.h +++ b/include/xbps_api_impl.h @@ -127,7 +127,7 @@ xbps_dictionary_t HIDDEN xbps_find_pkg_in_array(xbps_array_t, const char *, const char *); xbps_dictionary_t HIDDEN xbps_find_virtualpkg_in_array(struct xbps_handle *, xbps_array_t, const char *, const char *); -void HIDDEN xbps_transaction_revdeps(struct xbps_handle *, xbps_array_t); +int HIDDEN xbps_transaction_revdeps(struct xbps_handle *, xbps_array_t); bool HIDDEN xbps_transaction_shlibs(struct xbps_handle *, xbps_array_t, xbps_array_t); int HIDDEN xbps_transaction_init(struct xbps_handle *); diff --git a/lib/transaction_prepare.c b/lib/transaction_prepare.c index 425fca42..7bdd5d02 100644 --- a/lib/transaction_prepare.c +++ b/lib/transaction_prepare.c @@ -272,11 +272,13 @@ xbps_transaction_init(struct xbps_handle *xhp) return 0; } +#define MAX_REPEAT 512 + int xbps_transaction_prepare(struct xbps_handle *xhp) { xbps_array_t array, pkgs, edges; - unsigned int i, cnt; + unsigned int i, j, cnt; int rv = 0; if ((rv = xbps_transaction_init(xhp)) != 0) @@ -285,60 +287,79 @@ xbps_transaction_prepare(struct xbps_handle *xhp) if (xhp->transd == NULL) return ENXIO; - /* - * Collect dependencies for pkgs in transaction. - */ - if ((edges = xbps_array_create()) == NULL) - return ENOMEM; - /* - * The edges are also appended after its dependencies have been - * collected; the edges at the original array are removed later. - */ - pkgs = xbps_dictionary_get(xhp->transd, "packages"); - assert(xbps_object_type(pkgs) == XBPS_TYPE_ARRAY); - cnt = xbps_array_count(pkgs); - for (i = 0; i < cnt; i++) { - xbps_dictionary_t pkgd; - xbps_string_t str; - const char *tract = NULL; - - pkgd = xbps_array_get(pkgs, i); - str = xbps_dictionary_get(pkgd, "pkgver"); - xbps_dictionary_get_cstring_nocopy(pkgd, "transaction", &tract); - if ((strcmp(tract, "remove") == 0) || strcmp(tract, "hold") == 0) - continue; - - assert(xbps_object_type(str) == XBPS_TYPE_STRING); - - if (!xbps_array_add(edges, str)) + for (j = 0; j < MAX_REPEAT; j++) { + /* + * Collect dependencies for pkgs in transaction. + */ + if ((edges = xbps_array_create()) == NULL) return ENOMEM; + /* + * The edges are also appended after its dependencies have been + * collected; the edges at the original array are removed later. + */ + pkgs = xbps_dictionary_get(xhp->transd, "packages"); + assert(xbps_object_type(pkgs) == XBPS_TYPE_ARRAY); + cnt = xbps_array_count(pkgs); + for (i = 0; i < cnt; i++) { + xbps_dictionary_t pkgd; + xbps_string_t str; + const char *tract = NULL; - if ((rv = xbps_repository_find_deps(xhp, pkgs, pkgd)) != 0) + pkgd = xbps_array_get(pkgs, i); + str = xbps_dictionary_get(pkgd, "pkgver"); + xbps_dictionary_get_cstring_nocopy(pkgd, "transaction", &tract); + if ((strcmp(tract, "remove") == 0) || strcmp(tract, "hold") == 0) + continue; + + assert(xbps_object_type(str) == XBPS_TYPE_STRING); + + if (!xbps_array_add(edges, str)) + return ENOMEM; + + if ((rv = xbps_repository_find_deps(xhp, pkgs, pkgd)) != 0) + return rv; + + if (!xbps_array_add(pkgs, pkgd)) + return ENOMEM; + } + /* ... remove dup edges at head */ + for (i = 0; i < xbps_array_count(edges); i++) { + const char *pkgver = NULL; + xbps_array_get_cstring_nocopy(edges, i, &pkgver); + xbps_remove_pkg_from_array_by_pkgver(pkgs, pkgver); + } + xbps_object_release(edges); + + /* + * Check for packages to be replaced. + */ + if ((rv = xbps_transaction_package_replace(xhp, pkgs)) != 0) { + xbps_object_release(xhp->transd); + xhp->transd = NULL; + return rv; + } + /* + * Check reverse dependencies. + */ + if ((rv = xbps_transaction_revdeps(xhp, pkgs)) == 0) + break; + if (rv != EAGAIN) return rv; - - if (!xbps_array_add(pkgs, pkgd)) - return ENOMEM; } - /* ... remove dup edges at head */ - for (i = 0; i < xbps_array_count(edges); i++) { - const char *pkgver = NULL; - xbps_array_get_cstring_nocopy(edges, i, &pkgver); - xbps_remove_pkg_from_array_by_pkgver(pkgs, pkgver); - } - xbps_object_release(edges); - /* - * Check for packages to be replaced. + * Repeated too many times. */ - if ((rv = xbps_transaction_package_replace(xhp, pkgs)) != 0) { - xbps_object_release(xhp->transd); - xhp->transd = NULL; - return rv; + if (j == MAX_REPEAT) { + xbps_dbg_printf(xhp, "[trans] aborted due to too many repetitions" + " while resolving dependencies!\n"); + return ELOOP; + } else { + xbps_dbg_printf(xhp, "[trans] resolved dependencies in" + " %d repetitions.\n", j); } /* * If there are missing deps or revdeps bail out. */ - xbps_transaction_revdeps(xhp, pkgs); array = xbps_dictionary_get(xhp->transd, "missing_deps"); if (xbps_array_count(array)) { if (xhp->flags & XBPS_FLAG_FORCE_REMOVE_REVDEPS) { diff --git a/lib/transaction_revdeps.c b/lib/transaction_revdeps.c index fb27d97d..ee686301 100644 --- a/lib/transaction_revdeps.c +++ b/lib/transaction_revdeps.c @@ -101,10 +101,21 @@ broken_pkg(xbps_array_t mdeps, const char *dep, const char *pkg, const char *tra free(str); } -void HIDDEN +static int +update_pkg(struct xbps_handle *xhp, const char *pkg) +{ + int rv = 0; + rv = xbps_transaction_update_pkg(xhp, pkg); + if (rv == EEXIST) + return 0; + return rv; +} + +int HIDDEN xbps_transaction_revdeps(struct xbps_handle *xhp, xbps_array_t pkgs) { xbps_array_t mdeps; + int updated = 0; mdeps = xbps_dictionary_get(xhp->transd, "missing_deps"); @@ -235,9 +246,17 @@ xbps_transaction_revdeps(struct xbps_handle *xhp, xbps_array_t pkgs) free(pkgname); continue; } + if (update_pkg(xhp, pkgname) == 0) { + updated++; + free(pkgname); + continue; + } free(pkgname); broken_pkg(mdeps, curpkgver, pkgver, tract); } } + if (updated > 0) + return EAGAIN; + return 0; }