]> git.ipfire.org Git - pakfire.git/commitdiff
libpakfire: Allow extracting problems from solver
authorMichael Tremer <michael.tremer@ipfire.org>
Sat, 20 May 2017 13:13:36 +0000 (15:13 +0200)
committerMichael Tremer <michael.tremer@ipfire.org>
Sat, 20 May 2017 13:13:36 +0000 (15:13 +0200)
When a request could not be solved, the solver will return
a list of problems of what went wrong.

Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
12 files changed:
Makefile.am
src/_pakfire/_pakfiremodule.c
src/_pakfire/problem.c
src/_pakfire/problem.h
src/_pakfire/request.c
src/_pakfire/solution.c
src/libpakfire/include/pakfire/problem.h [new file with mode: 0644]
src/libpakfire/include/pakfire/request.h
src/libpakfire/include/pakfire/types.h
src/libpakfire/libpakfire.sym
src/libpakfire/problem.c [new file with mode: 0644]
src/libpakfire/request.c

index 8b615339e1fd9ccccd2da6426606e18a5a83da83..4e48a6b1a44ec7289dc6d0a34209f41995f32bb4 100644 (file)
@@ -241,6 +241,7 @@ libpakfire_la_SOURCES = \
        src/libpakfire/package.c \
        src/libpakfire/packagelist.c \
        src/libpakfire/pool.c \
+       src/libpakfire/problem.c \
        src/libpakfire/relation.c \
        src/libpakfire/relationlist.c \
        src/libpakfire/repo.c \
@@ -264,6 +265,7 @@ pkginclude_HEADERS += \
        src/libpakfire/include/pakfire/packagecache.h \
        src/libpakfire/include/pakfire/packagelist.h \
        src/libpakfire/include/pakfire/pool.h \
+       src/libpakfire/include/pakfire/problem.h \
        src/libpakfire/include/pakfire/relation.h \
        src/libpakfire/include/pakfire/relationlist.h \
        src/libpakfire/include/pakfire/repo.h \
index 773e090fac45b048179289a2f77e7d21c30e0c89..8de3f47c7b316158c8f8ec861d778c5377b02419 100644 (file)
@@ -51,15 +51,6 @@ static PyMethodDef pakfireModuleMethods[] = {
        { NULL, NULL, 0, NULL }
 };
 
-static PyMethodDef Problem_methods[] = {
-       {"get_rule", (PyCFunction)Problem_get_rule, METH_NOARGS, NULL},
-       {"get_source", (PyCFunction)Problem_get_source, METH_NOARGS, NULL},
-       {"get_target", (PyCFunction)Problem_get_target, METH_NOARGS, NULL},
-       {"get_dep", (PyCFunction)Problem_get_dep, METH_NOARGS, NULL},
-       {"get_solutions", (PyCFunction)Problem_get_solutions, METH_NOARGS, NULL},
-       { NULL, NULL, 0, NULL }
-};
-
 static PyMethodDef Solvable_methods[] = {
        {"get_name", (PyCFunction)Solvable_get_name, METH_NOARGS, NULL},
        {"get_evr", (PyCFunction)Solvable_get_evr, METH_NOARGS, NULL},
@@ -151,7 +142,6 @@ PyMODINIT_FUNC PyInit__pakfire(void) {
        PyModule_AddObject(module, "Pool", (PyObject *)&PoolType);
 
        // Problem
-       ProblemType.tp_methods = Problem_methods;
        if (PyType_Ready(&ProblemType) < 0)
                return NULL;
        Py_INCREF(&ProblemType);
index 3a15cee17cfcada2ef573ec66d8a00056a793184..0f00f1020c33ec2382c0881140d90e45a353691f 100644 (file)
@@ -1,7 +1,7 @@
 /*#############################################################################
 #                                                                             #
 # Pakfire - The IPFire package management system                              #
-# Copyright (C) 2011 Pakfire development team                                 #
+# Copyright (C) 2017 Pakfire development team                                 #
 #                                                                             #
 # This program is free software: you can redistribute it and/or modify        #
 # it under the terms of the GNU General Public License as published by        #
 #############################################################################*/
 
 #include <Python.h>
+#include <assert.h>
 
-#include "constants.h"
-#include "problem.h"
-#include "relation.h"
-#include "request.h"
-#include "solution.h"
-#include "solvable.h"
-#include "solver.h"
-
-PyTypeObject ProblemType = {
-       PyVarObject_HEAD_INIT(NULL, 0)
-       tp_name: "_pakfire.Problem",
-       tp_basicsize: sizeof(ProblemObject),
-       tp_flags: Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
-       tp_new : Problem_new,
-       tp_dealloc: (destructor) Problem_dealloc,
-       tp_doc: "Sat Problem objects",
-       tp_str: (reprfunc)Problem_string,
-};
-
-PyObject* Problem_new(PyTypeObject *type, PyObject *args, PyObject *kwds) {
-       ProblemObject *self;
-       SolverObject *solver;
-       RequestObject *request;
-       Id problem_id;
-
-       if (!PyArg_ParseTuple(args, "OOi", &solver, &request, &problem_id)) {
-               /* XXX raise exception */
-               return NULL;
-       }
+#include <pakfire/errno.h>
+#include <pakfire/problem.h>
 
-       self = (ProblemObject *)type->tp_alloc(type, 0);
-       if (self != NULL) {
-               self->_pool = request->_pool;
-               self->_solver = solver->_solver;
-               self->_id = problem_id;
+#include "pool.h"
+#include "problem.h"
 
-               // Initialize problem information.
-               Problem_init(self);
+static ProblemObject* Problem_new_core(PyTypeObject* type, PakfireProblem problem) {
+       ProblemObject* self = (ProblemObject *)type->tp_alloc(type, 0);
+       if (self) {
+               self->problem = problem;
        }
 
-       return (PyObject *)self;
+       return self;
 }
 
-PyObject *Problem_dealloc(ProblemObject *self) {
-       Py_TYPE(self)->tp_free((PyObject *)self);
+PyObject* new_problem(PakfireProblem problem) {
+       ProblemObject* p = Problem_new_core(&ProblemType, problem);
 
-       Py_RETURN_NONE;
+       return (PyObject*)p;
 }
 
-PyObject *Problem_init(ProblemObject *self) {
-       Id id = solver_findproblemrule(self->_solver, self->_id);
-
-       self->rule = solver_ruleinfo(self->_solver, id, &self->source,
-               &self->target, &self->dep);
-
-       Py_RETURN_NONE;
-}
+static PyObject* Problem_new(PyTypeObject* type, PyObject* args, PyObject* kwds) {
+       ProblemObject* self = Problem_new_core(type, NULL);
 
-PyObject *Problem_get_rule(ProblemObject *self) {
-       return Py_BuildValue("i", self->rule);
+       return (PyObject *)self;
 }
 
-PyObject *Problem_get_source(ProblemObject *self) {
-       SolvableObject *solvable;
-
-       if (self->source == ID_NULL)
-               Py_RETURN_NONE;
-
-       solvable = PyObject_New(SolvableObject, &SolvableType);
-       if (solvable == NULL)
-               return NULL;
-
-       solvable->_pool = self->_pool;
-       solvable->_id = self->source;
+static void Problem_dealloc(ProblemObject* self) {
+       if (self->problem)
+               pakfire_problem_free(self->problem);
 
-       return (PyObject *)solvable;
+       Py_TYPE(self)->tp_free((PyObject *)self);
 }
 
-PyObject *Problem_get_target(ProblemObject *self) {
-       SolvableObject *solvable;
+static int Problem_init(ProblemObject* self, PyObject* args, PyObject* kwds) {
+#if 0
+       PyObject* pool;
 
-       if (self->target == ID_NULL)
-               Py_RETURN_NONE;
+       if (!PyArg_ParseTuple(args, "O!", &PoolType, &pool))
+               return -1;
 
-       solvable = PyObject_New(SolvableObject, &SolvableType);
-       if (solvable == NULL)
-               return NULL;
+       self->pool = (PoolObject *)pool;
+       Py_INCREF(self->pool);
 
-       solvable->_pool = self->_pool;
-       solvable->_id = self->target;
+       self->request = pakfire_request_create(self->pool->pool);
+#endif
 
-       return (PyObject *)solvable;
+       return 0;
 }
 
-PyObject *Problem_get_dep(ProblemObject *self) {
-       RelationObject *relation;
-
-       if (self->dep == ID_NULL)
-               Py_RETURN_NONE;
-
-       relation = PyObject_New(RelationObject, &RelationType);
-       if (relation == NULL)
-               return NULL;
+static PyObject* Problem_string(ProblemObject* self) {
+       const char* string = pakfire_problem_to_string(self->problem);
 
-       relation->_pool = self->_pool;
-       relation->_id = self->dep;
-
-       return (PyObject *)relation;
+       return PyUnicode_FromString(string);
 }
 
-PyObject *Problem_get_solutions(ProblemObject *self) {
-       SolutionObject *solution;
-       Id s = 0;
-
-       PyObject *list = PyList_New(0);
-
-       while ((s = solver_next_solution(self->_solver, self->_id, s)) != 0) {
-               solution = PyObject_New(SolutionObject, &SolutionType);
-
-               solution->_solver = self->_solver;
-               solution->problem_id = self->_id;
-               solution->id = s;
-
-               PyList_Append(list, (PyObject *)solution);
-       }
-
-       return list;
-}
-
-PyObject *Problem_string(ProblemObject *self) {
-       Pool *pool = self->_pool;
-       char s[STRING_SIZE];
-
-       switch (self->rule) {
-               case SOLVER_RULE_DISTUPGRADE:
-                       snprintf(s, STRING_SIZE - 1,
-                               _("%s does not belong to a distupgrade repository"),
-                               pool_solvid2str(pool, self->source)
-                       );
-                       break;
-
-               case SOLVER_RULE_INFARCH:
-                       snprintf(s, STRING_SIZE - 1,
-                               _("%s has inferior architecture"),
-                               pool_solvid2str(pool, self->source)
-                       );
-                       break;
-
-               case SOLVER_RULE_UPDATE:
-                       snprintf(s, STRING_SIZE - 1,
-                               _("problem with installed package %s"),
-                               pool_solvid2str(pool, self->source)
-                       );
-                       break;
-
-               case SOLVER_RULE_JOB:
-                       snprintf(s, STRING_SIZE - 1, _("conflicting requests"));
-                       break;
-
-               case SOLVER_RULE_JOB_NOTHING_PROVIDES_DEP:
-                       snprintf(s, STRING_SIZE - 1,
-                               _("nothing provides requested %s"),
-                               pool_dep2str(pool, self->dep)
-                       );
-                       break;
-
-               case SOLVER_RULE_RPM:
-                       snprintf(s, STRING_SIZE - 1, _("some dependency problem"));
-                       break;
-
-               case SOLVER_RULE_RPM_NOT_INSTALLABLE:
-                       snprintf(s, STRING_SIZE - 1,
-                               _("package %s is not installable"),
-                               pool_solvid2str(pool, self->source)
-                       );
-                       break;
-
-               case SOLVER_RULE_RPM_NOTHING_PROVIDES_DEP:
-                       snprintf(s, STRING_SIZE - 1,
-                               _("nothing provides %s needed by %s"),
-                               pool_dep2str(pool, self->dep),  pool_solvid2str(pool, self->source)
-                       );
-                       break;
-
-               case SOLVER_RULE_RPM_SAME_NAME:
-                       snprintf(s, STRING_SIZE - 1,
-                               _("cannot install both %s and %s"),
-                               pool_solvid2str(pool, self->source),  pool_solvid2str(pool, self->target)
-                       );
-                       break;
-
-               case SOLVER_RULE_RPM_PACKAGE_CONFLICT:
-                       snprintf(s, STRING_SIZE - 1,
-                               _("package %s conflicts with %s provided by %s"),
-                               pool_solvid2str(pool, self->source), pool_dep2str(pool, self->dep),
-                               pool_solvid2str(pool, self->target)
-                       );
-                       break;
-
-               case SOLVER_RULE_RPM_PACKAGE_OBSOLETES:
-                       snprintf(s, STRING_SIZE - 1,
-                               _("package %s obsoletes %s provided by %s"),
-                               pool_solvid2str(pool, self->source), pool_dep2str(pool, self->dep),
-                               pool_solvid2str(pool, self->target)
-                       );
-                       break;
-
-               case SOLVER_RULE_RPM_INSTALLEDPKG_OBSOLETES:
-                       snprintf(s, STRING_SIZE - 1,
-                               _("installed package %s obsoletes %s provided by %s"),
-                               pool_solvid2str(pool, self->source), pool_dep2str(pool, self->dep),
-                               pool_solvid2str(pool, self->target)
-                       );
-                       break;
-
-               case SOLVER_RULE_RPM_IMPLICIT_OBSOLETES:
-                       snprintf(s, STRING_SIZE - 1,
-                               _("package %s implicitely obsoletes %s provided by %s"),
-                               pool_solvid2str(pool, self->source), pool_dep2str(pool, self->dep),
-                               pool_solvid2str(pool, self->target)
-                       );
-                       break;
-
-               case SOLVER_RULE_RPM_PACKAGE_REQUIRES:
-                       snprintf(s, STRING_SIZE - 1,
-                               _("package %s requires %s, but none of the providers can be installed"),
-                               pool_solvid2str(pool, self->source), pool_dep2str(pool, self->dep)
-                       );
-                       break;
-
-               case SOLVER_RULE_RPM_SELF_CONFLICT:
-                       snprintf(s, STRING_SIZE - 1,
-                               _("package %s conflicts with %s provided by itself"),
-                               pool_solvid2str(pool, self->source), pool_dep2str(pool, self->dep)
-                       );
-                       break;
-
-               case SOLVER_RULE_UNKNOWN:
-               case SOLVER_RULE_FEATURE:
-               case SOLVER_RULE_LEARNT:
-               case SOLVER_RULE_CHOICE:
-                       snprintf(s, STRING_SIZE - 1, _("bad rule type"));
-                       break;
+static struct PyMethodDef Problem_methods[] = {
+       { NULL }
+};
 
-       }
+static struct PyGetSetDef Problem_getsetters[] = {
+       { NULL },
+};
 
-       return Py_BuildValue("s", &s);
-}
+PyTypeObject ProblemType = {
+       PyVarObject_HEAD_INIT(NULL, 0)
+       tp_name:            "_pakfire.Problem",
+       tp_basicsize:       sizeof(ProblemObject),
+       tp_flags:           Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
+       tp_new:             Problem_new,
+       tp_dealloc:         (destructor)Problem_dealloc,
+       tp_init:            (initproc)Problem_init,
+       tp_doc:             "Problem object",
+       tp_methods:         Problem_methods,
+       tp_getset:          Problem_getsetters,
+       tp_str:             (reprfunc)Problem_string,
+};
index 22b3b7478332ac3171d91522b07e73ebbeb22274..7146b5c5da1c4773901ae45f13af51c1a9f6d166 100644 (file)
@@ -1,7 +1,7 @@
 /*#############################################################################
 #                                                                             #
 # Pakfire - The IPFire package management system                              #
-# Copyright (C) 2011 Pakfire development team                                 #
+# Copyright (C) 2017 Pakfire development team                                 #
 #                                                                             #
 # This program is free software: you can redistribute it and/or modify        #
 # it under the terms of the GNU General Public License as published by        #
 
 #include <Python.h>
 
-#include <solv/pool.h>
-#include <solv/solver.h>
+#include <pakfire/problem.h>
 
-// Sat Problem object
 typedef struct {
-    PyObject_HEAD
-    Pool *_pool;
-    Solver *_solver;
-    Id _id;
-
-    // problem information
-    Id rule;
-    Id source;
-    Id target;
-    Id dep;
+       PyObject_HEAD
+       PakfireProblem problem;
 } ProblemObject;
 
-extern PyObject *Problem_new(PyTypeObject *type, PyObject *args, PyObject *kwds);
-extern PyObject *Problem_dealloc(ProblemObject *self);
-
-extern PyObject *Problem_init(ProblemObject *self);
-extern PyObject *Problem_string(ProblemObject *self);
-
-extern PyObject *Problem_get_rule(ProblemObject *self);
-extern PyObject *Problem_get_source(ProblemObject *self);
-extern PyObject *Problem_get_target(ProblemObject *self);
-extern PyObject *Problem_get_dep(ProblemObject *self);
-
-extern PyObject *Problem_get_solutions(ProblemObject *self);
-
 extern PyTypeObject ProblemType;
 
+PyObject* new_problem(PakfireProblem problem);
+
 #endif /* PYTHON_PAKFIRE_PROBLEM_H */
index 0ac6db6270c69b3eec19bef26bfb4d1f778acea8..dc786baac002043fff8023b23df6d242fc659851 100644 (file)
@@ -25,6 +25,7 @@
 #include <pakfire/request.h>
 
 #include "package.h"
+#include "problem.h"
 #include "relation.h"
 #include "request.h"
 #include "selector.h"
@@ -214,6 +215,23 @@ static PyObject* Request_get_pool(RequestObject* self) {
        return (PyObject *)pool;
 }
 
+static PyObject* Request_get_problems(RequestObject* self) {
+       PyObject* list = PyList_New(0);
+
+       PakfireProblem problem = pakfire_request_get_problems(self->request);
+       while (problem) {
+               PyObject* p = new_problem(problem);
+               PyList_Append(list, p);
+
+               Py_DECREF(p);
+
+               // Move on to next problem
+               problem = pakfire_problem_next(problem);
+       }
+
+       return list;
+}
+
 static struct PyMethodDef Request_methods[] = {
        {
                "install",
@@ -261,6 +279,13 @@ static struct PyMethodDef Request_methods[] = {
 };
 
 static struct PyGetSetDef Request_getsetters[] = {
+       {
+               "problems",
+               (getter)Request_get_problems,
+               NULL,
+               NULL,
+               NULL
+       },
        {
                "pool",
                (getter)Request_get_pool,
index 22651e61002e44fd4982c0f7e3e2abd5d76c6c62..c1eac65ae02f4d8b9304b2ee66b5fae0368d2e6a 100644 (file)
@@ -50,8 +50,10 @@ PyObject *Solution_new(PyTypeObject *type, PyObject *args, PyObject *kwds) {
 
        self = (SolutionObject *)type->tp_alloc(type, 0);
        if (self != NULL) {
+#if 0
                self->_solver = problem->_solver;
                self->problem_id = problem->_id;
+#endif
                self->id = id;
        }
 
diff --git a/src/libpakfire/include/pakfire/problem.h b/src/libpakfire/include/pakfire/problem.h
new file mode 100644 (file)
index 0000000..07fb678
--- /dev/null
@@ -0,0 +1,51 @@
+/*#############################################################################
+#                                                                             #
+# Pakfire - The IPFire package management system                              #
+# Copyright (C) 2017 Pakfire development team                                 #
+#                                                                             #
+# This program is free software: you can redistribute it and/or modify        #
+# it under the terms of the GNU General Public License as published by        #
+# the Free Software Foundation, either version 3 of the License, or           #
+# (at your option) any later version.                                         #
+#                                                                             #
+# This program is distributed in the hope that it will be useful,             #
+# but WITHOUT ANY WARRANTY; without even the implied warranty of              #
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the               #
+# GNU General Public License for more details.                                #
+#                                                                             #
+# You should have received a copy of the GNU General Public License           #
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.       #
+#                                                                             #
+#############################################################################*/
+
+#ifndef PAKFIRE_PROBLEM_H
+#define PAKFIRE_PROBLEM_H
+
+#include <solv/pool.h>
+#include <solv/queue.h>
+
+#include <pakfire/request.h>
+
+PakfireProblem pakfire_problem_create(PakfireRequest request, Id id);
+PakfireProblem pakfire_problem_ref(PakfireProblem problem);
+void pakfire_problem_free(PakfireProblem problem);
+
+PakfireProblem pakfire_problem_next(PakfireProblem problem);
+void pakfire_problem_append(PakfireProblem problem, PakfireProblem new_problem);
+
+const char* pakfire_problem_to_string(PakfireProblem problem);
+
+#ifdef PAKFIRE_PRIVATE
+
+struct _PakfireProblem {
+       PakfireRequest request;
+       Id id;
+       char* string;
+
+       PakfireProblem next;
+       int nrefs;
+};
+
+#endif
+
+#endif /* PAKFIRE_PROBLEM_H */
index 01f70a599c67d18d1dc8a7f8a29173b1d69276f5..f29b0a975e2e44328ec07a00e713637778391a69 100644 (file)
@@ -38,11 +38,13 @@ enum _pakfire_solver_flags {
 };
 
 PakfireRequest pakfire_request_create(PakfirePool pool);
+PakfireRequest pakfire_request_ref(PakfireRequest request);
 void pakfire_request_free(PakfireRequest request);
 
 PakfirePool pakfire_request_pool(PakfireRequest request);
 
 int pakfire_request_solve(PakfireRequest request, int flags);
+PakfireProblem pakfire_request_get_problems(PakfireRequest request);
 PakfireTransaction pakfire_request_get_transaction(PakfireRequest request);
 
 int pakfire_request_install(PakfireRequest request, PakfirePackage package);
@@ -73,6 +75,7 @@ struct _PakfireRequest {
        Queue queue;
        Solver* solver;
        Transaction* transaction;
+       int nrefs;
 };
 
 #endif
index 4ea175b5f04a12b6b1ba9395b41182e6d31abf5a..51d764212b32efef32573f881d137883994804d3 100644 (file)
@@ -29,6 +29,7 @@ typedef struct _PakfirePackage* PakfirePackage;
 typedef struct _PakfirePackageCache* PakfirePackageCache;
 typedef struct _PakfirePackageList* PakfirePackageList;
 typedef struct _PakfirePool* PakfirePool;
+typedef struct _PakfireProblem* PakfireProblem;
 typedef struct _PakfireRelation* PakfireRelation;
 typedef struct _PakfireRelationList* PakfireRelationList;
 typedef struct _PakfireRepo* PakfireRepo;
index 047a7a0bb31034b46c5da844a02904bcce34c7c4..7e6e776c6934dc20135260e4577bc0a56053f74c 100644 (file)
@@ -159,6 +159,14 @@ global:
        pakfire_pool_version_compare;
        pakfire_pool_whatprovides;
 
+       # problem
+       pakfire_problem_append;
+       pakfire_problem_create;
+       pakfire_problem_free;
+       pakfire_problem_next;
+       pakfire_problem_ref;
+       pakfire_problem_to_string;
+
        # repo
        pakfire_repo_cmp;
        pakfire_repo_count;
@@ -213,6 +221,7 @@ global:
        pakfire_request_erase;
        pakfire_request_erase_relation;
        pakfire_request_erase_selector;
+       pakfire_request_get_problems;
        pakfire_request_get_transaction;
        pakfire_request_install;
        pakfire_request_install_relation;
diff --git a/src/libpakfire/problem.c b/src/libpakfire/problem.c
new file mode 100644 (file)
index 0000000..7f2b1a7
--- /dev/null
@@ -0,0 +1,244 @@
+/*#############################################################################
+#                                                                             #
+# Pakfire - The IPFire package management system                              #
+# Copyright (C) 2017 Pakfire development team                                 #
+#                                                                             #
+# This program is free software: you can redistribute it and/or modify        #
+# it under the terms of the GNU General Public License as published by        #
+# the Free Software Foundation, either version 3 of the License, or           #
+# (at your option) any later version.                                         #
+#                                                                             #
+# This program is distributed in the hope that it will be useful,             #
+# but WITHOUT ANY WARRANTY; without even the implied warranty of              #
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the               #
+# GNU General Public License for more details.                                #
+#                                                                             #
+# You should have received a copy of the GNU General Public License           #
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.       #
+#                                                                             #
+#############################################################################*/
+
+#include <pakfire/constants.h>
+#include <pakfire/i18n.h>
+#include <pakfire/problem.h>
+#include <pakfire/request.h>
+#include <pakfire/util.h>
+
+static char* to_string(PakfireProblem problem) {
+       Solver* solver = problem->request->solver;
+       Pool* pool = solver->pool;
+
+       // Get the problem rule
+       Id rule = solver_findproblemrule(solver, problem->id);
+
+       // Extract some information about that rule
+       Id dep;
+       Id source;
+       Id target;
+
+       SolverRuleinfo type = solver_ruleinfo(solver, rule, &source, &target, &dep);
+
+       char s[STRING_SIZE];
+       switch (type) {
+               case SOLVER_RULE_DISTUPGRADE:
+                       snprintf(s, STRING_SIZE - 1,
+                               _("%s does not belong to a distupgrade repository"),
+                               pool_solvid2str(pool, source)
+                       );
+                       break;
+
+               case SOLVER_RULE_INFARCH:
+                       snprintf(s, STRING_SIZE - 1,
+                               _("%s has inferior architecture"),
+                               pool_solvid2str(pool, source)
+                       );
+                       break;
+
+               case SOLVER_RULE_UPDATE:
+                       snprintf(s, STRING_SIZE - 1,
+                               _("problem with installed package %s"),
+                               pool_solvid2str(pool, source)
+                       );
+                       break;
+
+               case SOLVER_RULE_JOB:
+                       snprintf(s, STRING_SIZE - 1, _("conflicting requests"));
+                       break;
+
+               case SOLVER_RULE_JOB_UNSUPPORTED:
+                       snprintf(s, STRING_SIZE - 1, _("unsupported request"));
+
+               case SOLVER_RULE_JOB_NOTHING_PROVIDES_DEP:
+                       snprintf(s, STRING_SIZE - 1,
+                               _("nothing provides requested %s"),
+                               pool_dep2str(pool, dep)
+                       );
+                       break;
+
+               case SOLVER_RULE_JOB_UNKNOWN_PACKAGE:
+                       snprintf(s, STRING_SIZE - 1, _("package %s does not exist"),
+                               pool_dep2str(pool, dep)
+                       );
+                       break;
+
+               case SOLVER_RULE_JOB_PROVIDED_BY_SYSTEM:
+                       snprintf(s, STRING_SIZE - 1, _("%s is provided by the system"),
+                               pool_dep2str(pool, dep)
+                       );
+                       break;
+
+               case SOLVER_RULE_RPM:
+                       snprintf(s, STRING_SIZE - 1, _("some dependency problem"));
+                       break;
+
+               case SOLVER_RULE_BEST:
+                       if (source > 0)
+                               snprintf(s, STRING_SIZE - 1,
+                                       _("cannot install the best update candidate for package %s"),
+                                       pool_solvid2str(pool, source)
+                               );
+                       else
+                               snprintf(s, STRING_SIZE - 1, _("cannot install the best candidate for the job"));
+                       break;
+
+               case SOLVER_RULE_RPM_NOT_INSTALLABLE:
+                       snprintf(s, STRING_SIZE - 1,
+                               _("package %s is not installable"),
+                               pool_solvid2str(pool, source)
+                       );
+                       break;
+
+               case SOLVER_RULE_RPM_NOTHING_PROVIDES_DEP:
+                       snprintf(s, STRING_SIZE - 1,
+                               _("nothing provides %s needed by %s"),
+                               pool_dep2str(pool, dep),  pool_solvid2str(pool, source)
+                       );
+                       break;
+
+               case SOLVER_RULE_RPM_SAME_NAME:
+                       snprintf(s, STRING_SIZE - 1,
+                               _("cannot install both %s and %s"),
+                               pool_solvid2str(pool, source),  pool_solvid2str(pool, target)
+                       );
+                       break;
+
+               case SOLVER_RULE_RPM_PACKAGE_CONFLICT:
+                       snprintf(s, STRING_SIZE - 1,
+                               _("package %s conflicts with %s provided by %s"),
+                               pool_solvid2str(pool, source), pool_dep2str(pool, dep),
+                               pool_solvid2str(pool, target)
+                       );
+                       break;
+
+               case SOLVER_RULE_RPM_PACKAGE_OBSOLETES:
+                       snprintf(s, STRING_SIZE - 1,
+                               _("package %s obsoletes %s provided by %s"),
+                               pool_solvid2str(pool, source), pool_dep2str(pool, dep),
+                               pool_solvid2str(pool, target)
+                       );
+                       break;
+
+               case SOLVER_RULE_RPM_INSTALLEDPKG_OBSOLETES:
+                       snprintf(s, STRING_SIZE - 1,
+                               _("installed package %s obsoletes %s provided by %s"),
+                               pool_solvid2str(pool, source), pool_dep2str(pool, dep),
+                               pool_solvid2str(pool, target)
+                       );
+                       break;
+
+               case SOLVER_RULE_RPM_IMPLICIT_OBSOLETES:
+                       snprintf(s, STRING_SIZE - 1,
+                               _("package %s implicitely obsoletes %s provided by %s"),
+                               pool_solvid2str(pool, source), pool_dep2str(pool, dep),
+                               pool_solvid2str(pool, target)
+                       );
+                       break;
+
+               case SOLVER_RULE_RPM_PACKAGE_REQUIRES:
+                       snprintf(s, STRING_SIZE - 1,
+                               _("package %s requires %s, but none of the providers can be installed"),
+                               pool_solvid2str(pool, source), pool_dep2str(pool, dep)
+                       );
+                       break;
+
+               case SOLVER_RULE_RPM_SELF_CONFLICT:
+                       snprintf(s, STRING_SIZE - 1,
+                               _("package %s conflicts with %s provided by itself"),
+                               pool_solvid2str(pool, source), pool_dep2str(pool, dep)
+                       );
+                       break;
+
+               case SOLVER_RULE_YUMOBS:
+                       snprintf(s, STRING_SIZE - 1,
+                               _("both package %s and %s obsolete %s"),
+                               pool_solvid2str(pool, source), pool_solvid2str(pool, target), pool_dep2str(pool, dep)
+                       );
+                       break;
+
+               case SOLVER_RULE_UNKNOWN:
+               case SOLVER_RULE_FEATURE:
+               case SOLVER_RULE_LEARNT:
+               case SOLVER_RULE_CHOICE:
+                       snprintf(s, STRING_SIZE - 1, _("bad rule type"));
+                       break;
+
+       }
+
+       return pakfire_strdup(s);
+}
+
+PakfireProblem pakfire_problem_create(PakfireRequest request, Id id) {
+       PakfireProblem problem = pakfire_calloc(1, sizeof(*problem));
+
+       problem->request = pakfire_request_ref(request);
+       problem->id = id;
+
+       // Initialise reference counter
+       problem->nrefs = 1;
+       problem->next = NULL;
+
+       // Extract information from solver
+       problem->string = to_string(problem);
+
+       return problem;
+}
+
+PakfireProblem pakfire_problem_ref(PakfireProblem problem) {
+       problem->nrefs++;
+
+       return problem;
+}
+
+void pakfire_problem_free(PakfireProblem problem) {
+       if (--problem->nrefs > 0)
+               return;
+
+       if (problem->next)
+               pakfire_problem_free(problem->next);
+
+       pakfire_request_free(problem->request);
+
+       if (problem->string)
+               pakfire_free(problem->string);
+
+       pakfire_free(problem);
+}
+
+PakfireProblem pakfire_problem_next(PakfireProblem problem) {
+       return problem->next;
+}
+
+void pakfire_problem_append(PakfireProblem problem, PakfireProblem new_problem) {
+       PakfireProblem next;
+
+       // Go to last problem in list
+       while ((next = pakfire_problem_next(problem)) != NULL) {
+               problem = next;
+       }
+
+       problem->next = pakfire_problem_ref(new_problem);
+}
+
+const char* pakfire_problem_to_string(PakfireProblem problem) {
+       return problem->string;
+}
index e42811788d96f6c46e26f6297117ef6749b85802..24847d32a44097927d8030e0458ba077b4cacfc8 100644 (file)
@@ -27,6 +27,7 @@
 #endif
 
 #include <pakfire/package.h>
+#include <pakfire/problem.h>
 #include <pakfire/request.h>
 #include <pakfire/selector.h>
 #include <pakfire/transaction.h>
@@ -39,10 +40,22 @@ PakfireRequest pakfire_request_create(PakfirePool pool) {
 
        queue_init(&request->queue);
 
+       // Initialise reference counter
+       request->nrefs = 1;
+
+       return request;
+}
+
+PakfireRequest pakfire_request_ref(PakfireRequest request) {
+       request->nrefs++;
+
        return request;
 }
 
 void pakfire_request_free(PakfireRequest request) {
+       if (--request->nrefs > 0)
+               return;
+
        if (request->transaction)
                transaction_free(request->transaction);
 
@@ -134,6 +147,22 @@ int pakfire_request_solve(PakfireRequest request, int flags) {
        return ret;
 }
 
+PakfireProblem pakfire_request_get_problems(PakfireRequest request) {
+       Id problem = 0;
+       PakfireProblem ret = NULL;
+
+       while ((problem = solver_next_problem(request->solver, problem)) != 0) {
+               PakfireProblem p = pakfire_problem_create(request, problem);
+
+               if (ret)
+                       pakfire_problem_append(ret, p);
+               else
+                       ret = p;
+       }
+
+       return ret;
+}
+
 PakfireTransaction pakfire_request_get_transaction(PakfireRequest request) {
        if (!request->transaction)
                return NULL;