]> git.ipfire.org Git - pakfire.git/commitdiff
Initial import of the sat solver code.
authorMichael Tremer <michael.tremer@ipfire.org>
Fri, 29 Apr 2011 19:20:03 +0000 (21:20 +0200)
committerMichael Tremer <michael.tremer@ipfire.org>
Fri, 29 Apr 2011 19:20:03 +0000 (21:20 +0200)
16 files changed:
pakfire/base.py
pakfire/builder.py
pakfire/depsolve.py [deleted file]
pakfire/packages/base.py
pakfire/packages/binary.py
pakfire/packages/installed.py
pakfire/packages/source.py
pakfire/repository/__init__.py
pakfire/repository/actions.py [new file with mode: 0644]
pakfire/repository/base.py
pakfire/repository/index.py
pakfire/repository/solver.py [new file with mode: 0644]
pakfire/repository/transaction.py [new file with mode: 0644]
pakfire/transaction.py [deleted file]
po/POTFILES.in
po/pakfire.pot

index 6412a842801792c87c6f6fe302fe30dcc069ae7a..cc8d66c1f7ecbc36c408ba847db80cc57931563f 100644 (file)
@@ -7,20 +7,18 @@ import string
 
 import builder
 import config
-import depsolve
 import distro
 import logger
-import packages
 import repository
-import transaction
+import packages
 import util
 
 from constants import *
 from i18n import _
 
 class Pakfire(object):
-       def __init__(self, builder=False, configs=[], disable_repos=None,
-                       distro_config=None):
+       def __init__(self, builder=False, configs=[], enable_repos=None,
+                       disable_repos=None, distro_config=None):
                # Check if we are operating as the root user.
                self.check_root_user()
 
@@ -46,16 +44,11 @@ class Pakfire(object):
                # Get more information about the distribution we are running
                # or building
                self.distro = distro.Distribution(self, distro_config)
-               self.repos  = repository.Repositories(self)
+               self.repos  = repository.Repositories(self,
+                       enable_repos=enable_repos, disable_repos=disable_repos)
 
-               # Disable repositories if passed on command line
-               if disable_repos:
-                       for repo in disable_repos:
-                               self.repos.disable_repo(repo)
-
-               # Update all indexes of the repositories (not force) so that we will
-               # always work with valid data.
-               self.repos.update()
+               # Create a short reference to the solver of this pakfire instance.
+               self.solver = self.repos.solver
 
        def destroy(self):
                if not self.path == "/":
@@ -92,54 +85,22 @@ class Pakfire(object):
                raise BuildError, arch
 
        def install(self, requires):
-               ds = depsolve.DependencySet(pakfire=self)
-
+               # Create a new request.
+               request = self.solver.create_request()
                for req in requires:
-                       if isinstance(req, packages.BinaryPackage):
-                               ds.add_package(req)
-                       else:
-                               ds.add_requires(req)
+                       request.install(req)
 
-               ds.resolve()
-               ds.dump()
+               # Do the solving.
+               t = self.solver.solve(request)
 
-               ret = cli.ask_user(_("Is this okay?"))
-               if not ret:
+               if not t:
                        return
 
-               ts = transaction.Transaction(self, ds)
-               ts.run()
+               t.run()
 
        def update(self, pkgs):
-               ds = depsolve.DependencySet(pakfire=self)
-
-               for pkg in ds.packages:
-                       # Skip unwanted packages (passed on command line)
-                       if pkgs and not pkg.name in pkgs:
-                               continue
-
-                       updates = self.repos.get_by_name(pkg.name)
-                       updates = packages.PackageListing(updates)
-
-                       latest = updates.get_most_recent()
-
-                       # If the current package is already the latest
-                       # we skip it.
-                       if latest == pkg:
-                               continue
-
-                       # Otherwise we want to update the package.
-                       ds.add_package(latest)
-
-               ds.resolve()
-               ds.dump()
-
-               ret = cli.ask_user(_("Is this okay?"))
-               if not ret:
-                       return
-
-               ts = transaction.Transaction(self, ds)
-               ts.run()
+               # XXX needs to be done
+               pass
 
        def info(self, patterns):
                pkgs = []
@@ -251,8 +212,7 @@ class Pakfire(object):
        def provides(self, patterns):
                pkgs = []
                for pattern in patterns:
-                       requires = depsolve.Requires(None, pattern)
-                       pkgs += self.repos.get_by_provides(requires)
+                       pkgs += self.repos.get_by_provides(pattern)
 
                pkgs = packages.PackageListing(pkgs)
                #pkgs.unique()
@@ -262,8 +222,7 @@ class Pakfire(object):
        def requires(self, patterns):
                pkgs = []
                for pattern in patterns:
-                       requires = depsolve.Requires(None, pattern)
-                       pkgs += self.repos.get_by_requires(requires)
+                       pkgs += self.repos.get_by_requires(pattern)
 
                pkgs = packages.PackageListing(pkgs)
                #pkgs.unique()
index 124c7c7957ceae37c5e385df8811cd604b30f6cc..db648088a6a914cb90645851ed3af65e0096149b 100644 (file)
@@ -14,11 +14,9 @@ import uuid
 
 import base
 import chroot
-import depsolve
 import logger
 import packages
 import repository
-import transaction
 import util
 
 from constants import *
@@ -135,6 +133,10 @@ class Builder(object):
                """
                return self.distro.arch
 
+       @property
+       def solver(self):
+               return self.pakfire.solver
+
        @property
        def info(self):
                return {
@@ -269,19 +271,29 @@ class Builder(object):
                if not requires:
                        return
 
-               ds = depsolve.DependencySet(self.pakfire)
-               for r in requires:
-                       if isinstance(r, packages.BinaryPackage):
-                               ds.add_package(r)
-                       else:
-                               ds.add_requires(r)
-               ds.resolve()
-               ds.dump(logger=self.log)
+               # Create a request and fill it with what we need.
+               request = self.solver.create_request()
+
+               for req in requires:
+                       if isinstance(req, packages.BinaryPackage):
+                               req = req.friendly_name
+
+                       req = self.solver.create_relation(req)
 
-               ts = transaction.Transaction(self.pakfire, ds)
-               ts.run()
+                       request.install(req)
+
+               # Do the solving.
+               transaction = self.solver.solve(request)
+
+               # Show the user what is going to be done.
+               transaction.dump(logger=self.log)
+
+               # Run the transaction.
+               transaction.run()
 
        def install_test(self):
+               return # XXX currently disabled
+
                pkgs = []
 
                # Connect packages to the FS repository.
diff --git a/pakfire/depsolve.py b/pakfire/depsolve.py
deleted file mode 100644 (file)
index 3ccec24..0000000
+++ /dev/null
@@ -1,270 +0,0 @@
-#!/usr/bin/python
-
-import logging
-import re
-
-import packages
-import repository
-import transaction
-import util
-
-from errors import *
-
-from i18n import _
-
-PKG_DUMP_FORMAT = " %-21s %-8s %-21s %-19s %5s "
-
-class Requires(object):
-       def __init__(self, pkg, requires, dep=False):
-               self.pkg = pkg
-               self.requires = requires
-               self.dep = dep
-
-       def __repr__(self):
-               return "<%s %s>" % (self.__class__.__name__, self.requires)
-
-       def __str__(self):
-               return self.requires
-
-       def __cmp__(self, other):
-               return cmp(self.requires, other.requires)
-
-       def __hash__(self):
-               return hash(self.requires)
-
-       @property
-       def type(self):
-               if self.requires.startswith("/"):
-                       return "file"
-
-               elif "(" in self.requires:
-                       return "virtual"
-
-               elif ">" in self.requires or "<" in self.requires or "=" in self.requires:
-                       return "expr"
-
-               elif not re.match("^lib.*\.so.*", self.requires):
-                       return "lib"
-
-               return "generic"
-
-
-class Conflicts(object):
-       def __init__(self, pkg, conflicts):
-               self.pkg = pkg
-               self.conflicts = conflicts
-
-       def __repr__(self):
-               return "<%s %s>" % (self.__class__.__name__, self.conflicts)
-
-       def __str__(self):
-               return self.conflicts
-
-       def __hash__(self):
-               return hash(self.conflicts)
-
-
-class Obsoletes(object):
-       def __init__(self, pkg, obsoletes):
-               self.pkg = pkg
-               self.obsoletes = obsoletes
-
-       def __repr__(self):
-               return "<%s %s>" % (self.__class__.__name__, self.obsoletes)
-
-       def __str__(self):
-               return self.obsoletes
-
-       def __hash__(self):
-               return hash(self.obsoletes)
-
-
-class DependencySet(object):
-       def __init__(self, pakfire):
-               # Reference all repositories
-               self.repos = pakfire.repos #repository.Repositories()
-
-               # List of packages in this set
-               self.__packages = set()
-
-               # Helper lists
-               self.__conflicts = set()
-               self.__requires = set()
-               self.__obsoletes = set()
-
-               # Create a new transaction set.
-               self.ts = transaction.TransactionSet()
-
-               # Read-in all packages from the database that have
-               # been installed previously and need to be taken into
-               # account when resolving dependencies.
-               for pkg in self.repos.local.packages:
-                       self.add_package(pkg, transaction=False)
-
-       def add_requires(self, requires, pkg=None, dep=False):
-               requires = Requires(pkg, requires, dep)
-
-               if requires in self.__requires:
-                       return
-
-               for pkg in self.__packages:
-                       if pkg.does_provide(requires):
-                               logging.debug("Skipping requires '%s' which is already provided by %s" % (requires.requires, pkg))
-                               return
-
-               #logging.debug("Adding requires: %s" % requires)
-               self.__requires.add(requires)
-
-       def add_obsoletes(self, obsoletes, pkg=None):
-               obsoletes = Obsoletes(pkg, obsoletes)
-
-               self.__obsoletes.add(obsoletes)
-
-       def add_package(self, pkg, dep=False, transaction=True):
-               #print pkg, sorted(self.__packages)
-               #assert not pkg in self.__packages
-               if pkg in self.__packages:
-                       logging.debug("Trying to add package which is already in the dependency set: %s" % pkg)
-                       return
-
-               if transaction:
-                       transaction_mode = "install"
-                       for p in self.__packages:
-                               if pkg.name == p.name:
-                                       transaction_mode = "update"
-
-                                       # Set pointer to package that is updated.
-                                       pkg.old_package = p
-
-                                       # Remove old package from list of packages.
-                                       self.__packages.remove(pkg.old_package)
-                                       break
-
-                       # Add package to transaction set
-                       func = getattr(self.ts, transaction_mode)
-                       func(pkg, dep=dep)
-
-               #if not isinstance(pkg, packages.DatabasePackage):
-               #       logging.info(" --> Adding package to dependency set: %s" % pkg.friendly_name)
-               self.__packages.add(pkg)
-
-               # Add the requirements of the newly added package.
-               for req in pkg.requires:
-                       self.add_requires(req, pkg, dep=True)
-
-               # Remove all requires that are fulfilled by this package.
-               # For that we copy the matching requires to _requires and remove them
-               # afterwards, because changing self.__requires in a "for" loop is not
-               # a good idea.
-               _requires = []
-               for req in self.__requires:
-                       if pkg.does_provide(req):
-                               _requires.append(req)
-
-               for req in _requires:
-                       self.__requires.remove(req)
-
-       @property
-       def packages(self):
-               if not self.__requires:
-                       return self.__packages[:]
-
-       def resolve(self):
-               unresolveable_reqs = []
-
-               while self.__requires:
-                       requires = self.__requires.pop()
-                       logging.debug("Resolving requirement \"%s\"" % requires)
-
-                       # Fetch all candidates from the repositories and save the
-                       # best one
-                       if requires.type == "file":
-                               candidates = self.repos.get_by_file(requires.requires)
-                       else:
-                               candidates = self.repos.get_by_provides(requires)
-
-                       # Turn the candidates into a package listing.
-                       candidates = packages.PackageListing(candidates)
-
-                       if not candidates:
-                               logging.debug("  Got no candidates for that")
-                               unresolveable_reqs.append(requires)
-                               continue
-
-                       logging.debug("  Got candidates for that:")
-                       for candidate in candidates:
-                               logging.debug("  --> %s" % candidate)
-
-                       best = candidates.get_most_recent()
-                       if best:
-                               self.add_package(best, dep=requires.dep)
-
-               if unresolveable_reqs:
-                       raise DependencyError, "Cannot resolve %s" % \
-                               " ".join([r.requires for r in unresolveable_reqs])
-
-       def dump_pkg(self, format, pkg):
-               return format % (
-                       pkg.name,
-                       pkg.arch,
-                       pkg.friendly_version,
-                       pkg.repo.name,
-                       util.format_size(pkg.size),
-               )
-
-       def dump_pkgs(self, caption, pkgs):
-               if not pkgs:
-                       return []
-
-               s = [caption,]
-               for pkg in sorted(pkgs):
-                       s.append(self.dump_pkg(PKG_DUMP_FORMAT, pkg))
-               s.append("")
-               return s
-
-       def dump(self, logger=None):
-               # If no logger was given, we use the root logger.
-               if not logger:
-                       logger = logging.getLogger()
-
-               width = 80
-               line = "=" * width
-
-               s = []
-               s.append(line)
-               s.append(PKG_DUMP_FORMAT % (_("Package"), _("Arch"), _("Version"), _("Repository"), _("Size")))
-               s.append(line)
-
-               s += self.dump_pkgs(_("Installing:"), self.ts.installs)
-               s += self.dump_pkgs(_("Installing for dependencies:"), self.ts.install_deps)
-               s += self.dump_pkgs(_("Updating:"), self.ts.updates)
-               s += self.dump_pkgs(_("Updating for dependencies:"), self.ts.update_deps)
-               s += self.dump_pkgs(_("Removing:"), self.ts.removes)
-               s += self.dump_pkgs(_("Removing for dependencies:"), self.ts.remove_deps)
-
-               s.append(_("Transaction Summary"))
-               s.append(line)
-
-               format = "%-20s %-4d %s"
-
-               if self.ts.installs or self.ts.install_deps:
-                       s.append(format % (_("Install"),
-                               len(self.ts.installs + self.ts.install_deps), _("Package(s)")))
-
-               if self.ts.updates or self.ts.update_deps:
-                       s.append(format % (_("Updates"),
-                               len(self.ts.updates + self.ts.update_deps), _("Package(s)")))
-
-               if self.ts.removes or self.ts.remove_deps:
-                       s.append(format % (_("Remove"),
-                               len(self.ts.removes + self.ts.remove_deps), _("Package(s)")))
-
-               # Calculate the size of all files that need to be downloaded this this
-               # transaction.
-               download_size = sum([p.size for p in self.ts.downloads])
-               if download_size:
-                       s.append(_("Total download size: %s") % util.format_size(download_size))
-               s.append("")
-
-               for line in s:
-                       logger.info(line)
index d7d1f48c41e0127e5598ebe18ff10eba594dd847..bd90428b9ebeba0d99232e25469b09e1e335541a 100644 (file)
@@ -1,13 +1,9 @@
 #!/usr/bin/python
 
-
-import fnmatch
 import logging
-import re
 
 import util
 
-import pakfire.depsolve
 from pakfire.i18n import _
 
 class Package(object):
@@ -291,6 +287,10 @@ class Package(object):
        def supported_arches(self):
                return self.metadata.get("PKG_SUPPORTED_ARCHES", "all")
 
+       @property
+       def vendor(self):
+               return self.metadata.get("PKG_VENDOR", "")
+
        @property
        def requires(self):
                ret = ""
@@ -310,101 +310,17 @@ class Package(object):
                return set(ret.split())
 
        @property
-       def _provides(self):
-               # Make package identifyable by its name and version/release tuples.
-               provides = [
-                       self.name,
-                       "%s=%s-%s" % (self.name, self.version, self.release),
-                       "%s=%s:%s-%s" % (self.name, self.epoch, self.version, self.release),
-               ]
+       def provides(self):
+               provides = self.metadata.get("PKG_PROVIDES", "").split()
 
                return set(provides)
 
-       ### methods ###
-
-       def _does_provide_file(self, requires):
-               for file in self.filelist:
-                       if fnmatch.fnmatch(file, requires.requires):
-                               return True
-
-               return False
-
-       def does_provide(self, requires):
-               if not isinstance(requires, pakfire.depsolve.Requires):
-                       requires = pakfire.depsolve.Requires(self, requires)
-
-               # Get all provide strings from the package data
-               # and return true if requires is matched.
-               if requires.requires in self.provides:
-                       return True
-
-               if requires.type == "file":
-                       return self._does_provide_file(requires)
-
-               elif requires.type == "expr":
-                       # Handle all expressions like "gcc>=4.0.0-1"
-                       (e_expr, e_name, e_epoch, e_version, e_release) = \
-                               util.parse_pkg_expr(requires.requires)
-
-                       # If the package names do not match, we do not provide this:
-                       if not self.name == e_name:
-                               return False
-
-                       ret = util.version_compare(self.version_tuple, (e_epoch, e_version, e_release))
-
-                       # If we equal the version, we provide this
-                       if "=" in e_expr and ret == 0:
-                               return True
-
-                       elif ">" in e_expr and ret > 0:
-                               return True
-
-                       elif "<" in e_expr and ret < 0:
-                               return True
-
-                       return False
-
-               elif requires.type == "virtual":
-                       (r_type, r_expr, r_name, r_version) = \
-                               util.parse_virtual_expr(requires.requires)
-
-                       # If we get an invalid expression with no name, we
-                       # do not provide this.
-                       if not r_name:
-                               return False
-
-                       for provides in self.provides:
-                               (p_type, p_expr, p_name, p_version) = \
-                                       util.parse_virtual_expr(provides)
-
-                               # If name does not match, we have no match at all.
-                               if not p_type == r_type or not p_name == r_name:
-                                       continue
-
-                               # Check if the expression is fulfilled.
-                               if r_expr == "=":
-                                       return p_version == r_version
-
-                               elif r_expr == ">=":
-                                       return p_version >= r_version
-
-                               elif r_expr == ">":
-                                       return p_version > r_version
-
-                               elif r_expr == "<":
-                                       return p_version < r_version
-
-                               elif r_expr == "<=":
-                                       return p_version <= r_version
-
-                               elif not r_expr:
-                                       # If we get here, the name matches and there was no version
-                                       # required.
-                                       return True
+       @property
+       def obsoletes(self):
+               obsoletes = self.metadata.get("PKG_OBSOLETES", "").split()
 
-               # No match was found at all
-               return False
+               return set(obsoletes)
 
-       def extract(self, path):
-               raise NotImplementedError
+       def extract(self, path, prefix=None):
+               raise NotImplementedError, "%s" % type(self)
 
index 06c6bbf841fa8d21aa12887c0b81dae814fcdd9b..15005662425aff907da900d3b46d40c2e66e7c44 100644 (file)
@@ -1,7 +1,5 @@
 #!/usr/bin/python
 
-import sys
-
 from file import FilePackage
 
 class BinaryPackage(FilePackage):
@@ -9,20 +7,6 @@ class BinaryPackage(FilePackage):
        def arch(self):
                return self.metadata.get("PKG_ARCH")
 
-       @property
-       def provides(self):
-               if not hasattr(self, "__provides"):
-                       # Get automatic provides
-                       provides = self._provides
-
-                       # Add other provides
-                       for prov in self.metadata.get("PKG_PROVIDES", "").split():
-                               provides.add(prov)
-
-                       self.__provides = provides
-
-               return self.__provides
-
        @property
        def conflicts(self):
                conflicts = self.metadata.get("PKG_CONFLICTS", "").split()
index 5b6943ed882576dbeb98a02a2c05d2a7eb8b2183..9d66dec4bdd8d72bdd3ddf1675970606a1480b63 100644 (file)
@@ -110,35 +110,27 @@ class DatabasePackage(Package):
 
        @property
        def provides(self):
-               if not hasattr(self, "__provides"):
-                       # Get automatic provides
-                       provides = self._provides
+               provides = self.metadata.get("provides", "").split()
 
-                       # Add other provides
-                       for prov in self.metadata.get("provides", "").split():
-                               provides.add(prov)
-
-                       self.__provides = provides
-
-               return self.__provides
+               return set(provides)
 
        @property
        def requires(self):
-               requires = self.metadata.get("requires")
-               
-               if requires:
-                       return requires.split()
+               requires = self.metadata.get("requires", "").split()
 
-               return []
+               return set(requires)
 
        @property
        def conflicts(self):
-               conflicts = self.metadata.get("conflicts")
+               conflicts = self.metadata.get("conflicts", "").split()
 
-               if conflicts:
-                       return conflicts.split()
+               return set(conflicts)
+
+       @property
+       def obsoletes(self):
+               obsoletes = self.metadata.get("obsoletes", "").split()
 
-               return []
+               return set(obsoletes)
 
        @property
        def hash1(self):
@@ -154,18 +146,14 @@ class DatabasePackage(Package):
 
        @property
        def filelist(self):
-               if not hasattr(self, "__filelist"):
-                       c = self.db.cursor()
+               c = self.db.cursor()
+               try:
                        c.execute("SELECT name FROM files WHERE pkg = ?", (self.id,))
 
-                       self.__filelist = []
-                       for f in c:
-                               self.__filelist.append(f["name"])
-
+                       return [f["name"] for f in c]
+               finally:
                        c.close()
 
-               return self.__filelist
-
        def _does_provide_file(self, requires):
                """
                        A faster version to find a file in the database.
index e606f474828bec2915ced6651925badb9dc0c75b..67a0b48e75d28e42feaa2500fb435581726109db 100644 (file)
@@ -13,8 +13,3 @@ class SourcePackage(FilePackage):
                        Return the requirements for the build.
                """
                return self.metadata.get("PKG_REQUIRES", "").split()
-
-       @property
-       def provides(self):
-               # XXX just a dummy
-               return []
index f0aebf33fd30fb9c874385c1546ec6c5d9e50d1e..21557e5bd6dec2928cfd5f7e581af83cdf4f643d 100644 (file)
@@ -2,6 +2,8 @@
 
 import logging
 
+import solver
+
 from installed import InstalledRepository
 from local import LocalRepository, LocalBuildRepository, LocalSourceRepository
 from oddments import DummyRepository, FileSystemRepository
@@ -14,7 +16,7 @@ class Repositories(object):
                This is the place where repositories can be activated or deactivated.
        """
 
-       def __init__(self, pakfire):
+       def __init__(self, pakfire, enable_repos=None, disable_repos=None):
                self.pakfire = pakfire
 
                self.config = pakfire.config
@@ -38,6 +40,15 @@ class Repositories(object):
                for repo_name, repo_args in self.config.get_repos():
                        self._parse(repo_name, repo_args)
 
+               # XXX need to process enable_repos and disable_repos here
+
+               # Update all indexes of the repositories (not force) so that we will
+               # always work with valid data.
+               self.update()
+
+               # Initialize the solver.
+               self.solver = solver.Solver(self.pakfire, self)
+
        def __len__(self):
                """
                        Return the count of enabled repositories.
@@ -93,40 +104,48 @@ class Repositories(object):
                for repo in self.enabled:
                        repo.update(force=force)
 
+       def get_repo_by_name(self, name):
+               for repo in self.enabled:
+                       if repo.name == name:
+                               return repo
+
        def get_all(self):
                for repo in self.enabled:
                        for pkg in repo.get_all():
                                yield pkg
 
        def get_by_name(self, name):
-               for repo in self.enabled:
-                       for pkg in repo.get_by_name(name):
-                               yield pkg
+               #for repo in self.enabled:
+               #       for pkg in repo.get_by_name(name):
+               #               yield pkg
+               return self.solver.get_by_name(name)
 
        def get_by_glob(self, pattern):
                for repo in self.enabled:
                        for pkg in repo.get_by_glob(pattern):
                                yield pkg
 
-       def get_by_provides(self, requires):
-               if requires.type == "file":
-                       for pkg in self.get_by_file(requires.requires):
-                               yield pkg
-
-               else:
-                       for repo in self.enabled:
-                               for pkg in repo.get_by_provides(requires):
-                                       yield pkg
+       #def get_by_provides(self, requires):
+       #       if requires.type == "file":
+       #               for pkg in self.get_by_file(requires.requires):
+       #                       yield pkg
+       #
+       #       else:
+       #               for repo in self.enabled:
+       #                       for pkg in repo.get_by_provides(requires):
+       #                               yield pkg
+       get_by_provides = get_by_name
 
        def get_by_requires(self, requires):
                for repo in self.enabled:
                        for pkg in repo.get_by_requires(requires):
                                yield pkg
 
-       def get_by_file(self, filename):
-               for repo in self.enabled:
-                       for pkg in repo.get_by_file(filename):
-                               yield pkg
+       #def get_by_file(self, filename):
+       #       for repo in self.enabled:
+       #               for pkg in repo.get_by_file(filename):
+       #                       yield pkg
+       get_by_file = get_by_name
 
        def get_by_group(self, group):
                for repo in self.enabled:
diff --git a/pakfire/repository/actions.py b/pakfire/repository/actions.py
new file mode 100644 (file)
index 0000000..e69de29
index cdf65779f38c5a2f753702789d9e6ba36acae9e8..d80448cbb7c55f3ffc8e1f318874367e31fe382d 100644 (file)
@@ -105,6 +105,11 @@ class RepositoryFactory(object):
                        if group in pkg.groups:
                                yield pkg
 
+       def get_by_friendly_name(self, name):
+               for pkg in self.packages:
+                       if pkg.friendly_name == name:
+                               return pkg
+
        def search(self, pattern):
                """
                        Returns a list of packages, that match the given pattern,
