From: Michael Tremer Date: Sat, 20 May 2017 13:13:36 +0000 (+0200) Subject: libpakfire: Allow extracting problems from solver X-Git-Tag: 0.9.28~1285^2~1340 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=d528058e3db3c540f34b7725b7e68177550e5787;p=pakfire.git libpakfire: Allow extracting problems from solver When a request could not be solved, the solver will return a list of problems of what went wrong. Signed-off-by: Michael Tremer --- diff --git a/Makefile.am b/Makefile.am index 8b615339e..4e48a6b1a 100644 --- a/Makefile.am +++ b/Makefile.am @@ -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 \ diff --git a/src/_pakfire/_pakfiremodule.c b/src/_pakfire/_pakfiremodule.c index 773e090fa..8de3f47c7 100644 --- a/src/_pakfire/_pakfiremodule.c +++ b/src/_pakfire/_pakfiremodule.c @@ -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); diff --git a/src/_pakfire/problem.c b/src/_pakfire/problem.c index 3a15cee17..0f00f1020 100644 --- a/src/_pakfire/problem.c +++ b/src/_pakfire/problem.c @@ -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 # @@ -19,252 +19,82 @@ #############################################################################*/ #include +#include -#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 +#include - 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, +}; diff --git a/src/_pakfire/problem.h b/src/_pakfire/problem.h index 22b3b7478..7146b5c5d 100644 --- a/src/_pakfire/problem.h +++ b/src/_pakfire/problem.h @@ -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 # @@ -23,36 +23,15 @@ #include -#include -#include +#include -// 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 */ diff --git a/src/_pakfire/request.c b/src/_pakfire/request.c index 0ac6db627..dc786baac 100644 --- a/src/_pakfire/request.c +++ b/src/_pakfire/request.c @@ -25,6 +25,7 @@ #include #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, diff --git a/src/_pakfire/solution.c b/src/_pakfire/solution.c index 22651e610..c1eac65ae 100644 --- a/src/_pakfire/solution.c +++ b/src/_pakfire/solution.c @@ -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 index 000000000..07fb6785a --- /dev/null +++ b/src/libpakfire/include/pakfire/problem.h @@ -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 . # +# # +#############################################################################*/ + +#ifndef PAKFIRE_PROBLEM_H +#define PAKFIRE_PROBLEM_H + +#include +#include + +#include + +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 */ diff --git a/src/libpakfire/include/pakfire/request.h b/src/libpakfire/include/pakfire/request.h index 01f70a599..f29b0a975 100644 --- a/src/libpakfire/include/pakfire/request.h +++ b/src/libpakfire/include/pakfire/request.h @@ -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 diff --git a/src/libpakfire/include/pakfire/types.h b/src/libpakfire/include/pakfire/types.h index 4ea175b5f..51d764212 100644 --- a/src/libpakfire/include/pakfire/types.h +++ b/src/libpakfire/include/pakfire/types.h @@ -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; diff --git a/src/libpakfire/libpakfire.sym b/src/libpakfire/libpakfire.sym index 047a7a0bb..7e6e776c6 100644 --- a/src/libpakfire/libpakfire.sym +++ b/src/libpakfire/libpakfire.sym @@ -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 index 000000000..7f2b1a76a --- /dev/null +++ b/src/libpakfire/problem.c @@ -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 . # +# # +#############################################################################*/ + +#include +#include +#include +#include +#include + +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; +} diff --git a/src/libpakfire/request.c b/src/libpakfire/request.c index e42811788..24847d32a 100644 --- a/src/libpakfire/request.c +++ b/src/libpakfire/request.c @@ -27,6 +27,7 @@ #endif #include +#include #include #include #include @@ -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;