src/libpakfire/repocache.c \
src/libpakfire/request.c \
src/libpakfire/selector.c \
+ src/libpakfire/solution.c \
src/libpakfire/solver.c \
src/libpakfire/step.c \
src/libpakfire/transaction.c \
src/libpakfire/include/pakfire/repocache.h \
src/libpakfire/include/pakfire/request.h \
src/libpakfire/include/pakfire/selector.h \
+ src/libpakfire/include/pakfire/solution.h \
src/libpakfire/include/pakfire/solver.h \
src/libpakfire/include/pakfire/step.h \
src/libpakfire/include/pakfire/transaction.h \
{ NULL, NULL, 0, NULL }
};
-static PyMethodDef Solution_methods[] = {
- { NULL, NULL, 0, NULL }
-};
-
static struct PyModuleDef moduledef = {
.m_base = PyModuleDef_HEAD_INIT,
.m_name = "_pakfire",
PyModule_AddObject(module, "Request", (PyObject *)&RequestType);
// Solution
- SolutionType.tp_methods = Solution_methods;
if (PyType_Ready(&SolutionType) < 0)
return NULL;
+
Py_INCREF(&SolutionType);
PyModule_AddObject(module, "Solution", (PyObject *)&SolutionType);
#include "pool.h"
#include "problem.h"
+#include "solution.h"
static ProblemObject* Problem_new_core(PyTypeObject* type, PakfireProblem problem) {
ProblemObject* self = (ProblemObject *)type->tp_alloc(type, 0);
return PyUnicode_FromString(string);
}
+static PyObject* Problem_get_solutions(ProblemObject* self) {
+ PyObject* list = PyList_New(0);
+
+ PakfireSolution solution = pakfire_problem_get_solutions(self->problem);
+ while (solution) {
+ PyObject* s = new_solution(solution);
+ PyList_Append(list, s);
+ Py_DECREF(s);
+
+ solution = pakfire_solution_next(solution);
+ }
+
+ return list;
+}
+
static struct PyMethodDef Problem_methods[] = {
{ NULL }
};
static struct PyGetSetDef Problem_getsetters[] = {
+ {
+ "solutions",
+ (getter)Problem_get_solutions,
+ NULL,
+ NULL,
+ NULL,
+ },
{ NULL },
};
/*#############################################################################
# #
# 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 <solv/policy.h>
-#include <solv/solverdebug.h>
+#include <pakfire/errno.h>
+#include <pakfire/solution.h>
-#include "constants.h"
-#include "problem.h"
+#include "pool.h"
#include "solution.h"
-PyTypeObject SolutionType = {
- PyVarObject_HEAD_INIT(NULL, 0)
- tp_name: "_pakfire.Solution",
- tp_basicsize: sizeof(SolutionObject),
- tp_flags: Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
- tp_new: Solution_new,
- tp_dealloc: (destructor)Solution_dealloc,
- tp_doc: "Sat Solution objects",
- tp_str: (reprfunc)Solution_string,
-};
-
-PyObject *Solution_new(PyTypeObject *type, PyObject *args, PyObject *kwds) {
- SolutionObject *self;
- ProblemObject *problem;
- Id id;
-
- if (!PyArg_ParseTuple(args, "Oi", &problem, &id)) {
- /* XXX raise exception */
- return NULL;
- }
-
- 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;
+static SolutionObject* Solution_new_core(PyTypeObject* type, PakfireSolution solution) {
+ SolutionObject* self = (SolutionObject *)type->tp_alloc(type, 0);
+ if (self) {
+ self->solution = solution;
}
- return (PyObject *)self;
+ return self;
}
-PyObject *Solution_dealloc(SolutionObject *self) {
- Py_TYPE(self)->tp_free((PyObject *)self);
+PyObject* new_solution(PakfireSolution solution) {
+ SolutionObject* s = Solution_new_core(&SolutionType, solution);
- Py_RETURN_NONE;
+ return (PyObject*)s;
}
-PyObject *Solution_string(SolutionObject *self) {
- Pool *pool = self->_solver->pool;
- Solver *solver = self->_solver;
- char str[STRING_SIZE];
-
- Solvable *s, *sd;
- Id p, rp;
- Id how, what, select;
-
- Id element = 0;
- while ((element = solver_next_solutionelement(solver, self->problem_id, self->id, element, &p, &rp)) != 0) {
- if (p == SOLVER_SOLUTION_JOB) {
- how = solver->job.elements[rp - 1];
- what = solver->job.elements[rp];
- select = how & SOLVER_SELECTMASK;
-
- switch (how & SOLVER_JOBMASK) {
- case SOLVER_INSTALL:
- if (select == SOLVER_SOLVABLE && pool->installed && pool->solvables[what].repo == pool->installed)
- snprintf(str, STRING_SIZE - 1, _("do not keep %s installed"),
- pool_solvid2str(pool, what));
- else if (select == SOLVER_SOLVABLE_PROVIDES)
- snprintf(str, STRING_SIZE - 1, _("do not install a solvable %s"),
- solver_select2str(pool, select, what));
- else
- snprintf(str, STRING_SIZE - 1, _("do not install %s"),
- solver_select2str(pool, select, what));
- break;
-
- case SOLVER_ERASE:
- if (select == SOLVER_SOLVABLE && !(pool->installed && pool->solvables[what].repo == pool->installed))
- snprintf(str, STRING_SIZE - 1, _("do not forbid installation of %s"),
- pool_solvid2str(pool, what));
- else if (select == SOLVER_SOLVABLE_PROVIDES)
- snprintf(str, STRING_SIZE - 1, _("do not deinstall all solvables %s"),
- solver_select2str(pool, select, what));
- else
- snprintf(str, STRING_SIZE - 1, _("do not deinstall %s"),
- solver_select2str(pool, select, what));
- break;
-
- case SOLVER_UPDATE:
- snprintf(str, STRING_SIZE - 1, _("do not install most recent version of %s"),
- solver_select2str(pool, select, what));
- break;
-
- case SOLVER_LOCK:
- snprintf(str, STRING_SIZE - 1, _("do not lock %s"),
- solver_select2str(pool, select, what));
- break;
+static PyObject* Solution_new(PyTypeObject* type, PyObject* args, PyObject* kwds) {
+ SolutionObject* self = Solution_new_core(type, NULL);
- default:
- snprintf(str, STRING_SIZE - 1, _("do something different"));
- break;
- }
-
- } else if (p == SOLVER_SOLUTION_INFARCH) {
- s = pool->solvables + rp;
- if (pool->installed && s->repo == pool->installed)
- snprintf(str, STRING_SIZE - 1, _("keep %s despite the inferior architecture"),
- pool_solvable2str(pool, s));
- else
- snprintf(str, STRING_SIZE - 1, _("install %s despite the inferior architecture"),
- pool_solvable2str(pool, s));
-
- } else if (p == SOLVER_SOLUTION_DISTUPGRADE) {
- s = pool->solvables + rp;
- if (pool->installed && s->repo == pool->installed)
- snprintf(str, STRING_SIZE - 1, _("keep obsolete %s"),
- pool_solvable2str(pool, s));
- else
- snprintf(str, STRING_SIZE - 1, _("install %s from excluded repository"),
- pool_solvable2str(pool, s));
-
- } else {
- s = pool->solvables + p;
- sd = rp ? pool->solvables + rp : 0;
-
- if (sd) {
- int illegal = policy_is_illegal(solver, s, sd, 0);
+ return (PyObject *)self;
+}
- // XXX multiple if clauses can match here
- if ((illegal & POLICY_ILLEGAL_DOWNGRADE) != 0)
- snprintf(str, STRING_SIZE - 1, _("allow downgrade of %s to %s"),
- pool_solvable2str(pool, s), pool_solvable2str(pool, sd));
+static void Solution_dealloc(SolutionObject* self) {
+ if (self->solution)
+ pakfire_solution_free(self->solution);
- if ((illegal & POLICY_ILLEGAL_ARCHCHANGE) != 0)
- snprintf(str, STRING_SIZE - 1, _("allow architecture change of %s to %s"),
- pool_solvable2str(pool, s), pool_solvable2str(pool, sd));
+ Py_TYPE(self)->tp_free((PyObject *)self);
+}
- if ((illegal & POLICY_ILLEGAL_VENDORCHANGE) != 0) {
- if (sd->vendor)
- snprintf(str, STRING_SIZE - 1, _("allow vendor change from '%s' (%s) to '%s' (%s)"),
- pool_id2str(pool, s->vendor), pool_solvable2str(pool, s),
- pool_id2str(pool, sd->vendor), pool_solvable2str(pool, sd));
- else
- snprintf(str, STRING_SIZE - 1, _("allow vendor change from '%s' (%s) to no vendor (%s)"),
- pool_id2str(pool, s->vendor), pool_solvable2str(pool, s),
- pool_solvable2str(pool, sd));
- }
+static int Solution_init(SolutionObject* self, PyObject* args, PyObject* kwds) {
+ return 0;
+}
- if (!illegal)
- snprintf(str, STRING_SIZE - 1, _("allow replacement of %s with %s"),
- pool_solvable2str(pool, s), pool_solvable2str(pool, sd));
- }
- }
- }
+static PyObject* Solution_string(SolutionObject* self) {
+ const char* string = pakfire_solution_to_string(self->solution);
- return Py_BuildValue("s", &str);
+ return PyUnicode_FromString(string);
}
+
+PyTypeObject SolutionType = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ tp_name: "_pakfire.Solution",
+ tp_basicsize: sizeof(SolutionObject),
+ tp_flags: Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
+ tp_new: Solution_new,
+ tp_dealloc: (destructor)Solution_dealloc,
+ tp_init: (initproc)Solution_init,
+ tp_doc: "Solution object",
+ tp_str: (reprfunc)Solution_string,
+};
/*#############################################################################
# #
# 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 "solver.h"
+#include <pakfire/solution.h>
-// Sat Solution object
typedef struct {
- PyObject_HEAD
- Solver *_solver;
- Id problem_id;
- Id id;
+ PyObject_HEAD
+ PakfireSolution solution;
} SolutionObject;
-extern PyObject *Solution_new(PyTypeObject *type, PyObject *args, PyObject *kwds);
-extern PyObject *Solution_dealloc(SolutionObject *self);
-
-extern PyObject *Solution_string(SolutionObject *self);
-
extern PyTypeObject SolutionType;
+PyObject* new_solution(PakfireSolution solution);
+
#endif /* PYTHON_PAKFIRE_SOLUTION_H */
const char* pakfire_problem_to_string(PakfireProblem problem);
+PakfireSolution pakfire_problem_get_solutions(PakfireProblem problem);
+
#ifdef PAKFIRE_PRIVATE
struct _PakfireProblem {
--- /dev/null
+/*#############################################################################
+# #
+# 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_SOLUTION_H
+#define PAKFIRE_SOLUTION_H
+
+#include <pakfire/problem.h>
+
+PakfireSolution pakfire_solution_create(PakfireProblem problem, Id id);
+PakfireSolution pakfire_solution_ref(PakfireSolution solution);
+void pakfire_solution_free(PakfireSolution solution);
+
+PakfireSolution pakfire_solution_next(PakfireSolution solution);
+void pakfire_solution_append(PakfireSolution solution, PakfireSolution new_solution);
+
+char* pakfire_solution_to_string(PakfireSolution solution);
+
+#ifdef PAKFIRE_PRIVATE
+
+struct _PakfireSolution {
+ PakfireProblem problem;
+ Id id;
+ char** elements;
+
+ PakfireSolution next;
+ int nrefs;
+};
+
+#endif
+
+#endif /* PAKFIRE_SOLUTION_H */
typedef struct _PakfireRepoCache* PakfireRepoCache;
typedef struct _PakfireRequest* PakfireRequest;
typedef struct _PakfireSelector* PakfireSelector;
+typedef struct _PakfireSolution* PakfireSolution;
typedef struct _PakfireStep* PakfireStep;
typedef struct _PakfireTransaction* PakfireTransaction;
pakfire_problem_append;
pakfire_problem_create;
pakfire_problem_free;
+ pakfire_problem_get_solutions;
pakfire_problem_next;
pakfire_problem_ref;
pakfire_problem_to_string;
pakfire_selector_providers;
pakfire_selector_set;
+ # solution
+ pakfire_solution_create;
+ pakfire_solution_free;
+ pakfire_solution_next;
+ pakfire_solution_ref;
+ pakfire_solution_to_string;
+
# step
pakfire_step_create;
pakfire_step_free;
#include <pakfire/i18n.h>
#include <pakfire/problem.h>
#include <pakfire/request.h>
+#include <pakfire/solution.h>
#include <pakfire/util.h>
static char* to_string(PakfireProblem problem) {
const char* pakfire_problem_to_string(PakfireProblem problem) {
return problem->string;
}
+
+PakfireSolution pakfire_problem_get_solutions(PakfireProblem problem) {
+ PakfireSolution ret = NULL;
+
+ Id solution = 0;
+ while ((solution = solver_next_solution(problem->request->solver, problem->id, solution)) != 0) {
+ PakfireSolution s = pakfire_solution_create(problem, solution);
+
+ if (ret)
+ pakfire_solution_append(ret, s);
+ else
+ ret = s;
+ }
+
+ return ret;
+}
--- /dev/null
+/*#############################################################################
+# #
+# 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 <assert.h>
+
+#include <solv/policy.h>
+
+#include <pakfire/constants.h>
+#include <pakfire/i18n.h>
+#include <pakfire/problem.h>
+#include <pakfire/solution.h>
+#include <pakfire/util.h>
+
+static void import_elements(PakfireSolution solution) {
+ Solver* solver = solution->problem->request->solver;
+ Pool* pool = solver->pool;
+
+ // Reserve memory
+ unsigned int num = solver_solutionelement_count(solver, solution->problem->id, solution->id);
+ char** elements = solution->elements = pakfire_calloc(num + 1, sizeof(*elements));
+
+ Id p;
+ Id rp;
+ Id element = 0;
+ while ((element = solver_next_solutionelement(solver, solution->problem->id, solution->id, element, &p, &rp)) != 0) {
+ char line[STRING_SIZE];
+
+ if (p == SOLVER_SOLUTION_JOB || p == SOLVER_SOLUTION_POOLJOB) {
+ if (p == SOLVER_SOLUTION_JOB)
+ rp += solver->pooljobcnt;
+
+ Id how = solver->job.elements[rp-1];
+ Id what = solver->job.elements[rp];
+
+ // XXX pool_job2str must be localised
+ snprintf(line, STRING_SIZE - 1, _("do not ask to %s"),
+ pool_job2str(pool, how, what, 0));
+
+ } else if (p == SOLVER_SOLUTION_INFARCH) {
+ Solvable* s = pool->solvables + rp;
+
+ if (pool->installed && s->repo == pool->installed)
+ snprintf(line, STRING_SIZE - 1, _("keep %s despite the inferior architecture"),
+ pool_solvable2str(pool, s));
+ else
+ snprintf(line, STRING_SIZE - 1, _("install %s despite the inferior architecture"),
+ pool_solvable2str(pool, s));
+
+ } else if (p == SOLVER_SOLUTION_DISTUPGRADE) {
+ Solvable* s = pool->solvables + rp;
+
+ if (pool->installed && s->repo == pool->installed)
+ snprintf(line, STRING_SIZE - 1, _("keep obsolete %s"),
+ pool_solvable2str(pool, s));
+ else
+ snprintf(line, STRING_SIZE - 1, _("install %s"),
+ pool_solvable2str(pool, s));
+
+ } else if (p == SOLVER_SOLUTION_BEST) {
+ Solvable* s = pool->solvables + rp;
+
+ if (pool->installed && s->repo == pool->installed)
+ snprintf(line, STRING_SIZE - 1, _("keep old %s"),
+ pool_solvable2str(pool, s));
+ else
+ snprintf(line, STRING_SIZE - 1, _("install %s despite the old version"),
+ pool_solvable2str(pool, s));
+
+ } else if (p > 0 && rp == 0)
+ snprintf(line, STRING_SIZE - 1, _("allow deinstallation of %s"),
+ pool_solvid2str(pool, p));
+
+ else if (p > 0 && rp > 0)
+ snprintf(line, STRING_SIZE - 1, _("allow replacement of %s with %s"),
+ pool_solvid2str(pool, p), pool_solvid2str(pool, rp));
+
+ else
+ snprintf(line, STRING_SIZE - 1, _("bad solution element"));
+
+ // Save line in elements array
+ *elements++ = pakfire_strdup(line);
+ }
+
+ // Terminate array
+ *elements = NULL;
+}
+
+PakfireSolution pakfire_solution_create(PakfireProblem problem, Id id) {
+ PakfireSolution solution = pakfire_calloc(1, sizeof(*solution));
+
+ solution->problem = pakfire_problem_ref(problem);
+ solution->id = id;
+
+ // Initialise reference counter
+ solution->nrefs = 1;
+ solution->next = NULL;
+
+ // Extract information from solver
+ import_elements(solution);
+
+ return solution;
+}
+
+PakfireSolution pakfire_solution_ref(PakfireSolution solution) {
+ solution->nrefs++;
+
+ return solution;
+}
+
+void pakfire_solution_free(PakfireSolution solution) {
+ if (--solution->nrefs > 0)
+ return;
+
+ if (solution->next)
+ pakfire_solution_free(solution->next);
+
+ pakfire_problem_free(solution->problem);
+
+ if (solution->elements)
+ while (*solution->elements)
+ pakfire_free(*solution->elements++);
+
+ pakfire_free(solution);
+}
+
+PakfireSolution pakfire_solution_next(PakfireSolution solution) {
+ return solution->next;
+}
+
+void pakfire_solution_append(PakfireSolution solution, PakfireSolution new_solution) {
+ PakfireSolution next;
+
+ // Go to last problem in list
+ while ((next = pakfire_solution_next(solution)) != NULL) {
+ solution = next;
+ }
+
+ solution->next = pakfire_solution_ref(new_solution);
+}
+
+static size_t count_elements_length(PakfireSolution solution) {
+ size_t length = 0;
+
+ char** elements = solution->elements;
+ while (*elements) {
+ length += strlen(*elements++) + 1;
+ }
+
+ return length;
+}
+
+char* pakfire_solution_to_string(PakfireSolution solution) {
+ // Determine length of output string
+ size_t length = count_elements_length(solution);
+
+ // Allocate string
+ char s[length];
+ char* p = s;
+
+ char** elements = solution->elements;
+ while (*elements) {
+ // Copy line
+ char* e = *elements++;
+ while (*e)
+ *p++ = *e++;
+
+ // Add newline
+ *p++ = '\n';
+ }
+
+ // Terminate string
+ if (p > s)
+ *(p-1) = '\0';
+
+ // Make sure that we wrote the string exactly to
+ // the last character
+ assert((s + length) == p);
+
+ return pakfire_strdup(s);
+}