]> git.ipfire.org Git - pakfire.git/commitdiff
Implement install/erase/update with new convenience functions
authorMichael Tremer <michael.tremer@ipfire.org>
Mon, 21 Jun 2021 10:28:47 +0000 (10:28 +0000)
committerMichael Tremer <michael.tremer@ipfire.org>
Mon, 21 Jun 2021 10:28:47 +0000 (10:28 +0000)
Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
src/_pakfire/pakfire.c
src/pakfire/cli.py

index 39b3c1f5b07ec4fb45bbb235667c38d7e58336f4..6a32772c0d803c6e87eb58e115d9d62ec248e8af 100644 (file)
@@ -31,6 +31,7 @@
 #include <pakfire/key.h>
 #include <pakfire/repo.h>
 #include <pakfire/repolist.h>
+#include <pakfire/request.h>
 #include <pakfire/util.h>
 
 #include "errors.h"
@@ -204,6 +205,173 @@ static PyObject* Pakfire_get_repo(PakfireObject* self, PyObject* args) {
        return obj;
 }
 
+static int convert_packages(PyObject* object, void* address) {
+       char*** packages = (char***)address;
+
+       // Called for cleanup
+       if (!object)
+               goto ERROR;
+
+       if (!PySequence_Check(object)) {
+               PyErr_SetString(PyExc_ValueError, "Packages must be a sequence");
+               goto ERROR;
+       }
+
+       const unsigned int length = PySequence_Length(object);
+       if (!length) {
+               PyErr_SetString(PyExc_ValueError, "Packages list is empty");
+               goto ERROR;
+       }
+
+       // Allocate array
+       *packages = calloc(length + 1, sizeof(*packages));
+       if (!*packages) {
+               PyErr_SetFromErrno(PyExc_OSError);
+               goto ERROR;
+       }
+
+       for (unsigned int i = 0; i < length; i++) {
+               PyObject* item = PySequence_GetItem(object, i);
+
+               // Check if input is a string
+               if (!PyUnicode_Check(item)) {
+                       Py_DECREF(item);
+
+                       PyErr_SetString(PyExc_AttributeError, "Expected a string");
+                       goto ERROR;
+               }
+
+               // Fetch string
+               const char* package = PyUnicode_AsUTF8(item);
+               if (!package) {
+                       Py_DECREF(item);
+                       goto ERROR;
+               }
+
+               // Add package to array
+               *packages[i] = strdup(package);
+               if (!*packages[i]) {
+                       Py_DECREF(item);
+                       goto ERROR;
+               }
+
+               Py_DECREF(item);
+       }
+
+       // Success
+       return Py_CLEANUP_SUPPORTED;
+
+ERROR:
+       if (*packages) {
+               for (char** package = *packages; *package; package++)
+                       free(*package);
+               free(*packages);
+       }
+
+       return 0;
+}
+
+static PyObject* Pakfire_install(PakfireObject* self, PyObject* args, PyObject* kwargs) {
+       char* kwlist[] = {
+               "packages",
+               "include_recommended",
+               NULL
+       };
+       char** packages = NULL;
+       int include_recommended = 1;
+       int flags = 0;
+
+       if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&|$p", kwlist,
+                       convert_packages, &packages, &include_recommended))
+               return NULL;
+
+       // XXX include_recommended
+
+       // Run pakfire_install
+       int r = pakfire_install(self->pakfire, (const char**)packages, flags, NULL);
+       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",
+               NULL
+       };
+       char** packages = NULL;
+       int flags = 0;
+
+       if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&", kwlist,
+                       convert_packages, &packages))
+               return NULL;
+
+       // Run pakfire_erase
+       int r = pakfire_erase(self->pakfire, (const char**)packages, flags, NULL);
+       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",
+               "allow_archchange",
+               "allow_vendorchange",
+               NULL
+       };
+       char** packages = NULL;
+       int allow_archchange = 0;
+       int allow_vendorchange = 0;
+       int flags = 0;
+
+       if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&|$pp", kwlist,
+                       convert_packages, &packages, &allow_archchange, &allow_vendorchange))
+               return NULL;
+
+       if (allow_archchange)
+               flags |= PAKFIRE_SOLVER_ALLOW_ARCHCHANGE;
+
+       if (allow_vendorchange)
+               flags |= PAKFIRE_SOLVER_ALLOW_VENDORCHANGE;
+
+       // Run pakfire_update
+       int r = pakfire_update(self->pakfire, (const char**)packages, flags, NULL);
+       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* _import_keylist(PakfireObject* pakfire, PakfireKey* keys) {
        PyObject* list = PyList_New(0);
 
@@ -911,6 +1079,12 @@ static struct PyMethodDef Pakfire_methods[] = {
                METH_VARARGS,
                NULL
        },
+       {
+               "erase",
+               (PyCFunction)Pakfire_erase,
+               METH_VARARGS|METH_KEYWORDS,
+               NULL
+       },
        {
                "execute",
                (PyCFunction)Pakfire_execute,
@@ -947,6 +1121,12 @@ static struct PyMethodDef Pakfire_methods[] = {
                METH_VARARGS,
                NULL
        },
+       {
+               "install",
+               (PyCFunction)Pakfire_install,
+               METH_VARARGS|METH_KEYWORDS,
+               NULL,
+       },
        {
                "read_makefile",
                (PyCFunction)Pakfire_read_makefile,
@@ -971,6 +1151,12 @@ static struct PyMethodDef Pakfire_methods[] = {
                METH_NOARGS,
                NULL,
        },
+       {
+               "update",
+               (PyCFunction)Pakfire_update,
+               METH_VARARGS|METH_KEYWORDS,
+               NULL
+       },
        {
                "version_compare",
                (PyCFunction)Pakfire_version_compare,
index fe0307f6935c83b89c27e479ddf1fc6bfac3acd9..59e5cc0a76df6d9ec7ea00e5a07076e6c0de32ad 100644 (file)
@@ -163,12 +163,8 @@ class Cli(object):
                        help=_("Update the whole system or one specific package"))
                update.add_argument("package", nargs="*",
                        help=_("Give a name of a package to update or leave emtpy for all"))
-               update.add_argument("--exclude", "-x", nargs="+",
-                       help=_("Exclude package from update"))
                update.add_argument("--allow-archchange", action="store_true",
                        help=_("Allow changing the architecture of packages"))
-               update.add_argument("--allow-downgrade", action="store_true",
-                       help=_("Allow downgrading of packages"))
                update.add_argument("--allow-vendorchange", action="store_true",
                        help=_("Allow changing the vendor of packages"))
                update.set_defaults(func=self.handle_update)
@@ -268,9 +264,6 @@ class Cli(object):
 
                        return e.exit_code
 
-       def _execute_transaction(self, transaction):
-               transaction.run()
-
        def handle_info(self, ns):
                with self.pakfire(ns) as p:
                        for pkg in p.info(ns.package):
@@ -286,22 +279,13 @@ class Cli(object):
 
                                print("%-24s: %s" % (pkg.name, pkg.summary))
 
-       def handle_update(self, ns, check=False):
-               with self.pakfire(ns) as p:
-                       transaction = p.update(
-                               ns.package, excludes=ns.exclude,
-                               allow_archchange=ns.allow_archchange,
-                               allow_vendorchange=ns.allow_vendorchange,
-                       )
-
-                       # If we are only checking for updates,
-                       # we dump the transaction and exit here.
-                       if check:
-                               self._dump_transaction(transaction)
-                               return
-
-                       # Otherwise we execute the transaction
-                       self._execute_transaction(transaction)
+       def handle_update(self, ns):
+               p = self.pakfire(ns)
+               p.update(
+                       ns.package,
+                       allow_archchange=ns.allow_archchange,
+                       allow_vendorchange=ns.allow_vendorchange,
+               )
 
        def handle_sync(self, ns):
                with self.pakfire(ns) as p:
@@ -325,11 +309,8 @@ class Cli(object):
                        )
 
        def handle_install(self, ns):
-               with self.pakfire(ns) as p:
-                       transaction = p.install(ns.package, without_recommends=ns.without_recommends)
-
-                       # Execute the transaction
-                       self._execute_transaction(transaction)
+               p = self.pakfire(ns)
+               p.install(ns.package, include_recommended=not ns.without_recommends)
 
        def handle_reinstall(self, ns):
                with self.pakfire(ns) as p:
@@ -339,10 +320,8 @@ class Cli(object):
                        self._execute_transaction(transaction)
 
        def handle_remove(self, ns):
-               with self.pakfire(ns) as p:
-                       transaction = p.erase(ns.package)
-
-                       self._execute_transaction(transaction)
+               p = self.pakfire(ns)
+               p.erase(ns.package)
 
        def handle_provides(self, ns, long=False):
                with self.pakfire(ns) as p: