]> git.ipfire.org Git - people/ms/pakfire.git/blobdiff - src/_pakfire/pakfire.c
python: Pakfire.execute(): Fix parsing some arguments
[people/ms/pakfire.git] / src / _pakfire / pakfire.c
index 17cf72c0079a1fb45e53ad55a45cbe139a62a4ad..a5a45e54736c2b1fbe2091579f716879800a9555 100644 (file)
 #define PY_SSIZE_T_CLEAN
 #include <Python.h>
 #include <errno.h>
+#include <syslog.h>
 
 #include <pakfire/archive.h>
 #include <pakfire/build.h>
 #include <pakfire/constants.h>
+#include <pakfire/ctx.h>
 #include <pakfire/dist.h>
 #include <pakfire/jail.h>
 #include <pakfire/logging.h>
 #include <pakfire/key.h>
 #include <pakfire/repo.h>
 #include <pakfire/repolist.h>
-#include <pakfire/request.h>
 #include <pakfire/transaction.h>
 #include <pakfire/util.h>
 
 #include "archive.h"
+#include "ctx.h"
 #include "errors.h"
 #include "key.h"
 #include "pakfire.h"
 static PyObject* Pakfire_new(PyTypeObject* type, PyObject* args, PyObject* kwds) {
        PakfireObject* self = (PakfireObject *)type->tp_alloc(type, 0);
        if (self) {
+               self->ctx = NULL;
                self->pakfire = NULL;
-
-               // Callbacks
-               self->callbacks.log = NULL;
-               self->callbacks.confirm = NULL;
        }
 
        return (PyObject *)self;
 }
 
-static void Pakfire_log_callback(void* data, int priority, const char* file, int line,
-               const char* fn, const char* format, va_list args) {
-       PyObject* callback = (PyObject*)data;
-       PyObject* exception = NULL;
-
-       // Do nothing if callback isn't set
-       if (!callback)
-               return;
-
-       PyGILState_STATE state = PyGILState_Ensure();
-
-       // Translate priority to Python logging priorities
-       switch (priority) {
-               case LOG_DEBUG:
-                       priority = 10;
-                       break;
-
-               case LOG_INFO:
-                       priority = 20;
-                       break;
-
-               case LOG_ERR:
-                       priority = 40;
-                       break;
-
-               // Drop messages of an unknown priority
-               default:
-                       return;
-       }
-
-       PyObject* tuple = NULL;
-       PyObject* result = NULL;
-       char* buffer = NULL;
-
-       // Make line
-       int r = vasprintf(&buffer, format, args);
-       if (r < 0)
-               goto ERROR;
-
-       // Build a tuple with the priority and the log message
-       tuple = Py_BuildValue("(is)", priority, buffer);
-       if (!tuple)
-               goto ERROR;
-
-       // Call the callback
-       result = PyObject_CallObject(callback, tuple);
-
-ERROR:
-       /*
-               We cannot really catch any Python errors here, since we cannot send
-               any error codes up the chain.
-
-               So, in order to debug the problem, We will check if an exception has
-               occurred and if so, print it to the console.
-       */
-       exception = PyErr_Occurred();
-       if (exception)
-               PyErr_Print();
-
-       if (buffer)
-               free(buffer);
-       Py_XDECREF(tuple);
-       Py_XDECREF(result);
-
-       // Release the GIL
-       PyGILState_Release(state);
-}
-
-static int Pakfire_confirm_callback(struct pakfire* pakfire, void* data,
-               const char* message, const char* question) {
-       PyObject* callback = (PyObject*)data;
-       PyObject* result = NULL;
-       int r = 0;
-
-       // Do nothing if callback isn't set
-       if (!callback)
-               return 0;
-
-       // Acquire GIL
-       PyGILState_STATE state = PyGILState_Ensure();
-
-       PyObject* args = Py_BuildValue("(ss)", message, question);
-       if (!args) {
-               r = -1;
-               goto ERROR;
-       }
-
-       result = PyObject_CallObject(callback, args);
-
-       // If the callback raised an exception, we will ignore it and indicate
-       // that an error happened, but we cannot re-raise the exception
-       if (!result) {
-               r = -1;
-               goto ERROR;
-       }
-
-       // Set the return code
-       if (result == Py_True)
-               r = 0;
-       else
-               r = 1;
-
-ERROR:
-       Py_DECREF(args);
-       Py_DECREF(result);
-
-       // Release the GIL
-       PyGILState_Release(state);
-
-       return r;
-}
-
 static int Pakfire_init(PakfireObject* self, PyObject* args, PyObject* kwds) {
        char* kwlist[] = {
+               "ctx",
                "path",
                "arch",
-               "logger",
-               "offline",
                "conf",
-               "confirm_callback",
                NULL,
        };
+       CtxObject* ctx = NULL;
        const char* path = NULL;
        const char* arch = NULL;
-       const char* conf = NULL;
-       int offline = 0;
-       int r;
+       PyObject* conf = Py_None;
+       int r = 1;
 
-       if (!PyArg_ParseTupleAndKeywords(args, kwds, "|zzOpzO", kwlist,
-                       &path, &arch, &self->callbacks.log, &offline, &conf, &self->callbacks.confirm))
-               return -1;
+       FILE* fconf = NULL;
 
-       // Check if log callback is callable
-       if (self->callbacks.log && !PyCallable_Check(self->callbacks.log)) {
-               PyErr_SetString(PyExc_TypeError, "logger must be callable\n");
-               return -1;
-       }
+       if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!|zzO", kwlist,
+                       &CtxType, &ctx, &path, &arch, &conf))
+               goto ERROR;
 
-       // 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;
+       // Map the configuration
+       if (conf != Py_None) {
+               fconf = PyObject_AsFileHandle(conf, "r");
+               if (!fconf)
+                       goto ERROR;
        }
 
        int flags = 0;
 
-       // Enable offline mode
-       if (offline)
-               flags |= PAKFIRE_FLAGS_OFFLINE;
-
-       // Configure callbacks
-       if (self->callbacks.log)
-               Py_INCREF(self->callbacks.log);
-
        Py_BEGIN_ALLOW_THREADS
 
+       // Store a reference to the context
+       self->ctx = pakfire_ctx_ref(ctx->ctx);
+
        // Create a new Pakfire instance
-       r = pakfire_create(&self->pakfire, path, arch, conf, flags,
-               LOG_DEBUG, Pakfire_log_callback, self->callbacks.log);
+       r = pakfire_create(&self->pakfire, self->ctx, path, arch, fconf, flags);
 
        Py_END_ALLOW_THREADS
 
-       if (r) {
+       if (r < 0) {
+               errno = -r;
+
                switch (errno) {
                        // Invalid architecture or path
                        case EINVAL:
@@ -232,40 +110,27 @@ static int Pakfire_init(PakfireObject* self, PyObject* args, PyObject* kwds) {
                                PyErr_SetFromErrno(PyExc_OSError);
                }
 
-               return -1;
+               r = -1;
+               goto ERROR;
     }
 
-       // Configure confirm callback
-       if (self->callbacks.confirm) {
-               pakfire_set_confirm_callback(self->pakfire,
-                       Pakfire_confirm_callback, self->callbacks.confirm);
-
-               Py_INCREF(self->callbacks.confirm);
-       }
+ERROR:
+       if (fconf)
+               fclose(fconf);
 
-       return 0;
+       return -r;
 }
 
 static void Pakfire_dealloc(PakfireObject* self) {
        if (self->pakfire) {
-               // Reset log callback
-               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);
-               }
-
                Py_BEGIN_ALLOW_THREADS
 
                pakfire_unref(self->pakfire);
 
                Py_END_ALLOW_THREADS
        }
+       if (self->ctx)
+               pakfire_ctx_unref(self->ctx);
 
        Py_TYPE(self)->tp_free((PyObject *)self);
 }
@@ -305,31 +170,6 @@ 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;
-
-       // Acquire GIL
-       PyGILState_STATE state = PyGILState_Ensure();
-
-       // Compile arguments
-       PyObject* args = Py_BuildValue("(is)", progress, status);
-       if (args) {
-               // Call the callback
-               PyObject* result = PyObject_CallObject(callback, args);
-
-               Py_XDECREF(result);
-               Py_DECREF(args);
-       }
-
-       // Release the GIL
-       PyGILState_Release(state);
-}
-
 static int convert_packages(PyObject* object, void* address) {
        char*** packages = (char***)address;
 
@@ -398,213 +238,20 @@ ERROR:
        return 0;
 }
 
-static PyObject* Pakfire_install(PakfireObject* self, PyObject* args, PyObject* kwargs) {
-       char* kwlist[] = {
-               "packages",
-               "dryrun",
-               "without_recommended",
-               "allow_uninstall",
-               "allow_downgrade",
-               "status_callback",
-               NULL
-       };
-       char** packages = NULL;
-       int dryrun = 0;
-       int without_recommended = 0;
-       int allow_uninstall = 0;
-       int allow_downgrade = 0;
-       int solver_flags = 0;
-       int transaction_flags = 0;
-       PyObject* status_callback = NULL;
-       int r;
-
-       if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&|$ppppO", kwlist,
-                       convert_packages, &packages, &dryrun, &without_recommended, &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;
-       }
-
-       // Enable dry-run mode
-       if (dryrun)
-               transaction_flags |= PAKFIRE_TRANSACTION_DRY_RUN;
-
-       // Do not install recommended packages
-       if (without_recommended)
-               solver_flags |= PAKFIRE_REQUEST_WITHOUT_RECOMMENDED;
-
-       // Can the solver uninstall packages?
-       if (allow_uninstall)
-               solver_flags |= PAKFIRE_REQUEST_ALLOW_UNINSTALL;
-
-       // Can the solver downgrade packages?
-       if (allow_downgrade)
-               solver_flags |= PAKFIRE_REQUEST_ALLOW_DOWNGRADE;
-
-       Py_BEGIN_ALLOW_THREADS
-
-       // Run pakfire_install
-       r = pakfire_install(self->pakfire, transaction_flags, solver_flags,
-               (const char**)packages, NULL, 0, NULL, Pakfire_status_callback, status_callback);
-
-       Py_END_ALLOW_THREADS
-
-       if (r)
-               PyErr_SetFromErrno(PyExc_OSError);
-
-       if (packages) {
-               for (char** package = packages; *package; package++)
-                       free(*package);
-               free(packages);
-       }
-
-       if (r)
-               return NULL;
-
-       Py_RETURN_NONE;
-}
-
-static PyObject* Pakfire_erase(PakfireObject* self, PyObject* args, PyObject* kwargs) {
-       char* kwlist[] = {
-               "packages",
-               "dryrun",
-               "keep_dependencies",
-               "status_callback",
-               NULL
-       };
-       char** packages = NULL;
-       int dryrun = 0;
-       int keep_dependencies = 0;
-       int transaction_flags = 0;
-       int flags = 0;
-       PyObject* status_callback = NULL;
-       int r;
-
-       if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&|$ppO", kwlist,
-                       convert_packages, &packages, &dryrun, &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 (dryrun)
-               transaction_flags |= PAKFIRE_TRANSACTION_DRY_RUN;
-
-       if (keep_dependencies)
-               flags |= PAKFIRE_REQUEST_KEEP_DEPS;
-
-       Py_BEGIN_ALLOW_THREADS
-
-       // Run pakfire_erase
-       r = pakfire_erase(self->pakfire, transaction_flags, 0, (const char**)packages,
-               NULL, flags, NULL, Pakfire_status_callback, status_callback);
-
-       Py_END_ALLOW_THREADS
-
-       if (r)
-               PyErr_SetFromErrno(PyExc_OSError);
-
-       if (packages) {
-               for (char** package = packages; *package; package++)
-                       free(*package);
-               free(packages);
-       }
-
-       if (r)
-               return NULL;
-
-       Py_RETURN_NONE;
-}
-
-static PyObject* Pakfire_update(PakfireObject* self, PyObject* args, PyObject* kwargs) {
-       char* kwlist[] = {
-               "packages",
-               "dryrun",
-               "excludes",
-               "allow_uninstall",
-               "allow_downgrade",
-               "status_callback",
-               NULL
-       };
-       char** packages = NULL;
-       char** excludes = NULL;
-       int dryrun = 0;
-       int allow_uninstall = 0;
-       int allow_downgrade = 0;
-       int solver_flags = 0;
-       int transaction_flags = 0;
-       PyObject* status_callback = NULL;
-       int r;
-
-       if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&|$pO&ppO", kwlist,
-                       convert_packages, &packages, &dryrun, convert_packages, &excludes,
-                       &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;
-       }
-
-       if (dryrun)
-               transaction_flags = PAKFIRE_TRANSACTION_DRY_RUN;
-
-       // Can the solver uninstall packages?
-       if (allow_uninstall)
-               solver_flags |= PAKFIRE_REQUEST_ALLOW_UNINSTALL;
-
-       // Can the solver downgrade packages?
-       if (allow_downgrade)
-               solver_flags |= PAKFIRE_REQUEST_ALLOW_DOWNGRADE;
-
-       Py_BEGIN_ALLOW_THREADS
-
-       // Run pakfire_update
-       r = pakfire_update(self->pakfire, transaction_flags, solver_flags,
-               (const char**)packages, (const char**)excludes, 0, NULL,
-               Pakfire_status_callback, status_callback);
-
-       Py_END_ALLOW_THREADS
-
-       if (r)
-               PyErr_SetFromErrno(PyExc_OSError);
-
-       if (packages) {
-               for (char** package = packages; *package; package++)
-                       free(*package);
-               free(packages);
-       }
-
-       if (excludes) {
-               for (char** exclude = excludes; *exclude; exclude++)
-                       free(*exclude);
-               free(excludes);
-       }
-
-       if (r)
-               return NULL;
-
-       Py_RETURN_NONE;
-}
-
+/*
+       XXX This could be moved out of here as this no longer depends on Pakfire
+*/
 static PyObject* Pakfire_generate_key(PakfireObject* self, PyObject* args, PyObject* kwds) {
-       char* kwlist[] = { "algorithm", NULL };
+       char* kwlist[] = { "algorithm", "comment", NULL };
        struct pakfire_key* key = NULL;
        pakfire_key_algo_t algo = PAKFIRE_KEY_ALGO_NULL;
+       const char* comment = NULL;
 
-       if (!PyArg_ParseTupleAndKeywords(args, kwds, "i", kwlist, &algo))
+       if (!PyArg_ParseTupleAndKeywords(args, kwds, "is", kwlist, &algo, &comment))
                return NULL;
 
        // Generate a new key
-       int r = pakfire_key_generate(&key, self->pakfire, algo);
+       int r = pakfire_key_generate(&key, self->ctx, algo, comment);
        if (r) {
                PyErr_SetFromErrno(PyExc_OSError);
                return NULL;
@@ -615,24 +262,27 @@ static PyObject* Pakfire_generate_key(PakfireObject* self, PyObject* args, PyObj
 
        return object;
 }
-
+/*
+       XXX This could be moved out of here as this no longer depends on Pakfire
+*/
 static PyObject* Pakfire_import_key(PakfireObject* self, PyObject* args) {
        struct pakfire_key* key = NULL;
        PyObject* object = NULL;
-       PyObject* file = NULL;
+       char* data = NULL;
+       Py_ssize_t data_length = 0;
        int r;
 
        // Parse arguments
-       if (!PyArg_ParseTuple(args, "O", &file))
+       if (!PyArg_ParseTuple(args, "s#", &data, &data_length))
                return NULL;
 
-       // Treat the object as a file
-       FILE* f = PyObject_AsFileHandle(file, "r");
+       // Map the object
+       FILE* f = fmemopen(data, data_length, "r");
        if (!f)
                return NULL;
 
        // Import the key
-       r = pakfire_key_import(&key, self->pakfire, f);
+       r = pakfire_key_import(&key, self->ctx, f);
        if (r) {
                PyErr_SetFromErrno(PyExc_OSError);
                goto ERROR;
@@ -662,7 +312,7 @@ static PyObject* Pakfire_whatprovides(PakfireObject* self, PyObject* args) {
                return NULL;
 
        // Create a new list
-       r = pakfire_packagelist_create(&list, self->pakfire);
+       r = pakfire_packagelist_create(&list, self->ctx);
        if (r) {
                PyErr_SetFromErrno(PyExc_OSError);
                goto ERROR;
@@ -696,7 +346,7 @@ static PyObject* Pakfire_whatrequires(PakfireObject* self, PyObject* args) {
        Py_BEGIN_ALLOW_THREADS
 
        // Create a new list
-       r = pakfire_packagelist_create(&list, self->pakfire);
+       r = pakfire_packagelist_create(&list, self->ctx);
        if (r) {
                Py_BLOCK_THREADS
                PyErr_SetFromErrno(PyExc_OSError);
@@ -738,7 +388,7 @@ static PyObject* Pakfire_search(PakfireObject* self, PyObject* args, PyObject* k
        if (name_only)
                flags |= PAKFIRE_SEARCH_NAME_ONLY;
 
-       r = pakfire_packagelist_create(&list, self->pakfire);
+       r = pakfire_packagelist_create(&list, self->ctx);
        if (r) {
                PyErr_SetFromErrno(PyExc_OSError);
                goto ERROR;
@@ -771,8 +421,8 @@ static PyObject* Pakfire_version_compare(PakfireObject* self, PyObject* args) {
        return PyLong_FromLong(cmp);
 }
 
-static int Pakfire_execute_output_callback(struct pakfire* pakfire, void* data,
-               int priority, const char* line, size_t length) {
+static int Pakfire_execute_output_callback(struct pakfire_ctx* ctx, struct pakfire_jail* jail,
+               void* data, const char* line, size_t length) {
        PyObject* callback = (PyObject*)data;
        int r = 0;
 
@@ -780,23 +430,12 @@ static int Pakfire_execute_output_callback(struct pakfire* pakfire, void* data,
        if (!callback)
                return 0;
 
-       // Translate priority to Python logging priorities
-       switch (priority) {
-               case LOG_INFO:
-                       priority = 20;
-                       break;
-
-               case LOG_ERR:
-                       priority = 40;
-                       break;
-       }
-
        // Remove the trailing newline
        if (line && line[length - 1] == '\n')
                length--;
 
        // Create tuple with arguments for the callback function
-       PyObject* args = Py_BuildValue("(is#)", priority, line, (Py_ssize_t)length);
+       PyObject* args = Py_BuildValue("(is#)", LOG_INFO, line, (Py_ssize_t)length);
        if (!args)
                return 1;
 
@@ -861,7 +500,7 @@ static PyObject* Pakfire_execute(PakfireObject* self, PyObject* args, PyObject*
 
                if (!PyUnicode_Check(item)) {
                        PyErr_Format(PyExc_TypeError, "Item %u in command is not a string", i);
-                       return NULL;
+                       goto ERROR;
                }
 
                // Copy to argv
@@ -887,12 +526,6 @@ static PyObject* Pakfire_execute(PakfireObject* self, PyObject* args, PyObject*
                goto ERROR;
        }
 
-       // Check callback
-       if (callback && !PyCallable_Check(callback)) {
-               PyErr_SetString(PyExc_TypeError, "callback must be callable\n");
-               goto ERROR;
-       }
-
        // Set nice
        if (nice) {
                r = pakfire_jail_nice(jail, nice);
@@ -930,39 +563,43 @@ static PyObject* Pakfire_execute(PakfireObject* self, PyObject* args, PyObject*
                }
        }
 
-       const Py_ssize_t num_bind = PySequence_Length(bind);
-
        // Bind
-       for (unsigned int i = 0; i < num_bind; i++) {
-               PyObject* b = PySequence_ITEM(bind, i);
-               if (!b)
-                       goto ERROR;
+       if (bind && PySequence_Check(bind)) {
+               const Py_ssize_t num_bind = PySequence_Length(bind);
 
-               // Check if this is a Unicode object
-               if (!PyUnicode_Check(b)) {
-                       PyErr_SetString(PyExc_ValueError, "bind contains a non-Unicode object");
-                       Py_DECREF(b);
-                       goto ERROR;
-               }
+               for (unsigned int i = 0; i < num_bind; i++) {
+                       PyObject* b = PySequence_ITEM(bind, i);
+                       if (!b)
+                               goto ERROR;
 
-               const char* path = PyUnicode_AsUTF8(b);
+                       // Check if this is a Unicode object
+                       if (!PyUnicode_Check(b)) {
+                               PyErr_SetString(PyExc_ValueError, "bind contains a non-Unicode object");
+                               Py_DECREF(b);
+                               goto ERROR;
+                       }
+
+                       const char* path = PyUnicode_AsUTF8(b);
+
+                       // Perform bind
+                       r = pakfire_jail_bind(jail, path, path, 0);
+                       if (r) {
+                               PyErr_SetFromErrno(PyExc_OSError);
+                               Py_DECREF(b);
+                               goto ERROR;
+                       }
 
-               // Perform bind
-               r = pakfire_jail_bind(jail, path, path, 0);
-               if (r) {
-                       PyErr_SetFromErrno(PyExc_OSError);
                        Py_DECREF(b);
-                       goto ERROR;
                }
-
-               Py_DECREF(b);
        }
 
        Py_BEGIN_ALLOW_THREADS
 
+       // Set callback
+       pakfire_jail_set_stdout_callback(jail, Pakfire_execute_output_callback, callback);
+
        // Execute command
-       r = pakfire_jail_exec(jail, argv,
-               NULL, Pakfire_execute_output_callback, callback, 0);
+       r = pakfire_jail_exec(jail, argv, 0);
 
        Py_END_ALLOW_THREADS
 
@@ -1023,48 +660,6 @@ static PyObject* Pakfire_dist(PakfireObject* self, PyObject* args) {
        return ret;
 }
 
-static PyObject* Pakfire_copy_in(PakfireObject* self, PyObject* args) {
-       const char* src = NULL;
-       const char* dst = NULL;
-
-       if (!PyArg_ParseTuple(args, "ss", &src, &dst))
-               return NULL;
-
-       Py_BEGIN_ALLOW_THREADS
-
-       int r = pakfire_copy_in(self->pakfire, src, dst);
-       if (r) {
-               Py_BLOCK_THREADS
-               PyErr_SetFromErrno(PyExc_OSError);
-               return NULL;
-       }
-
-       Py_END_ALLOW_THREADS
-
-       Py_RETURN_NONE;
-}
-
-static PyObject* Pakfire_copy_out(PakfireObject* self, PyObject* args) {
-       const char* src = NULL;
-       const char* dst = NULL;
-
-       if (!PyArg_ParseTuple(args, "ss", &src, &dst))
-               return NULL;
-
-       Py_BEGIN_ALLOW_THREADS
-
-       int r = pakfire_copy_out(self->pakfire, src, dst);
-       if (r) {
-               Py_BLOCK_THREADS
-               PyErr_SetFromErrno(PyExc_OSError);
-               return NULL;
-       }
-
-       Py_END_ALLOW_THREADS
-
-       Py_RETURN_NONE;
-}
-
 static PyObject* Pakfire_get_repos(PakfireObject* self) {
        struct pakfire_repolist* repos = pakfire_get_repos(self->pakfire);
        if (!repos) {
@@ -1286,87 +881,6 @@ static PyObject* Pakfire_refresh(PakfireObject* self, PyObject* args) {
        Py_RETURN_NONE;
 }
 
-static PyObject* Pakfire_check(PakfireObject* self) {
-       struct pakfire_filelist* errors = NULL;
-       int r;
-
-       // Allocate a filelist for errors
-       r = pakfire_filelist_create(&errors, self->pakfire);
-       if (r)
-               goto ERROR;
-
-       Py_BEGIN_ALLOW_THREADS
-
-       // Perform check
-       r = pakfire_check(self->pakfire, errors);
-
-       Py_END_ALLOW_THREADS
-
-       if (r)
-               goto ERROR;
-
-       const size_t num_errors = pakfire_filelist_length(errors);
-
-       // Did we find any errors?
-       if (num_errors) {
-               PyObject* _errors = PyList_FromFileList(errors);
-               if (!_errors)
-                       goto ERROR;
-
-               pakfire_filelist_unref(errors);
-
-               // Raise CheckFileVerificationError
-               PyErr_SetObject(PyExc_CheckFileVerificationError, _errors);
-               Py_DECREF(_errors);
-               return NULL;
-       }
-
-       pakfire_filelist_unref(errors);
-       Py_RETURN_NONE;
-
-ERROR:
-       // Cleanup
-       if (errors)
-               pakfire_filelist_unref(errors);
-
-       // Raise exception from errno
-       PyErr_SetFromErrno(PyExc_OSError);
-       return NULL;
-}
-
-static PyObject* Pakfire_sync(PakfireObject* self, PyObject* args, PyObject* kwargs) {
-       char* kwlist[] = {
-               "keep_orphaned",
-               "status_callback",
-               NULL,
-       };
-       int keep_orphaned = 0;
-       int flags = 0;
-       PyObject* status_callback = NULL;
-       int r;
-
-       if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|$pO", kwlist,
-                       &keep_orphaned, &status_callback))
-               return NULL;
-
-       if (keep_orphaned)
-               flags |= PAKFIRE_REQUEST_KEEP_ORPHANED;
-
-       Py_BEGIN_ALLOW_THREADS
-
-       r = pakfire_sync(self->pakfire, 0, flags, NULL,
-                       Pakfire_status_callback, status_callback);
-       if (r) {
-               Py_BLOCK_THREADS
-               PyErr_SetFromErrno(PyExc_OSError);
-               return NULL;
-       }
-
-       Py_END_ALLOW_THREADS
-
-       Py_RETURN_NONE;
-}
-
 static PyObject* Pakfire_open(PakfireObject* self, PyObject* args) {
        struct pakfire_archive* archive = NULL;
        const char* path = NULL;
@@ -1462,6 +976,59 @@ ERROR:
        return ret;
 }
 
+static PyObject* Pakfire_mkimage(PakfireObject* self, PyObject* args, PyObject* kwargs) {
+       char* kwlist[] = {
+               "type",
+               "path",
+               NULL,
+       };
+       struct pakfire_build* build = NULL;
+       const char* type = NULL;
+       PyObject* file = NULL;
+       FILE* f = NULL;
+       int r;
+
+       if (!PyArg_ParseTupleAndKeywords(args, kwargs, "sO", kwlist, &type, &file))
+               return NULL;
+
+       // Make a file handle out of file
+       f = PyObject_AsFileHandle(file, "w");
+       if (!f)
+               return NULL;
+
+       // Create a new build environment
+       r = pakfire_build_create(&build, self->pakfire, NULL, 0);
+       if (r) {
+               PyErr_SetFromErrno(PyExc_OSError);
+               goto ERROR;
+       }
+
+       Py_BEGIN_ALLOW_THREADS
+
+       // Run mkimage
+       r = pakfire_build_mkimage(build, type, f);
+       if (r) {
+               Py_BLOCK_THREADS;
+
+               if (r < 0)
+                       PyErr_SetFromErrno(PyExc_OSError);
+
+               goto ERROR;
+       }
+
+       Py_END_ALLOW_THREADS
+
+ERROR:
+       if (build)
+               pakfire_build_unref(build);
+       if (f)
+               fclose(f);
+       if (r)
+               return NULL;
+
+       Py_RETURN_NONE;
+}
+
 static struct PyMethodDef Pakfire_methods[] = {
        {
                "build",
@@ -1469,42 +1036,18 @@ static struct PyMethodDef Pakfire_methods[] = {
                METH_VARARGS|METH_KEYWORDS,
                NULL
        },
-       {
-               "check",
-               (PyCFunction)Pakfire_check,
-               METH_NOARGS,
-               NULL,
-       },
        {
                "clean",
                (PyCFunction)Pakfire_clean,
                METH_NOARGS,
                NULL,
        },
-       {
-               "copy_in",
-               (PyCFunction)Pakfire_copy_in,
-               METH_VARARGS,
-               NULL,
-       },
-       {
-               "copy_out",
-               (PyCFunction)Pakfire_copy_out,
-               METH_VARARGS,
-               NULL,
-       },
        {
                "dist",
                (PyCFunction)Pakfire_dist,
                METH_VARARGS,
                NULL
        },
-       {
-               "erase",
-               (PyCFunction)Pakfire_erase,
-               METH_VARARGS|METH_KEYWORDS,
-               NULL
-       },
        {
                "execute",
                (PyCFunction)Pakfire_execute,
@@ -1530,10 +1073,10 @@ static struct PyMethodDef Pakfire_methods[] = {
                NULL,
        },
        {
-               "install",
-               (PyCFunction)Pakfire_install,
+               "mkimage",
+               (PyCFunction)Pakfire_mkimage,
                METH_VARARGS|METH_KEYWORDS,
-               NULL,
+               NULL
        },
        {
                "open",
@@ -1565,18 +1108,6 @@ static struct PyMethodDef Pakfire_methods[] = {
                METH_VARARGS|METH_KEYWORDS,
                NULL,
        },
-       {
-               "sync",
-               (PyCFunction)Pakfire_sync,
-               METH_VARARGS|METH_KEYWORDS,
-               NULL,
-       },
-       {
-               "update",
-               (PyCFunction)Pakfire_update,
-               METH_VARARGS|METH_KEYWORDS,
-               NULL
-       },
        {
                "version_compare",
                (PyCFunction)Pakfire_version_compare,