python setup.py sdist
.PHONY: install
-install:
+install: po
python setup.py install --root $(DESTDIR)
-mkdir -pv $(DESTDIR)/etc/pakfire.repos.d
from _pakfire import *
import transaction
+import util
from i18n import _
self.pakfire = pakfire
self.pool = pool
- self._solver = _pakfire.Solver(self.pool)
+ def solve(self, request, update=False, uninstall=False, allow_downgrade=False,
+ interactive=False):
- def solve(self, request, update=False, uninstall=False, allow_downgrade=False):
- self._solver.set_allow_uninstall(uninstall)
- self._solver.set_allow_downgrade(allow_downgrade)
+ # Create a new solver.
+ solver = _pakfire.Solver(self.pool)
+
+ solver.set_allow_uninstall(uninstall)
+ solver.set_allow_downgrade(allow_downgrade)
# Configure the solver for an update.
if update:
- self._solver.set_updatesystem(True)
- self._solver.set_do_split_provides(True)
+ solver.set_updatesystem(True)
+ solver.set_do_split_provides(True)
- res = self._solver.solve(request)
+ # Actually solve the request.
+ res = solver.solve(request)
logging.debug("Solver status: %s" % res)
# If the solver succeeded, we return the transaction and return.
if res:
# Return a resulting Transaction.
- t = Transaction(self._solver)
+ t = Transaction(solver)
return transaction.Transaction.from_solver(self.pakfire, self, t)
# Do the problem handling...
- problems = self._solver.get_problems(request)
+ problems = solver.get_problems(request)
logging.info("")
- logging.info(_("The solver returned %s problems:") % len(problems))
- logging.info("")
+ logging.info(_("The solver returned one problem:", "The solver returned %(num)s problems:",
+ len(problems)) % { "num" : len(problems) })
i = 0
- for p in self._solver.get_problems(request):
+ for problem in problems:
i += 1
# Print information about the problem to the user.
- logging.info(_(" Problem #%d:") % i)
- logging.info(" %s" % p)
- logging.info("")
+ logging.info(" #%d: %s" % (i, problem))
+
+ logging.info("")
- return res
+ if not interactive:
+ return False
+
+ # Ask the user if he or she want to modify the request. If not, just exit.
+ if not util.ask_user(_("Do you want to manually alter the request?")):
+ return False
+
+ print _("You can now try to satisfy the solver by modifying your request.")
+
+ altered = False
+ while True:
+ if len(problems) > 1:
+ print _("Which problem to you want to resolve?")
+ if altered:
+ print _("Press enter to try to re-solve the request.")
+ print "[1-%s]:" % len(problems),
+
+ answer = raw_input()
+
+ # If the user did not enter anything, we abort immediately.
+ if not answer:
+ break
+
+ # If the user did type anything else than an integer, we ask
+ # again.
+ try:
+ answer = int(answer)
+ except ValueError:
+ continue
+
+ # If the user entered an integer outside of range, we ask
+ # again.
+ try:
+ problem = problems[answer - 1]
+ except KeyError:
+ continue
+
+ else:
+ problem = problem[0]
+
+ # Get all solutions.
+ solutions = problem.get_solutions()
+
+ if len(solutions) == 1:
+ solution = solutions[0]
+ print _(" Solution: %s") % solution
+ print
+
+ if util.ask_user("Do you accept the solution above?"):
+ altered = True
+ print "XXX do something"
+
+ continue
+ else:
+ print _(" Solutions:")
+ i = 0
+ for solution in solutions:
+ i += 1
+ print " #%d: %s" % (i, solution)
+
+ print
+
+ if not altered:
+ return False
+
+ # If the request was altered by the user, we try to solve it again
+ # and see what happens.
+ return self.solve(request, update=update, uninstall=uninstall,
+ allow_downgrade=allow_downgrade, interactive=interactive)
src/relation.c
src/repo.c
src/request.c
+src/solution.c
src/solvable.c
src/solver.c
src/step.c
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2011-07-29 15:04+0200\n"
+"POT-Creation-Date: 2011-07-29 17:32+0200\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
msgid "Loading installed packages"
msgstr ""
-#: ../pakfire/satsolver.py:105
-#, python-format
-msgid "The solver returned %s problems:"
+#: ../pakfire/satsolver.py:110
+msgid "The solver returned one problem:"
msgstr ""
#. Print information about the problem to the user.
-#: ../pakfire/satsolver.py:113
+#: ../pakfire/satsolver.py:118
#, python-format
-msgid " Problem #%d:"
+msgid " #%d: %s"
+msgstr ""
+
+#. Ask the user if he or she want to modify the request. If not, just exit.
+#: ../pakfire/satsolver.py:126
+msgid "Do you want to manually alter the request?"
+msgstr ""
+
+#: ../pakfire/satsolver.py:129
+msgid "You can now try to satisfy the solver by modifying your request."
+msgstr ""
+
+#: ../pakfire/satsolver.py:134
+msgid "Which problem to you want to resolve?"
+msgstr ""
+
+#: ../pakfire/satsolver.py:136
+msgid "Press enter to try to re-solve the request."
+msgstr ""
+
+#: ../pakfire/satsolver.py:167
+#, python-format
+msgid " Solution: %s"
+msgstr ""
+
+#: ../pakfire/satsolver.py:176
+msgid " Solutions:"
msgstr ""
#: ../pakfire/transaction.py:89
msgid "%s [y/N]"
msgstr ""
-#: ../src/problem.c:126
+#: ../src/problem.c:140
#, c-format
msgid "%s does not belong to a distupgrade repository"
msgstr ""
-#: ../src/problem.c:133
+#: ../src/problem.c:147
#, c-format
msgid "%s has inferior architecture"
msgstr ""
-#: ../src/problem.c:140
+#: ../src/problem.c:154
#, c-format
msgid "problem with installed package %s"
msgstr ""
-#: ../src/problem.c:146
+#: ../src/problem.c:160
#, c-format
msgid "conflicting requests"
msgstr ""
-#: ../src/problem.c:151
+#: ../src/problem.c:165
#, c-format
msgid "nothing provides requested %s"
msgstr ""
-#: ../src/problem.c:157
+#: ../src/problem.c:171
#, c-format
msgid "some dependency problem"
msgstr ""
-#: ../src/problem.c:162
+#: ../src/problem.c:176
#, c-format
msgid "package %s is not installable"
msgstr ""
-#: ../src/problem.c:169
+#: ../src/problem.c:183
#, c-format
msgid "nothing provides %s needed by %s"
msgstr ""
-#: ../src/problem.c:176
+#: ../src/problem.c:190
#, c-format
msgid "cannot install both %s and %s"
msgstr ""
-#: ../src/problem.c:183
+#: ../src/problem.c:197
#, c-format
msgid "package %s conflicts with %s provided by %s"
msgstr ""
-#: ../src/problem.c:191
+#: ../src/problem.c:205
#, c-format
msgid "package %s obsoletes %s provided by %s"
msgstr ""
-#: ../src/problem.c:199
+#: ../src/problem.c:213
#, c-format
msgid "installed package %s obsoletes %s provided by %s"
msgstr ""
-#: ../src/problem.c:207
+#: ../src/problem.c:221
#, c-format
msgid "package %s implicitely obsoletes %s provided by %s"
msgstr ""
-#: ../src/problem.c:215
+#: ../src/problem.c:229
#, c-format
msgid "package %s requires %s, but none of the providers can be installed"
msgstr ""
-#: ../src/problem.c:222
+#: ../src/problem.c:236
#, c-format
msgid "package %s conflicts with %s provided by itself"
msgstr ""
-#: ../src/problem.c:231
+#: ../src/problem.c:245
#, c-format
msgid "bad rule type"
msgstr ""
+
+#: ../src/solution.c:67
+#, c-format
+msgid "do not keep %s installed"
+msgstr ""
+
+#: ../src/solution.c:70
+#, c-format
+msgid "do not install a solvable %s"
+msgstr ""
+
+#: ../src/solution.c:73
+#, c-format
+msgid "do not install %s"
+msgstr ""
+
+#: ../src/solution.c:79
+#, c-format
+msgid "do not forbid installation of %s"
+msgstr ""
+
+#: ../src/solution.c:82
+#, c-format
+msgid "do not deinstall all solvables %s"
+msgstr ""
+
+#: ../src/solution.c:85
+#, c-format
+msgid "do not deinstall %s"
+msgstr ""
+
+#: ../src/solution.c:90
+#, c-format
+msgid "do not install most recent version of %s"
+msgstr ""
+
+#: ../src/solution.c:95
+#, c-format
+msgid "do not lock %s"
+msgstr ""
+
+#: ../src/solution.c:100
+#, c-format
+msgid "do something different"
+msgstr ""
+
+#: ../src/solution.c:107
+#, c-format
+msgid "keep %s despite the inferior architecture"
+msgstr ""
+
+#: ../src/solution.c:110
+#, c-format
+msgid "install %s despite the inferior architecture"
+msgstr ""
+
+#: ../src/solution.c:116
+#, c-format
+msgid "keep obsolete %s"
+msgstr ""
+
+#: ../src/solution.c:119
+#, c-format
+msgid "install %s from excluded repository"
+msgstr ""
+
+#: ../src/solution.c:131
+#, c-format
+msgid "allow downgrade of %s to %s"
+msgstr ""
+
+#: ../src/solution.c:135
+#, c-format
+msgid "allow architecture change of %s to %s"
+msgstr ""
+
+#: ../src/solution.c:140
+#, c-format
+msgid "allow vendor change from '%s' (%s) to '%s' (%s)"
+msgstr ""
+
+#: ../src/solution.c:144
+#, c-format
+msgid "allow vendor change from '%s' (%s) to no vendor (%s)"
+msgstr ""
+
+#: ../src/solution.c:150
+#, c-format
+msgid "allow replacement of %s with %s"
+msgstr ""
#include "relation.h"
#include "repo.h"
#include "request.h"
+#include "solution.h"
#include "solvable.h"
#include "solver.h"
#include "step.h"
{"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 }
};
{ NULL, NULL, 0, NULL }
};
+static PyMethodDef Solution_methods[] = {
+ { NULL, NULL, 0, NULL }
+};
+
static PyMethodDef Solver_methods[] = {
{"solve", (PyCFunction)Solver_solve, METH_VARARGS, NULL},
{"get_allow_downgrade", (PyCFunction)Solver_get_allow_downgrade, METH_NOARGS, NULL},
Py_INCREF(&RequestType);
PyModule_AddObject(m, "Request", (PyObject *)&RequestType);
+ // Solution
+ SolutionType.tp_methods = Solution_methods;
+ if (PyType_Ready(&SolutionType) < 0)
+ return;
+ Py_INCREF(&SolutionType);
+ PyModule_AddObject(m, "Solution", (PyObject *)&SolutionType);
+
// Solver
SolverType.tp_methods = Solver_methods;
if (PyType_Ready(&SolverType) < 0)
#include "problem.h"
#include "relation.h"
#include "request.h"
+#include "solution.h"
#include "solvable.h"
#include "solver.h"
}
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;
}
extern PyObject *Problem_get_target(ProblemObject *self);
extern PyObject *Problem_get_dep(ProblemObject *self);
+extern PyObject *Problem_get_solutions(ProblemObject *self);
+
extern PyTypeObject ProblemType;
#endif
--- /dev/null
+
+#include <Python.h>
+
+#include <satsolver/policy.h>
+#include <satsolver/solverdebug.h>
+
+#include "config.h"
+#include "problem.h"
+#include "solution.h"
+
+PyTypeObject SolutionType = {
+ PyObject_HEAD_INIT(NULL)
+ 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) {
+ self->_solver = problem->_solver;
+ self->problem_id = problem->_id;
+ self->id = id;
+ }
+
+ return (PyObject *)self;
+}
+
+PyObject *Solution_dealloc(SolutionObject *self) {
+ self->ob_type->tp_free((PyObject *)self);
+
+ Py_RETURN_NONE;
+}
+
+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 && solver->installed && pool->solvables[what].repo == solver->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 && !(solver->installed && pool->solvables[what].repo == solver->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;
+
+ default:
+ snprintf(str, STRING_SIZE - 1, _("do something different"));
+ break;
+ }
+
+ } else if (p == SOLVER_SOLUTION_INFARCH) {
+ s = pool->solvables + rp;
+ if (solver->installed && s->repo == solver->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 (solver->installed && s->repo == solver->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);
+
+ // 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));
+
+ 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));
+
+ 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));
+ }
+
+ if (!illegal)
+ snprintf(str, STRING_SIZE - 1, _("allow replacement of %s with %s"),
+ pool_solvable2str(pool, s), pool_solvable2str(pool, sd));
+ }
+ }
+ }
+
+ return Py_BuildValue("s", &str);
+}
--- /dev/null
+
+#ifndef PAKFIRE_SOLUTION_H
+#define PAKFIRE_SOLUTION_H
+
+#include <Python.h>
+
+#include "solver.h"
+
+// Sat Solution object
+typedef struct {
+ PyObject_HEAD
+ Solver *_solver;
+ Id problem_id;
+ Id id;
+} 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;
+
+#endif