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