]>
Commit | Line | Data |
---|---|---|
47a4cb89 | 1 | #!/usr/bin/python |
b792d887 MT |
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 | ############################################################################### | |
47a4cb89 | 21 | |
7c8f2953 MT |
22 | import os |
23 | import random | |
24 | import string | |
25 | ||
0ca71090 | 26 | import actions |
18edfe75 | 27 | import builder |
53bb7960 | 28 | import config |
7c8f2953 | 29 | import distro |
862bea4d | 30 | import filelist |
7c8f2953 | 31 | import logger |
ae20b05f | 32 | import packages |
0ca71090 | 33 | import repository |
c605d735 | 34 | import satsolver |
0ca71090 | 35 | import transaction |
7c8f2953 MT |
36 | import util |
37 | ||
8b6bc023 MT |
38 | import logging |
39 | log = logging.getLogger("pakfire") | |
40 | ||
7c8f2953 | 41 | from constants import * |
7c8f2953 MT |
42 | from i18n import _ |
43 | ||
7c8f2953 | 44 | class Pakfire(object): |
018127aa MT |
45 | RELATIONS = ( |
46 | (">=", satsolver.REL_GE,), | |
47 | ("<=", satsolver.REL_LE,), | |
48 | ("=" , satsolver.REL_EQ,), | |
49 | ("<" , satsolver.REL_LT,), | |
50 | (">" , satsolver.REL_GT,), | |
51 | ) | |
52 | ||
eb34496a | 53 | def __init__(self, mode=None, path="/", configs=[], |
715d7009 | 54 | enable_repos=None, disable_repos=None, |
6a509182 | 55 | distro_config=None, **kwargs): |
6557ff4c MT |
56 | |
57 | # Set the mode. | |
6a509182 | 58 | assert mode in ("normal", "builder", "server",) |
6557ff4c MT |
59 | self.mode = mode |
60 | ||
7c8f2953 MT |
61 | # Check if we are operating as the root user. |
62 | self.check_root_user() | |
63 | ||
64 | # The path where we are operating in. | |
6557ff4c MT |
65 | self.path = path |
66 | ||
67 | # Configure the instance of Pakfire we just started. | |
68 | if mode == "builder": | |
7c8f2953 | 69 | self.path = os.path.join(BUILD_ROOT, util.random_string()) |
7c8f2953 | 70 | |
6557ff4c | 71 | elif mode == "normal": |
7b1e25fd | 72 | # check if we are actually running on an ipfire system. |
0891edd2 MT |
73 | if self.path == "/": |
74 | self.check_is_ipfire() | |
7c8f2953 MT |
75 | |
76 | # Read configuration file(s) | |
6557ff4c | 77 | self.config = config.Config(type=mode) |
7c8f2953 MT |
78 | for filename in configs: |
79 | self.config.read(filename) | |
6a509182 MT |
80 | # Assume, that all other keyword arguments are configuration |
81 | # parameters. | |
82 | self.config.update(kwargs) | |
7c8f2953 MT |
83 | |
84 | # Setup the logger | |
85 | logger.setup_logging(self.config) | |
86 | self.config.dump() | |
87 | ||
88 | # Get more information about the distribution we are running | |
89 | # or building | |
53bb7960 | 90 | self.distro = distro.Distribution(self, distro_config) |
c605d735 | 91 | self.pool = satsolver.Pool(self.distro.arch) |
ae20b05f MT |
92 | self.repos = repository.Repositories(self, |
93 | enable_repos=enable_repos, disable_repos=disable_repos) | |
7c8f2953 | 94 | |
60845a36 MT |
95 | def __del__(self): |
96 | # Reset logging. | |
97 | logger.setup_logging() | |
98 | ||
c605d735 MT |
99 | def create_solver(self): |
100 | return satsolver.Solver(self, self.pool) | |
101 | ||
063606f6 MT |
102 | def create_request(self, builder=False): |
103 | request = satsolver.Request(self.pool) | |
104 | ||
105 | # Add multiinstall information. | |
106 | for solv in PAKFIRE_MULTIINSTALL: | |
107 | request.noobsoletes(solv) | |
108 | ||
109 | return request | |
7c8f2953 | 110 | |
018127aa MT |
111 | def create_relation(self, s): |
112 | assert s | |
113 | ||
862bea4d MT |
114 | if isinstance(s, filelist._File): |
115 | return satsolver.Relation(self.pool, s.name) | |
116 | ||
117 | elif s.startswith("/"): | |
018127aa MT |
118 | return satsolver.Relation(self.pool, s) |
119 | ||
120 | for pattern, type in self.RELATIONS: | |
121 | if not pattern in s: | |
122 | continue | |
123 | ||
124 | name, version = s.split(pattern, 1) | |
125 | ||
126 | return satsolver.Relation(self.pool, name, version, type) | |
127 | ||
128 | return satsolver.Relation(self.pool, s) | |
129 | ||
7c8f2953 MT |
130 | def destroy(self): |
131 | if not self.path == "/": | |
132 | util.rm(self.path) | |
133 | ||
c07a3ca7 MT |
134 | @property |
135 | def environ(self): | |
136 | env = {} | |
137 | ||
138 | # Get distribution information. | |
139 | env.update(self.distro.environ) | |
140 | ||
141 | return env | |
142 | ||
7c8f2953 MT |
143 | @property |
144 | def supported_arches(self): | |
3ad4bb5a | 145 | return self.config.supported_arches |
7c8f2953 | 146 | |
6a509182 MT |
147 | @property |
148 | def offline(self): | |
149 | """ | |
150 | A shortcut that indicates if the system is running in offline mode. | |
151 | """ | |
152 | return self.config.get("offline", False) | |
153 | ||
7c8f2953 MT |
154 | def check_root_user(self): |
155 | if not os.getuid() == 0 or not os.getgid() == 0: | |
156 | raise Exception, "You must run pakfire as the root user." | |
157 | ||
158 | def check_build_mode(self): | |
159 | """ | |
160 | Check if we are running in build mode. | |
161 | Otherwise, raise an exception. | |
162 | """ | |
6557ff4c | 163 | if not self.mode == "builder": |
7c8f2953 MT |
164 | raise BuildError, "Cannot build when not in build mode." |
165 | ||
166 | def check_host_arch(self, arch): | |
167 | """ | |
168 | Check if we can build for arch. | |
169 | """ | |
7c8f2953 MT |
170 | # If no arch was given on the command line we build for our |
171 | # own arch which should always work. | |
172 | if not arch: | |
173 | return True | |
174 | ||
3ad4bb5a | 175 | if not self.config.host_supports_arch(arch): |
7c8f2953 MT |
176 | raise BuildError, "Cannot build for the target architecture: %s" % arch |
177 | ||
178 | raise BuildError, arch | |
18edfe75 | 179 | |
7b1e25fd | 180 | def check_is_ipfire(self): |
c07a3ca7 MT |
181 | return # XXX disabled for now |
182 | ||
7b1e25fd MT |
183 | ret = os.path.exists("/etc/ipfire-release") |
184 | ||
185 | if not ret: | |
186 | raise NotAnIPFireSystemError, "You can run pakfire only on an IPFire system" | |
187 | ||
6557ff4c MT |
188 | @property |
189 | def builder(self): | |
190 | # XXX just backwards compatibility | |
191 | return self.mode == "builder" | |
192 | ||
b25a3d84 MT |
193 | def resolvdep(self, requires): |
194 | # Create a new request. | |
195 | request = self.create_request() | |
196 | for req in requires: | |
197 | req = self.create_relation(req) | |
198 | request.install(req) | |
199 | ||
200 | # Do the solving. | |
201 | solver = self.create_solver() | |
202 | t = solver.solve(request) | |
203 | ||
204 | if t: | |
205 | t.dump() | |
206 | else: | |
8b6bc023 | 207 | log.info(_("Nothing to do")) |
b25a3d84 | 208 | |
c07a3ca7 MT |
209 | def install(self, requires, interactive=True, logger=None, **kwargs): |
210 | if not logger: | |
8b6bc023 | 211 | logger = logging.getLogger("pakfire") |
c07a3ca7 | 212 | |
ae20b05f | 213 | # Create a new request. |
84680c15 | 214 | request = self.create_request() |
c07a3ca7 MT |
215 | |
216 | # Expand all groups. | |
18edfe75 | 217 | for req in requires: |
c07a3ca7 MT |
218 | if req.startswith("@"): |
219 | reqs = self.grouplist(req[1:]) | |
220 | else: | |
221 | reqs = [req,] | |
222 | ||
223 | for req in reqs: | |
224 | if not isinstance(req, packages.BinaryPackage): | |
225 | req = self.create_relation(req) | |
226 | ||
227 | request.install(req) | |
18edfe75 | 228 | |
ae20b05f | 229 | # Do the solving. |
84680c15 | 230 | solver = self.create_solver() |
c07a3ca7 | 231 | t = solver.solve(request, **kwargs) |
18edfe75 | 232 | |
ae20b05f | 233 | if not t: |
c07a3ca7 MT |
234 | if not interactive: |
235 | raise DependencyError | |
236 | ||
8b6bc023 | 237 | log.info(_("Nothing to do")) |
18edfe75 MT |
238 | return |
239 | ||
c07a3ca7 MT |
240 | if interactive: |
241 | # Ask if the user acknowledges the transaction. | |
242 | if not t.cli_yesno(): | |
243 | return | |
244 | ||
245 | else: | |
246 | t.dump(logger=logger) | |
c0fd807c MT |
247 | |
248 | # Run the transaction. | |
ae20b05f | 249 | t.run() |
18edfe75 | 250 | |
325e6065 | 251 | def localinstall(self, files, yes=None, allow_uninstall=False): |
de7fba8f | 252 | repo_name = repo_desc = "localinstall" |
e0b99370 MT |
253 | |
254 | # Create a new repository that holds all packages we passed on | |
255 | # the commandline. | |
022c792a MT |
256 | repo = repository.RepositoryDir(self, repo_name, repo_desc, |
257 | os.path.join(LOCAL_TMP_PATH, "repo_%s" % util.random_string())) | |
e0b99370 | 258 | |
022c792a MT |
259 | # Register the repository. |
260 | self.repos.add_repo(repo) | |
e0b99370 | 261 | |
022c792a MT |
262 | try: |
263 | # Add all packages to the repository index. | |
264 | for file in files: | |
265 | repo.collect_packages(file) | |
e0b99370 | 266 | |
022c792a MT |
267 | # Break if no packages were added at all. |
268 | if not len(repo): | |
8b6bc023 | 269 | log.critical(_("There are no packages to install.")) |
022c792a | 270 | return |
e0b99370 | 271 | |
022c792a MT |
272 | # Create a new request that installs all solvables from the |
273 | # repository. | |
274 | request = self.create_request() | |
275 | for solv in [p.solvable for p in repo]: | |
276 | request.install(solv) | |
e0b99370 | 277 | |
022c792a | 278 | solver = self.create_solver() |
325e6065 | 279 | t = solver.solve(request, uninstall=allow_uninstall) |
e0b99370 | 280 | |
022c792a MT |
281 | # If solving was not possible, we exit here. |
282 | if not t: | |
8b6bc023 | 283 | log.info(_("Nothing to do")) |
022c792a | 284 | return |
c0fd807c | 285 | |
08d60af8 MT |
286 | if yes is None: |
287 | # Ask the user if this is okay. | |
288 | if not t.cli_yesno(): | |
289 | return | |
290 | elif yes: | |
291 | t.dump() | |
292 | else: | |
022c792a MT |
293 | return |
294 | ||
295 | # If okay, run the transcation. | |
296 | t.run() | |
297 | ||
298 | finally: | |
299 | # Remove the temporary copy of the repository we have created earlier. | |
300 | repo.remove() | |
75bb74a7 | 301 | self.repos.rem_repo(repo) |
e0b99370 | 302 | |
0ca71090 MT |
303 | def reinstall(self, pkgs, strict=False): |
304 | """ | |
305 | Reinstall one or more packages. | |
306 | ||
307 | If strict is True, only a package with excatly the same UUID | |
308 | will replace the currently installed one. | |
309 | """ | |
310 | # XXX it is possible to install packages without fulfulling | |
311 | # all dependencies. | |
312 | ||
313 | reinstall_pkgs = [] | |
314 | for pattern in pkgs: | |
315 | _pkgs = [] | |
316 | for pkg in self.repos.whatprovides(pattern): | |
317 | # Do not reinstall non-installed packages. | |
318 | if not pkg.is_installed(): | |
319 | continue | |
320 | ||
321 | _pkgs.append(pkg) | |
322 | ||
323 | if not _pkgs: | |
8b6bc023 | 324 | log.warning(_("Could not find any installed package providing \"%s\".") \ |
0ca71090 MT |
325 | % pattern) |
326 | elif len(_pkgs) == 1: | |
327 | reinstall_pkgs.append(_pkgs[0]) | |
328 | #t.add("reinstall", _pkgs[0]) | |
329 | else: | |
8b6bc023 | 330 | log.warning(_("Multiple reinstall candidates for \"%s\": %s") \ |
0ca71090 MT |
331 | % (pattern, ", ".join(p.friendly_name for p in sorted(_pkgs)))) |
332 | ||
333 | if not reinstall_pkgs: | |
8b6bc023 | 334 | log.info(_("Nothing to do")) |
0ca71090 MT |
335 | return |
336 | ||
337 | # Packages we want to replace. | |
338 | # Contains a tuple with the old and the new package. | |
339 | pkgs = [] | |
340 | ||
341 | # Find the package that is installed in a remote repository to | |
342 | # download it again and re-install it. We need that. | |
343 | for pkg in reinstall_pkgs: | |
344 | # Collect all candidates in here. | |
345 | _pkgs = [] | |
346 | ||
347 | provides = "%s=%s" % (pkg.name, pkg.friendly_version) | |
348 | for _pkg in self.repos.whatprovides(provides): | |
349 | if _pkg.is_installed(): | |
350 | continue | |
351 | ||
352 | if strict: | |
353 | if pkg.uuid == _pkg.uuid: | |
354 | _pkgs.append(_pkg) | |
355 | else: | |
356 | _pkgs.append(_pkg) | |
357 | ||
358 | if not _pkgs: | |
8b6bc023 | 359 | log.warning(_("Could not find package %s in a remote repository.") % \ |
0ca71090 MT |
360 | pkg.friendly_name) |
361 | else: | |
362 | # Sort packages to reflect repository priorities, etc... | |
363 | # and take the best (first) one. | |
364 | _pkgs.sort() | |
365 | ||
366 | # Re-install best package and cleanup the old one. | |
367 | pkgs.append((pkg, _pkgs[0])) | |
368 | ||
369 | # Eventually, create a request. | |
370 | request = None | |
371 | ||
372 | _pkgs = [] | |
373 | for old, new in pkgs: | |
374 | if old.uuid == new.uuid: | |
375 | _pkgs.append((old, new)) | |
376 | else: | |
377 | if request is None: | |
378 | # Create a new request. | |
379 | request = self.create_request() | |
380 | ||
381 | # Install the new package, the old will | |
382 | # be cleaned up automatically. | |
383 | request.install(new.solvable) | |
384 | ||
385 | if request: | |
386 | solver = self.create_solver() | |
387 | t = solver.solve(request) | |
388 | else: | |
389 | # Create new transaction. | |
390 | t = transaction.Transaction(self) | |
391 | ||
392 | for old, new in _pkgs: | |
393 | # Install the new package and remove the old one. | |
394 | t.add(actions.ActionReinstall.type, new) | |
395 | t.add(actions.ActionCleanup.type, old) | |
396 | ||
397 | t.sort() | |
398 | ||
399 | if not t: | |
8b6bc023 | 400 | log.info(_("Nothing to do")) |
0ca71090 MT |
401 | return |
402 | ||
403 | if not t.cli_yesno(): | |
404 | return | |
405 | ||
406 | t.run() | |
407 | ||
05fb1da0 | 408 | def update(self, pkgs, check=False, excludes=None, allow_vendorchange=False, allow_archchange=False): |
e38914be MT |
409 | """ |
410 | check indicates, if the method should return after calculation | |
411 | of the transaction. | |
412 | """ | |
84680c15 | 413 | request = self.create_request() |
0c1a80b8 | 414 | |
6c395339 MT |
415 | # If there are given any packets on the command line, we will |
416 | # only update them. Otherwise, we update the whole system. | |
417 | if pkgs: | |
418 | update = False | |
419 | for pkg in pkgs: | |
b34c426d | 420 | pkg = self.create_relation(pkg) |
6c395339 MT |
421 | request.update(pkg) |
422 | else: | |
423 | update = True | |
0c1a80b8 | 424 | |
8834f7c9 MT |
425 | # Exclude packages that should not be updated. |
426 | if excludes: | |
427 | for exclude in excludes: | |
8b6bc023 | 428 | log.info(_("Excluding %s.") % exclude) |
8834f7c9 MT |
429 | |
430 | exclude = self.create_relation(exclude) | |
431 | request.lock(exclude) | |
432 | ||
84680c15 | 433 | solver = self.create_solver() |
05fb1da0 MT |
434 | t = solver.solve(request, update=update, |
435 | allow_vendorchange=allow_vendorchange, | |
436 | allow_archchange=allow_archchange) | |
0c1a80b8 MT |
437 | |
438 | if not t: | |
8b6bc023 | 439 | log.info(_("Nothing to do")) |
e38914be MT |
440 | |
441 | # If we are running in check mode, we return a non-zero value to | |
442 | # indicate, that there are no updates. | |
443 | if check: | |
444 | return 1 | |
445 | else: | |
446 | return | |
447 | ||
448 | # Just exit here, because we won't do the transaction in this mode. | |
449 | if check: | |
450 | t.dump() | |
0c1a80b8 MT |
451 | return |
452 | ||
c0fd807c MT |
453 | # Ask the user if the transaction is okay. |
454 | if not t.cli_yesno(): | |
455 | return | |
0c1a80b8 | 456 | |
c0fd807c | 457 | # Run the transaction. |
0c1a80b8 | 458 | t.run() |
18edfe75 | 459 | |
67d1ddbd MT |
460 | def downgrade(self, pkgs, allow_vendorchange=False, allow_archchange=False): |
461 | assert pkgs | |
462 | ||
463 | # Create a new request. | |
464 | request = self.create_request() | |
465 | ||
466 | # Fill request. | |
467 | for pattern in pkgs: | |
468 | best = None | |
469 | for pkg in self.repos.whatprovides(pattern): | |
470 | # Only consider installed packages. | |
471 | if not pkg.is_installed(): | |
472 | continue | |
473 | ||
474 | if best and pkg > best: | |
475 | best = pkg | |
476 | elif best is None: | |
477 | best = pkg | |
478 | ||
479 | if best is None: | |
8b6bc023 | 480 | log.warning(_("\"%s\" package does not seem to be installed.") % pattern) |
67d1ddbd MT |
481 | else: |
482 | rel = self.create_relation("%s<%s" % (best.name, best.friendly_version)) | |
483 | request.install(rel) | |
484 | ||
485 | # Solve the request. | |
486 | solver = self.create_solver() | |
487 | t = solver.solve(request, allow_downgrade=True, | |
488 | allow_vendorchange=allow_vendorchange, | |
489 | allow_archchange=allow_archchange) | |
490 | ||
491 | if not t: | |
8b6bc023 | 492 | log.info(_("Nothing to do")) |
67d1ddbd MT |
493 | return |
494 | ||
495 | if not t.cli_yesno(): | |
496 | return | |
497 | ||
498 | t.run() | |
499 | ||
a39fd08b MT |
500 | def remove(self, pkgs): |
501 | # Create a new request. | |
84680c15 | 502 | request = self.create_request() |
a39fd08b | 503 | for pkg in pkgs: |
b34c426d | 504 | pkg = self.create_relation(pkg) |
a39fd08b MT |
505 | request.remove(pkg) |
506 | ||
507 | # Solve the request. | |
84680c15 | 508 | solver = self.create_solver() |
6eb8f338 | 509 | t = solver.solve(request, uninstall=True) |
a39fd08b MT |
510 | |
511 | if not t: | |
8b6bc023 | 512 | log.info(_("Nothing to do")) |
a39fd08b MT |
513 | return |
514 | ||
c0fd807c MT |
515 | # Ask the user if okay. |
516 | if not t.cli_yesno(): | |
517 | return | |
518 | ||
519 | # Process the transaction. | |
a39fd08b MT |
520 | t.run() |
521 | ||
c1e7f927 | 522 | def info(self, patterns): |
18edfe75 MT |
523 | pkgs = [] |
524 | ||
1f27e8fe MT |
525 | # For all patterns we run a single search which returns us a bunch |
526 | # of solvables which are transformed into Package objects. | |
18edfe75 | 527 | for pattern in patterns: |
5dda5744 | 528 | if os.path.exists(pattern) and not os.path.isdir(pattern): |
c07a3ca7 MT |
529 | pkg = packages.open(self, self.repos.dummy, pattern) |
530 | if pkg: | |
531 | pkgs.append(pkg) | |
1f27e8fe | 532 | |
c07a3ca7 MT |
533 | else: |
534 | solvs = self.pool.search(pattern, satsolver.SEARCH_GLOB, "solvable:name") | |
e1972777 | 535 | |
c07a3ca7 MT |
536 | for solv in solvs: |
537 | pkg = packages.SolvPackage(self, solv) | |
538 | if pkg in pkgs: | |
539 | continue | |
540 | ||
541 | pkgs.append(pkg) | |
18edfe75 | 542 | |
e1972777 | 543 | return sorted(pkgs) |
18edfe75 MT |
544 | |
545 | def search(self, pattern): | |
546 | # Do the search. | |
c2e67297 | 547 | pkgs = {} |
884cd2fb | 548 | for solv in self.pool.search(pattern, satsolver.SEARCH_STRING|satsolver.SEARCH_FILES): |
c2e67297 | 549 | pkg = packages.SolvPackage(self, solv) |
18edfe75 | 550 | |
c2e67297 MT |
551 | # Check, if a package with the name is already in the resultset |
552 | # and always replace older ones by more recent ones. | |
553 | if pkgs.has_key(pkg.name): | |
554 | if pkgs[pkg.name] < pkg: | |
555 | pkgs[pkg.name] = pkg | |
556 | else: | |
557 | pkgs[pkg.name] = pkg | |
558 | ||
559 | # Return a list of the packages, alphabetically sorted. | |
560 | return sorted(pkgs.values()) | |
18edfe75 | 561 | |
c07a3ca7 MT |
562 | def groupinstall(self, group, **kwargs): |
563 | self.install("@%s" % group, **kwargs) | |
18edfe75 MT |
564 | |
565 | def grouplist(self, group): | |
fec9a917 MT |
566 | pkgs = [] |
567 | ||
568 | for solv in self.pool.search(group, satsolver.SEARCH_SUBSTRING, "solvable:group"): | |
569 | pkg = packages.SolvPackage(self, solv) | |
18edfe75 | 570 | |
fec9a917 MT |
571 | if group in pkg.groups and not pkg.name in pkgs: |
572 | pkgs.append(pkg.name) | |
18edfe75 | 573 | |
fec9a917 | 574 | return sorted(pkgs) |
18edfe75 MT |
575 | |
576 | @staticmethod | |
1710ccec | 577 | def build(pkg, resultdirs=None, shell=False, install_test=True, after_shell=False, **kwargs): |
18edfe75 MT |
578 | if not resultdirs: |
579 | resultdirs = [] | |
580 | ||
ff9299d0 | 581 | b = builder.BuildEnviron(pkg, **kwargs) |
18edfe75 MT |
582 | p = b.pakfire |
583 | ||
584 | # Always include local repository. | |
585 | resultdirs.append(p.repos.local_build.path) | |
586 | ||
587 | try: | |
8930b228 MT |
588 | # Start to prepare the build environment by mounting |
589 | # the filesystems and extracting files. | |
590 | b.start() | |
591 | ||
1710ccec MT |
592 | try: |
593 | # Build the package. | |
594 | b.build(install_test=install_test) | |
595 | except BuildError: | |
596 | # Raise the error, if the user does not want to | |
597 | # have a shell. | |
598 | if not shell: | |
599 | raise | |
18edfe75 | 600 | |
1710ccec MT |
601 | # Run a shell to debug the issue. |
602 | b.shell() | |
603 | ||
604 | # If the user requests a shell after a successful build, | |
605 | # we run it here. | |
606 | if after_shell: | |
607 | b.shell() | |
608 | ||
609 | # Copy-out all resultfiles if the build was successful. | |
18edfe75 MT |
610 | for resultdir in resultdirs: |
611 | if not resultdir: | |
612 | continue | |
613 | ||
614 | b.copy_result(resultdir) | |
18edfe75 | 615 | finally: |
8930b228 | 616 | b.stop() |
18edfe75 | 617 | |
c07a3ca7 | 618 | def _build(self, pkg, resultdir, nodeps=False, **kwargs): |
ff9299d0 | 619 | b = builder.Builder(self, pkg, resultdir, **kwargs) |
c07a3ca7 MT |
620 | |
621 | try: | |
622 | b.build() | |
623 | except Error: | |
624 | raise BuildError, _("Build command has failed.") | |
0d96815e MT |
625 | |
626 | # If the build was successful, cleanup all temporary files. | |
627 | b.cleanup() | |
c07a3ca7 | 628 | |
18edfe75 MT |
629 | @staticmethod |
630 | def shell(pkg, **kwargs): | |
ff9299d0 | 631 | b = builder.BuildEnviron(pkg, **kwargs) |
18edfe75 MT |
632 | |
633 | try: | |
8930b228 | 634 | b.start() |
18edfe75 MT |
635 | b.shell() |
636 | finally: | |
8930b228 | 637 | b.stop() |
18edfe75 | 638 | |
c07a3ca7 | 639 | def dist(self, pkgs, resultdirs=None): |
269c59f3 | 640 | assert resultdirs |
18edfe75 | 641 | |
c07a3ca7 MT |
642 | for pkg in pkgs: |
643 | pkg = packages.Makefile(self, pkg) | |
50f96897 | 644 | |
c07a3ca7 | 645 | pkg.dist(resultdirs) |
18edfe75 MT |
646 | |
647 | def provides(self, patterns): | |
648 | pkgs = [] | |
649 | for pattern in patterns: | |
e1972777 MT |
650 | for pkg in self.repos.whatprovides(pattern): |
651 | if pkg in pkgs: | |
652 | continue | |
18edfe75 | 653 | |
e1972777 | 654 | pkgs.append(pkg) |
18edfe75 | 655 | |
e1972777 | 656 | return sorted(pkgs) |
18edfe75 | 657 | |
8276111d MT |
658 | def repo_create(self, path, input_paths, type="binary"): |
659 | assert type in ("binary", "source",) | |
660 | ||
c605d735 | 661 | repo = repository.RepositoryDir( |
18edfe75 MT |
662 | self, |
663 | name="new", | |
664 | description="New repository.", | |
665 | path=path, | |
8276111d | 666 | type=type, |
18edfe75 MT |
667 | ) |
668 | ||
669 | for input_path in input_paths: | |
c605d735 | 670 | repo.collect_packages(input_path) |
18edfe75 MT |
671 | |
672 | repo.save() | |
673 | ||
8276111d MT |
674 | return repo |
675 | ||
18edfe75 | 676 | def repo_list(self): |
c605d735 | 677 | return [r for r in self.repos] |
31267a64 MT |
678 | |
679 | def clean_all(self): | |
8b6bc023 | 680 | log.debug("Cleaning up everything...") |
31267a64 MT |
681 | |
682 | # Clean up repository caches. | |
683 | self.repos.clean() | |
35d89fd7 MT |
684 | |
685 | def check(self, downgrade=True, uninstall=True): | |
686 | """ | |
687 | Try to fix any errors in the system. | |
688 | """ | |
689 | # Detect any errors in the dependency tree. | |
690 | # For that we create an empty request and solver and try to solve | |
691 | # something. | |
692 | request = self.create_request() | |
693 | solver = self.create_solver() | |
694 | ||
695 | # XXX the solver does crash if we call it with fix_system=1, | |
696 | # allow_downgrade=1 and uninstall=1. Need to fix this. | |
697 | allow_downgrade = False | |
698 | uninstall = False | |
699 | ||
700 | t = solver.solve(request, fix_system=True, allow_downgrade=downgrade, | |
701 | uninstall=uninstall) | |
702 | ||
703 | if not t: | |
8b6bc023 | 704 | log.info(_("Everything is fine.")) |
35d89fd7 MT |
705 | return |
706 | ||
707 | # Ask the user if okay. | |
708 | if not t.cli_yesno(): | |
709 | return | |
710 | ||
711 | # Process the transaction. | |
712 | t.run() |