@@ -123,3 +128,17 @@ class RepositoryFactory(object):
                        Returns all packages.
                """
                return self.index.packages
+
+       @property
+       def size(self):
+               """
+                       Return the number of packages.
+               """
+               return self.index.size
+
+       @property
+       def filelist(self):
+               if hasattr(self.index, "filelist"):
+                       return self.index.filelist
+
+               return {}
index 2b2991eae3e33e99ecf24b5414b3c276492142d3..854e0a3a9f807f868a33d9b7aa9cfd9fbb74e9a1 100644 (file)
@@ -64,6 +64,14 @@ class Index(object):
                for pkg in self._packages:
                        yield pkg
 
+       @property
+       def size(self):
+               i = 0
+               for pkg in self.packages:
+                       i += 1
+
+               return i
+
        def update(self, force=False):
                pass
 
@@ -180,6 +188,23 @@ class DatabaseIndexFactory(Index):
 
                c.close()
 
+       @property
+       def filelist(self):
+               c = self.db.cursor()
+               c.execute("SELECT pkg, name FROM files")
+
+               files = {}
+
+               for entry in c:
+                       file = entry["name"]
+                       try:
+                               files[pkg_id].append(file)
+                       except KeyError:
+                               files[pkg_id] = [file,]
+
+               c.close()
+
+               return files
 
 class InstalledIndex(DatabaseIndexFactory):
        def open_database(self):
diff --git a/pakfire/repository/solver.py b/pakfire/repository/solver.py
new file mode 100644 (file)
index 0000000..b9f5772
--- /dev/null
@@ -0,0 +1,187 @@
+#!/usr/bin/python
+
+import logging
+import satsolver
+import time
+
+from transaction import Transaction
+
+import pakfire.util as util
+
+from pakfire.constants import *
+from pakfire.i18n import _
+
+class Solver(object):
+       RELATIONS = (
+               (">=", satsolver.REL_GE,),
+               ("<=", satsolver.REL_LE,),
+               ("=" , satsolver.REL_EQ,),
+               ("<" , satsolver.REL_LT,),
+               (">" , satsolver.REL_GT,),
+       )
+
+       def __init__(self, pakfire, repos, arch=None):
+               self.pakfire = pakfire
+               self.repos = repos
+
+               if not arch:
+                       arch = self.pakfire.distro.arch
+
+               # Mapping from solver ID to a package.
+               self.id2pkg = {}
+
+               # Initialize the pool and set the architecture.
+               self.pool = satsolver.Pool()
+               self.pool.set_arch(arch)
+
+               # Initialize all repositories.
+               self.repos = self.init_repos()
+
+               self.pool.prepare()
+
+       def create_relation(self, s):
+               s = str(s)
+
+               if s.startswith("/"):
+                       return satsolver.Relation(self.pool, s)
+
+               for pattern, type in self.RELATIONS:
+                       if not pattern in s:
+                               continue
+
+                       name, version = s.split(pattern, 1)
+
+                       return satsolver.Relation(self.pool, name, type, version)
+
+               return satsolver.Relation(self.pool, s)
+
+       def init_repos(self):
+               repos = []
+
+               for repo in self.repos.enabled:
+                       solvrepo = self.pool.create_repo(repo.name)
+                       if repo.name == "installed":
+                               self.pool.set_installed(solvrepo)
+
+                       pb = util.make_progress(_("Loading %s") % repo.name, repo.size)
+                       i = 0
+
+                       for pkg in repo.get_all():
+                               if pb:
+                                       i += 1
+                                       pb.update(i)
+
+                               self.add_package(pkg)
+
+                       logging.debug("Initialized new repo '%s' with %s packages." % \
+                               (solvrepo.name(), solvrepo.size()))
+
+                       if pb:
+                               pb.finish()
+
+                       repos.append(solvrepo)
+
+               return repos
+
+       def get_repo(self, name):
+               for repo in self.pool.repos():
+                       if not repo.name() == name:
+                               continue
+
+                       return repo
+
+       def add_package(self, pkg, repo_name=None):
+               if not repo_name:
+                       repo_name = pkg.repo.name
+
+               solvrepo = self.get_repo(repo_name)
+               assert solvrepo
+
+               solvable = satsolver.Solvable(solvrepo, str(pkg.name),
+                       str(pkg.friendly_version), str(pkg.arch))
+
+               # Store the solver's ID.
+               self.id2pkg[solvable.id()] = pkg
+
+               # Set vendor.
+               solvable.set_vendor(pkg.vendor)
+
+               # Import all requires.
+               for req in pkg.requires:
+                       rel = self.create_relation(req)
+                       solvable.requires().add(rel)
+
+               # Import all provides.
+               for prov in pkg.provides:
+                       rel = self.create_relation(prov)
+                       solvable.provides().add(rel)
+
+               # Import all conflicts.
+               for conf in pkg.conflicts:
+                       rel = self.create_relation(conf)
+                       solvable.conflicts().add(rel)
+
+               # Import all obsoletes.
+               for obso in pkg.obsoletes:
+                       rel = self.create_relation(obso)
+                       solvable.obsoletes().add(rel)
+
+               # Import all files that are in the package.
+               rel = self.create_relation("solvable:filemarker")
+               solvable.provides().add(rel)
+               for file in pkg.filelist:
+                       rel = self.create_relation(file)
+                       solvable.provides().add(rel)
+
+       def create_request(self):
+               return self.pool.create_request()
+
+       def solve(self, request):
+               solver = self.pool.create_solver()
+               solver.set_allow_uninstall(True)
+
+               while True:
+                       # Save start time.
+                       time_start = time.time()
+
+                       # Acutally run the solver.
+                       res = solver.solve(request)
+
+                       # Log time and status of the solver.
+                       logging.debug("Solving took %s" % (time.time() - time_start))
+                       logging.debug("Solver status: %s" % res)
+
+                       # If the solver succeeded, we return the transaction and return.
+                       if res:
+                               # Return a resulting Transaction.
+                               return Transaction.from_solver(self.pakfire, self, solver)
+
+                       # Solver had an error and we now see what we can do:
+                       logging.info("The solver returned %s problems." % solver.problems_count())
+
+                       for p in solver.problems(request):
+                               logging.info("Problem: %s" % p)
+                               for s in p.solutions():
+                                       s = "%s" % s
+                                       logging.info(s.strip())
+
+                       break
+
+       def solvables2packages(self, solvables):
+               pkgs = []
+
+               for solv in solvables:
+                       pkg = self.id2pkg[solv.id()]
+                       pkgs.append(pkg)
+
+               return pkgs
+
+       def get_by_provides(self, provides):
+               print provides
+               provides = self.create_relation(provides)
+
+               pkgs = self.solvables2packages(self.pool.providers(provides))
+
+               return pkgs
+
+       get_by_name = get_by_provides
diff --git a/pakfire/repository/transaction.py b/pakfire/repository/transaction.py
new file mode 100644 (file)
index 0000000..f1ce127
--- /dev/null
@@ -0,0 +1,341 @@
+#!/usr/bin/python
+
+import logging
+import os
+import progressbar
+import sys
+
+import pakfire.packages as packages
+import pakfire.util as util
+
+from pakfire.i18n import _
+
+PKG_DUMP_FORMAT = " %-21s %-8s %-21s %-19s %5s "
+
+class ActionError(Exception):
+       pass
+
+
+class Action(object):
+       def __init__(self, pakfire, pkg, deps=None):
+               self.pakfire = pakfire
+               self.pkg = pkg
+               self.deps = deps or []
+
+       def __cmp__(self, other):
+               # XXX ugly
+               return cmp(self.__repr__(), other.__repr__())
+
+       def __repr__(self):
+               return "<%s %s>" % (self.__class__.__name__, self.pkg.friendly_name)
+
+       def remove_dep(self, dep):
+               if not self.deps:
+                       return
+
+               while dep in self.deps:
+                       logging.debug("Removing dep %s from %s" % (dep, self))
+                       self.deps.remove(dep)
+
+       def run(self):
+               raise NotImplementedError
+
+       @property
+       def local(self):
+               """
+                       Reference to local repository (database).
+               """
+               return self.pakfire.repos.local
+
+
+class ActionCleanup(Action):
+       def gen_files(self):
+               """
+                       Return a list of all files that are not in the package anymore
+                       and so to be removed.
+               """
+               files = []
+
+               # Compare the filelist of the old and the new package and save the
+               # difference.
+
+               for f in self.pkg.old_package.filelist:
+                       if f in self.pkg.filelist:
+                               continue
+
+                       # Save absolute path.
+                       f = os.path.join(self.pakfire.path, f)
+                       files.append(f)
+
+               return files
+
+       def remove_files(self, message, files):
+               if not files:
+                       return
+
+               pb = util.make_progress(message, len(files))
+               i = 0
+
+               for f in self.gen_files():
+                       # Update progress if any.
+                       i += 1
+                       if pb:
+                               pb.update(i)
+
+                       # Skip non-existant files (mabye the user removed it already?)
+                       if not os.path.exists(f):
+                               continue
+
+                       logging.debug("Going to remove file: %s" % f)
+
+                       try:
+                               os.unlink(f)
+                       except:
+                               logging.critical("Could not remove file: %s. Do it manually." % f)
+
+                       # XXX remove file from database
+
+               if pb:
+                       pb.finish()
+
+       def run(self):
+               files = self.gen_files()
+
+               if not files:
+                       return
+
+               self.remove_files(_("Cleanup: %s") % self.pkg.name, files)
+
+
+class ActionScript(Action):
+       def run(self):
+               pass # XXX TBD
+
+
+class ActionScriptPreIn(ActionScript):
+       pass
+
+
+class ActionScriptPostIn(ActionScript):
+       pass
+
+
+class ActionScriptPreUn(ActionScript):
+       pass
+
+
+class ActionScriptPostUn(ActionScript):
+       pass
+
+
+class ActionInstall(Action):
+       type = "install"
+
+       def extract(self, message, prefix=None):
+               logging.debug("Extracting package %s" % self.pkg.friendly_name)
+
+               if prefix is None:
+                       prefix = self.pakfire.path
+
+               self.pkg.extract(message, prefix=prefix)
+
+               # Create package in the database
+               self.local.index.add_package(self.pkg)
+
+       def run(self):
+               self.extract(_("Installing: %s") % self.pkg.name)
+
+               self.pakfire.solver.add_package(self.pkg, "installed")
+
+
+class ActionUpdate(ActionInstall):
+       type = "update"
+
+       def run(self):
+               self.extract(_("Updating: %s") % self.pkg.name)
+
+
+class ActionRemove(ActionCleanup):
+       type = "remove"
+
+       def run(self):
+               files = self.pkg.filelist
+
+               if not files:
+                       return
+
+               self.remove_files(_("Removing: %s") % self.pkg.name, files)
+
+
+class Transaction(object):
+       action_classes = [
+               ActionInstall,
+               ActionUpdate,
+               ActionRemove,
+       ]
+
+       def __init__(self, pakfire):
+               self.pakfire = pakfire
+               self.actions = []
+
+               self.downloads = []
+
+       @classmethod
+       def from_solver(cls, pakfire, solver1, solver2):
+               # Grab the original transaction object from the solver.
+               _transaction = solver2.transaction()
+
+               # Order the objects in the transaction in that way we will run the
+               # installation.
+               _transaction.order()
+
+               # Create a new instance of our own transaction class.
+               transaction = cls(pakfire)
+
+               for step in _transaction.steps():
+                       action = step.type_s()
+                       pkg = solver1.id2pkg[step.solvable().id()]
+
+                       if not isinstance(pkg, packages.BinaryPackage):
+                               transaction.downloads.append(pkg)
+
+                       for action_cls in cls.action_classes:
+                               if action_cls.type == action:
+                                       action = action_cls(pakfire, pkg)
+
+                       if not isinstance(action, Action):
+                               raise Exception, "Unknown action required: %s" % action
+
+                       transaction.add_action(action)
+
+               return transaction
+
+       def download(self):
+               if not self.downloads:
+                       return
+
+               i = 0
+               for pkg in self.downloads:
+                       i += 1
+
+                       # Actually download the package.
+                       pkg_bin = pkg.download(text="(%2d/%02d): " % (i, len(self.downloads)))
+
+                       # Replace the package in all actions where it matches.
+                       actions = [a for a in self.actions if a.pkg == pkg]
+
+                       for action in actions:
+                               action.pkg = pkg_bin
+
+               # Reset packages to be downloaded.
+               self.downloads = []
+               print
+
+       @property
+       def installs(self):
+               return [a for a in self.actions if a.type == "install"]
+
+       @property
+       def removes(self):
+               return [a for a in self.actions if a.type == "remove"]
+
+       @property
+       def updates(self):
+               return [a for a in self.actions if a.type == "update"]
+
+       def dump_pkg(self, pkg):
+               ret = []
+
+               name = pkg.name
+               if len(name) > 21:
+                       ret.append(" %s" % name)
+                       name = ""
+
+               ret.append(PKG_DUMP_FORMAT % (name, pkg.arch, pkg.friendly_version,
+                       pkg.repo.name, util.format_size(pkg.size)))
+
+               return ret
+
+       def dump_pkgs(self, caption, pkgs):
+               if not pkgs:
+                       return []
+
+               s = [caption,]
+               for pkg in sorted(pkgs):
+                       s += self.dump_pkg(pkg)
+               s.append("")
+               return s
+
+       def dump(self, logger=None):
+               if not logger:
+                       logger = logging.getLogger()
+
+               width = 80
+               line = "=" * width
+
+               s = []
+               s.append(line)
+               s.append(PKG_DUMP_FORMAT % (_("Package"), _("Arch"), _("Version"), _("Repository"), _("Size")))
+               s.append(line)
+
+               s += self.dump_pkgs(_("Installing:"), [a.pkg for a in self.installs])
+               s += self.dump_pkgs(_("Updating:"), [a.pkg for a in self.updates])
+               s += self.dump_pkgs(_("Removing:"), [a.pkg for a in self.removes])
+
+               s.append(_("Transaction Summary"))
+               s.append(line)
+
+               format = "%-20s %-4d %s"
+
+               if self.installs:
+                       s.append(format % (_("Install"), len(self.installs), _("Package(s)")))
+               
+               if self.updates:
+                       s.append(format % (_("Updates"), len(self.updates), _("Package(s)")))
+               
+               if self.removes:
+                       s.append(format % (_("Remove"), len(self.removes), _("Package(s)")))
+
+               # Calculate the size of all files that need to be downloaded this this
+               # transaction.
+               download_size = sum([p.size for p in self.downloads])
+               if download_size:
+                       s.append(_("Total download size: %s") % util.format_size(download_size))
+               s.append("")
+
+               for line in s:
+                       logger.info(line)
+
+       def run_action(self, action):
+               try:
+                       action.run()
+               except ActionError, e:
+                       logging.error("Action finished with an error: %s - %s" % (action, e))
+
+       def add_action(self, action):
+               logging.debug("New action added: %s" % action)
+
+               self.actions.append(action)
+
+       def remove_action(self, action):
+               logging.debug("Removing action: %s" % action)
+
+               self.actions.remove(action)
+               for action in self.actions:
+                       action.remove_dep(action)
+
+       def run(self):
+               # Download all packages.
+               self.download()
+
+               while True:
+                       if not [a for a in self.actions]:
+                               break
+
+                       for action in self.actions:
+                               if action.deps:
+                                       #logging.debug("Skipping %s which cannot be run now." % action)
+                                       continue
+
+                               self.run_action(action)
+                               self.remove_action(action)
diff --git a/pakfire/transaction.py b/pakfire/transaction.py
deleted file mode 100644 (file)
index d2dc90b..0000000
+++ /dev/null
@@ -1,351 +0,0 @@
-#!/usr/bin/python
-
-import logging
-import os
-import progressbar
-import sys
-import tarfile
-
-import depsolve
-import packages
-import util
-
-from i18n import _
-
-class ActionError(Exception):
-       pass
-
-
-class Action(object):
-       def __init__(self, pakfire, pkg, deps=None):
-               self.pakfire = pakfire
-               self.pkg = pkg
-               self.deps = deps or []
-
-       def __cmp__(self, other):
-               # XXX ugly
-               return cmp(self.__repr__(), other.__repr__())
-
-       def __repr__(self):
-               return "<%s %s>" % (self.__class__.__name__, self.pkg.friendly_name)
-
-       def remove_dep(self, dep):
-               if not self.deps:
-                       return
-
-               while dep in self.deps:
-                       logging.debug("Removing dep %s from %s" % (dep, self))
-                       self.deps.remove(dep)
-
-       def run(self):
-               raise NotImplementedError
-
-       @property
-       def local(self):
-               """
-                       Reference to local repository (database).
-               """
-               return self.pakfire.repos.local
-
-
-class ActionCleanup(Action):
-       def gen_files(self):
-               """
-                       Return a list of all files that are not in the package anymore
-                       and so to be removed.
-               """
-               files = []
-
-               # Compare the filelist of the old and the new package and save the
-               # difference.
-
-               for f in self.pkg.old_package.filelist:
-                       if f in self.pkg.filelist:
-                               continue
-
-                       # Save absolute path.
-                       f = os.path.join(self.pakfire.path, f)
-                       files.append(f)
-
-               return files
-
-       def remove_files(self, message, files):
-               if not files:
-                       return
-
-               pb = util.make_progress(message, len(files))
-               i = 0
-
-               for f in self.gen_files():
-                       # Update progress if any.
-                       i += 1
-                       if pb:
-                               pb.update(i)
-
-                       # Skip non-existant files (mabye the user removed it already?)
-                       if not os.path.exists(f):
-                               continue
-
-                       logging.debug("Going to remove file: %s" % f)
-
-                       try:
-                               os.unlink(f)
-                       except:
-                               logging.critical("Could not remove file: %s. Do it manually." % f)
-
-                       # XXX remove file from database
-
-               if pb:
-                       pb.finish()
-
-       def run(self):
-               files = self.gen_files()
-
-               if not files:
-                       return
-
-               self.remove_files(_("Cleanup: %s") % self.pkg.name, files)
-
-
-class ActionScript(Action):
-       def run(self):
-               pass # XXX TBD
-
-
-class ActionScriptPreIn(ActionScript):
-       pass
-
-
-class ActionScriptPostIn(ActionScript):
-       pass
-
-
-class ActionScriptPreUn(ActionScript):
-       pass
-
-
-class ActionScriptPostUn(ActionScript):
-       pass
-
-
-class ActionInstall(Action):
-       def extract(self, message, prefix=None):
-               logging.debug("Extracting package %s" % self.pkg.friendly_name)
-
-               if prefix is None:
-                       prefix = self.pakfire.path
-
-               self.pkg.extract(message, prefix=prefix)
-
-               # Create package in the database
-               self.local.index.add_package(self.pkg)
-
-       def run(self):
-               self.extract(_("Installing: %s") % self.pkg.name)
-
-
-class ActionUpdate(ActionInstall):
-       def run(self):
-               self.extract(_("Updating: %s") % self.pkg.name)
-
-
-class ActionRemove(ActionCleanup):
-       def run(self):
-               files = self.pkg.filelist
-
-               if not files:
-                       return
-
-               self.remove_files(_("Removing: %s") % self.pkg.name, files)
-
-
-class TransactionSet(object):
-       def __init__(self):
-               self.installs = []
-               self.install_deps = []
-
-               self.updates = []
-               self.update_deps = []
-
-               self.removes = []
-               self.remove_deps = []
-
-       @property
-       def download_lists(self):
-               # All elements in these lists must be local.
-               return (self.installs, self.install_deps, self.updates, self.update_deps)
-
-       @property
-       def downloads(self):
-               """
-                       Return a list containing all packages that need to be downloaded.
-               """
-               pkgs = []
-               for dl_list in self.download_lists:
-                       pkgs += dl_list
-
-               pkgs.sort()
-
-               for pkg in pkgs:
-                       # Skip all packages that are already local.
-                       if pkg.local:
-                               continue
-
-                       yield pkg
-
-       def install(self, pkg, dep=False):
-               logging.info(" --> Marking package for install: %s" % pkg.friendly_name)
-
-               if dep:
-                       self.install_deps.append(pkg)
-               else:
-                       self.installs.append(pkg)
-
-       def remove(self, pkg, dep=False):
-               logging.info(" --> Marking package for remove: %s" % pkg.friendly_name)
-
-               if dep:
-                       self.remove_deps.append(pkg)
-               else:
-                       self.removes.append(pkg)
-
-       def update(self, pkg, dep=False):
-               assert pkg.old_package
-
-               logging.info(" --> Marking package for update: %s (was %s)" % \
-                       (pkg.friendly_name, pkg.old_package.friendly_version))
-
-               if dep:
-                       self.update_deps.append(pkg)
-               else:
-                       self.updates.append(pkg)
-
-       def download(self):
-               """
-                       Convert all packages to BinaryPackage.
-               """
-               pkgs = []
-               for pkg in self.downloads:
-                       pkgs.append(pkg)
-
-               # If there are no packages to download skip the rest.
-               if not pkgs:
-                       return
-
-               logging.info("Downloading packages:")
-               i = 0
-               for download in pkgs:
-                       i += 1
-                       pkg = download.download(text="(%2d/%02d): " % (i, len(pkgs)))
-
-                       for download_list in self.download_lists:
-                               if download in download_list:
-                                       download_list.remove(download)
-                                       download_list.append(pkg)
-                                       break
-
-               # Just an empty line to seperate the downloads from the extractions.
-               logging.info("")
-
-
-class Transaction(object):
-       def __init__(self, pakfire, ds):
-               self.pakfire = pakfire
-               self.ds = ds
-
-               self._actions = []
-
-       def _install_pkg(self, pkg):
-               assert isinstance(pkg, packages.BinaryPackage)
-
-               # XXX add dependencies for running the script here
-               action_prein   = ActionScriptPreIn(self.pakfire, pkg)
-
-               action_install = ActionInstall(self.pakfire, pkg, deps=[action_prein])
-
-               # XXX add dependencies for running the script here
-               action_postin  = ActionScriptPostIn(self.pakfire, pkg, deps=[action_install])
-
-               for action in (action_prein, action_install, action_postin):
-                       self.add_action(action)
-
-       def _update_pkg(self, pkg):
-               assert isinstance(pkg, packages.BinaryPackage)
-
-               action_update = ActionUpdate(self.pakfire, pkg)
-
-               action_cleanup  = ActionCleanup(self.pakfire, pkg, deps=[action_update])
-
-               for action in (action_update, action_cleanup):
-                       self.add_action(action)
-
-       def _remove_pkg(self, pkg):
-               # XXX add scripts
-               action_remove = ActionRemove(self.pakfire, pkg)
-
-               for action in (action_remove):
-                       self.add_action(action)
-
-       def populate(self):
-               # Determine which packages we have to add
-               # and which we have to remove.
-
-               # Add all packages that need to be installed.
-               for pkg in self.ds.ts.installs + self.ds.ts.install_deps:
-                       self._install_pkg(pkg)
-
-               # Add all packages that need to be updated.
-               for pkg in self.ds.ts.updates + self.ds.ts.update_deps:
-                       self._update_pkg(pkg)
-
-               # Add all packages that need to be removed.
-               for pkg in self.ds.ts.removes + self.ds.ts.remove_deps:
-                       self._remove_pkg(pkg)
-
-       def add_action(self, action):
-               logging.debug("New action added: %s" % action)
-
-               self._actions.append(action)
-
-       def remove_action(self, action):
-               logging.debug("Removing action: %s" % action)
-
-               self._actions.remove(action)
-               for _action in self.actions:
-                       _action.remove_dep(action)
-
-       @property
-       def actions(self):
-               for action in self._actions:
-                       yield action
-
-       @property
-       def packages(self):
-               for action in self._actions:
-                       yield action.pkg
-
-       def run_action(self, action):
-               try:
-                       action.run()
-               except ActionError, e:
-                       logging.error("Action finished with an error: %s - %s" % (action, e))
-
-       def run(self):
-               # Download all packages.
-               self.ds.ts.download()
-
-               # Create all the actions that need to be done.
-               self.populate()
-
-               while True:
-                       if not [a for a in self.actions]:
-                               break
-
-                       for action in self.actions:
-                               if action.deps:
-                                       #logging.debug("Skipping %s which cannot be run now." % action)
-                                       continue
-
-                               self.run_action(action)
-                               self.remove_action(action)
-
index 1a1127a0cf4272aac9c4f50b9ac3c0b1c7f9bd52..48d38bb5df363e3d013c48a78dee83c5d277e762 100644 (file)
@@ -1,36 +1,43 @@
-pakfire/base.py
-pakfire/builder.py
-pakfire/cli.py
-pakfire/config.py
-pakfire/constants.py
-pakfire/depsolve.py
+pakfire/util.py
+pakfire/api.py
 pakfire/distro.py
-pakfire/downloader.py
-pakfire/errors.py
-pakfire/i18n.py
-pakfire/__init__.py
-pakfire/logger.py
+pakfire/packages/util.py
 pakfire/packages/base.py
-pakfire/packages/binary.py
-pakfire/packages/file.py
-pakfire/packages/__init__.py
-pakfire/packages/installed.py
-pakfire/packages/listing.py
 pakfire/packages/make.py
-pakfire/packages/packager.py
+pakfire/packages/__init__.py
 pakfire/packages/source.py
-pakfire/packages/util.py
+pakfire/packages/packager.py
+pakfire/packages/file.py
+pakfire/packages/installed.py
 pakfire/packages/virtual.py
+pakfire/packages/listing.py
+pakfire/packages/binary.py
+pakfire/chroot.py
+pakfire/downloader.py
+pakfire/compress.py
+pakfire/base.py
+pakfire/i18n.py
+pakfire/__init__.py
+pakfire/server/base.py
+pakfire/server/slave.py
+pakfire/server/__init__.py
+pakfire/server/master.py
 pakfire/repository/base.py
-pakfire/repository/cache.py
 pakfire/repository/database.py
-pakfire/repository/index.py
 pakfire/repository/__init__.py
-pakfire/repository/installed.py
+pakfire/repository/solver.py
+pakfire/repository/transaction.py
 pakfire/repository/local.py
-pakfire/repository/metadata.py
-pakfire/repository/oddments.py
 pakfire/repository/remote.py
-pakfire/transaction.py
-pakfire/util.py
-scripts/pakfire
+pakfire/repository/oddments.py
+pakfire/repository/metadata.py
+pakfire/repository/installed.py
+pakfire/repository/actions.py
+pakfire/repository/cache.py
+pakfire/repository/index.py
+pakfire/config.py
+pakfire/logger.py
+pakfire/builder.py
+pakfire/cli.py
+pakfire/errors.py
+pakfire/constants.py
index b16a365c5b1639a9cc3064ecb00c2cf7308fb901..a2bb874fe8b006d333785ea98f6101ed0554910d 100644 (file)
@@ -8,7 +8,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: PACKAGE VERSION\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2011-04-23 12:44+0200\n"
+"POT-Creation-Date: 2011-04-29 21:17+0200\n"
 "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
 "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
 "Language-Team: LANGUAGE <LL@li.org>\n"
@@ -17,11 +17,152 @@ msgstr ""
 "Content-Type: text/plain; charset=CHARSET\n"
 "Content-Transfer-Encoding: 8bit\n"
 
-#: ../pakfire/base.py:106 ../pakfire/base.py:137
-msgid "Is this okay?"
+#: ../pakfire/packages/base.py:67
+msgid "Name"
+msgstr ""
+
+#: ../pakfire/packages/base.py:68 ../pakfire/repository/transaction.py:278
+msgid "Arch"
 msgstr ""
 
-#: ../pakfire/builder.py:208
+#: ../pakfire/packages/base.py:69 ../pakfire/repository/transaction.py:278
+msgid "Version"
+msgstr ""
+
+#: ../pakfire/packages/base.py:70
+msgid "Release"
+msgstr ""
+
+#: ../pakfire/packages/base.py:71 ../pakfire/repository/transaction.py:278
+msgid "Size"
+msgstr ""
+
+#: ../pakfire/packages/base.py:72
+msgid "Repo"
+msgstr ""
+
+#: ../pakfire/packages/base.py:73
+msgid "Summary"
+msgstr ""
+
+#: ../pakfire/packages/base.py:74
+msgid "Groups"
+msgstr ""
+
+#: ../pakfire/packages/base.py:75
+msgid "URL"
+msgstr ""
+
+#: ../pakfire/packages/base.py:76
+msgid "License"
+msgstr ""
+
+#: ../pakfire/packages/base.py:79
+msgid "Description"
+msgstr ""
+
+#: ../pakfire/packages/base.py:85
+msgid "UUID"
+msgstr ""
+
+#: ../pakfire/packages/base.py:86
+msgid "Build ID"
+msgstr ""
+
+#: ../pakfire/packages/base.py:87
+msgid "Build date"
+msgstr ""
+
+#: ../pakfire/packages/base.py:88
+msgid "Build host"
+msgstr ""
+
+#: ../pakfire/packages/base.py:90
+msgid "Provides"
+msgstr ""
+
+#: ../pakfire/packages/base.py:95
+msgid "Requires"
+msgstr ""
+
+#: ../pakfire/repository/solver.py:66
+#, python-format
+msgid "Loading %s"
+msgstr ""
+
+#: ../pakfire/repository/transaction.py:107
+#, python-format
+msgid "Cleanup: %s"
+msgstr ""
+
+#: ../pakfire/repository/transaction.py:146
+#, python-format
+msgid "Installing: %s"
+msgstr ""
+
+#: ../pakfire/repository/transaction.py:155
+#, python-format
+msgid "Updating: %s"
+msgstr ""
+
+#: ../pakfire/repository/transaction.py:167
+#, python-format
+msgid "Removing: %s"
+msgstr ""
+
+#: ../pakfire/repository/transaction.py:278
+msgid "Package"
+msgstr ""
+
+#: ../pakfire/repository/transaction.py:278 ../pakfire/cli.py:237
+msgid "Repository"
+msgstr ""
+
+#: ../pakfire/repository/transaction.py:281
+msgid "Installing:"
+msgstr ""
+
+#: ../pakfire/repository/transaction.py:282
+msgid "Updating:"
+msgstr ""
+
+#: ../pakfire/repository/transaction.py:283
+msgid "Removing:"
+msgstr ""
+
+#: ../pakfire/repository/transaction.py:285
+msgid "Transaction Summary"
+msgstr ""
+
+#: ../pakfire/repository/transaction.py:291
+msgid "Install"
+msgstr ""
+
+#: ../pakfire/repository/transaction.py:291
+#: ../pakfire/repository/transaction.py:294
+#: ../pakfire/repository/transaction.py:297
+msgid "Package(s)"
+msgstr ""
+
+#: ../pakfire/repository/transaction.py:294
+msgid "Updates"
+msgstr ""
+
+#: ../pakfire/repository/transaction.py:297
+msgid "Remove"
+msgstr ""
+
+#: ../pakfire/repository/transaction.py:303
+#, python-format
+msgid "Total download size: %s"
+msgstr ""
+
+#: ../pakfire/repository/index.py:335
+#, python-format
+msgid "%s: package database"
+msgstr ""
+
+#: ../pakfire/builder.py:254
 #, python-format
 msgid "Extracting: %s (source)"
 msgstr ""
@@ -123,10 +264,6 @@ msgstr ""
 msgid "List all currently enabled repositories."
 msgstr ""
 
-#: ../pakfire/cli.py:237 ../pakfire/depsolve.py:229
-msgid "Repository"
-msgstr ""
-
 #: ../pakfire/cli.py:237
 msgid "Enabled"
 msgstr ""
@@ -218,150 +355,3 @@ msgstr ""
 #: ../pakfire/cli.py:498
 msgid "Send a keepalive to the server."
 msgstr ""
-
-#: ../pakfire/depsolve.py:229
-msgid "Package"
-msgstr ""
-
-#: ../pakfire/depsolve.py:229 ../pakfire/packages/base.py:72
-msgid "Arch"
-msgstr ""
-
-#: ../pakfire/depsolve.py:229 ../pakfire/packages/base.py:73
-msgid "Version"
-msgstr ""
-
-#: ../pakfire/depsolve.py:229 ../pakfire/packages/base.py:75
-msgid "Size"
-msgstr ""
-
-#: ../pakfire/depsolve.py:232
-msgid "Installing:"
-msgstr ""
-
-#: ../pakfire/depsolve.py:233
-msgid "Installing for dependencies:"
-msgstr ""
-
-#: ../pakfire/depsolve.py:234
-msgid "Updating:"
-msgstr ""
-
-#: ../pakfire/depsolve.py:235
-msgid "Updating for dependencies:"
-msgstr ""
-
-#: ../pakfire/depsolve.py:236
-msgid "Removing:"
-msgstr ""
-
-#: ../pakfire/depsolve.py:237
-msgid "Removing for dependencies:"
-msgstr ""
-
-#: ../pakfire/depsolve.py:239
-msgid "Transaction Summary"
-msgstr ""
-
-#: ../pakfire/depsolve.py:245
-msgid "Install"
-msgstr ""
-
-#: ../pakfire/depsolve.py:246 ../pakfire/depsolve.py:250
-#: ../pakfire/depsolve.py:254
-msgid "Package(s)"
-msgstr ""
-
-#: ../pakfire/depsolve.py:249
-msgid "Updates"
-msgstr ""
-
-#: ../pakfire/depsolve.py:253
-msgid "Remove"
-msgstr ""
-
-#: ../pakfire/depsolve.py:260
-#, python-format
-msgid "Total download size: %s"
-msgstr ""
-
-#: ../pakfire/packages/base.py:71
-msgid "Name"
-msgstr ""
-
-#: ../pakfire/packages/base.py:74
-msgid "Release"
-msgstr ""
-
-#: ../pakfire/packages/base.py:76
-msgid "Repo"
-msgstr ""
-
-#: ../pakfire/packages/base.py:77
-msgid "Summary"
-msgstr ""
-
-#: ../pakfire/packages/base.py:78
-msgid "Groups"
-msgstr ""
-
-#: ../pakfire/packages/base.py:79
-msgid "URL"
-msgstr ""
-
-#: ../pakfire/packages/base.py:80
-msgid "License"
-msgstr ""
-
-#: ../pakfire/packages/base.py:83
-msgid "Description"
-msgstr ""
-
-#: ../pakfire/packages/base.py:89
-msgid "UUID"
-msgstr ""
-
-#: ../pakfire/packages/base.py:90
-msgid "Build ID"
-msgstr ""
-
-#: ../pakfire/packages/base.py:91
-msgid "Build date"
-msgstr ""
-
-#: ../pakfire/packages/base.py:92
-msgid "Build host"
-msgstr ""
-
-#: ../pakfire/packages/base.py:94
-msgid "Provides"
-msgstr ""
-
-#: ../pakfire/packages/base.py:99
-msgid "Requires"
-msgstr ""
-
-#: ../pakfire/repository/index.py:310
-#, python-format
-msgid "%s: package database"
-msgstr ""
-
-#: ../pakfire/transaction.py:107
-#, python-format
-msgid "Cleanup: %s"
-msgstr ""
-
-#: ../pakfire/transaction.py:144
-#, python-format
-msgid "Installing: %s"
-msgstr ""
-
-#: ../pakfire/transaction.py:149
-#, python-format
-msgid "Updating: %s"
-msgstr ""
-
-#: ../pakfire/transaction.py:159
-#, python-format
-msgid "Removing: %s"
-msgstr ""