diff --git a/lib/package_remove.c b/lib/package_remove.c index 32e9e635..8349f5c5 100644 --- a/lib/package_remove.c +++ b/lib/package_remove.c @@ -192,18 +192,6 @@ xbps_remove_pkg(struct xbps_handle *xhp, const char *pkgver, bool update) goto out; } - /* - * Execute the post REMOVE action if file exists and we aren't - * updating the package. - */ - rv = xbps_pkg_exec_script(xhp, pkgd, "remove-script", "post", false); - if (rv != 0) { - xbps_set_cb_state(xhp, XBPS_STATE_REMOVE_FAIL, - rv, pkgver, - "%s: [remove] REMOVE script failed to execute " - "post ACTION: %s", pkgver, strerror(rv)); - goto out; - } /* * Set package state to "half-removed". */ @@ -216,19 +204,9 @@ xbps_remove_pkg(struct xbps_handle *xhp, const char *pkgver, bool update) pkgver, strerror(rv)); goto out; } + /* XXX: setting the state and then removing the package seems useless. */ purge: - /* - * Execute the purge REMOVE action if file exists. - */ - rv = xbps_pkg_exec_script(xhp, pkgd, "remove-script", "purge", false); - if (rv != 0) { - xbps_set_cb_state(xhp, XBPS_STATE_REMOVE_FAIL, - rv, pkgver, - "%s: REMOVE script failed to execute " - "purge ACTION: %s", pkgver, strerror(rv)); - goto out; - } /* * Remove package metadata plist. */ diff --git a/lib/transaction_commit.c b/lib/transaction_commit.c index a1eb89f1..3daadf26 100644 --- a/lib/transaction_commit.c +++ b/lib/transaction_commit.c @@ -56,9 +56,56 @@ * data type is specified on its edge, i.e string, array, integer, dictionary. */ +static int +run_post_remove_scripts(struct xbps_handle *xhp, xbps_array_t remove_scripts) +{ + int rv = 0; + + for (unsigned int i = 0; i < xbps_array_count(remove_scripts); i++) { + xbps_dictionary_t dict; + bool update = false; + xbps_data_t script = NULL; + const char *pkgver = NULL; + const void *buf; + size_t buflen; + + dict = xbps_array_get(remove_scripts, i); + assert(dict); + + xbps_dictionary_get_cstring_nocopy(dict, "pkgver", &pkgver); + assert(pkgver); + + xbps_dictionary_get_bool(dict, "update", &update); + + script = xbps_dictionary_get(dict, "remove-script"); + assert(script); + + buf = xbps_data_data_nocopy(script); + buflen = xbps_data_size(script); + rv = xbps_pkg_exec_buffer(xhp, buf, buflen, pkgver, "post", update); + if (rv != 0) { + xbps_set_cb_state(xhp, XBPS_STATE_TRANS_FAIL, rv, pkgver, + "%s: [trans] REMOVE script failed to execute pre ACTION: %s", + pkgver, strerror(rv)); + goto out; + } + rv = xbps_pkg_exec_buffer(xhp, buf, buflen, pkgver, "purge", update); + if (rv != 0) { + xbps_set_cb_state(xhp, XBPS_STATE_TRANS_FAIL, rv, pkgver, + "%s: [trans] REMOVE script failed to execute pre ACTION: %s", + pkgver, strerror(rv)); + goto out; + } + } + +out: + return rv; +} + int xbps_transaction_commit(struct xbps_handle *xhp) { + xbps_array_t remove_scripts; xbps_dictionary_t pkgdb_pkgd; xbps_object_t obj; xbps_object_iterator_t iter; @@ -69,6 +116,15 @@ xbps_transaction_commit(struct xbps_handle *xhp) setlocale(LC_ALL, ""); + /* + * Store remove scripts and pkgver in this array so + * that we can run them after the package has been removed + * from the package database. + */ + remove_scripts = xbps_array_create(); + if (remove_scripts == NULL) + return errno ? errno : ENOMEM; + assert(xbps_object_type(xhp->transd) == XBPS_TYPE_DICTIONARY); /* * Create cachedir if necessary. @@ -159,8 +215,15 @@ xbps_transaction_commit(struct xbps_handle *xhp) /* * Run all pre-remove scripts. + * And store the remove scripts in remove_scripts + * so we can execute the post and purge actions + * after the package is removed from the pkgdb. */ while ((obj = xbps_object_iterator_next(iter)) != NULL) { + xbps_dictionary_t dict; + xbps_data_t script = NULL; + const char *pkgdb_pkgver; + xbps_dictionary_get_cstring_nocopy(obj, "pkgver", &pkgver); xbps_dictionary_get_cstring_nocopy(obj, "pkgname", &pkgname); @@ -170,13 +233,45 @@ xbps_transaction_commit(struct xbps_handle *xhp) "%s: %d\n", __func__, pkgver, ttype); continue; } + if ((pkgdb_pkgd = xbps_pkgdb_get_pkg(xhp, pkgname)) == NULL) { - rv = errno; + rv = ENOENT; xbps_dbg_printf(xhp, "[trans] cannot find %s in pkgdb: %s\n", - pkgver, strerror(rv)); + pkgname, strerror(rv)); goto out; } + + script = xbps_dictionary_get(pkgdb_pkgd, "remove-script"); + if (script == NULL) + continue; + + xbps_dictionary_get_cstring_nocopy(pkgdb_pkgd, "pkgver", &pkgdb_pkgver); + assert(pkgdb_pkgver); + update = ttype == XBPS_TRANS_UPDATE; + + dict = xbps_dictionary_create(); + if (dict == NULL) { + rv = errno ? errno : ENOMEM; + goto out; + } + if (!xbps_dictionary_set_cstring(dict, "pkgver", pkgdb_pkgver)) { + rv = errno ? errno : ENOMEM; + goto out; + } + if (!xbps_dictionary_set_bool(dict, "update", update)) { + rv = errno ? errno : ENOMEM; + goto out; + } + if (!xbps_dictionary_set(dict, "remove-script", script)) { + rv = errno ? errno : ENOMEM; + goto out; + } + if (!xbps_array_add(remove_scripts, dict)) { + rv = errno ? errno : ENOMEM; + goto out; + } + xbps_object_release(dict); rv = xbps_pkg_exec_script(xhp, pkgdb_pkgd, "remove-script", "pre", update); if (rv != 0) { xbps_set_cb_state(xhp, XBPS_STATE_TRANS_FAIL, rv, pkgver, @@ -289,7 +384,16 @@ xbps_transaction_commit(struct xbps_handle *xhp) goto out; /* - * Configure all unpacked packages. + * Run all post and purge-remove scripts. + */ + rv = run_post_remove_scripts(xhp, remove_scripts); + if (rv < 0) { + rv = -rv; + goto out; + } + + /* + * Configure all unpacked packages (post-install). */ xbps_set_cb_state(xhp, XBPS_STATE_TRANS_CONFIGURE, 0, NULL, NULL); @@ -325,6 +429,7 @@ xbps_transaction_commit(struct xbps_handle *xhp) } out: + xbps_object_release(remove_scripts); xbps_object_iterator_release(iter); if (rv == 0) { /* Force a pkgdb write for all unpacked pkgs in transaction */