From: Michael Tremer Date: Mon, 9 May 2022 16:12:37 +0000 (+0000) Subject: callbacks: Rework them to be easier to pass around X-Git-Tag: 0.9.28~810 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=8a2ff479f94ab68094a109448f496641980da685;p=pakfire.git callbacks: Rework them to be easier to pass around Signed-off-by: Michael Tremer --- diff --git a/src/_pakfire/pakfire.c b/src/_pakfire/pakfire.c index 32965390e..eda9663d5 100644 --- a/src/_pakfire/pakfire.c +++ b/src/_pakfire/pakfire.c @@ -51,8 +51,6 @@ static PyObject* Pakfire_new(PyTypeObject* type, PyObject* args, PyObject* kwds) // Callbacks self->callbacks.log = NULL; self->callbacks.confirm = NULL; - self->callbacks.status = NULL; - self->callbacks.progress = NULL; } return (PyObject *)self; @@ -134,52 +132,6 @@ static int Pakfire_confirm_callback(struct pakfire* pakfire, void* data, return r; } -static void Pakfire_status_callback(void* data, const char* message) { - struct callbacks* callbacks = (struct callbacks*)data; - - // Do nothing if callback isn't set - if (!callbacks->status) - return; - - PyObject* args = NULL; - PyObject* result = NULL; - - // Create arguments tuple - args = Py_BuildValue("(s)", message); - if (!args) - goto ERROR; - - // Call the callback - result = PyObject_CallObject(callbacks->status, args); - -ERROR: - Py_XDECREF(args); - Py_XDECREF(result); -} - -static void Pakfire_progress_callback(void* data, int progress) { - struct callbacks* callbacks = (struct callbacks*)data; - - // Do nothing if callback isn't set - if (!callbacks->progress) - return; - - PyObject* args = NULL; - PyObject* result = NULL; - - // Create arguments tuple - args = Py_BuildValue("(i)", progress); - if (!args) - goto ERROR; - - // Call the callback - result = PyObject_CallObject(callbacks->progress, args); - -ERROR: - Py_XDECREF(args); - Py_XDECREF(result); -} - static int Pakfire_init(PakfireObject* self, PyObject* args, PyObject* kwds) { char* kwlist[] = { "path", @@ -291,10 +243,6 @@ static void Pakfire_dealloc(PakfireObject* self) { pakfire_unref(self->pakfire); } - // Free callbacks - Py_XDECREF(self->callbacks.status); - Py_XDECREF(self->callbacks.progress); - Py_TYPE(self)->tp_free((PyObject *)self); } @@ -333,6 +281,26 @@ static PyObject* Pakfire_get_repo(PakfireObject* self, PyObject* args) { return obj; } +static void Pakfire_status_callback(struct pakfire* pakfire, void* data, + int progress, const char* status) { + PyObject* callback = (PyObject*)data; + + // Do not attempt to call nothing + if (!callback) + return; + + // Compile arguments + PyObject* args = Py_BuildValue("(is)", progress, status); + if (!args) + return; + + // Call the callback + PyObject* result = PyObject_CallObject(callback, args); + + Py_XDECREF(result); + Py_DECREF(args); +} + static int convert_packages(PyObject* object, void* address) { char*** packages = (char***)address; @@ -403,6 +371,7 @@ static PyObject* Pakfire_install(PakfireObject* self, PyObject* args, PyObject* "without_recommended", "allow_uninstall", "allow_downgrade", + "status_callback", NULL }; char** packages = NULL; @@ -410,11 +379,18 @@ static PyObject* Pakfire_install(PakfireObject* self, PyObject* args, PyObject* int allow_uninstall = 0; int allow_downgrade = 0; int solver_flags = 0; + PyObject* status_callback = NULL; - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&|$ppp", kwlist, + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&|$pppO", kwlist, convert_packages, &packages, &without_recommended, &allow_uninstall, - &allow_downgrade)) + &allow_downgrade, &status_callback)) + return NULL; + + // Check if callback is callable + if (status_callback && !PyCallable_Check(status_callback)) { + PyErr_SetString(PyExc_TypeError, "status_callback must be callable"); return NULL; + } // Do not install recommended packages if (without_recommended) @@ -429,7 +405,8 @@ static PyObject* Pakfire_install(PakfireObject* self, PyObject* args, PyObject* solver_flags |= PAKFIRE_REQUEST_ALLOW_DOWNGRADE; // Run pakfire_install - int r = pakfire_install(self->pakfire, solver_flags, (const char**)packages, NULL, 0, NULL); + int r = pakfire_install(self->pakfire, solver_flags, (const char**)packages, + NULL, 0, NULL, Pakfire_status_callback, status_callback); if (r) PyErr_SetFromErrno(PyExc_OSError); @@ -449,21 +426,30 @@ static PyObject* Pakfire_erase(PakfireObject* self, PyObject* args, PyObject* kw char* kwlist[] = { "packages", "keep_dependencies", + "status_callback", NULL }; char** packages = NULL; int keep_dependencies = 0; int flags = 0; + PyObject* status_callback = NULL; - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&|$p", kwlist, - convert_packages, &packages, &keep_dependencies)) + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&|$pO", kwlist, + convert_packages, &packages, &keep_dependencies, &status_callback)) return NULL; + // Check if callback is callable + if (status_callback && !PyCallable_Check(status_callback)) { + PyErr_SetString(PyExc_TypeError, "status_callback must be callable"); + return NULL; + } + if (keep_dependencies) flags |= PAKFIRE_REQUEST_KEEP_DEPS; // Run pakfire_erase - int r = pakfire_erase(self->pakfire, 0, (const char**)packages, NULL, flags, NULL); + int r = pakfire_erase(self->pakfire, 0, (const char**)packages, NULL, flags, NULL, + Pakfire_status_callback, status_callback); if (r) PyErr_SetFromErrno(PyExc_OSError); @@ -485,6 +471,7 @@ static PyObject* Pakfire_update(PakfireObject* self, PyObject* args, PyObject* k "excludes", "allow_uninstall", "allow_downgrade", + "status_callback", NULL }; char** packages = NULL; @@ -492,11 +479,18 @@ static PyObject* Pakfire_update(PakfireObject* self, PyObject* args, PyObject* k int allow_uninstall = 0; int allow_downgrade = 0; int solver_flags = 0; + PyObject* status_callback = NULL; - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&|$O&pp", kwlist, + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&|$O&ppO", kwlist, convert_packages, &packages, convert_packages, &excludes, - &allow_uninstall, &allow_downgrade)) + &allow_uninstall, &allow_downgrade, &status_callback)) + return NULL; + + // Check if callback is callable + if (status_callback && !PyCallable_Check(status_callback)) { + PyErr_SetString(PyExc_TypeError, "status_callback must be callable"); return NULL; + } // Can the solver uninstall packages? if (allow_uninstall) @@ -508,7 +502,7 @@ static PyObject* Pakfire_update(PakfireObject* self, PyObject* args, PyObject* k // Run pakfire_update int r = pakfire_update(self->pakfire, solver_flags, (const char**)packages, - (const char**)excludes, 0, NULL); + (const char**)excludes, 0, NULL, Pakfire_status_callback, status_callback); if (r) PyErr_SetFromErrno(PyExc_OSError); @@ -1135,17 +1129,24 @@ static PyObject* Pakfire_check(PakfireObject* self) { } static PyObject* Pakfire_sync(PakfireObject* self, PyObject* args, PyObject* kwargs) { - char* kwlist[] = {"keep_orphaned", NULL}; + char* kwlist[] = { + "keep_orphaned", + "status_callback", + NULL, + }; int keep_orphaned = 0; int flags = 0; + PyObject* status_callback = NULL; - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|$p", kwlist, &keep_orphaned)) + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|$pO", kwlist, + &keep_orphaned, &status_callback)) return NULL; if (keep_orphaned) flags |= PAKFIRE_REQUEST_KEEP_ORPHANED; - int r = pakfire_sync(self->pakfire, 0, flags, NULL); + int r = pakfire_sync(self->pakfire, 0, flags, NULL, + Pakfire_status_callback, status_callback); if (r) { PyErr_SetFromErrno(PyExc_OSError); return NULL; diff --git a/src/_pakfire/pakfire.h b/src/_pakfire/pakfire.h index 5a5c6b3f0..5a37fabe0 100644 --- a/src/_pakfire/pakfire.h +++ b/src/_pakfire/pakfire.h @@ -33,8 +33,6 @@ typedef struct { struct callbacks { PyObject* log; PyObject* confirm; - PyObject* status; - PyObject* progress; } callbacks; } PakfireObject; diff --git a/src/libpakfire/build.c b/src/libpakfire/build.c index b9ae91439..3a1080194 100644 --- a/src/libpakfire/build.c +++ b/src/libpakfire/build.c @@ -757,7 +757,7 @@ PAKFIRE_EXPORT int pakfire_build(struct pakfire* pakfire, const char* path, }; // Install the package into the build environment - r = pakfire_install(pakfire, 0, packages, NULL, 0, NULL); + r = pakfire_install(pakfire, 0, packages, NULL, 0, NULL, NULL, NULL); if (r) { ERROR(pakfire, "Could not install %s\n", path); goto ERROR; diff --git a/src/libpakfire/include/pakfire/pakfire.h b/src/libpakfire/include/pakfire/pakfire.h index ba162bda6..ec731a8d2 100644 --- a/src/libpakfire/include/pakfire/pakfire.h +++ b/src/libpakfire/include/pakfire/pakfire.h @@ -60,6 +60,8 @@ typedef int (*pakfire_confirm_callback)(struct pakfire* pakfire, void* data, const char* message, const char* question); void pakfire_set_confirm_callback(struct pakfire* pakfire, pakfire_confirm_callback callback, void* data); +typedef void (*pakfire_status_callback)(struct pakfire* pakfire, void* data, + int progress, const char* status); int pakfire_create(struct pakfire** pakfire, const char* path, const char* arch, const char* conf, int flags, pakfire_log_callback log_callback, void* log_data); @@ -108,11 +110,14 @@ void pakfire_log_set_priority(struct pakfire* pakfire, int priority); // Install/Erase/Update int pakfire_install(struct pakfire* pakfire, int solver_flags, const char** packages, - const char** locks, int job_flags, int* changed); + const char** locks, int job_flags, int* changed, + pakfire_status_callback status_callback, void* status_callback_data); int pakfire_erase(struct pakfire* pakfire, int solver_flags, const char** packages, - const char** locks, int job_flags, int* changed); + const char** locks, int job_flags, int* changed, + pakfire_status_callback status_callback, void* status_callback_data); int pakfire_update(struct pakfire* pakfire, int solver_flags, const char** packages, - const char** locks, int jobs_flags, int* changed); + const char** locks, int jobs_flags, int* changed, + pakfire_status_callback status_callback, void* status_callback_data); // Check @@ -120,7 +125,8 @@ int pakfire_check(struct pakfire* pakfire); // Sync -int pakfire_sync(struct pakfire* pakfire, int solver_flags, int flags, int* changed); +int pakfire_sync(struct pakfire* pakfire, int solver_flags, int flags, int* changed, + pakfire_status_callback status_callback, void* status_callback_data); #ifdef PAKFIRE_PRIVATE @@ -145,8 +151,6 @@ struct pakfire_config* pakfire_get_config(struct pakfire* pakfire); int pakfire_is_mountpoint(struct pakfire* pakfire, const char* path); int pakfire_confirm(struct pakfire* pakfire, const char* message, const char* question); -void pakfire_call_status_callback(struct pakfire* pakfire, const char* message, ...); -void pakfire_call_progress_callback(struct pakfire* pakfire, int progress); gpgme_ctx_t pakfire_get_gpgctx(struct pakfire* pakfire); diff --git a/src/libpakfire/include/pakfire/transaction.h b/src/libpakfire/include/pakfire/transaction.h index e5bbf7502..0cabaa81c 100644 --- a/src/libpakfire/include/pakfire/transaction.h +++ b/src/libpakfire/include/pakfire/transaction.h @@ -29,6 +29,9 @@ struct pakfire_transaction* pakfire_transaction_unref(struct pakfire_transaction size_t pakfire_transaction_count(struct pakfire_transaction* transaction); char* pakfire_transaction_dump(struct pakfire_transaction* transaction, size_t width); +void pakfire_transaction_set_status_callback( + struct pakfire_transaction* transaction, pakfire_status_callback callback, void* data); + int pakfire_transaction_run(struct pakfire_transaction* transaction); int pakfire_transaction_download(struct pakfire_transaction* transaction); @@ -37,7 +40,6 @@ int pakfire_transaction_download(struct pakfire_transaction* transaction); #include - int pakfire_transaction_create(struct pakfire_transaction** transaction, struct pakfire* pakfire, Solver* solver); diff --git a/src/libpakfire/pakfire.c b/src/libpakfire/pakfire.c index 970df779c..5b6991186 100644 --- a/src/libpakfire/pakfire.c +++ b/src/libpakfire/pakfire.c @@ -97,18 +97,6 @@ struct pakfire { // Confirm pakfire_confirm_callback confirm; void* confirm_data; - - // Status - void (*status)(void* data, const char* message); - void* status_data; - - // Progress - void (*progress)(void* data, int progress); - void* progress_data; - - // Speed - void (*speed)(void* data, const char* speed); - void* speed_data; } callbacks; // Logging @@ -1144,39 +1132,6 @@ void pakfire_release_lock(struct pakfire* pakfire) { unlink(pakfire->lock_path); } -void pakfire_call_status_callback(struct pakfire* pakfire, const char* message, ...) { - char* buffer = NULL; - va_list args; - int r; - - // Do nothing if call isn't set - if (!pakfire->callbacks.status) - return; - - // Format the message - va_start(args, message); - r = vasprintf(&buffer, message, args); - va_end(args); - - if (r < 0) - return; - - // Call the callback - pakfire->callbacks.status(pakfire->callbacks.status_data, buffer); - - // Cleanup - if (buffer) - free(buffer); -} - -void pakfire_call_progress_callback(struct pakfire* pakfire, int progress) { - // Do nothing if call isn't set - if (!pakfire->callbacks.progress) - return; - - pakfire->callbacks.progress(pakfire->callbacks.progress_data, progress); -} - const char* pakfire_get_keystore_path(struct pakfire* pakfire) { return pakfire->keystore_path; } @@ -1867,7 +1822,8 @@ struct archive* pakfire_make_archive_disk_writer(struct pakfire* pakfire) { static int pakfire_perform_transaction(struct pakfire* pakfire, int solver_flags, int (*action)(struct pakfire_request* request, const char* what, int flags), - const char** packages, const char** locks, int job_flags, int* changed) { + const char** packages, const char** locks, int job_flags, int* changed, + pakfire_status_callback status_callback, void* status_callback_data) { struct pakfire_request* request = NULL; struct pakfire_transaction* transaction = NULL; struct pakfire_problem** problems = NULL; @@ -1945,6 +1901,11 @@ static int pakfire_perform_transaction(struct pakfire* pakfire, int solver_flags if (changed) *changed = pakfire_transaction_count(transaction); + // Set status callback + if (status_callback) + pakfire_transaction_set_status_callback( + transaction, status_callback, status_callback_data); + // Run the transaction r = pakfire_transaction_run(transaction); if (r) @@ -1972,20 +1933,23 @@ ERROR: } PAKFIRE_EXPORT int pakfire_install(struct pakfire* pakfire, int solver_flags, - const char** packages, const char** locks, int flags, int* changed) { + const char** packages, const char** locks, int flags, int* changed, + pakfire_status_callback status_callback, void* status_callback_data) { return pakfire_perform_transaction(pakfire, solver_flags, pakfire_request_install, - packages, locks, flags, changed); + packages, locks, flags, changed, status_callback, status_callback_data); } PAKFIRE_EXPORT int pakfire_erase(struct pakfire* pakfire, int solver_flags, - const char** packages, const char** locks, int flags, int* changed) { + const char** packages, const char** locks, int flags, int* changed, + pakfire_status_callback status_callback, void* status_callback_data) { return pakfire_perform_transaction(pakfire, solver_flags, pakfire_request_erase, - packages, locks, flags, changed); + packages, locks, flags, changed, status_callback, status_callback_data); } static int pakfire_perform_transaction_simple(struct pakfire* pakfire, int solver_flags, int (*action)(struct pakfire_request* request, int flags), - int job_flags, int* changed) { + int job_flags, int* changed, + pakfire_status_callback status_callback, void* status_callback_data) { struct pakfire_request* request = NULL; struct pakfire_transaction* transaction = NULL; struct pakfire_problem** problems = NULL; @@ -2042,6 +2006,11 @@ static int pakfire_perform_transaction_simple(struct pakfire* pakfire, int solve if (changed) *changed = pakfire_transaction_count(transaction); + // Set status callback + if (status_callback) + pakfire_transaction_set_status_callback( + transaction, status_callback, status_callback_data); + // Run the transaction r = pakfire_transaction_run(transaction); if (r) @@ -2068,19 +2037,22 @@ ERROR: } PAKFIRE_EXPORT int pakfire_update(struct pakfire* pakfire, int solver_flags, - const char** packages, const char** locks, int flags, int* changed) { + const char** packages, const char** locks, int flags, int* changed, + pakfire_status_callback status_callback, void* status_callback_data) { // If no packages are being passed, we will try to update everything // XXX add locks if (!packages) return pakfire_perform_transaction_simple( - pakfire, solver_flags, pakfire_request_update_all, flags, changed); + pakfire, solver_flags, pakfire_request_update_all, flags, changed, + status_callback, status_callback_data); return pakfire_perform_transaction(pakfire, solver_flags, pakfire_request_update, - packages, locks, flags, changed); + packages, locks, flags, changed, status_callback, status_callback_data); } static int pakfire_verify(struct pakfire* pakfire, int *changed) { - return pakfire_perform_transaction_simple(pakfire, 0, pakfire_request_verify, 0, changed); + return pakfire_perform_transaction_simple(pakfire, 0, pakfire_request_verify, + 0, changed, NULL, NULL); } PAKFIRE_EXPORT int pakfire_check(struct pakfire* pakfire) { @@ -2109,9 +2081,10 @@ ERROR: return r; } -PAKFIRE_EXPORT int pakfire_sync(struct pakfire* pakfire, int solver_flags, int flags, int* changed) { +PAKFIRE_EXPORT int pakfire_sync(struct pakfire* pakfire, int solver_flags, int flags, + int* changed, pakfire_status_callback status_callback, void* status_callback_data) { return pakfire_perform_transaction_simple(pakfire, solver_flags, - pakfire_request_sync, flags, changed); + pakfire_request_sync, flags, changed, status_callback, status_callback_data); } // Build Stuff @@ -2135,7 +2108,7 @@ static int pakfire_build_install_packages(struct pakfire* pakfire, int* snapshot int changed = 0; // Install everything - r = pakfire_install(pakfire, 0, (const char**)packages, NULL, 0, &changed); + r = pakfire_install(pakfire, 0, (const char**)packages, NULL, 0, &changed, NULL, NULL); if (r) { ERROR(pakfire, "Could not install build dependencies: %m\n"); goto ERROR; @@ -2146,7 +2119,7 @@ static int pakfire_build_install_packages(struct pakfire* pakfire, int* snapshot *snapshot_needs_update = 1; // Update everything - r = pakfire_sync(pakfire, 0, 0, &changed); + r = pakfire_sync(pakfire, 0, 0, &changed, NULL, NULL); if (r) { ERROR(pakfire, "Could not update packages: %m\n"); goto ERROR; diff --git a/src/libpakfire/transaction.c b/src/libpakfire/transaction.c index 0b8ba0f66..e7f92b6a9 100644 --- a/src/libpakfire/transaction.c +++ b/src/libpakfire/transaction.c @@ -54,6 +54,13 @@ struct pakfire_transaction { struct pakfire_package** packages; size_t num; size_t progress; + + // Callbacks + struct pakfire_transaction_callbacks { + // Status + pakfire_status_callback status; + void* status_data; + } callbacks; }; enum pakfire_actions { @@ -262,10 +269,48 @@ PAKFIRE_EXPORT struct pakfire_transaction* pakfire_transaction_unref( return NULL; } +void pakfire_transaction_set_status_callback(struct pakfire_transaction* transaction, + pakfire_status_callback callback, void* data) { + transaction->callbacks.status = callback; + transaction->callbacks.status_data = data; +} + static int pakfire_transaction_get_progress(struct pakfire_transaction* transaction) { return transaction->progress * 100 / transaction->num; } +static void pakfire_transaction_status(struct pakfire_transaction* transaction, + const char* message, ...) { + char* buffer = NULL; + va_list args; + int r; + + // Do nothing if callback isn't set + if (!transaction->callbacks.status) + return; + + // Format the message + if (message) { + va_start(args, message); + r = vasprintf(&buffer, message, args); + va_end(args); + + if (r < 0) + return; + } + + // Fetch progress + const int progress = pakfire_transaction_get_progress(transaction); + + // Call the callback + transaction->callbacks.status(transaction->pakfire, + transaction->callbacks.status_data, progress, buffer); + + // Cleanup + if (buffer) + free(buffer); +} + PAKFIRE_EXPORT size_t pakfire_transaction_count(struct pakfire_transaction* transaction) { return transaction->num; } @@ -701,7 +746,7 @@ static int pakfire_transaction_extract(struct pakfire_transaction* transaction, const char* nevra = pakfire_package_get_nevra(pkg); // Update status - pakfire_call_status_callback(transaction->pakfire, _("Installing %s..."), nevra); + pakfire_transaction_status(transaction, _("Installing %s..."), nevra); // Extract payload to the root of the Pakfire instance int r = pakfire_archive_extract(archive, NULL); @@ -877,8 +922,7 @@ static int pakfire_transaction_run_step(struct pakfire_transaction* transaction, transaction->progress++; // Update progress callback - pakfire_call_progress_callback(transaction->pakfire, - pakfire_transaction_get_progress(transaction)); + pakfire_transaction_status(transaction, NULL); switch (type) { case PAKFIRE_STEP_INSTALL: @@ -970,15 +1014,15 @@ static int pakfire_transaction_run_steps(struct pakfire_transaction* transaction // Update status switch (action) { case PAKFIRE_ACTION_VERIFY: - pakfire_call_status_callback(transaction->pakfire, _("Verifying packages...")); + pakfire_transaction_status(transaction, _("Verifying packages...")); break; case PAKFIRE_ACTION_PRETRANS: - pakfire_call_status_callback(transaction->pakfire, _("Preparing installation...")); + pakfire_transaction_status(transaction, _("Preparing installation...")); break; case PAKFIRE_ACTION_POSTTRANS: - pakfire_call_status_callback(transaction->pakfire, _("Finishing up...")); + pakfire_transaction_status(transaction, _("Finishing up...")); break; default: