]> git.ipfire.org Git - pakfire.git/commitdiff
pakfire: Introduce confirm callback
authorMichael Tremer <michael.tremer@ipfire.org>
Mon, 9 May 2022 10:04:51 +0000 (10:04 +0000)
committerMichael Tremer <michael.tremer@ipfire.org>
Mon, 9 May 2022 10:15:57 +0000 (10:15 +0000)
Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
src/_pakfire/pakfire.c
src/_pakfire/pakfire.h
src/libpakfire/include/pakfire/pakfire.h
src/libpakfire/include/pakfire/ui.h
src/libpakfire/libpakfire.sym
src/libpakfire/pakfire.c
src/libpakfire/transaction.c
src/libpakfire/ui.c

index dac3e3ab7301ae9347c25746f5f64840165a0cd0..32965390e4d991dda9aa4747d8a7b7921071a813 100644 (file)
@@ -50,6 +50,7 @@ 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;
        }
@@ -108,6 +109,31 @@ ERROR:
        Py_XDECREF(result);
 }
 
+static int Pakfire_confirm_callback(struct pakfire* pakfire, void* data,
+               const char* message, const char* question) {
+       PyObject* callback = (PyObject*)data;
+       int r = 0;
+
+       // Do nothing if callback isn't set
+       if (!callback)
+               return 0;
+
+       PyObject* args = Py_BuildValue("(ss)", message, question);
+       if (!args)
+               return -1;
+
+       PyObject* result = PyObject_CallObject(callback, args);
+
+       // Extract return code
+       if (PyLong_Check(result))
+               r = PyLong_AsLong(result);
+
+       Py_DECREF(args);
+       Py_DECREF(result);
+
+       return r;
+}
+
 static void Pakfire_status_callback(void* data, const char* message) {
        struct callbacks* callbacks = (struct callbacks*)data;
 
@@ -165,6 +191,7 @@ static int Pakfire_init(PakfireObject* self, PyObject* args, PyObject* kwds) {
                "build",
                "enable_ccache",
                "enable_snapshot",
+               "confirm_callback",
                NULL,
        };
        const char* path = NULL;
@@ -176,9 +203,9 @@ static int Pakfire_init(PakfireObject* self, PyObject* args, PyObject* kwds) {
        int enable_ccache = 1;
        int enable_snapshot = 1;
 
-       if (!PyArg_ParseTupleAndKeywords(args, kwds, "|zzOppzppp", kwlist,
+       if (!PyArg_ParseTupleAndKeywords(args, kwds, "|zzOppzpppO", kwlist,
                        &path, &arch, &self->callbacks.log, &interactive, &offline, &conf, &build,
-                       &enable_ccache, &enable_snapshot))
+                       &enable_ccache, &enable_snapshot, &self->callbacks.confirm))
                return -1;
 
        // Check if log callback is callable
@@ -187,6 +214,12 @@ static int Pakfire_init(PakfireObject* self, PyObject* args, PyObject* kwds) {
                return -1;
        }
 
+       // Check if confirm callback is callable
+       if (self->callbacks.confirm && !PyCallable_Check(self->callbacks.confirm)) {
+               PyErr_SetString(PyExc_TypeError, "Confirm callback is not callable");
+               return -1;
+       }
+
        int flags = 0;
 
        // Enable interactive mode
@@ -230,19 +263,35 @@ static int Pakfire_init(PakfireObject* self, PyObject* args, PyObject* kwds) {
                return -1;
     }
 
+       // Configure confirm callback
+       if (self->callbacks.confirm) {
+               pakfire_set_confirm_callback(self->pakfire,
+                       Pakfire_confirm_callback, self->callbacks.confirm);
+
+               Py_INCREF(self->callbacks.confirm);
+       }
+
        return 0;
 }
 
 static void Pakfire_dealloc(PakfireObject* self) {
        if (self->pakfire) {
                // Reset log callback
-               pakfire_set_log_callback(self->pakfire, NULL, NULL);
+               if (self->callbacks.log) {
+                       pakfire_set_log_callback(self->pakfire, NULL, NULL);
+                       Py_DECREF(self->callbacks.log);
+               }
+
+               // Reset confirm callback
+               if (self->callbacks.confirm) {
+                       pakfire_set_confirm_callback(self->pakfire, NULL, NULL);
+                       Py_DECREF(self->callbacks.confirm);
+               }
 
                pakfire_unref(self->pakfire);
        }
 
        // Free callbacks
-       Py_XDECREF(self->callbacks.log);
        Py_XDECREF(self->callbacks.status);
        Py_XDECREF(self->callbacks.progress);
 
index f720f1402b84ad7f5427c01c7eb82241477f13b4..5a5c6b3f062f5504996dfe2de860a92ec2c2b35b 100644 (file)
@@ -32,6 +32,7 @@ typedef struct {
        // Callbacks
        struct callbacks {
                PyObject* log;
+               PyObject* confirm;
                PyObject* status;
                PyObject* progress;
        } callbacks;
index 9f50ec62f2a89c71c934f8b532e1c79f7a4b7d99..ba162bda6366aed166619baab76b438ef8836262 100644 (file)
@@ -56,6 +56,10 @@ typedef void (*pakfire_log_callback)(void* data, int priority, const char* file,
         int line, const char* fn, const char* format, va_list args);
 void pakfire_set_log_callback(struct pakfire* pakfire,
        pakfire_log_callback callback, void* data);
+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);
 
 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);
@@ -140,6 +144,7 @@ void pakfire_release_lock(struct pakfire* pakfire);
 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);
 
index c4ad3ff30611d4a0c326acdfd169c6439dfc0765..223c878c84c86da405547173659293689eb8e604 100644 (file)
@@ -26,7 +26,8 @@
 #include <pakfire/problem.h>
 #include <pakfire/request.h>
 
-int pakfire_ui_confirm(struct pakfire* pakfire, const char* message, const char* question);
+int pakfire_ui_confirm(struct pakfire* pakfire, void* data,
+       const char* message, const char* question);
 
 int pakfire_ui_pick_solution(struct pakfire* pakfire, struct pakfire_request* request,
        struct pakfire_problem** problems);
index 3feed459dc16042ae0660337d52e3b059b0092ca..884f0329e19b9e90a2784b29d601d1b496d5f5ee 100644 (file)
@@ -40,6 +40,7 @@ global:
        pakfire_ref;
        pakfire_refresh;
        pakfire_search;
+       pakfire_set_confirm_callback;
        pakfire_set_log_callback;
        pakfire_sync;
        pakfire_unref;
index 43054935a832f9169f126954f97ff97bec973618..970df779c10104b46d09f704f44b2185c2df8978 100644 (file)
@@ -94,6 +94,10 @@ struct pakfire {
                pakfire_log_callback log;
                void* log_data;
 
+               // Confirm
+               pakfire_confirm_callback confirm;
+               void* confirm_data;
+
                // Status
                void (*status)(void* data, const char* message);
                void* status_data;
@@ -908,6 +912,9 @@ PAKFIRE_EXPORT int pakfire_create(struct pakfire** pakfire, const char* path,
        if (env)
                pakfire_log_set_priority(p, log_priority(env));
 
+       // Setup confirm callback
+       pakfire_set_confirm_callback(p, pakfire_ui_confirm, NULL);
+
        // Initialise configuration
        r = pakfire_config_create(&p->config);
        if (r)
@@ -1709,6 +1716,28 @@ void pakfire_log(struct pakfire* pakfire, int priority, const char* file, int li
        errno = saved_errno;
 }
 
+// UI
+
+PAKFIRE_EXPORT void pakfire_set_confirm_callback(struct pakfire* pakfire,
+               pakfire_confirm_callback callback, void* data) {
+       pakfire->callbacks.confirm = callback;
+       pakfire->callbacks.confirm_data = data;
+}
+
+int pakfire_confirm(struct pakfire* pakfire, const char* message, const char* question) {
+       // No callback configured
+       if (!pakfire->callbacks.confirm)
+               return 0;
+
+       // Skip this, if running in non-interactive mode
+       if (!pakfire_has_flag(pakfire, PAKFIRE_FLAGS_INTERACTIVE))
+               return 0;
+
+       // Run callback
+       return pakfire->callbacks.confirm(
+               pakfire, pakfire->callbacks.confirm_data, message, question);
+}
+
 static const char* pakfire_user_lookup(void* data, la_int64_t uid) {
        struct pakfire* pakfire = (struct pakfire*)data;
 
index e2026381fc451a6837cbc6b353d262001b856574..0b8ba0f660e8cbd481ee45a6b65c0f23b182e014 100644 (file)
@@ -1224,7 +1224,7 @@ PAKFIRE_EXPORT int pakfire_transaction_run(struct pakfire_transaction* transacti
 
        // Check if we should continue
        if (pakfire_has_flag(transaction->pakfire, PAKFIRE_FLAGS_INTERACTIVE)) {
-               r = pakfire_ui_confirm(transaction->pakfire, dump, _("Is this okay? [y/N]"));
+               r = pakfire_confirm(transaction->pakfire, dump, _("Is this okay? [y/N]"));
                if (r) {
                        ERROR(transaction->pakfire, "Transaction aborted upon user request\n");
                        goto ERROR;
index e009e5493f88f56412f52584beeef65e8cb39146..f62f60371abc9aa4f93329f16ff8ea8ec3f64c81 100644 (file)
 #include <pakfire/request.h>
 #include <pakfire/ui.h>
 
-int pakfire_ui_confirm(struct pakfire* pakfire, const char* message, const char* question) {
+int pakfire_ui_confirm(struct pakfire* pakfire, void* data, const char* message,
+               const char* question) {
        // The message is only printed once
        printf("%s\n", message);
 
-       // Skip this, if running in non-interactive mode
-       if (!pakfire_has_flag(pakfire, PAKFIRE_FLAGS_INTERACTIVE))
-               return 0;
-
        char* line = NULL;
        size_t length = 0;
        int r = 1;