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