# try to solve it.
request = self.solver.create_request()
for solvable in repo:
- print solvable
request.install(solvable)
t = self.solver.solve(request)
if isinstance(req, packages.BinaryPackage):
req = req.friendly_name
- req = self.solver.create_relation(req)
+ if "<" in req or ">" in req or "=" in req:
+ req = self.solver.create_relation(req)
request.install(req)
# Do the solving.
- transaction = self.solver.solve(request)
+ transaction = self.solver.solve(request, allow_downgrade=True)
+
+ # XXX check for errors
# Show the user what is going to be done.
transaction.dump(logger=self.log)
transaction.run()
def install_test(self):
+ # XXX currently disabled
+ return
+
pkgs = []
for dir, subdirs, files in os.walk(self.chrootPath("result")):
for file in files:
#!/usr/bin/python
import logging
+import xml.sax.saxutils
import util
"maintainer" : self.maintainer,
"url" : self.url,
"license" : self.license,
+ "hash1" : self.hash1,
+ "vendor" : self.vendor,
+ "build_host" : self.build_host,
+ "build_time" : self.build_time,
+ "size" : self.size,
+ "inst_size" : self.inst_size,
}
return info
+ @property
+ def hash1(self):
+ return "0"*40
+
@property
def size(self):
"""
"""
return 0
+ @property
+ def inst_size(self):
+ # XXX to be done
+ return 0
+
@property
def local(self):
"""
@property
def build_host(self):
- return self.metadata.get("BUILD_HOST")
+ host = self.metadata.get("BUILD_HOST")
+
+ # XXX Workaround tripple X as hostname.
+ if host == "X"*3:
+ host = ""
+
+ return host
@property
def build_id(self):
def vendor(self):
return self.metadata.get("PKG_VENDOR", "")
+ @property
+ def pre_requires(self):
+ return set() # XXX to be done
+
@property
def requires(self):
ret = ""
return set(provides)
+ @property
+ def conflicts(self):
+ conflicts = self.metadata.get("PKG_CONFLICTS", "").split()
+
+ return set(conflicts)
+
@property
def obsoletes(self):
obsoletes = self.metadata.get("PKG_OBSOLETES", "").split()
return set(obsoletes)
def extract(self, path, prefix=None):
- raise NotImplementedError, "%s" % type(self)
+ raise NotImplementedError, "%s" % repr(self)
+
+ def export_xml_string(self):
+ info = self.info
+ info["groups"] = " ".join(info["groups"])
+
+ # Escape everything to conform to XML.
+ for key, value in info.items():
+ if not type(value) in (type(a) for a in ("a", u"a")):
+ continue
+
+ info[key] = xml.sax.saxutils.escape(value, {'"': """})
+
+ s = """\
+ <package type="rpm">
+ <name>%(name)s</name>
+ <arch>%(arch)s</arch>
+ <version epoch="%(epoch)s" ver="%(version)s" rel="%(release)s"/>
+ <checksum type="sha" pkgid="YES">%(hash1)s</checksum>
+ <summary>%(summary)s</summary>
+ <description>%(description)s</description>
+ <packager>%(maintainer)s</packager>
+ <url>%(url)s</url>
+ <time file="0" build="%(build_time)s"/>
+ <size package="%(size)s" installed="%(inst_size)s" />
+ <format>
+ <rpm:license>%(license)s</rpm:license>
+ <rpm:vendor>%(vendor)s</rpm:vendor>
+ <rpm:group>%(groups)s</rpm:group>
+ <rpm:buildhost>%(build_host)s</rpm:buildhost>\n""" \
+ % info
+
+ if self.provides:
+ s += "<rpm:provides>"
+ for provides in self.provides:
+ s += "<rpm:entry name=\"%s\" />" % provides
+ s += "</rpm:provides>"
+
+ if self.requires or self.pre_requires:
+ s += "<rpm:requires>"
+ for requires in self.requires:
+ s += "<rpm:entry name=\"%s\" />" % requires
+
+ for requires in self.pre_requires:
+ s += "<rpm:entry name=\"%s\" pre=\"1\" />" % requires
+ s += "</rpm:requires>"
+
+ if self.conflicts:
+ s += "<rpm:conflicts>"
+ for conflict in self.conflicts:
+ s += "<rpm:entry name=\"%s\" />" % conflict
+ s += "</rpm:conflicts>"
+
+ if self.obsoletes:
+ s += "<rpm:obsoletes>"
+ for obsolete in self.obsoletes:
+ s += "<rpm:entry name=\"%s\" />" % obsolete
+ s += "</rpm:obsoletes>"
+
+ for file in self.filelist:
+ # XXX what about type="dir"?
+ s += "<file>%s</file>" % file
+
+ s += "</format></package>"
+ return s
# Remove triple X placeholder that was used some time.
if comp == "X"*3:
- comp = None
+ return None
- return comp
+ return comp or "xz"
@property
def signature(self):
Downloads the package from repository and returns a new instance
of BinaryPackage.
"""
+
+ # XXX a bit hacky, but InstalledRepository has no cache.
+ if self.repo.name == "installed":
+ return self
+
# Marker, if we need to download the package.
download = True
import fnmatch
import glob
+import logging
+import re
class RepositoryFactory(object):
def __init__(self, pakfire, name, description):
# All repositories are enabled by default
self.enabled = True
+ # Reference to corresponding Repo object in the solver.
+ self.solver_repo = None
+
def __repr__(self):
return "<%s %s>" % (self.__class__.__name__, self.name)
if pkg.name == name:
yield pkg
+ def get_by_evr(self, name, evr):
+ m = re.match(r"([0-9]+\:)?([0-9A-Za-z\.\-]+)-([0-9]+\.?[a-z0-9]+|[0-9]+)", evr)
+
+ if not m:
+ raise Exception, "Invalid input: %s" % evr
+
+ (epoch, version, release) = m.groups()
+ if epoch and epoch.endswith(":"):
+ epoch = epoch[:-1]
+
+ pkgs = [p for p in self.index.get_by_evr(name, epoch, version, release)]
+
+ if not pkgs:
+ return
+
+ if not len(pkgs) == 1:
+ raise Exception
+
+ return pkgs[0]
+
def get_by_glob(self, pattern):
"""
Returns a list of all packages that names match the glob pattern
return self.index.filelist
return {}
+
+ def import_to_solver(self, solver, repo):
+ if hasattr(self, "index"):
+ self.solver_repo = repo
+
+ self.index.import_to_solver(solver, repo)
import os
import random
import shutil
+import subprocess
import time
import database
if match:
yield pkg
+ def get_by_evr(self, name, epoch, version, release):
+ try:
+ epoch = int(epoch)
+ except TypeError:
+ epoch = 0
+
+ for pkg in self.packages:
+ if pkg.type == "source":
+ continue
+
+ if pkg.name == name and pkg.epoch == epoch \
+ and pkg.version == version and pkg.release == release:
+ yield pkg
+
def get_by_id(self, id):
raise NotImplementedError
def add_package(self, pkg):
raise NotImplementedError
+ @property
+ def cachefile(self):
+ return None
+
+ def import_to_solver(self, solver, repo):
+ if self.cachefile:
+ if not os.path.exists(self.cachefile):
+ self.create_solver_cache()
+
+ logging.debug("Importing repository cache data from %s" % self.cachefile)
+ repo.add_solv(self.cachefile)
+
+ else:
+ for pkg in self.packages:
+ solver.add_package(pkg, repo.name())
+
+ logging.debug("Initialized new repo '%s' with %s packages." % \
+ (repo.name(), repo.size()))
+
+ def create_solver_cache(self):
+ cachedir = os.path.dirname(self.cachefile)
+ if not os.path.exists(cachedir):
+ os.makedirs(cachedir)
+
+ f = open(self.cachefile, "w")
+
+ # Write metadata header.
+ xml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
+ xml += "<metadata xmlns=\"http://linux.duke.edu/metadata/common\""
+ xml += " xmlns:rpm=\"http://linux.duke.edu/metadata/rpm\">\n"
+
+ # We dump an XML string for every package in this repository and
+ # write it to the XML file.
+ for pkg in self.packages:
+ xml += pkg.export_xml_string()
+
+ # Write footer.
+ xml += "</metadata>"
+
+ p = subprocess.Popen("rpmmd2solv", stdin=subprocess.PIPE,
+ stdout=subprocess.PIPE)
+ stdout, stderr = p.communicate(xml)
+
+ f.write(stdout)
+ f.close()
+
class DirectoryIndex(Index):
def __init__(self, pakfire, repo, path):
return files
+
class InstalledIndex(DatabaseIndexFactory):
def open_database(self):
# Open the local package database.
# XXX this code needs lots of work:
# XXX * check the metadata content
+
+ @property
+ def cachefile(self):
+ return "%s.cache" % self.db.filename
from base import RepositoryFactory
class RemoteRepository(RepositoryFactory):
+ cacheable = True
+
def __init__(self, pakfire, name, description, url, mirrorlist, gpgkey, enabled):
RepositoryFactory.__init__(self, pakfire, name, description)
return priority
- def update(self, force=False):
- if self.index:
- self.index.update(force=force)
+ #def update(self, force=False):
+ # if self.index:
+ # self.index.update(force=force)
def _replace_from_cache(self, pkg):
for _pkg in self.cache.packages:
self.pool.set_arch(arch)
# Initialize all repositories.
- self.repos = self.init_repos()
+ for repo in self.repos.enabled:
+ self.init_repo(repo)
+
+# self.init_repos()
self.pool.prepare()
+ logging.debug("Solver pool has %s solvables." % self.pool.size())
+
+ def create_repo(self, *args, **kwargs):
+ return self.pool.create_repo(*args, **kwargs)
+
def create_relation(self, s):
s = str(s)
return satsolver.Relation(self.pool, s)
- def init_repos(self):
- repos = []
+ def init_repo(self, repo):
+ solvrepo = self.pool.create_repo(repo.name)
+ if repo.name == "installed":
+ self.pool.set_installed(solvrepo)
- for repo in self.repos.enabled:
- solvrepo = self.pool.create_repo(repo.name)
- if repo.name == "installed":
- self.pool.set_installed(solvrepo)
+ repo.import_to_solver(self, solvrepo)
+ return
- pb = util.make_progress(_("Loading %s") % repo.name, repo.size)
- i = 0
+ # XXX dead code
+ 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
+
+ # Let's see if this repository has a cache and use it if possible.
+ cachefile = repo.metadata_cachefile
+ print cachefile
+ if cachefile and os.path.exists(cachefile):
+ solvrepo.add_solv(cachefile)
+
+ else:
for pkg in repo.get_all():
if pb:
i += 1
self.add_package(pkg)
- logging.debug("Initialized new repo '%s' with %s packages." % \
- (solvrepo.name(), solvrepo.size()))
+ logging.debug("Initialized new repo '%s' with %s packages." % \
+ (solvrepo.name(), solvrepo.size()))
- if pb:
- pb.finish()
+ if pb:
+ pb.finish()
- repos.append(solvrepo)
+ repos.append(solvrepo)
- return repos
-
- def get_repo(self, name):
- for repo in self.pool.repos():
- if not repo.name() == name:
- continue
+ def add_package(self, pkg, reponame):
+ repo = self.repos.get_repo_by_name(reponame)
- 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),
+ solvable = satsolver.Solvable(repo.solver_repo, 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)
def create_request(self):
return self.pool.create_request()
- def solve(self, request, update=False, interactive=False):
+ def solve(self, request, update=False, allow_downgrade=False, interactive=False):
solver = self.pool.create_solver()
#solver.set_allow_uninstall(True)
+ solver.set_allow_downgrade(allow_downgrade)
+
# Configure the solver for an update.
if update:
solver.set_update_system(True)
# Solver had an error and we now see what we can do:
logging.info("The solver returned %s problems." % solver.problems_count())
- # XXX everything after this line is totally broken and does not do its
- # job correctly.
- return
-
jobactions = {
satsolver.INSTALL_SOLVABLE : "install",
satsolver.UPDATE_SOLVABLE : "update",
if not interactive:
continue
+ continue # XXX
+
logging.info(" - %s -" % _("Empty to abort."))
while True:
raise Exception, "Unknown action called."
break
- def solvables2packages(self, solvables):
- pkgs = []
+ def solv2pkg(self, solv):
+ repo = self.repos.get_repo_by_name(solv.repo().name())
- for solv in solvables:
- pkg = self.id2pkg[solv.id()]
- pkgs.append(pkg)
-
- return pkgs
+ return repo.get_by_evr(solv.name(), solv.evr())
def get_by_provides(self, provides):
- print provides
provides = self.create_relation(provides)
pkgs = self.solvables2packages(self.pool.providers(provides))
logging.debug("Removing dep %s from %s" % (dep, self))
self.deps.remove(dep)
+ @property
+ def needs_download(self):
+ return self.type in ("install", "reinstall", "update", "downgrade",) \
+ and not isinstance(self.pkg, packages.BinaryPackage)
+
+ def download(self, text):
+ if not self.needs_download:
+ return
+
+ self.pkg = self.pkg.download(text)
+
def run(self):
raise NotImplementedError
self.local.index.add_package(self.pkg)
def run(self):
- self.extract(_("Installing: %s") % self.pkg.name)
+ msg = _("Extracting: %s")
+
+ if self.type == "install":
+ msg = _("Installing: %s")
+ elif self.type == "reinstall":
+ msg = _("Reinstalling: %s")
+ elif self.type == "update":
+ msg = _("Updating: %s")
+ elif self.type == "downgrade":
+ msg = _("Downgrading: %s")
+
+ self.extract(msg % self.pkg.name)
self.pakfire.solver.add_package(self.pkg, "installed")
class ActionUpdate(ActionInstall):
type = "upgrade"
- def run(self):
- self.extract(_("Updating: %s") % self.pkg.name)
-
-
class ActionRemove(ActionCleanup):
type = "erase"
self.remove_files(_("Removing: %s") % self.pkg.name, files)
+class ActionReinstall(ActionInstall):
+ type = "reinstall"
+
+
+class ActionDowngrade(ActionInstall):
+ type = "downgrade"
+
+
class Transaction(object):
action_classes = [
ActionInstall,
ActionUpdate,
ActionRemove,
ActionCleanup,
+ ActionReinstall,
+ ActionDowngrade,
]
def __init__(self, pakfire):
self.pakfire = pakfire
self.actions = []
- self.downloads = []
-
- self.installs = []
- self.updates = []
- self.removes = []
-
@classmethod
def from_solver(cls, pakfire, solver1, solver2):
# Grab the original transaction object from the solver.
# Create a new instance of our own transaction class.
transaction = cls(pakfire)
- # Copy all information.
- transaction.installs = solver1.solvables2packages(solver2.installs())
- transaction.updates = \
- [p for p in solver1.solvables2packages(solver2.updates()) if not p.repo.name == "installed"]
- transaction.removes = solver1.solvables2packages(solver2.removes())
-
for step in _transaction.steps():
action = step.type_s(satsolver.TRANSACTION_MODE_ACTIVE)
- pkg = solver1.id2pkg[step.solvable().id()]
+ pkg = solver1.solv2pkg(step.solvable())
- if action in ("install", "upgrade") and not isinstance(pkg, packages.BinaryPackage):
+ if action in ("install", "reinstall", "upgrade") and \
+ not isinstance(pkg, packages.BinaryPackage):
transaction.downloads.append(pkg)
for action_cls in cls.action_classes:
transaction.add_action(action)
+ print transaction.actions
return transaction
- def download(self):
- if not self.downloads:
- return
+ @property
+ def installs(self):
+ return [a.pkg for a in self.actions if isinstance(a, ActionInstall)]
- i = 0
- for pkg in self.downloads:
- i += 1
+ @property
+ def reinstalls(self):
+ return [a.pkg for a in self.actions if isinstance(a, ActionReinstall)]
- # Actually download the package.
- pkg_bin = pkg.download(text="(%2d/%02d): " % (i, len(self.downloads)))
+ @property
+ def removes(self):
+ return [a.pkg for a in self.actions if isinstance(a, ActionRemove)]
- # Replace the package in all actions where it matches.
- actions = [a for a in self.actions if a.pkg == pkg]
+ @property
+ def updates(self):
+ return [a.pkg for a in self.actions if isinstance(a, ActionUpdate)]
- for action in actions:
- action.pkg = pkg_bin
+ @property
+ def downgrades(self):
+ return [a.pkg for a in self.actions if isinstance(a, ActionDowngrade)]
- # Reset packages to be downloaded.
- self.downloads = []
- print
+ @property
+ def downloads(self):
+ return [a for a in self.actions if a.needs_download]
+
+ def download(self):
+ downloads = self.downloads
+
+ i = 0
+ for action in self.actions:
+ i += 1
+
+ action.download(text="(%02d/%02d): " % (i, len(downloads)))
def dump_pkg(self, pkg):
ret = []
width = 80
line = "=" * width
- s = []
+ s = [""]
s.append(line)
s.append(PKG_DUMP_FORMAT % (_("Package"), _("Arch"), _("Version"), _("Repository"), _("Size")))
s.append(line)
- s += self.dump_pkgs(_("Installing:"), self.installs)
- s += self.dump_pkgs(_("Updating:"), self.updates)
- s += self.dump_pkgs(_("Removing:"), self.removes)
+ actions = (
+ (_("Installing:"), self.installs),
+ (_("Reinstalling:"), self.reinstalls),
+ (_("Updating:"), self.updates),
+ (_("Downgrading:"), self.downgrades),
+ (_("Removing:"), self.removes),
+ )
+
+ for caption, pkgs in actions:
+ s += self.dump_pkgs(caption, pkgs)
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)")))
+ for caption, pkgs in actions:
+ if not len(pkgs):
+ continue
+ s.append(format % (caption, len(pkgs), _("package", "packages", len(pkgs))))
# Calculate the size of all files that need to be downloaded this this
# transaction.
- download_size = sum([p.size for p in self.downloads])
+ download_size = sum([a.pkg.size for a in self.downloads])
if download_size:
s.append(_("Total download size: %s") % util.format_size(download_size))
s.append("")
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2011-05-19 12:48+0200\n"
+"POT-Creation-Date: 2011-05-21 17:16+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"
msgid "%s [y/N]"
msgstr ""
-#: ../pakfire/packages/base.py:67
+#: ../pakfire/packages/base.py:68
msgid "Name"
msgstr ""
-#: ../pakfire/packages/base.py:68 ../pakfire/repository/transaction.py:226
+#: ../pakfire/packages/base.py:69 ../pakfire/repository/transaction.py:256
msgid "Arch"
msgstr ""
-#: ../pakfire/packages/base.py:69 ../pakfire/repository/transaction.py:226
+#: ../pakfire/packages/base.py:70 ../pakfire/repository/transaction.py:256
msgid "Version"
msgstr ""
-#: ../pakfire/packages/base.py:70
+#: ../pakfire/packages/base.py:71
msgid "Release"
msgstr ""
-#: ../pakfire/packages/base.py:71 ../pakfire/repository/transaction.py:226
+#: ../pakfire/packages/base.py:72 ../pakfire/repository/transaction.py:256
msgid "Size"
msgstr ""
-#: ../pakfire/packages/base.py:72
+#: ../pakfire/packages/base.py:73
msgid "Repo"
msgstr ""
-#: ../pakfire/packages/base.py:73
+#: ../pakfire/packages/base.py:74
msgid "Summary"
msgstr ""
-#: ../pakfire/packages/base.py:74
+#: ../pakfire/packages/base.py:75
msgid "Groups"
msgstr ""
-#: ../pakfire/packages/base.py:75
+#: ../pakfire/packages/base.py:76
msgid "URL"
msgstr ""
-#: ../pakfire/packages/base.py:76
+#: ../pakfire/packages/base.py:77
msgid "License"
msgstr ""
-#: ../pakfire/packages/base.py:79
+#: ../pakfire/packages/base.py:80
msgid "Description"
msgstr ""
-#: ../pakfire/packages/base.py:85
+#: ../pakfire/packages/base.py:86
msgid "UUID"
msgstr ""
-#: ../pakfire/packages/base.py:86
+#: ../pakfire/packages/base.py:87
msgid "Build ID"
msgstr ""
-#: ../pakfire/packages/base.py:87
+#: ../pakfire/packages/base.py:88
msgid "Build date"
msgstr ""
-#: ../pakfire/packages/base.py:88
+#: ../pakfire/packages/base.py:89
msgid "Build host"
msgstr ""
-#: ../pakfire/packages/base.py:90
+#: ../pakfire/packages/base.py:91
msgid "Provides"
msgstr ""
-#: ../pakfire/packages/base.py:95
+#: ../pakfire/packages/base.py:96
msgid "Requires"
msgstr ""
-#: ../pakfire/repository/solver.py:66
+#: ../pakfire/repository/solver.py:80
#, python-format
msgid "Loading %s"
msgstr ""
-#: ../pakfire/repository/solver.py:197
+#. XXX
+#: ../pakfire/repository/solver.py:202
msgid "Empty to abort."
msgstr ""
-#: ../pakfire/repository/solver.py:200
+#: ../pakfire/repository/solver.py:205
msgid "Choose a solution:"
msgstr ""
-#: ../pakfire/repository/solver.py:216
+#: ../pakfire/repository/solver.py:221
msgid "You have entered an invalid solution. Try again."
msgstr ""
-#: ../pakfire/repository/transaction.py:95
+#: ../pakfire/repository/transaction.py:106
+#, python-format
+msgid "Extracting: %s"
+msgstr ""
+
+#: ../pakfire/repository/transaction.py:109
#, python-format
msgid "Installing: %s"
msgstr ""
-#: ../pakfire/repository/transaction.py:104
+#: ../pakfire/repository/transaction.py:111
+#, python-format
+msgid "Reinstalling: %s"
+msgstr ""
+
+#: ../pakfire/repository/transaction.py:113
#, python-format
msgid "Updating: %s"
msgstr ""
-#: ../pakfire/repository/transaction.py:116
+#: ../pakfire/repository/transaction.py:115
+#, python-format
+msgid "Downgrading: %s"
+msgstr ""
+
+#: ../pakfire/repository/transaction.py:134
#, python-format
msgid "Removing: %s"
msgstr ""
-#: ../pakfire/repository/transaction.py:226
+#: ../pakfire/repository/transaction.py:256
msgid "Package"
msgstr ""
-#: ../pakfire/repository/transaction.py:226 ../pakfire/cli.py:223
+#: ../pakfire/repository/transaction.py:256 ../pakfire/cli.py:223
msgid "Repository"
msgstr ""
-#: ../pakfire/repository/transaction.py:229
+#: ../pakfire/repository/transaction.py:260
msgid "Installing:"
msgstr ""
-#: ../pakfire/repository/transaction.py:230
-msgid "Updating:"
-msgstr ""
-
-#: ../pakfire/repository/transaction.py:231
-msgid "Removing:"
+#: ../pakfire/repository/transaction.py:261
+msgid "Reinstalling:"
msgstr ""
-#: ../pakfire/repository/transaction.py:233
-msgid "Transaction Summary"
+#: ../pakfire/repository/transaction.py:262
+msgid "Updating:"
msgstr ""
-#: ../pakfire/repository/transaction.py:239
-msgid "Install"
+#: ../pakfire/repository/transaction.py:263
+msgid "Downgrading:"
msgstr ""
-#: ../pakfire/repository/transaction.py:239
-#: ../pakfire/repository/transaction.py:242
-#: ../pakfire/repository/transaction.py:245
-msgid "Package(s)"
+#: ../pakfire/repository/transaction.py:264
+msgid "Removing:"
msgstr ""
-#: ../pakfire/repository/transaction.py:242
-msgid "Updates"
+#: ../pakfire/repository/transaction.py:270
+msgid "Transaction Summary"
msgstr ""
-#: ../pakfire/repository/transaction.py:245
-msgid "Remove"
+#: ../pakfire/repository/transaction.py:278
+msgid "package"
msgstr ""
-#: ../pakfire/repository/transaction.py:251
+#: ../pakfire/repository/transaction.py:284
#, python-format
msgid "Total download size: %s"
msgstr ""
-#: ../pakfire/repository/transaction.py:260
+#: ../pakfire/repository/transaction.py:293
msgid "Is this okay?"
msgstr ""
-#: ../pakfire/repository/index.py:335
+#: ../pakfire/repository/index.py:397
#, python-format
msgid "%s: package database"
msgstr ""