From: Michael Tremer Date: Sat, 27 Oct 2012 17:47:21 +0000 (+0200) Subject: General cleanup work. X-Git-Tag: 0.9.24~51 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=36b328f28353431c16e07d6087220af13204204f;p=pakfire.git General cleanup work. --- diff --git a/python/pakfire/api.py b/python/pakfire/api.py index c44c9abec..db02fb2ba 100644 --- a/python/pakfire/api.py +++ b/python/pakfire/api.py @@ -35,7 +35,7 @@ def install(requires, ignore_recommended=False, **pakfire_args): def resolvdep(pkgs, **pakfire_args): pakfire = Pakfire(**pakfire_args) - return pakfire.resolvdep(pkgs) + return pakfire.pool.resolvdep(pkgs) def reinstall(pkgs, **pakfire_args): pakfire = Pakfire(**pakfire_args) diff --git a/python/pakfire/base.py b/python/pakfire/base.py index c6419f143..52223d17d 100644 --- a/python/pakfire/base.py +++ b/python/pakfire/base.py @@ -25,6 +25,7 @@ import string import actions import builder +import config import distro import filelist import keyring @@ -45,30 +46,25 @@ from i18n import _ class Pakfire(object): mode = None - def __init__(self, path="/", config=None, configs=None, arch=None, - enable_repos=None, disable_repos=None, **kwargs): + def __init__(self, path="/", config=None, configs=None, arch=None, **kwargs): + # Indicates if this instance has already been initialized. + self.initialized = False + # Check if we are operating as the root user. self.check_root_user() # The path where we are operating in. self.path = path - # Configure the instance of Pakfire we just started. - if self.mode == "builder": - self.path = os.path.join(BUILD_ROOT, util.random_string()) - - elif not self.mode: - # check if we are actually running on an ipfire system. - if self.path == "/": - self.check_is_ipfire() + # check if we are actually running on an ipfire system. + if not self.mode and self.path == "/": + self.check_is_ipfire() # Get the configuration. if config: - assert configs is None, "You cannot pass configs and config." self.config = config else: - # Read configuration file(s). - self.config = Config(files=configs) + self.config = self._load_config(configs) # Update configuration with additional arguments. for section, settings in kwargs.items(): @@ -82,21 +78,39 @@ class Pakfire(object): # Get more information about the distribution we are running # or building - self.distro = distro.Distribution(self) + self.distro = distro.Distribution(self.config.get_distro_conf()) if arch: self.distro.arch = arch - self.pool = satsolver.Pool(self.distro.arch) - self.repos = repository.Repositories(self, - enable_repos=enable_repos, disable_repos=disable_repos) + self.pool = satsolver.Pool(self.distro.arch) + self.repos = repository.Repositories(self) + + def initialize(self): + """ + Initialize pakfire instance. + """ + if self.initialized: + return + + # Initialize repositories. + self.repos.initialize() + + self.initialized = True + + def _load_config(self, files=None): + """ + This method loads all needed configuration files. + """ + return config.Config(files=files) def __del__(self): # Reset logging. logger.setup_logging() def destroy(self): - if not self.path == "/": - util.rm(self.path) + self.repos.shutdown() + + self.initialized = False @property def environ(self): @@ -148,6 +162,9 @@ class Pakfire(object): return self.mode == "builder" def install(self, requires, interactive=True, logger=None, signatures_mode=None, **kwargs): + # Initialize this pakfire instance. + self.initialize() + if not logger: logger = logging.getLogger("pakfire") @@ -220,6 +237,9 @@ class Pakfire(object): If strict is True, only a package with excatly the same UUID will replace the currently installed one. """ + # Initialize this pakfire instance. + self.initialize() + if logger is None: logger = logging.getLogger("pakfire") @@ -328,6 +348,9 @@ class Pakfire(object): check indicates, if the method should return after calculation of the transaction. """ + # Initialize this pakfire instance. + self.initialize() + if logger is None: logger = logging.getLogger("pakfire") @@ -376,6 +399,9 @@ class Pakfire(object): def downgrade(self, pkgs, allow_vendorchange=False, allow_archchange=False): assert pkgs + # Initialize this pakfire instance. + self.initialize() + # Create a new request. request = self.pool.create_request() @@ -420,6 +446,9 @@ class Pakfire(object): t.run() def remove(self, pkgs): + # Initialize this pakfire instance. + self.initialize() + # Create a new request. request = self.pool.create_request(remove=pkgs) @@ -443,6 +472,9 @@ class Pakfire(object): t.run() def info(self, patterns): + # Initialize this pakfire instance. + self.initialize() + pkgs = [] # For all patterns we run a single search which returns us a bunch @@ -466,6 +498,9 @@ class Pakfire(object): return sorted(pkgs) def search(self, pattern): + # Initialize this pakfire instance. + self.initialize() + # Do the search. pkgs = {} for solv in self.pool.search(pattern, satsolver.SEARCH_STRING|satsolver.SEARCH_FILES): @@ -486,9 +521,15 @@ class Pakfire(object): self.install("@%s" % group, **kwargs) def grouplist(self, group): + # Initialize this pakfire instance. + self.initialize() + return self.pool.grouplist(group) def provides(self, patterns): + # Initialize this pakfire instance. + self.initialize() + pkgs = [] for pattern in patterns: for pkg in self.repos.whatprovides(pattern): @@ -500,9 +541,15 @@ class Pakfire(object): return sorted(pkgs) def repo_list(self): + # Initialize this pakfire instance. + self.initialize() + return [r for r in self.repos] def clean_all(self): + # Initialize this pakfire instance. + self.initialize() + log.debug("Cleaning up everything...") # Clean up repository caches. @@ -512,6 +559,9 @@ class Pakfire(object): """ Try to fix any errors in the system. """ + # Initialize this pakfire instance. + self.initialize() + # Detect any errors in the dependency tree. # For that we create an empty request and solver and try to solve # something. @@ -543,21 +593,46 @@ class Pakfire(object): class PakfireBuilder(Pakfire): mode = "builder" + def __init__(self, distro_name=None, *args, **kwargs): + self.distro_name = distro_name + + kwargs.update({ + "path" : os.path.join(BUILD_ROOT, util.random_string()), + }) + + Pakfire.__init__(self, *args, **kwargs) + + # Let's see what is our host distribution. + self.host_distro = distro.Distribution() + + def _load_config(self, files=None): + c = config.ConfigBuilder(files=files) + + if self.distro_name is None: + self.distro_name = c.get("builder", "distro", None) + + if self.distro_name: + c.load_distro_config(self.distro_name) + + if not c.has_distro_conf(): + log.error(_("You have not set the distribution for which you want to build.")) + log.error(_("Please do so in builder.conf or on the CLI.")) + raise ConfigError, _("Distribution configuration is missing.") + + return c + def dist(self, pkg, resultdir): pkg = packages.Makefile(self, pkg) return pkg.dist(resultdir=resultdir) - @staticmethod - def build(pkg, resultdirs=None, shell=False, install_test=True, after_shell=False, **kwargs): - if not resultdirs: - resultdirs = [] + def build(self, pkg, resultdirs=None, shell=False, install_test=True, after_shell=False, **kwargs): - b = builder.BuildEnviron(pkg, **kwargs) - p = b.pakfire + # As the BuildEnviron is only able to handle source packages, we must package makefiles. + if pkg.endswith(".%s" % MAKEFILE_EXTENSION): + pkg = self.dist(pkg, resultdir=LOCAL_TMP_PATH) - # Always include local repository. - resultdirs.append(p.repos.local_build.path) + b = builder.BuildEnviron(self, pkg, **kwargs) try: # Start to prepare the build environment by mounting @@ -577,17 +652,24 @@ class PakfireBuilder(Pakfire): # Run a shell to debug the issue. b.shell() - # If the user requests a shell after a successful build, - # we run it here. - if after_shell: - b.shell() - # Copy-out all resultfiles if the build was successful. + if not resultdirs: + resultdirs = [] + + # Always include local repository. + resultdirs.append(self.repos.local_build.path) + for resultdir in resultdirs: if not resultdir: continue b.copy_result(resultdir) + + # If the user requests a shell after a successful build, + # we run it here. + if after_shell: + b.shell() + finally: b.stop() @@ -607,9 +689,8 @@ class PakfireBuilder(Pakfire): # If the build was successful, cleanup all temporary files. b.cleanup() - @staticmethod - def shell(pkg, **kwargs): - b = builder.BuildEnviron(pkg, **kwargs) + def shell(self, pkg, **kwargs): + b = builder.BuildEnviron(self, pkg, **kwargs) try: b.start() diff --git a/python/pakfire/builder.py b/python/pakfire/builder.py index c0c0d43bc..d655fec0b 100644 --- a/python/pakfire/builder.py +++ b/python/pakfire/builder.py @@ -69,55 +69,25 @@ class BuildEnviron(object): # The version of the kernel this machine is running. kernel_version = os.uname()[2] - def __init__(self, filename=None, distro_name=None, config=None, configs=None, arch=None, - build_id=None, logfile=None, builder_mode="release", **pakfire_args): - # Set mode. - assert builder_mode in ("development", "release",) - self.mode = builder_mode - - # Disable the build repository in release mode. - if self.mode == "release": - if pakfire_args.has_key("disable_repos") and pakfire_args["disable_repos"]: - pakfire_args["disable_repos"] += ["build",] - else: - pakfire_args["disable_repos"] = ["build",] - - # Save the build id and generate one if no build id was provided. - if not build_id: - build_id = "%s" % uuid.uuid4() + def __init__(self, pakfire, filename=None, distro_name=None, build_id=None, logfile=None, release_build=True): + self.pakfire = pakfire - self.build_id = build_id + # Check if the given pakfire instance is of the correct type. + assert isinstance(self.pakfire, base.PakfireBuilder) - # Setup the logging. - if logfile: - self.log = log.getChild(self.build_id) - # Propage everything to the root logger that we will see something - # on the terminal. - self.log.propagate = 1 - self.log.setLevel(logging.INFO) - - # Add the given logfile to the logger. - h = logging.FileHandler(logfile) - self.log.addHandler(h) - - # Format the log output for the file. - f = logger.BuildFormatter() - h.setFormatter(f) - else: - # If no logile was given, we use the root logger. - self.log = logging.getLogger("pakfire") + # Check if this host can build the requested architecture. + if not system.host_supports_arch(self.arch): + raise BuildError, _("Cannot build for %s on this host.") % self.arch - # Initialize a cgroup (if supported). - self.cgroup = None - if cgroup.supported(): - self.cgroup = cgroup.CGroup("pakfire/builder/%s" % self.build_id) + # This build is a release build? + self.release_build = release_build - # Attach the pakfire-builder process to the parent group. - self.cgroup.parent.attach() + if self.release_build: + # Disable the local build repository in release mode. + self.pakfire.repos.disable_repo("build") - # Log information about pakfire and some more information, when we - # are running in release mode. - if self.mode == "release": + # Log information about pakfire and some more information, when we + # are running in release mode. logdata = { "host_arch" : system.arch, "hostname" : system.hostname, @@ -128,44 +98,39 @@ class BuildEnviron(object): for line in BUILD_LOG_HEADER.splitlines(): self.log.info(line % logdata) - # Create pakfire instance. - if pakfire_args.has_key("mode"): - del pakfire_args["mode"] - - if config is None: - config = ConfigBuilder(files=configs) + # Save the build id and generate one if no build id was provided. + if not build_id: + build_id = "%s" % uuid.uuid4() - if not configs: - if distro_name is None: - distro_name = config.get("builder", "distro", None) - config.load_distro_config(distro_name) + self.build_id = build_id - if not config.has_distro(): - log.error(_("You have not set the distribution for which you want to build.")) - log.error(_("Please do so in builder.conf or on the CLI.")) - raise ConfigError, _("Distribution configuration is missing.") + # Setup the logging. + self.init_logging(logfile) - self.pakfire = base.PakfireBuilder(config=config, arch=arch, **pakfire_args) + # Initialize a cgroup (if supported). + self.init_cgroup() - self.distro = self.pakfire.distro - self.path = self.pakfire.path + # XXX need to make this configureable + self.settings = { + "enable_loop_devices" : True, + "enable_ccache" : True, + "enable_icecream" : False, + "sign_packages" : False, + "buildroot_tmpfs" : False, + } + #self.settings.update(settings) - # Check if this host can build the requested architecture. - if not system.host_supports_arch(self.arch): - raise BuildError, _("Cannot build for %s on this host.") % self.arch + # Try to get the configured host key. If it is available, + # we will automatically sign all packages with it. + if self.keyring.get_host_key(secret=True): + self.settings["sign_packages"] = True # Where do we put the result? - self.resultdir = os.path.join(self.path, "result") + self.resultdir = os.path.join(self.pakfire.path, "result") # Open package. # If we have a plain makefile, we first build a source package and go with that. if filename: - if filename.endswith(".%s" % MAKEFILE_EXTENSION): - pkg = packages.Makefile(self.pakfire, filename) - filename = pkg.dist(os.path.join(self.resultdir, "src")) - - assert os.path.exists(filename), filename - # Open source package. self.pkg = packages.SourcePackage(self.pakfire, None, filename) assert self.pkg, filename @@ -182,35 +147,27 @@ class BuildEnviron(object): # No package :( self.pkg = None - # XXX need to make this configureable - self.settings = { - "enable_loop_devices" : True, - "enable_ccache" : True, - "enable_icecream" : False, - "sign_packages" : False, - "buildroot_tmpfs" : False, - } - #self.settings.update(settings) - - # Try to get the configured host key. If it is available, - # we will automatically sign all packages with it. - if self.keyring.get_host_key(secret=True): - self.settings["sign_packages"] = True - # Lock the buildroot self._lock = None - self.lock() # Save the build time. - self.build_time = int(time.time()) + self.build_time = time.time() def setup_signal_handlers(self): pass def start(self): + assert not self.pakfire.initialized, "Pakfire has already been initialized" + # Mount the directories. self._mountall() + # Lock the build environment. + self.lock() + + # Initialize pakfire instance. + self.pakfire.initialize() + # Populate /dev. self.populate_dev() @@ -240,8 +197,11 @@ class BuildEnviron(object): else: util.orphans_kill(self.path) - # Close pakfire instance. - del self.pakfire + # Shut down pakfire instance. + self.pakfire.destroy() + + # Unlock build environment. + self.unlock() # Umount the build environment. self._umountall() @@ -249,20 +209,33 @@ class BuildEnviron(object): # Remove all files. self.destroy() + @property + def distro(self): + """ + Proxy method for easy access to the distribution. + """ + return self.pakfire.distro + + @property + def path(self): + """ + Proxy method for easy access to the path. + """ + return self.pakfire.path + @property def arch(self): """ Inherit architecture from distribution configuration. """ - return self.distro.arch + return self.pakfire.distro.arch @property def personality(self): """ Gets the personality from the distribution configuration. """ - if self.distro: - return self.distro.personality + return self.pakfire.distro.personality @property def info(self): @@ -300,6 +273,38 @@ class BuildEnviron(object): self._lock.close() self._lock = None + def init_cgroup(self): + """ + Initialize cgroup (if the system supports it). + """ + if not cgroup.supported(): + self.cgroup = None + return + + self.cgroup = cgroup.CGroup("pakfire/builder/%s" % self.build_id) + + # Attach the pakfire-builder process to the parent group. + self.cgroup.parent.attach() + + def init_logging(self, logfile): + if logfile: + self.log = log.getChild(self.build_id) + # Propage everything to the root logger that we will see something + # on the terminal. + self.log.propagate = 1 + self.log.setLevel(logging.INFO) + + # Add the given logfile to the logger. + h = logging.FileHandler(logfile) + self.log.addHandler(h) + + # Format the log output for the file. + f = logger.BuildFormatter() + h.setFormatter(f) + else: + # If no logile was given, we use the root logger. + self.log = logging.getLogger("pakfire") + def copyin(self, file_out, file_in): if file_in.startswith("/"): file_in = file_in[1:] @@ -366,7 +371,7 @@ class BuildEnviron(object): return ret - def extract(self, requires=None, build_deps=True): + def extract(self, requires=None): """ Gets a dependency set and extracts all packages to the environment. @@ -523,16 +528,20 @@ class BuildEnviron(object): mountpoints = [] for src, dest, fs, options in reversed(self.mountpoints): + dest = self.chrootPath(dest) + if not dest in mountpoints: mountpoints.append(dest) - for dest in mountpoints: - mountpoint = self.chrootPath(dest) + while mountpoints: + for mp in mountpoints: + try: + self.execute_root("umount -n %s" % mp, shell=True) + except ShellEnvironmentError: + pass - try: - self.execute_root("umount -n %s" % mountpoint, shell=True) - except ShellEnvironmentError: - pass + if not os.path.ismount(mp): + mountpoints.remove(mp) @property def mountpoints(self): @@ -727,12 +736,13 @@ class BuildEnviron(object): "--nodeps", "--resultdir=/result", ] - build_command = " ".join(build_command) # Check if only the preparation stage should be run. if prepare: build_command.append("--prepare") + build_command = " ".join(build_command) + error = False try: self.execute(build_command, logger=self.log) diff --git a/python/pakfire/cli.py b/python/pakfire/cli.py index 0b5aa25a9..e974c0eb9 100644 --- a/python/pakfire/cli.py +++ b/python/pakfire/cli.py @@ -26,14 +26,14 @@ import shutil import sys import tempfile -import pakfire.api as pakfire - +import base import client import config import logger import packages import repository import server +import transaction import util from system import system @@ -45,6 +45,8 @@ from i18n import _ logger.setup_logging() class Cli(object): + pakfire = base.Pakfire + def __init__(self): self.parser = argparse.ArgumentParser( description = _("Pakfire command line interface."), @@ -98,7 +100,7 @@ class Cli(object): @property def pakfire_args(self): - ret = { "mode" : "normal" } + ret = {} if hasattr(self.args, "root"): ret["path"] = self.args.root @@ -288,72 +290,76 @@ class Cli(object): return func() def handle_info(self, long=False): - pkgs = pakfire.info(self.args.package, **self.pakfire_args) + p = self.pakfire(**self.pakfire_args) - for pkg in pkgs: + for pkg in p.info(self.args.package): print pkg.dump(long=long) def handle_search(self): - pkgs = pakfire.search(self.args.pattern, **self.pakfire_args) + p = self.pakfire(**self.pakfire_args) - for pkg in pkgs: + for pkg in p.search(self.args.pattern): print pkg.dump(short=True) def handle_update(self, **args): - args.update(self.pakfire_args) - - pakfire.update(self.args.package, excludes=self.args.exclude, + p = self.pakfire(**self.pakfire_args) + p.update( + self.args.package, + excludes=self.args.exclude, allow_vendorchange=self.args.allow_vendorchange, allow_archchange=self.args.allow_archchange, - **args) + **args + ) def handle_check_update(self): self.handle_update(check=True) def handle_downgrade(self, **args): - args.update(self.pakfire_args) - - pakfire.downgrade(self.args.package, + p = self.pakfire(**self.pakfire_args) + p.downgrade( + self.args.package, allow_vendorchange=self.args.allow_vendorchange, allow_archchange=self.args.allow_archchange, - **args) + **args + ) def handle_install(self): - pakfire.install(self.args.package, - ignore_recommended=self.args.without_recommends, - **self.pakfire_args) + p = self.pakfire(**self.pakfire_args) + p.install(self.args.package, ignore_recommended=self.args.without_recommends) def handle_reinstall(self): - pakfire.reinstall(self.args.package, **self.pakfire_args) + p = self.pakfire(**self.pakfire_args) + p.reinstall(self.args.package) def handle_remove(self): - pakfire.remove(self.args.package, **self.pakfire_args) + p = self.pakfire(**self.pakfire_args) + p.remove(self.args.package) - def handle_provides(self): - pkgs = pakfire.provides(self.args.pattern, **self.pakfire_args) + def handle_provides(self, long=False): + p = self.pakfire(**self.pakfire_args) - for pkg in pkgs: - print pkg.dump() + for pkg in p.provides(self.args.pattern): + print pkg.dump(long=long) def handle_grouplist(self): - pkgs = pakfire.grouplist(self.args.group[0], **self.pakfire_args) + p = self.pakfire(**self.pakfire_args) - for pkg in pkgs: + for pkg in p.grouplist(self.args.group[0]): print " * %s" % pkg def handle_groupinstall(self): - pakfire.groupinstall(self.args.group[0], **self.pakfire_args) + p = self.pakfire(**self.pakfire_args) + p.groupinstall(self.args.group[0]) def handle_repolist(self): - repos = pakfire.repo_list(**self.pakfire_args) + p = self.pakfire(**self.pakfire_args) FORMAT = " %-20s %8s %12s %12s " - title = FORMAT % (_("Repository"), _("Enabled"), _("Priority"), _("Packages")) print title print "=" * len(title) # spacing line - for repo in repos: + for repo in p.repo_list(): # Skip the installed repository. if repo.name == "installed": continue @@ -363,21 +369,28 @@ class Cli(object): def handle_clean_all(self): print _("Cleaning up everything...") - pakfire.clean_all(**self.pakfire_args) + p = self.pakfire(**self.pakfire_args) + p.clean_all() def handle_check(self): - pakfire.check(**self.pakfire_args) + p = self.pakfire(**self.pakfire_args) + p.check() def handle_resolvdep(self): - (pkg,) = self.args.package + p = self.pakfire(**self.pakfire_args) - solver = pakfire.resolvdep(pkg, **self.pakfire_args) + (pkg,) = self.args.package + solver = p.pool.resolvdep(pkg) assert solver.status - solver.transaction.dump() + + t = transaction.Transaction.from_solver(p, solver) + t.dump() class CliBuilder(Cli): + pakfire = base.PakfireBuilder + def __init__(self): # Check if we are already running in a pakfire container. In that # case, we cannot start another pakfire-builder. @@ -424,7 +437,7 @@ class CliBuilder(Cli): @property def pakfire_args(self): - ret = { "mode" : "builder" } + ret = {} if hasattr(self.args, "disable_repo"): ret["disable_repos"] = self.args.disable_repo @@ -505,9 +518,19 @@ class CliBuilder(Cli): # Check whether to enable the install test. install_test = not self.args.no_install_test - pakfire.build(pkg, builder_mode=self.args.mode, install_test=install_test, - arch=self.args.arch, resultdirs=[self.args.resultdir,], - shell=True, after_shell=self.args.after_shell, **self.pakfire_args) + if self.args.mode == "release": + release_build = True + else: + release_build = False + + p = self.pakfire(arch=self.args.arch, **self.pakfire_args) + p.build(pkg, + install_test=install_test, + resultdirs=[self.args.resultdir,], + shell=True, + after_shell=self.args.after_shell, + release_build=release_build, + ) def handle_shell(self): pkg = None @@ -523,8 +546,13 @@ class CliBuilder(Cli): else: raise FileNotFoundError, pkg - pakfire.shell(pkg, builder_mode=self.args.mode, - arch=self.args.arch, **self.pakfire_args) + if self.args.mode == "release": + release_build = True + else: + release_build = False + + p = self.pakfire(arch=self.args.arch, **self.pakfire_args) + p.shell(pkg, release_build=release_build) def handle_dist(self): # Get the packages from the command line options @@ -543,22 +571,17 @@ class CliBuilder(Cli): # current working directory. resultdir = self.args.resultdir or os.getcwd() - # Change the default pakfire configuration, because - # packaging source packages can be done in server mode. - pakfire_args = self.pakfire_args - pakfire_args["mode"] = "server" - + p = self.pakfire(**self.pakfire_args) for pkg in pkgs: - pakfire.dist(pkg, resultdir=resultdir, **pakfire_args) + p.dist(pkg, resultdir=resultdir) def handle_provides(self): - pkgs = pakfire.provides(self.args.pattern, **self.pakfire_args) - - for pkg in pkgs: - print pkg.dump(long=True) + Cli.handle_provides(long=True) class CliServer(Cli): + pakfire = base.PakfireServer + def __init__(self): self.parser = argparse.ArgumentParser( description = _("Pakfire server command line interface."), @@ -590,7 +613,7 @@ class CliServer(Cli): @property def pakfire_args(self): - ret = { "mode" : "server" } + ret = {} if hasattr(self.args, "offline") and self.args.offline: ret["downloader"] = { @@ -683,8 +706,8 @@ class CliServer(Cli): def handle_repo_create(self): path = self.args.path[0] - pakfire.repo_create(path, self.args.inputs, key_id=self.args.key, - **self.pakfire_args) + p = self.pakfire(**self.pakfire_args) + p.repo_create(path, self.args.inputs, key_id=self.args.key) def handle_info(self): info = self.server.info() @@ -757,7 +780,7 @@ class CliBuilderIntern(Cli): "resultdir" : self.args.resultdir, } - pakfire._build(pkg, **kwargs) + self.pakfire._build(pkg, **kwargs) class CliClient(Cli): @@ -882,10 +905,11 @@ class CliClient(Cli): try: if package.endswith(".%s" % MAKEFILE_EXTENSION): - pakfire_args = { "mode" : "server" } + pakfire_args = {} # Create a source package from the makefile. - package = pakfire.dist(package, temp_dir, **pakfire_args) + p = self.pakfire(**self.pakfire_args) + package = p.dist(package, temp_dir) elif package.endswith(".%s" % PACKAGE_EXTENSION): pass @@ -1141,9 +1165,6 @@ class CliKey(Cli): # Finally parse all arguments from the command line and save them. self.args = self.parser.parse_args() - # Create a pakfire instance. - self.pakfire = pakfire.Pakfire(**self.pakfire_args) - self.action2func = { "generate" : self.handle_generate, "import" : self.handle_import, @@ -1156,11 +1177,7 @@ class CliKey(Cli): @property def pakfire_args(self): - ret = { - "mode" : "server", - } - - return ret + return {} def parse_command_generate(self): # Parse "generate" command. @@ -1234,30 +1251,33 @@ class CliKey(Cli): print # Generate the key. - pakfire.key_generate(realname, email, **self.pakfire_args) + p = self.pakfire(**self.pakfire_args) + p.key_generate(realname, email) def handle_import(self): filename = self.args.filename[0] # Simply import the file. - pakfire.key_import(filename, **self.pakfire_args) + p = self.pakfire(**self.pakfire_args) + p.key_import(filename) def handle_export(self): keyid = self.args.keyid[0] filename = self.args.filename[0] secret = self.args.secret - pakfire.key_export(keyid, filename, secret=secret, **self.pakfire_args) + p = self.pakfire(**self.pakfire_args) + p.key_export(keyid, filename, secret=secret) def handle_delete(self): keyid = self.args.keyid[0] - pakfire.key_delete(keyid, **self.pakfire_args) + p = self.pakfire(**self.pakfire_args) + p.key_delete(keyid) def handle_list(self): - lines = pakfire.key_list(**self.pakfire_args) - - for line in lines: + p = self.pakfire(**self.pakfire_args) + for line in p.key_list(): print line def handle_sign(self): @@ -1275,9 +1295,12 @@ class CliKey(Cli): key = self.args.key[0] + # Create pakfire instance. + p = self.pakfire(**self.pakfire_args) + for file in files: # Open the package. - pkg = packages.open(self.pakfire, None, file) + pkg = packages.open(p, None, file) print _("Signing %s...") % pkg.friendly_name pkg.sign(key) @@ -1292,9 +1315,12 @@ class CliKey(Cli): file = os.path.abspath(file) files.append(file) + # Create pakfire instance. + p = self.pakfire(**self.pakfire_args) + for file in files: # Open the package. - pkg = packages.open(self.pakfire, None, file) + pkg = packages.open(p, None, file) print _("Verifying %s...") % pkg.friendly_name sigs = pkg.verify() diff --git a/python/pakfire/config.py b/python/pakfire/config.py index adca6549f..3cc7c4224 100644 --- a/python/pakfire/config.py +++ b/python/pakfire/config.py @@ -215,9 +215,12 @@ class _Config(object): for f in self._files: log.debug(" %s" % f) - def has_distro(self): + def has_distro_conf(self): return self._config.has_key("distro") + def get_distro_conf(self): + return self.get_section("distro") + class Config(_Config): files = ["general.conf", "distro.conf"] diff --git a/python/pakfire/distro.py b/python/pakfire/distro.py index 832858cfe..d4cc6e7e4 100644 --- a/python/pakfire/distro.py +++ b/python/pakfire/distro.py @@ -25,29 +25,23 @@ import re import logging log = logging.getLogger("pakfire") -from errors import ConfigError -from repository import Repositories from system import system class Distribution(object): - def __init__(self, pakfire, data=None): - self.pakfire = pakfire + def __init__(self, data=None): self._data = {} - if data is None: + if data: + self.update(data) + else: # Read /etc/os-release if it does exist. self.read_osrelease() - # Inherit configuration from Pakfire configuration. - self.update(self.pakfire.config.get_section("distro")) - else: - self._data = data - # Dump all data self.dump() def read_osrelease(self): - filename = os.path.join(self.pakfire.path, "etc", "os-release") + filename = "/etc/os-release" if not os.path.exists(filename): return @@ -78,10 +72,6 @@ class Distribution(object): self.update(data) - @property - def config(self): - return self.pakfire.config - def dump(self): log.debug("Distribution configuration:") diff --git a/python/pakfire/repository/__init__.py b/python/pakfire/repository/__init__.py index 040cb5fce..5d2f4c193 100644 --- a/python/pakfire/repository/__init__.py +++ b/python/pakfire/repository/__init__.py @@ -38,12 +38,9 @@ class Repositories(object): This is the place where repositories can be activated or deactivated. """ - def __init__(self, pakfire, enable_repos=None, disable_repos=None): + def __init__(self, pakfire): self.pakfire = pakfire - self.config = pakfire.config - self.distro = pakfire.distro - # Place to store the repositories self.__repos = {} @@ -55,7 +52,7 @@ class Repositories(object): self.add_repo(self.local) # If we running in build mode, we include our local build repository. - if self.pakfire.builder: + if self.pakfire.mode == "builder": self.local_build = RepositoryBuild(self.pakfire) self.add_repo(self.local_build) @@ -63,24 +60,6 @@ class Repositories(object): for repo_name, repo_args in self.config.get_repos(): self._parse(repo_name, repo_args) - # Enable all repositories here as demanded on commandline - if enable_repos: - for repo in enable_repos: - self.enable_repo(repo) - - # Disable all repositories here as demanded on commandline - if disable_repos: - # * is magic to disable all repositories. - if "*" in disable_repos: - disable_repos = [r.name for r in self] - - for repo in disable_repos: - self.disable_repo(repo) - - # Update all indexes of the repositories (not force) so that we will - # always work with valid data. - self.update(force=False, offline=self.pakfire.offline) - def __iter__(self): repositories = self.__repos.values() repositories.sort() @@ -93,6 +72,40 @@ class Repositories(object): """ return len([r for r in self if r.enabled]) + @property + def initialized(self): + """ + Indicates if all repositories are initialized. + """ + for repo in self: + if not repo.opened: + return False + + return True + + def initialize(self): + # Nothing to do, if everything is already up to date. + if self.initialized: + return + + for repo in self: + repo.open() + + def shutdown(self): + """ + Shuts down all repositores. + """ + for repo in self: + repo.close() + + @property + def config(self): + return self.pakfire.config + + @property + def distro(self): + return self.pakfire.distro + @property def pool(self): return self.pakfire.pool @@ -171,17 +184,6 @@ class Repositories(object): except KeyError: pass - def update(self, force=False, offline=False): - log.debug("Updating all repository indexes (force=%s)" % force) - - # update all indexes if necessary or forced - for repo in self: - # Skip disabled repositories. - if not repo.enabled: - continue - - repo.update(force=force, offline=offline) - def whatprovides(self, what): what = self.pakfire.pool.create_relation(what) diff --git a/python/pakfire/repository/base.py b/python/pakfire/repository/base.py index d7850da0d..c16ca37c8 100644 --- a/python/pakfire/repository/base.py +++ b/python/pakfire/repository/base.py @@ -45,6 +45,9 @@ class RepositoryFactory(object): # Create an index (in memory). self.index = index.Index(self.pakfire, self) + # Marks if this repository has been opened. + self.opened = False + def __repr__(self): return "<%s %s>" % (self.__class__.__name__, self.name) @@ -105,12 +108,17 @@ class RepositoryFactory(object): """ return False - def update(self, force=False, offline=False): + def open(self): + """ + Opens the repository, so we can work with the data. + """ + self.opened = True + + def close(self): """ - A function that is called to update the local data of - the repository. + Close and delete all resources that are used by this repository. """ - raise NotImplementedError, self + self.opened = False def clean(self): """ diff --git a/python/pakfire/repository/database.py b/python/pakfire/repository/database.py index 4c5084c21..23bb64cc6 100644 --- a/python/pakfire/repository/database.py +++ b/python/pakfire/repository/database.py @@ -118,6 +118,10 @@ class DatabaseLocal(Database): Database.__init__(self, pakfire, filename) + def initialize(self): + # Open the database. + self.open() + # Check if we actually can open the database. if not self.format in DATABASE_FORMATS_SUPPORTED: raise DatabaseFormatError, _("The format of the database is not supported by this version of pakfire.") diff --git a/python/pakfire/repository/local.py b/python/pakfire/repository/local.py index c6f9128a4..f38b408e3 100644 --- a/python/pakfire/repository/local.py +++ b/python/pakfire/repository/local.py @@ -255,34 +255,35 @@ class RepositoryBuild(RepositoryDir): RepositoryDir.__init__(self, pakfire, "build", "Locally built packages", path) - def update(self, force=False, offline=False): - # If force is not given, but there are no files in the repository, - # we force an update anyway. - if not force: - force = len(self) == 0 + def open(self): + # Find all files in the repository dir. + files = self.search_files(self.path) - if force: - # Wipe the index. - self.index.clear() + # Create progress bar. + pb = util.make_progress(_("%s: Reading packages...") % self.name, len(files)) + i = 0 - # Find all files in the repository dir. - files = self.search_files(self.path) + # Add all files to the index. + for file in files: + if pb: + i += 1 + pb.update(i) - # Create progress bar. - pb = util.make_progress(_("%s: Adding packages...") % self.name, len(files)) - i = 0 + pkg = packages.open(self.pakfire, self, file) + self.index.add_package(pkg) + + if pb: + pb.finish() - # Add all files to the index. - for file in files: - if pb: - i += 1 - pb.update(i) + # Mark repo as open. + self.opened = True - pkg = packages.open(self.pakfire, self, file) - self.index.add_package(pkg) + def close(self): + # Wipe the index. + self.index.clear() - if pb: - pb.finish() + # Mark repository as not being open. + self.opened = False @property def local(self): diff --git a/python/pakfire/repository/remote.py b/python/pakfire/repository/remote.py index 6d2cdc7a9..410750acb 100644 --- a/python/pakfire/repository/remote.py +++ b/python/pakfire/repository/remote.py @@ -117,17 +117,21 @@ class RepositoryRemote(base.RepositoryFactory): # Remove all files in the files cache. self.cache.destroy() - def update(self, force=False, offline=False): - if force and offline: - raise OfflineModeError, _("You cannot force to update metadata in offline mode.") - + def open(self): # First update the repository metadata. - self.update_metadata(force=force, offline=offline) - self.update_database(force=force, offline=offline) + self.update_metadata() + self.update_database() # Read the database. self.open_database() + # Mark the repository as open. + self.opened = True + + def close(self): + # Mark the repository as not open. + self.opened = False + def open_metadata(self, path=None): if not path: path = self.cache_path(os.path.basename(METADATA_DOWNLOAD_FILE)) diff --git a/python/pakfire/repository/system.py b/python/pakfire/repository/system.py index 386f25255..08584cf6b 100644 --- a/python/pakfire/repository/system.py +++ b/python/pakfire/repository/system.py @@ -51,35 +51,44 @@ class RepositorySystem(base.RepositoryFactory): """ return 10 - def update(self, force=False, offline=False): - # XXX using the cache is currently disabled - #if not force: - # if os.path.exists(self.cache_file): - # self.index.read(self.cache_file) - # - # force = len(self) == 0 + def open(self): + # Initialize database. + self.db.initialize() - force = True + # Create a progressbar. + pb = util.make_progress(_("Loading installed packages"), len(self.db)) - if force: - # Create a progressbar. - pb = util.make_progress(_("Loading installed packages"), len(self.db)) + # Remove all data from the current index. + self.index.clear() - # Remove all data from the current index. - self.index.clear() + i = 0 + for pkg in self.db.packages: + if pb: + i += 1 + pb.update(i) + + self.index.add_package(pkg) - i = 0 - for pkg in self.db.packages: - if pb: - i += 1 - pb.update(i) + self.index.optimize() - self.index.add_package(pkg) + if pb: + pb.finish() - self.index.optimize() + # Mark repo as open. + self.opened = True - if pb: - pb.finish() + def close(self): + # Commit all data that is currently pending for writing. + self.db.commit() + + # Close database. + self.db.close() + + # Remove indexed data from memory. + self.index.clear() + + # Mark repo as closed. + self.opened = False def commit(self): # Commit the database to disk.