]> git.ipfire.org Git - pakfire.git/blob - python/pakfire/satsolver.py
Rewrite the buildsystem of this package.
[pakfire.git] / python / pakfire / satsolver.py
1 #!/usr/bin/python
2 ###############################################################################
3 # #
4 # Pakfire - The IPFire package management system #
5 # Copyright (C) 2011 Pakfire development team #
6 # #
7 # This program is free software: you can redistribute it and/or modify #
8 # it under the terms of the GNU General Public License as published by #
9 # the Free Software Foundation, either version 3 of the License, or #
10 # (at your option) any later version. #
11 # #
12 # This program is distributed in the hope that it will be useful, #
13 # but WITHOUT ANY WARRANTY; without even the implied warranty of #
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
15 # GNU General Public License for more details. #
16 # #
17 # You should have received a copy of the GNU General Public License #
18 # along with this program. If not, see <http://www.gnu.org/licenses/>. #
19 # #
20 ###############################################################################
21
22 import logging
23
24 import _pakfire
25 from _pakfire import *
26
27 import transaction
28 import util
29
30 from i18n import _
31
32 class Request(_pakfire.Request):
33 def install(self, what):
34 if isinstance(what, Solvable):
35 self.install_solvable(what)
36 return
37
38 elif isinstance(what, Relation):
39 self.install_relation(what)
40 return
41
42 elif type(what) == type("string"):
43 self.install_name(what)
44 return
45
46 raise Exception, "Unknown type"
47
48 def remove(self, what):
49 if isinstance(what, Solvable):
50 self.remove_solvable(what)
51 return
52
53 elif isinstance(what, Relation):
54 self.remove_relation(what)
55 return
56
57 elif type(what) == type("string"):
58 self.remove_name(what)
59 return
60
61 raise Exception, "Unknown type"
62
63 def update(self, what):
64 if isinstance(what, Solvable):
65 self.update_solvable(what)
66 return
67
68 elif isinstance(what, Relation):
69 self.update_relation(what)
70 return
71
72 elif type(what) == type("string"):
73 self.update_name(what)
74 return
75
76 raise Exception, "Unknown type"
77
78 def lock(self, what):
79 if isinstance(what, Solvable):
80 self.lock_solvable(what)
81 return
82
83 elif isinstance(what, Relation):
84 self.lock_relation(what)
85 return
86
87 elif type(what) == type("string"):
88 self.lock_name(what)
89 return
90
91 raise Exception, "Unknown type"
92
93 def noobsoletes(self, what):
94 if isinstance(what, Solvable):
95 self.noobsoletes_solvable(what)
96 return
97
98 elif isinstance(what, Relation):
99 self.noobsoletes_relation(what)
100 return
101
102 elif type(what) == type("string"):
103 self.noobsoletes_name(what)
104 return
105
106 raise Exception, "Unknown type"
107
108
109 class Solver(object):
110 def __init__(self, pakfire, pool):
111 self.pakfire = pakfire
112 self.pool = pool
113
114 def solve(self, request, update=False, uninstall=False, allow_downgrade=False,
115 fix_system=False, interactive=False, logger=None):
116 # If no logger was provided, we use the root logger.
117 if logger is None:
118 logger = logging.getLogger()
119
120 # Create a new solver.
121 solver = _pakfire.Solver(self.pool)
122
123 solver.set_fix_system(fix_system)
124 solver.set_allow_uninstall(uninstall)
125 solver.set_allow_downgrade(allow_downgrade)
126
127 # Configure the solver for an update.
128 if update:
129 solver.set_updatesystem(True)
130 solver.set_do_split_provides(True)
131
132 # Actually solve the request.
133 res = solver.solve(request)
134
135 logger.debug("Solver status: %s" % res)
136
137 # If the solver succeeded, we return the transaction and return.
138 if res:
139 # Return a resulting Transaction.
140 t = Transaction(solver)
141
142 return transaction.Transaction.from_solver(self.pakfire, self, t)
143
144 # Do the problem handling...
145 problems = solver.get_problems(request)
146
147 logger.info("")
148 logger.info(_("The solver returned one problem:", "The solver returned %(num)s problems:",
149 len(problems)) % { "num" : len(problems) })
150
151 i = 0
152 for problem in problems:
153 i += 1
154
155 # Print information about the problem to the user.
156 logger.info(" #%d: %s" % (i, problem))
157
158 logger.info("")
159
160 if not interactive:
161 return False
162
163 # Ask the user if he or she want to modify the request. If not, just exit.
164 if not util.ask_user(_("Do you want to manually alter the request?")):
165 return False
166
167 print _("You can now try to satisfy the solver by modifying your request.")
168
169 altered = False
170 while True:
171 if len(problems) > 1:
172 print _("Which problem to you want to resolve?")
173 if altered:
174 print _("Press enter to try to re-solve the request.")
175 print "[1-%s]:" % len(problems),
176
177 answer = raw_input()
178
179 # If the user did not enter anything, we abort immediately.
180 if not answer:
181 break
182
183 # If the user did type anything else than an integer, we ask
184 # again.
185 try:
186 answer = int(answer)
187 except ValueError:
188 continue
189
190 # If the user entered an integer outside of range, we ask
191 # again.
192 try:
193 problem = problems[answer - 1]
194 except KeyError:
195 continue
196
197 else:
198 problem = problem[0]
199
200 # Get all solutions.
201 solutions = problem.get_solutions()
202
203 if len(solutions) == 1:
204 solution = solutions[0]
205 print _(" Solution: %s") % solution
206 print
207
208 if util.ask_user("Do you accept the solution above?"):
209 altered = True
210 print "XXX do something"
211
212 continue
213 else:
214 print _(" Solutions:")
215 i = 0
216 for solution in solutions:
217 i += 1
218 print " #%d: %s" % (i, solution)
219
220 print
221
222 if not altered:
223 return False
224
225 # If the request was altered by the user, we try to solve it again
226 # and see what happens.
227 return self.solve(request, update=update, uninstall=uninstall,
228 allow_downgrade=allow_downgrade, interactive=interactive)