[PackageKit-commit] packagekit: Branch 'master' - 73 commits

Richard Hughes hughsient at kemper.freedesktop.org
Sun Sep 28 01:08:35 PDT 2008


 backends/apt.deprecated/aptBackend.py                |  536 +++++++
 backends/apt.deprecated/helpers/.gitignore           |    1 
 backends/apt.deprecated/helpers/Makefile.am          |   29 
 backends/apt.deprecated/helpers/aptBackend.py        |  536 -------
 backends/apt.deprecated/helpers/get-depends.py       |   20 
 backends/apt.deprecated/helpers/get-details.py       |   18 
 backends/apt.deprecated/helpers/get-repo-list.py     |   20 
 backends/apt.deprecated/helpers/get-requires.py      |   20 
 backends/apt.deprecated/helpers/get-update-detail.py |   18 
 backends/apt.deprecated/helpers/get-updates.py       |   19 
 backends/apt.deprecated/helpers/install-files.py     |   21 
 backends/apt.deprecated/helpers/packagekit           |    1 
 backends/apt.deprecated/helpers/refresh-cache.py     |   17 
 backends/apt.deprecated/helpers/repo-enable.py       |   20 
 backends/apt.deprecated/helpers/resolve.py           |   20 
 backends/apt.deprecated/helpers/search-details.py    |   21 
 backends/apt.deprecated/helpers/search-file.py       |   21 
 backends/apt.deprecated/helpers/search-group.py      |   21 
 backends/apt.deprecated/helpers/search-name.py       |   21 
 backends/apt.deprecated/packagekit                   |    1 
 backends/apt.deprecated/pk-backend-apt.c             |   26 
 backends/apt/aptDBUSBackend.py                       |  285 +++-
 backends/apt/pk-backend-apt.c                        |   37 
 backends/apt/test.py                                 |  257 ++-
 backends/conary/.gitignore                           |    2 
 backends/conary/Makefile.am                          |   13 
 backends/conary/conaryBackend.py                     |  987 ++++++++++++++
 backends/conary/conaryCallback.py                    |  124 +
 backends/conary/conaryFilter.py                      |   40 
 backends/conary/helpers/Makefile.am                  |   30 
 backends/conary/helpers/conaryBackend.py             |  981 --------------
 backends/conary/helpers/conaryCallback.py            |  115 -
 backends/conary/helpers/get-depends.py               |   19 
 backends/conary/helpers/get-details.py               |   18 
 backends/conary/helpers/get-files.py                 |   18 
 backends/conary/helpers/get-repo-list.py             |   19 
 backends/conary/helpers/get-requires.py              |   19 
 backends/conary/helpers/get-update-detail.py         |   18 
 backends/conary/helpers/get-updates.py               |   19 
 backends/conary/helpers/install-packages.py          |   18 
 backends/conary/helpers/packagekit                   |    1 
 backends/conary/helpers/refresh-cache.py             |   17 
 backends/conary/helpers/remove-packages.py           |   19 
 backends/conary/helpers/repo-enable.py               |   19 
 backends/conary/helpers/repo-set-data.py             |   20 
 backends/conary/helpers/resolve.py                   |   19 
 backends/conary/helpers/search-details.py            |   81 -
 backends/conary/helpers/search-group.py              |   21 
 backends/conary/helpers/search-name.py               |   21 
 backends/conary/helpers/update-packages.py           |   18 
 backends/conary/helpers/update-system.py             |   17 
 backends/conary/packagekit                           |    1 
 backends/conary/pk-backend-conary.c                  |   39 
 backends/pisi/.gitignore                             |    2 
 backends/pisi/Makefile.am                            |   11 
 backends/pisi/helpers/Makefile.am                    |   32 
 backends/pisi/helpers/get-depends.py                 |   19 
 backends/pisi/helpers/get-details.py                 |   19 
 backends/pisi/helpers/get-files.py                   |   19 
 backends/pisi/helpers/get-repo-list.py               |   19 
 backends/pisi/helpers/get-requires.py                |   19 
 backends/pisi/helpers/get-updates.py                 |   21 
 backends/pisi/helpers/install-files.py               |   22 
 backends/pisi/helpers/install-packages.py            |   19 
 backends/pisi/helpers/pisiBackend.py                 |  414 ------
 backends/pisi/helpers/refresh-cache.py               |   19 
 backends/pisi/helpers/remove-packages.py             |   19 
 backends/pisi/helpers/repo-set-data.py               |   19 
 backends/pisi/helpers/resolve.py                     |   19 
 backends/pisi/helpers/search-details.py              |   19 
 backends/pisi/helpers/search-file.py                 |   19 
 backends/pisi/helpers/search-group.py                |   19 
 backends/pisi/helpers/search-name.py                 |   19 
 backends/pisi/helpers/update-packages.py             |   19 
 backends/pisi/helpers/update-system.py               |   19 
 backends/pisi/packagekit                             |    1 
 backends/pisi/pisiBackend.py                         |  422 ++++++
 backends/pisi/pk-backend-pisi.c                      |   54 
 backends/razor/pk-backend-razor.c                    |    2 
 backends/smart/Makefile.am                           |    9 
 backends/smart/helpers/.gitignore                    |    1 
 backends/smart/helpers/Makefile.am                   |   36 
 backends/smart/helpers/download-packages.py          |   22 
 backends/smart/helpers/get-depends.py                |   22 
 backends/smart/helpers/get-details.py                |   20 
 backends/smart/helpers/get-files.py                  |   19 
 backends/smart/helpers/get-packages.py               |   21 
 backends/smart/helpers/get-repo-list.py              |   20 
 backends/smart/helpers/get-requires.py               |   22 
 backends/smart/helpers/get-update-detail.py          |   20 
 backends/smart/helpers/get-updates.py                |   21 
 backends/smart/helpers/install-files.py              |   21 
 backends/smart/helpers/install-packages.py           |   20 
 backends/smart/helpers/packagekit                    |    1 
 backends/smart/helpers/refresh-cache.py              |   19 
 backends/smart/helpers/remove-packages.py            |   22 
 backends/smart/helpers/repo-enable.py                |   21 
 backends/smart/helpers/repo-set-data.py              |   22 
 backends/smart/helpers/resolve.py                    |   21 
 backends/smart/helpers/search-details.py             |   22 
 backends/smart/helpers/search-file.py                |   22 
 backends/smart/helpers/search-group.py               |   22 
 backends/smart/helpers/search-name.py                |   19 
 backends/smart/helpers/smartBackend.py               | 1306 -------------------
 backends/smart/helpers/update-packages.py            |   20 
 backends/smart/helpers/update-system.py              |   19 
 backends/smart/helpers/what-provides.py              |   23 
 backends/smart/pk-backend-smart.c                    |   27 
 backends/smart/smartBackend.py                       | 1306 +++++++++++++++++++
 backends/urpmi/helpers/urpmi-dispatched-backend.pl   |    4 
 backends/urpmi/pk-backend-urpmi.c                    |   18 
 backends/yum/pk-backend-yum.c                        |   23 
 backends/yum/yumBackend.py                           |  499 +++----
 backends/yum/yumComps.py                             |   22 
 backends/yum/yumFilter.py                            |  238 +--
 backends/zypp/pk-backend-zypp.cpp                    |   14 
 backends/zypp/zypp-utils.cpp                         |    5 
 configure.ac                                         |   29 
 contrib/Makefile.am                                  |    4 
 contrib/PackageKit.spec.in                           |   31 
 contrib/gstreamer-plugin/.gitignore                  |    5 
 contrib/gstreamer-plugin/Makefile.am                 |   38 
 contrib/gstreamer-plugin/pk-gstreamer-install.c      |  367 +++++
 contrib/gstreamer-plugin/test.sh                     |    2 
 data/tests/Makefile.am                               |    1 
 libpackagekit/pk-catalog.c                           |   14 
 libpackagekit/pk-client.c                            |   30 
 libpackagekit/pk-common.c                            |  108 -
 libpackagekit/pk-common.h                            |    3 
 libpackagekit/pk-control.c                           |   23 
 libpackagekit/pk-package-ids.c                       |   49 
 libpackagekit/pk-package-ids.h                       |   16 
 libpackagekit/pk-task-list.c                         |   13 
 po/ms.po                                             |  488 +++++++
 po/pl.po                                             |  164 +-
 python/packagekit/Makefile.am                        |    3 
 python/packagekit/backend.py                         |   27 
 python/packagekit/daemonBackend.py                   |    6 
 python/packagekit/filter.py                          |  145 ++
 python/packagekit/misc.py                            |   78 -
 python/packagekit/pylint.sh                          |    2 
 src/pk-backend-spawn.h                               |    2 
 src/pk-backend.c                                     |    4 
 src/pk-interface-transaction.xml                     |   10 
 src/pk-transaction-list.c                            |   74 +
 src/pk-transaction.c                                 |  175 +-
 146 files changed, 5896 insertions(+), 6008 deletions(-)

New commits:
commit 76d8dc81ff747f194605fb2e90d23aaf6471e150
Author: Tim Lauridsen <timlau at fedoraproject.org>
Date:   Sun Sep 28 07:56:35 2008 +0200

    python API: add the right type to obj vars and add name,ver,arch,repoid vars to the Package object

diff --git a/python/packagekit/misc.py b/python/packagekit/misc.py
index 274503d..f6950f2 100644
--- a/python/packagekit/misc.py
+++ b/python/packagekit/misc.py
@@ -20,6 +20,11 @@
 #     Tim Lauridsen <timlau at fedoraproject.org>
 
 # Misc classes and funtions
+def _to_unicode( txt, encoding='utf-8'):
+    if isinstance(txt, basestring):
+        if not isinstance(txt, unicode):
+            txt = unicode(txt, encoding, errors='replace')
+    return txt
 
 class PackageKitPackage:
     '''
@@ -28,13 +33,19 @@ class PackageKitPackage:
     def __init__(self, info, package_id, summary):
         self.installed = (info == 'installed')
         self.id = str(package_id)
+        self.summary = _to_unicode(summary)
+        n,v,a,r = self.id.split(';')
+        self.name = n
+        self.ver = v
+        self.arch = a
+        self.repoid = r
         self.summary = unicode(summary)
         self.info = str(info)
 
     def __str__(self):
         (name, ver, arch, repo) = tuple(self.id.split(";"))
         p =  "%s-%s.%s" % (name, ver, arch)
-        return "%-40s : %s : %s" % (p, self.info, self.summary)
+        return p
 
 class PackageKitDistroUpgrade:
     '''
@@ -42,8 +53,8 @@ class PackageKitDistroUpgrade:
     '''
     def __init__(self, upgrade_type, name, summary):
         self.upgrade_type = upgrade_type
-        self.name = name
-        self.summary = (summary)
+        self.name = str(name)
+        self.summary = _to_unicode(summary)
 
     def __str__(self):
         return " type : %s, name : %s, summary : %s " % (
@@ -55,11 +66,11 @@ class PackageKitDetails:
     '''
     def __init__(self, package_id, package_license, group, detail, url, size):
         self.id = str(package_id)
-        self.license = package_license
-        self.group = group
-        self.detail = unicode(detail)
-        self.url = url
-        self.size = size
+        self.license = str(package_license)
+        self.group = str(group)
+        self.detail = _to_unicode(detail)
+        self.url = str(url)
+        self.size = int(size)
 
 class PackageKitUpdateDetails:
     '''
@@ -69,26 +80,26 @@ class PackageKitUpdateDetails:
                  cve_url, restart, update_text, changelog, state, \
                  issued, updated):
         self.id = str(package_id)
-        self.updates = updates
-        self.obsoletes = obsoletes
-        self.vendor_url = vendor_url
-        self.bugzilla_url = bugzilla_url
-        self.cve_url = cve_url
-        self.restart = restart
-        self.update_text = update_text
-        self.changelog = changelog
-        self.state = state
-        self.issued = issued
-        self.updated = updated
+        self.updates = str(updates)
+        self.obsoletes = str(obsoletes)
+        self.vendor_url = str(vendor_url)
+        self.bugzilla_url = str(bugzilla_url)
+        self.cve_url = str(cve_url)
+        self.restart = (restart == 'yes')
+        self.update_text = _to_unicode(update_text)
+        self.changelog = _to_unicode(changelog)
+        self.state = str(state)
+        self.issued = str(issued)
+        self.updated = str(updated)
 
 class PackageKitRepos:
     '''
     container class from values from the Repos signal
     '''
-    def __init__(self, package_id, description, enabled):
-        self.id = str(package_id)
-        self.description = description
-        self.enabled = enabled
+    def __init__(self, repo_id, description, enabled):
+        self.id = str(repo_id)
+        self.description = _to_unicode(description)
+        self.enabled = (enabled == 'yes')
 
 class PackageKitFiles:
     '''
@@ -96,5 +107,5 @@ class PackageKitFiles:
     '''
     def __init__(self, package_id, files):
         self.id = str(package_id)
-        self.files = files
-            
+        self.files = str(files)
+
commit 2bc31340a34e031f9cc7abae94b60b572ae18c49
Author: Sebastian Heinlein <devel at glatzor.de>
Date:   Sun Sep 28 00:03:04 2008 +0200

    APT: Follow api change in the client library

diff --git a/backends/apt/test.py b/backends/apt/test.py
index 45223a0..9a2d716 100755
--- a/backends/apt/test.py
+++ b/backends/apt/test.py
@@ -90,7 +90,7 @@ class AptBackendTestCase(unittest.TestCase):
         marked = map(lambda p: p.name, self.cache.getChanges())
         for p in pkgs:
             name = p.id.split(";")[0]
-            if p.status == INFO_BLOCKED:
+            if p.info == INFO_BLOCKED:
                 if name in blocked:
                     blocked.remove(name)
                 else:
commit 88ef5aa5e8efed6a77dae595c7a11f665ea34be3
Author: Sebastian Heinlein <devel at glatzor.de>
Date:   Sat Sep 27 23:48:44 2008 +0200

    Python client: store 'free' strings as unicodes instead of utf-8 encoded
    strings

diff --git a/python/packagekit/misc.py b/python/packagekit/misc.py
index 354bbc9..274503d 100644
--- a/python/packagekit/misc.py
+++ b/python/packagekit/misc.py
@@ -21,12 +21,6 @@
 
 # Misc classes and funtions
 
-def _to_utf8( obj, errors='replace'):
-    '''convert 'unicode' to an encoded utf-8 byte string '''
-    if isinstance(obj, unicode):
-        obj = obj.encode('utf-8', errors)
-    return obj
-
 class PackageKitPackage:
     '''
     container class from values from the Package signal
@@ -34,8 +28,8 @@ class PackageKitPackage:
     def __init__(self, info, package_id, summary):
         self.installed = (info == 'installed')
         self.id = str(package_id)
-        self.summary = _to_utf8(summary)
-        self.info = info
+        self.summary = unicode(summary)
+        self.info = str(info)
 
     def __str__(self):
         (name, ver, arch, repo) = tuple(self.id.split(";"))
@@ -49,7 +43,7 @@ class PackageKitDistroUpgrade:
     def __init__(self, upgrade_type, name, summary):
         self.upgrade_type = upgrade_type
         self.name = name
-        self.summary = _to_utf8(summary)
+        self.summary = (summary)
 
     def __str__(self):
         return " type : %s, name : %s, summary : %s " % (
@@ -63,7 +57,7 @@ class PackageKitDetails:
         self.id = str(package_id)
         self.license = package_license
         self.group = group
-        self.detail = _to_utf8(detail)
+        self.detail = unicode(detail)
         self.url = url
         self.size = size
 
commit df9ed3cc6ffe9afd715180263448ac85f8dc63b6
Author: Sebastian Heinlein <devel at glatzor.de>
Date:   Sat Sep 27 23:45:25 2008 +0200

    Python client: store the whole info in PackageKitPackage. This is
    required for e.g. GetUpdates

diff --git a/python/packagekit/misc.py b/python/packagekit/misc.py
index e6d113f..354bbc9 100644
--- a/python/packagekit/misc.py
+++ b/python/packagekit/misc.py
@@ -31,19 +31,16 @@ class PackageKitPackage:
     '''
     container class from values from the Package signal
     '''
-    def __init__(self, installed, package_id, summary):
-        self.installed = (installed == 'installed')
+    def __init__(self, info, package_id, summary):
+        self.installed = (info == 'installed')
         self.id = str(package_id)
         self.summary = _to_utf8(summary)
+        self.info = info
 
     def __str__(self):
         (name, ver, arch, repo) = tuple(self.id.split(";"))
         p =  "%s-%s.%s" % (name, ver, arch)
-        if self.installed:
-            inst = "installed"
-        else:
-            inst = "available"
-        return "%-40s : %s : %s" % (p, inst, self.summary)
+        return "%-40s : %s : %s" % (p, self.info, self.summary)
 
 class PackageKitDistroUpgrade:
     '''
commit e6ad69b4389e024db2bcc981ef6209aaaeb282a1
Merge: d02d54b... 1765dc9...
Author: Sebastian Heinlein <devel at glatzor.de>
Date:   Sat Sep 27 15:43:25 2008 +0200

    Merge branch 'master' of git+ssh://glatzor@git.packagekit.org/srv/git/PackageKit

commit d02d54b7069fcc29c778de7363567e5405003fad
Author: Sebastian Heinlein <devel at glatzor.de>
Date:   Sat Sep 27 15:42:53 2008 +0200

    APT: Call doExitDelay in doExit

diff --git a/backends/apt/aptDBUSBackend.py b/backends/apt/aptDBUSBackend.py
index 8b4a303..91a7754 100755
--- a/backends/apt/aptDBUSBackend.py
+++ b/backends/apt/aptDBUSBackend.py
@@ -510,7 +510,7 @@ class PackageKitAptBackend(PackageKitBaseBackend):
 
     @serialize
     def doExit(self):
-        pass
+        gobject.idle_add(self._doExitDelay)
 
     def doCancel(self):
         pklog.info("Canceling current action")
commit 16a79b02b5c5fdc5f76088037ee6f609a961af12
Author: Sebastian Heinlein <devel at glatzor.de>
Date:   Sat Sep 27 15:42:17 2008 +0200

    DaemonBackend: the doExitDelay should be called in the doExit
    implementation

diff --git a/python/packagekit/daemonBackend.py b/python/packagekit/daemonBackend.py
index 3c3eda1..8d33b6e 100644
--- a/python/packagekit/daemonBackend.py
+++ b/python/packagekit/daemonBackend.py
@@ -390,12 +390,14 @@ class PackageKitBaseBackend(dbus.service.Object):
                          in_signature='', out_signature='')
     def Exit(self):
         pklog.info("Exit()")
-        gobject.idle_add (self._doExitDelay)
         self.doExit()
 
     def doExit(self):
         '''
         Should be replaced in the corresponding backend sub class
+        
+        Call this method at the end to make sure that dbus can still respond
+        gobject.idle_add (self._doExitDelay)
         '''
         self.ErrorCode(ERROR_NOT_SUPPORTED,
                        "This function is not implemented in this backend")
commit 4bc7370cac1564fa3109d2a62df53d62a5cba176
Author: Sebastian Heinlein <devel at glatzor.de>
Date:   Sat Sep 27 15:35:06 2008 +0200

    APT: Follow renaming of async decorator and make GetFiles threaded

diff --git a/backends/apt/aptDBUSBackend.py b/backends/apt/aptDBUSBackend.py
index 1e3a9fa..8b4a303 100755
--- a/backends/apt/aptDBUSBackend.py
+++ b/backends/apt/aptDBUSBackend.py
@@ -47,7 +47,7 @@ import dbus.service
 import dbus.mainloop.glib
 import gobject
 
-from packagekit.daemonBackend import PACKAGEKIT_DBUS_INTERFACE, PACKAGEKIT_DBUS_PATH, PackageKitBaseBackend, PackagekitProgress, pklog, threaded, async
+from packagekit.daemonBackend import PACKAGEKIT_DBUS_INTERFACE, PACKAGEKIT_DBUS_PATH, PackageKitBaseBackend, PackagekitProgress, pklog, threaded, serialize
 from packagekit.enums import *
 
 import debfile
@@ -508,10 +508,10 @@ class PackageKitAptBackend(PackageKitBaseBackend):
         self.NoPercentageUpdates()
         self._open_cache(progress=False)
 
+    @serialize
     def doExit(self):
         pass
 
-    @threaded
     def doCancel(self):
         pklog.info("Canceling current action")
         self.StatusChanged(STATUS_CANCEL)
@@ -519,6 +519,7 @@ class PackageKitAptBackend(PackageKitBaseBackend):
         self._canceled.wait()
 
     @threaded
+    @serialize
     def doSearchFile(self, filters, filename):
         '''
         Implement the apt2-search-file functionality
@@ -541,6 +542,7 @@ class PackageKitAptBackend(PackageKitBaseBackend):
         self.Finished(EXIT_SUCCESS)
 
     @threaded
+    @serialize
     def doSearchGroup(self, filters, group):
         '''
         Implement the apt2-search-group functionality
@@ -558,6 +560,7 @@ class PackageKitAptBackend(PackageKitBaseBackend):
         self.Finished(EXIT_SUCCESS)
 
     @threaded
+    @serialize
     def doSearchName(self, filters, search):
         '''
         Implement the apt2-search-name functionality
@@ -575,6 +578,7 @@ class PackageKitAptBackend(PackageKitBaseBackend):
         self.Finished(EXIT_SUCCESS)
 
     @threaded
+    @serialize
     def doSearchDetails(self, filters, search):
         '''
         Implement the apt2-search-details functionality
@@ -619,7 +623,7 @@ class PackageKitAptBackend(PackageKitBaseBackend):
         self.Finished(EXIT_SUCCESS)
 
     @threaded
-    @async
+    @serialize
     def doGetDistroUpgrades(self):
         '''
         Implement the {backend}-get-distro-upgrades functionality
@@ -656,7 +660,7 @@ class PackageKitAptBackend(PackageKitBaseBackend):
         self.Finished(EXIT_SUCCESS)
 
     @threaded
-    @async
+    @serialize
     def doGetUpdates(self, filters):
         '''
         Implement the {backend}-get-update functionality
@@ -723,6 +727,7 @@ class PackageKitAptBackend(PackageKitBaseBackend):
         self.Finished(EXIT_SUCCESS)
 
     @threaded
+    @serialize
     def doGetUpdateDetail(self, pkg_ids):
         '''
         Implement the {backend}-get-update-details functionality
@@ -762,6 +767,7 @@ class PackageKitAptBackend(PackageKitBaseBackend):
         self.Finished(EXIT_SUCCESS)
 
     @threaded
+    @serialize
     def doGetDetails(self, pkg_ids):
         '''
         Implement the {backend}-get-details functionality
@@ -794,7 +800,7 @@ class PackageKitAptBackend(PackageKitBaseBackend):
             self.Finished(EXIT_SUCCESS)
 
     @threaded
-    @async
+    @serialize
     @unlock_cache_afterwards
     def doUpdateSystem(self):
         '''
@@ -819,7 +825,7 @@ class PackageKitAptBackend(PackageKitBaseBackend):
         self.Finished(EXIT_SUCCESS)
 
     @threaded
-    @async
+    @serialize
     @unlock_cache_afterwards
     def doRemovePackages(self, ids, deps=True, auto=False):
         '''
@@ -870,7 +876,7 @@ class PackageKitAptBackend(PackageKitBaseBackend):
         self.Finished(EXIT_SUCCESS)
 
     @threaded
-    @async
+    @serialize
     def doGetRepoList(self, filters):
         '''
         Implement the {backend}-get-repo-list functionality
@@ -951,7 +957,7 @@ class PackageKitAptBackend(PackageKitBaseBackend):
         self.Finished(EXIT_SUCCESS)
 
     @threaded
-    @async
+    @serialize
     def doRepoEnable(self, repo_id, enable):
         '''
         Implement the {backend}-repo-enable functionality
@@ -1038,7 +1044,7 @@ class PackageKitAptBackend(PackageKitBaseBackend):
         self.Finished(EXIT_SUCCESS)
 
     @threaded
-    @async
+    @serialize
     @unlock_cache_afterwards
     def doUpdatePackages(self, ids):
         '''
@@ -1086,7 +1092,7 @@ class PackageKitAptBackend(PackageKitBaseBackend):
         self.Finished(EXIT_SUCCESS)
 
     @threaded
-    @async
+    @serialize
     def doDownloadPackages(self, ids, dest):
         '''
         Implement the {backend}-download-packages functionality
@@ -1152,7 +1158,7 @@ class PackageKitAptBackend(PackageKitBaseBackend):
         self.Finished(EXIT_SUCCESS)
  
     @threaded
-    @async
+    @serialize
     @unlock_cache_afterwards
     def doInstallPackages(self, ids):
         '''
@@ -1199,7 +1205,7 @@ class PackageKitAptBackend(PackageKitBaseBackend):
         self.Finished(EXIT_SUCCESS)
 
     @threaded
-    @async
+    @serialize
     @unlock_cache_afterwards
     def doInstallFiles(self, trusted, full_paths):
         '''
@@ -1279,7 +1285,7 @@ class PackageKitAptBackend(PackageKitBaseBackend):
         self.Finished(EXIT_SUCCESS)
 
     @threaded
-    @async
+    @serialize
     @unlock_cache_afterwards
     def doRefreshCache(self, force):
         '''
@@ -1304,6 +1310,7 @@ class PackageKitAptBackend(PackageKitBaseBackend):
         self.Finished(EXIT_SUCCESS)
 
     @threaded
+    @serialize
     def doGetPackages(self, filters):
         '''
         Implement the apt2-get-packages functionality
@@ -1321,6 +1328,7 @@ class PackageKitAptBackend(PackageKitBaseBackend):
         self.Finished(EXIT_SUCCESS)
 
     @threaded
+    @serialize
     def doResolve(self, filters, names):
         '''
         Implement the apt2-resolve functionality
@@ -1342,6 +1350,7 @@ class PackageKitAptBackend(PackageKitBaseBackend):
         self.Finished(EXIT_SUCCESS)
 
     @threaded
+    @serialize
     def doGetDepends(self, filter, ids, recursive=False):
         '''
         Implement the apt2-get-depends functionality
@@ -1409,6 +1418,7 @@ class PackageKitAptBackend(PackageKitBaseBackend):
         self.Finished(EXIT_SUCCESS)
 
     @threaded
+    @serialize
     def doGetRequires(self, filter, ids, recursive=False):
         '''
         Implement the apt2-get-requires functionality
@@ -1465,6 +1475,7 @@ class PackageKitAptBackend(PackageKitBaseBackend):
         self.Finished(EXIT_SUCCESS)
 
     @threaded
+    @serialize
     def doWhatProvides(self, filters, provides_type, search):
         def get_mapping_db(path):
             """
@@ -1558,6 +1569,8 @@ class PackageKitAptBackend(PackageKitBaseBackend):
             return
         self.Finished(EXIT_SUCCESS)
 
+    @threaded
+    @serialize
     def doGetFiles(self, package_ids):
         """
         Emit the Files signal which includes the files included in a package
commit e7d748e49a4b9597f975fb8aadbc8fafb06d5595
Author: Sebastian Heinlein <devel at glatzor.de>
Date:   Sat Sep 27 15:33:19 2008 +0200

    DaemonBackend: Rename async decorartor to serialze to avoid confusions

diff --git a/python/packagekit/daemonBackend.py b/python/packagekit/daemonBackend.py
index 1fca9c8..3c3eda1 100644
--- a/python/packagekit/daemonBackend.py
+++ b/python/packagekit/daemonBackend.py
@@ -124,7 +124,7 @@ def threaded(func):
     wrapper.__name__ = func.__name__
     return wrapper
 
-def async(func):
+def serialize(func):
     '''
     Decorator which makes sure no other threads are running before executing function.
     '''
commit faa495b03a03acebe4fe0d06fc2d951edf260fb4
Author: Sebastian Heinlein <devel at glatzor.de>
Date:   Sat Sep 27 15:02:56 2008 +0200

    APT: Make the master fd of the child non blocking

diff --git a/backends/apt/aptDBUSBackend.py b/backends/apt/aptDBUSBackend.py
index 54ad500..1e3a9fa 100755
--- a/backends/apt/aptDBUSBackend.py
+++ b/backends/apt/aptDBUSBackend.py
@@ -18,6 +18,7 @@ the Free Software Foundation; either version 2 of the License, or
 __author__  = "Sebastian Heinlein <devel at glatzor.de>"
 
 import errno
+import fcntl
 import gdbm
 import httplib
 import locale
@@ -258,6 +259,7 @@ class DpkgInstallProgress(apt.progress.InstallProgress):
         """
         pklog.debug("Executing: %s" % cmd)
         (self.master_fd, slave) = pty.openpty()
+        fcntl.fcntl(self.master_fd, fcntl.F_SETFL, os.O_NONBLOCK)
         p = subprocess.Popen(cmd, stdout=slave, stdin=slave)
         self.child_pid = p.pid
         res = self.waitChild()
@@ -384,7 +386,7 @@ class PackageKitInstallProgress(apt.progress.InstallProgress):
         self.last_activity = None
         self.conffile_prompts = set()
         # insanly long timeout to be able to kill hanging maintainer scripts
-        self.timeout = 10*60
+        self.timeout = 10 * 60
         self.start_time = None
         self.output = ""
 
@@ -406,6 +408,8 @@ class PackageKitInstallProgress(apt.progress.InstallProgress):
     def fork(self):
         pklog.debug("fork()")
         (pid, self.master_fd) = pty.fork()
+        if pid != 0:
+            fcntl.fcntl(self.master_fd, fcntl.F_SETFL, os.O_NONBLOCK)
         return pid
 
     def updateInterface(self):
commit a7880dac0f6a26ecfe46c99b138c75ad2ccaa527
Author: Sebastian Heinlein <devel at glatzor.de>
Date:   Sat Sep 27 14:06:11 2008 +0200

    APT: Fix a wrong error enum

diff --git a/backends/apt/aptDBUSBackend.py b/backends/apt/aptDBUSBackend.py
index 1cb3e77..54ad500 100755
--- a/backends/apt/aptDBUSBackend.py
+++ b/backends/apt/aptDBUSBackend.py
@@ -1268,7 +1268,7 @@ class PackageKitAptBackend(PackageKitBaseBackend):
             self.Finished(EXIT_FAILED)
         except Exception, e:
             self._recover()
-            self.ErrorCode(ERROR_INTERNAL, "Failed to install dpkg: %s" % e)
+            self.ErrorCode(ERROR_INTERNAL_ERROR, e.message)
             self.Finished(EXIT_FAILED)
             return
         self.PercentageChanged(100)
commit 91647a735a0350dfdd95c0e27608b727c65329f3
Author: Sebastian Heinlein <devel at glatzor.de>
Date:   Sat Sep 27 14:04:52 2008 +0200

    APT: Use openpty() to create a fd which can be used for stdin and stdout
    in the dpkg call

diff --git a/backends/apt/aptDBUSBackend.py b/backends/apt/aptDBUSBackend.py
index 9ab7741..1cb3e77 100755
--- a/backends/apt/aptDBUSBackend.py
+++ b/backends/apt/aptDBUSBackend.py
@@ -257,9 +257,8 @@ class DpkgInstallProgress(apt.progress.InstallProgress):
         Run and monitor a dpkg command line call
         """
         pklog.debug("Executing: %s" % cmd)
-        p = subprocess.Popen(cmd, stdout=subprocess.PIPE, 
-                             stdin=subprocess.PIPE)
-        self.master_fd = p.stdout.fileno()
+        (self.master_fd, slave) = pty.openpty()
+        p = subprocess.Popen(cmd, stdout=slave, stdin=slave)
         self.child_pid = p.pid
         res = self.waitChild()
         return res
commit b4eaf4a428358221f085eefe4d9a512af1c56770
Author: Sebastian Heinlein <devel at glatzor.de>
Date:   Sat Sep 27 13:17:48 2008 +0200

    APT: Try to recover from a failed package manager operation by running
    "dpkg --configure -a"

diff --git a/backends/apt/aptDBUSBackend.py b/backends/apt/aptDBUSBackend.py
index f89c6a5..9ab7741 100755
--- a/backends/apt/aptDBUSBackend.py
+++ b/backends/apt/aptDBUSBackend.py
@@ -236,6 +236,14 @@ class DpkgInstallProgress(apt.progress.InstallProgress):
     """
     Class to initiate and monitor installation of local package files with dpkg
     """
+    def recover(self):
+        """
+        Run "dpkg --configure -a"
+        """
+        cmd = ["/usr/bin/dpkg", "--status-fd", str(self.writefd), 
+               "--configure", "-a"]
+        self.run(cmd)
+
     def install(self, filenames):
         """
         Install the given package using a dpkg command line call
@@ -1247,7 +1255,7 @@ class PackageKitAptBackend(PackageKitBaseBackend):
             d.install(full_paths)
             d.finishUpdate()
         except InstallTimeOutPKError, e:
-            self._open_cache(prange=(95,100))
+            self._recover()
             #FIXME: should provide more information
             self.ErrorCode(ERROR_UNKNOWN,
                            "Transaction was cancelled since the installation "
@@ -1256,11 +1264,11 @@ class PackageKitAptBackend(PackageKitBaseBackend):
                            "require input on the terminal:\n%s" % e.message)
             self.Finished(EXIT_KILLED)
         except PackageManagerFailedPKError, e:
-            self._open_cache(prange=(95,100))
+            self._recover()
             self.ErrorCode(ERROR_UNKNOWN, "%s\n%s" % (e.message, e.output))
             self.Finished(EXIT_FAILED)
         except Exception, e:
-            self._open_cache(prange=(95,100))
+            self._recover()
             self.ErrorCode(ERROR_INTERNAL, "Failed to install dpkg: %s" % e)
             self.Finished(EXIT_FAILED)
             return
@@ -1636,6 +1644,22 @@ class PackageKitAptBackend(PackageKitBaseBackend):
             return
         self._last_cache_refresh = time.time()
 
+    def _recover(self, prange=(95,100)):
+        """
+        Try to recover from a package manager failure
+        """
+        self.StatusChanged(STATUS_CLEANUP)
+        self.NoPercentageUpdates()
+        try:
+            apt_pkg.PkgSystemLock()
+            d = PackageKitDpkgInstallProgress(self)
+            d.startUpdate()
+            d.recover()
+            d.finishUpdate()
+        except:
+            pass
+        self._open_cache(prange)
+
     def _commit_changes(self, fetch_range=(5,50), install_range=(50,90)):
         """
         Commit changes to the cache and handle errors
@@ -1652,6 +1676,7 @@ class PackageKitAptBackend(PackageKitBaseBackend):
             self.Finished(EXIT_CANCELLED)
             self._canceled.clear()
         except InstallTimeOutPKError, e:
+            self._recover()
             self._open_cache(prange=(95,100))
             #FIXME: should provide more information
             self.ErrorCode(ERROR_UNKNOWN,
@@ -1661,7 +1686,7 @@ class PackageKitAptBackend(PackageKitBaseBackend):
                            "require input on the terminal:\n%s" % e.message)
             self.Finished(EXIT_KILLED)
         except PackageManagerFailedPKError, e:
-            self._open_cache(prange=(95,100))
+            self._recover()
             self.ErrorCode(ERROR_UNKNOWN, "%s\n%s" % (e.message, e.output))
             self.Finished(EXIT_FAILED)
         else:
commit b2ee8dc17983bb93811933ca03458dfae3e72335
Author: Sebastian Heinlein <devel at glatzor.de>
Date:   Sat Sep 27 12:49:20 2008 +0200

    APT: Copy and paste error handling from apt to dpkg call

diff --git a/backends/apt/aptDBUSBackend.py b/backends/apt/aptDBUSBackend.py
index e6e85fa..f89c6a5 100755
--- a/backends/apt/aptDBUSBackend.py
+++ b/backends/apt/aptDBUSBackend.py
@@ -1246,8 +1246,22 @@ class PackageKitAptBackend(PackageKitBaseBackend):
             d.startUpdate()
             d.install(full_paths)
             d.finishUpdate()
+        except InstallTimeOutPKError, e:
+            self._open_cache(prange=(95,100))
+            #FIXME: should provide more information
+            self.ErrorCode(ERROR_UNKNOWN,
+                           "Transaction was cancelled since the installation "
+                           "of a package hung.\n"
+                           "This can be caused by maintainer scripts which "
+                           "require input on the terminal:\n%s" % e.message)
+            self.Finished(EXIT_KILLED)
+        except PackageManagerFailedPKError, e:
+            self._open_cache(prange=(95,100))
+            self.ErrorCode(ERROR_UNKNOWN, "%s\n%s" % (e.message, e.output))
+            self.Finished(EXIT_FAILED)
         except Exception, e:
-            self.ErrorCode(ERROR_UNKNOWN, "Failed to install dpkg: %s" % e)
+            self._open_cache(prange=(95,100))
+            self.ErrorCode(ERROR_INTERNAL, "Failed to install dpkg: %s" % e)
             self.Finished(EXIT_FAILED)
             return
         self.PercentageChanged(100)
commit 15d767edee116994dcfe5622861ffa411f57cfa5
Author: Sebastian Heinlein <devel at glatzor.de>
Date:   Sat Sep 27 12:44:39 2008 +0200

    APT: Do not fork the whole backend to only run dpkg. Use Popen instead.
    Furthermore improve the whole error reporting during installation

diff --git a/backends/apt/aptDBUSBackend.py b/backends/apt/aptDBUSBackend.py
index 66e6b85..e6e85fa 100755
--- a/backends/apt/aptDBUSBackend.py
+++ b/backends/apt/aptDBUSBackend.py
@@ -31,6 +31,7 @@ import shutil
 import socket
 import stat
 import string
+import subprocess
 import sys
 import time
 import threading
@@ -156,7 +157,16 @@ def unlock_cache_afterwards(func):
     return wrapper
 
 
-class InstallTimeOutPKError(Exception):
+class PKError(Exception):
+    pass
+
+class PackageManagerFailedPKError(PKError):
+    def __init__(self, msg, pkg, output):
+        self.message = msg
+        self.package = pkg
+        self.output = output
+
+class InstallTimeOutPKError(PKError):
     pass
 
 class PackageKitCache(apt.cache.Cache):
@@ -226,22 +236,23 @@ class DpkgInstallProgress(apt.progress.InstallProgress):
     """
     Class to initiate and monitor installation of local package files with dpkg
     """
-    def run(self, filename):
+    def install(self, filenames):
         """
-        Start installing the given Debian package
+        Install the given package using a dpkg command line call
         """
-        try:
-            self.debname = os.path.basename(filename).split("_")[0]
-        except:
-            self.debname = "unknown"
-        pid = self.fork()
-        if pid == 0:
-            # child
-            dpkg_res = os.system("/usr/bin/dpkg --status-fd %s -i %s" % \
-                                 (self.writefd, filename))
-            res = os.WEXITSTATUS(dpkg_res)
-            os._exit(res)
-        self.child_pid = pid
+        cmd = ["/usr/bin/dpkg", "--status-fd", str(self.writefd), "-i"]
+        cmd.extend(filenames)
+        self.run(cmd)
+
+    def run(self, cmd):
+        """
+        Run and monitor a dpkg command line call
+        """
+        pklog.debug("Executing: %s" % cmd)
+        p = subprocess.Popen(cmd, stdout=subprocess.PIPE, 
+                             stdin=subprocess.PIPE)
+        self.master_fd = p.stdout.fileno()
+        self.child_pid = p.pid
         res = self.waitChild()
         return res
 
@@ -261,12 +272,13 @@ class DpkgInstallProgress(apt.progress.InstallProgress):
         if self.read.endswith("\n"):
             statusl = string.split(self.read, ":")
             if len(statusl) < 3:
-                print "got garbage from dpkg: '%s'" % read
+                pklog.warn("got garbage from dpkg: '%s'" % read)
                 self.read = ""
             status = statusl[2].strip()
+            pkg = statusl[1].strip()
             #print status
             if status == "error":
-                self.error(self.debname, status)
+                self.error(pkg, status)
             elif status == "conffile-prompt":
                 # we get a string like this:
                 # 'current-conffile' 'new-conffile' useredited distedited
@@ -274,6 +286,7 @@ class DpkgInstallProgress(apt.progress.InstallProgress):
                 if match:
                      self.conffile(match.group(1), match.group(2))
             else:
+                pklog.debug("Dpkg status: %s" % status)
                 self.status = status
             self.read = ""
 
@@ -366,6 +379,7 @@ class PackageKitInstallProgress(apt.progress.InstallProgress):
         # insanly long timeout to be able to kill hanging maintainer scripts
         self.timeout = 10*60
         self.start_time = None
+        self.output = ""
 
     def statusChange(self, pkg, percent, status):
         self.last_activity = time.time()
@@ -373,7 +387,7 @@ class PackageKitInstallProgress(apt.progress.InstallProgress):
         if self.pprev < progress:
             self._backend.PercentageChanged(int(progress))
             self.pprev = progress
-        pklog.debug("PM status: %s" % status)
+        pklog.debug("APT status: %s" % status)
 
     def startUpdate(self):
         # The apt system lock was set by _lock_cache() before
@@ -389,16 +403,21 @@ class PackageKitInstallProgress(apt.progress.InstallProgress):
 
     def updateInterface(self):
         apt.progress.InstallProgress.updateInterface(self)
+        # Collect the output from the package manager
         try:
-            pklog.debug("%s" % os.read(self.master_fd, 512))
-        except Exception, e:
-            pklog.debug("ioerror: %s" % e)
-        # we timed out, send ctrl-c
+            out = os.read(self.master_fd, 512)
+            self.output = self.output + out
+            pklog.debug("APT out: %s " % out)
+        except OSError:
+            pass
+        # catch a time out by sending crtl+c
         if self.last_activity + self.timeout < time.time():
             pklog.critical("no activity for %s time sending ctrl-c" \
                            % self.timeout)
             os.write(self.master_fd, chr(3))
-            raise InstallTimeOutPKError
+            #FIXME: include this into the normal install progress and add 
+            #       correct package information
+            raise InstallTimeOutPKError(self.output)
 
     def conffile(self, current, new):
         pklog.warning("Config file prompt: '%s' (sending no)" % current)
@@ -406,6 +425,9 @@ class PackageKitInstallProgress(apt.progress.InstallProgress):
         pklog.debug("wrote n, send %i bytes" % i)
         self.conffile_prompts.add(new)
 
+    def error(self, pkg, msg):
+        raise PackageManagerFailedPKError(pkg, msg, self.output)
+
     def finishUpdate(self):
         pklog.debug("finishUpdate()")
         if self.conffile_prompts:
@@ -424,20 +446,23 @@ class PackageKitDpkgInstallProgress(DpkgInstallProgress,
     """
     Class to integrate the progress of core dpkg operations into PackageKit
     """
-    def run(self, filename):
-        return DpkgInstallProgress.run(self, filename)
+    def run(self, filenames):
+        return DpkgInstallProgress.run(self, filenames)
 
     def updateInterface(self):
         DpkgInstallProgress.updateInterface(self)
         try:
-            pklog.debug("%s" % os.read(self.master_fd, 512))
-        except Exception, e:
-            pklog.debug("ioerror: %s" % e)
+            out = os.read(self.master_fd, 512)
+            self.output += out
+            if out != "": pklog.debug("Dpkg out: %s" % out)
+        except OSError:
+            pass
         # we timed out, send ctrl-c
         if self.last_activity + self.timeout < time.time():
             pklog.critical("no activity for %s time sending "
                            "ctrl-c" % self.timeout)
             os.write(self.master_fd, chr(3))
+            raise InstallTimeOutPKError(self.output)
 
 
 if REPOS_SUPPORT == True:
@@ -1207,26 +1232,24 @@ class PackageKitAptBackend(PackageKitBaseBackend):
             self.Finished(EXIT_FAILED)
             return
         if not self._commit_changes((10,25), (25,50)): return False
-        # Install the Debian package files
-        if not self._lock_cache(): return
+        # Check for later available packages
         for deb in packages:
-            try:
-                res = deb.install(PackageKitDpkgInstallProgress(self))
-            except Exception, e:
-                self.ErrorCode(ERROR_UNKNOWN, "Failed to install dpkg: %s" % e)
-                self.Finished(EXIT_FAILED)
-                return
-            print res
-            if res != 0:
-                self.ErrorCode(ERROR_UNKNOWN, 
-                               "Failed to install package %s" % deb.pkgname)
-                self.Finished(EXIT_FAILED)
-                return
             # Check if there is a newer version in the cache
             if deb.compareToVersionInCache() == debfile.VERSION_OUTDATED:
                 self.Message(MESSAGE_NEWER_PACKAGE_EXISTS, 
                              "There is a later version of %s "
                              "available in the repositories." % deb.pkgname)
+        # Install the Debian package files
+        if not self._lock_cache(): return
+        d = PackageKitDpkgInstallProgress(self)
+        try:
+            d.startUpdate()
+            d.install(full_paths)
+            d.finishUpdate()
+        except Exception, e:
+            self.ErrorCode(ERROR_UNKNOWN, "Failed to install dpkg: %s" % e)
+            self.Finished(EXIT_FAILED)
+            return
         self.PercentageChanged(100)
         self.Finished(EXIT_SUCCESS)
 
@@ -1614,18 +1637,18 @@ class PackageKitAptBackend(PackageKitBaseBackend):
             self._open_cache(prange=(95,100))
             self.Finished(EXIT_CANCELLED)
             self._canceled.clear()
-        except InstallTimeOutPKError:
+        except InstallTimeOutPKError, e:
             self._open_cache(prange=(95,100))
             #FIXME: should provide more information
             self.ErrorCode(ERROR_UNKNOWN,
                            "Transaction was cancelled since the installation "
                            "of a package hung.\n"
                            "This can be caused by maintainer scripts which "
-                           "require input on the terminal.")
+                           "require input on the terminal:\n%s" % e.message)
             self.Finished(EXIT_KILLED)
-        except:
+        except PackageManagerFailedPKError, e:
             self._open_cache(prange=(95,100))
-            self.ErrorCode(ERROR_UNKNOWN, "Applying changes failed")
+            self.ErrorCode(ERROR_UNKNOWN, "%s\n%s" % (e.message, e.output))
             self.Finished(EXIT_FAILED)
         else:
             return True
commit 1765dc9722ac3c5ef983a62a265575373c5d91e4
Author: Scott Reeves <sreeves at novell.com>
Date:   Fri Sep 26 18:01:54 2008 -0600

    fix returning bogus packages by setting ignoreAlreadyRecommended

diff --git a/backends/zypp/pk-backend-zypp.cpp b/backends/zypp/pk-backend-zypp.cpp
index 5330d2c..c8e355d 100644
--- a/backends/zypp/pk-backend-zypp.cpp
+++ b/backends/zypp/pk-backend-zypp.cpp
@@ -1765,17 +1765,17 @@ backend_what_provides_thread (PkBackend *backend)
 	zypp::sat::WhatProvides prov (cap);
 
 	if((provides == PK_PROVIDES_ENUM_HARDWARE_DRIVER) || g_ascii_strcasecmp("drivers_for_attached_hardware", search) == 0) {
-
-
 		// solver run
 		zypp::ResPool pool = zypp_build_pool(true);
 		zypp::Resolver solver(pool);
+		solver.setIgnoreAlreadyRecommended (TRUE);
 
 		if (solver.resolvePool () == FALSE) {
 			std::list<zypp::ResolverProblem_Ptr> problems = solver.problems ();
 			for (std::list<zypp::ResolverProblem_Ptr>::iterator it = problems.begin (); it != problems.end (); it++){
 				egg_warning("Solver problem (This should never happen): '%s'", (*it)->description ().c_str ());
 			}
+			solver.setIgnoreAlreadyRecommended (FALSE);
 			pk_backend_error_code (backend, PK_ERROR_ENUM_DEP_RESOLUTION_FAILED, "Resolution failed");
 			pk_backend_finished (backend);
 			return FALSE;
@@ -1806,9 +1806,7 @@ backend_what_provides_thread (PkBackend *backend)
 			}
 			it->statusReset ();
 		}
-
-
-
+		solver.setIgnoreAlreadyRecommended (FALSE);
 	}else{
 		for(zypp::sat::WhatProvides::const_iterator it = prov.begin (); it != prov.end (); it++) {
 			gchar *package_id = zypp_build_package_id_from_resolvable (*it);
commit 5728dcd11117483feddca05e995b9544ea76411d
Author: Richard Hughes <richard at hughsie.com>
Date:   Fri Sep 26 20:12:25 2008 +0100

    conary: use PackagekitFilter to reduce a load of complexity

diff --git a/backends/conary/conaryBackend.py b/backends/conary/conaryBackend.py
index 71f60cb..15000b7 100644
--- a/backends/conary/conaryBackend.py
+++ b/backends/conary/conaryBackend.py
@@ -32,6 +32,7 @@ from conary import trove
 from packagekit.backend import *
 from packagekit.package import *
 from conaryCallback import UpdateCallback
+from conaryFilter import *
 
 pkpackage = PackagekitPackage()
 
@@ -196,6 +197,7 @@ class PackageKitConaryBackend(PackageKitBaseBackend):
 
     def _do_search(self, searchlist, filters):
         fltlist = filters.split(';')
+        pkgfilter = ConaryFilter(fltlist)
         troveSpecs = [ updatecmd.parseTroveSpec(searchlist,
                                                 allowEmptyName=False) ]
         # get a hold of cached data
@@ -225,13 +227,16 @@ class PackageKitConaryBackend(PackageKitBaseBackend):
             name = troveTuple[0]
             version = versions.ThawVersion(troveTuple[1])
             flavor = deps.ThawFlavor(troveTuple[2])
-            id = self.get_package_id(name, version, flavor)
-            summary = self._get_metadata(id, 'shortDesc') or " "
             troveTuple = tuple([name, version, flavor])
             installed = self.check_installed(troveTuple)
+            if installed:
+                pkgfilter.add_installed([troveTuple])
+            else:
+                pkgfilter.add_available([troveTuple])
 
-            if self._do_filtering(name, fltlist, installed):
-                self.package(id, installed, summary)
+        # we couldn't do this when generating the list
+        package_list = pkgfilter.post_process()
+        self._show_package_list(package_list)
 
     def _get_update(self, applyList, cache=True):
         updJob = self.client.newUpdateJob()
@@ -286,6 +291,12 @@ class PackageKitConaryBackend(PackageKitBaseBackend):
             installed = INFO_AVAILABLE
         return installed
 
+    def _pkg_is_installed(self, pkg):
+        '''
+        Return if the package is installed.
+        '''
+        return self.check_installed(pkg)
+
     @ExceptionHandler
     def search_group(self, filters, key):
         '''
@@ -297,6 +308,8 @@ class PackageKitConaryBackend(PackageKitBaseBackend):
         self.status(STATUS_QUERY)
 
         fltlist = filters.split(';')
+        pkgfilter = ConaryFilter(fltlist)
+        pkgfilter = ConaryFilter(fltlist)
         cache = Cache()
 
         try:
@@ -313,15 +326,27 @@ class PackageKitConaryBackend(PackageKitBaseBackend):
             name = troveTuple[0]
             version = versions.ThawVersion(troveTuple[1])
             flavor = deps.ThawFlavor(troveTuple[2])
-            id = self.get_package_id(name, version, flavor)
-            summary = self._get_metadata(id, 'shortDesc') or " "
             category = troveTuple[3][0]
             category = category.encode('UTF-8')
             troveTuple = tuple([name, version, flavor])
             installed = self.check_installed(troveTuple)
+            if installed:
+                pkgfilter.add_installed([troveTuple])
+            else:
+                pkgfilter.add_available([troveTuple])
+
+        # we couldn't do this when generating the list
+        package_list = pkgfilter.post_process()
+        self._show_package_list(package_list)
 
-            if self._do_filtering(name, fltlist, installed):
-                self.package(id, installed, summary)
+    def _show_package_list(self, lst):
+        for (troveTuple, status) in lst:
+            name = troveTuple[0]
+            version = troveTuple[1]
+            flavor = troveTuple[2]
+            package_id = self.get_package_id(name, version, flavor)
+            summary = self._get_metadata(package_id, 'shortDesc') or " "
+            self.package(package_id, status, summary)
 
     @ExceptionHandler
     def search_name(self, options, searchlist):
@@ -620,53 +645,6 @@ class PackageKitConaryBackend(PackageKitBaseBackend):
             installed = self.check_installed(troveTuple)
             self._show_package(name, version, flavor, INFO_NORMAL)
 
-    def _do_filtering(self, pkg, filterList, installed):
-        ''' Filter the package, based on the filter in filterList '''
-        # do we print to stdout?
-        do_print = False
-        if filterList == ['none']: # 'none' = all packages.
-            return True
-        elif FILTER_INSTALLED in filterList and installed == INFO_INSTALLED:
-            do_print = True
-        elif FILTER_NOT_INSTALLED in filterList and installed == INFO_AVAILABLE:
-            do_print = True
-
-        if len(filterList) == 1: # Only one filter, return
-            return do_print
-
-        if do_print:
-            return self._do_extra_filtering(pkg, filterList)
-        else:
-            return do_print
-
-    def _do_extra_filtering(self, pkg, filterList):
-        ''' do extra filtering (devel etc) '''
-
-        for flt in filterList:
-            if flt in (FILTER_INSTALLED, FILTER_NOT_INSTALLED):
-                continue
-            elif flt in (FILTER_DEVELOPMENT, FILTER_NOT_DEVELOPMENT):
-                if not self._do_devel_filtering(flt, pkg):
-                    return False
-        return True
-
-    def _do_devel_filtering(self, flt, pkg):
-        isDevel = False
-        if flt == FILTER_DEVELOPMENT:
-            wantDevel = True
-        else:
-            wantDevel = False
-        #
-        # TODO: Add Devel detection Code here.Set isDevel = True, if it is a
-        #       devel app.
-        #
-        regex =  re.compile(r'(:devel)')
-        if regex.search(pkg.name):
-            isDevel = True
-        #
-        #
-        return isDevel == wantDevel
-
     def _findPackage(self, id):
         '''
         find a package based on a package id (name;version;arch;repoid)
commit 6e981c0ed5b6b74c988880acc6b88c4ac46e8a92
Author: Richard Hughes <richard at hughsie.com>
Date:   Fri Sep 26 19:41:14 2008 +0100

    conary, subclass PackagekitFilter, not used yet

diff --git a/backends/conary/Makefile.am b/backends/conary/Makefile.am
index 24d7598..3f57301 100644
--- a/backends/conary/Makefile.am
+++ b/backends/conary/Makefile.am
@@ -1,6 +1,7 @@
 helperdir = $(datadir)/PackageKit/helpers/conary
 dist_helper_DATA = 			\
 	conaryBackend.py		\
+	conaryFilter.py		\
 	conaryCallback.py
 
 plugindir = $(PK_PLUGIN_DIR)
diff --git a/backends/conary/conaryFilter.py b/backends/conary/conaryFilter.py
new file mode 100644
index 0000000..f2b1a0b
--- /dev/null
+++ b/backends/conary/conaryFilter.py
@@ -0,0 +1,40 @@
+#!/usr/bin/python
+# Licensed under the GNU General Public License Version 2
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# Copyright (C) 2008
+#    Richard Hughes <richard at hughsie.com>
+
+# imports
+from packagekit.filter import *
+
+import re
+
+class ConaryFilter(PackagekitFilter):
+
+    def _pkg_get_unique(self, pkg):
+        '''
+        Return a unique string for the package
+        '''
+        return "%s-%s.%s" % (pkg[0], pkg[1], pkg[2])
+
+    def _pkg_is_devel(self, pkg):
+        '''
+        Return if the package is development.
+        '''
+        regex = re.compile(r'(:devel)')
+        return regex.search(pkg.name)
+
commit d12dcdbeefda2b15b690322103b1d0b36a0c3108
Author: Richard Hughes <richard at hughsie.com>
Date:   Fri Sep 26 19:16:01 2008 +0100

    yum: use the new PackagekitFilter abstract object

diff --git a/backends/yum/yumFilter.py b/backends/yum/yumFilter.py
index 7c5b712..9e1b563 100644
--- a/backends/yum/yumFilter.py
+++ b/backends/yum/yumFilter.py
@@ -20,17 +20,13 @@
 
 # imports
 from packagekit.enums import *
-from packagekit.package import PackagekitPackage
+from packagekit.filter import *
 
 import rpmUtils
 import re
 
 GUI_KEYS = re.compile(r'(qt)|(gtk)')
 
-def _get_nevra(pkg):
-    ''' gets the NEVRA for a pkg '''
-    return "%s-%s:%s-%s.%s" % (pkg.name, pkg.epoch, pkg.version, pkg.release, pkg.arch)
-
 def _is_main_package(repo):
     if repo.endswith('-debuginfo'):
         return False
@@ -52,43 +48,6 @@ def _do_newest_filtering(pkglist):
         newest[key] = (pkg, state)
     return newest.values()
 
-def _do_installed_filtering(flt, pkg):
-    is_installed = False
-    if flt == FILTER_INSTALLED:
-        want_installed = True
-    else:
-        want_installed = False
-    is_installed = pkg.repo.id == 'installed'
-    return is_installed == want_installed
-
-def _check_for_gui(pkg):
-    '''  Check if the GUI_KEYS regex matches any package requirements'''
-    for req in pkg.requires:
-        reqname = req[0]
-        if GUI_KEYS.search(reqname):
-            return True
-    return False
-
-def _do_devel_filtering(flt, pkg):
-    is_devel = False
-    if flt == FILTER_DEVELOPMENT:
-        want_devel = True
-    else:
-        want_devel = False
-    regex =  re.compile(r'(-devel)|(-debuginfo)|(-static)|(-libs)')
-    if regex.search(pkg.name):
-        is_devel = True
-    return is_devel == want_devel
-
-def _do_gui_filtering(flt, pkg):
-    is_gui = False
-    if flt == FILTER_GUI:
-        want_gui = True
-    else:
-        want_gui = False
-    is_gui = _check_for_gui(pkg)
-    return is_gui == want_gui
-
 def _basename_filter(package_list):
     '''
     Filter the list so that the number of packages are reduced.
@@ -132,35 +91,7 @@ def _basename_filter(package_list):
             base_list_already_got.append ((base, version))
     return output_list
 
-class YumFilter(object, PackagekitPackage):
-
-    def __init__(self, fltlist="none"):
-        ''' connect to all enabled repos '''
-        self.fltlist = fltlist
-        self.package_list = [] #we can't do emitting as found if we are post-processing
-        self.installed_nevra = []
-
-    def add_installed(self, pkgs):
-        ''' add a list of packages that are already installed '''
-        for pkg in pkgs:
-            if self.pre_process(pkg):
-                self.package_list.append((pkg, INFO_INSTALLED))
-            self.installed_nevra.append(_get_nevra(pkg))
-
-    def add_available(self, pkgs):
-        # add a list of packages that are available
-        for pkg in pkgs:
-            nevra = _get_nevra(pkg)
-            if nevra not in self.installed_nevra:
-                if self.pre_process(pkg):
-                    self.package_list.append((pkg, INFO_AVAILABLE))
-
-    def add_custom(self, pkg, info):
-        ''' add a custom packages indervidually '''
-        nevra = _get_nevra(pkg)
-        if nevra not in self.installed_nevra:
-            if self.pre_process(pkg):
-                self.package_list.append((pkg, info))
+class YumFilter(PackagekitFilter):
 
     def post_process(self):
         ''' do filtering we couldn't do when generating the list '''
@@ -173,31 +104,38 @@ class YumFilter(object, PackagekitPackage):
 
         return self.package_list
 
-    def pre_process(self, pkg):
-        ''' do extra filtering (gui, devel etc) '''
-        for flt in self.fltlist:
-            if flt in (FILTER_INSTALLED, FILTER_NOT_INSTALLED):
-                if not _do_installed_filtering(flt, pkg):
-                    return False
-            elif flt in (FILTER_GUI, FILTER_NOT_GUI):
-                if not _do_gui_filtering(flt, pkg):
-                    return False
-            elif flt in (FILTER_DEVELOPMENT, FILTER_NOT_DEVELOPMENT):
-                if not _do_devel_filtering(flt, pkg):
-                    return False
-            elif flt in (FILTER_FREE, FILTER_NOT_FREE):
-                if not self._do_free_filtering(flt, pkg):
-                    return False
-        return True
-
-    def _do_free_filtering(self, flt, pkg):
-        is_free = False
-        if flt == FILTER_FREE:
-            want_free = True
-        else:
-            want_free = False
-
-        is_free = self.check_license_field(pkg.license)
+    def _pkg_get_unique(self, pkg):
+        '''
+        Return a unique string for the package
+        '''
+        return "%s-%s:%s-%s.%s" % (pkg.name, pkg.epoch, pkg.version, pkg.release, pkg.arch)
+
+    def _pkg_is_installed(self, pkg):
+        '''
+        Return if the package is installed.
+        '''
+        return pkg.repo.id == 'installed'
+
+    def _pkg_is_devel(self, pkg):
+        '''
+        Return if the package is development.
+        '''
+        regex = re.compile(r'(-devel)|(-debuginfo)|(-static)|(-libs)')
+        return regex.search(pkg.name)
+
+    def _pkg_is_gui(self, pkg):
+        '''
+        Return if the package is a GUI program.
+        '''
+        for req in pkg.requires:
+            reqname = req[0]
+            if GUI_KEYS.search(reqname):
+                return True
+        return False
 
-        return is_free == want_free
+    def _pkg_is_free(self, pkg):
+        '''
+        Return if the package is free software.
+        '''
+        return self.check_license_field(pkg.license)
 
commit 87d079157662560caf17017567d3c42299acebc7
Author: Richard Hughes <richard at hughsie.com>
Date:   Fri Sep 26 19:15:22 2008 +0100

    feature: add an abstract filter object as backends keep getting this wrong

diff --git a/python/packagekit/Makefile.am b/python/packagekit/Makefile.am
index 410f021..1493596 100644
--- a/python/packagekit/Makefile.am
+++ b/python/packagekit/Makefile.am
@@ -17,7 +17,8 @@ packagekitpython_PYTHON =				\
 	progress.py					\
 	package.py					\
 	client.py					\
-	misc.py					\
+	filter.py					\
+	misc.py						\
 	$(NULL)
 
 clean-local :
diff --git a/python/packagekit/filter.py b/python/packagekit/filter.py
new file mode 100644
index 0000000..a64c012
--- /dev/null
+++ b/python/packagekit/filter.py
@@ -0,0 +1,145 @@
+#!/usr/bin/python
+# Licensed under the GNU General Public License Version 2
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# Copyright (C) 2008
+#    Richard Hughes <richard at hughsie.com>
+
+# imports
+from enums import *
+from package import PackagekitPackage
+
+class PackagekitFilter(object, PackagekitPackage):
+
+    def __init__(self, fltlist="none"):
+        ''' save state '''
+        self.fltlist = fltlist
+        self.package_list = [] #we can't do emitting as found if we are post-processing
+        self.installed_unique = []
+
+    def add_installed(self, pkgs):
+        ''' add a list of packages that are already installed '''
+        for pkg in pkgs:
+            if self.pre_process(pkg):
+                self.package_list.append((pkg, INFO_INSTALLED))
+            self.installed_unique.append(self._pkg_get_unique(pkg))
+
+    def add_available(self, pkgs):
+        ''' add a list of packages that are available '''
+        for pkg in pkgs:
+            nevra = self._pkg_get_unique(pkg)
+            if nevra not in self.installed_unique:
+                if self.pre_process(pkg):
+                    self.package_list.append((pkg, INFO_AVAILABLE))
+
+    def add_custom(self, pkg, info):
+        ''' add a custom packages indervidually '''
+        nevra = self._pkg_get_unique(pkg)
+        if nevra not in self.installed_unique:
+            if self.pre_process(pkg):
+                self.package_list.append((pkg, info))
+
+    def pre_process(self, pkg):
+        ''' do extra filtering (gui, devel etc) '''
+        for flt in self.fltlist:
+            if flt in (FILTER_INSTALLED, FILTER_NOT_INSTALLED):
+                if not self._do_installed_filtering(flt, pkg):
+                    return False
+            elif flt in (FILTER_GUI, FILTER_NOT_GUI):
+                if not self._do_gui_filtering(flt, pkg):
+                    return False
+            elif flt in (FILTER_DEVELOPMENT, FILTER_NOT_DEVELOPMENT):
+                if not self._do_devel_filtering(flt, pkg):
+                    return False
+            elif flt in (FILTER_FREE, FILTER_NOT_FREE):
+                if not self._do_free_filtering(flt, pkg):
+                    return False
+        return True
+
+    def post_process(self):
+        '''
+        do filtering we couldn't do when generating the list
+        Needed to be implemented in a sub class
+        '''
+        return self.package_list
+
+    def _pkg_get_unique(self, pkg):
+        '''
+        Return a unique string for the package
+        Needed to be implemented in a sub class
+        '''
+        return True
+
+    def _pkg_is_installed(self, pkg):
+        '''
+        Return if the package is installed.
+        Needed to be implemented in a sub class
+        '''
+        return True
+
+    def _pkg_is_devel(self, pkg):
+        '''
+        Return if the package is development.
+        Needed to be implemented in a sub class
+        '''
+        return True
+
+    def _pkg_is_gui(self, pkg):
+        '''
+        Return if the package is a GUI program.
+        Needed to be implemented in a sub class
+        '''
+        return True
+
+    def _pkg_is_free(self, pkg):
+        '''
+        Return if the package is free software.
+        Needed to be implemented in a sub class
+        '''
+        return True
+
+    def _do_installed_filtering(self, flt, pkg):
+        is_installed = self._pkg_is_installed(pkg)
+        if flt == FILTER_INSTALLED:
+            want_installed = True
+        else:
+            want_installed = False
+        return is_installed == want_installed
+
+    def _do_devel_filtering(self, flt, pkg):
+        is_devel = self._pkg_is_devel(pkg)
+        if flt == FILTER_DEVELOPMENT:
+            want_devel = True
+        else:
+            want_devel = False
+        return is_devel == want_devel
+
+    def _do_gui_filtering(self, flt, pkg):
+        is_gui = self._pkg_is_gui(pkg)
+        if flt == FILTER_GUI:
+            want_gui = True
+        else:
+            want_gui = False
+        return is_gui == want_gui
+
+    def _do_free_filtering(self, flt, pkg):
+        is_free = self._pkg_is_free(pkg)
+        if flt == FILTER_FREE:
+            want_free = True
+        else:
+            want_free = False
+        return is_free == want_free
+
commit b0de1d54b7185bf42c0ee0540c261765abc4cebd
Author: Richard Hughes <richard at hughsie.com>
Date:   Fri Sep 26 18:28:43 2008 +0100

    conary: small trivial fixes

diff --git a/backends/conary/conaryBackend.py b/backends/conary/conaryBackend.py
index b9ecbe4..71f60cb 100644
--- a/backends/conary/conaryBackend.py
+++ b/backends/conary/conaryBackend.py
@@ -20,6 +20,7 @@
 
 import sys
 import os
+import re
 
 from conary import errors
 from conary.deps import deps
@@ -124,6 +125,25 @@ def ExceptionHandler(func):
             self.error(ERROR_UNKNOWN, display(e), exit=True)
     return wrapper
 
+def _format_str(str):
+    """
+    Convert a multi line string to a list separated by ';'
+    """
+    if str:
+        lines = str.split('\n')
+        return ";".join(lines)
+    else:
+        return ""
+
+def _format_list(lst):
+    """
+    Convert a multi line string to a list separated by ';'
+    """
+    if lst:
+        return ";".join(lst)
+    else:
+        return ""
+
 class PackageKitConaryBackend(PackageKitBaseBackend):
     # Packages there require a reboot
     rebootpkgs = ("kernel", "glibc", "hal", "dbus")
@@ -387,7 +407,7 @@ class PackageKitConaryBackend(PackageKitBaseBackend):
         '''
         Implement the {backend}-update functionality
         '''
-        self.allow_cancel(True);
+        self.allow_cancel(True)
         self.percentage(0)
         self.status(STATUS_RUNNING)
 
@@ -474,15 +494,6 @@ class PackageKitConaryBackend(PackageKitBaseBackend):
             result = trove.getMetadata()[field]
         return result
 
-    def _format_list(self, lst):
-        """
-        Convert a multi line string to a list separated by ';'
-        """
-        if lst:
-            return ";".join(lst)
-        else:
-            return ""
-
     def _get_update_extras(self, id):
         notice = self._get_metadata(id, 'notice') or " "
         urls = {'jira':[], 'cve' : [], 'vendor': []}
@@ -505,10 +516,10 @@ class PackageKitConaryBackend(PackageKitBaseBackend):
 
             # Reboot flag
             if notice.get_metadata().has_key('reboot_suggested') and notice['reboot_suggested']:
-                                reboot = 'system'
+                reboot = 'system'
             else:
                 reboot = 'none'
-            return self._format_str(desc), urls, reboot
+            return _format_str(desc), urls, reboot
         else:
             return "", urls, "none"
 
@@ -529,11 +540,11 @@ class PackageKitConaryBackend(PackageKitBaseBackend):
         update = ""
         obsolete = ""
         #desc, urls, reboot = self._get_update_extras(id)
-        #cve_url = self._format_list(urls['cve'])
+        #cve_url = _format_list(urls['cve'])
         cve_url = ""
-        #bz_url = self._format_list(urls['jira'])
+        #bz_url = _format_list(urls['jira'])
         bz_url = ""
-        #vendor_url = self._format_list(urls['vendor'])
+        #vendor_url = _format_list(urls['vendor'])
         vendor_url = ""
         reboot = "none"
         desc = self._get_metadata(id, 'longDesc') or " "
@@ -612,7 +623,7 @@ class PackageKitConaryBackend(PackageKitBaseBackend):
     def _do_filtering(self, pkg, filterList, installed):
         ''' Filter the package, based on the filter in filterList '''
         # do we print to stdout?
-        do_print = False;
+        do_print = False
         if filterList == ['none']: # 'none' = all packages.
             return True
         elif FILTER_INSTALLED in filterList and installed == INFO_INSTALLED:
@@ -631,10 +642,10 @@ class PackageKitConaryBackend(PackageKitBaseBackend):
     def _do_extra_filtering(self, pkg, filterList):
         ''' do extra filtering (devel etc) '''
 
-        for filter in filterList:
-            if filter in (FILTER_INSTALLED, FILTER_NOT_INSTALLED):
+        for flt in filterList:
+            if flt in (FILTER_INSTALLED, FILTER_NOT_INSTALLED):
                 continue
-            elif filter in (FILTER_DEVELOPMENT, FILTER_NOT_DEVELOPMENT):
+            elif flt in (FILTER_DEVELOPMENT, FILTER_NOT_DEVELOPMENT):
                 if not self._do_devel_filtering(flt, pkg):
                     return False
         return True
@@ -694,8 +705,8 @@ class Cache(object):
     dbPath = '/var/cache/conary/'
     jobPath = dbPath + 'jobs'
 
-    """ Class to retrieve and cache package information from label. """
     def __init__(self):
+        """ Class to retrieve and cache package information from label. """
         if not os.path.isdir(self.dbPath):
             os.makedirs(self.dbPath)
         if not os.path.isdir(self.jobPath):
commit d8a2c113d040af8bbf27ea27860f8d70086691f5
Author: Richard Hughes <richard at hughsie.com>
Date:   Fri Sep 26 18:15:29 2008 +0100

    trivial: move some of the methods in yumBackend into functions, and get rid of the handle_repo_error decorator

diff --git a/backends/yum/yumBackend.py b/backends/yum/yumBackend.py
index 63167fe..9441476 100755
--- a/backends/yum/yumBackend.py
+++ b/backends/yum/yumBackend.py
@@ -76,6 +76,106 @@ def sigquit(signum, frame):
         yumbase.doUnlock(YUM_PID_FILE)
     sys.exit(1)
 
+def _to_unicode(txt, encoding='utf-8'):
+    if isinstance(txt, basestring):
+        if not isinstance(txt, unicode):
+            txt = unicode(txt, encoding, errors='replace')
+    return txt
+
+def _get_package_ver(po):
+    ''' return the a ver as epoch:version-release or version-release, if epoch=0'''
+    if po.epoch != '0':
+        ver = "%s:%s-%s" % (po.epoch, po.version, po.release)
+    else:
+        ver = "%s-%s" % (po.version, po.release)
+    return ver
+
+def _format_str(str):
+    """
+    Convert a multi line string to a list separated by ';'
+    """
+    if str:
+        lines = str.split('\n')
+        return ";".join(lines)
+    else:
+        return ""
+
+def _format_list(lst):
+    """
+    Convert a multi line string to a list separated by ';'
+    """
+    if lst:
+        return ";".join(lst)
+    else:
+        return ""
+
+def _get_status(notice):
+    ut = notice['type']
+    if ut == 'security':
+        return INFO_SECURITY
+    elif ut == 'bugfix':
+        return INFO_BUGFIX
+    elif ut == 'enhancement':
+        return INFO_ENHANCEMENT
+    else:
+        return INFO_UNKNOWN
+
+def _getEVR(idver):
+    '''
+    get the e, v, r from the package id version
+    '''
+    cpos = idver.find(':')
+    if cpos != -1:
+        epoch = idver[:cpos]
+        idver = idver[cpos+1:]
+    else:
+        epoch = '0'
+    (version, release) = tuple(idver.split('-'))
+    return epoch, version, release
+
+def _text_to_boolean(text):
+    '''
+    Parses true and false
+    '''
+    if text == 'true':
+        return True
+    if text == 'TRUE':
+        return True
+    if text == 'yes':
+        return True
+    if text == 'YES':
+        return True
+    return False
+
+def _truncate(text, length, etc='...'):
+    if len(text) < length:
+        return text
+    else:
+        return text[:length] + etc
+
+def _is_development_repo(repo):
+    if repo.endswith('-debuginfo'):
+        return True
+    if repo.endswith('-testing'):
+        return True
+    if repo.endswith('-debug'):
+        return True
+    if repo.endswith('-development'):
+        return True
+    if repo.endswith('-source'):
+        return True
+    return False
+
+def _format_msgs(msgs):
+    if isinstance(msgs, basestring):
+        msgs = msgs.split('\n')
+    text = ";".join(msgs)
+    text = _truncate(text, 1024)
+    text = text.replace(";Please report this error in bugzilla", "")
+    text = text.replace("Missing Dependency: ", "")
+    text = text.replace(" (installed)", "")
+    return text
+
 class PackageKitYumBackend(PackageKitBaseBackend, PackagekitPackage):
 
     # Packages there require a reboot
@@ -83,22 +183,6 @@ class PackageKitYumBackend(PackageKitBaseBackend, PackagekitPackage):
               "kernel-xen0", "kernel-xenU", "kernel-xen", "kernel-xen-guest",
               "glibc", "hal", "dbus", "xen")
 
-    def handle_repo_error(func):
-        def wrapper(*args, **kwargs):
-            self = args[0]
-
-            try:
-                func(*args, **kwargs)
-            except yum.Errors.RepoError, e:
-                self._refresh_yum_cache()
-
-                try:
-                    func(*args, **kwargs)
-                except yum.Errors.RepoError, e:
-                    self.error(ERROR_NO_CACHE, str(e))
-
-        return wrapper
-
     def __init__(self, args, lock=True):
         signal.signal(signal.SIGQUIT, sigquit)
         PackageKitBaseBackend.__init__(self, args)
@@ -110,6 +194,7 @@ class PackageKitYumBackend(PackageKitBaseBackend, PackagekitPackage):
             if not self.comps.connect():
                 self.error(ERROR_GROUP_LIST_INVALID, 'comps categories could not be loaded')
 
+        # this is global so we can catch sigquit and closedown
         yumbase = self.yumbase
         self._setup_yum()
         if lock:
@@ -126,7 +211,7 @@ class PackageKitYumBackend(PackageKitBaseBackend, PackagekitPackage):
         @param bytes: The size of the package, in bytes
         convert the description to UTF before sending
         '''
-        desc = self._to_unicode(desc)
+        desc = _to_unicode(desc)
         PackageKitBaseBackend.details(self, package_id, package_license, group, desc, url, bytes)
 
     def package(self, package_id, status, summary):
@@ -137,15 +222,9 @@ class PackageKitYumBackend(PackageKitBaseBackend, PackagekitPackage):
         @param summary: The package Summary
         convert the summary to UTF before sending
         '''
-        summary = self._to_unicode(summary)
+        summary = _to_unicode(summary)
         PackageKitBaseBackend.package(self, package_id, status, summary)
 
-    def _to_unicode(self, txt, encoding='utf-8'):
-        if isinstance(txt, basestring):
-            if not isinstance(txt, unicode):
-                txt = unicode(txt, encoding, errors='replace')
-        return txt
-
     def doLock(self):
         ''' Lock Yum'''
         retries = 0
@@ -153,11 +232,11 @@ class PackageKitYumBackend(PackageKitBaseBackend, PackagekitPackage):
             try: # Try to lock yum
                 self.yumbase.doLock(YUM_PID_FILE)
                 PackageKitBaseBackend.doLock(self)
-            except:
+            except yum.Errors.LockError, e:
                 time.sleep(2)
                 retries += 1
                 if retries > 100:
-                    self.error(ERROR_CANNOT_GET_LOCK, 'Yum is locked by another application')
+                    self.error(ERROR_CANNOT_GET_LOCK, 'Yum is locked by another application. details: %s' % str(e))
 
     def unLock(self):
         ''' Unlock Yum'''
@@ -166,23 +245,11 @@ class PackageKitYumBackend(PackageKitBaseBackend, PackagekitPackage):
             self.yumbase.closeRpmDB()
             self.yumbase.doUnlock(YUM_PID_FILE)
 
-    def _get_package_ver(self, po):
-        ''' return the a ver as epoch:version-release or version-release, if epoch=0'''
-        if po.epoch != '0':
-            ver = "%s:%s-%s" % (po.epoch, po.version, po.release)
-        else:
-            ver = "%s-%s" % (po.version, po.release)
-        return ver
-
-    def _get_nevra(self, pkg):
-        ''' gets the NEVRA for a pkg '''
-        return "%s-%s:%s-%s.%s" % (pkg.name, pkg.epoch, pkg.version, pkg.release, pkg.arch)
-
-    def _do_meta_package_search(self, filters, key):
+    def _do_meta_package_search(self, fltlist, key):
         grps = self.comps.get_meta_packages()
         for grpid in grps:
             if key in grpid:
-                self._show_meta_package(grpid, filters)
+                self._show_meta_package(grpid, fltlist)
 
     def set_locale(self, code):
         '''
@@ -191,7 +258,6 @@ class PackageKitYumBackend(PackageKitBaseBackend, PackagekitPackage):
         '''
         self._lang = code
 
-    @handle_repo_error
     def _do_search(self, searchlist, filters, key):
         '''
         Search for yum packages
@@ -199,31 +265,35 @@ class PackageKitYumBackend(PackageKitBaseBackend, PackagekitPackage):
         @param filters: package types to search (all, installed, available)
         @param key: key to seach for
         '''
-        res = self.yumbase.searchGenerator(searchlist, [key])
-        fltlist = filters.split(';')
-        pkgfilter = YumFilter(fltlist)
-        package_list = [] #we can't do emitting as found if we are post-processing
-        installed = []
-        available = []
+        try:
+            res = self.yumbase.searchGenerator(searchlist, [key])
+        except yum.Errors.RepoError, e:
+            self.error(ERROR_NO_CACHE, str(e))
+        else:
+            fltlist = filters.split(';')
+            pkgfilter = YumFilter(fltlist)
+            package_list = [] #we can't do emitting as found if we are post-processing
+            installed = []
+            available = []
 
-        if FILTER_NOT_COLLECTIONS not in fltlist:
-            self._do_meta_package_search(fltlist, key)
+            if FILTER_NOT_COLLECTIONS not in fltlist:
+                self._do_meta_package_search(fltlist, key)
 
-        if FILTER_COLLECTIONS in fltlist:
-            return
+            if FILTER_COLLECTIONS in fltlist:
+                return
 
-        for (pkg, values) in res:
-            if pkg.repo.id == 'installed':
-                installed.append(pkg)
-            else:
-                available.append(pkg)
+            for (pkg, _) in res:
+                if pkg.repo.id == 'installed':
+                    installed.append(pkg)
+                else:
+                    available.append(pkg)
 
-        pkgfilter.add_installed(installed)
-        pkgfilter.add_available(available)
+            pkgfilter.add_installed(installed)
+            pkgfilter.add_available(available)
 
-        # we couldn't do this when generating the list
-        package_list = pkgfilter.post_process()
-        self._show_package_list(package_list)
+            # we couldn't do this when generating the list
+            package_list = pkgfilter.post_process()
+            self._show_package_list(package_list)
 
     def _show_package_list(self, lst):
         for (pkg, status) in lst:
@@ -287,7 +357,7 @@ class PackageKitYumBackend(PackageKitBaseBackend, PackagekitPackage):
             self._show_meta_package(col, fltlist)
         self.percentage(100)
 
-    def _show_meta_package(self, grpid, fltlist=[]):
+    def _show_meta_package(self, grpid, fltlist):
         show_avail = FILTER_INSTALLED not in fltlist
         show_inst = FILTER_NOT_INSTALLED not in fltlist
         package_id = "%s;;;meta" % grpid
@@ -301,7 +371,6 @@ class PackageKitYumBackend(PackageKitBaseBackend, PackagekitPackage):
                 if show_avail:
                     self.package(package_id, INFO_COLLECTION_AVAILABLE, name)
 
-    #@handle_repo_error
     def search_group(self, filters, group_key):
         '''
         Implement the {backend}-search-group functionality
@@ -315,8 +384,7 @@ class PackageKitYumBackend(PackageKitBaseBackend, PackagekitPackage):
         fltlist = filters.split(';')
         pkgfilter = YumFilter(fltlist)
 
-        # Handle collections
-        # FIXME: add the right enum here
+        # handle collections
         if group_key == GROUP_COLLECTIONS:
             self._handle_collections(fltlist)
             return
@@ -345,7 +413,6 @@ class PackageKitYumBackend(PackageKitBaseBackend, PackagekitPackage):
 
         self.percentage(100)
 
-    @handle_repo_error
     def get_packages(self, filters):
         '''
         Search for yum packages
@@ -368,14 +435,17 @@ class PackageKitYumBackend(PackageKitBaseBackend, PackagekitPackage):
 
         # Now show available packages.
         if FILTER_INSTALLED not in fltlist:
-            pkgs = self.yumbase.pkgSack
-            pkgfilter.add_available(pkgs)
+            try:
+                pkgs = self.yumbase.pkgSack
+            except yum.Errors.RepoError, e:
+                self.error(ERROR_NO_CACHE, str(e))
+            else:
+                pkgfilter.add_available(pkgs)
 
         # we couldn't do this when generating the list
         package_list = pkgfilter.post_process()
         self._show_package_list(package_list)
 
-    @handle_repo_error
     def search_file(self, filters, key):
         '''
         Implement the {backend}-search-file functionality
@@ -397,15 +467,18 @@ class PackageKitYumBackend(PackageKitBaseBackend, PackagekitPackage):
         # Check available for file
         if not FILTER_INSTALLED in fltlist:
             # Check available for file
-            self.yumbase.repos.populateSack(mdtype='filelists')
-            pkgs = self.yumbase.pkgSack.searchFiles(key)
-            pkgfilter.add_available(pkgs)
+            try:
+                self.yumbase.repos.populateSack(mdtype='filelists')
+                pkgs = self.yumbase.pkgSack.searchFiles(key)
+            except yum.Errors.RepoError, e:
+                self.error(ERROR_NO_CACHE, str(e))
+            else:
+                pkgfilter.add_available(pkgs)
 
         # we couldn't do this when generating the list
         package_list = pkgfilter.post_process()
         self._show_package_list(package_list)
 
-    @handle_repo_error
     def what_provides(self, filters, provides_type, search):
         '''
         Implement the {backend}-what-provides functionality
@@ -425,14 +498,17 @@ class PackageKitYumBackend(PackageKitBaseBackend, PackagekitPackage):
 
         if not FILTER_INSTALLED in fltlist:
             # Check available for file
-            pkgs = self.yumbase.pkgSack.searchProvides(search)
-            pkgfilter.add_available(pkgs)
+            try:
+                pkgs = self.yumbase.pkgSack.searchProvides(search)
+            except yum.Errors.RepoError, e:
+                self.error(ERROR_NO_CACHE, str(e))
+            else:
+                pkgfilter.add_available(pkgs)
 
         # we couldn't do this when generating the list
         package_list = pkgfilter.post_process()
         self._show_package_list(package_list)
 
-    @handle_repo_error
     def download_packages(self, directory, package_ids):
         '''
         Implement the {backend}-download-packages functionality
@@ -448,14 +524,17 @@ class PackageKitYumBackend(PackageKitBaseBackend, PackagekitPackage):
         # download each package
         for package in package_ids:
             self.percentage(percentage)
-            pkg, inst = self._findPackage(package)
+            pkg, _ = self._findPackage(package)
             # if we couldn't map package_id -> pkg
             if not pkg:
                 self.message(MESSAGE_COULD_NOT_FIND_PACKAGE, "Could not find the package %s" % package)
                 continue
 
             n, a, e, v, r = pkg.pkgtup
-            packs = self.yumbase.pkgSack.searchNevra(n, e, v, r, a)
+            try:
+                packs = self.yumbase.pkgSack.searchNevra(n, e, v, r, a)
+            except yum.Errors.RepoError, e:
+                self.error(ERROR_NO_CACHE, str(e))
 
             # if we couldn't map package_id -> pkg
             if len(packs) == 0:
@@ -487,29 +566,16 @@ class PackageKitYumBackend(PackageKitBaseBackend, PackagekitPackage):
 
         # emit the file list we downloaded
         file_list = ";".join(files)
-        self.files(package, file_list)
+        self.files(package_ids[0], file_list)
 
         # in case we don't sum to 100
         self.percentage(100)
 
-    def _getEVR(self, idver):
-        '''
-        get the e, v, r from the package id version
-        '''
-        cpos = idver.find(':')
-        if cpos != -1:
-            epoch = idver[:cpos]
-            idver = idver[cpos+1:]
-        else:
-            epoch = '0'
-        (version, release) = tuple(idver.split('-'))
-        return epoch, version, release
-
     def _is_meta_package(self, package_id):
         grp = None
         if len(package_id.split(';')) > 1:
             # Split up the id
-            (name, idver, a, repo) = self.get_package_from_id(package_id)
+            (name, _, _, repo) = self.get_package_from_id(package_id)
             if repo == 'meta':
                 grp = self.yumbase.comps.return_group(name)
                 if not grp:
@@ -529,7 +595,7 @@ class PackageKitYumBackend(PackageKitBaseBackend, PackagekitPackage):
             # Split up the id
             (n, idver, a, d) = self.get_package_from_id(package_id)
             # get e, v, r from package id version
-            e, v, r = self._getEVR(idver)
+            e, v, r = _getEVR(idver)
         else:
             n = package_id
             e = v = r = a = d = None
@@ -556,29 +622,6 @@ class PackageKitYumBackend(PackageKitBaseBackend, PackagekitPackage):
         # repo id did not match
         return None, False
 
-    def _get_pkg_requirements(self, pkg, reqlist=[]):
-        pkgs = self.yumbase.rpmdb.searchRequires(pkg.name)
-        reqlist.extend(pkgs)
-        if pkgs:
-            for po in pkgs:
-                self._get_pkg_requirements(po, reqlist)
-        else:
-            return reqlist
-
-    def _text_to_boolean(self, text):
-        '''
-        Parses true and false
-        '''
-        if text == 'true':
-            return True
-        if text == 'TRUE':
-            return True
-        if text == 'yes':
-            return True
-        if text == 'YES':
-            return True
-        return False
-
     def get_requires(self, filters, package_ids, recursive_text):
         '''
         Print a list of requires for a given package
@@ -593,7 +636,7 @@ class PackageKitYumBackend(PackageKitBaseBackend, PackagekitPackage):
         bump = 100 / len(package_ids)
         deps_list = []
         resolve_list = []
-        recursive = self._text_to_boolean(recursive_text)
+        recursive = _text_to_boolean(recursive_text)
 
         for package in package_ids:
             self.percentage(percentage)
@@ -605,7 +648,7 @@ class PackageKitYumBackend(PackageKitBaseBackend, PackagekitPackage):
                     txmbr = self.yumbase.groupRemove(grp.groupid)
                     rc, msgs =  self.yumbase.buildTransaction()
                     if rc != 2:
-                        self.error(ERROR_DEP_RESOLUTION_FAILED, self._format_msgs(msgs))
+                        self.error(ERROR_DEP_RESOLUTION_FAILED, _format_msgs(msgs))
                     else:
                         for txmbr in self.yumbase.tsInfo:
                             deps_list.append(txmbr.po)
@@ -618,7 +661,7 @@ class PackageKitYumBackend(PackageKitBaseBackend, PackagekitPackage):
                     if txmbrs:
                         rc, msgs =  self.yumbase.buildTransaction()
                         if rc != 2:
-                            self.error(ERROR_DEP_RESOLUTION_FAILED, self._format_msgs(msgs))
+                            self.error(ERROR_DEP_RESOLUTION_FAILED, _format_msgs(msgs))
                         else:
                             for txmbr in self.yumbase.tsInfo:
                                 if pkg not in deps_list:
@@ -708,7 +751,7 @@ class PackageKitYumBackend(PackageKitBaseBackend, PackagekitPackage):
 
         # first try and find the highest EVR package that is already installed
         for pkgi in pkglist:
-            n, a, e, v, r = pkgi.pkgtup
+            n, a, e, v, _ = pkgi.pkgtup
             pkgs = self.yumbase.rpmdb.searchNevra(name=n, epoch=e, ver=v, arch=a)
             for pkg in pkgs:
                 if best:
@@ -797,10 +840,10 @@ class PackageKitYumBackend(PackageKitBaseBackend, PackagekitPackage):
                 if grp.installed:
                     self.error(ERROR_PACKAGE_ALREADY_INSTALLED, "The Group %s is already installed" % grp.groupid)
                 else:
-                    txmbr = self.yumbase.groupInstall(grp.groupid)
+                    txmbr = self.yumbase.selectGroup(grp.groupid)
                     rc, msgs =  self.yumbase.buildTransaction()
                     if rc != 2:
-                        self.error(ERROR_DEP_RESOLUTION_FAILED, self._format_msgs(msgs))
+                        self.error(ERROR_DEP_RESOLUTION_FAILED, _format_msgs(msgs))
                     else:
                         for txmbr in self.yumbase.tsInfo:
                             deps_list.append(txmbr.po)
@@ -813,7 +856,7 @@ class PackageKitYumBackend(PackageKitBaseBackend, PackagekitPackage):
                     if txmbrs:
                         rc, msgs =  self.yumbase.buildTransaction()
                         if rc != 2:
-                            self.error(ERROR_DEP_RESOLUTION_FAILED, self._format_msgs(msgs))
+                            self.error(ERROR_DEP_RESOLUTION_FAILED, _format_msgs(msgs))
                         else:
                             for txmbr in self.yumbase.tsInfo:
                                 if pkg not in deps_list:
@@ -841,13 +884,13 @@ class PackageKitYumBackend(PackageKitBaseBackend, PackagekitPackage):
         self.status(STATUS_INFO)
         fltlist = filters.split(';')
         pkgfilter = YumFilter(fltlist)
-        recursive = self._text_to_boolean(recursive_text)
+        recursive = _text_to_boolean(recursive_text)
 
         # before we do an install we do ~installed + recursive true,
         # which we can emulate quicker by doing a transaction, but not
         # executing it
         if filters == FILTER_NOT_INSTALLED and recursive:
-            self._get_depends_not_installed (fltlist, package_ids);
+            self._get_depends_not_installed (fltlist, package_ids)
             return
 
         percentage = 0
@@ -864,8 +907,7 @@ class PackageKitYumBackend(PackageKitBaseBackend, PackagekitPackage):
                 pkgs = self._get_group_packages(grp)
                 grp_pkgs.extend(pkgs)
             else:
-                name = package.split(';')[0]
-                pkg, inst = self._findPackage(package)
+                pkg, _ = self._findPackage(package)
                 if pkg:
                     resolve_list.append(pkg)
                 else:
@@ -958,7 +1000,7 @@ class PackageKitYumBackend(PackageKitBaseBackend, PackagekitPackage):
             self.percentage(100)
 
         except yum.Errors.RepoError, e:
-            message = self._format_msgs(e.value)
+            message = _format_msgs(e.value)
             if message.find ("No more mirrors to try") != -1:
                 self.error(ERROR_NO_MORE_MIRRORS_TO_TRY, message)
             else:
@@ -969,7 +1011,6 @@ class PackageKitYumBackend(PackageKitBaseBackend, PackagekitPackage):
         # update the comps groups too
         self.comps.refresh()
 
-    @handle_repo_error
     def resolve(self, filters, packages):
         '''
         Implement the {backend}-resolve functionality
@@ -990,17 +1031,21 @@ class PackageKitYumBackend(PackageKitBaseBackend, PackagekitPackage):
                     self._show_package(pkg, INFO_INSTALLED)
             # Get available packages
             if FILTER_INSTALLED not in fltlist:
-                for pkg in self.yumbase.pkgSack.returnNewestByNameArch():
-                    if pkg.name == package:
-                        show = True
-                        for instpo in installedByKey:
-                            # Check if package have a smaller & equal EVR to a inst pkg
-                            if pkg.EVR < instpo.EVR or pkg.EVR == instpo.EVR:
-                                show = False
-                        if show:
-                            self._show_package(pkg, INFO_AVAILABLE)
-
-    @handle_repo_error
+                try:
+                    pkgs = self.yumbase.pkgSack.returnNewestByNameArch()
+                except yum.Errors.RepoError, e:
+                    self.error(ERROR_NO_CACHE, str(e))
+                else:
+                    for pkg in pkgs:
+                        if pkg.name == package:
+                            show = True
+                            for instpo in installedByKey:
+                                # Check if package have a smaller & equal EVR to a inst pkg
+                                if pkg.EVR < instpo.EVR or pkg.EVR == instpo.EVR:
+                                    show = False
+                            if show:
+                                self._show_package(pkg, INFO_AVAILABLE)
+
     def install_packages(self, package_ids):
         '''
         Implement the {backend}-install-packages functionality
@@ -1227,7 +1272,7 @@ class PackageKitYumBackend(PackageKitBaseBackend, PackagekitPackage):
         txmbrs = []
         try:
             for package in package_ids:
-                pkg, inst = self._findPackage(package)
+                pkg, _ = self._findPackage(package)
                 if pkg:
                     txmbr = self.yumbase.update(po=pkg)
                     txmbrs.extend(txmbr)
@@ -1251,22 +1296,6 @@ class PackageKitYumBackend(PackageKitBaseBackend, PackagekitPackage):
                 self.require_restart(RESTART_SYSTEM, "")
                 break
 
-    def _truncate(self, text, length, etc='...'):
-        if len(text) < length:
-            return text
-        else:
-            return text[:length] + etc
-
-    def _format_msgs(self, msgs):
-        if isinstance(msgs, basestring):
-            msgs = msgs.split('\n')
-        text = ";".join(msgs)
-        text = self._truncate(text, 1024)
-        text = text.replace(";Please report this error in bugzilla", "")
-        text = text.replace("Missing Dependency: ", "")
-        text = text.replace(" (installed)", "")
-        return text
-
     def _runYumTransaction(self, removedeps=None):
         '''
         Run the yum Transaction
@@ -1277,7 +1306,7 @@ class PackageKitYumBackend(PackageKitBaseBackend, PackagekitPackage):
         except yum.Errors.RepoError, e:
             self.error(ERROR_REPO_NOT_AVAILABLE, str(e))
         if rc != 2:
-            self.error(ERROR_DEP_RESOLUTION_FAILED, self._format_msgs(msgs))
+            self.error(ERROR_DEP_RESOLUTION_FAILED, _format_msgs(msgs))
         else:
             self._check_for_reboot()
             if removedeps == False:
@@ -1292,9 +1321,9 @@ class PackageKitYumBackend(PackageKitBaseBackend, PackagekitPackage):
                 self.yumbase.processTransaction(callback=callback,
                                       rpmDisplay=rpmDisplay)
             except yum.Errors.YumDownloadError, ye:
-                self.error(ERROR_PACKAGE_DOWNLOAD_FAILED, self._format_msgs(ye.value))
+                self.error(ERROR_PACKAGE_DOWNLOAD_FAILED, _format_msgs(ye.value))
             except yum.Errors.YumGPGCheckError, ye:
-                self.error(ERROR_BAD_GPG_SIGNATURE, self._format_msgs(ye.value))
+                self.error(ERROR_BAD_GPG_SIGNATURE, _format_msgs(ye.value))
             except GPGKeyNotImported, e:
                 keyData = self.yumbase.missingGPGKey
                 if not keyData:
@@ -1315,7 +1344,7 @@ class PackageKitYumBackend(PackageKitBaseBackend, PackagekitPackage):
                                              'gpg')
                 self.error(ERROR_GPG_FAILURE, "GPG key %s required" % keyData['hexkeyid'])
             except yum.Errors.YumBaseError, ye:
-                message = self._format_msgs(ye.value)
+                message = _format_msgs(ye.value)
                 if message.find ("conflicts with file") != -1:
                     self.error(ERROR_FILE_CONFLICTS, message)
                 if message.find ("rpm_check_debug vs depsolve") != -1:
@@ -1389,7 +1418,7 @@ class PackageKitYumBackend(PackageKitBaseBackend, PackagekitPackage):
                 self.details(package_id, "", group, desc, "", size)
 
             else:
-                pkg, inst = self._findPackage(package)
+                pkg, _ = self._findPackage(package)
                 if pkg:
                     self._show_details_pkg(pkg)
                 else:
@@ -1397,7 +1426,7 @@ class PackageKitYumBackend(PackageKitBaseBackend, PackagekitPackage):
 
     def _show_details_pkg(self, pkg):
 
-        pkgver = self._get_package_ver(pkg)
+        pkgver = _get_package_ver(pkg)
         package_id = self.get_package_id(pkg.name, pkgver, pkg.arch, pkg.repo)
         desc = pkg.description
         desc = desc.replace('\n\n', ';')
@@ -1413,19 +1442,17 @@ class PackageKitYumBackend(PackageKitBaseBackend, PackagekitPackage):
         self.status(STATUS_INFO)
 
         for package in package_ids:
-            pkg, inst = self._findPackage(package)
+            pkg, _ = self._findPackage(package)
             if pkg:
                 files = pkg.returnFileEntries('dir')
                 files.extend(pkg.returnFileEntries()) # regular files
-
                 file_list = ";".join(files)
-
                 self.files(package, file_list)
             else:
                 self.error(ERROR_PACKAGE_NOT_FOUND, 'Package %s was not found' % package)
 
     def _pkg_to_id(self, pkg):
-        pkgver = self._get_package_ver(pkg)
+        pkgver = _get_package_ver(pkg)
         package_id = self.get_package_id(pkg.name, pkgver, pkg.arch, pkg.repo)
         return package_id
 
@@ -1434,17 +1461,6 @@ class PackageKitYumBackend(PackageKitBaseBackend, PackagekitPackage):
         package_id = self._pkg_to_id(pkg)
         self.package(package_id, status, pkg.summary)
 
-    def _get_status(self, notice):
-        ut = notice['type']
-        if ut == 'security':
-            return INFO_SECURITY
-        elif ut == 'bugfix':
-            return INFO_BUGFIX
-        elif ut == 'enhancement':
-            return INFO_ENHANCEMENT
-        else:
-            return INFO_UNKNOWN
-
     def get_distro_upgrades(self):
         '''
         Implement the {backend}-get-distro-upgrades functionality
@@ -1535,11 +1551,11 @@ class PackageKitYumBackend(PackageKitBaseBackend, PackagekitPackage):
             self.error(ERROR_REPO_NOT_AVAILABLE, str(e))
         md = self.updateMetadata
         for pkg in pkgs:
-            if pkgfilter._do_extra_filtering(pkg):
+            if pkgfilter.pre_process(pkg):
                 # Get info about package in updates info
                 notice = md.get_notice((pkg.name, pkg.version, pkg.release))
                 if notice:
-                    status = self._get_status(notice)
+                    status = _get_status(notice)
                     pkgfilter.add_custom(pkg, status)
                 else:
                     pkgfilter.add_custom(pkg, INFO_NORMAL)
@@ -1566,19 +1582,6 @@ class PackageKitYumBackend(PackageKitBaseBackend, PackagekitPackage):
         except yum.Errors.RepoError, e:
             self.error(ERROR_REPO_NOT_FOUND, str(e))
 
-    def _is_development_repo(self, repo):
-        if repo.endswith('-debuginfo'):
-            return True
-        if repo.endswith('-testing'):
-            return True
-        if repo.endswith('-debug'):
-            return True
-        if repo.endswith('-development'):
-            return True
-        if repo.endswith('-source'):
-            return True
-        return False
-
     def get_repo_list(self, filters):
         '''
         Implement the {backend}-get-repo-list functionality
@@ -1588,7 +1591,7 @@ class PackageKitYumBackend(PackageKitBaseBackend, PackagekitPackage):
         self.status(STATUS_INFO)
 
         for repo in self.yumbase.repos.repos.values():
-            if filters != FILTER_NOT_DEVELOPMENT or not self._is_development_repo(repo.id):
+            if filters != FILTER_NOT_DEVELOPMENT or not _is_development_repo(repo.id):
                 if repo.isEnabled():
                     self.repo_detail(repo.id, repo.name, 'true')
                 else:
@@ -1606,7 +1609,6 @@ class PackageKitYumBackend(PackageKitBaseBackend, PackagekitPackage):
         return ""
 
     def _get_updated(self, pkg):
-        updated = None
         pkgs = self.yumbase.rpmdb.searchNevra(name=pkg.name, arch=pkg.arch)
         if pkgs:
             return self._pkg_to_id(pkgs[0])
@@ -1626,25 +1628,6 @@ class PackageKitYumBackend(PackageKitBaseBackend, PackagekitPackage):
     _updateMetadata = None
     updateMetadata = property(fget=_get_update_metadata)
 
-    def _format_str(self, str):
-        """
-        Convert a multi line string to a list separated by ';'
-        """
-        if str:
-            lines = str.split('\n')
-            return ";".join(lines)
-        else:
-            return ""
-
-    def _format_list(self, lst):
-        """
-        Convert a multi line string to a list separated by ';'
-        """
-        if lst:
-            return ";".join(lst)
-        else:
-            return ""
-
     def _get_update_extras(self, pkg):
         md = self.updateMetadata
         notice = md.get_notice((pkg.name, pkg.version, pkg.release))
@@ -1686,7 +1669,7 @@ class PackageKitYumBackend(PackageKitBaseBackend, PackagekitPackage):
                 reboot = 'system'
             else:
                 reboot = 'none'
-            return self._format_str(desc), urls, reboot, changelog, state, issued, updated
+            return _format_str(desc), urls, reboot, changelog, state, issued, updated
         else:
             return "", urls, "none", '', '', '', ''
 
@@ -1700,13 +1683,13 @@ class PackageKitYumBackend(PackageKitBaseBackend, PackagekitPackage):
         self.percentage(None)
         self.status(STATUS_INFO)
         for package in package_ids:
-            pkg, inst = self._findPackage(package)
+            pkg, _ = self._findPackage(package)
             update = self._get_updated(pkg)
             obsolete = self._get_obsoleted(pkg.name)
             desc, urls, reboot, changelog, state, issued, updated = self._get_update_extras(pkg)
-            cve_url = self._format_list(urls['cve'])
-            bz_url = self._format_list(urls['bugzilla'])
-            vendor_url = self._format_list(urls['vendor'])
+            cve_url = _format_list(urls['cve'])
+            bz_url = _format_list(urls['bugzilla'])
+            vendor_url = _format_list(urls['vendor'])
             self.update_detail(package, update, obsolete, vendor_url, bz_url, cve_url, reboot, desc, changelog, state, issued, updated)
 
     def repo_set_data(self, repoid, parameter, value):
@@ -1732,7 +1715,7 @@ class PackageKitYumBackend(PackageKitBaseBackend, PackagekitPackage):
         self.allow_cancel(True)
         self.percentage(None)
         self.status(STATUS_INFO)
-        pkg, inst = self._findPackage(package)
+        pkg, _ = self._findPackage(package)
         if pkg:
             try:
                 self.yumbase.getKeyForPackage(pkg, askcb = lambda x, y, z: True)
@@ -1784,19 +1767,19 @@ class DownloadCallback(BaseMeter):
         self.oldName = None
         self.lastPct = 0
         self.totalPct = 0
-        self.pkgs = None
+        self.saved_pkgs = None
         self.numPkgs = 0
         self.bump = 0.0
 
     def setPackages(self, new_pkgs, startPct, numPct):
-        self.pkgs = new_pkgs
-        self.numPkgs = float(len(self.pkgs))
+        self.saved_pkgs = new_pkgs
+        self.numPkgs = float(len(self.saved_pkgs))
         self.bump = numPct/self.numPkgs
         self.totalPct = startPct
 
     def _getPackage(self, name):
-        if self.pkgs:
-            for pkg in self.pkgs:
+        if self.saved_pkgs:
+            for pkg in self.saved_pkgs:
                 if isinstance(pkg, YumLocalPackage):
                     rpmfn = pkg.localPkg
                 else:
@@ -1919,7 +1902,7 @@ class PackageKitCallback(RPMBaseCallback):
             # we don't know the summary text
             self.base.package(package_id, status, "")
         else:
-            pkgver = self.base._get_package_ver(self.curpkg)
+            pkgver = _get_package_ver(self.curpkg)
             package_id = self.base.get_package_id(self.curpkg.name, pkgver, self.curpkg.arch, self.curpkg.repo)
             self.base.package(package_id, status, self.curpkg.summary)
 
@@ -1930,7 +1913,7 @@ class PackageKitCallback(RPMBaseCallback):
                 self.base.status(self.state_actions[action])
                 self._showName(self.info_actions[action])
             except exceptions.KeyError, e:
-                self.base.message(MESSAGE_BACKEND_ERROR, "The constant '%s' was unknown, please report" % action)
+                self.base.message(MESSAGE_BACKEND_ERROR, "The constant '%s' was unknown, please report. details: %s" % (action, str(e)))
             pct = self._calcTotalPct(ts_current, ts_total)
             self.base.percentage(pct)
         val = (ts_current*100L)/ts_total
commit 4a0efc25f48396dc0f91a4f36164a1da407fa15c
Author: Richard Hughes <richard at hughsie.com>
Date:   Fri Sep 26 18:13:36 2008 +0100

    trivial: correct the groups database name, and make the variables in main static

diff --git a/backends/yum/yumComps.py b/backends/yum/yumComps.py
index 53e41f9..bcd9975 100755
--- a/backends/yum/yumComps.py
+++ b/backends/yum/yumComps.py
@@ -190,7 +190,7 @@ class yumComps:
         self.cursor = None
         self.connection = None
         if not db:
-            db = '/var/cache/yum/packagekit-groups-V2.sqlite'
+            db = '/var/cache/yum/packagekit-groups.sqlite'
         self.db = db
 
     def connect(self):
@@ -300,22 +300,22 @@ class yumComps:
 if __name__ == "__main__":
     import yum
     import os
-    yb = yum.YumBase()
-    db = "packagekit-groupsV2.sqlite"
-    comps = yumComps(yb, db)
+    _yb = yum.YumBase()
+    _db = "./packagekit-groups.sqlite"
+    comps = yumComps(_yb, _db)
     comps.connect()
     comps.refresh()
     print "pk group system"
     print 40 * "="
-    pkgs = comps.get_package_list('system')
-    print pkgs
+    _pkgs = comps.get_package_list('system')
+    print _pkgs
     print "comps group games"
     print 40 * "="
-    pkgs = comps.get_meta_package_list('games')
-    print pkgs
+    _pkgs = comps.get_meta_package_list('games')
+    print _pkgs
     print "comps group kde-desktop"
     print 40 * "="
-    pkgs = comps.get_meta_package_list('kde-desktop')
-    print pkgs
-    os.unlink(db) # kill the db
+    _pkgs = comps.get_meta_package_list('kde-desktop')
+    print _pkgs
+    os.unlink(_db) # kill the db
 
commit 3649b115e29e70e59b98162ba4249dba145e7916
Author: Richard Hughes <richard at hughsie.com>
Date:   Fri Sep 26 18:11:51 2008 +0100

    trivial: move some of the methods in yumFilter into functions

diff --git a/backends/yum/yumFilter.py b/backends/yum/yumFilter.py
index 1888fd4..7c5b712 100644
--- a/backends/yum/yumFilter.py
+++ b/backends/yum/yumFilter.py
@@ -27,6 +27,111 @@ import re
 
 GUI_KEYS = re.compile(r'(qt)|(gtk)')
 
+def _get_nevra(pkg):
+    ''' gets the NEVRA for a pkg '''
+    return "%s-%s:%s-%s.%s" % (pkg.name, pkg.epoch, pkg.version, pkg.release, pkg.arch)
+
+def _is_main_package(repo):
+    if repo.endswith('-debuginfo'):
+        return False
+    if repo.endswith('-devel'):
+        return False
+    if repo.endswith('-libs'):
+        return False
+    return True
+
+def _do_newest_filtering(pkglist):
+    '''
+    Only return the newest package for each name.arch
+    '''
+    newest = {}
+    for pkg, state in pkglist:
+        key = (pkg.name, pkg.arch)
+        if key in newest and pkg <= newest[key][0]:
+            continue
+        newest[key] = (pkg, state)
+    return newest.values()
+
+def _do_installed_filtering(flt, pkg):
+    is_installed = False
+    if flt == FILTER_INSTALLED:
+        want_installed = True
+    else:
+        want_installed = False
+    is_installed = pkg.repo.id == 'installed'
+    return is_installed == want_installed
+
+def _check_for_gui(pkg):
+    '''  Check if the GUI_KEYS regex matches any package requirements'''
+    for req in pkg.requires:
+        reqname = req[0]
+        if GUI_KEYS.search(reqname):
+            return True
+    return False
+
+def _do_devel_filtering(flt, pkg):
+    is_devel = False
+    if flt == FILTER_DEVELOPMENT:
+        want_devel = True
+    else:
+        want_devel = False
+    regex =  re.compile(r'(-devel)|(-debuginfo)|(-static)|(-libs)')
+    if regex.search(pkg.name):
+        is_devel = True
+    return is_devel == want_devel
+
+def _do_gui_filtering(flt, pkg):
+    is_gui = False
+    if flt == FILTER_GUI:
+        want_gui = True
+    else:
+        want_gui = False
+    is_gui = _check_for_gui(pkg)
+    return is_gui == want_gui
+
+def _basename_filter(package_list):
+    '''
+    Filter the list so that the number of packages are reduced.
+    This is done by only displaying gtk2 rather than gtk2-devel, gtk2-debuginfo, etc.
+    This imlementation is done by comparing the SRPM name, and if not falling back
+    to the first entry.
+    We have to fall back else we don't emit packages where the SRPM does not produce a
+    RPM with the same name, for instance, mono produces mono-core, mono-data and mono-winforms.
+    @package_list: a (pkg, status) list of packages
+    A new list is returned that has been filtered
+    '''
+    base_list = []
+    output_list = []
+    base_list_already_got = []
+
+    #find out the srpm name and add to a new array of compound data
+    for (pkg, status) in package_list:
+        if pkg.sourcerpm:
+            base = rpmUtils.miscutils.splitFilename(pkg.sourcerpm)[0]
+            base_list.append ((pkg, status, base, pkg.version))
+        else:
+            base_list.append ((pkg, status, 'nosrpm', pkg.version))
+
+    #find all the packages that match thier basename name (done seporately so we get the "best" match)
+    for (pkg, status, base, version) in base_list:
+        if base == pkg.name and (base, version) not in base_list_already_got:
+            output_list.append((pkg, status))
+            base_list_already_got.append ((base, version))
+
+    #for all the ones not yet got, can we match against a non devel match?
+    for (pkg, status, base, version) in base_list:
+        if (base, version) not in base_list_already_got:
+            if _is_main_package(pkg.name):
+                output_list.append((pkg, status))
+                base_list_already_got.append ((base, version))
+
+    #add the remainder of the packages, which should just be the single debuginfo's
+    for (pkg, status, base, version) in base_list:
+        if (base, version) not in base_list_already_got:
+            output_list.append((pkg, status))
+            base_list_already_got.append ((base, version))
+    return output_list
+
 class YumFilter(object, PackagekitPackage):
 
     def __init__(self, fltlist="none"):
@@ -38,158 +143,53 @@ class YumFilter(object, PackagekitPackage):
     def add_installed(self, pkgs):
         ''' add a list of packages that are already installed '''
         for pkg in pkgs:
-            if self._do_extra_filtering(pkg):
+            if self.pre_process(pkg):
                 self.package_list.append((pkg, INFO_INSTALLED))
-            self.installed_nevra.append(self._get_nevra(pkg))
+            self.installed_nevra.append(_get_nevra(pkg))
 
     def add_available(self, pkgs):
         # add a list of packages that are available
         for pkg in pkgs:
-            nevra = self._get_nevra(pkg)
+            nevra = _get_nevra(pkg)
             if nevra not in self.installed_nevra:
-                if self._do_extra_filtering(pkg):
+                if self.pre_process(pkg):
                     self.package_list.append((pkg, INFO_AVAILABLE))
 
     def add_custom(self, pkg, info):
         ''' add a custom packages indervidually '''
-        nevra = self._get_nevra(pkg)
+        nevra = _get_nevra(pkg)
         if nevra not in self.installed_nevra:
-            if self._do_extra_filtering(pkg):
+            if self.pre_process(pkg):
                 self.package_list.append((pkg, info))
 
     def post_process(self):
         ''' do filtering we couldn't do when generating the list '''
 
         if FILTER_BASENAME in self.fltlist:
-            self.package_list = self._basename_filter(self.package_list)
+            self.package_list = _basename_filter(self.package_list)
 
         if FILTER_NEWEST in self.fltlist:
-            self.package_list = self._do_newest_filtering(self.package_list)
+            self.package_list = _do_newest_filtering(self.package_list)
 
         return self.package_list
 
-    def _get_nevra(self, pkg):
-        ''' gets the NEVRA for a pkg '''
-        return "%s-%s:%s-%s.%s" % (pkg.name, pkg.epoch, pkg.version, pkg.release, pkg.arch)
-
-    def _is_main_package(self, repo):
-        if repo.endswith('-debuginfo'):
-            return False
-        if repo.endswith('-devel'):
-            return False
-        if repo.endswith('-libs'):
-            return False
-        return True
-
-    def _basename_filter(self, package_list):
-        '''
-        Filter the list so that the number of packages are reduced.
-        This is done by only displaying gtk2 rather than gtk2-devel, gtk2-debuginfo, etc.
-        This imlementation is done by comparing the SRPM name, and if not falling back
-        to the first entry.
-        We have to fall back else we don't emit packages where the SRPM does not produce a
-        RPM with the same name, for instance, mono produces mono-core, mono-data and mono-winforms.
-        @package_list: a (pkg, status) list of packages
-        A new list is returned that has been filtered
-        '''
-        base_list = []
-        output_list = []
-        base_list_already_got = []
-
-        #find out the srpm name and add to a new array of compound data
-        for (pkg, status) in package_list:
-            if pkg.sourcerpm:
-                base = rpmUtils.miscutils.splitFilename(pkg.sourcerpm)[0]
-                base_list.append ((pkg, status, base, pkg.version))
-            else:
-                base_list.append ((pkg, status, 'nosrpm', pkg.version))
-
-        #find all the packages that match thier basename name (done seporately so we get the "best" match)
-        for (pkg, status, base, version) in base_list:
-            if base == pkg.name and (base, version) not in base_list_already_got:
-                output_list.append((pkg, status))
-                base_list_already_got.append ((base, version))
-
-        #for all the ones not yet got, can we match against a non devel match?
-        for (pkg, status, base, version) in base_list:
-            if (base, version) not in base_list_already_got:
-                if self._is_main_package(pkg.name):
-                    output_list.append((pkg, status))
-                    base_list_already_got.append ((base, version))
-
-        #add the remainder of the packages, which should just be the single debuginfo's
-        for (pkg, status, base, version) in base_list:
-            if (base, version) not in base_list_already_got:
-                output_list.append((pkg, status))
-                base_list_already_got.append ((base, version))
-        return output_list
-
-    def _do_newest_filtering(self, pkglist):
-        '''
-        Only return the newest package for each name.arch
-        '''
-        newest = {}
-        for pkg, state in pkglist:
-            key = (pkg.name, pkg.arch)
-            if key in newest and pkg <= newest[key][0]:
-                continue
-            newest[key] = (pkg, state)
-        return newest.values()
-
-    def _do_extra_filtering(self, pkg):
+    def pre_process(self, pkg):
         ''' do extra filtering (gui, devel etc) '''
         for flt in self.fltlist:
             if flt in (FILTER_INSTALLED, FILTER_NOT_INSTALLED):
-                if not self._do_installed_filtering(flt, pkg):
+                if not _do_installed_filtering(flt, pkg):
                     return False
             elif flt in (FILTER_GUI, FILTER_NOT_GUI):
-                if not self._do_gui_filtering(flt, pkg):
+                if not _do_gui_filtering(flt, pkg):
                     return False
             elif flt in (FILTER_DEVELOPMENT, FILTER_NOT_DEVELOPMENT):
-                if not self._do_devel_filtering(flt, pkg):
+                if not _do_devel_filtering(flt, pkg):
                     return False
             elif flt in (FILTER_FREE, FILTER_NOT_FREE):
                 if not self._do_free_filtering(flt, pkg):
                     return False
         return True
 
-    def _do_installed_filtering(self, flt, pkg):
-        is_installed = False
-        if flt == FILTER_INSTALLED:
-            want_installed = True
-        else:
-            want_installed = False
-        is_installed = pkg.repo.id == 'installed'
-        return is_installed == want_installed
-
-    def _do_gui_filtering(self, flt, pkg):
-        is_gui = False
-        if flt == FILTER_GUI:
-            want_gui = True
-        else:
-            want_gui = False
-        is_gui = self._check_for_gui(pkg)
-        return is_gui == want_gui
-
-    def _check_for_gui(self, pkg):
-        '''  Check if the GUI_KEYS regex matches any package requirements'''
-        for req in pkg.requires:
-            reqname = req[0]
-            if GUI_KEYS.search(reqname):
-                return True
-        return False
-
-    def _do_devel_filtering(self, flt, pkg):
-        is_devel = False
-        if flt == FILTER_DEVELOPMENT:
-            want_devel = True
-        else:
-            want_devel = False
-        regex =  re.compile(r'(-devel)|(-debuginfo)|(-static)|(-libs)')
-        if regex.search(pkg.name):
-            is_devel = True
-        return is_devel == want_devel
-
     def _do_free_filtering(self, flt, pkg):
         is_free = False
         if flt == FILTER_FREE:
commit 898db33e95f7c16e3113fcab3192b6b621161ede
Author: Richard Hughes <richard at hughsie.com>
Date:   Fri Sep 26 17:43:54 2008 +0100

    trivial: add some more exclusions to pylint

diff --git a/python/packagekit/pylint.sh b/python/packagekit/pylint.sh
index 946878c..e1eb226 100755
--- a/python/packagekit/pylint.sh
+++ b/python/packagekit/pylint.sh
@@ -1 +1 @@
-pylint --disable-msg=W0614,C0301,C0103,W0613,C0111,R0913,R0904 $1
+pylint --disable-msg=W0614,C0301,C0103,W0613,C0111,R0913,R0904,R0903,C0302,W0401,R0912,R0914,R0911,R0915,R0902 $1
commit 311ff6710206d5010cff52b6ce01205f1067197a
Author: Richard Hughes <richard at hughsie.com>
Date:   Fri Sep 26 17:43:33 2008 +0100

    trivial bugfix: correct the method type of resolve

diff --git a/python/packagekit/backend.py b/python/packagekit/backend.py
index c4fefe8..e7934cf 100644
--- a/python/packagekit/backend.py
+++ b/python/packagekit/backend.py
@@ -335,7 +335,7 @@ class PackageKitBaseBackend:
         '''
         self.error(ERROR_NOT_SUPPORTED, "This function is not implemented in this backend")
 
-    def resolve(self, name):
+    def resolve(self, filters, name):
         '''
         Implement the {backend}-resolve functionality
         Needed to be implemented in a sub class
commit 69c3ebb69fe22731bf00fade5228dd2a3be50b8b
Author: Richard Hughes <richard at hughsie.com>
Date:   Fri Sep 26 15:51:04 2008 +0100

    trivial: when yum knows the summary, actually use it

diff --git a/backends/yum/yumBackend.py b/backends/yum/yumBackend.py
index 58a9c40..63167fe 100755
--- a/backends/yum/yumBackend.py
+++ b/backends/yum/yumBackend.py
@@ -1913,12 +1913,15 @@ class PackageKitCallback(RPMBaseCallback):
         return pct
 
     def _showName(self, status):
+        # curpkg is a yum package object or simple string of the package name
         if type(self.curpkg) in types.StringTypes:
             package_id = self.base.get_package_id(self.curpkg, '', '', '')
+            # we don't know the summary text
+            self.base.package(package_id, status, "")
         else:
             pkgver = self.base._get_package_ver(self.curpkg)
             package_id = self.base.get_package_id(self.curpkg.name, pkgver, self.curpkg.arch, self.curpkg.repo)
-        self.base.package(package_id, status, "")
+            self.base.package(package_id, status, self.curpkg.summary)
 
     def event(self, package, action, te_current, te_total, ts_current, ts_total):
         if str(package) != str(self.curpkg):
commit ade9a3cccc29968e5199917aab57bddef5b9ef07
Author: Anders F Bjorklund <afb at users.sourceforge.net>
Date:   Fri Sep 26 16:11:55 2008 +0200

    remove the helpers directory

diff --git a/backends/smart/helpers/.gitignore b/backends/smart/helpers/.gitignore
deleted file mode 100644
index 0d20b64..0000000
--- a/backends/smart/helpers/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-*.pyc
diff --git a/backends/smart/helpers/download-packages.py b/backends/smart/helpers/download-packages.py
deleted file mode 100755
index d4e989f..0000000
--- a/backends/smart/helpers/download-packages.py
+++ /dev/null
@@ -1,22 +0,0 @@
-#!/usr/bin/python
-#
-# Copyright (C) 2007 Richard Hughes <richard at hughsie.com>
-# Copyright (C) 2007 James Bowes <jbowes at dangerouslyinc.com>
-#
-# Licensed under the GNU General Public License Version 2
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
-
-import sys
-
-from smartBackend import PackageKitSmartBackend
-
-directory = sys.argv[1]
-packages = sys.argv[2:]
-backend = PackageKitSmartBackend(sys.argv[1:])
-backend.download_packages(directory, packages)
-sys.exit(0)
-
diff --git a/backends/smart/helpers/get-depends.py b/backends/smart/helpers/get-depends.py
deleted file mode 100755
index a1fb640..0000000
--- a/backends/smart/helpers/get-depends.py
+++ /dev/null
@@ -1,22 +0,0 @@
-#!/usr/bin/python
-#
-# Copyright (C) 2007 Richard Hughes <richard at hughsie.com>
-# Copyright (C) 2007 James Bowes <jbowes at dangerouslyinc.com>
-#
-# Licensed under the GNU General Public License Version 2
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
-
-import sys
-
-from smartBackend import PackageKitSmartBackend
-filters = sys.argv[1]
-package = sys.argv[2]
-recursive = sys.argv[3]
-
-backend = PackageKitSmartBackend(sys.argv[1:])
-backend.get_depends(filters, package.split(PACKAGE_IDS_DELIM), recursive)
-sys.exit(0)
diff --git a/backends/smart/helpers/get-details.py b/backends/smart/helpers/get-details.py
deleted file mode 100755
index 9dd2c9d..0000000
--- a/backends/smart/helpers/get-details.py
+++ /dev/null
@@ -1,20 +0,0 @@
-#!/usr/bin/python
-#
-# Copyright (C) 2007 Richard Hughes <richard at hughsie.com>
-# Copyright (C) 2007 James Bowes <jbowes at dangerouslyinc.com>
-#
-# Licensed under the GNU General Public License Version 2
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
-
-import sys
-
-from smartBackend import PackageKitSmartBackend
-
-package = sys.argv[1]
-backend = PackageKitSmartBackend(sys.argv[1:])
-backend.get_details(package.split(PACKAGE_IDS_DELIM))
-sys.exit(0)
diff --git a/backends/smart/helpers/get-files.py b/backends/smart/helpers/get-files.py
deleted file mode 100755
index 098f2aa..0000000
--- a/backends/smart/helpers/get-files.py
+++ /dev/null
@@ -1,19 +0,0 @@
-#!/usr/bin/python
-#
-# Copyright (C) 2007 Richard Hughes <richard at hughsie.com>
-# Copyright (C) 2007 James Bowes <jbowes at dangerouslyinc.com>
-#
-# Licensed under the GNU General Public License Version 2
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
-
-import sys
-
-from smartBackend import PackageKitSmartBackend
-package = sys.argv[1]
-backend = PackageKitSmartBackend(sys.argv[1:])
-backend.get_files(package.split(PACKAGE_IDS_DELIM))
-sys.exit(0)
diff --git a/backends/smart/helpers/get-packages.py b/backends/smart/helpers/get-packages.py
deleted file mode 100755
index 74eade7..0000000
--- a/backends/smart/helpers/get-packages.py
+++ /dev/null
@@ -1,21 +0,0 @@
-#!/usr/bin/python
-#
-# Copyright (C) 2007 Richard Hughes <richard at hughsie.com>
-# Copyright (C) 2007 James Bowes <jbowes at dangerouslyinc.com>
-#
-# Licensed under the GNU General Public License Version 2
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
-
-import sys
-
-from smartBackend import PackageKitSmartBackend
-
-filters = sys.argv[1]
-
-backend = PackageKitSmartBackend(sys.argv[1:])
-backend.get_packages(filters)
-sys.exit(0)
diff --git a/backends/smart/helpers/get-repo-list.py b/backends/smart/helpers/get-repo-list.py
deleted file mode 100755
index 6f26ffb..0000000
--- a/backends/smart/helpers/get-repo-list.py
+++ /dev/null
@@ -1,20 +0,0 @@
-#!/usr/bin/python
-#
-# Copyright (C) 2007 Richard Hughes <richard at hughsie.com>
-# Copyright (C) 2007 James Bowes <jbowes at dangerouslyinc.com>
-#
-# Licensed under the GNU General Public License Version 2
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
-
-import sys
-
-from smartBackend import PackageKitSmartBackend
-filters = sys.argv[1]
-
-backend = PackageKitSmartBackend(sys.argv[2:])
-backend.get_repo_list(filters)
-sys.exit(0)
diff --git a/backends/smart/helpers/get-requires.py b/backends/smart/helpers/get-requires.py
deleted file mode 100755
index 5b3d793..0000000
--- a/backends/smart/helpers/get-requires.py
+++ /dev/null
@@ -1,22 +0,0 @@
-#!/usr/bin/python
-#
-# Copyright (C) 2007 Richard Hughes <richard at hughsie.com>
-# Copyright (C) 2007 James Bowes <jbowes at dangerouslyinc.com>
-#
-# Licensed under the GNU General Public License Version 2
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
-
-import sys
-
-from smartBackend import PackageKitSmartBackend
-filters = sys.argv[1]
-package = sys.argv[2]
-recursive = sys.argv[3]
-
-backend = PackageKitSmartBackend(sys.argv[1:])
-backend.get_requires(filters, package.split(PACKAGE_IDS_DELIM), recursive)
-sys.exit(0)
diff --git a/backends/smart/helpers/get-update-detail.py b/backends/smart/helpers/get-update-detail.py
deleted file mode 100755
index 305a0bf..0000000
--- a/backends/smart/helpers/get-update-detail.py
+++ /dev/null
@@ -1,20 +0,0 @@
-#!/usr/bin/python
-#
-# Copyright (C) 2007 Richard Hughes <richard at hughsie.com>
-# Copyright (C) 2007 James Bowes <jbowes at dangerouslyinc.com>
-#
-# Licensed under the GNU General Public License Version 2
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
-
-import sys
-
-from smartBackend import PackageKitSmartBackend
-
-package = sys.argv[1]
-backend = PackageKitSmartBackend(sys.argv[1:])
-backend.get_update_detail(package.split(PACKAGE_IDS_DELIM))
-sys.exit(0)
diff --git a/backends/smart/helpers/get-updates.py b/backends/smart/helpers/get-updates.py
deleted file mode 100755
index c311814..0000000
--- a/backends/smart/helpers/get-updates.py
+++ /dev/null
@@ -1,21 +0,0 @@
-#!/usr/bin/python
-#
-# Copyright (C) 2007 Richard Hughes <richard at hughsie.com>
-# Copyright (C) 2007 James Bowes <jbowes at dangerouslyinc.com>
-#
-# Licensed under the GNU General Public License Version 2
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
-
-import sys
-
-from smartBackend import PackageKitSmartBackend
-
-filter = sys.argv[1]
-
-backend = PackageKitSmartBackend(sys.argv[1:])
-backend.get_updates(filter)
-sys.exit(0)
diff --git a/backends/smart/helpers/install-files.py b/backends/smart/helpers/install-files.py
deleted file mode 100755
index 560270c..0000000
--- a/backends/smart/helpers/install-files.py
+++ /dev/null
@@ -1,21 +0,0 @@
-#!/usr/bin/python
-#
-# Copyright (C) 2007 Richard Hughes <richard at hughsie.com>
-# Copyright (C) 2007 James Bowes <jbowes at dangerouslyinc.com>
-#
-# Licensed under the GNU General Public License Version 2
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
-
-import sys
-
-from smartBackend import PackageKitSmartBackend
-
-trusted = sys.argv[1]
-files_to_inst = sys.argv[2:]
-backend = PackageKitSmartBackend(sys.argv[1:])
-backend.install_files(trusted, files_to_inst)
-sys.exit(0)
diff --git a/backends/smart/helpers/install-packages.py b/backends/smart/helpers/install-packages.py
deleted file mode 100755
index 3c63de5..0000000
--- a/backends/smart/helpers/install-packages.py
+++ /dev/null
@@ -1,20 +0,0 @@
-#!/usr/bin/python
-#
-# Copyright (C) 2007 Richard Hughes <richard at hughsie.com>
-# Copyright (C) 2007 James Bowes <jbowes at dangerouslyinc.com>
-#
-# Licensed under the GNU General Public License Version 2
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
-
-import sys
-
-from smartBackend import PackageKitSmartBackend
-
-packages = sys.argv[1:]
-backend = PackageKitSmartBackend(sys.argv[1:])
-backend.install_packages(packages)
-sys.exit(0)
diff --git a/backends/smart/helpers/packagekit b/backends/smart/helpers/packagekit
deleted file mode 120000
index 8d22531..0000000
--- a/backends/smart/helpers/packagekit
+++ /dev/null
@@ -1 +0,0 @@
-../../../python/packagekit
\ No newline at end of file
diff --git a/backends/smart/helpers/refresh-cache.py b/backends/smart/helpers/refresh-cache.py
deleted file mode 100755
index 862e4da..0000000
--- a/backends/smart/helpers/refresh-cache.py
+++ /dev/null
@@ -1,19 +0,0 @@
-#!/usr/bin/python
-#
-# Copyright (C) 2007 Richard Hughes <richard at hughsie.com>
-# Copyright (C) 2007 James Bowes <jbowes at dangerouslyinc.com>
-#
-# Licensed under the GNU General Public License Version 2
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
-
-import sys
-
-from smartBackend import PackageKitSmartBackend
-
-backend = PackageKitSmartBackend(sys.argv[1:])
-backend.refresh_cache()
-sys.exit(0)
diff --git a/backends/smart/helpers/remove-packages.py b/backends/smart/helpers/remove-packages.py
deleted file mode 100755
index c1b77e4..0000000
--- a/backends/smart/helpers/remove-packages.py
+++ /dev/null
@@ -1,22 +0,0 @@
-#!/usr/bin/python
-#
-# Copyright (C) 2007 Richard Hughes <richard at hughsie.com>
-# Copyright (C) 2007 James Bowes <jbowes at redhat.com>
-#
-# Licensed under the GNU General Public License Version 2
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
-
-import sys
-
-from smartBackend import PackageKitSmartBackend
-
-allow_deps = sys.argv[1]
-packages = sys.argv[2:]
-backend = PackageKitSmartBackend(sys.argv[1:])
-backend.remove_packages(allow_deps, packages)
-
-sys.exit(0)
diff --git a/backends/smart/helpers/repo-enable.py b/backends/smart/helpers/repo-enable.py
deleted file mode 100755
index b283422..0000000
--- a/backends/smart/helpers/repo-enable.py
+++ /dev/null
@@ -1,21 +0,0 @@
-#!/usr/bin/python
-#
-# Copyright (C) 2007 Richard Hughes <richard at hughsie.com>
-# Copyright (C) 2007 James Bowes <jbowes at dangerouslyinc.com>
-#
-# Licensed under the GNU General Public License Version 2
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
-
-import sys
-
-from smartBackend import PackageKitSmartBackend
-
-repoid = sys.argv[1]
-state=sys.argv[2]
-backend = PackageKitSmartBackend(sys.argv[2:])
-backend.repo_enable(repoid,state)
-sys.exit(0)
diff --git a/backends/smart/helpers/repo-set-data.py b/backends/smart/helpers/repo-set-data.py
deleted file mode 100755
index 221e4ac..0000000
--- a/backends/smart/helpers/repo-set-data.py
+++ /dev/null
@@ -1,22 +0,0 @@
-#!/usr/bin/python
-#
-# Copyright (C) 2007 Richard Hughes <richard at hughsie.com>
-# Copyright (C) 2007 James Bowes <jbowes at dangerouslyinc.com>
-#
-# Licensed under the GNU General Public License Version 2
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
-
-import sys
-
-from smartBackend import PackageKitSmartBackend
-
-repoid = sys.argv[1]
-para=sys.argv[2]
-value=sys.argv[3]
-backend = PackageKitSmartBackend(sys.argv[2:])
-backend.repo_set_data(repoid,para,value)
-sys.exit(0)
diff --git a/backends/smart/helpers/resolve.py b/backends/smart/helpers/resolve.py
deleted file mode 100755
index 0d6b392..0000000
--- a/backends/smart/helpers/resolve.py
+++ /dev/null
@@ -1,21 +0,0 @@
-#!/usr/bin/python
-#
-# Copyright (C) 2007 Richard Hughes <richard at hughsie.com>
-# Copyright (C) 2007 James Bowes <jbowes at redhat.com>
-#
-# Licensed under the GNU General Public License Version 2
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
-
-import sys
-import smartBackend
-
-filters = sys.argv[1]
-packages = sys.argv[2:]
-backend = smartBackend.PackageKitSmartBackend(sys.argv[2:])
-backend.resolve(filters, packages)
-
-sys.exit()
diff --git a/backends/smart/helpers/search-details.py b/backends/smart/helpers/search-details.py
deleted file mode 100755
index fb77501..0000000
--- a/backends/smart/helpers/search-details.py
+++ /dev/null
@@ -1,22 +0,0 @@
-#!/usr/bin/python
-#
-# Copyright (C) 2007 Richard Hughes <richard at hughsie.com>
-# Copyright (C) 2007 James Bowes <jbowes at dangerouslyinc.com>
-#
-# Licensed under the GNU General Public License Version 2
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
-
-import sys
-
-from smartBackend import PackageKitSmartBackend
-
-options = sys.argv[1]
-searchterms = sys.argv[2]
-
-backend = PackageKitSmartBackend(sys.argv[1:])
-backend.search_details(options,searchterms)
-sys.exit(0)
diff --git a/backends/smart/helpers/search-file.py b/backends/smart/helpers/search-file.py
deleted file mode 100755
index 2b1d118..0000000
--- a/backends/smart/helpers/search-file.py
+++ /dev/null
@@ -1,22 +0,0 @@
-#!/usr/bin/python
-#
-# Copyright (C) 2007 Richard Hughes <richard at hughsie.com>
-# Copyright (C) 2007 James Bowes <jbowes at dangerouslyinc.com>
-#
-# Licensed under the GNU General Public License Version 2
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
-
-import sys
-
-from smartBackend import PackageKitSmartBackend
-
-options = sys.argv[1]
-searchterms = sys.argv[2]
-
-backend = PackageKitSmartBackend(sys.argv[1:])
-backend.search_file(options,searchterms)
-sys.exit(0)
diff --git a/backends/smart/helpers/search-group.py b/backends/smart/helpers/search-group.py
deleted file mode 100755
index da01f6d..0000000
--- a/backends/smart/helpers/search-group.py
+++ /dev/null
@@ -1,22 +0,0 @@
-#!/usr/bin/python
-#
-# Copyright (C) 2007 Richard Hughes <richard at hughsie.com>
-# Copyright (C) 2007 James Bowes <jbowes at dangerouslyinc.com>
-#
-# Licensed under the GNU General Public License Version 2
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
-
-import sys
-
-from smartBackend import PackageKitSmartBackend
-
-options = sys.argv[1]
-searchterms = sys.argv[2]
-
-backend = PackageKitSmartBackend(sys.argv[1:])
-backend.search_group(options,searchterms)
-sys.exit(0)
diff --git a/backends/smart/helpers/search-name.py b/backends/smart/helpers/search-name.py
deleted file mode 100755
index 2ea180c..0000000
--- a/backends/smart/helpers/search-name.py
+++ /dev/null
@@ -1,19 +0,0 @@
-#!/usr/bin/python
-#
-# Copyright (C) 2007 Richard Hughes <richard at hughsie.com>
-# Copyright (C) 2007 James Bowes <jbowes at redhat.com>
-#
-# Licensed under the GNU General Public License Version 2
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
-
-import sys
-import smartBackend
-
-backend = smartBackend.PackageKitSmartBackend(sys.argv[2:])
-backend.search_name(sys.argv[1], sys.argv[2])
-
-sys.exit()
diff --git a/backends/smart/helpers/update-packages.py b/backends/smart/helpers/update-packages.py
deleted file mode 100755
index a304a70..0000000
--- a/backends/smart/helpers/update-packages.py
+++ /dev/null
@@ -1,20 +0,0 @@
-#!/usr/bin/python
-#
-# Copyright (C) 2007 Richard Hughes <richard at hughsie.com>
-# Copyright (C) 2007 James Bowes <jbowes at dangerouslyinc.com>
-#
-# Licensed under the GNU General Public License Version 2
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
-
-import sys
-
-from smartBackend import PackageKitSmartBackend
-
-packages = sys.argv[1:]
-backend = PackageKitSmartBackend(sys.argv[1:])
-backend.update_packages(packages)
-sys.exit(0)
diff --git a/backends/smart/helpers/update-system.py b/backends/smart/helpers/update-system.py
deleted file mode 100755
index 6ba5c29..0000000
--- a/backends/smart/helpers/update-system.py
+++ /dev/null
@@ -1,19 +0,0 @@
-#!/usr/bin/python
-#
-# Copyright (C) 2007 Richard Hughes <richard at hughsie.com>
-# Copyright (C) 2007 James Bowes <jbowes at dangerouslyinc.com>
-#
-# Licensed under the GNU General Public License Version 2
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
-
-import sys
-
-from smartBackend import PackageKitSmartBackend
-
-backend = PackageKitSmartBackend(sys.argv[1:])
-backend.update_system()
-sys.exit(0)
diff --git a/backends/smart/helpers/what-provides.py b/backends/smart/helpers/what-provides.py
deleted file mode 100755
index d5ec4ba..0000000
--- a/backends/smart/helpers/what-provides.py
+++ /dev/null
@@ -1,23 +0,0 @@
-#!/usr/bin/python
-#
-# Copyright (C) 2007 Richard Hughes <richard at hughsie.com>
-# Copyright (C) 2007 James Bowes <jbowes at dangerouslyinc.com>
-#
-# Licensed under the GNU General Public License Version 2
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
-
-import sys
-
-from smartBackend import PackageKitSmartBackend
-
-filters = sys.argv[1]
-provides_type = sys.argv[2]
-search = sys.argv[3]
-
-backend = PackageKitSmartBackend(sys.argv[1:])
-backend.what_provides(filters, provides_type, search)
-sys.exit(0)
commit 3a4981b9bb377ab7f0b23a1a5560a9cb5110805c
Author: Richard Hughes <richard at hughsie.com>
Date:   Fri Sep 26 14:52:05 2008 +0100

    trivial: fix a typo i made in the conary backend

diff --git a/backends/conary/conaryBackend.py b/backends/conary/conaryBackend.py
index 7190472..b9ecbe4 100644
--- a/backends/conary/conaryBackend.py
+++ b/backends/conary/conaryBackend.py
@@ -991,7 +991,7 @@ class Cache(object):
                 #    self._addPackageLicense(trv, license)
 
 def main():
-    backend = PackageKitYumBackend('', lock=True)
+    backend = PackageKitConaryBackend('', lock=True)
     backend.dispatcher(sys.argv[1:])
 
 if __name__ == "__main__":
commit c187825c7dc5771cdaa3edd458566280895bda9e
Author: Richard Hughes <richard at hughsie.com>
Date:   Fri Sep 26 14:51:35 2008 +0100

    trivial: remove the old helpers from apt.deprecated, just to rip out really dead code

diff --git a/backends/apt.deprecated/aptBackend.py b/backends/apt.deprecated/aptBackend.py
new file mode 100644
index 0000000..e5f78ca
--- /dev/null
+++ b/backends/apt.deprecated/aptBackend.py
@@ -0,0 +1,536 @@
+#
+# vim: ts=4 et sts=4
+#
+# Copyright (C) 2007 Ali Sabil <ali.sabil at gmail.com>
+# Copyright (C) 2007 Tom Parker <palfrey at tevp.net>
+#
+# Licensed under the GNU General Public License Version 2
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+
+import sys
+import os
+import re
+
+from packagekit.backend import *
+import apt_pkg,apt_inst
+
+import warnings
+warnings.filterwarnings(action='ignore', category=FutureWarning)
+import apt
+from aptsources.distro import get_distro
+from aptsources.sourceslist import SourcesList
+from sets import Set
+from os.path import join,exists
+from urlparse import urlparse
+from apt.debfile import DebPackage
+from os import system
+
+class Package(apt.Package):
+    def __str__(self):
+        return "Package %s, version %s"%(self.name,self._version)
+
+    def _cmp_deps(self,deps, version):
+        for (v,c) in deps:
+            if not apt_pkg.CheckDep(version,c,v):
+                return False
+        return True
+
+    def __init__(self, backend, pkg, data="",version=[]):
+        apt.package.Package.__init__(self, pkg._cache, pkg._depcache,
+                                     pkg._records, pkg._list, pkg._pcache,
+                                     pkg._pkg)
+        self._version = version
+        self._data = data
+        self._backend = backend
+        wanted_ver = None
+        if self.installedVersion!=None and self._cmp_deps(version,self.installedVersion):
+            wanted_ver = self.installedVersion
+        elif self.installedVersion == None and version == []:
+            #self.markInstall(False,False)
+            wanted_ver = self.candidateVersion
+
+        for ver in pkg._pkg.VersionList:
+            #print "vers",dir(ver),version,ver
+            #print data
+            if (wanted_ver == None or wanted_ver == ver.VerStr) and self._cmp_deps(version,ver.VerStr):
+                f, index = ver.FileList.pop(0)
+                if self._data == "":
+                    if f.Origin=="" and f.Archive=="now":
+                        self._data = "local_install"
+                    elif f.Origin!="" or f.Archive!="":
+                        self._data = "%s/%s"%(f.Origin.replace("/","_"),f.Archive.replace("/","_"))
+                    else:
+                        self._data = "%s/unknown"%f.Site
+                self._version = ver.VerStr
+                break
+        else:
+            print "wanted",wanted_ver
+            for ver in pkg._pkg.VersionList:
+                print "vers",version,ver.VerStr
+            backend.error(ERROR_PACKAGE_NOT_FOUND, "Can't find version %s for %s"%(version,self.name))
+
+    def setVersion(self,version,compare="="):
+        if version!=None and (self.installedVersion == None or not apt_pkg.CheckDep(version,compare,self.installedVersion)):
+            self.markInstall(False,False)
+            if self.candidateVersion != version:
+                if self._data == "":
+                    for ver in pkg._pkg.VersionList:
+                        f, index = ver.FileList.pop(0)
+                        self._data = "%s/%s"%(f.Origin,f.Archive)
+                        if ver.VerStr == version:
+                            break
+
+                # FIXME: this is a nasty hack, assuming that the best way to resolve
+                # deps for non-default repos is by switching the default release.
+                # We really need a better resolver (but that's hard)
+                assert self._data!=""
+                origin = self._data[self._data.find("/")+1:]
+                print "origin",origin
+                name = self.name
+                apt_pkg.Config.Set("APT::Default-Release",origin)
+                if not self._backend._caches.has_key(origin):
+                    self._backend._caches[origin] = apt.Cache(PackageKitProgress(self))
+                    print "new cache for %s"%origin
+                self.__setParent(self._backend._caches[origin][name])
+                self.markInstall(False,False)
+                if not apt_pkg.CheckDep(self.candidateVersion,compare,version):
+                    self._backend.error(ERROR_PACKAGE_NOT_FOUND,
+                            "Unable to locate package version %s (only got %s) for %s"%(version,self.candidateVersion,name))
+                    return
+                self.markKeep()
+
+    @property
+    def group(self):
+        section = self.section.split('/')[-1].lower()
+        #if section in ():
+        #    return GROUP_ACCESSIBILITY
+        if section in ('utils',):
+            return "accessories"
+        #if section in ():
+        #    return GROUP_EDUCATION
+        if section in ('games',):
+            return "games"
+        if section in ('graphics',):
+            return "graphics"
+        if section in ('net', 'news', 'web', 'comm'):
+            return "internet"
+        if section in ('editors', 'tex'):
+            return "office"
+        if section in ('misc',):
+            return "other"
+        if section in ('devel', 'libdevel', 'interpreters', 'perl', 'python'):
+            return "programming"
+        if section in ('sound',):
+            return "multimedia"
+        if section in ('base', 'admin'):
+            return "system"
+        return "unknown"
+
+    @property
+    def isInstalled(self):
+        return super(self.__class__,self).isInstalled and self.installedVersion == self._version
+
+    @property
+    def isDevelopment(self):
+        name = self.name.lower()
+        section = self.section.split('/')[-1].lower()
+        return name.endswith('-dev') or name.endswith('-dbg') or \
+                section in ('devel', 'libdevel')
+
+    @property
+    def isGui(self):
+        section = self.section.split('/')[-1].lower()
+        return section in ('x11', 'gnome', 'kde')
+
+    _HYPHEN_PATTERN = re.compile(r'(\s|_)+')
+
+    def matchName(self, name):
+        needle = name.strip().lower()
+        haystack = self.name.lower()
+        needle = Package._HYPHEN_PATTERN.sub('-', needle)
+        haystack = Package._HYPHEN_PATTERN.sub('-', haystack)
+        if haystack.find(needle) >= 0:
+            return True
+        return False
+
+    def matchDetails(self, details):
+        if self.matchName(details):
+            return True
+        needle = details.strip().lower()
+        haystack = self.description.lower()
+        if haystack.find(needle) >= 0:
+            return True
+        return False
+
+    def matchGroup(self, name):
+        needle = name.strip().lower()
+        haystack = self.group
+        if haystack.startswith(needle):
+            return True
+        return False
+
+class PackageKitProgress(apt.progress.OpProgress, apt.progress.FetchProgress):
+    def __init__(self, backend):
+        self._backend = backend
+        apt.progress.OpProgress.__init__(self)
+        apt.progress.FetchProgress.__init__(self)
+
+    # OpProgress callbacks
+    def update(self, percent):
+        pass
+
+    def done(self):
+        pass
+
+    # FetchProgress callbacks
+    def pulse(self):
+        apt.progress.FetchProgress.pulse(self)
+        self._backend.percentage(self.percent)
+        return True
+
+    def stop(self):
+        self._backend.percentage(100)
+
+    def mediaChange(self, medium, drive):
+        # This probably should not be an error, but a Message.
+        self._backend.error(ERROR_UNKNOWN,
+                "Medium change needed")
+
+class PackageKitAptBackend(PackageKitBaseBackend):
+    def __init__(self, args):
+        PackageKitBaseBackend.__init__(self, args)
+        self.status(STATUS_SETUP)
+        self._caches  = {}
+        self._apt_cache = apt.Cache(PackageKitProgress(self))
+        default = apt_pkg.Config.Find("APT::Default-Release")
+        if default=="":
+            d = get_distro()
+            if d.id == "Debian":
+                default = "stable"
+            elif d.id == "Ubuntu":
+                default = "main"
+            else:
+                raise Exception,d.id
+
+        self._caches[default] = self._apt_cache
+
+
+    def search_name(self, filters, key):
+        '''
+        Implement the {backend}-search-name functionality
+        '''
+        self.status(STATUS_INFO)
+        self.allow_cancel(True)
+        for package in self._do_search(filters,
+                lambda pkg: pkg.matchName(key)):
+            self._emit_package(package)
+
+    def search_details(self, filters, key):
+        '''
+        Implement the {backend}-search-details functionality
+        '''
+        self.status(STATUS_INFO)
+        self.allow_cancel(True)
+        for package in self._do_search(filters,
+                lambda pkg: pkg.matchDetails(key)):
+            self._emit_package(package)
+
+    def search_group(self, filters, key):
+        '''
+        Implement the {backend}-search-group functionality
+        '''
+        self.status(STATUS_INFO)
+        self.allow_cancel(True)
+        for package in self._do_search(filters,
+                lambda pkg: pkg.matchGroup(key)):
+            self._emit_package(package)
+
+    def search_file(self, filters, key):
+        '''
+        Implement the {backend}-search-file functionality
+        '''
+        self.allow_cancel(True)
+        self.percentage(None)
+
+        self.error(ERROR_NOT_SUPPORTED,
+                "This function is not implemented in this backend")
+
+    def refresh_cache(self):
+        '''
+        Implement the {backend}-refresh_cache functionality
+        '''
+        self.status(STATUS_REFRESH_CACHE)
+        try:
+            res = self._apt_cache.update(PackageKitProgress(self))
+        except Exception, error_message:
+             self.error(ERROR_UNKNOWN,
+                        "Failed to fetch the following items:\n%s" % error_message)
+        return res
+
+    def get_details(self, package):
+        '''
+        Implement the {backend}-get-details functionality
+        '''
+        self.status(STATUS_INFO)
+        name, version, arch, data = self.get_package_from_id(package)
+        pkg = Package(self, self._apt_cache[name])
+        description = re.sub('\s+', ' ', pkg.description).strip()
+        self.description(package, 'unknown', pkg.group, description,
+                         pkg.architecture, pkg.packageSize)
+
+    def resolve(self, name):
+        '''
+        Implement the {backend}-resolve functionality
+        '''
+        self.status(STATUS_INFO)
+        try:
+            pkg = Package(self,self._apt_cache[name])
+            self._emit_package(pkg)
+        except KeyError:
+            self.error(ERROR_PACKAGE_NOT_FOUND,"Can't find a package called '%s'"%name)
+
+    def _do_deps(self,inp,deps,recursive):
+        inp.markInstall()
+        newkeys = []
+        for x in inp.candidateDependencies:
+            n = x.or_dependencies[0].name
+            if not deps.has_key(n):
+                deps[n] = []
+                newkeys.append(n)
+            deps[n].append((x.or_dependencies[0].version,x.or_dependencies[0].relation))
+        if recursive:
+            for n in newkeys:
+                try:
+                    deps = self._do_deps(Package(self,self._apt_cache[n],version=deps[n]),deps,recursive)
+                except KeyError: # FIXME: we're assuming this is a virtual package, which we can't cope with yet
+                    del deps[n]
+                    continue
+        return deps
+
+    def get_depends(self,filters,package, recursive):
+        '''
+        Implement the {backend}-get-depends functionality
+        '''
+        self.allow_cancel(True)
+        self.status(STATUS_INFO)
+        recursive = (recursive == "True")
+        name, version, arch, data = self.get_package_from_id(package)
+        pkg = Package(self,self._apt_cache[name],version=[(version,"=")],data=data)
+        pkg.setVersion(version)
+        deps = self._do_deps(pkg, {}, recursive)
+        for n in deps.keys():
+           self._emit_package(Package(self,self._apt_cache[n],version=deps[n]))
+
+    def _do_reqs(self,inp,pkgs,recursive):
+        extra = []
+        fails = []
+        for r in inp._pkg.RevDependsList:
+            ch = apt_pkg.CheckDep(inp._version,r.CompType,r.TargetVer)
+            v = (r.ParentPkg.Name,r.ParentVer.VerStr)
+            if not ch or v in fails:
+                #print "skip",r.TargetVer,r.CompType,r.ParentPkg.Name,r.ParentVer.VerStr
+                fails.append(v)
+                continue
+            p = Package(self,self._apt_cache[r.ParentPkg.Name],r.ParentVer.VerStr)
+            if v not in pkgs:
+                extra.append(p)
+                #print "new pkg",p
+                self._emit_package(p)
+            pkgs.add(v)
+        if recursive:
+            for e in extra:
+                pkgs = self._do_reqs(p, pkgs,recursive)
+        return pkgs
+
+    def get_requires(self,package,recursive):
+        '''
+        Implement the {backend}-get-requires functionality
+        '''
+        self.allow_cancel(True)
+        self.status(STATUS_INFO)
+        recursive = (recursive == "True")
+        name, version, arch, data = self.get_package_from_id(package)
+        pkg = Package(self,self._apt_cache[name], version=[(version,"=")], data=data)
+
+        pkgs = Set()
+        self._do_reqs(pkg,pkgs, recursive)
+
+    def _build_repo_list(self):
+        repo = {}
+
+        sources = SourcesList()
+        repo["__sources"] = sources
+
+        root = apt_pkg.Config.FindDir("Dir::State::Lists")
+        #print root
+        for entry in sources:
+            if entry.type!="":
+                url = entry.uri
+                #if entry.template!=None:
+                url +="/dists/"
+                url += entry.dist
+                url = url.replace("//dists","/dists")
+                #print url
+                path = join(root,"%s_Release"%(apt_pkg.URItoFileName(url)))
+                if not exists(path):
+                    #print path
+                    name = "%s/unknown"%urlparse(entry.uri)[1]
+                else:
+                    lines = file(path).readlines()
+                    origin = ""
+                    suite = ""
+                    for l in lines:
+                        if l.find("Origin: ")==0:
+                            origin = l.split(" ",1)[1].strip()
+                        elif l.find("Suite: ")==0:
+                            suite = l.split(" ",1)[1].strip()
+                    assert origin!="" and suite!=""
+                    name = "%s/%s"%(origin,suite)
+                if entry.type == "deb-src":
+                    name += "-src"
+
+                repo[name] = {"entry":entry}
+        return repo
+
+    def get_repo_list(self, filters):
+        '''
+        Implement the {backend}-get-repo-list functionality
+        '''
+        self.allow_interrupt(True)
+        self.status(STATUS_INFO)
+        repo = self._build_repo_list()
+        for e in repo.keys():
+            if e == "__sources":
+                continue
+            self.repo_detail(repo[e]["entry"].line.strip(),e,not repo[e]["entry"].disabled)
+
+    def repo_enable(self, repoid, enable):
+        '''
+        Implement the {backend}-repo-enable functionality
+        '''
+        enable = (enable == "True")
+        repo = self._build_repo_list()
+        if not repo.has_key(repoid):
+            self.error(ERROR_REPO_NOT_FOUND,"Couldn't find repo '%s'"%repoid)
+            return
+        r = repo[repoid]
+        if not r["entry"].disabled == enable: # already there
+            return
+        r["entry"].set_enabled(enable)
+        try:
+            repo["__sources"].save()
+        except IOError,e:
+            self.error(ERROR_UNKNOWN, "Problem while trying to save repo settings to %s: %s"%(e.filename,e.strerror))
+
+    def get_updates(self, filter):
+        self._apt_cache.upgrade(False)
+        for pkg in self._apt_cache.getChanges():
+            self._emit_package(Package(self, pkg))
+
+    def get_update_detail(self, package):
+        self.allow_cancel(True)
+        self.percentage(None)
+        self.status(STATUS_INFO)
+        name, version, arch, data = self.get_package_from_id(package)
+        update = ""
+        obsolete = ""
+        cve_url = ""
+        bz_url = ""
+        vendor_url = ""
+        reboot = "none"
+        desc = self._apt_cache[name].description
+        self.update_detail(package,update,obsolete,vendor_url,bz_url,cve_url,reboot,desc)
+
+
+    def install_files (self, inst_files):
+        '''
+        Implement the {backend}-install_files functionality
+        Install the package containing the inst_file file
+        '''
+        if not exists(inst_file):
+            self.error(ERROR_PACKAGE_NOT_FOUND,"Can't find %s"%inst_file)
+            return
+        deb = DebPackage(inst_file)
+        deps = {}
+        for k in ["Depends","Recommends"]:
+            if not deb._sections.has_key(k):
+                continue
+            for items in apt_pkg.ParseDepends(deb[k]):
+                assert len(items) == 1,"Can't handle or deps properly yet"
+                (pkg,ver,comp) = items[0]
+                if not deps.has_key(pkg):
+                    deps[pkg] = []
+                deps[pkg].append((ver,comp))
+        for n in deps.keys():
+           p = Package(self,self._apt_cache[n],version=deps[n])
+           if not p.isInstalled:
+               p.markInstall()
+        assert self._apt_cache.getChanges()==[],"Don't handle install changes yet"
+        # FIXME: nasty hack. Need a better way in
+        ret = system("dpkg -i %s"%inst_file)
+        if ret!=0:
+            self.error(ERROR_UNKNOWN,"Can't install package")
+
+    ### Helpers ###
+    def _emit_package(self, package):
+        id = self.get_package_id(package.name,
+                package._version,
+                package.architecture,
+                package._data)
+        if package.isInstalled:
+            status = INFO_INSTALLED
+        else:
+            status = INFO_AVAILABLE
+        summary = package.summary
+        self.package(id, status, summary)
+
+    def _do_search(self, filters, condition):
+        filters = filters.split(';')
+        size = len(self._apt_cache)
+        percentage = 0
+        for i, pkg in enumerate(self._apt_cache):
+            new_percentage = i / float(size) * 100
+            if new_percentage - percentage >= 5:
+                percentage = new_percentage
+                self.percentage(percentage)
+            package = Package(self, pkg)
+            if package.installedVersion is None and \
+                    package.candidateVersion is None:
+                continue
+            if not condition(package):
+                continue
+                continue
+            vers = [x.VerStr for x in package._pkg.VersionList]
+            if package.installedVersion!=None:
+                i = package.installedVersion
+                if i in vers and vers[0]!=i:
+                    del vers[vers.index(i)]
+                    vers.insert(0,i)
+
+            for ver in vers:
+                p = Package(self, package, version=[[ver,"="]])
+                if self._do_filtering(p, filters):
+                    yield p
+        self.percentage(100)
+
+    def _do_filtering(self, package, filters):
+        if len(filters) == 0 or filters == ['none']:
+            return True
+        if (FILTER_INSTALLED in filters) and (not package.isInstalled):
+            return False
+        if (FILTER_NOT_INSTALLED in filters) and package.isInstalled:
+            return False
+        if (FILTER_GUI in filters) and (not package.isGui):
+            return False
+        if (FILTER_NOT_GUI in filters) and package.isGui:
+            return False
+        if (FILTER_DEVELOPMENT in filters) and (not package.isDevelopment):
+            return False
+        if (FILTER_NOT_DEVELOPMENT in filters) and package.isDevelopment:
+            return False
+        return True
+
diff --git a/backends/apt.deprecated/helpers/.gitignore b/backends/apt.deprecated/helpers/.gitignore
deleted file mode 100644
index 0d20b64..0000000
--- a/backends/apt.deprecated/helpers/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-*.pyc
diff --git a/backends/apt.deprecated/helpers/Makefile.am b/backends/apt.deprecated/helpers/Makefile.am
deleted file mode 100644
index 0299df2..0000000
--- a/backends/apt.deprecated/helpers/Makefile.am
+++ /dev/null
@@ -1,29 +0,0 @@
-
-helperdir = $(datadir)/PackageKit/helpers/apt
-
-NULL =
-
-dist_helper_DATA = 			\
-	install-files.py		\
-	search-name.py			\
-	search-details.py		\
-	search-group.py			\
-	search-file.py			\
-	get-depends.py			\
-	get-details.py			\
-	get-repo-list.py		\
-	get-requires.py			\
-	get-update-detail.py		\
-	get-updates.py			\
-	refresh-cache.py		\
-	repo-enable.py			\
-	resolve.py			\
-	aptBackend.py			\
-	$(NULL)
-
-install-data-hook:
-	chmod a+rx $(DESTDIR)$(helperdir)/*.py
-
-clean-local :
-	rm -f *~
-
diff --git a/backends/apt.deprecated/helpers/aptBackend.py b/backends/apt.deprecated/helpers/aptBackend.py
deleted file mode 100644
index e5f78ca..0000000
--- a/backends/apt.deprecated/helpers/aptBackend.py
+++ /dev/null
@@ -1,536 +0,0 @@
-#
-# vim: ts=4 et sts=4
-#
-# Copyright (C) 2007 Ali Sabil <ali.sabil at gmail.com>
-# Copyright (C) 2007 Tom Parker <palfrey at tevp.net>
-#
-# Licensed under the GNU General Public License Version 2
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
-
-import sys
-import os
-import re
-
-from packagekit.backend import *
-import apt_pkg,apt_inst
-
-import warnings
-warnings.filterwarnings(action='ignore', category=FutureWarning)
-import apt
-from aptsources.distro import get_distro
-from aptsources.sourceslist import SourcesList
-from sets import Set
-from os.path import join,exists
-from urlparse import urlparse
-from apt.debfile import DebPackage
-from os import system
-
-class Package(apt.Package):
-    def __str__(self):
-        return "Package %s, version %s"%(self.name,self._version)
-
-    def _cmp_deps(self,deps, version):
-        for (v,c) in deps:
-            if not apt_pkg.CheckDep(version,c,v):
-                return False
-        return True
-
-    def __init__(self, backend, pkg, data="",version=[]):
-        apt.package.Package.__init__(self, pkg._cache, pkg._depcache,
-                                     pkg._records, pkg._list, pkg._pcache,
-                                     pkg._pkg)
-        self._version = version
-        self._data = data
-        self._backend = backend
-        wanted_ver = None
-        if self.installedVersion!=None and self._cmp_deps(version,self.installedVersion):
-            wanted_ver = self.installedVersion
-        elif self.installedVersion == None and version == []:
-            #self.markInstall(False,False)
-            wanted_ver = self.candidateVersion
-
-        for ver in pkg._pkg.VersionList:
-            #print "vers",dir(ver),version,ver
-            #print data
-            if (wanted_ver == None or wanted_ver == ver.VerStr) and self._cmp_deps(version,ver.VerStr):
-                f, index = ver.FileList.pop(0)
-                if self._data == "":
-                    if f.Origin=="" and f.Archive=="now":
-                        self._data = "local_install"
-                    elif f.Origin!="" or f.Archive!="":
-                        self._data = "%s/%s"%(f.Origin.replace("/","_"),f.Archive.replace("/","_"))
-                    else:
-                        self._data = "%s/unknown"%f.Site
-                self._version = ver.VerStr
-                break
-        else:
-            print "wanted",wanted_ver
-            for ver in pkg._pkg.VersionList:
-                print "vers",version,ver.VerStr
-            backend.error(ERROR_PACKAGE_NOT_FOUND, "Can't find version %s for %s"%(version,self.name))
-
-    def setVersion(self,version,compare="="):
-        if version!=None and (self.installedVersion == None or not apt_pkg.CheckDep(version,compare,self.installedVersion)):
-            self.markInstall(False,False)
-            if self.candidateVersion != version:
-                if self._data == "":
-                    for ver in pkg._pkg.VersionList:
-                        f, index = ver.FileList.pop(0)
-                        self._data = "%s/%s"%(f.Origin,f.Archive)
-                        if ver.VerStr == version:
-                            break
-
-                # FIXME: this is a nasty hack, assuming that the best way to resolve
-                # deps for non-default repos is by switching the default release.
-                # We really need a better resolver (but that's hard)
-                assert self._data!=""
-                origin = self._data[self._data.find("/")+1:]
-                print "origin",origin
-                name = self.name
-                apt_pkg.Config.Set("APT::Default-Release",origin)
-                if not self._backend._caches.has_key(origin):
-                    self._backend._caches[origin] = apt.Cache(PackageKitProgress(self))
-                    print "new cache for %s"%origin
-                self.__setParent(self._backend._caches[origin][name])
-                self.markInstall(False,False)
-                if not apt_pkg.CheckDep(self.candidateVersion,compare,version):
-                    self._backend.error(ERROR_PACKAGE_NOT_FOUND,
-                            "Unable to locate package version %s (only got %s) for %s"%(version,self.candidateVersion,name))
-                    return
-                self.markKeep()
-
-    @property
-    def group(self):
-        section = self.section.split('/')[-1].lower()
-        #if section in ():
-        #    return GROUP_ACCESSIBILITY
-        if section in ('utils',):
-            return "accessories"
-        #if section in ():
-        #    return GROUP_EDUCATION
-        if section in ('games',):
-            return "games"
-        if section in ('graphics',):
-            return "graphics"
-        if section in ('net', 'news', 'web', 'comm'):
-            return "internet"
-        if section in ('editors', 'tex'):
-            return "office"
-        if section in ('misc',):
-            return "other"
-        if section in ('devel', 'libdevel', 'interpreters', 'perl', 'python'):
-            return "programming"
-        if section in ('sound',):
-            return "multimedia"
-        if section in ('base', 'admin'):
-            return "system"
-        return "unknown"
-
-    @property
-    def isInstalled(self):
-        return super(self.__class__,self).isInstalled and self.installedVersion == self._version
-
-    @property
-    def isDevelopment(self):
-        name = self.name.lower()
-        section = self.section.split('/')[-1].lower()
-        return name.endswith('-dev') or name.endswith('-dbg') or \
-                section in ('devel', 'libdevel')
-
-    @property
-    def isGui(self):
-        section = self.section.split('/')[-1].lower()
-        return section in ('x11', 'gnome', 'kde')
-
-    _HYPHEN_PATTERN = re.compile(r'(\s|_)+')
-
-    def matchName(self, name):
-        needle = name.strip().lower()
-        haystack = self.name.lower()
-        needle = Package._HYPHEN_PATTERN.sub('-', needle)
-        haystack = Package._HYPHEN_PATTERN.sub('-', haystack)
-        if haystack.find(needle) >= 0:
-            return True
-        return False
-
-    def matchDetails(self, details):
-        if self.matchName(details):
-            return True
-        needle = details.strip().lower()
-        haystack = self.description.lower()
-        if haystack.find(needle) >= 0:
-            return True
-        return False
-
-    def matchGroup(self, name):
-        needle = name.strip().lower()
-        haystack = self.group
-        if haystack.startswith(needle):
-            return True
-        return False
-
-class PackageKitProgress(apt.progress.OpProgress, apt.progress.FetchProgress):
-    def __init__(self, backend):
-        self._backend = backend
-        apt.progress.OpProgress.__init__(self)
-        apt.progress.FetchProgress.__init__(self)
-
-    # OpProgress callbacks
-    def update(self, percent):
-        pass
-
-    def done(self):
-        pass
-
-    # FetchProgress callbacks
-    def pulse(self):
-        apt.progress.FetchProgress.pulse(self)
-        self._backend.percentage(self.percent)
-        return True
-
-    def stop(self):
-        self._backend.percentage(100)
-
-    def mediaChange(self, medium, drive):
-        # This probably should not be an error, but a Message.
-        self._backend.error(ERROR_UNKNOWN,
-                "Medium change needed")
-
-class PackageKitAptBackend(PackageKitBaseBackend):
-    def __init__(self, args):
-        PackageKitBaseBackend.__init__(self, args)
-        self.status(STATUS_SETUP)
-        self._caches  = {}
-        self._apt_cache = apt.Cache(PackageKitProgress(self))
-        default = apt_pkg.Config.Find("APT::Default-Release")
-        if default=="":
-            d = get_distro()
-            if d.id == "Debian":
-                default = "stable"
-            elif d.id == "Ubuntu":
-                default = "main"
-            else:
-                raise Exception,d.id
-
-        self._caches[default] = self._apt_cache
-
-
-    def search_name(self, filters, key):
-        '''
-        Implement the {backend}-search-name functionality
-        '''
-        self.status(STATUS_INFO)
-        self.allow_cancel(True)
-        for package in self._do_search(filters,
-                lambda pkg: pkg.matchName(key)):
-            self._emit_package(package)
-
-    def search_details(self, filters, key):
-        '''
-        Implement the {backend}-search-details functionality
-        '''
-        self.status(STATUS_INFO)
-        self.allow_cancel(True)
-        for package in self._do_search(filters,
-                lambda pkg: pkg.matchDetails(key)):
-            self._emit_package(package)
-
-    def search_group(self, filters, key):
-        '''
-        Implement the {backend}-search-group functionality
-        '''
-        self.status(STATUS_INFO)
-        self.allow_cancel(True)
-        for package in self._do_search(filters,
-                lambda pkg: pkg.matchGroup(key)):
-            self._emit_package(package)
-
-    def search_file(self, filters, key):
-        '''
-        Implement the {backend}-search-file functionality
-        '''
-        self.allow_cancel(True)
-        self.percentage(None)
-
-        self.error(ERROR_NOT_SUPPORTED,
-                "This function is not implemented in this backend")
-
-    def refresh_cache(self):
-        '''
-        Implement the {backend}-refresh_cache functionality
-        '''
-        self.status(STATUS_REFRESH_CACHE)
-        try:
-            res = self._apt_cache.update(PackageKitProgress(self))
-        except Exception, error_message:
-             self.error(ERROR_UNKNOWN,
-                        "Failed to fetch the following items:\n%s" % error_message)
-        return res
-
-    def get_details(self, package):
-        '''
-        Implement the {backend}-get-details functionality
-        '''
-        self.status(STATUS_INFO)
-        name, version, arch, data = self.get_package_from_id(package)
-        pkg = Package(self, self._apt_cache[name])
-        description = re.sub('\s+', ' ', pkg.description).strip()
-        self.description(package, 'unknown', pkg.group, description,
-                         pkg.architecture, pkg.packageSize)
-
-    def resolve(self, name):
-        '''
-        Implement the {backend}-resolve functionality
-        '''
-        self.status(STATUS_INFO)
-        try:
-            pkg = Package(self,self._apt_cache[name])
-            self._emit_package(pkg)
-        except KeyError:
-            self.error(ERROR_PACKAGE_NOT_FOUND,"Can't find a package called '%s'"%name)
-
-    def _do_deps(self,inp,deps,recursive):
-        inp.markInstall()
-        newkeys = []
-        for x in inp.candidateDependencies:
-            n = x.or_dependencies[0].name
-            if not deps.has_key(n):
-                deps[n] = []
-                newkeys.append(n)
-            deps[n].append((x.or_dependencies[0].version,x.or_dependencies[0].relation))
-        if recursive:
-            for n in newkeys:
-                try:
-                    deps = self._do_deps(Package(self,self._apt_cache[n],version=deps[n]),deps,recursive)
-                except KeyError: # FIXME: we're assuming this is a virtual package, which we can't cope with yet
-                    del deps[n]
-                    continue
-        return deps
-
-    def get_depends(self,filters,package, recursive):
-        '''
-        Implement the {backend}-get-depends functionality
-        '''
-        self.allow_cancel(True)
-        self.status(STATUS_INFO)
-        recursive = (recursive == "True")
-        name, version, arch, data = self.get_package_from_id(package)
-        pkg = Package(self,self._apt_cache[name],version=[(version,"=")],data=data)
-        pkg.setVersion(version)
-        deps = self._do_deps(pkg, {}, recursive)
-        for n in deps.keys():
-           self._emit_package(Package(self,self._apt_cache[n],version=deps[n]))
-
-    def _do_reqs(self,inp,pkgs,recursive):
-        extra = []
-        fails = []
-        for r in inp._pkg.RevDependsList:
-            ch = apt_pkg.CheckDep(inp._version,r.CompType,r.TargetVer)
-            v = (r.ParentPkg.Name,r.ParentVer.VerStr)
-            if not ch or v in fails:
-                #print "skip",r.TargetVer,r.CompType,r.ParentPkg.Name,r.ParentVer.VerStr
-                fails.append(v)
-                continue
-            p = Package(self,self._apt_cache[r.ParentPkg.Name],r.ParentVer.VerStr)
-            if v not in pkgs:
-                extra.append(p)
-                #print "new pkg",p
-                self._emit_package(p)
-            pkgs.add(v)
-        if recursive:
-            for e in extra:
-                pkgs = self._do_reqs(p, pkgs,recursive)
-        return pkgs
-
-    def get_requires(self,package,recursive):
-        '''
-        Implement the {backend}-get-requires functionality
-        '''
-        self.allow_cancel(True)
-        self.status(STATUS_INFO)
-        recursive = (recursive == "True")
-        name, version, arch, data = self.get_package_from_id(package)
-        pkg = Package(self,self._apt_cache[name], version=[(version,"=")], data=data)
-
-        pkgs = Set()
-        self._do_reqs(pkg,pkgs, recursive)
-
-    def _build_repo_list(self):
-        repo = {}
-
-        sources = SourcesList()
-        repo["__sources"] = sources
-
-        root = apt_pkg.Config.FindDir("Dir::State::Lists")
-        #print root
-        for entry in sources:
-            if entry.type!="":
-                url = entry.uri
-                #if entry.template!=None:
-                url +="/dists/"
-                url += entry.dist
-                url = url.replace("//dists","/dists")
-                #print url
-                path = join(root,"%s_Release"%(apt_pkg.URItoFileName(url)))
-                if not exists(path):
-                    #print path
-                    name = "%s/unknown"%urlparse(entry.uri)[1]
-                else:
-                    lines = file(path).readlines()
-                    origin = ""
-                    suite = ""
-                    for l in lines:
-                        if l.find("Origin: ")==0:
-                            origin = l.split(" ",1)[1].strip()
-                        elif l.find("Suite: ")==0:
-                            suite = l.split(" ",1)[1].strip()
-                    assert origin!="" and suite!=""
-                    name = "%s/%s"%(origin,suite)
-                if entry.type == "deb-src":
-                    name += "-src"
-
-                repo[name] = {"entry":entry}
-        return repo
-
-    def get_repo_list(self, filters):
-        '''
-        Implement the {backend}-get-repo-list functionality
-        '''
-        self.allow_interrupt(True)
-        self.status(STATUS_INFO)
-        repo = self._build_repo_list()
-        for e in repo.keys():
-            if e == "__sources":
-                continue
-            self.repo_detail(repo[e]["entry"].line.strip(),e,not repo[e]["entry"].disabled)
-
-    def repo_enable(self, repoid, enable):
-        '''
-        Implement the {backend}-repo-enable functionality
-        '''
-        enable = (enable == "True")
-        repo = self._build_repo_list()
-        if not repo.has_key(repoid):
-            self.error(ERROR_REPO_NOT_FOUND,"Couldn't find repo '%s'"%repoid)
-            return
-        r = repo[repoid]
-        if not r["entry"].disabled == enable: # already there
-            return
-        r["entry"].set_enabled(enable)
-        try:
-            repo["__sources"].save()
-        except IOError,e:
-            self.error(ERROR_UNKNOWN, "Problem while trying to save repo settings to %s: %s"%(e.filename,e.strerror))
-
-    def get_updates(self, filter):
-        self._apt_cache.upgrade(False)
-        for pkg in self._apt_cache.getChanges():
-            self._emit_package(Package(self, pkg))
-
-    def get_update_detail(self, package):
-        self.allow_cancel(True)
-        self.percentage(None)
-        self.status(STATUS_INFO)
-        name, version, arch, data = self.get_package_from_id(package)
-        update = ""
-        obsolete = ""
-        cve_url = ""
-        bz_url = ""
-        vendor_url = ""
-        reboot = "none"
-        desc = self._apt_cache[name].description
-        self.update_detail(package,update,obsolete,vendor_url,bz_url,cve_url,reboot,desc)
-
-
-    def install_files (self, inst_files):
-        '''
-        Implement the {backend}-install_files functionality
-        Install the package containing the inst_file file
-        '''
-        if not exists(inst_file):
-            self.error(ERROR_PACKAGE_NOT_FOUND,"Can't find %s"%inst_file)
-            return
-        deb = DebPackage(inst_file)
-        deps = {}
-        for k in ["Depends","Recommends"]:
-            if not deb._sections.has_key(k):
-                continue
-            for items in apt_pkg.ParseDepends(deb[k]):
-                assert len(items) == 1,"Can't handle or deps properly yet"
-                (pkg,ver,comp) = items[0]
-                if not deps.has_key(pkg):
-                    deps[pkg] = []
-                deps[pkg].append((ver,comp))
-        for n in deps.keys():
-           p = Package(self,self._apt_cache[n],version=deps[n])
-           if not p.isInstalled:
-               p.markInstall()
-        assert self._apt_cache.getChanges()==[],"Don't handle install changes yet"
-        # FIXME: nasty hack. Need a better way in
-        ret = system("dpkg -i %s"%inst_file)
-        if ret!=0:
-            self.error(ERROR_UNKNOWN,"Can't install package")
-
-    ### Helpers ###
-    def _emit_package(self, package):
-        id = self.get_package_id(package.name,
-                package._version,
-                package.architecture,
-                package._data)
-        if package.isInstalled:
-            status = INFO_INSTALLED
-        else:
-            status = INFO_AVAILABLE
-        summary = package.summary
-        self.package(id, status, summary)
-
-    def _do_search(self, filters, condition):
-        filters = filters.split(';')
-        size = len(self._apt_cache)
-        percentage = 0
-        for i, pkg in enumerate(self._apt_cache):
-            new_percentage = i / float(size) * 100
-            if new_percentage - percentage >= 5:
-                percentage = new_percentage
-                self.percentage(percentage)
-            package = Package(self, pkg)
-            if package.installedVersion is None and \
-                    package.candidateVersion is None:
-                continue
-            if not condition(package):
-                continue
-                continue
-            vers = [x.VerStr for x in package._pkg.VersionList]
-            if package.installedVersion!=None:
-                i = package.installedVersion
-                if i in vers and vers[0]!=i:
-                    del vers[vers.index(i)]
-                    vers.insert(0,i)
-
-            for ver in vers:
-                p = Package(self, package, version=[[ver,"="]])
-                if self._do_filtering(p, filters):
-                    yield p
-        self.percentage(100)
-
-    def _do_filtering(self, package, filters):
-        if len(filters) == 0 or filters == ['none']:
-            return True
-        if (FILTER_INSTALLED in filters) and (not package.isInstalled):
-            return False
-        if (FILTER_NOT_INSTALLED in filters) and package.isInstalled:
-            return False
-        if (FILTER_GUI in filters) and (not package.isGui):
-            return False
-        if (FILTER_NOT_GUI in filters) and package.isGui:
-            return False
-        if (FILTER_DEVELOPMENT in filters) and (not package.isDevelopment):
-            return False
-        if (FILTER_NOT_DEVELOPMENT in filters) and package.isDevelopment:
-            return False
-        return True
-
diff --git a/backends/apt.deprecated/helpers/get-depends.py b/backends/apt.deprecated/helpers/get-depends.py
deleted file mode 100755
index 94dca4a..0000000
--- a/backends/apt.deprecated/helpers/get-depends.py
+++ /dev/null
@@ -1,20 +0,0 @@
-#!/usr/bin/python
-#
-# Copyright (C) 2007 Richard Hughes <richard at hughsie.com>
-#
-# Licensed under the GNU General Public License Version 2
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
-
-import sys
-
-from aptBackend import PackageKitAptBackend
-filters=sys.argv[1]
-package=sys.argv[2]
-recursive = sys.argv[3]
-backend = PackageKitAptBackend(sys.argv[1:])
-backend.get_depends(filters, package, recursive)
-sys.exit(0)
diff --git a/backends/apt.deprecated/helpers/get-details.py b/backends/apt.deprecated/helpers/get-details.py
deleted file mode 100755
index a813640..0000000
--- a/backends/apt.deprecated/helpers/get-details.py
+++ /dev/null
@@ -1,18 +0,0 @@
-#!/usr/bin/python
-#
-# Copyright (C) 2007 Ali Sabil <ali.sabil at gmail.com>
-#
-# Licensed under the GNU General Public License Version 2
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
-
-import sys
-from aptBackend import PackageKitAptBackend
-
-package = sys.argv[1]
-backend = PackageKitAptBackend(sys.argv[1:])
-backend.get_details(package)
-sys.exit(0)
diff --git a/backends/apt.deprecated/helpers/get-repo-list.py b/backends/apt.deprecated/helpers/get-repo-list.py
deleted file mode 100755
index 5529f72..0000000
--- a/backends/apt.deprecated/helpers/get-repo-list.py
+++ /dev/null
@@ -1,20 +0,0 @@
-#!/usr/bin/python
-#
-# Copyright (C) 2007 Richard Hughes <richard at hughsie.com>
-#
-# Licensed under the GNU General Public License Version 2
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
-
-import sys
-
-from aptBackend import PackageKitAptBackend
-filters = sys.argv[1]
-
-backend = PackageKitAptBackend(sys.argv[2:])
-backend.get_repo_list(filters)
-backend.unLock()
-sys.exit(0)
diff --git a/backends/apt.deprecated/helpers/get-requires.py b/backends/apt.deprecated/helpers/get-requires.py
deleted file mode 100755
index e581010..0000000
--- a/backends/apt.deprecated/helpers/get-requires.py
+++ /dev/null
@@ -1,20 +0,0 @@
-#!/usr/bin/python
-#
-# Copyright (C) 2007 Richard Hughes <richard at hughsie.com>
-#
-# Licensed under the GNU General Public License Version 2
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
-
-import sys
-
-from aptBackend import PackageKitAptBackend
-package = sys.argv[1]
-recursive = sys.argv[2]
-
-backend = PackageKitAptBackend(sys.argv[1:])
-backend.get_requires(package, recursive)
-sys.exit(0)
diff --git a/backends/apt.deprecated/helpers/get-update-detail.py b/backends/apt.deprecated/helpers/get-update-detail.py
deleted file mode 100755
index 5524d9a..0000000
--- a/backends/apt.deprecated/helpers/get-update-detail.py
+++ /dev/null
@@ -1,18 +0,0 @@
-#!/usr/bin/python
-#
-# Copyright (C) 2008 Michael Vogt <mvo at ubuntu.com>
-#
-# Licensed under the GNU General Public License Version 2
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
-
-import sys
-
-from aptBackend import PackageKitAptBackend
-package=sys.argv[1]
-backend = PackageKitAptBackend(sys.argv[2:])
-backend.get_update_detail(package)
-sys.exit(0)
diff --git a/backends/apt.deprecated/helpers/get-updates.py b/backends/apt.deprecated/helpers/get-updates.py
deleted file mode 100755
index 4f45fbf..0000000
--- a/backends/apt.deprecated/helpers/get-updates.py
+++ /dev/null
@@ -1,19 +0,0 @@
-#!/usr/bin/python
-#
-# Copyright (C) 2008 Michael Vogt <mvo at ubuntu.com>
-#
-# Licensed under the GNU General Public License Version 2
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
-
-import sys
-from aptBackend import PackageKitAptBackend
-
-filter = sys.argv[1]
-
-backend = PackageKitAptBackend(sys.argv[1:])
-backend.get_updates(filter)
-sys.exit(0)
diff --git a/backends/apt.deprecated/helpers/install-files.py b/backends/apt.deprecated/helpers/install-files.py
deleted file mode 100755
index dfa024c..0000000
--- a/backends/apt.deprecated/helpers/install-files.py
+++ /dev/null
@@ -1,21 +0,0 @@
-#!/usr/bin/python
-#
-# Copyright (C) 2007 Richard Hughes <richard at hughsie.com>
-# Copyright (C) 2007 Red Hat Inc, Seth Vidal <skvidal at fedoraproject.org>
-#
-# Licensed under the GNU General Public License Version 2
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
-
-import sys
-
-from aptBackend import PackageKitAptBackend
-
-trusted = sys.argv[1]
-files_to_inst = sys.argv[2:]
-backend = PackageKitAptBackend(sys.argv[1:])
-backend.install_files(trusted, files_to_inst)
-sys.exit(0)
diff --git a/backends/apt.deprecated/helpers/packagekit b/backends/apt.deprecated/helpers/packagekit
deleted file mode 120000
index 8d22531..0000000
--- a/backends/apt.deprecated/helpers/packagekit
+++ /dev/null
@@ -1 +0,0 @@
-../../../python/packagekit
\ No newline at end of file
diff --git a/backends/apt.deprecated/helpers/refresh-cache.py b/backends/apt.deprecated/helpers/refresh-cache.py
deleted file mode 100755
index 881479d..0000000
--- a/backends/apt.deprecated/helpers/refresh-cache.py
+++ /dev/null
@@ -1,17 +0,0 @@
-#!/usr/bin/python
-#
-# Copyright (C) 2007 Ali Sabil <ali.sabil at gmail.com>
-#
-# Licensed under the GNU General Public License Version 2
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
-
-import sys
-from aptBackend import PackageKitAptBackend
-
-backend = PackageKitAptBackend(sys.argv[1:])
-backend.refresh_cache()
-sys.exit(0)
diff --git a/backends/apt.deprecated/helpers/repo-enable.py b/backends/apt.deprecated/helpers/repo-enable.py
deleted file mode 100755
index 3cc36ae..0000000
--- a/backends/apt.deprecated/helpers/repo-enable.py
+++ /dev/null
@@ -1,20 +0,0 @@
-#!/usr/bin/python
-#
-# Copyright (C) 2007 Richard Hughes <richard at hughsie.com>
-#
-# Licensed under the GNU General Public License Version 2
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
-
-import sys
-
-from aptBackend import PackageKitAptBackend
-repoid = sys.argv[1]
-state=sys.argv[2]
-backend = PackageKitAptBackend(sys.argv[2:])
-backend.repo_enable(repoid,state)
-backend.unLock()
-sys.exit(0)
diff --git a/backends/apt.deprecated/helpers/resolve.py b/backends/apt.deprecated/helpers/resolve.py
deleted file mode 100755
index aac34df..0000000
--- a/backends/apt.deprecated/helpers/resolve.py
+++ /dev/null
@@ -1,20 +0,0 @@
-#!/usr/bin/python
-#
-# Copyright (C) 2007 Richard Hughes <richard at hughsie.com>
-#
-# Licensed under the GNU General Public License Version 2
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
-
-import sys
-
-from aptBackend import PackageKitAptBackend
-filters = sys.argv[1]
-name=sys.argv[2]
-backend = PackageKitAptBackend(sys.argv[2:])
-backend.resolve(name)
-backend.unLock()
-sys.exit(0)
diff --git a/backends/apt.deprecated/helpers/search-details.py b/backends/apt.deprecated/helpers/search-details.py
deleted file mode 100755
index d02f1b0..0000000
--- a/backends/apt.deprecated/helpers/search-details.py
+++ /dev/null
@@ -1,21 +0,0 @@
-#!/usr/bin/python
-#
-# Copyright (C) 2007 Ali Sabil <ali.sabil at gmail.com>
-#
-# Licensed under the GNU General Public License Version 2
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
-
-import sys
-
-options = sys.argv[1]
-searchlist = sys.argv[2]
-
-from aptBackend import PackageKitAptBackend
-
-backend = PackageKitAptBackend(sys.argv[1:])
-backend.search_details(options,searchlist)
-sys.exit(0)
diff --git a/backends/apt.deprecated/helpers/search-file.py b/backends/apt.deprecated/helpers/search-file.py
deleted file mode 100755
index ec60319..0000000
--- a/backends/apt.deprecated/helpers/search-file.py
+++ /dev/null
@@ -1,21 +0,0 @@
-#!/usr/bin/python
-#
-# Copyright (C) 2007 Ali Sabil <ali.sabil at gmail.com>
-#
-# Licensed under the GNU General Public License Version 2
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
-
-import sys
-
-options = sys.argv[1]
-searchlist = sys.argv[2]
-
-from aptBackend import PackageKitAptBackend
-
-backend = PackageKitAptBackend(sys.argv[1:])
-backend.search_file(options,searchlist)
-sys.exit(0)
diff --git a/backends/apt.deprecated/helpers/search-group.py b/backends/apt.deprecated/helpers/search-group.py
deleted file mode 100755
index f63ee80..0000000
--- a/backends/apt.deprecated/helpers/search-group.py
+++ /dev/null
@@ -1,21 +0,0 @@
-#!/usr/bin/python
-#
-# Copyright (C) 2007 Ali Sabil <ali.sabil at gmail.com>
-#
-# Licensed under the GNU General Public License Version 2
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
-
-import sys
-
-options = sys.argv[1]
-searchlist = sys.argv[2]
-
-from aptBackend import PackageKitAptBackend
-
-backend = PackageKitAptBackend(sys.argv[1:])
-backend.search_group(options,searchlist)
-sys.exit(0)
diff --git a/backends/apt.deprecated/helpers/search-name.py b/backends/apt.deprecated/helpers/search-name.py
deleted file mode 100755
index 9f73c89..0000000
--- a/backends/apt.deprecated/helpers/search-name.py
+++ /dev/null
@@ -1,21 +0,0 @@
-#!/usr/bin/python
-#
-# Copyright (C) 2007 Ali Sabil <ali.sabil at gmail.com>
-#
-# Licensed under the GNU General Public License Version 2
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
-
-import sys
-
-options = sys.argv[1]
-searchlist = sys.argv[2]
-
-from aptBackend import PackageKitAptBackend
-
-backend = PackageKitAptBackend(sys.argv[1:])
-backend.search_name(options,searchlist)
-sys.exit(0)
diff --git a/backends/apt.deprecated/packagekit b/backends/apt.deprecated/packagekit
new file mode 120000
index 0000000..0b64032
--- /dev/null
+++ b/backends/apt.deprecated/packagekit
@@ -0,0 +1 @@
+../../python/packagekit/
\ No newline at end of file
diff --git a/backends/apt.deprecated/pk-backend-apt.c b/backends/apt.deprecated/pk-backend-apt.c
index 4d18edd..7efcc6e 100644
--- a/backends/apt.deprecated/pk-backend-apt.c
+++ b/backends/apt.deprecated/pk-backend-apt.c
@@ -108,7 +108,7 @@ backend_get_depends (PkBackend *backend, PkBitfield filters, gchar **package_ids
 {
 	gchar *filters_text;
 	filters_text = pk_filter_bitfield_to_text (filters);
-	pk_backend_spawn_helper (spawn, "get-depends.py", filters_text, package_id, pk_backend_bool_to_text (recursive), NULL);
+	pk_backend_spawn_helper (spawn, "aptBackend.py", "get-depends", filters_text, package_id, pk_backend_bool_to_text (recursive), NULL);
 	g_free (filters_text);
 }
 
@@ -120,7 +120,7 @@ backend_get_updates (PkBackend *backend, PkBitfield filters)
 {
 	gchar *filters_text;
 	filters_text = pk_filter_bitfield_to_text (filters);
-	pk_backend_spawn_helper (spawn, "get-updates.py", filters_text, NULL);
+	pk_backend_spawn_helper (spawn, "aptBackend.py", "get-updates", filters_text, NULL);
 	g_free (filters_text);
 }
 
@@ -130,7 +130,7 @@ backend_get_updates (PkBackend *backend, PkBitfield filters)
 static void
 backend_get_update_detail (PkBackend *backend, gchar **package_ids)
 {
-	pk_backend_spawn_helper (spawn, "get-update-detail.py", package_id, NULL);
+	pk_backend_spawn_helper (spawn, "aptBackend.py", "get-update-detail", package_id, NULL);
 }
 
 /**
@@ -150,7 +150,7 @@ backend_install_packages (PkBackend *backend, gchar **package_ids)
 
 	/* send the complete list as stdin */
 	package_ids_temp = pk_package_ids_to_text (package_ids);
-	pk_backend_spawn_helper (spawn, "install-packages.py", package_ids_temp, NULL);
+	pk_backend_spawn_helper (spawn, "aptBackend.py", "install-packages", package_ids_temp, NULL);
 	g_free (package_ids_temp);
 }
 
@@ -167,7 +167,7 @@ backend_refresh_cache (PkBackend *backend, gboolean force)
 		return;
 	}
 
-	pk_backend_spawn_helper (spawn, "refresh-cache.py", NULL);
+	pk_backend_spawn_helper (spawn, "aptBackend.py", "refresh-cache", NULL);
 }
 
 /**
@@ -178,7 +178,7 @@ backend_remove_packages (PkBackend *backend, gchar **package_ids, gboolean allow
 {
 	gchar *package_ids_temp;
 	package_ids_temp = pk_package_ids_to_text (package_ids);
-	pk_backend_spawn_helper (spawn, "remove-packages.py", pk_backend_bool_to_text (allow_deps), package_ids_temp, NULL);
+	pk_backend_spawn_helper (spawn, "aptBackend.py", "remove-packages", pk_backend_bool_to_text (allow_deps), package_ids_temp, NULL);
 	g_free (package_ids_temp);
 } */
 
@@ -199,7 +199,7 @@ backend_update_packages (PkBackend *backend, gchar **package_ids)
 
 	/* send the complete list as stdin */
 	package_ids_temp = pk_package_ids_to_text (package_ids);
-	pk_backend_spawn_helper (spawn, "update-packages.py", package_ids_temp, NULL);
+	pk_backend_spawn_helper (spawn, "aptBackend.py", "update-packages", package_ids_temp, NULL);
 	g_free (package_ids_temp);
 }
 
@@ -209,7 +209,7 @@ backend_update_packages (PkBackend *backend, gchar **package_ids)
 static void
 backend_update_system (PkBackend *backend)
 {
-	pk_backend_spawn_helper (spawn, "update-system.py", NULL);
+	pk_backend_spawn_helper (spawn, "aptBackend.py", "update-system", NULL);
 }
 
 /**
@@ -220,7 +220,7 @@ backend_resolve (PkBackend *backend, PkBitfield filters, gchar **package_ids)
 {
 	gchar *filters_text;
 	filters_text = pk_filter_bitfield_to_text (filters);
-	pk_backend_spawn_helper (spawn, "resolve.py", filters_text, package_id, NULL);
+	pk_backend_spawn_helper (spawn, "aptBackend.py", "resolve", filters_text, package_id, NULL);
 	g_free (filters_text);
 }
 
@@ -232,7 +232,7 @@ backend_get_repo_list (PkBackend *backend, PkBitfield filters)
 {
 	gchar *filters_text;
 	filters_text = pk_filter_bitfield_to_text (filters);
-	pk_backend_spawn_helper (spawn, "get-repo-list.py", filters_text, NULL);
+	pk_backend_spawn_helper (spawn, "aptBackend.py", "get-repo-list", filters_text, NULL);
 	g_free (filters_text);
 }
 
commit 138b641a54726378dc4e4dec188d5235bb023972
Author: Richard Hughes <richard at hughsie.com>
Date:   Fri Sep 26 14:47:16 2008 +0100

    trivial: fix build after removing pisi

diff --git a/configure.ac b/configure.ac
index 2bee9dc..c91359f 100644
--- a/configure.ac
+++ b/configure.ac
@@ -552,7 +552,6 @@ backends/urpmi/helpers/urpmi_backend/Makefile
 backends/razor/Makefile
 backends/yum/Makefile
 backends/pisi/Makefile
-backends/pisi/helpers/Makefile
 backends/poldek/Makefile
 backends/zypp/Makefile
 data/Makefile
commit f66494c3c0ec2eb55b23045192caab9e3a022372
Merge: 119bc1b... f6dd84f...
Author: Richard Hughes <richard at hughsie.com>
Date:   Fri Sep 26 14:46:41 2008 +0100

    Merge branch 'pisi-dispatcher'

commit f6dd84f635e5feb93dd142aad2cfcbb6dd943f9c
Author: Richard Hughes <richard at hughsie.com>
Date:   Fri Sep 26 14:46:02 2008 +0100

    pisi: convert the backend to using a dispatcher

diff --git a/backends/pisi/.gitignore b/backends/pisi/.gitignore
index c851833..03a0663 100644
--- a/backends/pisi/.gitignore
+++ b/backends/pisi/.gitignore
@@ -7,4 +7,4 @@ Makefile.in
 *.loT
 *.o
 *~
-
+*.pyc
diff --git a/backends/pisi/Makefile.am b/backends/pisi/Makefile.am
index e51f285..1b49b3d 100644
--- a/backends/pisi/Makefile.am
+++ b/backends/pisi/Makefile.am
@@ -1,4 +1,7 @@
-SUBDIRS = helpers
+helperdir = $(datadir)/PackageKit/helpers/pisi
+dist_helper_DATA = 			\
+	pisiBackend.py
+
 plugindir = $(PK_PLUGIN_DIR)
 plugin_LTLIBRARIES = libpk_backend_pisi.la
 libpk_backend_pisi_la_SOURCES = pk-backend-pisi.c
@@ -6,3 +9,9 @@ libpk_backend_pisi_la_LIBADD = $(PK_PLUGIN_LIBS)
 libpk_backend_pisi_la_LDFLAGS = -module -avoid-version
 libpk_backend_pisi_la_CFLAGS = $(PK_PLUGIN_CFLAGS)
 
+install-data-hook:
+	chmod a+rx $(DESTDIR)$(helperdir)/*.py
+
+clean-local :
+	rm -f *~
+
diff --git a/backends/pisi/helpers/Makefile.am b/backends/pisi/helpers/Makefile.am
deleted file mode 100644
index aca9f54..0000000
--- a/backends/pisi/helpers/Makefile.am
+++ /dev/null
@@ -1,32 +0,0 @@
-
-helperdir = $(datadir)/PackageKit/helpers/pisi
-
-NULL =
-
-dist_helper_DATA = 			\
-	get-depends.py			\
-	get-files.py			\
-	get-details.py			\
-	get-repo-list.py 		\
-	get-requires.py			\
-	get-updates.py			\
-	install-files.py		\
-	install-packages.py		\
-	refresh-cache.py 		\
-	remove-packages.py		\
-	resolve.py			\
-	repo-set-data.py		\
-	search-details.py		\
-	search-file.py			\
-	search-group.py			\
-	search-name.py			\
-	update-packages.py		\
-	update-system.py		\
-	pisiBackend.py			\
-	$(NULL)
-
-install-data-hook:
-	chmod a+rx $(DESTDIR)$(helperdir)/*.py
-
-clean-local :
-	rm -f *~
diff --git a/backends/pisi/helpers/get-depends.py b/backends/pisi/helpers/get-depends.py
deleted file mode 100644
index 9c38947..0000000
--- a/backends/pisi/helpers/get-depends.py
+++ /dev/null
@@ -1,19 +0,0 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-#
-# Copyright (C) 2007 S.Çağlar Onur <caglar at pardus.org.tr>
-#
-# Licensed under the GNU General Public License Version 2
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
-
-import sys
-import pisiBackend
-
-backend = pisiBackend.PackageKitPisiBackend(sys.argv[1:])
-backend.get_depends(sys.argv[1], sys.argv[2], sys.argv[3])
-
-sys.exit()
diff --git a/backends/pisi/helpers/get-details.py b/backends/pisi/helpers/get-details.py
deleted file mode 100644
index 4531bd9..0000000
--- a/backends/pisi/helpers/get-details.py
+++ /dev/null
@@ -1,19 +0,0 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-#
-# Copyright (C) 2007 S.Çağlar Onur <caglar at pardus.org.tr>
-#
-# Licensed under the GNU General Public License Version 2
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
-
-import sys
-import pisiBackend
-
-backend = pisiBackend.PackageKitPisiBackend(sys.argv[1:])
-backend.get_details(sys.argv[1])
-
-sys.exit()
diff --git a/backends/pisi/helpers/get-files.py b/backends/pisi/helpers/get-files.py
deleted file mode 100644
index 7a1f178..0000000
--- a/backends/pisi/helpers/get-files.py
+++ /dev/null
@@ -1,19 +0,0 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-#
-# Copyright (C) 2007 S.Çağlar Onur <caglar at pardus.org.tr>
-#
-# Licensed under the GNU General Public License Version 2
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
-
-import sys
-import pisiBackend
-
-backend = pisiBackend.PackageKitPisiBackend(sys.argv[1:])
-backend.get_files(sys.argv[1])
-
-sys.exit()
diff --git a/backends/pisi/helpers/get-repo-list.py b/backends/pisi/helpers/get-repo-list.py
deleted file mode 100644
index db84d4a..0000000
--- a/backends/pisi/helpers/get-repo-list.py
+++ /dev/null
@@ -1,19 +0,0 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-#
-# Copyright (C) 2007 S.Çağlar Onur <caglar at pardus.org.tr>
-#
-# Licensed under the GNU General Public License Version 2
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
-
-import sys
-import pisiBackend
-
-backend = pisiBackend.PackageKitPisiBackend(sys.argv[2:])
-backend.get_repo_list()
-
-sys.exit()
diff --git a/backends/pisi/helpers/get-requires.py b/backends/pisi/helpers/get-requires.py
deleted file mode 100644
index c08194f..0000000
--- a/backends/pisi/helpers/get-requires.py
+++ /dev/null
@@ -1,19 +0,0 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-#
-# Copyright (C) 2007 S.Çağlar Onur <caglar at pardus.org.tr>
-#
-# Licensed under the GNU General Public License Version 2
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
-
-import sys
-import pisiBackend
-
-backend = pisiBackend.PackageKitPisiBackend(sys.argv[1:])
-backend.get_requires(sys.argv[1], sys.argv[2], sys.argv[3])
-
-sys.exit()
diff --git a/backends/pisi/helpers/get-updates.py b/backends/pisi/helpers/get-updates.py
deleted file mode 100644
index f5d79db..0000000
--- a/backends/pisi/helpers/get-updates.py
+++ /dev/null
@@ -1,21 +0,0 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-#
-# Copyright (C) 2007 S.Çağlar Onur <caglar at pardus.org.tr>
-#
-# Licensed under the GNU General Public License Version 2
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
-
-import sys
-import pisiBackend
-
-filter = sys.argv[1]
-
-backend = pisiBackend.PackageKitPisiBackend(sys.argv[1:])
-backend.get_updates(filter)
-
-sys.exit()
diff --git a/backends/pisi/helpers/install-files.py b/backends/pisi/helpers/install-files.py
deleted file mode 100755
index 55d6531..0000000
--- a/backends/pisi/helpers/install-files.py
+++ /dev/null
@@ -1,22 +0,0 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-#
-# Copyright (C) 2007 S.Çağlar Onur <caglar at pardus.org.tr>
-#
-# Licensed under the GNU General Public License Version 2
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
-
-import sys
-
-import pisiBackend
-
-trusted = sys.argv[1]
-files_to_inst = sys.argv[2:]
-backend = pisiBackend.PackageKitPisiBackend(sys.argv[1:])
-backend.install_files(trusted, files_to_inst)
-
-sys.exit()
diff --git a/backends/pisi/helpers/install-packages.py b/backends/pisi/helpers/install-packages.py
deleted file mode 100755
index ff2b478..0000000
--- a/backends/pisi/helpers/install-packages.py
+++ /dev/null
@@ -1,19 +0,0 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-#
-# Copyright (C) 2007 S.Çağlar Onur <caglar at pardus.org.tr>
-#
-# Licensed under the GNU General Public License Version 2
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
-
-import sys
-import pisiBackend
-
-backend = pisiBackend.PackageKitPisiBackend(sys.argv[1:])
-backend.install_packages(sys.argv[1])
-
-sys.exit()
diff --git a/backends/pisi/helpers/pisiBackend.py b/backends/pisi/helpers/pisiBackend.py
deleted file mode 100644
index 22be04c..0000000
--- a/backends/pisi/helpers/pisiBackend.py
+++ /dev/null
@@ -1,414 +0,0 @@
-# -*- coding: utf-8 -*-
-#
-# Licensed under the GNU General Public License Version 2
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-#
-# Copyright (C) 2007 S.Çağlar Onur <caglar at pardus.org.tr>
-
-import pisi
-from packagekit.backend import *
-
-class PackageKitPisiBackend(PackageKitBaseBackend):
-
-    # It's an ugly way to sync with PK Groups and PiSi Components
-    # Maybe we can provide these with our index?
-    groups = {
-            "applications" : GROUP_OTHER,
-            "applications.admin" : GROUP_ADMIN_TOOLS,
-            "applications.archive" : GROUP_OTHER,
-            "applications.crypto" : GROUP_SECURITY,
-            "applications.doc" : GROUP_PUBLISHING,
-            "applications.doc.docbook" : GROUP_PUBLISHING,
-            "applications.editors" : GROUP_ACCESSORIES,
-            "applications.editors.emacs" : GROUP_ACCESSORIES,
-            "applications.emulators" : GROUP_OTHER,
-            "applications.filesystems" : GROUP_OTHER,
-            "applications.games" : GROUP_GAMES,
-            "applications.hardware" : GROUP_OTHER,
-            "applications.multimedia" : GROUP_MULTIMEDIA,
-            "applications.network" : GROUP_INTERNET,
-            "applications.network.mozilla" : GROUP_INTERNET,
-            "applications.pda" : GROUP_ACCESSORIES,
-            "applications.powermanagement" : GROUP_POWER_MANAGEMENT,
-            "applications.printing" : GROUP_PUBLISHING,
-            "applications.science" : GROUP_EDUCATION,
-            "applications.science.astronomy" : GROUP_EDUCATION,
-            "applications.science.electronics" : GROUP_EDUCATION,
-            "applications.science.mathematics" : GROUP_EDUCATION,
-            "applications.security" : GROUP_SECURITY,
-            "applications.shells" : GROUP_OTHER,
-            "applications.tex" : GROUP_PUBLISHING,
-            "applications.util" : GROUP_ACCESSORIES,
-            "applications.virtualization" : GROUP_VIRTUALIZATION,
-            "desktop.fonts" : GROUP_FONTS,
-            "desktop.freedesktop" : GROUP_DESKTOP_OTHER,
-            "desktop.freedesktop.inputmethods" : GROUP_LOCALIZATION,
-            "desktop.freedesktop.xorg" : GROUP_DESKTOP_OTHER,
-            "desktop.freedesktop.xorg.lib" : GROUP_DESKTOP_OTHER,
-            "desktop.gnome" : GROUP_DESKTOP_GNOME,
-            "desktop.kde" : GROUP_DESKTOP_KDE,
-            "desktop.kde.base" : GROUP_DESKTOP_KDE,
-            "desktop.kde.i18n" : GROUP_LOCALIZATION,
-            "kernel" : GROUP_SYSTEM,
-            "kernel.drivers" : GROUP_SYSTEM,
-            "kernel.firmware" : GROUP_SYSTEM,
-            "kernel-xen" : GROUP_VIRTUALIZATION,
-            "kernel-xen.dom0" : GROUP_VIRTUALIZATION,
-            "kernel-xen.dom0.drivers" : GROUP_VIRTUALIZATION,
-            "kernel-xen.dom0.firmware" : GROUP_VIRTUALIZATION,
-            "kernel-xen.domU" : GROUP_VIRTUALIZATION,
-            "programming" : GROUP_PROGRAMMING,
-            "programming.environments" : GROUP_PROGRAMMING,
-            "programming.environments.eclipse" : GROUP_PROGRAMMING,
-            "programming.languages" : GROUP_PROGRAMMING,
-            "programming.languages.dotnet" : GROUP_PROGRAMMING,
-            "programming.languages.gambas" : GROUP_PROGRAMMING,
-            "programming.languages.haskell" : GROUP_PROGRAMMING,
-            "programming.languages.java" : GROUP_PROGRAMMING,
-            "programming.languages.lisp" : GROUP_PROGRAMMING,
-            "programming.languages.pascal" : GROUP_PROGRAMMING,
-            "programming.languages.perl" : GROUP_PROGRAMMING,
-            "programming.languages.php" : GROUP_PROGRAMMING,
-            "programming.languages.python" : GROUP_PROGRAMMING,
-            "programming.languages.tcl" : GROUP_PROGRAMMING,
-            "programming.libs" : GROUP_PROGRAMMING,
-            "programming.tools" : GROUP_PROGRAMMING,
-            "server" : GROUP_SERVERS,
-            "server.database" : GROUP_SERVERS,
-            "server.mail" : GROUP_SERVERS,
-            "server.nis" : GROUP_SERVERS,
-            "server.www" : GROUP_SERVERS,
-            "system" : GROUP_SYSTEM,
-            "system.base" : GROUP_SYSTEM,
-            "system.devel" : GROUP_PROGRAMMING,
-            "system.doc" : GROUP_SYSTEM,
-            "system.locale" : GROUP_LOCALIZATION
-        }
-
-    def __init__(self, args):
-        PackageKitBaseBackend.__init__(self, args)
-
-        self.componentdb = pisi.db.componentdb.ComponentDB()
-        self.filesdb = pisi.db.filesdb.FilesDB()
-        self.installdb = pisi.db.installdb.InstallDB()
-        self.packagedb = pisi.db.packagedb.PackageDB()
-        self.repodb = pisi.db.repodb.RepoDB()
-
-        # Do not ask any question to users
-        self.options = pisi.config.Options()
-        self.options.yes_all = True
-
-    def __get_package_version(self, package):
-        """ Returns version string of given package """
-        # Internal FIXME: PiSi may provide this
-        if package.build is not None:
-            version = "%s-%s-%s" % (package.version, package.release, package.build)
-        else:
-            version = "%s-%s" % (package.version, package.release)
-        return version
-
-    def __get_package(self, package, filters = None):
-        """ Returns package object suitable for other methods """
-        if self.installdb.has_package(package):
-            status = INFO_INSTALLED
-            pkg = self.installdb.get_package(package)
-        elif self.packagedb.has_package(package):
-            status = INFO_AVAILABLE
-            pkg = self.packagedb.get_package(package)
-        else:
-            self.error(ERROR_PACKAGE_NOT_FOUND, "Package was not found")
-
-        if filters:
-            if "none" not in filters:
-                filterlist = filters.split(';')
-
-                if FILTER_INSTALLED in filterlist and status != INFO_INSTALLED:
-                    return
-                if FILTER_NOT_INSTALLED in filterlist and status == INFO_INSTALLED:
-                    return
-                if FILTER_GUI in filterlist and "app:gui" not in pkg.isA:
-                    return
-                if FILTER_NOT_GUI in filterlist and "app:gui" in pkg.isA:
-                    return
-
-        version = self.__get_package_version(pkg)
-
-        id = self.get_package_id(pkg.name, version, pkg.architecture, "")
-
-        return self.package(id, status, pkg.summary)
-
-    def get_depends(self, filters, package_id, recursive):
-        """ Prints a list of depends for a given package """
-        self.allow_cancel(True)
-        self.percentage(None)
-
-        package = self.get_package_from_id(package_id)[0]
-
-        for pkg in self.packagedb.get_package(package).runtimeDependencies():
-            # Internal FIXME: PiSi API has really inconsistent for return types and arguments!
-            self.__get_package(pkg.package)
-
-    def get_details(self, package_id):
-        """ Prints a detailed description for a given package """
-        self.allow_cancel(True)
-        self.percentage(None)
-
-        package = self.get_package_from_id(package_id)[0]
-
-        if self.packagedb.has_package(package):
-            pkg = self.packagedb.get_package(package)
-
-            if self.groups.has_key(pkg.partOf):
-                group = self.groups[pkg.partOf]
-            else:
-                group = GROUP_UNKNOWN
-
-            self.details("%s-%s" % (pkg.name, self.__get_package_version(pkg)),
-                            pkg.license,
-                            group,
-                            pkg.description,
-                            pkg.packageURI,
-                            pkg.packageSize)
-        else:
-            self.error(ERROR_PACKAGE_NOT_FOUND, "Package was not found")
-
-    def get_files(self, package_id):
-        """ Prints a file list for a given package """
-        self.allow_cancel(True)
-        self.percentage(None)
-
-        package = self.get_package_from_id(package_id)[0]
-
-        if self.installdb.has_package(package):
-            pkg = self.installdb.get_files(package)
-
-            # FIXME: Add "/" as suffix
-            files = map(lambda y: y.path, pkg.list)
-
-            file_list = ";".join(files)
-
-            self.files(package, file_list)
-
-    def get_repo_list(self):
-        """ Prints available repositories """
-        self.allow_cancel(True);
-        self.percentage(None)
-
-        for repo in pisi.api.list_repos():
-            # Internal FIXME: What an ugly way to get repo uri
-            # FIXME: Use repository enabled/disabled state
-            self.repo_detail(repo, self.repodb.get_repo(repo).indexuri.get_uri(), "true")
-
-    def get_requires(self, filters, package_id, recursive):
-        """ Prints a list of requires for a given package """
-        self.allow_cancel(True)
-        self.percentage(None)
-
-        package = self.get_package_from_id(package_id)[0]
-
-        # FIXME: Handle packages which is not installed from repository
-        for pkg in self.packagedb.get_rev_deps(package):
-            self.__get_package(pkg[0])
-
-    def get_updates(self, filter):
-        """ Prints available updates and types """
-        self.allow_cancel(True);
-        self.percentage(None)
-
-        for package in pisi.api.list_upgradable():
-
-            pkg = self.packagedb.get_package(package)
-
-            version = self.__get_package_version(pkg)
-            id = self.get_package_id(pkg.name, version, pkg.architecture, "")
-
-            # Internal FIXME: PiSi must provide this information as a single API call :(
-            updates = [i for i in self.packagedb.get_package(package).history 
-                    if pisi.version.Version(i.release) > pisi.version.Version(self.installdb.get_package(package).release)]
-            if pisi.util.any(lambda i:i.type == "security", updates):
-                self.package(id, INFO_SECURITY, pkg.summary)
-            else:
-                self.package(id, INFO_NORMAL, pkg.summary)
-
-    def install_files(self, trusted, files):
-        """ Installs given package into system"""
-        # FIXME: install progress
-        self.allow_cancel(False);
-        self.percentage(None)
-
-        try:
-            self.status(STATUS_INSTALL)
-            pisi.api.install([file])
-        except pisi.Error,e:
-            # FIXME: Error: internal-error : Package re-install declined
-            # Force needed?
-            self.error(ERROR_PACKAGE_ALREADY_INSTALLED, e)
-
-    def install(self, package_id):
-        """ Installs given package into system"""
-        # FIXME: fetch/install progress
-        self.allow_cancel(False);
-        self.percentage(None)
-
-        package = self.get_package_from_id(package_id)[0]
-
-        if self.packagedb.has_package(package):
-            self.status(STATUS_INSTALL)
-            try:
-                pisi.api.install([package])
-            except pisi.Error,e:
-                self.error(ERROR_UNKNOWN, e)
-        else:
-            self.error(ERROR_PACKAGE_NOT_INSTALLED, "Package is already installed")
-
-    def refresh_cache(self):
-        """ Updates repository indexes """
-        self.allow_cancel(False);
-        self.percentage(0)
-        self.status(STATUS_REFRESH_CACHE)
-
-        slice = (100/len(pisi.api.list_repos()))/2
-
-        percentage = 0
-        for repo in pisi.api.list_repos():
-            pisi.api.update_repo(repo)
-            percentage += slice
-            self.percentage(percentage)
-
-        self.percentage(100)
-
-    def remove(self, deps, package_id):
-        """ Removes given package from system"""
-        self.allow_cancel(False);
-        self.percentage(None)
-
-        package = self.get_package_from_id(package_id)[0]
-
-        if self.installdb.has_package(package):
-            self.status(STATUS_REMOVE)
-            try:
-                pisi.api.remove([package])
-            except pisi.Error,e:
-                # system.base packages cannot be removed from system
-                self.error(ERROR_CANNOT_REMOVE_SYSTEM_PACKAGE, e)
-        else:
-            self.error(ERROR_PACKAGE_NOT_INSTALLED, "Package is not installed")
-
-    def repo_set_data(self, repo_id, parameter, value):
-        """ Sets a parameter for the repository specified """
-        self.allow_cancel(False)
-        self.percentage(None)
-
-        if parameter == "add-repo":
-            try:
-                pisi.api.add_repo(repo_id, value, parameter)
-            except pisi.Error, e:
-                self.error(ERROR_UNKNOWN, e)
-
-            try:
-                pisi.api.update_repo(repo_id)
-            except pisi.fetcher.FetchError:
-                pisi.api.remove_repo(repo_id)
-                self.error(ERROR_REPO_NOT_FOUND, "Could not be reached to repository, removing from system")
-        elif parameter == "remove-repo":
-            try:
-                pisi.api.remove_repo(repo_id)
-            except pisi.Error:
-                self.error(ERROR_REPO_NOT_FOUND, "Repository is not exists")
-        else:
-            self.error(ERROR_NOT_SUPPORTED, "Parameter not supported")
-
-    def resolve(self, filters, package):
-        """ Turns a single package name into a package_id suitable for the other methods """
-        self.allow_cancel(True);
-        self.percentage(None)
-
-        self.__get_package(package, filters)
-
-    def search_details(self, filters, key):
-        """ Prints a detailed list of packages contains search term """
-        self.allow_cancel(True)
-        self.percentage(None)
-        self.status(STATUS_INFO)
-        
-        # Internal FIXME: Use search_details instead of _package when API gains that ability :)
-        for pkg in pisi.api.search_package([key]):
-            self.__get_package(pkg, filters)
-
-    def search_file(self, filters, key):
-        """ Prints the installed package which contains the specified file """
-        self.allow_cancel(True)
-        self.percentage(None)
-        self.status(STATUS_INFO)
-
-        # Internal FIXME: Why it is needed?
-        key = key.lstrip("/")
-
-        for pkg, files in pisi.api.search_file(key):
-            self.__get_package(pkg)
-
-    def search_group(self, filters, group):
-        """ Prints a list of packages belongs to searched group """
-        self.allow_cancel(True)
-        self.percentage(None)
-        self.status(STATUS_INFO)
-
-        try:
-            for key in self.groups.keys():
-                if self.groups[key] == group:
-                    for pkg in self.componentdb.get_packages(key, walk = True):
-                        self.__get_package(pkg, filters)
-        except:
-            self.error(ERROR_GROUP_NOT_FOUND, "Component %s was not found" % group)
-
-    def search_name(self, filters, package):
-        """ Prints a list of packages contains search term in its name """
-        self.allow_cancel(True)
-        self.percentage(None)
-        self.status(STATUS_INFO)
-
-        for pkg in pisi.api.search_package([package]):
-            self.__get_package(pkg, filters)
-
-    def update(self, package_id):
-        """ Updates given package to its latest version """
-        # FIXME: fetch/install progress
-        self.allow_cancel(False);
-        self.percentage(None)
-
-        package = self.get_package_from_id(package_id)[0]
-
-        if self.installdb.has_package(package):
-            try:
-                pisi.api.upgrade([package])
-            except pisi.Error,e:
-                self.error(ERROR_UNKNOWN, e)
-        else:
-            self.error(ERROR_PACKAGE_NOT_INSTALLED, "Package is already installed")
-
-    def update_system(self):
-        """ Updates all available packages """
-        # FIXME: fetch/install progress
-        self.allow_cancel(False);
-        self.percentage(None)
-
-        if not len(pisi.api.list_upgradable()) > 0:
-            self.error(ERROR_NO_PACKAGES_TO_UPDATE, "System is already up2date")
-
-        try:
-            pisi.api.upgrade(pisi.api.list_upgradable())
-        except pisi.Error,e:
-            self.error(ERROR_UNKNOWN, e)
diff --git a/backends/pisi/helpers/refresh-cache.py b/backends/pisi/helpers/refresh-cache.py
deleted file mode 100644
index 8a0d15e..0000000
--- a/backends/pisi/helpers/refresh-cache.py
+++ /dev/null
@@ -1,19 +0,0 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-#
-# Copyright (C) 2007 S.Çağlar Onur <caglar at pardus.org.tr>
-#
-# Licensed under the GNU General Public License Version 2
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
-
-import sys
-import pisiBackend
-
-backend = pisiBackend.PackageKitPisiBackend(sys.argv[1:])
-backend.refresh_cache()
-
-sys.exit()
diff --git a/backends/pisi/helpers/remove-packages.py b/backends/pisi/helpers/remove-packages.py
deleted file mode 100755
index 98a3659..0000000
--- a/backends/pisi/helpers/remove-packages.py
+++ /dev/null
@@ -1,19 +0,0 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-#
-# Copyright (C) 2007 S.Çağlar Onur <caglar at pardus.org.tr>
-#
-# Licensed under the GNU General Public License Version 2
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
-
-import sys
-import pisiBackend
-
-backend = pisiBackend.PackageKitPisiBackend(sys.argv[1:])
-backend.remove_packages(sys.argv[1], sys.argv[2])
-
-sys.exit()
diff --git a/backends/pisi/helpers/repo-set-data.py b/backends/pisi/helpers/repo-set-data.py
deleted file mode 100644
index 05dbeb5..0000000
--- a/backends/pisi/helpers/repo-set-data.py
+++ /dev/null
@@ -1,19 +0,0 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-#
-# Copyright (C) 2007 S.Çağlar Onur <caglar at pardus.org.tr>
-#
-# Licensed under the GNU General Public License Version 2
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
-
-import sys
-import pisiBackend
-
-backend = pisiBackend.PackageKitPisiBackend(sys.argv[1:])
-backend.repo_set_data(sys.argv[1], sys.argv[2], sys.argv[3])
-
-sys.exit()
diff --git a/backends/pisi/helpers/resolve.py b/backends/pisi/helpers/resolve.py
deleted file mode 100644
index 1627bfa..0000000
--- a/backends/pisi/helpers/resolve.py
+++ /dev/null
@@ -1,19 +0,0 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-#
-# Copyright (C) 2007 S.Çağlar Onur <caglar at pardus.org.tr>
-#
-# Licensed under the GNU General Public License Version 2
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
-
-import sys
-import pisiBackend
-
-backend = pisiBackend.PackageKitPisiBackend(sys.argv[2:])
-backend.resolve(sys.argv[1], sys.argv[2])
-
-sys.exit()
diff --git a/backends/pisi/helpers/search-details.py b/backends/pisi/helpers/search-details.py
deleted file mode 100644
index 066b029..0000000
--- a/backends/pisi/helpers/search-details.py
+++ /dev/null
@@ -1,19 +0,0 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-#
-# Copyright (C) 2007 S.Çağlar Onur <caglar at pardus.org.tr>
-#
-# Licensed under the GNU General Public License Version 2
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
-
-import sys
-import pisiBackend
-
-backend = pisiBackend.PackageKitPisiBackend(sys.argv[1:])
-backend.search_details(sys.argv[1], sys.argv[2])
-
-sys.exit()
diff --git a/backends/pisi/helpers/search-file.py b/backends/pisi/helpers/search-file.py
deleted file mode 100644
index e086a00..0000000
--- a/backends/pisi/helpers/search-file.py
+++ /dev/null
@@ -1,19 +0,0 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-#
-# Copyright (C) 2007 S.Çağlar Onur <caglar at pardus.org.tr>
-#
-# Licensed under the GNU General Public License Version 2
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
-
-import sys
-import pisiBackend
-
-backend = pisiBackend.PackageKitPisiBackend(sys.argv[1:])
-backend.search_file(sys.argv[1], sys.argv[2])
-
-sys.exit()
diff --git a/backends/pisi/helpers/search-group.py b/backends/pisi/helpers/search-group.py
deleted file mode 100644
index 064149b..0000000
--- a/backends/pisi/helpers/search-group.py
+++ /dev/null
@@ -1,19 +0,0 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-#
-# Copyright (C) 2007 S.Çağlar Onur <caglar at pardus.org.tr>
-#
-# Licensed under the GNU General Public License Version 2
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
-
-import sys
-import pisiBackend
-
-backend = pisiBackend.PackageKitPisiBackend(sys.argv[1:])
-backend.search_group(sys.argv[1], sys.argv[2])
-
-sys.exit()
diff --git a/backends/pisi/helpers/search-name.py b/backends/pisi/helpers/search-name.py
deleted file mode 100644
index 1b4e3aa..0000000
--- a/backends/pisi/helpers/search-name.py
+++ /dev/null
@@ -1,19 +0,0 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-#
-# Copyright (C) 2007 S.Çağlar Onur <caglar at pardus.org.tr>
-#
-# Licensed under the GNU General Public License Version 2
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
-
-import sys
-import pisiBackend
-
-backend = pisiBackend.PackageKitPisiBackend(sys.argv[1:])
-backend.search_name(sys.argv[1], sys.argv[2])
-
-sys.exit()
diff --git a/backends/pisi/helpers/update-packages.py b/backends/pisi/helpers/update-packages.py
deleted file mode 100755
index 4660588..0000000
--- a/backends/pisi/helpers/update-packages.py
+++ /dev/null
@@ -1,19 +0,0 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-#
-# Copyright (C) 2007 S.Çağlar Onur <caglar at pardus.org.tr>
-#
-# Licensed under the GNU General Public License Version 2
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
-
-import sys
-import pisiBackend
-
-backend = pisiBackend.PackageKitPisiBackend(sys.argv[1:])
-backend.update_packages(sys.argv[1])
-
-sys.exit()
diff --git a/backends/pisi/helpers/update-system.py b/backends/pisi/helpers/update-system.py
deleted file mode 100644
index 86ec437..0000000
--- a/backends/pisi/helpers/update-system.py
+++ /dev/null
@@ -1,19 +0,0 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-#
-# Copyright (C) 2007 S.Çağlar Onur <caglar at pardus.org.tr>
-#
-# Licensed under the GNU General Public License Version 2
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
-
-import sys
-import pisiBackend
-
-backend = pisiBackend.PackageKitPisiBackend(sys.argv[1:])
-backend.update_system()
-
-sys.exit()
diff --git a/backends/pisi/packagekit b/backends/pisi/packagekit
new file mode 120000
index 0000000..0b64032
--- /dev/null
+++ b/backends/pisi/packagekit
@@ -0,0 +1 @@
+../../python/packagekit/
\ No newline at end of file
diff --git a/backends/pisi/pisiBackend.py b/backends/pisi/pisiBackend.py
new file mode 100755
index 0000000..36cf792
--- /dev/null
+++ b/backends/pisi/pisiBackend.py
@@ -0,0 +1,422 @@
+# -*- coding: utf-8 -*-
+#
+# Licensed under the GNU General Public License Version 2
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# Copyright (C) 2007 S.Çağlar Onur <caglar at pardus.org.tr>
+
+import pisi
+from packagekit.backend import *
+
+class PackageKitPisiBackend(PackageKitBaseBackend):
+
+    # It's an ugly way to sync with PK Groups and PiSi Components
+    # Maybe we can provide these with our index?
+    groups = {
+            "applications" : GROUP_OTHER,
+            "applications.admin" : GROUP_ADMIN_TOOLS,
+            "applications.archive" : GROUP_OTHER,
+            "applications.crypto" : GROUP_SECURITY,
+            "applications.doc" : GROUP_PUBLISHING,
+            "applications.doc.docbook" : GROUP_PUBLISHING,
+            "applications.editors" : GROUP_ACCESSORIES,
+            "applications.editors.emacs" : GROUP_ACCESSORIES,
+            "applications.emulators" : GROUP_OTHER,
+            "applications.filesystems" : GROUP_OTHER,
+            "applications.games" : GROUP_GAMES,
+            "applications.hardware" : GROUP_OTHER,
+            "applications.multimedia" : GROUP_MULTIMEDIA,
+            "applications.network" : GROUP_INTERNET,
+            "applications.network.mozilla" : GROUP_INTERNET,
+            "applications.pda" : GROUP_ACCESSORIES,
+            "applications.powermanagement" : GROUP_POWER_MANAGEMENT,
+            "applications.printing" : GROUP_PUBLISHING,
+            "applications.science" : GROUP_EDUCATION,
+            "applications.science.astronomy" : GROUP_EDUCATION,
+            "applications.science.electronics" : GROUP_EDUCATION,
+            "applications.science.mathematics" : GROUP_EDUCATION,
+            "applications.security" : GROUP_SECURITY,
+            "applications.shells" : GROUP_OTHER,
+            "applications.tex" : GROUP_PUBLISHING,
+            "applications.util" : GROUP_ACCESSORIES,
+            "applications.virtualization" : GROUP_VIRTUALIZATION,
+            "desktop.fonts" : GROUP_FONTS,
+            "desktop.freedesktop" : GROUP_DESKTOP_OTHER,
+            "desktop.freedesktop.inputmethods" : GROUP_LOCALIZATION,
+            "desktop.freedesktop.xorg" : GROUP_DESKTOP_OTHER,
+            "desktop.freedesktop.xorg.lib" : GROUP_DESKTOP_OTHER,
+            "desktop.gnome" : GROUP_DESKTOP_GNOME,
+            "desktop.kde" : GROUP_DESKTOP_KDE,
+            "desktop.kde.base" : GROUP_DESKTOP_KDE,
+            "desktop.kde.i18n" : GROUP_LOCALIZATION,
+            "kernel" : GROUP_SYSTEM,
+            "kernel.drivers" : GROUP_SYSTEM,
+            "kernel.firmware" : GROUP_SYSTEM,
+            "kernel-xen" : GROUP_VIRTUALIZATION,
+            "kernel-xen.dom0" : GROUP_VIRTUALIZATION,
+            "kernel-xen.dom0.drivers" : GROUP_VIRTUALIZATION,
+            "kernel-xen.dom0.firmware" : GROUP_VIRTUALIZATION,
+            "kernel-xen.domU" : GROUP_VIRTUALIZATION,
+            "programming" : GROUP_PROGRAMMING,
+            "programming.environments" : GROUP_PROGRAMMING,
+            "programming.environments.eclipse" : GROUP_PROGRAMMING,
+            "programming.languages" : GROUP_PROGRAMMING,
+            "programming.languages.dotnet" : GROUP_PROGRAMMING,
+            "programming.languages.gambas" : GROUP_PROGRAMMING,
+            "programming.languages.haskell" : GROUP_PROGRAMMING,
+            "programming.languages.java" : GROUP_PROGRAMMING,
+            "programming.languages.lisp" : GROUP_PROGRAMMING,
+            "programming.languages.pascal" : GROUP_PROGRAMMING,
+            "programming.languages.perl" : GROUP_PROGRAMMING,
+            "programming.languages.php" : GROUP_PROGRAMMING,
+            "programming.languages.python" : GROUP_PROGRAMMING,
+            "programming.languages.tcl" : GROUP_PROGRAMMING,
+            "programming.libs" : GROUP_PROGRAMMING,
+            "programming.tools" : GROUP_PROGRAMMING,
+            "server" : GROUP_SERVERS,
+            "server.database" : GROUP_SERVERS,
+            "server.mail" : GROUP_SERVERS,
+            "server.nis" : GROUP_SERVERS,
+            "server.www" : GROUP_SERVERS,
+            "system" : GROUP_SYSTEM,
+            "system.base" : GROUP_SYSTEM,
+            "system.devel" : GROUP_PROGRAMMING,
+            "system.doc" : GROUP_SYSTEM,
+            "system.locale" : GROUP_LOCALIZATION
+        }
+
+    def __init__(self, args):
+        PackageKitBaseBackend.__init__(self, args)
+
+        self.componentdb = pisi.db.componentdb.ComponentDB()
+        self.filesdb = pisi.db.filesdb.FilesDB()
+        self.installdb = pisi.db.installdb.InstallDB()
+        self.packagedb = pisi.db.packagedb.PackageDB()
+        self.repodb = pisi.db.repodb.RepoDB()
+
+        # Do not ask any question to users
+        self.options = pisi.config.Options()
+        self.options.yes_all = True
+
+    def __get_package_version(self, package):
+        """ Returns version string of given package """
+        # Internal FIXME: PiSi may provide this
+        if package.build is not None:
+            version = "%s-%s-%s" % (package.version, package.release, package.build)
+        else:
+            version = "%s-%s" % (package.version, package.release)
+        return version
+
+    def __get_package(self, package, filters = None):
+        """ Returns package object suitable for other methods """
+        if self.installdb.has_package(package):
+            status = INFO_INSTALLED
+            pkg = self.installdb.get_package(package)
+        elif self.packagedb.has_package(package):
+            status = INFO_AVAILABLE
+            pkg = self.packagedb.get_package(package)
+        else:
+            self.error(ERROR_PACKAGE_NOT_FOUND, "Package was not found")
+
+        if filters:
+            if "none" not in filters:
+                filterlist = filters.split(';')
+
+                if FILTER_INSTALLED in filterlist and status != INFO_INSTALLED:
+                    return
+                if FILTER_NOT_INSTALLED in filterlist and status == INFO_INSTALLED:
+                    return
+                if FILTER_GUI in filterlist and "app:gui" not in pkg.isA:
+                    return
+                if FILTER_NOT_GUI in filterlist and "app:gui" in pkg.isA:
+                    return
+
+        version = self.__get_package_version(pkg)
+
+        id = self.get_package_id(pkg.name, version, pkg.architecture, "")
+
+        return self.package(id, status, pkg.summary)
+
+    def get_depends(self, filters, package_id, recursive):
+        """ Prints a list of depends for a given package """
+        self.allow_cancel(True)
+        self.percentage(None)
+
+        package = self.get_package_from_id(package_id)[0]
+
+        for pkg in self.packagedb.get_package(package).runtimeDependencies():
+            # Internal FIXME: PiSi API has really inconsistent for return types and arguments!
+            self.__get_package(pkg.package)
+
+    def get_details(self, package_id):
+        """ Prints a detailed description for a given package """
+        self.allow_cancel(True)
+        self.percentage(None)
+
+        package = self.get_package_from_id(package_id)[0]
+
+        if self.packagedb.has_package(package):
+            pkg = self.packagedb.get_package(package)
+
+            if self.groups.has_key(pkg.partOf):
+                group = self.groups[pkg.partOf]
+            else:
+                group = GROUP_UNKNOWN
+
+            self.details("%s-%s" % (pkg.name, self.__get_package_version(pkg)),
+                            pkg.license,
+                            group,
+                            pkg.description,
+                            pkg.packageURI,
+                            pkg.packageSize)
+        else:
+            self.error(ERROR_PACKAGE_NOT_FOUND, "Package was not found")
+
+    def get_files(self, package_id):
+        """ Prints a file list for a given package """
+        self.allow_cancel(True)
+        self.percentage(None)
+
+        package = self.get_package_from_id(package_id)[0]
+
+        if self.installdb.has_package(package):
+            pkg = self.installdb.get_files(package)
+
+            # FIXME: Add "/" as suffix
+            files = map(lambda y: y.path, pkg.list)
+
+            file_list = ";".join(files)
+
+            self.files(package, file_list)
+
+    def get_repo_list(self):
+        """ Prints available repositories """
+        self.allow_cancel(True)
+        self.percentage(None)
+
+        for repo in pisi.api.list_repos():
+            # Internal FIXME: What an ugly way to get repo uri
+            # FIXME: Use repository enabled/disabled state
+            self.repo_detail(repo, self.repodb.get_repo(repo).indexuri.get_uri(), "true")
+
+    def get_requires(self, filters, package_id, recursive):
+        """ Prints a list of requires for a given package """
+        self.allow_cancel(True)
+        self.percentage(None)
+
+        package = self.get_package_from_id(package_id)[0]
+
+        # FIXME: Handle packages which is not installed from repository
+        for pkg in self.packagedb.get_rev_deps(package):
+            self.__get_package(pkg[0])
+
+    def get_updates(self, filter):
+        """ Prints available updates and types """
+        self.allow_cancel(True)
+        self.percentage(None)
+
+        for package in pisi.api.list_upgradable():
+
+            pkg = self.packagedb.get_package(package)
+
+            version = self.__get_package_version(pkg)
+            id = self.get_package_id(pkg.name, version, pkg.architecture, "")
+
+            # Internal FIXME: PiSi must provide this information as a single API call :(
+            updates = [i for i in self.packagedb.get_package(package).history
+                    if pisi.version.Version(i.release) > pisi.version.Version(self.installdb.get_package(package).release)]
+            if pisi.util.any(lambda i:i.type == "security", updates):
+                self.package(id, INFO_SECURITY, pkg.summary)
+            else:
+                self.package(id, INFO_NORMAL, pkg.summary)
+
+    def install_files(self, trusted, files):
+        """ Installs given package into system"""
+        # FIXME: install progress
+        self.allow_cancel(False)
+        self.percentage(None)
+
+        try:
+            self.status(STATUS_INSTALL)
+            pisi.api.install([file])
+        except pisi.Error,e:
+            # FIXME: Error: internal-error : Package re-install declined
+            # Force needed?
+            self.error(ERROR_PACKAGE_ALREADY_INSTALLED, e)
+
+    def install(self, package_id):
+        """ Installs given package into system"""
+        # FIXME: fetch/install progress
+        self.allow_cancel(False)
+        self.percentage(None)
+
+        package = self.get_package_from_id(package_id)[0]
+
+        if self.packagedb.has_package(package):
+            self.status(STATUS_INSTALL)
+            try:
+                pisi.api.install([package])
+            except pisi.Error,e:
+                self.error(ERROR_UNKNOWN, e)
+        else:
+            self.error(ERROR_PACKAGE_NOT_INSTALLED, "Package is already installed")
+
+    def refresh_cache(self):
+        """ Updates repository indexes """
+        self.allow_cancel(False)
+        self.percentage(0)
+        self.status(STATUS_REFRESH_CACHE)
+
+        slice = (100/len(pisi.api.list_repos()))/2
+
+        percentage = 0
+        for repo in pisi.api.list_repos():
+            pisi.api.update_repo(repo)
+            percentage += slice
+            self.percentage(percentage)
+
+        self.percentage(100)
+
+    def remove(self, deps, package_id):
+        """ Removes given package from system"""
+        self.allow_cancel(False)
+        self.percentage(None)
+
+        package = self.get_package_from_id(package_id)[0]
+
+        if self.installdb.has_package(package):
+            self.status(STATUS_REMOVE)
+            try:
+                pisi.api.remove([package])
+            except pisi.Error,e:
+                # system.base packages cannot be removed from system
+                self.error(ERROR_CANNOT_REMOVE_SYSTEM_PACKAGE, e)
+        else:
+            self.error(ERROR_PACKAGE_NOT_INSTALLED, "Package is not installed")
+
+    def repo_set_data(self, repo_id, parameter, value):
+        """ Sets a parameter for the repository specified """
+        self.allow_cancel(False)
+        self.percentage(None)
+
+        if parameter == "add-repo":
+            try:
+                pisi.api.add_repo(repo_id, value, parameter)
+            except pisi.Error, e:
+                self.error(ERROR_UNKNOWN, e)
+
+            try:
+                pisi.api.update_repo(repo_id)
+            except pisi.fetcher.FetchError:
+                pisi.api.remove_repo(repo_id)
+                self.error(ERROR_REPO_NOT_FOUND, "Could not be reached to repository, removing from system")
+        elif parameter == "remove-repo":
+            try:
+                pisi.api.remove_repo(repo_id)
+            except pisi.Error:
+                self.error(ERROR_REPO_NOT_FOUND, "Repository is not exists")
+        else:
+            self.error(ERROR_NOT_SUPPORTED, "Parameter not supported")
+
+    def resolve(self, filters, package):
+        """ Turns a single package name into a package_id suitable for the other methods """
+        self.allow_cancel(True)
+        self.percentage(None)
+
+        self.__get_package(package, filters)
+
+    def search_details(self, filters, key):
+        """ Prints a detailed list of packages contains search term """
+        self.allow_cancel(True)
+        self.percentage(None)
+        self.status(STATUS_INFO)
+
+        # Internal FIXME: Use search_details instead of _package when API gains that ability :)
+        for pkg in pisi.api.search_package([key]):
+            self.__get_package(pkg, filters)
+
+    def search_file(self, filters, key):
+        """ Prints the installed package which contains the specified file """
+        self.allow_cancel(True)
+        self.percentage(None)
+        self.status(STATUS_INFO)
+
+        # Internal FIXME: Why it is needed?
+        key = key.lstrip("/")
+
+        for pkg, files in pisi.api.search_file(key):
+            self.__get_package(pkg)
+
+    def search_group(self, filters, group):
+        """ Prints a list of packages belongs to searched group """
+        self.allow_cancel(True)
+        self.percentage(None)
+        self.status(STATUS_INFO)
+
+        try:
+            for key in self.groups.keys():
+                if self.groups[key] == group:
+                    for pkg in self.componentdb.get_packages(key, walk = True):
+                        self.__get_package(pkg, filters)
+        except:
+            self.error(ERROR_GROUP_NOT_FOUND, "Component %s was not found" % group)
+
+    def search_name(self, filters, package):
+        """ Prints a list of packages contains search term in its name """
+        self.allow_cancel(True)
+        self.percentage(None)
+        self.status(STATUS_INFO)
+
+        for pkg in pisi.api.search_package([package]):
+            self.__get_package(pkg, filters)
+
+    def update(self, package_id):
+        """ Updates given package to its latest version """
+        # FIXME: fetch/install progress
+        self.allow_cancel(False)
+        self.percentage(None)
+
+        package = self.get_package_from_id(package_id)[0]
+
+        if self.installdb.has_package(package):
+            try:
+                pisi.api.upgrade([package])
+            except pisi.Error,e:
+                self.error(ERROR_UNKNOWN, e)
+        else:
+            self.error(ERROR_PACKAGE_NOT_INSTALLED, "Package is already installed")
+
+    def update_system(self):
+        """ Updates all available packages """
+        # FIXME: fetch/install progress
+        self.allow_cancel(False)
+        self.percentage(None)
+
+        if not len(pisi.api.list_upgradable()) > 0:
+            self.error(ERROR_NO_PACKAGES_TO_UPDATE, "System is already up2date")
+
+        try:
+            pisi.api.upgrade(pisi.api.list_upgradable())
+        except pisi.Error,e:
+            self.error(ERROR_UNKNOWN, e)
+
+def main():
+    backend = PackageKitPisiBackend('', lock=True)
+    backend.dispatcher(sys.argv[1:])
+
+if __name__ == "__main__":
+    main()
+
diff --git a/backends/pisi/pk-backend-pisi.c b/backends/pisi/pk-backend-pisi.c
index 154ed35..edf4bcb 100644
--- a/backends/pisi/pk-backend-pisi.c
+++ b/backends/pisi/pk-backend-pisi.c
@@ -123,7 +123,7 @@ backend_get_depends (PkBackend *backend, PkBitfield filters, gchar **package_ids
 	gchar *package_ids_temp;
 	package_ids_temp = pk_package_ids_to_text (package_ids);
 	filters_text = pk_filter_bitfield_to_text (filters);
-	pk_backend_spawn_helper (spawn, "get-depends.py", filters_text, package_ids_temp, pk_backend_bool_to_text (recursive), NULL);
+	pk_backend_spawn_helper (spawn, "pisiBackend.py", "get-depends", filters_text, package_ids_temp, pk_backend_bool_to_text (recursive), NULL);
 	g_free (filters_text);
 	g_free (package_ids_temp);
 }
@@ -136,7 +136,7 @@ backend_get_details (PkBackend *backend, gchar **package_ids)
 {
 	gchar *package_ids_temp;
 	package_ids_temp = pk_package_ids_to_text (package_ids);
-	pk_backend_spawn_helper (spawn, "get-details.py", package_ids_temp, NULL);
+	pk_backend_spawn_helper (spawn, "pisiBackend.py", "get-details", package_ids_temp, NULL);
 	g_free (package_ids_temp);
 }
 
@@ -148,7 +148,7 @@ backend_get_files (PkBackend *backend, gchar **package_ids)
 {
 	gchar *package_ids_temp;
 	package_ids_temp = pk_package_ids_to_text (package_ids);
-	pk_backend_spawn_helper (spawn, "get-files.py", package_ids_temp, NULL);
+	pk_backend_spawn_helper (spawn, "pisiBackend.py", "get-files", package_ids_temp, NULL);
 	g_free (package_ids_temp);
 }
 
@@ -162,7 +162,7 @@ backend_get_requires (PkBackend *backend, PkBitfield filters, gchar **package_id
 	gchar *package_ids_temp;
 	package_ids_temp = pk_package_ids_to_text (package_ids);
 	filters_text = pk_filter_bitfield_to_text (filters);
-	pk_backend_spawn_helper (spawn, "get-requires.py", filters_text, package_ids_temp, pk_backend_bool_to_text (recursive), NULL);
+	pk_backend_spawn_helper (spawn, "pisiBackend.py", "get-requires", filters_text, package_ids_temp, pk_backend_bool_to_text (recursive), NULL);
 	g_free (filters_text);
 	g_free (package_ids_temp);
 }
@@ -175,7 +175,7 @@ backend_get_updates (PkBackend *backend, PkBitfield filters)
 {
 	gchar *filters_text;
 	filters_text = pk_filter_bitfield_to_text (filters);
-	pk_backend_spawn_helper (spawn, "get-updates.py", filters_text, NULL);
+	pk_backend_spawn_helper (spawn, "pisiBackend.py", "get-updates", filters_text, NULL);
 	g_free (filters_text);
 }
 
@@ -196,7 +196,7 @@ backend_install_packages (PkBackend *backend, gchar **package_ids)
 
 	/* send the complete list as stdin */
 	package_ids_temp = pk_package_ids_to_text (package_ids);
-	pk_backend_spawn_helper (spawn, "install-packages.py", package_ids_temp, NULL);
+	pk_backend_spawn_helper (spawn, "pisiBackend.py", "install-packages", package_ids_temp, NULL);
 	g_free (package_ids_temp);
 }
 
@@ -210,7 +210,7 @@ backend_install_files (PkBackend *backend, gboolean trusted, gchar **full_paths)
 
 	/* send the complete list as stdin */
 	package_ids_temp = pk_strv_to_text (full_paths, PK_BACKEND_SPAWN_FILENAME_DELIM);
-	pk_backend_spawn_helper (spawn, "install-files.py", pk_backend_bool_to_text (trusted), package_ids_temp, NULL);
+	pk_backend_spawn_helper (spawn, "pisiBackend.py", "install-files", pk_backend_bool_to_text (trusted), package_ids_temp, NULL);
 	g_free (package_ids_temp);
 }
 
@@ -227,7 +227,7 @@ backend_refresh_cache (PkBackend *backend, gboolean force)
 		return;
 	}
 
-	pk_backend_spawn_helper (spawn, "refresh-cache.py", NULL);
+	pk_backend_spawn_helper (spawn, "pisiBackend.py", "refresh-cache", NULL);
 }
 
 /**
@@ -240,7 +240,7 @@ backend_remove_packages (PkBackend *backend, gchar **package_ids, gboolean allow
 
 	/* send the complete list as stdin */
 	package_ids_temp = pk_package_ids_to_text (package_ids);
-	pk_backend_spawn_helper (spawn, "remove-packages.py", pk_backend_bool_to_text (allow_deps), package_ids_temp, NULL);
+	pk_backend_spawn_helper (spawn, "pisiBackend.py", "remove-packages", pk_backend_bool_to_text (allow_deps), package_ids_temp, NULL);
 	g_free (package_ids_temp);
 }
 
@@ -252,7 +252,7 @@ backend_search_details (PkBackend *backend, PkBitfield filters, const gchar *sea
 {
 	gchar *filters_text;
 	filters_text = pk_filter_bitfield_to_text (filters);
-	pk_backend_spawn_helper (spawn, "search-details.py", filters_text, search, NULL);
+	pk_backend_spawn_helper (spawn, "pisiBackend.py", "search-details", filters_text, search, NULL);
 	g_free (filters_text);
 }
 
@@ -264,7 +264,7 @@ backend_search_file (PkBackend *backend, PkBitfield filters, const gchar *search
 {
 	gchar *filters_text;
 	filters_text = pk_filter_bitfield_to_text (filters);
-	pk_backend_spawn_helper (spawn, "search-file.py", filters_text, search, NULL);
+	pk_backend_spawn_helper (spawn, "pisiBackend.py", "search-file", filters_text, search, NULL);
 	g_free (filters_text);
 }
 
@@ -276,7 +276,7 @@ backend_search_group (PkBackend *backend, PkBitfield filters, const gchar *searc
 {
 	gchar *filters_text;
 	filters_text = pk_filter_bitfield_to_text (filters);
-	pk_backend_spawn_helper (spawn, "search-group.py", filters_text, search, NULL);
+	pk_backend_spawn_helper (spawn, "pisiBackend.py", "search-group", filters_text, search, NULL);
 	g_free (filters_text);
 }
 
@@ -288,7 +288,7 @@ backend_search_name (PkBackend *backend, PkBitfield filters, const gchar *search
 {
 	gchar *filters_text;
 	filters_text = pk_filter_bitfield_to_text (filters);
-	pk_backend_spawn_helper (spawn, "search-name.py", filters_text, search, NULL);
+	pk_backend_spawn_helper (spawn, "pisiBackend.py", "search-name", filters_text, search, NULL);
 	g_free (filters_text);
 }
 
@@ -310,7 +310,7 @@ backend_update_packages (PkBackend *backend, gchar **package_ids)
 
 	/* send the complete list as stdin */
 	package_ids_temp = pk_package_ids_to_text (package_ids);
-	pk_backend_spawn_helper (spawn, "update.py", package_ids_temp, NULL);
+	pk_backend_spawn_helper (spawn, "pisiBackend.py", "update", package_ids_temp, NULL);
 	g_free (package_ids_temp);
 }
 
@@ -320,7 +320,7 @@ backend_update_packages (PkBackend *backend, gchar **package_ids)
 static void
 backend_update_system (PkBackend *backend)
 {
-	pk_backend_spawn_helper (spawn, "update-system.py", NULL);
+	pk_backend_spawn_helper (spawn, "pisiBackend.py", "update-system", NULL);
 }
 
 /**
@@ -333,7 +333,7 @@ backend_resolve (PkBackend *backend, PkBitfield filters, gchar **package_ids)
 	gchar *package_ids_temp;
 	filters_text = pk_filter_bitfield_to_text (filters);
 	package_ids_temp = pk_package_ids_to_text (package_ids);
-	pk_backend_spawn_helper (spawn, "resolve.py", filters_text, package_ids_temp, NULL);
+	pk_backend_spawn_helper (spawn, "pisiBackend.py", "resolve", filters_text, package_ids_temp, NULL);
 	g_free (filters_text);
 	g_free (package_ids_temp);
 }
@@ -346,7 +346,7 @@ backend_get_repo_list (PkBackend *backend, PkBitfield filters)
 {
 	gchar *filters_text;
 	filters_text = pk_filter_bitfield_to_text (filters);
-	pk_backend_spawn_helper (spawn, "get-repo-list.py", filters_text, NULL);
+	pk_backend_spawn_helper (spawn, "pisiBackend.py", "get-repo-list", filters_text, NULL);
 	g_free (filters_text);
 }
 
@@ -356,7 +356,7 @@ backend_get_repo_list (PkBackend *backend, PkBitfield filters)
 static void
 backend_repo_set_data (PkBackend *backend, const gchar *rid, const gchar *parameter, const gchar *value)
 {
-	pk_backend_spawn_helper (spawn, "repo-set-data.py", rid, parameter, value, NULL);
+	pk_backend_spawn_helper (spawn, "pisiBackend.py", "repo-set-data", rid, parameter, value, NULL);
 }
 
 PK_BACKEND_OPTIONS (
commit 119bc1b5d28a8a9fcf8a72a27fd8d1aa906c724f
Merge: d0fe1ae... 66467d3...
Author: Anders F Bjorklund <afb at users.sourceforge.net>
Date:   Fri Sep 26 15:39:16 2008 +0200

    Merge branch 'master' of git+ssh://afb@git.packagekit.org/srv/git/PackageKit

commit d0fe1ae52678bfa9977aea6dfac6ef42bce53bec
Author: Anders F Bjorklund <afb at users.sourceforge.net>
Date:   Fri Sep 26 15:38:41 2008 +0200

    smart: always use the dispatcher

diff --git a/backends/smart/Makefile.am b/backends/smart/Makefile.am
index c790201..edf67db 100644
--- a/backends/smart/Makefile.am
+++ b/backends/smart/Makefile.am
@@ -1,7 +1,14 @@
-SUBDIRS = helpers
+helperdir = $(datadir)/PackageKit/helpers/smart
+dist_helper_DATA = 			\
+	smartBackend.py
+
 plugindir = $(PK_PLUGIN_DIR)
 plugin_LTLIBRARIES = libpk_backend_smart.la
 libpk_backend_smart_la_SOURCES = pk-backend-smart.c
 libpk_backend_smart_la_LIBADD = $(PK_PLUGIN_LIBS)
 libpk_backend_smart_la_LDFLAGS = -module -avoid-version
 libpk_backend_smart_la_CFLAGS = $(PK_PLUGIN_CFLAGS)
+
+install-data-hook:
+	chmod a+rx $(DESTDIR)$(helperdir)/*.py
+
diff --git a/backends/smart/helpers/Makefile.am b/backends/smart/helpers/Makefile.am
deleted file mode 100644
index bceff02..0000000
--- a/backends/smart/helpers/Makefile.am
+++ /dev/null
@@ -1,36 +0,0 @@
-
-helperdir = $(datadir)/PackageKit/helpers/smart
-
-NULL =
-
-dist_helper_DATA = 			\
-	get-depends.py			\
-	get-details.py			\
-	get-files.py			\
-	get-repo-list.py		\
-	get-packages.py			\
-	get-requires.py			\
-	get-updates.py			\
-	install-files.py		\
-	install-packages.py		\
-	refresh-cache.py		\
-	remove-packages.py		\
-	repo-enable.py			\
-	repo-set-data.py		\
-	resolve.py			\
-	search-name.py			\
-	search-file.py			\
-	search-group.py			\
-	search-details.py		\
-	smartBackend.py			\
-	update-packages.py		\
-	update-system.py		\
-	download-packages.py		\
-	what-provides.py		\
-	$(NULL)
-
-install-data-hook:
-	chmod a+rx $(DESTDIR)$(helperdir)/*.py
-
-clean-local :
-	rm -f *~
diff --git a/backends/smart/helpers/smartBackend.py b/backends/smart/helpers/smartBackend.py
deleted file mode 100755
index 25d38a9..0000000
--- a/backends/smart/helpers/smartBackend.py
+++ /dev/null
@@ -1,1306 +0,0 @@
-#!/usr/bin/python
-# Licensed under the GNU General Public License Version 2
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-
-# Copyright (C) 2007 James Bowes <jbowes at dangerouslyinc.com>
-# Copyright (C) 2008 Anders F Bjorklund <afb at users.sourceforge.net>
-
-import smart
-from smart.interface import Interface
-from smart.progress import Progress
-from smart.fetcher import Fetcher
-from packagekit.backend import PackageKitBaseBackend
-from packagekit.package import PackagekitPackage
-from packagekit.enums import *
-import re
-import sys
-
-# Global vars
-pkpackage = PackagekitPackage()
-
-def needs_cache(func):
-    """ Load smart's channels, and save the cache when done. """
-    def cache_wrap(obj, *args, **kwargs):
-        if not obj._cacheloaded:
-            obj.status(STATUS_LOADING_CACHE)
-            obj.allow_cancel(True)
-            obj.ctrl.reloadChannels()
-        result = None
-        try:
-            result = func(obj, *args, **kwargs)
-        except UnicodeDecodeError, e:
-            pass
-        if not obj._cacheloaded:
-            obj.ctrl.saveSysConf()
-            obj._cacheloaded = True
-        return result
-    return cache_wrap
-
-
-class PackageKitSmartInterface(Interface):
-
-    def __init__(self, ctrl, backend):
-        Interface.__init__(self, ctrl)
-        smart.sysconf.set("max-active-downloads", 1, soft=True)
-        self._progress = PackageKitSmartProgress(True, backend)
-
-    def getProgress(self, obj, hassub=False):
-        self._progress.setHasSub(hassub)
-        fetcher = isinstance(obj, Fetcher) and obj or None
-        self._progress.setFetcher(fetcher)
-        return self._progress
-
-class PackageKitSmartProgress(Progress):
-
-    def __init__(self, hassub, backend):
-        Progress.__init__(self)
-        self._hassub = hassub
-        self._backend = backend
-        self._lasturl = None
-        self._oldstatus = None
-        self._oldcancel = None
-
-    def setFetcher(self, fetcher):
-        self._fetcher = fetcher
-        if fetcher:
-            self._oldstatus = self._backend._status
-            self._backend.status(STATUS_DOWNLOAD)
-            self._backend.allow_cancel(True)
-            self._backend.percentage(0)
-
-    def stop(self):
-        Progress.stop(self)
-        if self._oldstatus:
-            self._backend.percentage(100)
-            self._backend.allow_cancel(self._oldcancel)
-            self._backend.status(self._oldstatus)
-            self._oldstatus = None
-
-    def expose(self, topic, percent, subkey, subtopic, subpercent, data, done):
-        self._backend.percentage(percent)
-        if self.getHasSub() and subkey:
-            # unfortunately Progress doesn't provide the current package
-            if self._fetcher and subtopic != self._lasturl:
-                packages = self._backend._packagesdict
-                if not packages:
-                    filename = subtopic
-                    if filename.find('repomd') != -1 \
-                    or filename.find('Release') != -1:
-                        self._backend.status(STATUS_DOWNLOAD_REPOSITORY)
-                    elif filename.find('primary') != -1 \
-                    or filename.find('Packages') != -1:
-                        self._backend.status(STATUS_DOWNLOAD_PACKAGELIST)
-                    elif filename.find('filelists') != -1:
-                        self._backend.status(STATUS_DOWNLOAD_FILELIST)
-                    elif filename.find('other') != -1:
-                        self._backend.status(STATUS_DOWNLOAD_CHANGELOG)
-                    elif filename.find('comps') != -1:
-                        self._backend.status(STATUS_DOWNLOAD_GROUP)
-                    elif filename.find('updateinfo') != -1:
-                        self._backend.status(STATUS_DOWNLOAD_UPDATEINFO)
-                    return
-                for package in packages:
-                    for loader in package.loaders:
-                        info = loader.getInfo(package)
-                        for url in info.getURLs():
-                            # account for progress url from current mirror
-                            item = self._fetcher.getItem(url)
-                            if item:
-                                url = str(item.getURL())
-                                if subtopic == url:
-                                    self._backend._show_package(package)
-                self._lasturl = subtopic
-            elif isinstance(subkey, smart.cache.Package):
-                self._backend._show_package(subkey)
-            elif type(subkey) is tuple and len(subkey):
-                if isinstance(subkey[0], smart.cache.PackageInfo):
-                    self._backend._show_package(subkey[0].getPackage())
-
-class PackageKitSmartBackend(PackageKitBaseBackend):
-
-    _status = STATUS_UNKNOWN
-    _cancel = False
-
-    def __init__(self, args):
-        PackageKitBaseBackend.__init__(self, args)
-        self._cacheloaded = False
-
-        self.ctrl = smart.init()
-        smart.iface.object = PackageKitSmartInterface(self.ctrl, self)
-        smart.initPlugins()
-        smart.initPsyco()
-
-        self._package_list = []
-        self._packagesdict = None
-
-    def status(self, state):
-        PackageKitBaseBackend.status(self, state)
-        self._status = state
-
-    def allow_cancel(self, allow):
-        PackageKitBaseBackend.allow_cancel(self, allow)
-        self._cancel = allow
-
-    def reset(self):
-        self._package_list = []
-
-    @needs_cache
-    def install_packages(self, packageids):
-        packages = []
-        for packageid in packageids:
-            ratio, results, suggestions = self._search_packageid(packageid)
-            if not results:
-                packagestring = self._string_packageid(packageid)
-                self.error(ERROR_PACKAGE_NOT_FOUND,
-                           'Package %s was not found' % packagestring)
-            packages.extend(self._process_search_results(results))
-
-        available = []
-        for package in packages:
-            if package.installed:
-                self.error(ERROR_PACKAGE_ALREADY_INSTALLED,
-                           'Package %s is already installed' % package)
-            else:
-                available.append(package)
-        if len(available) < 1:
-            return
-
-        trans = smart.transaction.Transaction(self.ctrl.getCache(),
-                smart.transaction.PolicyInstall)
-        for package in available:
-            trans.enqueue(package, smart.transaction.INSTALL)
-
-        self.allow_cancel(False)
-        self.status(STATUS_DEP_RESOLVE)
-        trans.run()
-        self.status(STATUS_INSTALL)
-        self._packagesdict = trans.getChangeSet()
-        self.ctrl.commitTransaction(trans, confirm=False)
-
-    @needs_cache
-    def install_files(self, trusted, paths):
-        for path in paths:
-            self.ctrl.addFileChannel(path)
-        self.ctrl.reloadChannels()
-        trans = smart.transaction.Transaction(self.ctrl.getCache(),
-                smart.transaction.PolicyInstall)
-
-        for channel in self.ctrl.getFileChannels():
-            for loader in channel.getLoaders():
-                for package in loader.getPackages():
-                    if package.installed:
-                        self.error(ERROR_PACKAGE_ALREADY_INSTALLED,
-                                'Package %s is already installed' % package)
-                    trans.enqueue(package, smart.transaction.INSTALL)
-
-        self.allow_cancel(False)
-        self.status(STATUS_DEP_RESOLVE)
-        trans.run()
-        self.status(STATUS_INSTALL)
-        self._packagesdict = trans.getChangeSet()
-        self.ctrl.commitTransaction(trans, confirm=False)
-
-    @needs_cache
-    def remove_packages(self, allow_deps, packageids):
-        packages = []
-        for packageid in packageids:
-            ratio, results, suggestions = self._search_packageid(packageid)
-            if not results:
-                packagestring = self._string_packageid(packageid)
-                self.error(ERROR_PACKAGE_NOT_FOUND,
-                           'Package %s was not found' % packagestring)
-            packages.extend(self._process_search_results(results))
-
-        installed = []
-        for package in packages:
-            if not package.installed:
-                self.error(ERROR_PACKAGE_NOT_INSTALLED,
-                           'Package %s is not installed' % package)
-            elif package.essential:
-                self.error(ERROR_CANNOT_REMOVE_SYSTEM_PACKAGE,
-                           'Package %s cannot be removed' % package)
-            else:
-                installed.append(package)
-        if len(installed) < 1:
-            return
-
-        trans = smart.transaction.Transaction(self.ctrl.getCache(),
-                smart.transaction.PolicyRemove)
-        for package in installed:
-            trans.enqueue(package, smart.transaction.REMOVE)
-
-        self.allow_cancel(False)
-        self.status(STATUS_DEP_RESOLVE)
-        trans.run()
-        self.status(STATUS_REMOVE)
-        self._packagesdict = trans.getChangeSet()
-        self.ctrl.commitTransaction(trans, confirm=False)
-
-    @needs_cache
-    def update_packages(self, packageids):
-        packages = []
-        for packageid in packageids:
-            ratio, results, suggestions = self._search_packageid(packageid)
-            if not results:
-                packagestring = self._string_packageid(packageid)
-                self.error(ERROR_PACKAGE_NOT_FOUND,
-                           'Package %s was not found' % packagestring)
-            packages.extend(self._process_search_results(results))
-
-        installed = [package for package in packages if package.installed]
-        if len(installed) < 1:
-            return
-        trans = smart.transaction.Transaction(self.ctrl.getCache(),
-                smart.transaction.PolicyUpgrade)
-        for package in installed:
-            trans.enqueue(package, smart.transaction.UPGRADE)
-
-        self.allow_cancel(False)
-        self.status(STATUS_DEP_RESOLVE)
-        trans.run()
-        self.status(STATUS_UPDATE)
-        self._packagesdict = trans.getChangeSet()
-        self.ctrl.commitTransaction(trans, confirm=False)
-
-    @needs_cache
-    def download_packages(self, directory, packageids):
-        packages = []
-        for packageid in packageids:
-            ratio, results, suggestions = self._search_packageid(packageid)
-            if not results:
-                packagestring = self._string_packageid(packageid)
-                self.error(ERROR_PACKAGE_NOT_FOUND,
-                           'Package %s was not found' % packagestring)
-            packages.extend(self._process_search_results(results))
-        if len(packages) < 1:
-            return
-
-        self.status(STATUS_DOWNLOAD)
-        self.allow_cancel(True)
-        self._packagesdict = packages
-        self.ctrl.downloadPackages(packages, targetdir=directory)
-
-        pkgpath = self.ctrl.fetchPackages(packages, targetdir=directory)
-        for package, files in pkgpath.iteritems():
-            self.files(package, ";".join(files))
-
-    @needs_cache
-    def update_system(self):
-        self.status(STATUS_INFO)
-        cache = self.ctrl.getCache()
-
-        trans = smart.transaction.Transaction(cache,
-                smart.transaction.PolicyUpgrade)
-
-        for package in cache.getPackages():
-            if package.installed:
-                trans.enqueue(package, smart.transaction.UPGRADE)
-
-        self.allow_cancel(False)
-        self.status(STATUS_DEP_RESOLVE)
-        trans.run()
-        if not trans:
-            self.error(ERROR_NO_PACKAGES_TO_UPDATE,
-                       "No interesting upgrades available.")
-            return
-        self.status(STATUS_UPDATE)
-        self._packagesdict = trans.getChangeSet()
-        self.ctrl.commitTransaction(trans, confirm=False)
-
-    @needs_cache
-    def get_updates(self, filters):
-        self.status(STATUS_INFO)
-        cache = self.ctrl.getCache()
-
-        trans = smart.transaction.Transaction(cache,
-                smart.transaction.PolicyUpgrade)
-
-        for package in cache.getPackages():
-            if package.installed:
-                trans.enqueue(package, smart.transaction.UPGRADE)
-
-        self.allow_cancel(False)
-        self.status(STATUS_DEP_RESOLVE)
-        trans.run()
-        self.status(STATUS_INFO)
-        for (package, op) in trans.getChangeSet().items():
-            if op == smart.transaction.INSTALL:
-                if self._package_passes_filters(package, filters):
-                    status = self._get_status(package)
-                    self._add_package(package, status)
-        self._post_process_package_list(filters)
-        self._show_package_list()
-
-    @needs_cache
-    def get_update_detail(self, packageids):
-        self.status(STATUS_INFO)
-        self.allow_cancel(True)
-        for packageid in packageids:
-            ratio, results, suggestions = self._search_packageid(packageid)
-
-            packages = self._process_search_results(results)
-
-            if len(packages) == 0:
-                packagestring = self._string_packageid(packageid)
-                self.error(ERROR_PACKAGE_NOT_FOUND,
-                           'Package %s was not found' % packagestring)
-                return
-
-            channels = self._search_channels(packageid)
-
-            package = packages[0]
-            changelog = ''
-            errata = None
-            for loader in package.loaders:
-                if channels and loader.getChannel() not in channels:
-                    continue
-                info = loader.getInfo(package)
-                if hasattr(info, 'getChangeLog'):
-                    changelog = info.getChangeLog()
-                    changelog = ';'.join(changelog)
-                if hasattr(loader, 'getErrata'):
-                    errata = loader.getErrata(package)
-
-            upgrades = ''
-            if package.upgrades:
-                upgrades = []
-                for upg in package.upgrades:
-                    for prv in upg.providedby:
-                        for prvpkg in prv.packages:
-                            if prvpkg.installed:
-                                upgrades.append(
-                                    self._package_id(prvpkg, loader))
-                upgrades = '^'.join(upgrades)
-            obsoletes = ''
-
-            if not errata:
-                state = self._get_status(package) or ''
-                self.update_detail(self._package_id(package, loader),
-                    upgrades, obsoletes, '', '', '',
-                    'none', '', changelog, state, '', '')
-                continue
-
-            state = errata.getType()
-            issued = errata.getDate()
-            updated = ''
-
-            description = errata.getDescription()
-            description = description.replace(";", ",")
-            description = description.replace("\n", ";")
-
-            urls = errata.getReferenceURLs()
-            vendor_urls = []
-            bugzilla_urls = []
-            cve_urls = []
-            for url in urls:
-                if url.find("cve") != -1:
-                    cve_urls.append(url)
-                elif url.find("bugzilla") != -1:
-                    bugzilla_urls.append(url)
-                else:
-                    vendor_urls.append(url)
-            vendor_url = ';'.join(vendor_urls)
-            bugzilla_url = ';'.join(vendor_urls)
-            cve_url = ';'.join(vendor_urls)
-
-            if errata.isRebootSuggested():
-                reboot = 'system'
-            else:
-                reboot = 'none'
-
-            self.update_detail(self._package_id(package, loader),
-                upgrades, obsoletes, vendor_url, bugzilla_url, cve_url,
-                reboot, description, changelog, state, issued, updated)
-
-    @needs_cache
-    def resolve(self, filters, packages):
-        self.status(STATUS_QUERY)
-        self.allow_cancel(True)
-        for packagename in packages:
-            ratio, results, suggestions = self.ctrl.search(packagename)
-            for result in results:
-                if self._package_passes_filters(result, filters):
-                    self._add_package(result)
-        self._post_process_package_list(filters)
-        self._show_package_list()
-
-    @needs_cache
-    def search_name(self, filters, packagename):
-        globbed = "*%s*" % packagename
-        self.status(STATUS_QUERY)
-        self.allow_cancel(True)
-        ratio, results, suggestions = self.ctrl.search(globbed)
-
-        packages = self._process_search_results(results)
-
-        for package in packages:
-            if self._package_passes_filters(package, filters):
-                self._add_package(package)
-        self._post_process_package_list(filters)
-        self._show_package_list()
-
-    @needs_cache
-    def search_file(self, filters, searchstring):
-        self.status(STATUS_QUERY)
-        self.allow_cancel(True)
-        packages = self.ctrl.getCache().getPackages()
-        for package in packages:
-            if self._package_passes_filters(package, filters):
-                paths = []
-                for loader in package.loaders:
-                    channel = loader.getChannel()
-                    if package.installed and not \
-                       channel.getType().endswith('-sys'):
-                        continue
-                    info = loader.getInfo(package)
-                    paths = info.getPathList()
-                    if len(paths) > 0:
-                        break
-                if searchstring in paths:
-                    self._add_package(package)
-        self._post_process_package_list(filters)
-        self._show_package_list()
-
-    @needs_cache
-    def search_group(self, filters, searchstring):
-        self.status(STATUS_QUERY)
-        self.allow_cancel(True)
-        filter_desktops = searchstring.find("desktop") != -1
-        packages = self.ctrl.getCache().getPackages()
-        for package in packages:
-            if self._package_passes_filters(package, filters):
-                info = package.loaders.keys()[0].getInfo(package)
-                group = self._get_group(info, filter_desktops)
-                if searchstring in group:
-                    self._add_package(package)
-        self._post_process_package_list(filters)
-        self._show_package_list()
-
-    @needs_cache
-    def search_details(self, filters, searchstring):
-        self.status(STATUS_QUERY)
-        self.allow_cancel(True)
-        packages = self.ctrl.getCache().getPackages()
-        for package in packages:
-            if self._package_passes_filters(package, filters):
-                info = package.loaders.keys()[0].getInfo(package)
-                if searchstring in info.getDescription():
-                    self._add_package(package)
-
-    @needs_cache
-    def get_packages(self, filters):
-        self.status(STATUS_QUERY)
-        self.allow_cancel(True)
-        packages = self.ctrl.getCache().getPackages()
-        for package in packages:
-            if self._package_passes_filters(package, filters):
-                self._add_package(package)
-        self._post_process_package_list(filters)
-        self._show_package_list()
-
-    @needs_cache
-    def what_provides(self, filters, provides_type, search):
-        self.status(STATUS_QUERY)
-        self.allow_cancel(True)
-        if provides_type != PROVIDES_ANY:
-            self.error(ERROR_NOT_SUPPORTED,
-                       "provide %s not supported" % provides_type)
-            return
-        providers = self.ctrl.getCache().getProvides(search)
-        for provider in providers:
-            for package in provider.packages:
-                if self._package_passes_filters(package, filters):
-                    self._add_package(package)
-        self._post_process_package_list(filters)
-        self._show_package_list()
-
-    def refresh_cache(self):
-        self.status(STATUS_REFRESH_CACHE)
-        self.allow_cancel(True)
-        self.ctrl.rebuildSysConfChannels()
-        self.ctrl.reloadChannels(None, caching=smart.const.NEVER)
-        self.ctrl.saveSysConf()
-
-    GROUPS = {
-    # RPM (redhat)
-    'Amusements/Games'                        : GROUP_GAMES,
-    'Amusements/Graphics'                     : GROUP_GRAPHICS,
-    'Applications/Archiving'                  : GROUP_OTHER, ### FIXME
-    'Applications/Communications'             : GROUP_COMMUNICATION,
-    'Applications/Databases'                  : GROUP_OTHER, ### FIXME
-    'Applications/Editors'                    : GROUP_PUBLISHING,
-    'Applications/Emulators'                  : GROUP_VIRTUALIZATION,
-    'Applications/Engineering'                : GROUP_OTHER, ### FIXME
-    'Applications/File'                       : GROUP_OTHER, ### FIXME
-    'Applications/Internet'                   : GROUP_INTERNET,
-    'Applications/Multimedia'                 : GROUP_MULTIMEDIA,
-    'Applications/Productivity'               : GROUP_OFFICE,
-    'Applications/Publishing'                 : GROUP_PUBLISHING,
-    'Applications/System'                     : GROUP_SYSTEM,
-    'Applications/Text'                       : GROUP_PUBLISHING,
-    'Development/Debuggers'                   : GROUP_PROGRAMMING,
-    'Development/Languages'                   : GROUP_PROGRAMMING,
-    'Development/Libraries'                   : GROUP_PROGRAMMING,
-    'Development/System'                      : GROUP_PROGRAMMING,
-    'Development/Tools'                       : GROUP_PROGRAMMING,
-    'Documentation'                           : GROUP_DOCUMENTATION,
-    'System Environment/Base'                 : GROUP_SYSTEM,
-    'System Environment/Daemons'              : GROUP_SYSTEM,
-    'System Environment/Kernel'               : GROUP_SYSTEM,
-    'System Environment/Libraries'            : GROUP_SYSTEM,
-    'System Environment/Shells'               : GROUP_SYSTEM,
-    'User Interface/Desktops'                 : GROUP_DESKTOP_OTHER,
-    'User Interface/X'                        : GROUP_DESKTOP_OTHER,
-    'User Interface/X Hardware Support'       : GROUP_DESKTOP_OTHER,
-    # Yum
-    'Virtual'                                 : GROUP_COLLECTIONS,
-    'Virtual/Applications'                    : GROUP_COLLECTIONS,
-    'Virtual/Base System'                     : GROUP_COLLECTIONS,
-    'Virtual/Desktop Environments'            : GROUP_COLLECTIONS,
-    'Virtual/Development'                     : GROUP_COLLECTIONS,
-    'Virtual/Languages'                       : GROUP_COLLECTIONS,
-    'Virtual/Servers'                         : GROUP_COLLECTIONS,
-    # RPM (novell)
-    'Amusements/Teaching'                     : GROUP_EDUCATION,
-    'Amusements/Toys'                         : GROUP_GAMES,
-    'Hardware'                                : GROUP_SYSTEM,
-    'Productivity/Archiving'                  : GROUP_OTHER, ### FIXME
-    'Productivity/Clustering'                 : GROUP_OTHER, ### FIXME
-    'Productivity/Databases'                  : GROUP_OTHER, ### FIXME
-    'Productivity/Editors'                    : GROUP_PUBLISHING,
-    'Productivity/File utilities'             : GROUP_OTHER, ### FIXME
-    'Productivity/Graphics'                   : GROUP_GRAPHICS,
-    'Productivity/Hamradio'                   : GROUP_COMMUNICATION,
-    'Productivity/Multimedia'                 : GROUP_MULTIMEDIA,
-    'Productivity/Networking'                 : GROUP_NETWORK,
-    'Productivity/Networking/Email'           : GROUP_INTERNET,
-    'Productivity/Networking/News'            : GROUP_INTERNET,
-    'Productivity/Networking/Web'             : GROUP_INTERNET,
-    'Productivity/Office'                     : GROUP_OFFICE,
-    'Productivity/Other'                      : GROUP_OTHER,
-    'Productivity/Publishing'                 : GROUP_PUBLISHING,
-    'Productivity/Scientific'                 : GROUP_SCIENCE,
-    'Productivity/Security'                   : GROUP_SECURITY,
-    'Productivity/Telephony'                  : GROUP_COMMUNICATION,
-    'Productivity/Text'                       : GROUP_PUBLISHING,
-    'System/Base'                             : GROUP_SYSTEM,
-    'System/Daemons'                          : GROUP_SYSTEM,
-    'System/Emulators'                        : GROUP_VIRTUALIZATION,
-    'System/Kernel'                           : GROUP_SYSTEM,
-    'System/Libraries'                        : GROUP_SYSTEM,
-    'System/Shells'                           : GROUP_SYSTEM,
-    'System/GUI/GNOME'                        : GROUP_DESKTOP_GNOME,
-    'System/GUI/KDE'                          : GROUP_DESKTOP_KDE,
-    'System/GUI/Other'                        : GROUP_DESKTOP_OTHER,
-    'System/GUI/XFCE'                         : GROUP_DESKTOP_XFCE,
-    'System/I18n'                             : GROUP_LOCALIZATION,
-    'System/Localization'                     : GROUP_LOCALIZATION,
-    'System/X11'                              : GROUP_DESKTOP_OTHER,
-    'System/X11/Fonts'                        : GROUP_FONTS,
-    # YaST2
-#   'Virtual'                                 : GROUP_COLLECTIONS,
-    'Virtual/Base Technologies'               : GROUP_COLLECTIONS,
-    'Virtual/Desktop Functions'               : GROUP_COLLECTIONS,
-#   'Virtual/Development'                     : GROUP_COLLECTIONS,
-    'Virtual/GNOME Desktop'                   : GROUP_COLLECTIONS,
-    'Virtual/Graphical Environments'          : GROUP_COLLECTIONS,
-    'Virtual/KDE Desktop'                     : GROUP_COLLECTIONS,
-    'Virtual/Server Functions'                : GROUP_COLLECTIONS,
-    # RPM (mandriva)
-    'Accessibility'                           : GROUP_ACCESSIBILITY,
-    'Archiving'                               : GROUP_OTHER, ### FIXME
-    'Books'                                   : GROUP_DOCUMENTATION,
-    'Communications'                          : GROUP_COMMUNICATION,
-    'Databases'                               : GROUP_OTHER, ### FIXME
-    'Development'                             : GROUP_PROGRAMMING,
-    'Editors'                                 : GROUP_PUBLISHING,
-    'Education'                               : GROUP_EDUCATION,
-    'Emulators'                               : GROUP_VIRTUALIZATION,
-    'File tools'                              : GROUP_OTHER, ### FIXME
-    'Games'                                   : GROUP_GAMES,
-    'Graphical desktop'                       : GROUP_DESKTOP_OTHER,
-    'Graphical desktop/GNOME'                 : GROUP_DESKTOP_GNOME,
-    'Graphical desktop/KDE'                   : GROUP_DESKTOP_KDE,
-    'Graphical desktop/Xfce'                  : GROUP_DESKTOP_XFCE,
-    'Graphics'                                : GROUP_GRAPHICS,
-    'Monitoring'                              : GROUP_NETWORK,
-    'Networking'                              : GROUP_INTERNET,
-    'Office'                                  : GROUP_OFFICE,
-    'Publishing'                              : GROUP_PUBLISHING,
-    'Sciences'                                : GROUP_SCIENCE,
-    'Shells'                                  : GROUP_SYSTEM,
-    'Sound'                                   : GROUP_MULTIMEDIA,
-    'System'                                  : GROUP_SYSTEM,
-    'System/Fonts'                            : GROUP_FONTS,
-    'System/Internationalization'             : GROUP_LOCALIZATION,
-    'Terminals'                               : GROUP_SYSTEM,
-    'Text tools'                              : GROUP_ACCESSORIES,
-    'Toys'                                    : GROUP_GAMES,
-    'Video'                                   : GROUP_MULTIMEDIA,
-    # DEB
-    "admin"                                   : GROUP_ADMIN_TOOLS,
-    "base"                                    : GROUP_SYSTEM,
-    "comm"                                    : GROUP_COMMUNICATION,
-    "devel"                                   : GROUP_PROGRAMMING,
-    "doc"                                     : GROUP_DOCUMENTATION,
-    "editors"                                 : GROUP_PUBLISHING,
-    "electronics"                             : GROUP_ELECTRONICS,
-    "embedded"                                : GROUP_SYSTEM,
-    "games"                                   : GROUP_GAMES,
-    "gnome"                                   : GROUP_DESKTOP_GNOME,
-    "graphics"                                : GROUP_GRAPHICS,
-    "hamradio"                                : GROUP_COMMUNICATION,
-    "interpreters"                            : GROUP_PROGRAMMING,
-    "kde"                                     : GROUP_DESKTOP_KDE,
-    "libdevel"                                : GROUP_PROGRAMMING,
-    "libs"                                    : GROUP_SYSTEM,
-    "mail"                                    : GROUP_INTERNET,
-    "math"                                    : GROUP_SCIENCE,
-    "misc"                                    : GROUP_OTHER,
-    "net"                                     : GROUP_NETWORK,
-    "news"                                    : GROUP_INTERNET,
-    "oldlibs"                                 : GROUP_LEGACY,
-    "otherosfs"                               : GROUP_SYSTEM,
-    "perl"                                    : GROUP_PROGRAMMING,
-    "python"                                  : GROUP_PROGRAMMING,
-    "science"                                 : GROUP_SCIENCE,
-    "shells"                                  : GROUP_SYSTEM,
-    "sound"                                   : GROUP_MULTIMEDIA,
-    "tex"                                     : GROUP_PUBLISHING,
-    "text"                                    : GROUP_PUBLISHING,
-    "utils"                                   : GROUP_ACCESSORIES,
-    "web"                                     : GROUP_INTERNET,
-    "x11"                                     : GROUP_DESKTOP_OTHER,
-    "unknown"                                 : GROUP_UNKNOWN,
-    "alien"                                   : GROUP_UNKNOWN,
-    "translations"                            : GROUP_LOCALIZATION,
-    # APT
-    "metapackages"                            : GROUP_COLLECTIONS,
-    # Slack
-    "Slackware"                               : GROUP_UNKNOWN
-    }
-    
-    @needs_cache
-    def get_details(self, packageids):
-        self.status(STATUS_INFO)
-        self.allow_cancel(True)
-        for packageid in packageids:
-            ratio, results, suggestions = self._search_packageid(packageid)
-
-            packages = self._process_search_results(results)
-
-            if len(packages) == 0:
-                packagestring = self._string_packageid(packageid)
-                self.error(ERROR_PACKAGE_NOT_FOUND,
-                           'Package %s was not found' % packagestring)
-                return
-
-            channels = self._search_channels(packageid)
-
-            package = packages[0]
-            infos = []
-            for loader in package.loaders:
-                if channels and loader.getChannel() not in channels and not \
-                (package.installed and self._package_is_collection(package)):
-                    continue
-                info = loader.getInfo(package)
-                infos.append(info)
-
-            if len(infos) == 0:
-                self.error(ERROR_PACKAGE_NOT_FOUND,
-                           'Package %s in other repo' % package)
-                return
-
-            infos.sort()
-            info = infos[0]
-
-            description = info.getDescription()
-            description = description.replace("\n\n", ";")
-            description = description.replace("\n", " ")
-            urls = info.getReferenceURLs()
-            if urls:
-                url = urls[0]
-            else:
-                url = "unknown"
-
-            pkgsize = None
-            seen = {}
-            for loader in package.loaders:
-                info = loader.getInfo(package)
-                for pkgurl in info.getURLs():
-                    size = info.getSize(pkgurl)
-                    if size:
-                        pkgsize = size
-                        break
-                if pkgsize:
-                    break
-            if not pkgsize:
-                pkgsize = 0
-
-            if hasattr(info, 'getLicense'):
-                license = info.getLicense()
-            else:
-                license = ''
-
-            group = self._get_group(info)
-
-            self.details(self._package_id(package),
-                         license, group, description, url, pkgsize)
-
-    @needs_cache
-    def get_files(self, packageids):
-        self.status(STATUS_INFO)
-        self.allow_cancel(True)
-        for packageid in packageids:
-            ratio, results, suggestions = self._search_packageid(packageid)
-
-            packages = self._process_search_results(results)
-
-            if len(packages) == 0:
-                packagestring = self._string_packageid(packageid)
-                self.error(ERROR_PACKAGE_NOT_FOUND,
-                           'Package %s was not found' % packagestring)
-                return
-
-            channels = self._search_channels(packageid)
-
-            package = packages[0]
-            # FIXME: Only installed packages have path lists.
-            paths = None
-            for loader in package.loaders:
-                if channels and loader.getChannel() not in channels:
-                    continue
-                info = loader.getInfo(package)
-                paths = info.getPathList()
-                if len(paths) > 0:
-                    break
-
-            if paths == None:
-                self.error(ERROR_PACKAGE_NOT_FOUND,
-                           'Package %s in other repo' % package)
-                return
-
-            self.files(packageid, ";".join(paths))
-
-    def _text_to_boolean(self, text):
-        if text == 'true' or text == 'TRUE':
-            return True
-        elif text == 'yes' or text == 'YES':
-            return True
-        return False
-
-    def _best_package_from_list(self, package_list):
-        for installed in (True, False):
-            best = None
-            for package in package_list:
-                if not best or package > best:
-                    best = package
-            if best:
-                return best
-        return None
-
-    @needs_cache
-    def get_depends(self, filters, packageids, recursive_text):
-        recursive = self._text_to_boolean(recursive_text)
-        self.status(STATUS_INFO)
-        self.allow_cancel(True)
-        for packageid in packageids:
-            ratio, results, suggestions = self._search_packageid(packageid)
-
-            packages = self._process_search_results(results)
-
-            if len(packages) != 1:
-                return
-
-            package = packages[0]
-            original = package
-
-            extras = {}
-            for required in package.requires:
-                providers = {}
-                for provider in required.providedby:
-                    for package in provider.packages:
-                        if not providers.has_key(package):
-                            providers[package] = True
-                package = self._best_package_from_list(providers.keys())
-                if package and not extras.has_key(package):
-                    extras[package] = True
-
-            if original in extras:
-                del extras[original]
-            for package in extras.keys():
-                if self._package_passes_filters(package, filters):
-                    self._add_package(package)
-            self._post_process_package_list(filters)
-            self._show_package_list()
-
-    @needs_cache
-    def get_requires(self, filters, packageids, recursive_text):
-        recursive = self._text_to_boolean(recursive_text)
-        self.status(STATUS_INFO)
-        self.allow_cancel(True)
-        for packageid in packageids:
-            ratio, results, suggestions = self._search_packageid(packageid)
-
-            packages = self._process_search_results(results)
-
-            if len(packages) != 1:
-                return
-
-            package = packages[0]
-            original = package
-
-            extras = {}
-            for provided in package.provides:
-                requirers = {}
-                for requirer in provided.requiredby:
-                    for package in requirer.packages:
-                        if not requirers.has_key(package):
-                            requirers[package] = True
-                package = self._best_package_from_list(requirers.keys())
-                if package and not extras.has_key(package):
-                    extras[package] = True
-
-            if original in extras:
-                del extras[original]
-            for package in extras.keys():
-                if self._package_passes_filters(package, filters):
-                    self._add_package(package)
-            self._post_process_package_list(filters)
-            self._show_package_list()
-
-    def get_repo_list(self, filters):
-        self.status(STATUS_INFO)
-        self.allow_cancel(True)
-        channels = smart.sysconf.get("channels", ())
-        for alias in channels:
-            channel = smart.sysconf.get(("channels", alias))
-            name = channel.get("name", alias)
-            parsed = smart.channel.parseChannelData(channel)
-            enabled = 'true'
-            if channel.has_key('disabled') and channel['disabled'] == 'yes':
-                enabled = 'false'
-            channel['alias'] = alias
-            if self._channel_passes_filters(channel, filters):
-                self.repo_detail(alias, name, enabled)
-
-    def repo_enable(self, repoid, enable):
-        self.status(STATUS_INFO)
-        self.allow_cancel(True)
-        if smart.sysconf.has(("channels", repoid)):
-            if enable == "true":
-                smart.sysconf.remove(("channels", repoid, "disabled"))
-            else:
-                smart.sysconf.set(("channels", repoid, "disabled"), "yes")
-            self.ctrl.saveSysConf()
-        else:
-            self.error(ERROR_REPO_NOT_FOUND, "repo %s was not found" % repoid)
-
-    def repo_set_data(self, repoid, param, value):
-        self.status(STATUS_INFO)
-        self.allow_cancel(True)
-        if smart.sysconf.has(("channels", repoid)):
-            smart.sysconf.set(("channels", repoid, param), value)
-            self.ctrl.saveSysConf()
-        else:
-            self.error(ERROR_REPO_NOT_FOUND, "repo %s was not found" % repoid)
-
-    systemchannel = None # unfortunately package strings depend on system
-
-    def _machine(self):
-        import os
-        machine = os.uname()[-1]
-        if machine == "Power Macintosh": #<sigh>
-            machine = "ppc"
-        return machine
-
-    def _samearch(self, arch1, arch2):
-        if arch1 == arch2:
-            return True
-        if arch1 == 'noarch' or arch2 == 'noarch':
-            return True
-        x86 = re.compile(r'i[3456]86')
-        if x86.search(arch1) and x86.search(arch2):
-            return True
-        return False
-
-    def _splitpackage(self, package):
-        from smart.backends.rpm.base import RPMPackage
-        from smart.backends.deb.base import DebPackage
-        from smart.backends.slack.base import SlackPackage
-        if isinstance(package, RPMPackage):
-            name = package.name
-            version, arch = package.version.split('@')
-        elif isinstance(package, DebPackage):
-            name = package.name
-            version, arch = package.version, smart.backends.deb.base.DEBARCH
-        elif isinstance(package, SlackPackage):
-            name = package.name
-            ver, arch, rel = package.version.rsplit('-')
-            version = "%s-%s" % (ver, rel)
-        else:
-            version, arch = package.version, self._machine()
-        return name, version, arch
-
-    def _joinpackage(self, name, version, arch):
-        if not self.systemchannel:
-            channels = smart.sysconf.get("channels", ())
-            # FIXME: should look by type, not by alias
-            if "rpm-sys" in channels:
-                self.systemchannel = "rpm-sys"
-            elif "deb-sys" in channels:
-                self.systemchannel = "deb-sys"
-            elif "slack-sys" in channels:
-                self.systemchannel = "slack-sys"
-        if self.systemchannel == "rpm-sys":
-            pkg = "%s-%s@%s" % (name, version, arch)
-        elif self.systemchannel == "deb-sys":
-            pkg = "%s_%s" % (name, version)
-        elif self.systemchannel == "slack-sys":
-            ver, rel = version.rsplit("-")
-            pkg = "%s-%s-%s-%s" % (name, ver, arch, rel)
-        else:
-            pkg = "%s-%s" % (name, version)
-        return pkg
-
-    def _string_packageid(self, packageid):
-        idparts = packageid.split(';')
-        # note: currently you can only search in channels native to system
-        packagestring = self._joinpackage(idparts[0], idparts[1], idparts[2])
-        if packagestring.startswith('@'):
-            packagestring = packagestring.replace('@', '^', 1)
-        return packagestring
-
-    def _search_packageid(self, packageid):
-        packagestring = self._string_packageid(packageid)
-        ratio, results, suggestions = self.ctrl.search(packagestring)
-
-        return (ratio, results, suggestions)
-
-    def _channel_is_local(self, channel):
-        return isinstance(channel, smart.channel.FileChannel)
-
-    def _search_channels(self, packageid):
-        idparts = packageid.split(';')
-        repoid = idparts[3]
-        if repoid == 'local':
-            channels = self.ctrl.getFileChannels()
-        elif repoid:
-            if repoid == 'installed':
-                repoid = self.systemchannel
-            channels = self.ctrl.getChannels()
-            channels = [x for x in channels if x.getAlias() == repoid]
-        else:
-            channels = None
-        return channels
-
-    def _package_is_collection(self, package):
-        return package.name.startswith('^')
-
-    def _add_package(self, package, status=None):
-        if not status:
-            if self._package_is_collection(package):
-                if package.installed:
-                    status = INFO_COLLECTION_INSTALLED
-                else:
-                    status = INFO_COLLECTION_AVAILABLE
-            else:
-                if package.installed:
-                    status = INFO_INSTALLED
-                else:
-                    status = INFO_AVAILABLE
-        self._package_list.append((package, status))
-
-    def _show_package_list(self):
-        for package, status in self._package_list:
-            self._show_package(package, status)
-
-    def _package_id(self, package, loader=None):
-        name, version, arch = self._splitpackage(package)
-        collection = False
-        if name.startswith('^'):
-            collection = True
-            name = name.replace('^', '@', 1)
-        if not loader:
-            for loader in package.loaders:
-                break
-        channel = loader.getChannel()
-        if package.installed:
-            data = 'installed'
-        elif self._channel_is_local(channel):
-            data = 'local'
-        else:
-            data = channel.getAlias()
-        return pkpackage.get_package_id(name, version, arch, data)
-
-    def _show_package(self, package, status=None):
-        if not status:
-            if self._status == STATUS_DOWNLOAD:
-                status = INFO_DOWNLOADING
-            elif self._status == STATUS_INSTALL:
-                status = INFO_INSTALLING
-            elif self._status == STATUS_UPDATE:
-                status = INFO_UPDATING
-            elif self._status == STATUS_REMOVE:
-                status = INFO_REMOVING
-            else:
-                status = INFO_UNKNOWN
-        for loader in package.loaders:
-            channel = loader.getChannel()
-            if package.installed and not channel.getType().endswith('-sys') \
-            and not self._package_is_collection(package):
-                continue
-            info = loader.getInfo(package)
-            summary = info.getSummary()
-            self.package(self._package_id(package, loader), status, summary)
-
-    def _package_in_requires(self, packagename, groupname):
-        groups = self.ctrl.getCache().getPackages(groupname)
-        if groups:
-            group = groups[0]
-            for required in group.requires:
-                for provider in required.providedby:
-                    for package in provider.packages:
-                        if package.name == packagename:
-                            return True
-        return False
-
-    def _get_group(self, info, filter_desktops=True):
-        group = info.getGroup()
-        if group in self.GROUPS:
-            package = info.getPackage().name
-            if group == 'User Interface/X' and package.find('-fonts') != -1:
-                return GROUP_FONTS
-            if group == 'Applications/Productivity' and \
-            package.find('-langpack') != -1:
-                return GROUP_LOCALIZATION
-            if group == 'User Interface/Desktops' and filter_desktops:
-                if self._package_in_requires(package, "^gnome-desktop") or \
-                self._package_in_requires(package, "^gnome-desktop-optional"):
-                    return GROUP_DESKTOP_GNOME
-                if self._package_in_requires(package, "^kde-desktop") or \
-                self._package_in_requires(package, "^kde-desktop-optional"):
-                    return GROUP_DESKTOP_KDE
-                if self._package_in_requires(package, "^xfce-desktop") or \
-                self._package_in_requires(package, "^xfce-desktop-optional"):
-                    return GROUP_DESKTOP_XFCE
-            group = self.GROUPS[group]
-        else:
-            while group.find('/') != -1:
-                group = group.rsplit('/', 1)[0]
-                if group in self.GROUPS:
-                    group = self.GROUPS[group]
-                    break
-            else:
-                group = GROUP_UNKNOWN
-        return group
-
-    def _get_status(self, package):
-        for loader in package.loaders:
-            if hasattr(loader, 'getErrata'):
-                errata = loader.getErrata(package)
-                type = errata.getType()
-                if type == 'security':
-                    return INFO_SECURITY
-                elif type == 'bugfix':
-                    return INFO_BUGFIX
-                elif type == 'enhancement':
-                    return INFO_ENHANCEMENT
-        # using the flags for errata is deprecated
-        flags = smart.pkgconf.testAllFlags(package)
-        for flag in flags:
-            if flag == 'security':
-                return INFO_SECURITY
-            elif flag == 'bugfix':
-                return INFO_BUGFIX
-            elif flag == 'enhancement':
-                return INFO_ENHANCEMENT
-        return INFO_NORMAL
-
-    def _process_search_results(self, results):
-        packages = []
-        for obj in results:
-            if isinstance(obj, smart.cache.Package):
-                packages.append(obj)
-
-        if not packages:
-            for obj in results:
-                for pkg in obj.packages:
-                    packages.append(pkg)
-
-        return packages
-
-    def _channel_passes_filters(self, channel, filters):
-        filterlist = filters.split(';')
-        if FILTER_NOT_DEVELOPMENT in filterlist:
-            if channel['type'] == 'rpm-md':
-                repo = channel['alias']
-                if repo.endswith('-debuginfo'):
-                    return False
-                if repo.endswith('-testing'):
-                    return False
-                if repo.endswith('-debug'):
-                    return False
-                if repo.endswith('-development'):
-                    return False
-                if repo.endswith('-source'):
-                    return False
-        return True
-
-    def _package_is_graphical(self, package):
-        from smart.backends.rpm.base import RPMPackage
-        from smart.backends.deb.base import DebPackage
-        if isinstance(package, RPMPackage):
-            regex = re.compile(r'(qt)|(gtk)')
-            for required in package.requires:
-                for provider in required.providedby:
-                    for package in provider.packages:
-                        if regex.search(package.name):
-                            return True
-            return False
-        elif isinstance(package, DebPackage):
-            group = package.getGroup().split('/')[-1].lower()
-            return group in ['x11', 'gnome', 'kde']
-        else:
-            return None
-
-    def _package_is_development(self, package):
-        from smart.backends.rpm.base import RPMPackage
-        from smart.backends.deb.base import DebPackage
-        if isinstance(package, RPMPackage):
-            regex = re.compile(r'(-devel)|(-dgb)|(-static)')
-            return bool(regex.search(package.name))
-        elif isinstance(package, DebPackage):
-            group = package.getGroup().split('/')[-1].lower()
-            return package.name.endswith("-dev") or \
-                   package.name.endswith("-dbg") or \
-                   group in ['devel', 'libdevel']
-        else:
-            return None
-
-    def _package_passes_filters(self, package, filters):
-        filterlist = filters.split(';')
-        if FILTER_NOT_INSTALLED in filterlist and package.installed:
-            return False
-        elif FILTER_INSTALLED in filterlist and not package.installed:
-            return False
-        else:
-            loader = package.loaders.keys()[0]
-            info = loader.getInfo(package)
-            for filter in filterlist:
-                if filter in (FILTER_ARCH, FILTER_NOT_ARCH):
-                    name, version, arch = self._splitpackage(package)
-                    same = self._samearch(arch, self._machine())
-                    if filter == FILTER_ARCH and not same:
-                        return False
-                    if filter == FILTER_NOT_ARCH and same:
-                        return False
-                if filter in (FILTER_COLLECTIONS, FILTER_NOT_COLLECTIONS):
-                    collection = self._package_is_collection(package)
-                    if filter == FILTER_COLLECTIONS and not collection:
-                        return False
-                    if filter == FILTER_NOT_COLLECTIONS and collection:
-                        return False
-                if filter in (FILTER_GUI, FILTER_NOT_GUI):
-                    graphical = self._package_is_graphical(package)
-                    if graphical is None: # tristate boolean
-                        return None
-                    if filter == FILTER_GUI and not graphical:
-                        return False
-                    if filter == FILTER_NOT_GUI and graphical:
-                        return False
-                if filter in (FILTER_DEVELOPMENT, FILTER_NOT_DEVELOPMENT):
-                    development = self._package_is_development(package)
-                    if development is None: # tristate boolean
-                        return None
-                    if filter == FILTER_DEVELOPMENT and not development:
-                        return False
-                    if filter == FILTER_NOT_DEVELOPMENT and development:
-                        return False
-                if filter in (FILTER_BASENAME, FILTER_NOT_BASENAME):
-                    if hasattr(info, 'getSource'):
-                        source = info.getSource()
-                        if not source:
-                            return None
-                        same = (package.name == source)
-                        if filter == FILTER_BASENAME and not same:
-                            return False
-                        if filter == FILTER_NOT_BASENAME and same:
-                            return False
-                if filter in (FILTER_FREE, FILTER_NOT_FREE):
-                    if hasattr(info, 'getLicense'):
-                        license = info.getLicense()
-                        free = pkpackage.check_license_field(license)
-                        if free is None: # tristate boolean
-                            return None
-                        if filter == FILTER_FREE and not free:
-                            return False
-                        if filter == FILTER_NOT_FREE and free:
-                            return False
-                    else:
-                        self.error(ERROR_FILTER_INVALID, \
-                                   "filter %s not supported" % filter)
-                        return False
-        return True
-
-    def _package_has_basename(self, package):
-        from smart.backends.rpm.base import RPMPackage
-        from smart.backends.deb.base import DebPackage
-        if isinstance(package, RPMPackage):
-            if package.name.endswith("-devel") or \
-               package.name.endswith("-debuginfo") or \
-               package.name.endswith("-libs") or \
-               package.name.endswith("-static"):
-                return False
-            return True
-        elif isinstance(package, DebPackage):
-            if package.name.endswith("-dev") or \
-               package.name.endswith("-dbg"):
-                return False
-            return True
-        else:
-            return None
-
-    def _do_basename_filtering(self, package_list):
-        basename = {}
-        for package, status in package_list:
-            if self._package_has_basename(package):
-                basename[package] = (package, status)
-        return basename.values()
-
-    def _do_newest_filtering(self, package_list):
-        newest = {}
-        for package, status in package_list:
-            name, version, arch = self._splitpackage(package)
-            key = (name, arch)
-            if key in newest and package <= newest[key]:
-                continue
-            newest[key] = (package, status)
-        return newest.values()
-
-    def _post_process_package_list(self, filters):
-        filterlist = filters.split(';')
-        if FILTER_BASENAME in filterlist:
-            self._package_list = self._do_basename_filtering(self._package_list)
-        if FILTER_NEWEST in filterlist:
-            self._package_list = self._do_newest_filtering(self._package_list)
-
-def main():
-    backend = PackageKitSmartBackend('')
-    backend.dispatcher(sys.argv[1:])
-
-if __name__ == "__main__":
-    main()
diff --git a/backends/smart/pk-backend-smart.c b/backends/smart/pk-backend-smart.c
index a703039..16da9fe 100644
--- a/backends/smart/pk-backend-smart.c
+++ b/backends/smart/pk-backend-smart.c
@@ -27,11 +27,7 @@
 
 static PkBackendSpawn *spawn;
 
-#if 0
-#define BACKEND(x)	x ".py"
-#else
 #define BACKEND(x)	"smartBackend.py", x
-#endif
 
 /**
  * backend_initialize:
diff --git a/backends/smart/smartBackend.py b/backends/smart/smartBackend.py
new file mode 100755
index 0000000..25d38a9
--- /dev/null
+++ b/backends/smart/smartBackend.py
@@ -0,0 +1,1306 @@
+#!/usr/bin/python
+# Licensed under the GNU General Public License Version 2
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# Copyright (C) 2007 James Bowes <jbowes at dangerouslyinc.com>
+# Copyright (C) 2008 Anders F Bjorklund <afb at users.sourceforge.net>
+
+import smart
+from smart.interface import Interface
+from smart.progress import Progress
+from smart.fetcher import Fetcher
+from packagekit.backend import PackageKitBaseBackend
+from packagekit.package import PackagekitPackage
+from packagekit.enums import *
+import re
+import sys
+
+# Global vars
+pkpackage = PackagekitPackage()
+
+def needs_cache(func):
+    """ Load smart's channels, and save the cache when done. """
+    def cache_wrap(obj, *args, **kwargs):
+        if not obj._cacheloaded:
+            obj.status(STATUS_LOADING_CACHE)
+            obj.allow_cancel(True)
+            obj.ctrl.reloadChannels()
+        result = None
+        try:
+            result = func(obj, *args, **kwargs)
+        except UnicodeDecodeError, e:
+            pass
+        if not obj._cacheloaded:
+            obj.ctrl.saveSysConf()
+            obj._cacheloaded = True
+        return result
+    return cache_wrap
+
+
+class PackageKitSmartInterface(Interface):
+
+    def __init__(self, ctrl, backend):
+        Interface.__init__(self, ctrl)
+        smart.sysconf.set("max-active-downloads", 1, soft=True)
+        self._progress = PackageKitSmartProgress(True, backend)
+
+    def getProgress(self, obj, hassub=False):
+        self._progress.setHasSub(hassub)
+        fetcher = isinstance(obj, Fetcher) and obj or None
+        self._progress.setFetcher(fetcher)
+        return self._progress
+
+class PackageKitSmartProgress(Progress):
+
+    def __init__(self, hassub, backend):
+        Progress.__init__(self)
+        self._hassub = hassub
+        self._backend = backend
+        self._lasturl = None
+        self._oldstatus = None
+        self._oldcancel = None
+
+    def setFetcher(self, fetcher):
+        self._fetcher = fetcher
+        if fetcher:
+            self._oldstatus = self._backend._status
+            self._backend.status(STATUS_DOWNLOAD)
+            self._backend.allow_cancel(True)
+            self._backend.percentage(0)
+
+    def stop(self):
+        Progress.stop(self)
+        if self._oldstatus:
+            self._backend.percentage(100)
+            self._backend.allow_cancel(self._oldcancel)
+            self._backend.status(self._oldstatus)
+            self._oldstatus = None
+
+    def expose(self, topic, percent, subkey, subtopic, subpercent, data, done):
+        self._backend.percentage(percent)
+        if self.getHasSub() and subkey:
+            # unfortunately Progress doesn't provide the current package
+            if self._fetcher and subtopic != self._lasturl:
+                packages = self._backend._packagesdict
+                if not packages:
+                    filename = subtopic
+                    if filename.find('repomd') != -1 \
+                    or filename.find('Release') != -1:
+                        self._backend.status(STATUS_DOWNLOAD_REPOSITORY)
+                    elif filename.find('primary') != -1 \
+                    or filename.find('Packages') != -1:
+                        self._backend.status(STATUS_DOWNLOAD_PACKAGELIST)
+                    elif filename.find('filelists') != -1:
+                        self._backend.status(STATUS_DOWNLOAD_FILELIST)
+                    elif filename.find('other') != -1:
+                        self._backend.status(STATUS_DOWNLOAD_CHANGELOG)
+                    elif filename.find('comps') != -1:
+                        self._backend.status(STATUS_DOWNLOAD_GROUP)
+                    elif filename.find('updateinfo') != -1:
+                        self._backend.status(STATUS_DOWNLOAD_UPDATEINFO)
+                    return
+                for package in packages:
+                    for loader in package.loaders:
+                        info = loader.getInfo(package)
+                        for url in info.getURLs():
+                            # account for progress url from current mirror
+                            item = self._fetcher.getItem(url)
+                            if item:
+                                url = str(item.getURL())
+                                if subtopic == url:
+                                    self._backend._show_package(package)
+                self._lasturl = subtopic
+            elif isinstance(subkey, smart.cache.Package):
+                self._backend._show_package(subkey)
+            elif type(subkey) is tuple and len(subkey):
+                if isinstance(subkey[0], smart.cache.PackageInfo):
+                    self._backend._show_package(subkey[0].getPackage())
+
+class PackageKitSmartBackend(PackageKitBaseBackend):
+
+    _status = STATUS_UNKNOWN
+    _cancel = False
+
+    def __init__(self, args):
+        PackageKitBaseBackend.__init__(self, args)
+        self._cacheloaded = False
+
+        self.ctrl = smart.init()
+        smart.iface.object = PackageKitSmartInterface(self.ctrl, self)
+        smart.initPlugins()
+        smart.initPsyco()
+
+        self._package_list = []
+        self._packagesdict = None
+
+    def status(self, state):
+        PackageKitBaseBackend.status(self, state)
+        self._status = state
+
+    def allow_cancel(self, allow):
+        PackageKitBaseBackend.allow_cancel(self, allow)
+        self._cancel = allow
+
+    def reset(self):
+        self._package_list = []
+
+    @needs_cache
+    def install_packages(self, packageids):
+        packages = []
+        for packageid in packageids:
+            ratio, results, suggestions = self._search_packageid(packageid)
+            if not results:
+                packagestring = self._string_packageid(packageid)
+                self.error(ERROR_PACKAGE_NOT_FOUND,
+                           'Package %s was not found' % packagestring)
+            packages.extend(self._process_search_results(results))
+
+        available = []
+        for package in packages:
+            if package.installed:
+                self.error(ERROR_PACKAGE_ALREADY_INSTALLED,
+                           'Package %s is already installed' % package)
+            else:
+                available.append(package)
+        if len(available) < 1:
+            return
+
+        trans = smart.transaction.Transaction(self.ctrl.getCache(),
+                smart.transaction.PolicyInstall)
+        for package in available:
+            trans.enqueue(package, smart.transaction.INSTALL)
+
+        self.allow_cancel(False)
+        self.status(STATUS_DEP_RESOLVE)
+        trans.run()
+        self.status(STATUS_INSTALL)
+        self._packagesdict = trans.getChangeSet()
+        self.ctrl.commitTransaction(trans, confirm=False)
+
+    @needs_cache
+    def install_files(self, trusted, paths):
+        for path in paths:
+            self.ctrl.addFileChannel(path)
+        self.ctrl.reloadChannels()
+        trans = smart.transaction.Transaction(self.ctrl.getCache(),
+                smart.transaction.PolicyInstall)
+
+        for channel in self.ctrl.getFileChannels():
+            for loader in channel.getLoaders():
+                for package in loader.getPackages():
+                    if package.installed:
+                        self.error(ERROR_PACKAGE_ALREADY_INSTALLED,
+                                'Package %s is already installed' % package)
+                    trans.enqueue(package, smart.transaction.INSTALL)
+
+        self.allow_cancel(False)
+        self.status(STATUS_DEP_RESOLVE)
+        trans.run()
+        self.status(STATUS_INSTALL)
+        self._packagesdict = trans.getChangeSet()
+        self.ctrl.commitTransaction(trans, confirm=False)
+
+    @needs_cache
+    def remove_packages(self, allow_deps, packageids):
+        packages = []
+        for packageid in packageids:
+            ratio, results, suggestions = self._search_packageid(packageid)
+            if not results:
+                packagestring = self._string_packageid(packageid)
+                self.error(ERROR_PACKAGE_NOT_FOUND,
+                           'Package %s was not found' % packagestring)
+            packages.extend(self._process_search_results(results))
+
+        installed = []
+        for package in packages:
+            if not package.installed:
+                self.error(ERROR_PACKAGE_NOT_INSTALLED,
+                           'Package %s is not installed' % package)
+            elif package.essential:
+                self.error(ERROR_CANNOT_REMOVE_SYSTEM_PACKAGE,
+                           'Package %s cannot be removed' % package)
+            else:
+                installed.append(package)
+        if len(installed) < 1:
+            return
+
+        trans = smart.transaction.Transaction(self.ctrl.getCache(),
+                smart.transaction.PolicyRemove)
+        for package in installed:
+            trans.enqueue(package, smart.transaction.REMOVE)
+
+        self.allow_cancel(False)
+        self.status(STATUS_DEP_RESOLVE)
+        trans.run()
+        self.status(STATUS_REMOVE)
+        self._packagesdict = trans.getChangeSet()
+        self.ctrl.commitTransaction(trans, confirm=False)
+
+    @needs_cache
+    def update_packages(self, packageids):
+        packages = []
+        for packageid in packageids:
+            ratio, results, suggestions = self._search_packageid(packageid)
+            if not results:
+                packagestring = self._string_packageid(packageid)
+                self.error(ERROR_PACKAGE_NOT_FOUND,
+                           'Package %s was not found' % packagestring)
+            packages.extend(self._process_search_results(results))
+
+        installed = [package for package in packages if package.installed]
+        if len(installed) < 1:
+            return
+        trans = smart.transaction.Transaction(self.ctrl.getCache(),
+                smart.transaction.PolicyUpgrade)
+        for package in installed:
+            trans.enqueue(package, smart.transaction.UPGRADE)
+
+        self.allow_cancel(False)
+        self.status(STATUS_DEP_RESOLVE)
+        trans.run()
+        self.status(STATUS_UPDATE)
+        self._packagesdict = trans.getChangeSet()
+        self.ctrl.commitTransaction(trans, confirm=False)
+
+    @needs_cache
+    def download_packages(self, directory, packageids):
+        packages = []
+        for packageid in packageids:
+            ratio, results, suggestions = self._search_packageid(packageid)
+            if not results:
+                packagestring = self._string_packageid(packageid)
+                self.error(ERROR_PACKAGE_NOT_FOUND,
+                           'Package %s was not found' % packagestring)
+            packages.extend(self._process_search_results(results))
+        if len(packages) < 1:
+            return
+
+        self.status(STATUS_DOWNLOAD)
+        self.allow_cancel(True)
+        self._packagesdict = packages
+        self.ctrl.downloadPackages(packages, targetdir=directory)
+
+        pkgpath = self.ctrl.fetchPackages(packages, targetdir=directory)
+        for package, files in pkgpath.iteritems():
+            self.files(package, ";".join(files))
+
+    @needs_cache
+    def update_system(self):
+        self.status(STATUS_INFO)
+        cache = self.ctrl.getCache()
+
+        trans = smart.transaction.Transaction(cache,
+                smart.transaction.PolicyUpgrade)
+
+        for package in cache.getPackages():
+            if package.installed:
+                trans.enqueue(package, smart.transaction.UPGRADE)
+
+        self.allow_cancel(False)
+        self.status(STATUS_DEP_RESOLVE)
+        trans.run()
+        if not trans:
+            self.error(ERROR_NO_PACKAGES_TO_UPDATE,
+                       "No interesting upgrades available.")
+            return
+        self.status(STATUS_UPDATE)
+        self._packagesdict = trans.getChangeSet()
+        self.ctrl.commitTransaction(trans, confirm=False)
+
+    @needs_cache
+    def get_updates(self, filters):
+        self.status(STATUS_INFO)
+        cache = self.ctrl.getCache()
+
+        trans = smart.transaction.Transaction(cache,
+                smart.transaction.PolicyUpgrade)
+
+        for package in cache.getPackages():
+            if package.installed:
+                trans.enqueue(package, smart.transaction.UPGRADE)
+
+        self.allow_cancel(False)
+        self.status(STATUS_DEP_RESOLVE)
+        trans.run()
+        self.status(STATUS_INFO)
+        for (package, op) in trans.getChangeSet().items():
+            if op == smart.transaction.INSTALL:
+                if self._package_passes_filters(package, filters):
+                    status = self._get_status(package)
+                    self._add_package(package, status)
+        self._post_process_package_list(filters)
+        self._show_package_list()
+
+    @needs_cache
+    def get_update_detail(self, packageids):
+        self.status(STATUS_INFO)
+        self.allow_cancel(True)
+        for packageid in packageids:
+            ratio, results, suggestions = self._search_packageid(packageid)
+
+            packages = self._process_search_results(results)
+
+            if len(packages) == 0:
+                packagestring = self._string_packageid(packageid)
+                self.error(ERROR_PACKAGE_NOT_FOUND,
+                           'Package %s was not found' % packagestring)
+                return
+
+            channels = self._search_channels(packageid)
+
+            package = packages[0]
+            changelog = ''
+            errata = None
+            for loader in package.loaders:
+                if channels and loader.getChannel() not in channels:
+                    continue
+                info = loader.getInfo(package)
+                if hasattr(info, 'getChangeLog'):
+                    changelog = info.getChangeLog()
+                    changelog = ';'.join(changelog)
+                if hasattr(loader, 'getErrata'):
+                    errata = loader.getErrata(package)
+
+            upgrades = ''
+            if package.upgrades:
+                upgrades = []
+                for upg in package.upgrades:
+                    for prv in upg.providedby:
+                        for prvpkg in prv.packages:
+                            if prvpkg.installed:
+                                upgrades.append(
+                                    self._package_id(prvpkg, loader))
+                upgrades = '^'.join(upgrades)
+            obsoletes = ''
+
+            if not errata:
+                state = self._get_status(package) or ''
+                self.update_detail(self._package_id(package, loader),
+                    upgrades, obsoletes, '', '', '',
+                    'none', '', changelog, state, '', '')
+                continue
+
+            state = errata.getType()
+            issued = errata.getDate()
+            updated = ''
+
+            description = errata.getDescription()
+            description = description.replace(";", ",")
+            description = description.replace("\n", ";")
+
+            urls = errata.getReferenceURLs()
+            vendor_urls = []
+            bugzilla_urls = []
+            cve_urls = []
+            for url in urls:
+                if url.find("cve") != -1:
+                    cve_urls.append(url)
+                elif url.find("bugzilla") != -1:
+                    bugzilla_urls.append(url)
+                else:
+                    vendor_urls.append(url)
+            vendor_url = ';'.join(vendor_urls)
+            bugzilla_url = ';'.join(vendor_urls)
+            cve_url = ';'.join(vendor_urls)
+
+            if errata.isRebootSuggested():
+                reboot = 'system'
+            else:
+                reboot = 'none'
+
+            self.update_detail(self._package_id(package, loader),
+                upgrades, obsoletes, vendor_url, bugzilla_url, cve_url,
+                reboot, description, changelog, state, issued, updated)
+
+    @needs_cache
+    def resolve(self, filters, packages):
+        self.status(STATUS_QUERY)
+        self.allow_cancel(True)
+        for packagename in packages:
+            ratio, results, suggestions = self.ctrl.search(packagename)
+            for result in results:
+                if self._package_passes_filters(result, filters):
+                    self._add_package(result)
+        self._post_process_package_list(filters)
+        self._show_package_list()
+
+    @needs_cache
+    def search_name(self, filters, packagename):
+        globbed = "*%s*" % packagename
+        self.status(STATUS_QUERY)
+        self.allow_cancel(True)
+        ratio, results, suggestions = self.ctrl.search(globbed)
+
+        packages = self._process_search_results(results)
+
+        for package in packages:
+            if self._package_passes_filters(package, filters):
+                self._add_package(package)
+        self._post_process_package_list(filters)
+        self._show_package_list()
+
+    @needs_cache
+    def search_file(self, filters, searchstring):
+        self.status(STATUS_QUERY)
+        self.allow_cancel(True)
+        packages = self.ctrl.getCache().getPackages()
+        for package in packages:
+            if self._package_passes_filters(package, filters):
+                paths = []
+                for loader in package.loaders:
+                    channel = loader.getChannel()
+                    if package.installed and not \
+                       channel.getType().endswith('-sys'):
+                        continue
+                    info = loader.getInfo(package)
+                    paths = info.getPathList()
+                    if len(paths) > 0:
+                        break
+                if searchstring in paths:
+                    self._add_package(package)
+        self._post_process_package_list(filters)
+        self._show_package_list()
+
+    @needs_cache
+    def search_group(self, filters, searchstring):
+        self.status(STATUS_QUERY)
+        self.allow_cancel(True)
+        filter_desktops = searchstring.find("desktop") != -1
+        packages = self.ctrl.getCache().getPackages()
+        for package in packages:
+            if self._package_passes_filters(package, filters):
+                info = package.loaders.keys()[0].getInfo(package)
+                group = self._get_group(info, filter_desktops)
+                if searchstring in group:
+                    self._add_package(package)
+        self._post_process_package_list(filters)
+        self._show_package_list()
+
+    @needs_cache
+    def search_details(self, filters, searchstring):
+        self.status(STATUS_QUERY)
+        self.allow_cancel(True)
+        packages = self.ctrl.getCache().getPackages()
+        for package in packages:
+            if self._package_passes_filters(package, filters):
+                info = package.loaders.keys()[0].getInfo(package)
+                if searchstring in info.getDescription():
+                    self._add_package(package)
+
+    @needs_cache
+    def get_packages(self, filters):
+        self.status(STATUS_QUERY)
+        self.allow_cancel(True)
+        packages = self.ctrl.getCache().getPackages()
+        for package in packages:
+            if self._package_passes_filters(package, filters):
+                self._add_package(package)
+        self._post_process_package_list(filters)
+        self._show_package_list()
+
+    @needs_cache
+    def what_provides(self, filters, provides_type, search):
+        self.status(STATUS_QUERY)
+        self.allow_cancel(True)
+        if provides_type != PROVIDES_ANY:
+            self.error(ERROR_NOT_SUPPORTED,
+                       "provide %s not supported" % provides_type)
+            return
+        providers = self.ctrl.getCache().getProvides(search)
+        for provider in providers:
+            for package in provider.packages:
+                if self._package_passes_filters(package, filters):
+                    self._add_package(package)
+        self._post_process_package_list(filters)
+        self._show_package_list()
+
+    def refresh_cache(self):
+        self.status(STATUS_REFRESH_CACHE)
+        self.allow_cancel(True)
+        self.ctrl.rebuildSysConfChannels()
+        self.ctrl.reloadChannels(None, caching=smart.const.NEVER)
+        self.ctrl.saveSysConf()
+
+    GROUPS = {
+    # RPM (redhat)
+    'Amusements/Games'                        : GROUP_GAMES,
+    'Amusements/Graphics'                     : GROUP_GRAPHICS,
+    'Applications/Archiving'                  : GROUP_OTHER, ### FIXME
+    'Applications/Communications'             : GROUP_COMMUNICATION,
+    'Applications/Databases'                  : GROUP_OTHER, ### FIXME
+    'Applications/Editors'                    : GROUP_PUBLISHING,
+    'Applications/Emulators'                  : GROUP_VIRTUALIZATION,
+    'Applications/Engineering'                : GROUP_OTHER, ### FIXME
+    'Applications/File'                       : GROUP_OTHER, ### FIXME
+    'Applications/Internet'                   : GROUP_INTERNET,
+    'Applications/Multimedia'                 : GROUP_MULTIMEDIA,
+    'Applications/Productivity'               : GROUP_OFFICE,
+    'Applications/Publishing'                 : GROUP_PUBLISHING,
+    'Applications/System'                     : GROUP_SYSTEM,
+    'Applications/Text'                       : GROUP_PUBLISHING,
+    'Development/Debuggers'                   : GROUP_PROGRAMMING,
+    'Development/Languages'                   : GROUP_PROGRAMMING,
+    'Development/Libraries'                   : GROUP_PROGRAMMING,
+    'Development/System'                      : GROUP_PROGRAMMING,
+    'Development/Tools'                       : GROUP_PROGRAMMING,
+    'Documentation'                           : GROUP_DOCUMENTATION,
+    'System Environment/Base'                 : GROUP_SYSTEM,
+    'System Environment/Daemons'              : GROUP_SYSTEM,
+    'System Environment/Kernel'               : GROUP_SYSTEM,
+    'System Environment/Libraries'            : GROUP_SYSTEM,
+    'System Environment/Shells'               : GROUP_SYSTEM,
+    'User Interface/Desktops'                 : GROUP_DESKTOP_OTHER,
+    'User Interface/X'                        : GROUP_DESKTOP_OTHER,
+    'User Interface/X Hardware Support'       : GROUP_DESKTOP_OTHER,
+    # Yum
+    'Virtual'                                 : GROUP_COLLECTIONS,
+    'Virtual/Applications'                    : GROUP_COLLECTIONS,
+    'Virtual/Base System'                     : GROUP_COLLECTIONS,
+    'Virtual/Desktop Environments'            : GROUP_COLLECTIONS,
+    'Virtual/Development'                     : GROUP_COLLECTIONS,
+    'Virtual/Languages'                       : GROUP_COLLECTIONS,
+    'Virtual/Servers'                         : GROUP_COLLECTIONS,
+    # RPM (novell)
+    'Amusements/Teaching'                     : GROUP_EDUCATION,
+    'Amusements/Toys'                         : GROUP_GAMES,
+    'Hardware'                                : GROUP_SYSTEM,
+    'Productivity/Archiving'                  : GROUP_OTHER, ### FIXME
+    'Productivity/Clustering'                 : GROUP_OTHER, ### FIXME
+    'Productivity/Databases'                  : GROUP_OTHER, ### FIXME
+    'Productivity/Editors'                    : GROUP_PUBLISHING,
+    'Productivity/File utilities'             : GROUP_OTHER, ### FIXME
+    'Productivity/Graphics'                   : GROUP_GRAPHICS,
+    'Productivity/Hamradio'                   : GROUP_COMMUNICATION,
+    'Productivity/Multimedia'                 : GROUP_MULTIMEDIA,
+    'Productivity/Networking'                 : GROUP_NETWORK,
+    'Productivity/Networking/Email'           : GROUP_INTERNET,
+    'Productivity/Networking/News'            : GROUP_INTERNET,
+    'Productivity/Networking/Web'             : GROUP_INTERNET,
+    'Productivity/Office'                     : GROUP_OFFICE,
+    'Productivity/Other'                      : GROUP_OTHER,
+    'Productivity/Publishing'                 : GROUP_PUBLISHING,
+    'Productivity/Scientific'                 : GROUP_SCIENCE,
+    'Productivity/Security'                   : GROUP_SECURITY,
+    'Productivity/Telephony'                  : GROUP_COMMUNICATION,
+    'Productivity/Text'                       : GROUP_PUBLISHING,
+    'System/Base'                             : GROUP_SYSTEM,
+    'System/Daemons'                          : GROUP_SYSTEM,
+    'System/Emulators'                        : GROUP_VIRTUALIZATION,
+    'System/Kernel'                           : GROUP_SYSTEM,
+    'System/Libraries'                        : GROUP_SYSTEM,
+    'System/Shells'                           : GROUP_SYSTEM,
+    'System/GUI/GNOME'                        : GROUP_DESKTOP_GNOME,
+    'System/GUI/KDE'                          : GROUP_DESKTOP_KDE,
+    'System/GUI/Other'                        : GROUP_DESKTOP_OTHER,
+    'System/GUI/XFCE'                         : GROUP_DESKTOP_XFCE,
+    'System/I18n'                             : GROUP_LOCALIZATION,
+    'System/Localization'                     : GROUP_LOCALIZATION,
+    'System/X11'                              : GROUP_DESKTOP_OTHER,
+    'System/X11/Fonts'                        : GROUP_FONTS,
+    # YaST2
+#   'Virtual'                                 : GROUP_COLLECTIONS,
+    'Virtual/Base Technologies'               : GROUP_COLLECTIONS,
+    'Virtual/Desktop Functions'               : GROUP_COLLECTIONS,
+#   'Virtual/Development'                     : GROUP_COLLECTIONS,
+    'Virtual/GNOME Desktop'                   : GROUP_COLLECTIONS,
+    'Virtual/Graphical Environments'          : GROUP_COLLECTIONS,
+    'Virtual/KDE Desktop'                     : GROUP_COLLECTIONS,
+    'Virtual/Server Functions'                : GROUP_COLLECTIONS,
+    # RPM (mandriva)
+    'Accessibility'                           : GROUP_ACCESSIBILITY,
+    'Archiving'                               : GROUP_OTHER, ### FIXME
+    'Books'                                   : GROUP_DOCUMENTATION,
+    'Communications'                          : GROUP_COMMUNICATION,
+    'Databases'                               : GROUP_OTHER, ### FIXME
+    'Development'                             : GROUP_PROGRAMMING,
+    'Editors'                                 : GROUP_PUBLISHING,
+    'Education'                               : GROUP_EDUCATION,
+    'Emulators'                               : GROUP_VIRTUALIZATION,
+    'File tools'                              : GROUP_OTHER, ### FIXME
+    'Games'                                   : GROUP_GAMES,
+    'Graphical desktop'                       : GROUP_DESKTOP_OTHER,
+    'Graphical desktop/GNOME'                 : GROUP_DESKTOP_GNOME,
+    'Graphical desktop/KDE'                   : GROUP_DESKTOP_KDE,
+    'Graphical desktop/Xfce'                  : GROUP_DESKTOP_XFCE,
+    'Graphics'                                : GROUP_GRAPHICS,
+    'Monitoring'                              : GROUP_NETWORK,
+    'Networking'                              : GROUP_INTERNET,
+    'Office'                                  : GROUP_OFFICE,
+    'Publishing'                              : GROUP_PUBLISHING,
+    'Sciences'                                : GROUP_SCIENCE,
+    'Shells'                                  : GROUP_SYSTEM,
+    'Sound'                                   : GROUP_MULTIMEDIA,
+    'System'                                  : GROUP_SYSTEM,
+    'System/Fonts'                            : GROUP_FONTS,
+    'System/Internationalization'             : GROUP_LOCALIZATION,
+    'Terminals'                               : GROUP_SYSTEM,
+    'Text tools'                              : GROUP_ACCESSORIES,
+    'Toys'                                    : GROUP_GAMES,
+    'Video'                                   : GROUP_MULTIMEDIA,
+    # DEB
+    "admin"                                   : GROUP_ADMIN_TOOLS,
+    "base"                                    : GROUP_SYSTEM,
+    "comm"                                    : GROUP_COMMUNICATION,
+    "devel"                                   : GROUP_PROGRAMMING,
+    "doc"                                     : GROUP_DOCUMENTATION,
+    "editors"                                 : GROUP_PUBLISHING,
+    "electronics"                             : GROUP_ELECTRONICS,
+    "embedded"                                : GROUP_SYSTEM,
+    "games"                                   : GROUP_GAMES,
+    "gnome"                                   : GROUP_DESKTOP_GNOME,
+    "graphics"                                : GROUP_GRAPHICS,
+    "hamradio"                                : GROUP_COMMUNICATION,
+    "interpreters"                            : GROUP_PROGRAMMING,
+    "kde"                                     : GROUP_DESKTOP_KDE,
+    "libdevel"                                : GROUP_PROGRAMMING,
+    "libs"                                    : GROUP_SYSTEM,
+    "mail"                                    : GROUP_INTERNET,
+    "math"                                    : GROUP_SCIENCE,
+    "misc"                                    : GROUP_OTHER,
+    "net"                                     : GROUP_NETWORK,
+    "news"                                    : GROUP_INTERNET,
+    "oldlibs"                                 : GROUP_LEGACY,
+    "otherosfs"                               : GROUP_SYSTEM,
+    "perl"                                    : GROUP_PROGRAMMING,
+    "python"                                  : GROUP_PROGRAMMING,
+    "science"                                 : GROUP_SCIENCE,
+    "shells"                                  : GROUP_SYSTEM,
+    "sound"                                   : GROUP_MULTIMEDIA,
+    "tex"                                     : GROUP_PUBLISHING,
+    "text"                                    : GROUP_PUBLISHING,
+    "utils"                                   : GROUP_ACCESSORIES,
+    "web"                                     : GROUP_INTERNET,
+    "x11"                                     : GROUP_DESKTOP_OTHER,
+    "unknown"                                 : GROUP_UNKNOWN,
+    "alien"                                   : GROUP_UNKNOWN,
+    "translations"                            : GROUP_LOCALIZATION,
+    # APT
+    "metapackages"                            : GROUP_COLLECTIONS,
+    # Slack
+    "Slackware"                               : GROUP_UNKNOWN
+    }
+    
+    @needs_cache
+    def get_details(self, packageids):
+        self.status(STATUS_INFO)
+        self.allow_cancel(True)
+        for packageid in packageids:
+            ratio, results, suggestions = self._search_packageid(packageid)
+
+            packages = self._process_search_results(results)
+
+            if len(packages) == 0:
+                packagestring = self._string_packageid(packageid)
+                self.error(ERROR_PACKAGE_NOT_FOUND,
+                           'Package %s was not found' % packagestring)
+                return
+
+            channels = self._search_channels(packageid)
+
+            package = packages[0]
+            infos = []
+            for loader in package.loaders:
+                if channels and loader.getChannel() not in channels and not \
+                (package.installed and self._package_is_collection(package)):
+                    continue
+                info = loader.getInfo(package)
+                infos.append(info)
+
+            if len(infos) == 0:
+                self.error(ERROR_PACKAGE_NOT_FOUND,
+                           'Package %s in other repo' % package)
+                return
+
+            infos.sort()
+            info = infos[0]
+
+            description = info.getDescription()
+            description = description.replace("\n\n", ";")
+            description = description.replace("\n", " ")
+            urls = info.getReferenceURLs()
+            if urls:
+                url = urls[0]
+            else:
+                url = "unknown"
+
+            pkgsize = None
+            seen = {}
+            for loader in package.loaders:
+                info = loader.getInfo(package)
+                for pkgurl in info.getURLs():
+                    size = info.getSize(pkgurl)
+                    if size:
+                        pkgsize = size
+                        break
+                if pkgsize:
+                    break
+            if not pkgsize:
+                pkgsize = 0
+
+            if hasattr(info, 'getLicense'):
+                license = info.getLicense()
+            else:
+                license = ''
+
+            group = self._get_group(info)
+
+            self.details(self._package_id(package),
+                         license, group, description, url, pkgsize)
+
+    @needs_cache
+    def get_files(self, packageids):
+        self.status(STATUS_INFO)
+        self.allow_cancel(True)
+        for packageid in packageids:
+            ratio, results, suggestions = self._search_packageid(packageid)
+
+            packages = self._process_search_results(results)
+
+            if len(packages) == 0:
+                packagestring = self._string_packageid(packageid)
+                self.error(ERROR_PACKAGE_NOT_FOUND,
+                           'Package %s was not found' % packagestring)
+                return
+
+            channels = self._search_channels(packageid)
+
+            package = packages[0]
+            # FIXME: Only installed packages have path lists.
+            paths = None
+            for loader in package.loaders:
+                if channels and loader.getChannel() not in channels:
+                    continue
+                info = loader.getInfo(package)
+                paths = info.getPathList()
+                if len(paths) > 0:
+                    break
+
+            if paths == None:
+                self.error(ERROR_PACKAGE_NOT_FOUND,
+                           'Package %s in other repo' % package)
+                return
+
+            self.files(packageid, ";".join(paths))
+
+    def _text_to_boolean(self, text):
+        if text == 'true' or text == 'TRUE':
+            return True
+        elif text == 'yes' or text == 'YES':
+            return True
+        return False
+
+    def _best_package_from_list(self, package_list):
+        for installed in (True, False):
+            best = None
+            for package in package_list:
+                if not best or package > best:
+                    best = package
+            if best:
+                return best
+        return None
+
+    @needs_cache
+    def get_depends(self, filters, packageids, recursive_text):
+        recursive = self._text_to_boolean(recursive_text)
+        self.status(STATUS_INFO)
+        self.allow_cancel(True)
+        for packageid in packageids:
+            ratio, results, suggestions = self._search_packageid(packageid)
+
+            packages = self._process_search_results(results)
+
+            if len(packages) != 1:
+                return
+
+            package = packages[0]
+            original = package
+
+            extras = {}
+            for required in package.requires:
+                providers = {}
+                for provider in required.providedby:
+                    for package in provider.packages:
+                        if not providers.has_key(package):
+                            providers[package] = True
+                package = self._best_package_from_list(providers.keys())
+                if package and not extras.has_key(package):
+                    extras[package] = True
+
+            if original in extras:
+                del extras[original]
+            for package in extras.keys():
+                if self._package_passes_filters(package, filters):
+                    self._add_package(package)
+            self._post_process_package_list(filters)
+            self._show_package_list()
+
+    @needs_cache
+    def get_requires(self, filters, packageids, recursive_text):
+        recursive = self._text_to_boolean(recursive_text)
+        self.status(STATUS_INFO)
+        self.allow_cancel(True)
+        for packageid in packageids:
+            ratio, results, suggestions = self._search_packageid(packageid)
+
+            packages = self._process_search_results(results)
+
+            if len(packages) != 1:
+                return
+
+            package = packages[0]
+            original = package
+
+            extras = {}
+            for provided in package.provides:
+                requirers = {}
+                for requirer in provided.requiredby:
+                    for package in requirer.packages:
+                        if not requirers.has_key(package):
+                            requirers[package] = True
+                package = self._best_package_from_list(requirers.keys())
+                if package and not extras.has_key(package):
+                    extras[package] = True
+
+            if original in extras:
+                del extras[original]
+            for package in extras.keys():
+                if self._package_passes_filters(package, filters):
+                    self._add_package(package)
+            self._post_process_package_list(filters)
+            self._show_package_list()
+
+    def get_repo_list(self, filters):
+        self.status(STATUS_INFO)
+        self.allow_cancel(True)
+        channels = smart.sysconf.get("channels", ())
+        for alias in channels:
+            channel = smart.sysconf.get(("channels", alias))
+            name = channel.get("name", alias)
+            parsed = smart.channel.parseChannelData(channel)
+            enabled = 'true'
+            if channel.has_key('disabled') and channel['disabled'] == 'yes':
+                enabled = 'false'
+            channel['alias'] = alias
+            if self._channel_passes_filters(channel, filters):
+                self.repo_detail(alias, name, enabled)
+
+    def repo_enable(self, repoid, enable):
+        self.status(STATUS_INFO)
+        self.allow_cancel(True)
+        if smart.sysconf.has(("channels", repoid)):
+            if enable == "true":
+                smart.sysconf.remove(("channels", repoid, "disabled"))
+            else:
+                smart.sysconf.set(("channels", repoid, "disabled"), "yes")
+            self.ctrl.saveSysConf()
+        else:
+            self.error(ERROR_REPO_NOT_FOUND, "repo %s was not found" % repoid)
+
+    def repo_set_data(self, repoid, param, value):
+        self.status(STATUS_INFO)
+        self.allow_cancel(True)
+        if smart.sysconf.has(("channels", repoid)):
+            smart.sysconf.set(("channels", repoid, param), value)
+            self.ctrl.saveSysConf()
+        else:
+            self.error(ERROR_REPO_NOT_FOUND, "repo %s was not found" % repoid)
+
+    systemchannel = None # unfortunately package strings depend on system
+
+    def _machine(self):
+        import os
+        machine = os.uname()[-1]
+        if machine == "Power Macintosh": #<sigh>
+            machine = "ppc"
+        return machine
+
+    def _samearch(self, arch1, arch2):
+        if arch1 == arch2:
+            return True
+        if arch1 == 'noarch' or arch2 == 'noarch':
+            return True
+        x86 = re.compile(r'i[3456]86')
+        if x86.search(arch1) and x86.search(arch2):
+            return True
+        return False
+
+    def _splitpackage(self, package):
+        from smart.backends.rpm.base import RPMPackage
+        from smart.backends.deb.base import DebPackage
+        from smart.backends.slack.base import SlackPackage
+        if isinstance(package, RPMPackage):
+            name = package.name
+            version, arch = package.version.split('@')
+        elif isinstance(package, DebPackage):
+            name = package.name
+            version, arch = package.version, smart.backends.deb.base.DEBARCH
+        elif isinstance(package, SlackPackage):
+            name = package.name
+            ver, arch, rel = package.version.rsplit('-')
+            version = "%s-%s" % (ver, rel)
+        else:
+            version, arch = package.version, self._machine()
+        return name, version, arch
+
+    def _joinpackage(self, name, version, arch):
+        if not self.systemchannel:
+            channels = smart.sysconf.get("channels", ())
+            # FIXME: should look by type, not by alias
+            if "rpm-sys" in channels:
+                self.systemchannel = "rpm-sys"
+            elif "deb-sys" in channels:
+                self.systemchannel = "deb-sys"
+            elif "slack-sys" in channels:
+                self.systemchannel = "slack-sys"
+        if self.systemchannel == "rpm-sys":
+            pkg = "%s-%s@%s" % (name, version, arch)
+        elif self.systemchannel == "deb-sys":
+            pkg = "%s_%s" % (name, version)
+        elif self.systemchannel == "slack-sys":
+            ver, rel = version.rsplit("-")
+            pkg = "%s-%s-%s-%s" % (name, ver, arch, rel)
+        else:
+            pkg = "%s-%s" % (name, version)
+        return pkg
+
+    def _string_packageid(self, packageid):
+        idparts = packageid.split(';')
+        # note: currently you can only search in channels native to system
+        packagestring = self._joinpackage(idparts[0], idparts[1], idparts[2])
+        if packagestring.startswith('@'):
+            packagestring = packagestring.replace('@', '^', 1)
+        return packagestring
+
+    def _search_packageid(self, packageid):
+        packagestring = self._string_packageid(packageid)
+        ratio, results, suggestions = self.ctrl.search(packagestring)
+
+        return (ratio, results, suggestions)
+
+    def _channel_is_local(self, channel):
+        return isinstance(channel, smart.channel.FileChannel)
+
+    def _search_channels(self, packageid):
+        idparts = packageid.split(';')
+        repoid = idparts[3]
+        if repoid == 'local':
+            channels = self.ctrl.getFileChannels()
+        elif repoid:
+            if repoid == 'installed':
+                repoid = self.systemchannel
+            channels = self.ctrl.getChannels()
+            channels = [x for x in channels if x.getAlias() == repoid]
+        else:
+            channels = None
+        return channels
+
+    def _package_is_collection(self, package):
+        return package.name.startswith('^')
+
+    def _add_package(self, package, status=None):
+        if not status:
+            if self._package_is_collection(package):
+                if package.installed:
+                    status = INFO_COLLECTION_INSTALLED
+                else:
+                    status = INFO_COLLECTION_AVAILABLE
+            else:
+                if package.installed:
+                    status = INFO_INSTALLED
+                else:
+                    status = INFO_AVAILABLE
+        self._package_list.append((package, status))
+
+    def _show_package_list(self):
+        for package, status in self._package_list:
+            self._show_package(package, status)
+
+    def _package_id(self, package, loader=None):
+        name, version, arch = self._splitpackage(package)
+        collection = False
+        if name.startswith('^'):
+            collection = True
+            name = name.replace('^', '@', 1)
+        if not loader:
+            for loader in package.loaders:
+                break
+        channel = loader.getChannel()
+        if package.installed:
+            data = 'installed'
+        elif self._channel_is_local(channel):
+            data = 'local'
+        else:
+            data = channel.getAlias()
+        return pkpackage.get_package_id(name, version, arch, data)
+
+    def _show_package(self, package, status=None):
+        if not status:
+            if self._status == STATUS_DOWNLOAD:
+                status = INFO_DOWNLOADING
+            elif self._status == STATUS_INSTALL:
+                status = INFO_INSTALLING
+            elif self._status == STATUS_UPDATE:
+                status = INFO_UPDATING
+            elif self._status == STATUS_REMOVE:
+                status = INFO_REMOVING
+            else:
+                status = INFO_UNKNOWN
+        for loader in package.loaders:
+            channel = loader.getChannel()
+            if package.installed and not channel.getType().endswith('-sys') \
+            and not self._package_is_collection(package):
+                continue
+            info = loader.getInfo(package)
+            summary = info.getSummary()
+            self.package(self._package_id(package, loader), status, summary)
+
+    def _package_in_requires(self, packagename, groupname):
+        groups = self.ctrl.getCache().getPackages(groupname)
+        if groups:
+            group = groups[0]
+            for required in group.requires:
+                for provider in required.providedby:
+                    for package in provider.packages:
+                        if package.name == packagename:
+                            return True
+        return False
+
+    def _get_group(self, info, filter_desktops=True):
+        group = info.getGroup()
+        if group in self.GROUPS:
+            package = info.getPackage().name
+            if group == 'User Interface/X' and package.find('-fonts') != -1:
+                return GROUP_FONTS
+            if group == 'Applications/Productivity' and \
+            package.find('-langpack') != -1:
+                return GROUP_LOCALIZATION
+            if group == 'User Interface/Desktops' and filter_desktops:
+                if self._package_in_requires(package, "^gnome-desktop") or \
+                self._package_in_requires(package, "^gnome-desktop-optional"):
+                    return GROUP_DESKTOP_GNOME
+                if self._package_in_requires(package, "^kde-desktop") or \
+                self._package_in_requires(package, "^kde-desktop-optional"):
+                    return GROUP_DESKTOP_KDE
+                if self._package_in_requires(package, "^xfce-desktop") or \
+                self._package_in_requires(package, "^xfce-desktop-optional"):
+                    return GROUP_DESKTOP_XFCE
+            group = self.GROUPS[group]
+        else:
+            while group.find('/') != -1:
+                group = group.rsplit('/', 1)[0]
+                if group in self.GROUPS:
+                    group = self.GROUPS[group]
+                    break
+            else:
+                group = GROUP_UNKNOWN
+        return group
+
+    def _get_status(self, package):
+        for loader in package.loaders:
+            if hasattr(loader, 'getErrata'):
+                errata = loader.getErrata(package)
+                type = errata.getType()
+                if type == 'security':
+                    return INFO_SECURITY
+                elif type == 'bugfix':
+                    return INFO_BUGFIX
+                elif type == 'enhancement':
+                    return INFO_ENHANCEMENT
+        # using the flags for errata is deprecated
+        flags = smart.pkgconf.testAllFlags(package)
+        for flag in flags:
+            if flag == 'security':
+                return INFO_SECURITY
+            elif flag == 'bugfix':
+                return INFO_BUGFIX
+            elif flag == 'enhancement':
+                return INFO_ENHANCEMENT
+        return INFO_NORMAL
+
+    def _process_search_results(self, results):
+        packages = []
+        for obj in results:
+            if isinstance(obj, smart.cache.Package):
+                packages.append(obj)
+
+        if not packages:
+            for obj in results:
+                for pkg in obj.packages:
+                    packages.append(pkg)
+
+        return packages
+
+    def _channel_passes_filters(self, channel, filters):
+        filterlist = filters.split(';')
+        if FILTER_NOT_DEVELOPMENT in filterlist:
+            if channel['type'] == 'rpm-md':
+                repo = channel['alias']
+                if repo.endswith('-debuginfo'):
+                    return False
+                if repo.endswith('-testing'):
+                    return False
+                if repo.endswith('-debug'):
+                    return False
+                if repo.endswith('-development'):
+                    return False
+                if repo.endswith('-source'):
+                    return False
+        return True
+
+    def _package_is_graphical(self, package):
+        from smart.backends.rpm.base import RPMPackage
+        from smart.backends.deb.base import DebPackage
+        if isinstance(package, RPMPackage):
+            regex = re.compile(r'(qt)|(gtk)')
+            for required in package.requires:
+                for provider in required.providedby:
+                    for package in provider.packages:
+                        if regex.search(package.name):
+                            return True
+            return False
+        elif isinstance(package, DebPackage):
+            group = package.getGroup().split('/')[-1].lower()
+            return group in ['x11', 'gnome', 'kde']
+        else:
+            return None
+
+    def _package_is_development(self, package):
+        from smart.backends.rpm.base import RPMPackage
+        from smart.backends.deb.base import DebPackage
+        if isinstance(package, RPMPackage):
+            regex = re.compile(r'(-devel)|(-dgb)|(-static)')
+            return bool(regex.search(package.name))
+        elif isinstance(package, DebPackage):
+            group = package.getGroup().split('/')[-1].lower()
+            return package.name.endswith("-dev") or \
+                   package.name.endswith("-dbg") or \
+                   group in ['devel', 'libdevel']
+        else:
+            return None
+
+    def _package_passes_filters(self, package, filters):
+        filterlist = filters.split(';')
+        if FILTER_NOT_INSTALLED in filterlist and package.installed:
+            return False
+        elif FILTER_INSTALLED in filterlist and not package.installed:
+            return False
+        else:
+            loader = package.loaders.keys()[0]
+            info = loader.getInfo(package)
+            for filter in filterlist:
+                if filter in (FILTER_ARCH, FILTER_NOT_ARCH):
+                    name, version, arch = self._splitpackage(package)
+                    same = self._samearch(arch, self._machine())
+                    if filter == FILTER_ARCH and not same:
+                        return False
+                    if filter == FILTER_NOT_ARCH and same:
+                        return False
+                if filter in (FILTER_COLLECTIONS, FILTER_NOT_COLLECTIONS):
+                    collection = self._package_is_collection(package)
+                    if filter == FILTER_COLLECTIONS and not collection:
+                        return False
+                    if filter == FILTER_NOT_COLLECTIONS and collection:
+                        return False
+                if filter in (FILTER_GUI, FILTER_NOT_GUI):
+                    graphical = self._package_is_graphical(package)
+                    if graphical is None: # tristate boolean
+                        return None
+                    if filter == FILTER_GUI and not graphical:
+                        return False
+                    if filter == FILTER_NOT_GUI and graphical:
+                        return False
+                if filter in (FILTER_DEVELOPMENT, FILTER_NOT_DEVELOPMENT):
+                    development = self._package_is_development(package)
+                    if development is None: # tristate boolean
+                        return None
+                    if filter == FILTER_DEVELOPMENT and not development:
+                        return False
+                    if filter == FILTER_NOT_DEVELOPMENT and development:
+                        return False
+                if filter in (FILTER_BASENAME, FILTER_NOT_BASENAME):
+                    if hasattr(info, 'getSource'):
+                        source = info.getSource()
+                        if not source:
+                            return None
+                        same = (package.name == source)
+                        if filter == FILTER_BASENAME and not same:
+                            return False
+                        if filter == FILTER_NOT_BASENAME and same:
+                            return False
+                if filter in (FILTER_FREE, FILTER_NOT_FREE):
+                    if hasattr(info, 'getLicense'):
+                        license = info.getLicense()
+                        free = pkpackage.check_license_field(license)
+                        if free is None: # tristate boolean
+                            return None
+                        if filter == FILTER_FREE and not free:
+                            return False
+                        if filter == FILTER_NOT_FREE and free:
+                            return False
+                    else:
+                        self.error(ERROR_FILTER_INVALID, \
+                                   "filter %s not supported" % filter)
+                        return False
+        return True
+
+    def _package_has_basename(self, package):
+        from smart.backends.rpm.base import RPMPackage
+        from smart.backends.deb.base import DebPackage
+        if isinstance(package, RPMPackage):
+            if package.name.endswith("-devel") or \
+               package.name.endswith("-debuginfo") or \
+               package.name.endswith("-libs") or \
+               package.name.endswith("-static"):
+                return False
+            return True
+        elif isinstance(package, DebPackage):
+            if package.name.endswith("-dev") or \
+               package.name.endswith("-dbg"):
+                return False
+            return True
+        else:
+            return None
+
+    def _do_basename_filtering(self, package_list):
+        basename = {}
+        for package, status in package_list:
+            if self._package_has_basename(package):
+                basename[package] = (package, status)
+        return basename.values()
+
+    def _do_newest_filtering(self, package_list):
+        newest = {}
+        for package, status in package_list:
+            name, version, arch = self._splitpackage(package)
+            key = (name, arch)
+            if key in newest and package <= newest[key]:
+                continue
+            newest[key] = (package, status)
+        return newest.values()
+
+    def _post_process_package_list(self, filters):
+        filterlist = filters.split(';')
+        if FILTER_BASENAME in filterlist:
+            self._package_list = self._do_basename_filtering(self._package_list)
+        if FILTER_NEWEST in filterlist:
+            self._package_list = self._do_newest_filtering(self._package_list)
+
+def main():
+    backend = PackageKitSmartBackend('')
+    backend.dispatcher(sys.argv[1:])
+
+if __name__ == "__main__":
+    main()
diff --git a/configure.ac b/configure.ac
index 07cfbb2..d30a9cb 100644
--- a/configure.ac
+++ b/configure.ac
@@ -544,7 +544,6 @@ backends/conary/helpers/Makefile
 backends/dummy/Makefile
 backends/opkg/Makefile
 backends/smart/Makefile
-backends/smart/helpers/Makefile
 backends/test/Makefile
 backends/test/helpers/Makefile
 backends/urpmi/Makefile
commit 66467d3bdebbafd61b5f84c44962062333b219b1
Author: Richard Hughes <richard at hughsie.com>
Date:   Fri Sep 26 14:20:38 2008 +0100

    trivial: convert the conary backend to using the dispatcher, and make pylint a little happier

diff --git a/backends/conary/.gitignore b/backends/conary/.gitignore
index c851833..03a0663 100644
--- a/backends/conary/.gitignore
+++ b/backends/conary/.gitignore
@@ -7,4 +7,4 @@ Makefile.in
 *.loT
 *.o
 *~
-
+*.pyc
diff --git a/backends/conary/Makefile.am b/backends/conary/Makefile.am
index 35d8b98..24d7598 100644
--- a/backends/conary/Makefile.am
+++ b/backends/conary/Makefile.am
@@ -1,4 +1,8 @@
-SUBDIRS = helpers
+helperdir = $(datadir)/PackageKit/helpers/conary
+dist_helper_DATA = 			\
+	conaryBackend.py		\
+	conaryCallback.py
+
 plugindir = $(PK_PLUGIN_DIR)
 plugin_LTLIBRARIES = libpk_backend_conary.la
 libpk_backend_conary_la_SOURCES = pk-backend-conary.c
@@ -6,3 +10,9 @@ libpk_backend_conary_la_LIBADD = $(PK_PLUGIN_LIBS)
 libpk_backend_conary_la_LDFLAGS = -module -avoid-version
 libpk_backend_conary_la_CFLAGS = $(PK_PLUGIN_CFLAGS)
 
+install-data-hook:
+	chmod a+rx $(DESTDIR)$(helperdir)/*.py
+
+clean-local :
+	rm -f *~
+
diff --git a/backends/conary/conaryBackend.py b/backends/conary/conaryBackend.py
new file mode 100644
index 0000000..7190472
--- /dev/null
+++ b/backends/conary/conaryBackend.py
@@ -0,0 +1,998 @@
+#!/usr/bin/python
+# Licensed under the GNU General Public License Version 2
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# Copyright (C) 2007 Ken VanDine <ken at vandine.org>
+# Copyright (C) 2008 Richard Hughes <richard at hughsie.com>
+
+import sys
+import os
+
+from conary import errors
+from conary.deps import deps
+from conary import conarycfg, conaryclient
+from conary import dbstore, queryrep, versions, updatecmd
+from conary.local import database
+from conary import trove
+
+from packagekit.backend import *
+from packagekit.package import *
+from conaryCallback import UpdateCallback
+
+pkpackage = PackagekitPackage()
+
+groupMap = {
+    '2DGraphics'          : GROUP_GRAPHICS,
+    'Accessibility'       : GROUP_ACCESSIBILITY,
+    'AdvancedSettings'    : GROUP_ADMIN_TOOLS,
+    'Application'         : GROUP_OTHER,
+    'ArcadeGame'          : GROUP_GAMES,
+    'Audio'               : GROUP_MULTIMEDIA,
+    'AudioVideo'          : GROUP_MULTIMEDIA,
+    'BlocksGame'          : GROUP_GAMES,
+    'BoardGame'           : GROUP_GAMES,
+    'Calculator'          : GROUP_ACCESSORIES,
+    'Calendar'            : GROUP_ACCESSORIES,
+    'CardGame'            : GROUP_GAMES,
+    'Compiz'              : GROUP_SYSTEM,
+    'ContactManagement'   : GROUP_ACCESSORIES,
+    'Core'                : GROUP_SYSTEM,
+    'Database'            : GROUP_SERVERS,
+    'DesktopSettings'     : GROUP_ADMIN_TOOLS,
+    'Development'         : GROUP_PROGRAMMING,
+    'Email'               : GROUP_INTERNET,
+    'FileTransfer'        : GROUP_INTERNET,
+    'Filesystem'          : GROUP_SYSTEM,
+    'GNOME'               : GROUP_DESKTOP_GNOME,
+    'GTK'                 : GROUP_DESKTOP_GNOME,
+    'GUIDesigner'         : GROUP_PROGRAMMING,
+    'Game'                : GROUP_GAMES,
+    'Graphics'            : GROUP_GRAPHICS,
+    'HardwareSettings'    : GROUP_ADMIN_TOOLS,
+    'IRCClient'           : GROUP_INTERNET,
+    'InstantMessaging'    : GROUP_INTERNET,
+    'LogicGame'           : GROUP_GAMES,
+    'Monitor'             : GROUP_ADMIN_TOOLS,
+    'Music'               : GROUP_MULTIMEDIA,
+    'Network'             : GROUP_INTERNET,
+    'News'                : GROUP_INTERNET,
+    'Office'              : GROUP_OFFICE,
+    'P2P'                 : GROUP_INTERNET,
+    'PackageManager'      : GROUP_ADMIN_TOOLS,
+    'Photography'         : GROUP_MULTIMEDIA,
+    'Player'              : GROUP_MULTIMEDIA,
+    'Presentation'        : GROUP_OFFICE,
+    'Publishing'          : GROUP_OFFICE,
+    'RasterGraphics'      : GROUP_GRAPHICS,
+    'Security'            : GROUP_SECURITY,
+    'Settings'            : GROUP_ADMIN_TOOLS,
+    'Spreadsheet'         : GROUP_OFFICE,
+    'System'              : GROUP_SYSTEM,
+    'Telephony'           : GROUP_COMMUNICATION,
+    'TerminalEmulator'    : GROUP_ACCESSORIES,
+    'TextEditor'          : GROUP_ACCESSORIES,
+    'Utility'             : GROUP_ACCESSORIES,
+    'VectorGraphics'      : GROUP_GRAPHICS,
+    'Video'               : GROUP_MULTIMEDIA,
+    'Viewer'              : GROUP_MULTIMEDIA,
+    'WebBrowser'          : GROUP_INTERNET,
+    'WebDevelopment'      : GROUP_PROGRAMMING,
+    'WordProcessor'       : GROUP_OFFICE
+}
+
+revGroupMap = {}
+
+for (con_cat, pk_group) in groupMap.items():
+    if revGroupMap.has_key(pk_group):
+        revGroupMap[pk_group].append(con_cat)
+    else:
+        revGroupMap[pk_group] = [con_cat]
+
+#from conary.lib import util
+#sys.excepthook = util.genExcepthook()
+
+def ExceptionHandler(func):
+    def display(error):
+        return str(error).replace('\n', ' ')
+
+    def wrapper(self, *args, **kwargs):
+        try:
+            return func(self, *args, **kwargs)
+        #except Exception:
+        #    raise
+        except conaryclient.NoNewTrovesError:
+            return
+        except conaryclient.DepResolutionFailure, e:
+            self.error(ERROR_DEP_RESOLUTION_FAILED, display(e), exit=True)
+        except conaryclient.UpdateError, e:
+            # FIXME: Need a enum for UpdateError
+            self.error(ERROR_UNKNOWN, display(e), exit=True)
+        except Exception, e:
+            self.error(ERROR_UNKNOWN, display(e), exit=True)
+    return wrapper
+
+class PackageKitConaryBackend(PackageKitBaseBackend):
+    # Packages there require a reboot
+    rebootpkgs = ("kernel", "glibc", "hal", "dbus")
+
+    def __init__(self, args):
+        PackageKitBaseBackend.__init__(self, args)
+
+        self.cfg = conarycfg.ConaryConfiguration(True)
+        self.cfg.initializeFlavors()
+        self.cfg.autoResolve = True
+        self.cfg.keepRequired = True
+
+        self.client = conaryclient.ConaryClient(self.cfg)
+        self.callback = UpdateCallback(self, self.cfg)
+        self.client.setUpdateCallback(self.callback)
+
+    def _freezeData(self, version, flavor):
+        frzVersion = version.freeze()
+        frzFlavor = flavor.freeze()
+        return ','.join([frzVersion, frzFlavor])
+
+    def _thawData(self, data):
+        frzVersion, frzFlavor = data.split(', ')
+        version = versions.ThawVersion(frzVersion)
+        flavor = deps.ThawFlavor(frzFlavor)
+        return version, flavor
+
+    def _get_arch(self, flavor):
+        isdep = deps.InstructionSetDependency
+        arches = [ x.name for x in flavor.iterDepsByClass(isdep) ]
+        if not arches:
+            arches = [ 'noarch' ]
+        return ','.join(arches)
+
+    @ExceptionHandler
+    def get_package_id(self, name, versionObj, flavor):
+        version = versionObj.trailingRevision()
+        arch = self._get_arch(flavor)
+        data = self._freezeData(versionObj, flavor)
+        return pkpackage.get_package_id(name, version, arch, data)
+
+    @ExceptionHandler
+    def get_package_from_id(self, id):
+        name, verString, archString, data = \
+            pkpackage.get_package_from_id(id)
+
+        version, flavor = self._thawData(data)
+
+        return name, version, flavor
+
+    def _do_search(self, searchlist, filters):
+        fltlist = filters.split(';')
+        troveSpecs = [ updatecmd.parseTroveSpec(searchlist,
+                                                allowEmptyName=False) ]
+        # get a hold of cached data
+        cache = Cache()
+
+        try:
+            troveTupleList = cache.search(searchlist)
+        finally:
+            pass
+
+        # Remove dupes
+        tempDict = {}
+        try:
+            for element in troveTupleList:
+                tempDict[element] = None
+        except TypeError:
+            del tempDict  # move on to the next method
+        else:
+            troveTupleList = tempDict.keys()
+
+        # Get the latest first
+        troveTupleList.sort()
+        troveTupleList.reverse()
+
+        for troveTuple in troveTupleList:
+            troveTuple = tuple([item.encode('UTF-8') for item in troveTuple])
+            name = troveTuple[0]
+            version = versions.ThawVersion(troveTuple[1])
+            flavor = deps.ThawFlavor(troveTuple[2])
+            id = self.get_package_id(name, version, flavor)
+            summary = self._get_metadata(id, 'shortDesc') or " "
+            troveTuple = tuple([name, version, flavor])
+            installed = self.check_installed(troveTuple)
+
+            if self._do_filtering(name, fltlist, installed):
+                self.package(id, installed, summary)
+
+    def _get_update(self, applyList, cache=True):
+        updJob = self.client.newUpdateJob()
+        suggMap = self.client.prepareUpdateJob(updJob, applyList)
+        if cache:
+            Cache().cacheUpdateJob(applyList, updJob)
+        return updJob, suggMap
+
+    def _do_update(self, applyList):
+        jobPath = Cache().checkCachedUpdateJob(applyList)
+        if jobPath:
+            updJob = self.client.newUpdateJob()
+            try:
+                updJob.thaw(jobPath)
+            except IOError, err:
+                updJob = None
+        else:
+            updJob = self._get_update(applyList, cache=False)
+        self.allow_cancel(False)
+        restartDir = self.client.applyUpdateJob(updJob)
+        return updJob
+
+    def _get_package_update(self, name, version, flavor):
+        if name.startswith('-'):
+            applyList = [(name, (version, flavor), (None, None), False)]
+        else:
+            applyList = [(name, (None, None), (version, flavor), True)]
+        return self._get_update(applyList)
+
+    def _do_package_update(self, name, version, flavor):
+        if name.startswith('-'):
+            applyList = [(name, (version, flavor), (None, None), False)]
+        else:
+            applyList = [(name, (None, None), (version, flavor), True)]
+        return self._do_update(applyList)
+
+    @ExceptionHandler
+    def resolve(self, filter, package):
+        self.allow_cancel(True)
+        self.percentage(None)
+        self.status(STATUS_INFO)
+        self._do_search(package, filter)
+
+    @ExceptionHandler
+    def check_installed(self, troveTuple):
+        db = conaryclient.ConaryClient(self.cfg).db
+        try:
+            troveTuple = troveTuple[0], troveTuple[1], troveTuple[2]
+            localInstall = db.findTrove(None, troveTuple)
+            installed = INFO_INSTALLED
+        except:
+            installed = INFO_AVAILABLE
+        return installed
+
+    @ExceptionHandler
+    def search_group(self, filters, key):
+        '''
+        Implement the {backend}-search-name functionality
+        FIXME: Ignoring filters for now.
+        '''
+        self.allow_cancel(True)
+        self.percentage(None)
+        self.status(STATUS_QUERY)
+
+        fltlist = filters.split(';')
+        cache = Cache()
+
+        try:
+            troveTupleList = cache.searchByGroups(revGroupMap[key])
+        finally:
+            # FIXME: Really need to send an error here
+            pass
+
+        troveTupleList.sort()
+        troveTupleList.reverse()
+
+        for troveTuple in troveTupleList:
+            troveTuple = tuple([item.encode('UTF-8') for item in troveTuple[0:2]])
+            name = troveTuple[0]
+            version = versions.ThawVersion(troveTuple[1])
+            flavor = deps.ThawFlavor(troveTuple[2])
+            id = self.get_package_id(name, version, flavor)
+            summary = self._get_metadata(id, 'shortDesc') or " "
+            category = troveTuple[3][0]
+            category = category.encode('UTF-8')
+            troveTuple = tuple([name, version, flavor])
+            installed = self.check_installed(troveTuple)
+
+            if self._do_filtering(name, fltlist, installed):
+                self.package(id, installed, summary)
+
+    @ExceptionHandler
+    def search_name(self, options, searchlist):
+        '''
+        Implement the {backend}-search-name functionality
+        '''
+        self.allow_cancel(True)
+        self.percentage(None)
+        self.status(STATUS_QUERY)
+
+        self._do_search(searchlist, options)
+
+    def search_details(self, opt, key):
+        pass
+
+    def get_requires(self, filters, package_id):
+        pass
+
+    @ExceptionHandler
+    def get_depends(self, filters, package_id):
+        name, version, flavor, installed = self._findPackage(package_id)
+
+        if name:
+            if installed == INFO_INSTALLED:
+                self.error(ERROR_PACKAGE_ALREADY_INSTALLED, 'Package already installed')
+
+            else:
+                updJob, suggMap = self._get_package_update(name, version,
+                                                           flavor)
+                for what, need in suggMap:
+                    id = self.get_package_id(need[0], need[1], need[2])
+                    depInstalled = self.check_installed(need[0])
+                    if depInstalled == INFO_INSTALLED:
+                        self.package(id, INFO_INSTALLED, '')
+                    else:
+                        self.package(id, INFO_AVAILABLE, '')
+        else:
+            self.error(ERROR_PACKAGE_ALREADY_INSTALLED, 'Package was not found')
+
+    @ExceptionHandler
+    def get_files(self, package_id):
+        self.allow_cancel(True)
+        self.percentage(None)
+        self.status(STATUS_INFO)
+        def _get_files(troveSource, n, v, f):
+            files = []
+            troves = [(n, v, f)]
+            trv = troveSource.getTrove(n, v, f)
+            troves.extend([ x for x in trv.iterTroveList(strongRefs=True)
+                                if troveSource.hasTrove(*x)])
+            for n, v, f in troves:
+                for (pathId, path, fileId, version, file) in \
+                    troveSource.iterFilesInTrove(n, v, f, sortByPath = True,
+                                                 withFiles = True):
+                    files.append(path)
+            return files
+
+        name, version, flavor, installed = self._findPackage(package_id)
+
+        if installed == INFO_INSTALLED:
+            files = _get_files(self.client.db, name, version, flavor)
+        else:
+            files = _get_files(self.client.repos, name, version, flavor)
+
+        self.files(package_id, ';'.join(files))
+
+    @ExceptionHandler
+    def update_system(self):
+        self.allow_cancel(True)
+        updateItems = self.client.fullUpdateItemList()
+        applyList = [ (x[0], (None, None), x[1:], True) for x in updateItems ]
+        updJob, suggMap = self._do_update(applyList)
+
+    @ExceptionHandler
+    def refresh_cache(self):
+        self.percentage()
+        self.status(STATUS_REFRESH_CACHE)
+        cache = Cache()
+        cache.populate_database()
+
+    @ExceptionHandler
+    def update(self, packages):
+        '''
+        Implement the {backend}-update functionality
+        '''
+        self.allow_cancel(True);
+        self.percentage(0)
+        self.status(STATUS_RUNNING)
+
+        for package in packages.split(" "):
+            name, version, flavor, installed = self._findPackage(package)
+            if name:
+                self._do_package_update(name, version, flavor)
+            else:
+                self.error(ERROR_PACKAGE_ALREADY_INSTALLED, 'No available updates')
+
+    @ExceptionHandler
+    def update_packages(self, package_ids):
+        '''
+        Implement the {backend}-{install, update}-packages functionality
+        '''
+        for package_id in package_ids.split('%'):
+            name, version, flavor, installed = self._findPackage(package_id)
+
+            self.allow_cancel(True)
+            self.percentage(0)
+            self.status(STATUS_RUNNING)
+
+            if name:
+                if installed == INFO_INSTALLED:
+                    self.error(ERROR_PACKAGE_ALREADY_INSTALLED,
+                        'Package already installed')
+
+                self.status(INFO_INSTALLING)
+                self._get_package_update(name, version, flavor)
+                self._do_package_update(name, version, flavor)
+            else:
+                self.error(ERROR_PACKAGE_ALREADY_INSTALLED, 'Package was not found')
+
+    @ExceptionHandler
+    def remove_packages(self, allowDeps, package_ids):
+        '''
+        Implement the {backend}-remove-packages functionality
+        '''
+        self.allow_cancel(True)
+        self.percentage(0)
+        self.status(STATUS_RUNNING)
+
+        for package_id in package_ids.split('%'):
+            name, version, flavor, installed = self._findPackage(package_id)
+
+            if name:
+                if not installed == INFO_INSTALLED:
+                    self.error(ERROR_PACKAGE_NOT_INSTALLED, 'The package %s is not installed' % name)
+
+                name = '-%s' % name
+                self.status(INFO_REMOVING)
+                self._get_package_update(name, version, flavor)
+                self._do_package_update(name, version, flavor)
+            else:
+                self.error(ERROR_PACKAGE_ALREADY_INSTALLED, 'The package was not found')
+
+    def _get_metadata(self, id, field):
+        '''
+        Retrieve metadata from the repository and return result
+        field should be one of:
+                bibliography
+                url
+                notes
+                crypto
+                licenses
+                shortDesc
+                longDesc
+                categories
+        '''
+
+        self.allow_cancel(True)
+        self.percentage(None)
+        self.status(STATUS_QUERY)
+
+        n, v, f = self.get_package_from_id(id)
+
+        trvList = self.client.repos.findTrove(self.cfg.installLabelPath,
+                                     (n, v, f),
+                                     defaultFlavor = self.cfg.flavor)
+
+        troves = self.client.repos.getTroves(trvList, withFiles=False)
+        result = ''
+        for trove in troves:
+            result = trove.getMetadata()[field]
+        return result
+
+    def _format_list(self, lst):
+        """
+        Convert a multi line string to a list separated by ';'
+        """
+        if lst:
+            return ";".join(lst)
+        else:
+            return ""
+
+    def _get_update_extras(self, id):
+        notice = self._get_metadata(id, 'notice') or " "
+        urls = {'jira':[], 'cve' : [], 'vendor': []}
+        if notice:
+            # Update Details
+            desc = notice['description']
+            # Update References (Jira, CVE ...)
+            refs = notice['references']
+            if refs:
+                for ref in refs:
+                    typ = ref['type']
+                    href = ref['href']
+                    title = ref['title']
+                    if typ in ('jira', 'cve') and href != None:
+                        if title == None:
+                            title = ""
+                        urls[typ].append("%s;%s" % (href, title))
+                    else:
+                        urls['vendor'].append("%s;%s" % (ref['href'], ref['title']))
+
+            # Reboot flag
+            if notice.get_metadata().has_key('reboot_suggested') and notice['reboot_suggested']:
+                                reboot = 'system'
+            else:
+                reboot = 'none'
+            return self._format_str(desc), urls, reboot
+        else:
+            return "", urls, "none"
+
+    def _check_for_reboot(self, name):
+        if name in self.rebootpkgs:
+            self.require_restart(RESTART_SYSTEM, "")
+
+    @ExceptionHandler
+    def get_update_detail(self, id):
+        '''
+        Implement the {backend}-get-update_detail functionality
+        '''
+        self.allow_cancel(True)
+        self.percentage(None)
+        self.status(STATUS_INFO)
+        name, version, flavor, installed = self._findPackage(id)
+        #update = self._get_updated(pkg)
+        update = ""
+        obsolete = ""
+        #desc, urls, reboot = self._get_update_extras(id)
+        #cve_url = self._format_list(urls['cve'])
+        cve_url = ""
+        #bz_url = self._format_list(urls['jira'])
+        bz_url = ""
+        #vendor_url = self._format_list(urls['vendor'])
+        vendor_url = ""
+        reboot = "none"
+        desc = self._get_metadata(id, 'longDesc') or " "
+        self.update_detail(id, update, obsolete, vendor_url, bz_url, cve_url, reboot, desc)
+
+    @ExceptionHandler
+    def get_details(self, id):
+        '''
+        Print a detailed description for a given package
+        '''
+        self.allow_cancel(True)
+        self.percentage(None)
+        self.status(STATUS_INFO)
+
+        name, version, flavor, installed = self._findPackage(id)
+
+        if name:
+            shortDesc = self._get_metadata(id, 'shortDesc') or name
+            longDesc = self._get_metadata(id, 'longDesc') or ""
+            url = "http://www.foresightlinux.org/packages/" + name + ".html"
+            categories = self._get_metadata(id, 'categories') or "unknown"
+
+            # Package size goes here, but I don't know how to find that for conary packages.
+            self.details(id, None, categories, longDesc, url, 0)
+        else:
+            self.error(ERROR_PACKAGE_NOT_FOUND, 'Package was not found')
+
+    def _show_package(self, name, version, flavor, status):
+        '''  Show info about package'''
+        id = self.get_package_id(name, version, flavor)
+        summary = self._get_metadata(id, 'shortDesc') or ""
+        self.package(id, status, summary)
+
+    def _get_status(self, notice):
+        # We need to figure out how to get this info, this is a place holder
+        #ut = notice['type']
+        # TODO : Add more types to check
+        #if ut == 'security':
+        #    return INFO_SECURITY
+        #else:
+        #    return INFO_NORMAL
+        return INFO_NORMAL
+
+    @ExceptionHandler
+    def get_updates(self, filter):
+        self.allow_cancel(True)
+        self.percentage(None)
+        self.status(STATUS_INFO)
+
+        updateItems = self.client.fullUpdateItemList()
+        applyList = [ (x[0], (None, None), x[1:], True) for x in updateItems ]
+        updJob, suggMap = self._get_update(applyList)
+
+        jobLists = updJob.getJobs()
+
+        totalJobs = len(jobLists)
+        for num, job in enumerate(jobLists):
+            status = '2'
+            name = job[0][0]
+
+            # On an erase display the old version/flavor information.
+            version = job[0][2][0]
+            if version is None:
+                version = job[0][1][0]
+
+            flavor = job[0][2][1]
+            if flavor is None:
+                flavor = job[0][1][1]
+
+            troveTuple = []
+            troveTuple.append(name)
+            troveTuple.append(version)
+            installed = self.check_installed(troveTuple)
+            self._show_package(name, version, flavor, INFO_NORMAL)
+
+    def _do_filtering(self, pkg, filterList, installed):
+        ''' Filter the package, based on the filter in filterList '''
+        # do we print to stdout?
+        do_print = False;
+        if filterList == ['none']: # 'none' = all packages.
+            return True
+        elif FILTER_INSTALLED in filterList and installed == INFO_INSTALLED:
+            do_print = True
+        elif FILTER_NOT_INSTALLED in filterList and installed == INFO_AVAILABLE:
+            do_print = True
+
+        if len(filterList) == 1: # Only one filter, return
+            return do_print
+
+        if do_print:
+            return self._do_extra_filtering(pkg, filterList)
+        else:
+            return do_print
+
+    def _do_extra_filtering(self, pkg, filterList):
+        ''' do extra filtering (devel etc) '''
+
+        for filter in filterList:
+            if filter in (FILTER_INSTALLED, FILTER_NOT_INSTALLED):
+                continue
+            elif filter in (FILTER_DEVELOPMENT, FILTER_NOT_DEVELOPMENT):
+                if not self._do_devel_filtering(flt, pkg):
+                    return False
+        return True
+
+    def _do_devel_filtering(self, flt, pkg):
+        isDevel = False
+        if flt == FILTER_DEVELOPMENT:
+            wantDevel = True
+        else:
+            wantDevel = False
+        #
+        # TODO: Add Devel detection Code here.Set isDevel = True, if it is a
+        #       devel app.
+        #
+        regex =  re.compile(r'(:devel)')
+        if regex.search(pkg.name):
+            isDevel = True
+        #
+        #
+        return isDevel == wantDevel
+
+    def _findPackage(self, id):
+        '''
+        find a package based on a package id (name;version;arch;repoid)
+        '''
+        name, version, flavor = self.get_package_from_id(id)
+        troveTuple = (name, version, flavor)
+        installed = self.check_installed(troveTuple)
+        return name, version, flavor, installed
+
+    def repo_set_data(self, repoid, parameter, value):
+        '''
+        Implement the {backend}-repo-set-data functionality
+        '''
+        pass
+
+    def get_repo_list(self, filters):
+        '''
+        Implement the {backend}-get-repo-list functionality
+        '''
+        pass
+
+    def repo_enable(self, repoid, enable):
+        '''
+        Implement the {backend}-repo-enable functionality
+        '''
+
+
+class Cache(object):
+    # Database name and path
+    dbName = 'cache.db'
+    # Someday we might want to make this writable by users
+    #if 'HOME' in os.environ:
+    #    dbPath = '%s/.conary/cache/data/' % os.environ['HOME']
+    #else:
+    #    dbPath = '/var/cache/conary/'
+    dbPath = '/var/cache/conary/'
+    jobPath = dbPath + 'jobs'
+
+    """ Class to retrieve and cache package information from label. """
+    def __init__(self):
+        if not os.path.isdir(self.dbPath):
+            os.makedirs(self.dbPath)
+        if not os.path.isdir(self.jobPath):
+            os.mkdir(self.jobPath)
+
+        self.conn = dbstore.connect(os.path.join(self.dbPath, self.dbName))
+        self.cursor = self.conn.cursor()
+        self.cursor.execute("PRAGMA count_changes=0", start_transaction=False)
+
+        if os.path.isfile(os.path.join(self.dbPath, self.dbName)):
+            self._validate_tables()
+
+    def _validate_tables(self):
+        """ Validates that all tables are up to date. """
+        backend = PackageKitBaseBackend(self)
+        stmt = ("select tbl_name from sqlite_master "
+                "where type = 'table' and tbl_name like 'conary_%'")
+        self.cursor.execute(stmt)
+        # List of all tables with names that start with "conary_"
+        tbllist = self.cursor.fetchall()
+        if tbllist == [('conary_packages',)]:
+            self.cursor.execute('DROP TABLE conary_packages')
+            self.conn.commit()
+            tbllist = []
+        if tbllist != []:
+            return True
+            #print "Verified packages table"
+        else:
+            #print "Creating packages table..."
+            # Create all tables if database is empty
+            if len(tbllist) == 0:
+                self._create_database()
+                backend.status(STATUS_WAIT)
+                self.populate_database()
+                return True
+
+    def _getJobCachePath(self, applyList):
+        from conary.lib import sha1helper
+        applyStr = '\0'.join(['%s=%s[%s]--%s[%s]%s' % (x[0], x[1][0], x[1][1], x[2][0], x[2][1], x[3]) for x in applyList])
+        return self.jobPath + '/' + sha1helper.sha1ToString(sha1helper.sha1String(applyStr))
+
+    def checkCachedUpdateJob(self, applyList):
+        jobPath = self._getJobCachePath(applyList)
+        if os.path.exists(jobPath):
+            return jobPath
+
+    def cacheUpdateJob(self, applyList, updJob):
+        jobPath = self._getJobCachePath(applyList)
+        if os.path.exists(jobPath):
+            from conary.lib import util
+            util.rmtree(jobPath)
+        os.mkdir(jobPath)
+        updJob.freeze(jobPath)
+
+    def conaryquery(self):
+        self.cfg = conarycfg.ConaryConfiguration()
+        self.client = conaryclient.ConaryClient(self.cfg)
+        self.cfg.readFiles()
+        self.cfg.initializeFlavors()
+        self.repos = self.client.getRepos()
+        self.db = conaryclient.ConaryClient(self.cfg).db
+
+        troves = queryrep.getTrovesToDisplay(self.repos, None, None, None,
+            queryrep.VERSION_FILTER_LEAVES, queryrep.FLAVOR_FILTER_BEST,
+            self.cfg.installLabelPath, self.cfg.flavor, None)
+
+        packages = []
+
+        for troveTuple in troves:
+            # troveTuple is probably what we want to store in the cachedb
+            # Then use the below methods to present them in a nicer fashion
+            if troveTuple[0].endswith(':source'):
+                continue
+            if ":" in troveTuple[0]:
+                fragments = troveTuple[0].split(":")
+                trove = fragments[0]
+                component = fragments[1]
+            else:
+                trove = troveTuple[0]
+                component = ""
+
+            installed = 0
+            flavor = troveTuple[2].freeze()
+            fullVersion = troveTuple[1].freeze()
+            label = str(troveTuple[1].branch().label())
+            description = ""
+            category = ""
+            packagegroup = ""
+            size = ""
+            packages.append([trove, component, fullVersion, label, flavor,
+                             description, category, packagegroup, size])
+
+        return packages
+
+    def connect_memory(self):
+        return sqlite.connect(':memory:')
+
+    def cursor(self, connection):
+        return connection.cursor()
+
+    def _create_database(self):
+        #FIXME: delete the category column. it's not useful
+
+        """ Creates a blank database. """
+        sql = '''CREATE TABLE conary_packages (
+            packageId INTEGER,
+            trove text,
+            component text,
+            version text,
+            label text,
+            flavor text,
+            description text,
+            category text,
+            packagegroup text,
+            size text)'''
+
+        self.cursor.execute(sql)
+
+        sql = '''CREATE TABLE conary_categories (
+            categoryId INTEGER,
+            categoryName text)'''
+
+        self.cursor.execute(sql)
+
+        sql = '''CREATE TABLE conary_category_package_map (
+            categoryId INTEGER,
+            packageId INTEGER)'''
+
+        self.cursor.execute(sql)
+
+        sql = '''CREATE TABLE conary_licenses (
+            licenseId INTEGER,
+            licenseName text)'''
+
+        self.cursor.execute(sql)
+
+        sql = '''CREATE TABLE conary_license_package_map (
+            licenseId INTEGER,
+            packageId INTEGER)'''
+
+        self.cursor.execute(sql)
+
+        #self.conn.createIndex('conary_catagories', 'conary_category_name_idx', ['categoryName'])
+        #self.conn.createIndex('conary_catagories', 'conary_category_id_idx', ['categoryId'])
+
+
+
+    def commit(self):
+        self.cursor.commit()
+
+    def getTroves(self, label=None):
+        """
+        Returns all troves for now.  Add filtering capability.
+        """
+        stmt = ("select distinct trove, version, flavor, description, "
+                "category, packagegroup, size from conary_packages")
+
+        self.cursor.execute(stmt)
+        return self.cursor.fetchall()
+
+    def search(self, package, fullVersion=None):
+        """
+        Returns all troves for now.  Add filtering capability.
+        """
+        stmt = ("select distinct trove, version, flavor, description, "
+                "category, packagegroup, size from conary_packages")
+
+        if package and fullVersion:
+            stmt = ("select distinct trove, version, flavor from "
+                    "conary_packages where trove ='%s' and version = '%s'"
+                    % (package, fullVersion))
+        elif package:
+            stmt += (" where trove like '%%%s%%' and component = '' order by "
+                     "version desc" % package)
+
+        try:
+            self.cursor.execute(stmt)
+            results = self.cursor.fetchall()
+            return results
+        except Exception, e:
+            print str(e)
+            return None
+
+    def searchByGroups(self, groups):
+        """
+        Returns all troves for given groups. (trove, version, flavor)
+        Needs filtering capability.
+        ['all'] means all packages
+        FIXME: No filtering done on group text - SQL injection
+        """
+        if not groups:
+            groups = ["all"]
+
+        if "all" in groups:
+            stmt = ("SELECT DISTINCT CP.trove, CP.version, CP.flavor, CC.categoryName"
+                    "           FROM conary_packages CP, conary_categories CC, conary_category_package_map CCMap"
+                    "          WHERE CCMap.packageId = CP.packageId"
+                    "            AND CCMap.categoryId = CC.categoryId"
+                    "       GROUP BY CP.trove, CP.version, CP.flavor"
+                    "       ORDER BY CP.trove, CP.version DESC, CP.flavor")
+        else:
+            group_string = ", ".join(groups)
+            stmt = ("SELECT DISTINCT CP.trove, CP.version, CP.flavor, CC.categoryName"
+                    "           FROM conary_packages CP, conary_categories CC, conary_category_package_map CCMap"
+                    "          WHERE CC.categoryName IN (%s)"
+                    "            AND CCMap.packageId = CP.packageId"
+                    "            AND CCMap.categoryId = CC.categoryId"
+                    "       GROUP BY CP.trove, CP.version, CP.flavor"
+                    "       ORDER BY CP.trove, CP.version DESC, CP.flavor" % group_string)
+
+        try:
+            self.cursor.execute(stmt)
+            return self.cursor.fetchall()
+        except Exception, e:
+            print str(e)
+            return None
+
+    def _insert(self, trove):
+        """
+        Insert trove into database.
+        """
+        res = self.cursor.execute("SELECT COALESCE(max(packageId), 0) + 1 FROM conary_packages")
+        pkgId = res.fetchone()[0] + 1
+        trove = [pkgId] + trove[:]
+
+        values = [str(field) for field in trove]
+        cols = ", ".join("?" * len(trove))
+        sql = "INSERT INTO conary_packages VALUES (%s)" % cols
+
+        try:
+            self.cursor.execute(sql, values)
+            self.conn.commit()
+        except Exception, e:
+            print str(e)
+
+    def _clear_table(self, tableName='conary_packages'):
+        """
+        Deletes * records from table.
+        """
+        stmt = "DELETE FROM %s" % tableName
+        try:
+            self.cursor.execute(stmt)
+        except dbstore.sqlerrors.InvalidTable:
+            pass
+
+    def populate_database(self):
+        packages = self.conaryquery()
+        # Clear table first
+        for tblName in ('conary_packages', 'conary_category_package_map',
+                'conary_categories'):
+            self._clear_table(tblName)
+        for package in packages:
+            self._insert(package)
+
+    def _addPackageCategory(self, trv, category):
+        res = self.cursor.execute( \
+                'SELECT packageId FROM conary_packages WHERE trove=? and version=? and flavor = ?', trv.getName(), trv.getVersion().freeze(), trv.getFlavor().freeze())
+        res = res.fetchone()
+        if res:
+            # we have a packageID
+            pkgId = res[0]
+        else:
+            # we really should have had this data
+            raise RuntimeError
+
+        # now look up/make the categoryId
+        res = self.cursor.execute('SELECT categoryId FROM conary_categories WHERE categoryName=?', category)
+        res = res.fetchone()
+        if not res:
+            res = self.cursor.execute('SELECT COALESCE(MAX(categoryId), 0) + 1 FROM conary_categories')
+            catId = res.fetchone()[0]
+            self.cursor.execute('INSERT INTO conary_categories VALUES(?, ?)',
+                    catId, category)
+        else:
+            catId = category
+
+        self.cursor.execute("INSERT INTO conary_category_package_map VALUES(?, ?)", catId, pkgId)
+        self.conn.commit()
+
+    def populate_metadata(self, csList):
+        for cs in csList:
+            for troveCS in cs.iterNewTroveList():
+                trv = trove.Trove(troveCS)
+                if ':' in trv.getName():
+                    # components aren't tracked at the moment
+                    continue
+                metadata = trv.getMetadata()
+                categories = metadata.get('categories', [])
+                for category in categories:
+                    self._addPackageCategory(trv, category)
+                #licenses = metadata.get('licenses', [])
+                #for license in licenses:
+                #    self._addPackageLicense(trv, license)
+
+def main():
+    backend = PackageKitYumBackend('', lock=True)
+    backend.dispatcher(sys.argv[1:])
+
+if __name__ == "__main__":
+    main()
diff --git a/backends/conary/conaryCallback.py b/backends/conary/conaryCallback.py
new file mode 100644
index 0000000..7700853
--- /dev/null
+++ b/backends/conary/conaryCallback.py
@@ -0,0 +1,124 @@
+#!/usr/bin/python
+# Licensed under the GNU General Public License Version 2
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# Copyright (C) 2007 Elliot Peele <elliot at bentlogic.net>
+# Copyright (C) 2008 Richard Hughes <richard at hughsie.com>
+
+from conary import callbacks
+from packagekit.backend import *
+
+class UpdateCallback(callbacks.UpdateCallback):
+    def resolvingDependencies(self):
+        #self.backend.status('Resolving Dependencies')
+        self.backend.status(STATUS_DEP_RESOLVE)
+
+    def creatingRollback(self):
+        #self.backend.status('Creating Rollback')
+        self.backend.status(STATUS_ROLLBACK)
+
+    def committingTransaction(self):
+        #self.backend.status('Committing Transaction')
+        self.backend.status(STATUS_COMMIT)
+
+    def downloadingFileContents(self, got, need):
+        #self.backend.status('Downloading files for changeset')
+        self.backend.status(STATUS_DOWNLOAD)
+
+    def downloadingChangeSet(self, got, need):
+        self.backend.status(STATUS_DOWNLOAD)
+
+    def requestingFileContents(self):
+        #self.backend.status('Requesting File Contents')
+        self.backend.status(STATUS_REQUEST)
+
+    def requestingChangeSet(self):
+        #self.backend.status('Requesting Changeset')
+        self.backend.status(STATUS_REQUEST)
+
+    def done(self):
+        #self.backend.status('Done')
+        pass
+
+    def preparingUpdate(self, troveNum, troveCount, add=0):
+        if not self.currentJob or len(self.currentJob) == 0 or troveNum > troveCount:
+            return
+
+        if troveNum > 0 and troveCount > 0:
+            sub_percent = (add + troveNum) / (2 * float(troveCount)) * 100
+            self.backend.sub_percentage(sub_percent)
+
+            if self.smallUpdate:
+                self.backend.percentage(sub_percent)
+
+        if troveNum != 0:
+            troveNum -= 1
+
+        job = self.currentJob[troveNum]
+        name = job[0]
+        oldVersion, oldFlavor = job[1]
+        newVersion, newFlavor = job[2]
+
+        if oldVersion and newVersion:
+            self.backend.status(STATUS_UPDATE)
+            id = self.backend.get_package_id(name, newVersion, newFlavor)
+            self.backend.package(id, INFO_UPDATING, '')
+        elif oldVersion and not newVersion:
+            self.backend.status(STATUS_REMOVE)
+            id = self.backend.get_package_id(name, oldVersion, oldFlavor)
+            self.backend.package(id, INFO_REMOVING, '')
+        elif not oldVersion and newVersion:
+            self.backend.status(STATUS_INSTALL)
+            id = self.backend.get_package_id(name, newVersion, newFlavor)
+            self.backend.package(id, INFO_INSTALLING, '')
+
+
+    def creatingDatabaseTransaction(self, troveNum, troveCount):
+        self.preparingUpdate(troveNum, troveCount, add=troveCount)
+
+    def setChangesetHunk(self, num, total):
+        pass
+
+    def setUpdateHunk(self, hunk, hunkCount):
+        if hunk > 0 and hunkCount > 0:
+            percentage = hunk / float(hunkCount) * 100.0
+            self.backend.percentage(percentage)
+        else:
+            self.smallUpdate = True
+
+    def setUpdateJob(self, job):
+        self.currentJob = job
+
+    def updateDone(self):
+        self.currentJob = None
+
+    def tagHandlerOutput(self, tag, msg, stderr = False):
+        pass
+
+    def troveScriptOutput(self, typ, msg):
+        pass
+
+    def troveScriptFailure(self, typ, errcode):
+        pass
+
+    def __init__(self, backend, cfg=None):
+        callbacks.UpdateCallback.__init__(self)
+        if cfg:
+            self.setTrustThreshold(cfg.trustThreshold)
+
+        self.backend = backend
+        self.currentJob = None
+        self.smallUpdate = False
diff --git a/backends/conary/helpers/Makefile.am b/backends/conary/helpers/Makefile.am
deleted file mode 100644
index 54b0691..0000000
--- a/backends/conary/helpers/Makefile.am
+++ /dev/null
@@ -1,30 +0,0 @@
-
-helperdir = $(datadir)/PackageKit/helpers/conary
-
-NULL =
-
-dist_helper_DATA = 			\
-	search-name.py			\
-	search-details.py		\
-	get-depends.py			\
-	get-requires.py			\
-	get-updates.py			\
-	get-update-detail.py		\
-	install-packages.py		\
-	update-packages.py		\
-	refresh-cache.py		\
-	remove-packages.py		\
-	resolve.py			\
-	update-system.py		\
-	get-details.py			\
-	get-files.py			\
-	conaryBackend.py		\
-	conaryCallback.py		\
-	$(NULL)
-
-install-data-hook:
-	chmod a+rx $(DESTDIR)$(helperdir)/*.py
-
-clean-local :
-	rm -f *~
-
diff --git a/backends/conary/helpers/conaryBackend.py b/backends/conary/helpers/conaryBackend.py
deleted file mode 100644
index 91c0ed2..0000000
--- a/backends/conary/helpers/conaryBackend.py
+++ /dev/null
@@ -1,981 +0,0 @@
-#
-# Copyright (C) 2007 Ken VanDine <ken at vandine.org>
-#
-# Licensed under the GNU General Public License Version 2
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
-
-import sys
-import os
-
-from conary import errors
-from conary.deps import deps
-from conary import conarycfg, conaryclient
-from conary import dbstore, queryrep, versions, updatecmd
-from conary.local import database
-from conary import trove
-
-from packagekit.backend import *
-from packagekit.package import *
-from conaryCallback import UpdateCallback
-
-pkpackage = PackagekitPackage()
-
-groupMap = {
-    '2DGraphics'          : GROUP_GRAPHICS,
-    'Accessibility'       : GROUP_ACCESSIBILITY,
-    'AdvancedSettings'    : GROUP_ADMIN_TOOLS,
-    'Application'         : GROUP_OTHER,
-    'ArcadeGame'          : GROUP_GAMES,
-    'Audio'               : GROUP_MULTIMEDIA,
-    'AudioVideo'          : GROUP_MULTIMEDIA,
-    'BlocksGame'          : GROUP_GAMES,
-    'BoardGame'           : GROUP_GAMES,
-    'Calculator'          : GROUP_ACCESSORIES,
-    'Calendar'            : GROUP_ACCESSORIES,
-    'CardGame'            : GROUP_GAMES,
-    'Compiz'              : GROUP_SYSTEM,
-    'ContactManagement'   : GROUP_ACCESSORIES,
-    'Core'                : GROUP_SYSTEM,
-    'Database'            : GROUP_SERVERS,
-    'DesktopSettings'     : GROUP_ADMIN_TOOLS,
-    'Development'         : GROUP_PROGRAMMING,
-    'Email'               : GROUP_INTERNET,
-    'FileTransfer'        : GROUP_INTERNET,
-    'Filesystem'          : GROUP_SYSTEM,
-    'GNOME'               : GROUP_DESKTOP_GNOME,
-    'GTK'                 : GROUP_DESKTOP_GNOME,
-    'GUIDesigner'         : GROUP_PROGRAMMING,
-    'Game'                : GROUP_GAMES,
-    'Graphics'            : GROUP_GRAPHICS,
-    'HardwareSettings'    : GROUP_ADMIN_TOOLS,
-    'IRCClient'           : GROUP_INTERNET,
-    'InstantMessaging'    : GROUP_INTERNET,
-    'LogicGame'           : GROUP_GAMES,
-    'Monitor'             : GROUP_ADMIN_TOOLS,
-    'Music'               : GROUP_MULTIMEDIA,
-    'Network'             : GROUP_INTERNET,
-    'News'                : GROUP_INTERNET,
-    'Office'              : GROUP_OFFICE,
-    'P2P'                 : GROUP_INTERNET,
-    'PackageManager'      : GROUP_ADMIN_TOOLS,
-    'Photography'         : GROUP_MULTIMEDIA,
-    'Player'              : GROUP_MULTIMEDIA,
-    'Presentation'        : GROUP_OFFICE,
-    'Publishing'          : GROUP_OFFICE,
-    'RasterGraphics'      : GROUP_GRAPHICS,
-    'Security'            : GROUP_SECURITY,
-    'Settings'            : GROUP_ADMIN_TOOLS,
-    'Spreadsheet'         : GROUP_OFFICE,
-    'System'              : GROUP_SYSTEM,
-    'Telephony'           : GROUP_COMMUNICATION,
-    'TerminalEmulator'    : GROUP_ACCESSORIES,
-    'TextEditor'          : GROUP_ACCESSORIES,
-    'Utility'             : GROUP_ACCESSORIES,
-    'VectorGraphics'      : GROUP_GRAPHICS,
-    'Video'               : GROUP_MULTIMEDIA,
-    'Viewer'              : GROUP_MULTIMEDIA,
-    'WebBrowser'          : GROUP_INTERNET,
-    'WebDevelopment'      : GROUP_PROGRAMMING,
-    'WordProcessor'       : GROUP_OFFICE
-}
-
-revGroupMap = {}
-
-for (con_cat, pk_group) in groupMap.items():
-    if revGroupMap.has_key(pk_group):
-        revGroupMap[pk_group].append(con_cat)
-    else:
-        revGroupMap[pk_group] = [con_cat]
-       
-#from conary.lib import util
-#sys.excepthook = util.genExcepthook()
-
-def ExceptionHandler(func):
-    def display(error):
-        return str(error).replace('\n', ' ')
-
-    def wrapper(self, *args, **kwargs):
-        try:
-            return func(self, *args, **kwargs)
-        #except Exception:
-        #    raise
-        except conaryclient.NoNewTrovesError:
-            return
-        except conaryclient.DepResolutionFailure, e:
-            self.error(ERROR_DEP_RESOLUTION_FAILED, display(e), exit=True)
-        except conaryclient.UpdateError, e:
-            # FIXME: Need a enum for UpdateError
-            self.error(ERROR_UNKNOWN, display(e), exit=True)
-        except Exception, e:
-            self.error(ERROR_UNKNOWN, display(e), exit=True)
-    return wrapper
-
-class PackageKitConaryBackend(PackageKitBaseBackend):
-    # Packages there require a reboot
-    rebootpkgs = ("kernel", "glibc", "hal", "dbus")
-
-    def __init__(self, args):
-        PackageKitBaseBackend.__init__(self, args)
-
-        self.cfg = conarycfg.ConaryConfiguration(True)
-        self.cfg.initializeFlavors()
-        self.cfg.autoResolve = True
-        self.cfg.keepRequired = True
-
-        self.client = conaryclient.ConaryClient(self.cfg)
-        self.callback = UpdateCallback(self, self.cfg)
-        self.client.setUpdateCallback(self.callback)
-
-    def _freezeData(self, version, flavor):
-        frzVersion = version.freeze()
-        frzFlavor = flavor.freeze()
-        return ','.join([frzVersion, frzFlavor])
-
-    def _thawData(self, data):
-        frzVersion, frzFlavor = data.split(',')
-        version = versions.ThawVersion(frzVersion)
-        flavor = deps.ThawFlavor(frzFlavor)
-        return version, flavor
-
-    def _get_arch(self, flavor):
-        isdep = deps.InstructionSetDependency
-        arches = [ x.name for x in flavor.iterDepsByClass(isdep) ]
-        if not arches:
-            arches = [ 'noarch' ]
-        return ','.join(arches)
-
-    @ExceptionHandler
-    def get_package_id(self, name, versionObj, flavor):
-        version = versionObj.trailingRevision()
-        arch = self._get_arch(flavor)
-        data = self._freezeData(versionObj, flavor)
-        return pkpackage.get_package_id(name, version, arch, data)
-
-    @ExceptionHandler
-    def get_package_from_id(self, id):
-        name, verString, archString, data = \
-            pkpackage.get_package_from_id(id)
-
-        version, flavor = self._thawData(data)
-
-        return name, version, flavor
-
-    def _do_search(self, searchlist, filters):
-        fltlist = filters.split(';')
-        troveSpecs = [ updatecmd.parseTroveSpec(searchlist,
-                                                allowEmptyName=False) ]
-        # get a hold of cached data
-        cache = Cache()
-
-        try:
-            troveTupleList = cache.search(searchlist)
-        finally:
-            pass
-
-        # Remove dupes
-        tempDict = {}
-        try:
-            for element in troveTupleList:
-                tempDict[element] = None
-        except TypeError:
-            del tempDict  # move on to the next method
-        else:
-            troveTupleList = tempDict.keys()
-
-        # Get the latest first
-        troveTupleList.sort()
-        troveTupleList.reverse()
-
-        for troveTuple in troveTupleList:
-            troveTuple = tuple([item.encode('UTF-8') for item in troveTuple])
-            name = troveTuple[0]
-            version = versions.ThawVersion(troveTuple[1])
-            flavor = deps.ThawFlavor(troveTuple[2])
-            id = self.get_package_id(name, version, flavor)
-            summary = self._get_metadata(id, 'shortDesc') or " "
-            troveTuple = tuple([name, version, flavor])
-            installed = self.check_installed(troveTuple)
-
-            if self._do_filtering(name,fltlist,installed):
-                self.package(id, installed, summary)
-
-    def _get_update(self, applyList, cache=True):
-        updJob = self.client.newUpdateJob()
-        suggMap = self.client.prepareUpdateJob(updJob, applyList)
-        if cache:
-            Cache().cacheUpdateJob(applyList, updJob)
-        return updJob, suggMap
-
-    def _do_update(self, applyList):
-        jobPath = Cache().checkCachedUpdateJob(applyList)
-        if jobPath:
-            updJob = self.client.newUpdateJob()
-            try:
-                updJob.thaw(jobPath)
-            except IOError, err:
-                updJob = None
-        else:
-            updJob = self._get_update(applyList, cache=False)
-        self.allow_cancel(False)
-        restartDir = self.client.applyUpdateJob(updJob)
-        return updJob
-
-    def _get_package_update(self, name, version, flavor):
-        if name.startswith('-'):
-            applyList = [(name, (version, flavor), (None, None), False)]
-        else:
-            applyList = [(name, (None, None), (version, flavor), True)]
-        return self._get_update(applyList)
-
-    def _do_package_update(self, name, version, flavor):
-        if name.startswith('-'):
-            applyList = [(name, (version, flavor), (None, None), False)]
-        else:
-            applyList = [(name, (None, None), (version, flavor), True)]
-        return self._do_update(applyList)
-
-    @ExceptionHandler
-    def resolve(self, filter, package):
-        self.allow_cancel(True)
-        self.percentage(None)
-        self.status(STATUS_INFO)
-        self._do_search(package, filter)
-
-    @ExceptionHandler
-    def check_installed(self, troveTuple):
-        db = conaryclient.ConaryClient(self.cfg).db
-        try:
-            troveTuple = troveTuple[0], troveTuple[1], troveTuple[2]
-            localInstall = db.findTrove(None, troveTuple)
-            installed = INFO_INSTALLED
-        except:
-            installed = INFO_AVAILABLE
-        return installed
-
-    @ExceptionHandler
-    def search_group(self, filters, key):
-        '''
-        Implement the {backend}-search-name functionality
-        FIXME: Ignoring filters for now.
-        '''
-        self.allow_cancel(True)
-        self.percentage(None)
-        self.status(STATUS_QUERY)
-
-        fltlist = filters.split(';')
-        cache = Cache()
-
-        try:
-            troveTupleList = cache.searchByGroups(revGroupMap[key])
-        finally:
-            # FIXME: Really need to send an error here
-            pass
-
-        troveTupleList.sort()
-        troveTupleList.reverse()
-        
-        for troveTuple in troveTupleList:
-            troveTuple = tuple([item.encode('UTF-8') for item in troveTuple[0:2]])
-            name = troveTuple[0]
-            version = versions.ThawVersion(troveTuple[1])
-            flavor = deps.ThawFlavor(troveTuple[2])
-            id = self.get_package_id(name, version, flavor)
-            summary = self._get_metadata(id, 'shortDesc') or " "
-            category = troveTuple[3][0]
-            category = category.encode('UTF-8')
-            troveTuple = tuple([name, version, flavor])
-            installed = self.check_installed(troveTuple)
-            
-            if self._do_filtering(name,fltlist,installed):
-                self.package(id, installed, summary)
-
-    @ExceptionHandler
-    def search_name(self, options, searchlist):
-        '''
-        Implement the {backend}-search-name functionality
-        '''
-        self.allow_cancel(True)
-        self.percentage(None)
-        self.status(STATUS_QUERY)
-
-        self._do_search(searchlist, options)
-
-    def search_details(self, opt, key):
-        pass
-
-    def get_requires(self, filters, package_id):
-        pass
-
-    @ExceptionHandler
-    def get_depends(self, filters, package_id):
-        name, version, flavor, installed = self._findPackage(package_id)
-
-        if name:
-            if installed == INFO_INSTALLED:
-                self.error(ERROR_PACKAGE_ALREADY_INSTALLED, 'Package already installed')
-
-            else:
-                updJob, suggMap = self._get_package_update(name, version,
-                                                           flavor)
-                for what, need in suggMap:
-                    id = self.get_package_id(need[0], need[1], need[2])
-                    depInstalled = self.check_installed(need[0])
-                    if depInstalled == INFO_INSTALLED:
-                        self.package(id, INFO_INSTALLED, '')
-                    else:
-                        self.package(id, INFO_AVAILABLE, '')
-        else:
-            self.error(ERROR_PACKAGE_ALREADY_INSTALLED, 'Package was not found')
-
-    @ExceptionHandler
-    def get_files(self, package_id):
-        self.allow_cancel(True)
-        self.percentage(None)
-        self.status(STATUS_INFO)
-        def _get_files(troveSource, n, v, f):
-            files = []
-            troves = [(n, v, f)]
-            trv = troveSource.getTrove(n, v, f)
-            troves.extend([ x for x in trv.iterTroveList(strongRefs=True)
-                                if troveSource.hasTrove(*x)])
-            for n, v, f in troves:
-                for (pathId, path, fileId, version, file) in \
-                    troveSource.iterFilesInTrove(n, v, f, sortByPath = True,
-                                                 withFiles = True):
-                    files.append(path)
-            return files
-
-        name, version, flavor, installed = self._findPackage(package_id)
-
-        if installed == INFO_INSTALLED:
-            files = _get_files(self.client.db, name, version, flavor)
-        else:
-            files = _get_files(self.client.repos, name, version, flavor)
-
-        self.files(package_id, ';'.join(files))
-
-    @ExceptionHandler
-    def update_system(self):
-        self.allow_cancel(True)
-        updateItems = self.client.fullUpdateItemList()
-        applyList = [ (x[0], (None, None), x[1:], True) for x in updateItems ]
-        updJob, suggMap = self._do_update(applyList)
-
-    @ExceptionHandler
-    def refresh_cache(self):
-        self.percentage()
-        self.status(STATUS_REFRESH_CACHE)
-        cache = Cache()
-        cache.populate_database()
-
-    @ExceptionHandler
-    def update(self, packages):
-        '''
-        Implement the {backend}-update functionality
-        '''
-        self.allow_cancel(True);
-        self.percentage(0)
-        self.status(STATUS_RUNNING)
-
-        for package in packages.split(" "):
-            name, version, flavor, installed = self._findPackage(package)
-            if name:
-                self._do_package_update(name, version, flavor)
-            else:
-                self.error(ERROR_PACKAGE_ALREADY_INSTALLED, 'No available updates')
-
-    @ExceptionHandler
-    def update_packages(self, package_ids):
-        '''
-        Implement the {backend}-{install,update}-packages functionality
-        '''
-        for package_id in package_ids.split('%'):
-            name, version, flavor, installed = self._findPackage(package_id)
-
-            self.allow_cancel(True)
-            self.percentage(0)
-            self.status(STATUS_RUNNING)
-
-            if name:
-                if installed == INFO_INSTALLED:
-                    self.error(ERROR_PACKAGE_ALREADY_INSTALLED,
-                        'Package already installed')
-
-                self.status(INFO_INSTALLING)
-                self._get_package_update(name, version, flavor)
-                self._do_package_update(name, version, flavor)
-            else:
-                self.error(ERROR_PACKAGE_ALREADY_INSTALLED, 'Package was not found')
-
-    @ExceptionHandler
-    def remove_packages(self, allowDeps, package_ids):
-        '''
-        Implement the {backend}-remove-packages functionality
-        '''
-        self.allow_cancel(True)
-        self.percentage(0)
-        self.status(STATUS_RUNNING)
-
-        for package_id in package_ids.split('%'):
-            name, version, flavor, installed = self._findPackage(package_id)
-
-            if name:
-                if not installed == INFO_INSTALLED:
-                    self.error(ERROR_PACKAGE_NOT_INSTALLED, 'The package %s is not installed' % name)
-
-                name = '-%s' % name
-                self.status(INFO_REMOVING)
-                self._get_package_update(name, version, flavor)
-                self._do_package_update(name, version, flavor)
-            else:
-                self.error(ERROR_PACKAGE_ALREADY_INSTALLED, 'The package was not found')
-
-    def _get_metadata(self, id, field):
-        '''
-        Retrieve metadata from the repository and return result
-        field should be one of:
-                bibliography
-                url
-                notes
-                crypto
-                licenses
-                shortDesc
-                longDesc
-                categories
-        '''
-
-        self.allow_cancel(True)
-        self.percentage(None)
-        self.status(STATUS_QUERY)
-
-        n, v, f = self.get_package_from_id(id)
-
-        trvList = self.client.repos.findTrove(self.cfg.installLabelPath,
-                                     (n, v, f),
-                                     defaultFlavor = self.cfg.flavor)
-
-        troves = self.client.repos.getTroves(trvList, withFiles=False)
-        result = ''
-        for trove in troves:
-            result = trove.getMetadata()[field]
-        return result
-
-    def _format_list(self,lst):
-        """
-        Convert a multi line string to a list separated by ';'
-        """
-        if lst:
-            return ";".join(lst)
-        else:
-            return ""
-
-    def _get_update_extras(self,id):
-        notice = self._get_metadata(id, 'notice') or " "
-        urls = {'jira':[], 'cve' : [], 'vendor': []}
-        if notice:
-            # Update Details
-            desc = notice['description']
-            # Update References (Jira,CVE ...)
-            refs = notice['references']
-            if refs:
-                for ref in refs:
-                    typ = ref['type']
-                    href = ref['href']
-                    title = ref['title']
-                    if typ in ('jira','cve') and href != None:
-                        if title == None:
-                            title = ""
-                        urls[typ].append("%s;%s" % (href,title))
-                    else:
-                        urls['vendor'].append("%s;%s" % (ref['href'],ref['title']))
-
-            # Reboot flag
-            if notice.get_metadata().has_key('reboot_suggested') and notice['reboot_suggested']:
-                                reboot = 'system'
-            else:
-                reboot = 'none'
-            return self._format_str(desc),urls,reboot
-        else:
-            return "",urls,"none"
-
-    def _check_for_reboot(self, name):
-        if name in self.rebootpkgs:
-            self.require_restart(RESTART_SYSTEM,"")
-
-    @ExceptionHandler
-    def get_update_detail(self,id):
-        '''
-        Implement the {backend}-get-update_detail functionality
-        '''
-        self.allow_cancel(True)
-        self.percentage(None)
-        self.status(STATUS_INFO)
-        name, version, flavor, installed = self._findPackage(id)
-        #update = self._get_updated(pkg)
-        update = ""
-        obsolete = ""
-        #desc,urls,reboot = self._get_update_extras(id)
-        #cve_url = self._format_list(urls['cve'])
-        cve_url = ""
-        #bz_url = self._format_list(urls['jira'])
-        bz_url = ""
-        #vendor_url = self._format_list(urls['vendor'])
-        vendor_url = ""
-        reboot = "none"
-        desc = self._get_metadata(id, 'longDesc') or " "
-        self.update_detail(id,update,obsolete,vendor_url,bz_url,cve_url,reboot,desc)
-
-    @ExceptionHandler
-    def get_details(self, id):
-        '''
-        Print a detailed description for a given package
-        '''
-        self.allow_cancel(True)
-        self.percentage(None)
-        self.status(STATUS_INFO)
-
-        name, version, flavor, installed = self._findPackage(id)
-
-        if name:
-            shortDesc = self._get_metadata(id, 'shortDesc') or name
-            longDesc = self._get_metadata(id, 'longDesc') or ""
-            url = "http://www.foresightlinux.org/packages/" + name + ".html"
-            categories = self._get_metadata(id, 'categories') or "unknown"
-
-            # Package size goes here, but I don't know how to find that for conary packages.
-            self.details(id, None,  categories, longDesc, url, 0)
-        else:
-            self.error(ERROR_PACKAGE_NOT_FOUND,'Package was not found')
-
-    def _show_package(self,name, version, flavor, status):
-        '''  Show info about package'''
-        id = self.get_package_id(name, version, flavor)
-        summary = self._get_metadata(id, 'shortDesc') or ""
-        self.package(id, status, summary)
-
-    def _get_status(self, notice):
-        # We need to figure out how to get this info, this is a place holder
-        #ut = notice['type']
-        # TODO : Add more types to check
-        #if ut == 'security':
-        #    return INFO_SECURITY
-        #else:
-        #    return INFO_NORMAL
-        return INFO_NORMAL
-
-    @ExceptionHandler
-    def get_updates(self, filter):
-        self.allow_cancel(True)
-        self.percentage(None)
-        self.status(STATUS_INFO)
-
-        updateItems = self.client.fullUpdateItemList()
-        applyList = [ (x[0], (None, None), x[1:], True) for x in updateItems ]
-        updJob, suggMap = self._get_update(applyList)
-
-        jobLists = updJob.getJobs()
-
-        totalJobs = len(jobLists)
-        for num, job in enumerate(jobLists):
-            status = '2'
-            name = job[0][0]
-
-            # On an erase display the old version/flavor information.
-            version = job[0][2][0]
-            if version is None:
-                version = job[0][1][0]
-
-            flavor = job[0][2][1]
-            if flavor is None:
-                flavor = job[0][1][1]
-
-            troveTuple = []
-            troveTuple.append(name)
-            troveTuple.append(version)
-            installed = self.check_installed(troveTuple)
-            self._show_package(name, version, flavor, INFO_NORMAL)
-
-    def _do_filtering(self, pkg, filterList, installed):
-        ''' Filter the package, based on the filter in filterList '''
-        # do we print to stdout?
-        do_print = False;
-        if filterList == ['none']: # 'none' = all packages.
-            return True
-        elif FILTER_INSTALLED in filterList and installed == INFO_INSTALLED:
-            do_print = True
-        elif FILTER_NOT_INSTALLED in filterList and installed == INFO_AVAILABLE:
-            do_print = True
-
-        if len(filterList) == 1: # Only one filter, return
-            return do_print
-
-        if do_print:
-            return self._do_extra_filtering(pkg,filterList)
-        else:
-            return do_print
-
-    def _do_extra_filtering(self, pkg, filterList):
-        ''' do extra filtering (devel etc) '''
-
-        for filter in filterList:
-            if filter in (FILTER_INSTALLED, FILTER_NOT_INSTALLED):
-                continue
-            elif filter in (FILTER_DEVELOPMENT, FILTER_NOT_DEVELOPMENT):
-                if not self._do_devel_filtering(flt,pkg):
-                    return False
-        return True
-
-    def _do_devel_filtering(self, flt, pkg):
-        isDevel = False
-        if flt == FILTER_DEVELOPMENT:
-            wantDevel = True
-        else:
-            wantDevel = False
-        #
-        # TODO: Add Devel detection Code here.Set isDevel = True, if it is a
-        #       devel app.
-        #
-        regex =  re.compile(r'(:devel)')
-        if regex.search(pkg.name):
-            isDevel = True
-        #
-        #
-        return isDevel == wantDevel
-
-    def _findPackage(self, id):
-        '''
-        find a package based on a package id (name;version;arch;repoid)
-        '''
-        name, version, flavor = self.get_package_from_id(id)
-        troveTuple = (name, version, flavor)
-        installed = self.check_installed(troveTuple)
-        return name, version, flavor, installed
-
-    def repo_set_data(self, repoid, parameter, value):
-        '''
-        Implement the {backend}-repo-set-data functionality
-        '''
-        pass
-
-    def get_repo_list(self, filters):
-        '''
-        Implement the {backend}-get-repo-list functionality
-        '''
-        pass
-
-    def repo_enable(self, repoid, enable):
-        '''
-        Implement the {backend}-repo-enable functionality
-        '''
-
-
-class Cache(object):
-    # Database name and path
-    dbName = 'cache.db'
-    # Someday we might want to make this writable by users
-    #if 'HOME' in os.environ:
-    #    dbPath = '%s/.conary/cache/data/' % os.environ['HOME']
-    #else:
-    #    dbPath = '/var/cache/conary/'
-    dbPath = '/var/cache/conary/'
-    jobPath = dbPath + 'jobs'
-
-    """ Class to retrieve and cache package information from label. """
-    def __init__(self):
-        if not os.path.isdir(self.dbPath):
-            os.makedirs(self.dbPath)
-        if not os.path.isdir(self.jobPath):
-            os.mkdir(self.jobPath)
-
-        self.conn = dbstore.connect(os.path.join(self.dbPath, self.dbName))
-        self.cursor = self.conn.cursor()
-        self.cursor.execute("PRAGMA count_changes=0", start_transaction=False)
-
-        if os.path.isfile(os.path.join(self.dbPath, self.dbName)):
-            self._validate_tables()
-
-    def _validate_tables(self):
-        """ Validates that all tables are up to date. """
-        backend = PackageKitBaseBackend(self)
-        stmt = ("select tbl_name from sqlite_master "
-                "where type = 'table' and tbl_name like 'conary_%'")
-        self.cursor.execute(stmt)
-        # List of all tables with names that start with "conary_"
-        tbllist = self.cursor.fetchall()
-        if tbllist == [('conary_packages',)]:
-            self.cursor.execute('DROP TABLE conary_packages')
-            self.conn.commit()
-            tbllist = []
-        if tbllist != []:
-            return True
-            #print "Verified packages table"
-        else:
-            #print "Creating packages table..."
-            # Create all tables if database is empty
-            if len(tbllist) == 0:
-                self._create_database()
-                backend.status(STATUS_WAIT)
-                self.populate_database()
-                return True
-
-    def _getJobCachePath(self, applyList):
-        from conary.lib import sha1helper
-        applyStr = '\0'.join(['%s=%s[%s]--%s[%s]%s' % (x[0], x[1][0], x[1][1], x[2][0], x[2][1], x[3]) for x in applyList])
-        return self.jobPath + '/' + sha1helper.sha1ToString(sha1helper.sha1String(applyStr))
-
-    def checkCachedUpdateJob(self, applyList):
-        jobPath = self._getJobCachePath(applyList)
-        if os.path.exists(jobPath):
-            return jobPath
-
-    def cacheUpdateJob(self, applyList, updJob):
-        jobPath = self._getJobCachePath(applyList)
-        if os.path.exists(jobPath):
-            from conary.lib import util
-            util.rmtree(jobPath)
-        os.mkdir(jobPath)
-        updJob.freeze(jobPath)
-
-    def conaryquery(self):
-        self.cfg = conarycfg.ConaryConfiguration()
-        self.client = conaryclient.ConaryClient(self.cfg)
-        self.cfg.readFiles()
-        self.cfg.initializeFlavors()
-        self.repos = self.client.getRepos()
-        self.db = conaryclient.ConaryClient(self.cfg).db
-
-        troves = queryrep.getTrovesToDisplay(self.repos, None, None, None,
-            queryrep.VERSION_FILTER_LEAVES, queryrep.FLAVOR_FILTER_BEST,
-            self.cfg.installLabelPath, self.cfg.flavor, None)
-
-        packages = []
-
-        for troveTuple in troves:
-            # troveTuple is probably what we want to store in the cachedb
-            # Then use the below methods to present them in a nicer fashion
-            if troveTuple[0].endswith(':source'):
-                continue
-            if ":" in troveTuple[0]:
-                fragments = troveTuple[0].split(":")
-                trove = fragments[0]
-                component = fragments[1]
-            else:
-                trove = troveTuple[0]
-                component = ""
-
-            installed = 0
-            flavor = troveTuple[2].freeze()
-            fullVersion = troveTuple[1].freeze()
-            label = str(troveTuple[1].branch().label())
-            description = ""
-            category = ""
-            packagegroup = ""
-            size = ""
-            packages.append([trove, component, fullVersion, label, flavor,
-                             description, category, packagegroup, size])
-
-        return packages
-
-    def connect_memory(self):
-        return sqlite.connect(':memory:')
-
-    def cursor(self, connection):
-        return connection.cursor()
-
-    def _create_database(self):
-        #FIXME: delete the category column. it's not useful
-
-        """ Creates a blank database. """
-        sql = '''CREATE TABLE conary_packages (
-            packageId INTEGER,
-            trove text,
-            component text,
-            version text,
-            label text,
-            flavor text,
-            description text,
-            category text,
-            packagegroup text,
-            size text)'''
-
-        self.cursor.execute(sql)
-
-        sql = '''CREATE TABLE conary_categories (
-            categoryId INTEGER,
-            categoryName text)'''
-
-        self.cursor.execute(sql)
-
-        sql = '''CREATE TABLE conary_category_package_map (
-            categoryId INTEGER,
-            packageId INTEGER)'''
-
-        self.cursor.execute(sql)
-
-        sql = '''CREATE TABLE conary_licenses (
-            licenseId INTEGER,
-            licenseName text)'''
-
-        self.cursor.execute(sql)
-
-        sql = '''CREATE TABLE conary_license_package_map (
-            licenseId INTEGER,
-            packageId INTEGER)'''
-
-        self.cursor.execute(sql)
-
-        #self.conn.createIndex('conary_catagories', 'conary_category_name_idx', ['categoryName'])
-        #self.conn.createIndex('conary_catagories', 'conary_category_id_idx', ['categoryId'])
-
-
-
-    def commit(self):
-        self.cursor.commit()
-
-    def getTroves(self, label=None):
-        """
-        Returns all troves for now.  Add filtering capability.
-        """
-        stmt = ("select distinct trove, version, flavor, description, "
-                "category, packagegroup, size from conary_packages")
-
-        self.cursor.execute(stmt)
-        return self.cursor.fetchall()
-
-    def search(self, package, fullVersion=None):
-        """
-        Returns all troves for now.  Add filtering capability.
-        """
-        stmt = ("select distinct trove, version, flavor, description, "
-                "category, packagegroup, size from conary_packages")
-
-        if package and fullVersion:
-            stmt = ("select distinct trove, version, flavor from "
-                    "conary_packages where trove ='%s' and version = '%s'"
-                    % (package, fullVersion))
-        elif package:
-            stmt += (" where trove like '%%%s%%' and component = '' order by "
-                     "version desc" % package)
-
-        try:
-            self.cursor.execute(stmt)
-            results = self.cursor.fetchall()
-            return results
-        except Exception, e:
-            print str(e)
-            return None
-
-    def searchByGroups(self, groups):
-        """
-        Returns all troves for given groups. (trove, version, flavor)
-        Needs filtering capability.
-        ['all'] means all packages
-        FIXME: No filtering done on group text - SQL injection
-        """
-        if not groups:
-            groups = ["all"]
-
-        if "all" in groups:
-            stmt = ("SELECT DISTINCT CP.trove, CP.version, CP.flavor, CC.categoryName"
-                    "           FROM conary_packages CP, conary_categories CC, conary_category_package_map CCMap"
-                    "          WHERE CCMap.packageId = CP.packageId"
-                    "            AND CCMap.categoryId = CC.categoryId"
-                    "       GROUP BY CP.trove, CP.version, CP.flavor"
-                    "       ORDER BY CP.trove, CP.version DESC, CP.flavor")
-        else:
-            group_string = ", ".join(groups)
-            stmt = ("SELECT DISTINCT CP.trove, CP.version, CP.flavor, CC.categoryName"
-                    "           FROM conary_packages CP, conary_categories CC, conary_category_package_map CCMap"
-                    "          WHERE CC.categoryName IN (%s)"
-                    "            AND CCMap.packageId = CP.packageId"
-                    "            AND CCMap.categoryId = CC.categoryId"
-                    "       GROUP BY CP.trove, CP.version, CP.flavor"
-                    "       ORDER BY CP.trove, CP.version DESC, CP.flavor" % group_string)
-        
-        try:
-            self.cursor.execute(stmt)
-            return self.cursor.fetchall()
-        except Exception, e:
-            print str(e)
-            return None
-        
-    def _insert(self, trove):
-        """
-        Insert trove into database.
-        """
-        res = self.cursor.execute("SELECT COALESCE(max(packageId), 0) + 1 FROM conary_packages")
-        pkgId = res.fetchone()[0] + 1
-        trove = [pkgId] + trove[:]
-
-        values = [str(field) for field in trove]
-        cols = ",".join("?" * len(trove))
-        sql = "INSERT INTO conary_packages VALUES (%s)" % cols
-
-        try:
-            self.cursor.execute(sql, values)
-            self.conn.commit()
-        except Exception,e:
-            print str(e)
-
-    def _clear_table(self, tableName='conary_packages'):
-        """
-        Deletes * records from table.
-        """
-        stmt = "DELETE FROM %s" % tableName
-        try:
-            self.cursor.execute(stmt)
-        except dbstore.sqlerrors.InvalidTable:
-            pass
-
-    def populate_database(self):
-        packages = self.conaryquery()
-        # Clear table first
-        for tblName in ('conary_packages', 'conary_category_package_map',
-                'conary_categories'):
-            self._clear_table(tblName)
-        for package in packages:
-            self._insert(package)
-
-    def _addPackageCategory(self, trv, category):
-        res = self.cursor.execute( \
-                'SELECT packageId FROM conary_packages WHERE trove=? and version=? and flavor = ?', trv.getName(), trv.getVersion().freeze(), trv.getFlavor().freeze())
-        res = res.fetchone()
-        if res:
-            # we have a packageID
-            pkgId = res[0]
-        else:
-            # we really should have had this data
-            raise RuntimeError
-
-        # now look up/make the categoryId
-        res = self.cursor.execute('SELECT categoryId FROM conary_categories WHERE categoryName=?', category)
-        res = res.fetchone()
-        if not res:
-            res = self.cursor.execute('SELECT COALESCE(MAX(categoryId), 0) + 1 FROM conary_categories')
-            catId = res.fetchone()[0]
-            self.cursor.execute('INSERT INTO conary_categories VALUES(?, ?)',
-                    catId, category)
-        else:
-            catId = category
-
-        self.cursor.execute("INSERT INTO conary_category_package_map VALUES(?, ?)", catId, pkgId)
-        self.conn.commit()
-
-    def populate_metadata(self, csList):
-        for cs in csList:
-            for troveCS in cs.iterNewTroveList():
-                trv = trove.Trove(troveCS)
-                if ':' in trv.getName():
-                    # components aren't tracked at the moment
-                    continue
-                metadata = trv.getMetadata()
-                categories = metadata.get('categories', [])
-                for category in categories:
-                    self._addPackageCategory(trv, category)
-                #licenses = metadata.get('licenses', [])
-                #for license in licenses:
-                #    self._addPackageLicense(trv, license)
diff --git a/backends/conary/helpers/conaryCallback.py b/backends/conary/helpers/conaryCallback.py
deleted file mode 100644
index e61ac96..0000000
--- a/backends/conary/helpers/conaryCallback.py
+++ /dev/null
@@ -1,115 +0,0 @@
-#
-# Copyright (c) 2007 Elliot Peele <elliot at bentlogic.net>
-#
-# Licensed under the GNU General Public License Version 2
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
-#
-
-from conary import callbacks
-from packagekit.backend import *
-
-class UpdateCallback(callbacks.UpdateCallback):
-    def resolvingDependencies(self):
-        #self.backend.status('Resolving Dependencies')
-        self.backend.status(STATUS_DEP_RESOLVE)
-
-    def creatingRollback(self):
-        #self.backend.status('Creating Rollback')
-        self.backend.status(STATUS_ROLLBACK)
-
-    def committingTransaction(self):
-        #self.backend.status('Committing Transaction')
-        self.backend.status(STATUS_COMMIT)
-
-    def downloadingFileContents(self, got, need):
-        #self.backend.status('Downloading files for changeset')
-        self.backend.status(STATUS_DOWNLOAD)
-
-    def downloadingChangeSet(self, got, need):
-        self.backend.status(STATUS_DOWNLOAD)
-
-    def requestingFileContents(self):
-        #self.backend.status('Requesting File Contents')
-        self.backend.status(STATUS_REQUEST)
-
-    def requestingChangeSet(self):
-        #self.backend.status('Requesting Changeset')
-        self.backend.status(STATUS_REQUEST)
-
-    def done(self):
-        #self.backend.status('Done')
-        pass
-
-    def preparingUpdate(self, troveNum, troveCount, add=0):
-        if not self.currentJob or len(self.currentJob) == 0 or troveNum > troveCount:
-            return
-
-        if troveNum > 0 and troveCount > 0:
-            sub_percent = (add + troveNum) / (2 * float(troveCount)) * 100
-            self.backend.sub_percentage(sub_percent)
-
-            if self.smallUpdate:
-                self.backend.percentage(sub_percent)
-
-        if troveNum != 0:
-            troveNum -= 1
-
-        job = self.currentJob[troveNum]
-        name = job[0]
-        oldVersion, oldFlavor = job[1]
-        newVersion, newFlavor = job[2]
-
-        if oldVersion and newVersion:
-            self.backend.status(STATUS_UPDATE)
-            id = self.backend.get_package_id(name, newVersion, newFlavor)
-            self.backend.package(id, INFO_UPDATING, '')
-        elif oldVersion and not newVersion:
-            self.backend.status(STATUS_REMOVE)
-            id = self.backend.get_package_id(name, oldVersion, oldFlavor)
-            self.backend.package(id, INFO_REMOVING, '')
-        elif not oldVersion and newVersion:
-            self.backend.status(STATUS_INSTALL)
-            id = self.backend.get_package_id(name, newVersion, newFlavor)
-            self.backend.package(id, INFO_INSTALLING, '')
-
-
-    def creatingDatabaseTransaction(self, troveNum, troveCount):
-        self.preparingUpdate(troveNum, troveCount, add=troveCount)
-
-    def setChangesetHunk(self, num, total):
-        pass
-
-    def setUpdateHunk(self, hunk, hunkCount):
-        if hunk > 0 and hunkCount > 0:
-            percentage = hunk / float(hunkCount) * 100.0
-            self.backend.percentage(percentage)
-        else:
-            self.smallUpdate = True
-
-    def setUpdateJob(self, job):
-        self.currentJob = job
-
-    def updateDone(self):
-        self.currentJob = None
-
-    def tagHandlerOutput(self, tag, msg, stderr = False):
-        pass
-
-    def troveScriptOutput(self, typ, msg):
-        pass
-
-    def troveScriptFailure(self, typ, errcode):
-        pass
-
-    def __init__(self, backend, cfg=None):
-        callbacks.UpdateCallback.__init__(self)
-        if cfg:
-            self.setTrustThreshold(cfg.trustThreshold)
-
-        self.backend = backend
-        self.currentJob = None
-        self.smallUpdate = False
diff --git a/backends/conary/helpers/get-depends.py b/backends/conary/helpers/get-depends.py
deleted file mode 100755
index 2a9e4c2..0000000
--- a/backends/conary/helpers/get-depends.py
+++ /dev/null
@@ -1,19 +0,0 @@
-#!/usr/bin/python
-#
-# Copyright (C) 2007 Ken VanDine <ken at vandine.org>
-#
-# Licensed under the GNU General Public License Version 2
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
-
-import sys
-from conaryBackend import PackageKitConaryBackend
-
-filters = sys.argv[1]
-package = sys.argv[2]
-backend = PackageKitConaryBackend(sys.argv[1:])
-backend.get_depends(filters,package)
-sys.exit(0)
diff --git a/backends/conary/helpers/get-details.py b/backends/conary/helpers/get-details.py
deleted file mode 100755
index 1641283..0000000
--- a/backends/conary/helpers/get-details.py
+++ /dev/null
@@ -1,18 +0,0 @@
-#!/usr/bin/python
-#
-# Copyright (C) 2007 Ken VanDine <ken at vandine.org>
-#
-# Licensed under the GNU General Public License Version 2
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
-
-import sys
-from conaryBackend import PackageKitConaryBackend
-
-package = sys.argv[1]
-backend = PackageKitConaryBackend(sys.argv[1:])
-backend.get_details(package)
-sys.exit(0)
diff --git a/backends/conary/helpers/get-files.py b/backends/conary/helpers/get-files.py
deleted file mode 100755
index fe99262..0000000
--- a/backends/conary/helpers/get-files.py
+++ /dev/null
@@ -1,18 +0,0 @@
-#!/usr/bin/python
-#
-# Copyright (C) 2007 Elliot Peele <elliot at bentlogic.net>
-#
-# Licensed under the GNU General Public License Version 2
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
-
-import sys
-from conaryBackend import PackageKitConaryBackend
-
-package_id = sys.argv[1]
-backend = PackageKitConaryBackend(sys.argv[1:])
-backend.get_files(package_id)
-sys.exit(0)
diff --git a/backends/conary/helpers/get-repo-list.py b/backends/conary/helpers/get-repo-list.py
deleted file mode 100755
index 4c7eda5..0000000
--- a/backends/conary/helpers/get-repo-list.py
+++ /dev/null
@@ -1,19 +0,0 @@
-#!/usr/bin/python
-#
-# Copyright (C) 2007-2008 Richard Hughes <richard at hughsie.com>
-#
-# Licensed under the GNU General Public License Version 2
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
-
-import sys
-
-from conaryBackend import PackageKitConaryBackend
-filters = sys.argv[1]
-
-backend = PackageKitConaryBackend(sys.argv[2:])
-backend.get_repo_list(filters)
-sys.exit(0)
diff --git a/backends/conary/helpers/get-requires.py b/backends/conary/helpers/get-requires.py
deleted file mode 100755
index aa84bfa..0000000
--- a/backends/conary/helpers/get-requires.py
+++ /dev/null
@@ -1,19 +0,0 @@
-#!/usr/bin/python
-#
-# Copyright (C) 2007 Ken VanDine <ken at vandine.org>
-#
-# Licensed under the GNU General Public License Version 2
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
-
-import sys
-from conaryBackend import PackageKitConaryBackend
-
-filters = sys.argv[1]
-package = sys.argv[2]
-backend = PackageKitConaryBackend(sys.argv[1:])
-backend.get_requires(filters,package)
-sys.exit(0)
diff --git a/backends/conary/helpers/get-update-detail.py b/backends/conary/helpers/get-update-detail.py
deleted file mode 100755
index 271cce8..0000000
--- a/backends/conary/helpers/get-update-detail.py
+++ /dev/null
@@ -1,18 +0,0 @@
-#!/usr/bin/python
-#
-# Copyright (C) 2007 Ken VanDine <ken at vandine.org>
-#
-# Licensed under the GNU General Public License Version 2
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
-
-import sys
-from conaryBackend import PackageKitConaryBackend
-
-package = sys.argv[1]
-backend = PackageKitConaryBackend(sys.argv[1:])
-backend.get_update_detail(package)
-sys.exit(0)
diff --git a/backends/conary/helpers/get-updates.py b/backends/conary/helpers/get-updates.py
deleted file mode 100755
index 0d95bb2..0000000
--- a/backends/conary/helpers/get-updates.py
+++ /dev/null
@@ -1,19 +0,0 @@
-#!/usr/bin/python
-#
-# Copyright (C) 2007 Ken VanDine <ken at vandine.org>
-#
-# Licensed under the GNU General Public License Version 2
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
-
-import sys
-from conaryBackend import PackageKitConaryBackend
-
-filter = sys.argv[1]
-
-backend = PackageKitConaryBackend(sys.argv[1:])
-backend.get_updates(filter)
-sys.exit(0)
diff --git a/backends/conary/helpers/install-packages.py b/backends/conary/helpers/install-packages.py
deleted file mode 100755
index 125ffcf..0000000
--- a/backends/conary/helpers/install-packages.py
+++ /dev/null
@@ -1,18 +0,0 @@
-#!/usr/bin/python2.4
-#
-# Copyright (C) 2007 Ken VanDine <ken at vandine.org>
-#
-# Licensed under the GNU General Public License Version 2
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
-
-import sys
-from conaryBackend import PackageKitConaryBackend
-
-package_ids = sys.argv[1]
-backend = PackageKitConaryBackend(sys.argv[1:])
-backend.update_packages(package_ids)
-sys.exit(0)
diff --git a/backends/conary/helpers/packagekit b/backends/conary/helpers/packagekit
deleted file mode 120000
index 8d22531..0000000
--- a/backends/conary/helpers/packagekit
+++ /dev/null
@@ -1 +0,0 @@
-../../../python/packagekit
\ No newline at end of file
diff --git a/backends/conary/helpers/refresh-cache.py b/backends/conary/helpers/refresh-cache.py
deleted file mode 100755
index 277c942..0000000
--- a/backends/conary/helpers/refresh-cache.py
+++ /dev/null
@@ -1,17 +0,0 @@
-#!/usr/bin/python
-#
-# Copyright (C) 2007 Ken VanDine <ken at vandine.org>
-#
-# Licensed under the GNU General Public License Version 2
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
-
-import sys
-from conaryBackend import PackageKitConaryBackend
-
-backend = PackageKitConaryBackend(sys.argv[1:])
-backend.refresh_cache()
-sys.exit(0)
diff --git a/backends/conary/helpers/remove-packages.py b/backends/conary/helpers/remove-packages.py
deleted file mode 100755
index 260fe98..0000000
--- a/backends/conary/helpers/remove-packages.py
+++ /dev/null
@@ -1,19 +0,0 @@
-#!/usr/bin/python2.4
-#
-# Copyright (C) 2007 Ken VanDine <ken at vandine.org>
-#
-# Licensed under the GNU General Public License Version 2
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
-
-import sys
-from conaryBackend import PackageKitConaryBackend
-
-allowDeps = sys.argv[1]
-package_ids = sys.argv[2]
-backend = PackageKitConaryBackend(sys.argv[1:])
-backend.remove_packages(allowDeps, package_ids)
-sys.exit(0)
diff --git a/backends/conary/helpers/repo-enable.py b/backends/conary/helpers/repo-enable.py
deleted file mode 100755
index 09f0f4c..0000000
--- a/backends/conary/helpers/repo-enable.py
+++ /dev/null
@@ -1,19 +0,0 @@
-#!/usr/bin/python
-#
-# Copyright (C) 2007-2008 Richard Hughes <richard at hughsie.com>
-#
-# Licensed under the GNU General Public License Version 2
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
-
-import sys
-
-from conaryBackend import PackageKitConaryBackend
-repoid = sys.argv[1]
-state=sys.argv[2]
-backend = PackageKitConaryBackend(sys.argv[2:])
-backend.repo_enable(repoid,state)
-sys.exit(0)
diff --git a/backends/conary/helpers/repo-set-data.py b/backends/conary/helpers/repo-set-data.py
deleted file mode 100755
index 4ba6671..0000000
--- a/backends/conary/helpers/repo-set-data.py
+++ /dev/null
@@ -1,20 +0,0 @@
-#!/usr/bin/python
-#
-# Copyright (C) 2007-2008 Richard Hughes <richard at hughsie.com>
-#
-# Licensed under the GNU General Public License Version 2
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
-
-import sys
-
-from conaryBackend import PackageKitConaryBackend
-repoid = sys.argv[1]
-para = sys.argv[2]
-value=sys.argv[3]
-backend = PackageKitConaryBackend(sys.argv[2:])
-backend.repo_set_data(repoid,para,value)
-sys.exit(0)
diff --git a/backends/conary/helpers/resolve.py b/backends/conary/helpers/resolve.py
deleted file mode 100755
index 4de412f..0000000
--- a/backends/conary/helpers/resolve.py
+++ /dev/null
@@ -1,19 +0,0 @@
-#!/usr/bin/python
-#
-# Copyright (C) 2007 Elliot Peele <elliot at bentlogic.net>
-#
-# Licensed under the GNU General Public License Version 2
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
-
-import sys
-from conaryBackend import PackageKitConaryBackend
-
-filter = sys.argv[1]
-package = sys.argv[2]
-backend = PackageKitConaryBackend(sys.argv[1:])
-backend.resolve(filter, package)
-sys.exit(0)
diff --git a/backends/conary/helpers/search-details.py b/backends/conary/helpers/search-details.py
deleted file mode 100755
index 36958a0..0000000
--- a/backends/conary/helpers/search-details.py
+++ /dev/null
@@ -1,81 +0,0 @@
-#!/usr/bin/python
-#
-# Copyright (C) 2007 Ken VanDine <ken at vandine.org>
-#
-# Licensed under the GNU General Public License Version 2
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
-
-import sys
-from conary import conarycfg, conaryclient, queryrep, versions
-from conary.conaryclient import cmdline
-
-
-cfg = conarycfg.ConaryConfiguration()
-client = conaryclient.ConaryClient(cfg)
-cfg.readFiles()
-cfg.initializeFlavors()
-repos = client.getRepos()
-db = conaryclient.ConaryClient(cfg).db
-affinityDb = client.db
-
-options = sys.argv[1]
-searchterms = sys.argv[2]
-
-sys.stdout.write('no-percentage-updates\n')
-
-try:
-    localInstall = db.findTrove(None, (searchterms, None, None))
-    installed = 1
-except:
-    installed = 0
-
-troveSpecs = [ cmdline.parseTroveSpec(searchterms, allowEmptyName=False)]
-
-try:
-    # Look for packages with affinity
-    troveTupleList = queryrep.getTrovesToDisplay(repos, troveSpecs,
-        None, None, queryrep.VERSION_FILTER_LATEST,
-        queryrep.FLAVOR_FILTER_BEST, cfg.installLabelPath,
-        cfg.flavor, affinityDb)
-    # Look for packages regardless of affinity
-    troveTupleList.extend(queryrep.getTrovesToDisplay(repos, troveSpecs,
-        None, None, queryrep.VERSION_FILTER_LATEST,
-        queryrep.FLAVOR_FILTER_BEST, cfg.installLabelPath,
-        cfg.flavor, None))
-    # Remove dupes
-    tempDict = {}
-    for element in troveTupleList:
-        tempDict[element] = None
-        troveTupleList = tempDict.keys()
-
-    # Get the latest first
-    troveTupleList.sort()
-    troveTupleList.reverse()
-
-    for troveTuple in troveTupleList:
-        name = troveTuple[0]
-        version = troveTuple[1].trailingRevision().asString()
-        # Hard code this until i get the flavor parsing right
-        arch = "x86"
-        fullVersion = troveTuple[1].asString()
-        flavor = str(troveTuple[2])
-        data = fullVersion + " " + flavor
-        # We don't have summary data yet... so leave it blank for now
-        summary = " "
-        package_id = name + ";" + version + ";" + arch + ";" + data
-        do_print = 0;
-        if options == 'installed' and installed == 1:
-            do_print = 1
-        elif options == 'available' and installed == 0:
-            do_print = 1
-        elif options == 'all':
-            do_print = 1
-        # print in correct format
-        if do_print == 1:
-            print "package\t%s\t%s\t%s" % (installed, package_id, summary)
-except:
-    sys.stdout.write('error\tinternal-error\tAn internal error has occurred')
diff --git a/backends/conary/helpers/search-group.py b/backends/conary/helpers/search-group.py
deleted file mode 100755
index 2c77022..0000000
--- a/backends/conary/helpers/search-group.py
+++ /dev/null
@@ -1,21 +0,0 @@
-#!/usr/bin/python
-#
-# Copyright (C) 2007 Ken VanDine <ken at vandine.org>
-#
-# Licensed under the GNU General Public License Version 2
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
-
-import sys
-
-options = sys.argv[1]
-searchterms = sys.argv[2]
-
-from conaryBackend import PackageKitConaryBackend
-
-backend = PackageKitConaryBackend(sys.argv[1:])
-backend.search_group(options,searchterms)
-sys.exit(0)
diff --git a/backends/conary/helpers/search-name.py b/backends/conary/helpers/search-name.py
deleted file mode 100755
index 327e42f..0000000
--- a/backends/conary/helpers/search-name.py
+++ /dev/null
@@ -1,21 +0,0 @@
-#!/usr/bin/python
-#
-# Copyright (C) 2007 Ken VanDine <ken at vandine.org>
-#
-# Licensed under the GNU General Public License Version 2
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
-
-import sys
-
-options = sys.argv[1]
-searchlist = sys.argv[2]
-
-from conaryBackend import PackageKitConaryBackend
-
-backend = PackageKitConaryBackend(sys.argv[1:])
-backend.search_name(options,searchlist)
-sys.exit(0)
diff --git a/backends/conary/helpers/update-packages.py b/backends/conary/helpers/update-packages.py
deleted file mode 100755
index 2269781..0000000
--- a/backends/conary/helpers/update-packages.py
+++ /dev/null
@@ -1,18 +0,0 @@
-#!/usr/bin/python
-#
-# Copyright (C) 2007 Ken VanDine <ken at vandine.org>
-#
-# Licensed under the GNU General Public License Version 2
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
-
-import sys
-from conaryBackend import PackageKitConaryBackend
-
-packages = sys.argv[1]
-backend = PackageKitConaryBackend(sys.argv[1:])
-backend.update_packages(packages)
-sys.exit(0)
diff --git a/backends/conary/helpers/update-system.py b/backends/conary/helpers/update-system.py
deleted file mode 100755
index 7407180..0000000
--- a/backends/conary/helpers/update-system.py
+++ /dev/null
@@ -1,17 +0,0 @@
-#!/usr/bin/python
-#
-# Copyright (C) 2007 Ken VanDine <ken at vandine.org>
-#
-# Licensed under the GNU General Public License Version 2
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
-
-import sys
-from conaryBackend import PackageKitConaryBackend
-
-backend = PackageKitConaryBackend(sys.argv[1:])
-backend.update_system()
-sys.exit(0)
diff --git a/backends/conary/packagekit b/backends/conary/packagekit
new file mode 120000
index 0000000..0b64032
--- /dev/null
+++ b/backends/conary/packagekit
@@ -0,0 +1 @@
+../../python/packagekit/
\ No newline at end of file
diff --git a/backends/conary/pk-backend-conary.c b/backends/conary/pk-backend-conary.c
index 384141c..2ed14d5 100644
--- a/backends/conary/pk-backend-conary.c
+++ b/backends/conary/pk-backend-conary.c
@@ -30,7 +30,6 @@ static PkBackendSpawn *spawn;
  * backend_initialize:
  * This should only be run once per backend load, i.e. not every transaction
  */
-
 static void
 backend_initialize (PkBackend *backend)
 {
@@ -110,7 +109,7 @@ backend_get_details (PkBackend *backend, gchar **package_ids)
 {
 	gchar *package_ids_temp;
 	package_ids_temp = pk_package_ids_to_text (package_ids);
-	pk_backend_spawn_helper (spawn, "get-details.py", package_ids_temp, NULL);
+	pk_backend_spawn_helper (spawn, "conaryBackend.py", "get-details", package_ids_temp, NULL);
 	g_free (package_ids_temp);
 }
 
@@ -122,7 +121,7 @@ backend_get_files (PkBackend *backend, gchar **package_ids)
 {
 	gchar *package_ids_temp;
 	package_ids_temp = pk_package_ids_to_text (package_ids);
-	pk_backend_spawn_helper (spawn, "get-files.py", package_ids_temp, NULL);
+	pk_backend_spawn_helper (spawn, "conaryBackend.py", "get-files", package_ids_temp, NULL);
 	g_free (package_ids_temp);
 }
 
@@ -134,7 +133,7 @@ backend_get_updates (PkBackend *backend, PkBitfield filters)
 {
 	gchar *filters_text;
 	filters_text = pk_filter_bitfield_to_text (filters);
-	pk_backend_spawn_helper (spawn, "get-updates.py", filters_text, NULL);
+	pk_backend_spawn_helper (spawn, "conaryBackend.py", "get-updates", filters_text, NULL);
 	g_free (filters_text);
 }
 
@@ -146,7 +145,7 @@ backend_get_update_detail (PkBackend *backend, gchar **package_ids)
 {
 	gchar *package_ids_temp;
 	package_ids_temp = pk_package_ids_to_text (package_ids);
-	pk_backend_spawn_helper (spawn, "get-update-detail.py", package_ids_temp, NULL);
+	pk_backend_spawn_helper (spawn, "conaryBackend.py", "get-update-detail", package_ids_temp, NULL);
 	g_free (package_ids_temp);
 }
 
@@ -167,7 +166,7 @@ backend_install_packages (PkBackend *backend, gchar **package_ids)
 
 	/* send the complete list as stdin */
 	package_ids_temp = pk_package_ids_to_text (package_ids);
-	pk_backend_spawn_helper (spawn, "install-packages.py", package_ids_temp, NULL);
+	pk_backend_spawn_helper (spawn, "conaryBackend.py", "install-packages", package_ids_temp, NULL);
 	g_free (package_ids_temp);
 }
 
@@ -181,7 +180,7 @@ backend_install_files (PkBackend *backend, gboolean trusted, const gchar *full_p
 	gchar *package_ids_temp;
 
 	package_ids_temp = pk_package_ids_to_text (package_ids);
-	pk_backend_spawn_helper (spawn, "install-files.py", full_paths, NULL);
+	pk_backend_spawn_helper (spawn, "conaryBackend.py", "install-files", pk_backend_bool_to_text (trusted), full_paths, NULL);
 	g_free (package_ids_temp);
 }
  */
@@ -199,7 +198,7 @@ backend_refresh_cache (PkBackend *backend, gboolean force)
 		return;
 	}
 
-	pk_backend_spawn_helper (spawn, "refresh-cache.py", NULL);
+	pk_backend_spawn_helper (spawn, "conaryBackend.py", "refresh-cache", NULL);
 }
 
 /**
@@ -212,7 +211,7 @@ backend_remove_packages (PkBackend *backend, gchar **package_ids, gboolean allow
 
 	/* send the complete list as stdin */
 	package_ids_temp = pk_package_ids_to_text (package_ids);
-	pk_backend_spawn_helper (spawn, "remove-packages.py", pk_backend_bool_to_text (allow_deps), package_ids_temp, NULL);
+	pk_backend_spawn_helper (spawn, "conaryBackend.py", "remove-packages", pk_backend_bool_to_text (allow_deps), package_ids_temp, NULL);
 	g_free (package_ids_temp);
 }
 
@@ -224,7 +223,7 @@ backend_search_name (PkBackend *backend, PkBitfield filters, const gchar *search
 {
 	gchar *filters_text;
 	filters_text = pk_filter_bitfield_to_text (filters);
-	pk_backend_spawn_helper (spawn, "search-name.py", filters_text, search, NULL);
+	pk_backend_spawn_helper (spawn, "conaryBackend.py", "search-name", filters_text, search, NULL);
 	g_free (filters_text);
 }
 
@@ -246,7 +245,7 @@ backend_update_packages (PkBackend *backend, gchar **package_ids)
 
 	/* send the complete list as stdin */
 	package_ids_temp = pk_package_ids_to_text (package_ids);
-	pk_backend_spawn_helper (spawn, "update-packages.py", package_ids_temp, NULL);
+	pk_backend_spawn_helper (spawn, "conaryBackend.py", "update-packages", package_ids_temp, NULL);
 	g_free (package_ids_temp);
 }
 
@@ -256,7 +255,7 @@ backend_update_packages (PkBackend *backend, gchar **package_ids)
 static void
 backend_update_system (PkBackend *backend)
 {
-	pk_backend_spawn_helper (spawn, "update-system.py", NULL);
+	pk_backend_spawn_helper (spawn, "conaryBackend.py", "update-system", NULL);
 }
 
 /**
@@ -267,7 +266,7 @@ backend_resolve (PkBackend *backend, PkBitfield filters, gchar **package_ids)
 {
 	gchar *filters_text;
 	filters_text = pk_filter_bitfield_to_text (filters);
-	pk_backend_spawn_helper (spawn, "resolve.py", filters_text, package_ids[0], NULL);
+	pk_backend_spawn_helper (spawn, "conaryBackend.py", "resolve", filters_text, package_ids[0], NULL);
 	g_free (filters_text);
 }
 
diff --git a/configure.ac b/configure.ac
index 07cfbb2..de057ac 100644
--- a/configure.ac
+++ b/configure.ac
@@ -540,7 +540,6 @@ backends/alpm/Makefile
 backends/apt/Makefile
 backends/box/Makefile
 backends/conary/Makefile
-backends/conary/helpers/Makefile
 backends/dummy/Makefile
 backends/opkg/Makefile
 backends/smart/Makefile
commit 442e1f1bbdaa3a0549183602d36ca6dfb21c12bc
Author: Richard Hughes <richard at hughsie.com>
Date:   Fri Sep 26 13:50:17 2008 +0100

    bugfix: remove all the funny '^','|',<tab>,etc seporators and make the delimiters all the same
    
    The whole ^, |, \t space thing is pretty broken right now. I've just discovered a bug in GetDepends where multiple package_id are not being processed.
    
    I've committed a patch into git which sorts things out, once and for all. There's a constant PK_PACKAGE_IDS_DELIM (or PACKAGE_IDS_DELIM in python) that splits the package_ids, and PK_BACKEND_SPAWN_FILENAME_DELIM (python FILENAME_DELIM) is used to delimit multiple paths.
    
    Other changes:
    
    * pk_package_ids_to_text no longer takes a delimiter argument, as it's hardcoded to the define.
    * pk_va_list_to_argv no longer does insane things with '|'

diff --git a/backends/apt.deprecated/pk-backend-apt.c b/backends/apt.deprecated/pk-backend-apt.c
index e3499e3..4d18edd 100644
--- a/backends/apt.deprecated/pk-backend-apt.c
+++ b/backends/apt.deprecated/pk-backend-apt.c
@@ -149,7 +149,7 @@ backend_install_packages (PkBackend *backend, gchar **package_ids)
 	}
 
 	/* send the complete list as stdin */
-	package_ids_temp = pk_package_ids_to_text (package_ids, "|");
+	package_ids_temp = pk_package_ids_to_text (package_ids);
 	pk_backend_spawn_helper (spawn, "install-packages.py", package_ids_temp, NULL);
 	g_free (package_ids_temp);
 }
@@ -177,7 +177,7 @@ static void
 backend_remove_packages (PkBackend *backend, gchar **package_ids, gboolean allow_deps, gboolean autoremove)
 {
 	gchar *package_ids_temp;
-	package_ids_temp = pk_package_ids_to_text (package_ids, "|");
+	package_ids_temp = pk_package_ids_to_text (package_ids);
 	pk_backend_spawn_helper (spawn, "remove-packages.py", pk_backend_bool_to_text (allow_deps), package_ids_temp, NULL);
 	g_free (package_ids_temp);
 } */
@@ -198,7 +198,7 @@ backend_update_packages (PkBackend *backend, gchar **package_ids)
 	}
 
 	/* send the complete list as stdin */
-	package_ids_temp = pk_package_ids_to_text (package_ids, "|");
+	package_ids_temp = pk_package_ids_to_text (package_ids);
 	pk_backend_spawn_helper (spawn, "update-packages.py", package_ids_temp, NULL);
 	g_free (package_ids_temp);
 }
diff --git a/backends/conary/pk-backend-conary.c b/backends/conary/pk-backend-conary.c
index b893e62..384141c 100644
--- a/backends/conary/pk-backend-conary.c
+++ b/backends/conary/pk-backend-conary.c
@@ -109,7 +109,7 @@ static void
 backend_get_details (PkBackend *backend, gchar **package_ids)
 {
 	gchar *package_ids_temp;
-	package_ids_temp = pk_package_ids_to_text (package_ids, "%");
+	package_ids_temp = pk_package_ids_to_text (package_ids);
 	pk_backend_spawn_helper (spawn, "get-details.py", package_ids_temp, NULL);
 	g_free (package_ids_temp);
 }
@@ -121,7 +121,7 @@ static void
 backend_get_files (PkBackend *backend, gchar **package_ids)
 {
 	gchar *package_ids_temp;
-	package_ids_temp = pk_package_ids_to_text (package_ids, "%");
+	package_ids_temp = pk_package_ids_to_text (package_ids);
 	pk_backend_spawn_helper (spawn, "get-files.py", package_ids_temp, NULL);
 	g_free (package_ids_temp);
 }
@@ -145,7 +145,7 @@ static void
 backend_get_update_detail (PkBackend *backend, gchar **package_ids)
 {
 	gchar *package_ids_temp;
-	package_ids_temp = pk_package_ids_to_text (package_ids, "%");
+	package_ids_temp = pk_package_ids_to_text (package_ids);
 	pk_backend_spawn_helper (spawn, "get-update-detail.py", package_ids_temp, NULL);
 	g_free (package_ids_temp);
 }
@@ -166,7 +166,7 @@ backend_install_packages (PkBackend *backend, gchar **package_ids)
 	}
 
 	/* send the complete list as stdin */
-	package_ids_temp = pk_package_ids_to_text (package_ids, "%");
+	package_ids_temp = pk_package_ids_to_text (package_ids);
 	pk_backend_spawn_helper (spawn, "install-packages.py", package_ids_temp, NULL);
 	g_free (package_ids_temp);
 }
@@ -180,7 +180,7 @@ backend_install_files (PkBackend *backend, gboolean trusted, const gchar *full_p
 {
 	gchar *package_ids_temp;
 
-	package_ids_temp = pk_package_ids_to_text (package_ids, "%");
+	package_ids_temp = pk_package_ids_to_text (package_ids);
 	pk_backend_spawn_helper (spawn, "install-files.py", full_paths, NULL);
 	g_free (package_ids_temp);
 }
@@ -211,7 +211,7 @@ backend_remove_packages (PkBackend *backend, gchar **package_ids, gboolean allow
 	gchar *package_ids_temp;
 
 	/* send the complete list as stdin */
-	package_ids_temp = pk_package_ids_to_text (package_ids, "%");
+	package_ids_temp = pk_package_ids_to_text (package_ids);
 	pk_backend_spawn_helper (spawn, "remove-packages.py", pk_backend_bool_to_text (allow_deps), package_ids_temp, NULL);
 	g_free (package_ids_temp);
 }
@@ -245,7 +245,7 @@ backend_update_packages (PkBackend *backend, gchar **package_ids)
 	}
 
 	/* send the complete list as stdin */
-	package_ids_temp = pk_package_ids_to_text (package_ids, "%");
+	package_ids_temp = pk_package_ids_to_text (package_ids);
 	pk_backend_spawn_helper (spawn, "update-packages.py", package_ids_temp, NULL);
 	g_free (package_ids_temp);
 }
diff --git a/backends/pisi/pk-backend-pisi.c b/backends/pisi/pk-backend-pisi.c
index 14db961..154ed35 100644
--- a/backends/pisi/pk-backend-pisi.c
+++ b/backends/pisi/pk-backend-pisi.c
@@ -121,7 +121,7 @@ backend_get_depends (PkBackend *backend, PkBitfield filters, gchar **package_ids
 {
 	gchar *filters_text;
 	gchar *package_ids_temp;
-	package_ids_temp = pk_package_ids_to_text (package_ids, "|");
+	package_ids_temp = pk_package_ids_to_text (package_ids);
 	filters_text = pk_filter_bitfield_to_text (filters);
 	pk_backend_spawn_helper (spawn, "get-depends.py", filters_text, package_ids_temp, pk_backend_bool_to_text (recursive), NULL);
 	g_free (filters_text);
@@ -135,7 +135,7 @@ static void
 backend_get_details (PkBackend *backend, gchar **package_ids)
 {
 	gchar *package_ids_temp;
-	package_ids_temp = pk_package_ids_to_text (package_ids, "|");
+	package_ids_temp = pk_package_ids_to_text (package_ids);
 	pk_backend_spawn_helper (spawn, "get-details.py", package_ids_temp, NULL);
 	g_free (package_ids_temp);
 }
@@ -147,7 +147,7 @@ static void
 backend_get_files (PkBackend *backend, gchar **package_ids)
 {
 	gchar *package_ids_temp;
-	package_ids_temp = pk_package_ids_to_text (package_ids, "|");
+	package_ids_temp = pk_package_ids_to_text (package_ids);
 	pk_backend_spawn_helper (spawn, "get-files.py", package_ids_temp, NULL);
 	g_free (package_ids_temp);
 }
@@ -160,7 +160,7 @@ backend_get_requires (PkBackend *backend, PkBitfield filters, gchar **package_id
 {
 	gchar *filters_text;
 	gchar *package_ids_temp;
-	package_ids_temp = pk_package_ids_to_text (package_ids, "|");
+	package_ids_temp = pk_package_ids_to_text (package_ids);
 	filters_text = pk_filter_bitfield_to_text (filters);
 	pk_backend_spawn_helper (spawn, "get-requires.py", filters_text, package_ids_temp, pk_backend_bool_to_text (recursive), NULL);
 	g_free (filters_text);
@@ -195,7 +195,7 @@ backend_install_packages (PkBackend *backend, gchar **package_ids)
 	}
 
 	/* send the complete list as stdin */
-	package_ids_temp = pk_package_ids_to_text (package_ids, "|");
+	package_ids_temp = pk_package_ids_to_text (package_ids);
 	pk_backend_spawn_helper (spawn, "install-packages.py", package_ids_temp, NULL);
 	g_free (package_ids_temp);
 }
@@ -209,7 +209,7 @@ backend_install_files (PkBackend *backend, gboolean trusted, gchar **full_paths)
 	gchar *package_ids_temp;
 
 	/* send the complete list as stdin */
-	package_ids_temp = pk_package_ids_to_text (full_paths, "|");
+	package_ids_temp = pk_strv_to_text (full_paths, PK_BACKEND_SPAWN_FILENAME_DELIM);
 	pk_backend_spawn_helper (spawn, "install-files.py", pk_backend_bool_to_text (trusted), package_ids_temp, NULL);
 	g_free (package_ids_temp);
 }
@@ -239,7 +239,7 @@ backend_remove_packages (PkBackend *backend, gchar **package_ids, gboolean allow
 	gchar *package_ids_temp;
 
 	/* send the complete list as stdin */
-	package_ids_temp = pk_package_ids_to_text (package_ids, "|");
+	package_ids_temp = pk_package_ids_to_text (package_ids);
 	pk_backend_spawn_helper (spawn, "remove-packages.py", pk_backend_bool_to_text (allow_deps), package_ids_temp, NULL);
 	g_free (package_ids_temp);
 }
@@ -309,7 +309,7 @@ backend_update_packages (PkBackend *backend, gchar **package_ids)
 	}
 
 	/* send the complete list as stdin */
-	package_ids_temp = pk_package_ids_to_text (package_ids, "|");
+	package_ids_temp = pk_package_ids_to_text (package_ids);
 	pk_backend_spawn_helper (spawn, "update.py", package_ids_temp, NULL);
 	g_free (package_ids_temp);
 }
@@ -332,7 +332,7 @@ backend_resolve (PkBackend *backend, PkBitfield filters, gchar **package_ids)
 	gchar *filters_text;
 	gchar *package_ids_temp;
 	filters_text = pk_filter_bitfield_to_text (filters);
-	package_ids_temp = pk_package_ids_to_text (package_ids, "|");
+	package_ids_temp = pk_package_ids_to_text (package_ids);
 	pk_backend_spawn_helper (spawn, "resolve.py", filters_text, package_ids_temp, NULL);
 	g_free (filters_text);
 	g_free (package_ids_temp);
diff --git a/backends/smart/helpers/get-depends.py b/backends/smart/helpers/get-depends.py
index 64843cf..a1fb640 100755
--- a/backends/smart/helpers/get-depends.py
+++ b/backends/smart/helpers/get-depends.py
@@ -18,5 +18,5 @@ package = sys.argv[2]
 recursive = sys.argv[3]
 
 backend = PackageKitSmartBackend(sys.argv[1:])
-backend.get_depends(filters, package.split('|'), recursive)
+backend.get_depends(filters, package.split(PACKAGE_IDS_DELIM), recursive)
 sys.exit(0)
diff --git a/backends/smart/helpers/get-details.py b/backends/smart/helpers/get-details.py
index 065d72b..9dd2c9d 100755
--- a/backends/smart/helpers/get-details.py
+++ b/backends/smart/helpers/get-details.py
@@ -16,5 +16,5 @@ from smartBackend import PackageKitSmartBackend
 
 package = sys.argv[1]
 backend = PackageKitSmartBackend(sys.argv[1:])
-backend.get_details(package.split('|'))
+backend.get_details(package.split(PACKAGE_IDS_DELIM))
 sys.exit(0)
diff --git a/backends/smart/helpers/get-files.py b/backends/smart/helpers/get-files.py
index 1b25134..098f2aa 100755
--- a/backends/smart/helpers/get-files.py
+++ b/backends/smart/helpers/get-files.py
@@ -15,5 +15,5 @@ import sys
 from smartBackend import PackageKitSmartBackend
 package = sys.argv[1]
 backend = PackageKitSmartBackend(sys.argv[1:])
-backend.get_files(package.split('|'))
+backend.get_files(package.split(PACKAGE_IDS_DELIM))
 sys.exit(0)
diff --git a/backends/smart/helpers/get-requires.py b/backends/smart/helpers/get-requires.py
index bb24cdf..5b3d793 100755
--- a/backends/smart/helpers/get-requires.py
+++ b/backends/smart/helpers/get-requires.py
@@ -18,5 +18,5 @@ package = sys.argv[2]
 recursive = sys.argv[3]
 
 backend = PackageKitSmartBackend(sys.argv[1:])
-backend.get_requires(filters, package.split('|'), recursive)
+backend.get_requires(filters, package.split(PACKAGE_IDS_DELIM), recursive)
 sys.exit(0)
diff --git a/backends/smart/helpers/get-update-detail.py b/backends/smart/helpers/get-update-detail.py
index 0de45f4..305a0bf 100755
--- a/backends/smart/helpers/get-update-detail.py
+++ b/backends/smart/helpers/get-update-detail.py
@@ -16,5 +16,5 @@ from smartBackend import PackageKitSmartBackend
 
 package = sys.argv[1]
 backend = PackageKitSmartBackend(sys.argv[1:])
-backend.get_update_detail(package.split('|'))
+backend.get_update_detail(package.split(PACKAGE_IDS_DELIM))
 sys.exit(0)
diff --git a/backends/smart/pk-backend-smart.c b/backends/smart/pk-backend-smart.c
index 72c916b..a703039 100644
--- a/backends/smart/pk-backend-smart.c
+++ b/backends/smart/pk-backend-smart.c
@@ -23,6 +23,7 @@
 #include <pk-backend.h>
 #include <pk-backend-spawn.h>
 #include <pk-package-ids.h>
+#include <pk-common.h>
 
 static PkBackendSpawn *spawn;
 
@@ -144,7 +145,7 @@ backend_download_packages (PkBackend *backend, gchar **package_ids, const gchar
 	gchar *package_ids_temp;
 
 	/* send the complete list as stdin */
-	package_ids_temp = pk_package_ids_to_text (package_ids, "|");
+	package_ids_temp = pk_package_ids_to_text (package_ids);
 	pk_backend_spawn_helper (spawn, BACKEND("download-packages"), directory, package_ids_temp, NULL);
 	g_free (package_ids_temp);
 }
@@ -157,7 +158,7 @@ backend_get_depends (PkBackend *backend, PkBitfield filters, gchar **package_ids
 {
 	gchar *filters_text;
 	gchar *package_ids_temp;
-	package_ids_temp = pk_package_ids_to_text (package_ids, "|");
+	package_ids_temp = pk_package_ids_to_text (package_ids);
 	filters_text = pk_filter_bitfield_to_text (filters);
 	pk_backend_spawn_helper (spawn, BACKEND("get-depends"), filters_text, package_ids_temp, pk_backend_bool_to_text (recursive), NULL);
 	g_free (filters_text);
@@ -171,7 +172,7 @@ static void
 backend_get_details (PkBackend *backend, gchar **package_ids)
 {
 	gchar *package_ids_temp;
-	package_ids_temp = pk_package_ids_to_text (package_ids, "|");
+	package_ids_temp = pk_package_ids_to_text (package_ids);
 	pk_backend_spawn_helper (spawn, BACKEND("get-details"), package_ids_temp, NULL);
 	g_free (package_ids_temp);
 }
@@ -183,7 +184,7 @@ static void
 backend_get_files (PkBackend *backend, gchar **package_ids)
 {
 	gchar *package_ids_temp;
-	package_ids_temp = pk_package_ids_to_text (package_ids, "|");
+	package_ids_temp = pk_package_ids_to_text (package_ids);
 	pk_backend_spawn_helper (spawn, BACKEND("get-files"), package_ids_temp, NULL);
 	g_free (package_ids_temp);
 }
@@ -195,7 +196,7 @@ static void
 backend_get_requires (PkBackend *backend, PkBitfield filters, gchar **package_ids, gboolean recursive)
 {
 	gchar *package_ids_temp;
-	package_ids_temp = pk_package_ids_to_text (package_ids, "|");
+	package_ids_temp = pk_package_ids_to_text (package_ids);
 	gchar *filters_text;
 	filters_text = pk_filter_bitfield_to_text (filters);
 	pk_backend_spawn_helper (spawn, BACKEND("get-requires"), filters_text, package_ids_temp, pk_backend_bool_to_text (recursive), NULL);
@@ -234,7 +235,7 @@ static void
 backend_get_update_detail (PkBackend *backend, gchar **package_ids)
 {
 	gchar *package_ids_temp;
-	package_ids_temp = pk_package_ids_to_text (package_ids, "|");
+	package_ids_temp = pk_package_ids_to_text (package_ids);
 	pk_backend_spawn_helper (spawn, BACKEND("get-update-detail"), package_ids_temp, NULL);
 	g_free (package_ids_temp);
 }
@@ -255,7 +256,7 @@ backend_install_packages (PkBackend *backend, gchar **package_ids)
 	}
 
 	/* send the complete list as stdin */
-	package_ids_temp = pk_package_ids_to_text (package_ids, "|");
+	package_ids_temp = pk_package_ids_to_text (package_ids);
 	pk_backend_spawn_helper (spawn, BACKEND("install-packages"), package_ids_temp, NULL);
 	g_free (package_ids_temp);
 }
@@ -269,7 +270,7 @@ backend_install_files (PkBackend *backend, gboolean trusted, gchar **full_paths)
 	gchar *full_paths_temp;
 
 	/* send the complete list as stdin */
-	full_paths_temp = pk_package_ids_to_text (full_paths, "|");
+	full_paths_temp = pk_strv_to_text (full_paths, PK_BACKEND_SPAWN_FILENAME_DELIM);
 	pk_backend_spawn_helper (spawn, BACKEND("install-files"), pk_backend_bool_to_text (trusted), full_paths_temp, NULL);
 	g_free (full_paths_temp);
 }
@@ -299,7 +300,7 @@ backend_remove_packages (PkBackend *backend, gchar **package_ids, gboolean allow
 	gchar *package_ids_temp;
 
 	/* send the complete list as stdin */
-	package_ids_temp = pk_package_ids_to_text (package_ids, "|");
+	package_ids_temp = pk_package_ids_to_text (package_ids);
 	/* FIXME: Use autoremove */
 	pk_backend_spawn_helper (spawn, BACKEND("remove-packages"), pk_backend_bool_to_text (allow_deps), package_ids_temp, NULL);
 	g_free (package_ids_temp);
@@ -369,7 +370,7 @@ backend_update_packages (PkBackend *backend, gchar **package_ids)
 	}
 
 	/* send the complete list as stdin */
-	package_ids_temp = pk_package_ids_to_text (package_ids, "|");
+	package_ids_temp = pk_package_ids_to_text (package_ids);
 	pk_backend_spawn_helper (spawn, BACKEND("update-packages"), package_ids_temp, NULL);
 	g_free (package_ids_temp);
 }
@@ -392,7 +393,7 @@ backend_resolve (PkBackend *backend, PkBitfield filters, gchar **package_ids)
 	gchar *filters_text;
 	gchar *package_ids_temp;
 	filters_text = pk_filter_bitfield_to_text (filters);
-	package_ids_temp = pk_package_ids_to_text (package_ids, "|");
+	package_ids_temp = pk_package_ids_to_text (package_ids);
 	pk_backend_spawn_helper (spawn, BACKEND("resolve"), filters_text, package_ids_temp, NULL);
 	g_free (filters_text);
 	g_free (package_ids_temp);
diff --git a/backends/urpmi/helpers/urpmi-dispatched-backend.pl b/backends/urpmi/helpers/urpmi-dispatched-backend.pl
index f303280..e769f50 100755
--- a/backends/urpmi/helpers/urpmi-dispatched-backend.pl
+++ b/backends/urpmi/helpers/urpmi-dispatched-backend.pl
@@ -790,8 +790,8 @@ sub _print_package_update_details {
   }
   
   pk_print_update_detail(get_package_id($pkg),
-    join("^", @to_upgrade_pkids),
-    join("^", map(fullname_to_package_id($_), @to_remove)),
+    join("&", @to_upgrade_pkids),
+    join("&", map(fullname_to_package_id($_), @to_remove)),
     "http://qa.mandriva.com",
     "http://qa.mandriva.com",
     "http://qa.mandriva.com",
diff --git a/backends/urpmi/pk-backend-urpmi.c b/backends/urpmi/pk-backend-urpmi.c
index 5362cb9..0ae8e8f 100644
--- a/backends/urpmi/pk-backend-urpmi.c
+++ b/backends/urpmi/pk-backend-urpmi.c
@@ -131,7 +131,7 @@ static void
 backend_get_details (PkBackend *backend, gchar **package_ids)
 {
 	gchar *package_ids_temp;
-	package_ids_temp = pk_package_ids_to_text (package_ids, "|");
+	package_ids_temp = pk_package_ids_to_text (package_ids);
 	pk_backend_spawn_helper (spawn, "urpmi-dispatched-backend.pl", "get-details", package_ids_temp, NULL);
 	g_free (package_ids_temp);
 }
@@ -143,7 +143,7 @@ static void
 backend_get_files (PkBackend *backend, gchar **package_ids)
 {
 	gchar *package_ids_temp;
-	package_ids_temp = pk_package_ids_to_text (package_ids, "|");
+	package_ids_temp = pk_package_ids_to_text (package_ids);
 	pk_backend_spawn_helper (spawn, "urpmi-dispatched-backend.pl", "get-files", package_ids_temp, NULL);
 	g_free (package_ids_temp);
 }
@@ -156,7 +156,7 @@ backend_get_depends (PkBackend *backend, PkBitfield filters, gchar **package_ids
 {
 	gchar *filters_text;
 	gchar *package_ids_temp;
-	package_ids_temp = pk_package_ids_to_text (package_ids, "|");
+	package_ids_temp = pk_package_ids_to_text (package_ids);
 	filters_text = pk_filter_bitfield_to_text (filters);
 	pk_backend_spawn_helper (spawn, "urpmi-dispatched-backend.pl", "get-depends", filters_text, package_ids_temp, pk_backend_bool_to_text (recursive), NULL);
 	g_free (filters_text);
@@ -182,7 +182,7 @@ static void
 backend_get_update_detail (PkBackend *backend, gchar **package_ids)
 {
 	gchar *package_ids_temp;
-	package_ids_temp = pk_package_ids_to_text (package_ids, "|");
+	package_ids_temp = pk_package_ids_to_text (package_ids);
 	pk_backend_spawn_helper (spawn, "urpmi-dispatched-backend.pl", "get-update-detail", package_ids_temp, NULL);
 	g_free (package_ids_temp);
 }
@@ -219,7 +219,7 @@ backend_install_packages (PkBackend *backend, gchar **package_ids)
 	}
 
 	/* send the complete list as stdin */
-	package_ids_temp = pk_package_ids_to_text (package_ids, "|");
+	package_ids_temp = pk_package_ids_to_text (package_ids);
 	pk_backend_spawn_helper (spawn, "urpmi-dispatched-backend.pl", "install-packages", package_ids_temp, NULL);
 	g_free (package_ids_temp);
 }
@@ -233,7 +233,7 @@ backend_remove_packages (PkBackend *backend, gchar **package_ids, gboolean allow
 	gchar *package_ids_temp;
 
 	/* send the complete list as stdin */
-	package_ids_temp = pk_package_ids_to_text (package_ids, "|");
+	package_ids_temp = pk_package_ids_to_text (package_ids);
 	pk_backend_spawn_helper (spawn, "urpmi-dispatched-backend.pl", "remove-packages", pk_backend_bool_to_text (allow_deps), package_ids_temp, NULL);
 	g_free (package_ids_temp);
 }
@@ -269,7 +269,7 @@ static void
 backend_get_requires (PkBackend *backend, PkBitfield filters, gchar **package_ids, gboolean recursive)
 {
 	gchar *package_ids_temp;
-	package_ids_temp = pk_package_ids_to_text (package_ids, "|");
+	package_ids_temp = pk_package_ids_to_text (package_ids);
 	gchar *filters_text;
 	filters_text = pk_filter_bitfield_to_text (filters);
 	pk_backend_spawn_helper (spawn, "urpmi-dispatched-backend.pl", "get-requires", filters_text, package_ids_temp, pk_backend_bool_to_text (recursive), NULL);
@@ -310,7 +310,7 @@ backend_resolve (PkBackend *backend, PkBitfield filters, gchar **package_ids)
 	gchar *filters_text;
 	gchar *package_ids_temp;
 	filters_text = pk_filter_bitfield_to_text (filters);
-	package_ids_temp = pk_package_ids_to_text (package_ids, "|");
+	package_ids_temp = pk_package_ids_to_text (package_ids);
 	pk_backend_spawn_helper (spawn, "urpmi-dispatched-backend.pl", "resolve", filters_text, package_ids_temp, NULL);
 	g_free (filters_text);
 	g_free (package_ids_temp);
@@ -333,7 +333,7 @@ backend_update_packages (PkBackend *backend, gchar **package_ids)
 	}
 
 	/* send the complete list as stdin */
-	package_ids_temp = pk_package_ids_to_text (package_ids, "|");
+	package_ids_temp = pk_package_ids_to_text (package_ids);
 	pk_backend_spawn_helper (spawn, "urpmi-dispatched-backend.pl", "update-packages", package_ids_temp, NULL);
 	g_free (package_ids_temp);
 }
diff --git a/backends/yum/pk-backend-yum.c b/backends/yum/pk-backend-yum.c
index be6f420..ff70758 100644
--- a/backends/yum/pk-backend-yum.c
+++ b/backends/yum/pk-backend-yum.c
@@ -22,6 +22,7 @@
 #include <pk-backend.h>
 #include <pk-backend-spawn.h>
 #include <pk-package-ids.h>
+#include <pk-common.h>
 
 static PkBackendSpawn *spawn;
 
@@ -126,7 +127,7 @@ backend_download_packages (PkBackend *backend, gchar **package_ids, const gchar
 	gchar *package_ids_temp;
 
 	/* send the complete list as stdin */
-	package_ids_temp = pk_package_ids_to_text (package_ids, "|");
+	package_ids_temp = pk_package_ids_to_text (package_ids);
 	pk_backend_spawn_helper (spawn, "yumBackend.py", "download-packages", directory, package_ids_temp, NULL);
 	g_free (package_ids_temp);
 }
@@ -139,7 +140,7 @@ backend_get_depends (PkBackend *backend, PkBitfield filters, gchar **package_ids
 {
 	gchar *filters_text;
 	gchar *package_ids_temp;
-	package_ids_temp = pk_package_ids_to_text (package_ids, "|");
+	package_ids_temp = pk_package_ids_to_text (package_ids);
 	filters_text = pk_filter_bitfield_to_text (filters);
 	pk_backend_spawn_helper (spawn, "yumBackend.py", "get-depends", filters_text, package_ids_temp, pk_backend_bool_to_text (recursive), NULL);
 	g_free (filters_text);
@@ -153,7 +154,7 @@ static void
 backend_get_details (PkBackend *backend, gchar **package_ids)
 {
 	gchar *package_ids_temp;
-	package_ids_temp = pk_package_ids_to_text (package_ids, "|");
+	package_ids_temp = pk_package_ids_to_text (package_ids);
 	pk_backend_spawn_helper (spawn, "yumBackend.py", "get-details", package_ids_temp, NULL);
 	g_free (package_ids_temp);
 }
@@ -174,7 +175,7 @@ static void
 backend_get_files (PkBackend *backend, gchar **package_ids)
 {
 	gchar *package_ids_temp;
-	package_ids_temp = pk_package_ids_to_text (package_ids, "|");
+	package_ids_temp = pk_package_ids_to_text (package_ids);
 	pk_backend_spawn_helper (spawn,  "yumBackend.py", "get-files", package_ids_temp, NULL);
 	g_free (package_ids_temp);
 }
@@ -186,7 +187,7 @@ static void
 backend_get_requires (PkBackend *backend, PkBitfield filters, gchar **package_ids, gboolean recursive)
 {
 	gchar *package_ids_temp;
-	package_ids_temp = pk_package_ids_to_text (package_ids, "|");
+	package_ids_temp = pk_package_ids_to_text (package_ids);
 	gchar *filters_text;
 	filters_text = pk_filter_bitfield_to_text (filters);
 	pk_backend_spawn_helper (spawn, "yumBackend.py", "get-requires", filters_text, package_ids_temp, pk_backend_bool_to_text (recursive), NULL);
@@ -225,7 +226,7 @@ static void
 backend_get_update_detail (PkBackend *backend, gchar **package_ids)
 {
 	gchar *package_ids_temp;
-	package_ids_temp = pk_package_ids_to_text (package_ids, "|");
+	package_ids_temp = pk_package_ids_to_text (package_ids);
 	pk_backend_spawn_helper (spawn, "yumBackend.py", "get-update-detail", package_ids_temp, NULL);
 	g_free (package_ids_temp);
 }
@@ -246,7 +247,7 @@ backend_install_packages (PkBackend *backend, gchar **package_ids)
 	}
 
 	/* send the complete list as stdin */
-	package_ids_temp = pk_package_ids_to_text (package_ids, "|");
+	package_ids_temp = pk_package_ids_to_text (package_ids);
 	pk_backend_spawn_helper (spawn, "yumBackend.py", "install-packages", package_ids_temp, NULL);
 	g_free (package_ids_temp);
 }
@@ -260,7 +261,7 @@ backend_install_files (PkBackend *backend, gboolean trusted, gchar **full_paths)
 	gchar *package_ids_temp;
 
 	/* send the complete list as stdin */
-	package_ids_temp = pk_package_ids_to_text (full_paths, "|");
+	package_ids_temp = pk_strv_to_text (full_paths, PK_BACKEND_SPAWN_FILENAME_DELIM);
 	pk_backend_spawn_helper (spawn, "yumBackend.py", "install-files", pk_backend_bool_to_text (trusted), package_ids_temp, NULL);
 	g_free (package_ids_temp);
 }
@@ -303,7 +304,7 @@ backend_remove_packages (PkBackend *backend, gchar **package_ids, gboolean allow
 	gchar *package_ids_temp;
 
 	/* send the complete list as stdin */
-	package_ids_temp = pk_package_ids_to_text (package_ids, "|");
+	package_ids_temp = pk_package_ids_to_text (package_ids);
 	pk_backend_spawn_helper (spawn, "yumBackend.py", "remove-packages", pk_backend_bool_to_text (allow_deps), package_ids_temp, NULL);
 	g_free (package_ids_temp);
 }
@@ -372,7 +373,7 @@ backend_update_packages (PkBackend *backend, gchar **package_ids)
 	}
 
 	/* send the complete list as stdin */
-	package_ids_temp = pk_package_ids_to_text (package_ids, "|");
+	package_ids_temp = pk_package_ids_to_text (package_ids);
 	pk_backend_spawn_helper (spawn, "yumBackend.py", "update-packages", package_ids_temp, NULL);
 	g_free (package_ids_temp);
 }
@@ -395,7 +396,7 @@ backend_resolve (PkBackend *backend, PkBitfield filters, gchar **package_ids)
 	gchar *filters_text;
 	gchar *package_ids_temp;
 	filters_text = pk_filter_bitfield_to_text (filters);
-	package_ids_temp = pk_package_ids_to_text (package_ids, "|");
+	package_ids_temp = pk_package_ids_to_text (package_ids);
 	pk_backend_spawn_helper (spawn, "yumBackend.py", "resolve", filters_text, package_ids_temp, NULL);
 	g_free (filters_text);
 	g_free (package_ids_temp);
diff --git a/backends/zypp/pk-backend-zypp.cpp b/backends/zypp/pk-backend-zypp.cpp
index 7a089be..5330d2c 100644
--- a/backends/zypp/pk-backend-zypp.cpp
+++ b/backends/zypp/pk-backend-zypp.cpp
@@ -55,6 +55,8 @@
 #include <map>
 #include <list>
 
+#include <pk-package-ids.h>
+
 #include "zypp-utils.h"
 #include "zypp-events.h"
 
@@ -924,11 +926,11 @@ backend_get_update_detail_thread (PkBackend *backend)
 			zypp::sat::SolvableSet content = patch->contents ();
 
 			for (zypp::sat::SolvableSet::const_iterator it = content.begin (); it != content.end (); it++) {
-				//obsoletes = g_strconcat (obsoletes, zypp_build_package_id_capabilities (it->obsoletes ()), "^", (gchar *)NULL);
+				//obsoletes = g_strconcat (obsoletes, zypp_build_package_id_capabilities (it->obsoletes ()), PK_PACKAGE_IDS_DELIM, (gchar *)NULL);
 				if (strlen(obsoletes) == 0) {
 					obsoletes = zypp_build_package_id_capabilities (it->obsoletes ());
 				} else {
-					obsoletes = g_strconcat (obsoletes, "^", zypp_build_package_id_capabilities (it->obsoletes ()), (gchar *)NULL);
+					obsoletes = g_strconcat (obsoletes, PK_PACKAGE_IDS_DELIM, zypp_build_package_id_capabilities (it->obsoletes ()), (gchar *)NULL);
 				}
 			}
 		}
diff --git a/backends/zypp/zypp-utils.cpp b/backends/zypp/zypp-utils.cpp
index 8becd3c..51bdcdb 100644
--- a/backends/zypp/zypp-utils.cpp
+++ b/backends/zypp/zypp-utils.cpp
@@ -53,6 +53,7 @@
 #include <zypp/base/Logger.h>
 
 #include <pk-backend.h>
+#include <pk-package-ids.h>
 
 #include "zypp-utils.h"
 
@@ -881,11 +882,11 @@ zypp_build_package_id_capabilities (zypp::Capabilities caps)
 
 	for (zypp::sat::WhatProvides::const_iterator it = provs.begin (); it != provs.end (); it++) {
 		gchar *package_id = zypp_build_package_id_from_resolvable (*it);
-		//package_ids = g_strconcat (package_ids, package_id, "^", (gchar *)NULL);
+		//package_ids = g_strconcat (package_ids, package_id, PK_PACKAGE_IDS_DELIM, (gchar *)NULL);
 		if (strlen (package_ids) == 0) {			
 			package_ids = g_strdup (package_id);
 		} else {
-			package_ids = g_strconcat (package_ids, "^", package_id, (gchar *)NULL);
+			package_ids = g_strconcat (package_ids, PK_PACKAGE_IDS_DELIM, package_id, (gchar *)NULL);
 		}
 		g_free (package_id);
 	}
diff --git a/contrib/PackageKit.spec.in b/contrib/PackageKit.spec.in
index 71b7070..6b1a0f4 100644
--- a/contrib/PackageKit.spec.in
+++ b/contrib/PackageKit.spec.in
@@ -154,10 +154,10 @@ codecs from configured repositories using PackageKit.
 
 %build
 # build and test on all architectures
-%configure --enable-dummy --with-default-backend=dummy --enable-tests --enable-local
-make %{?_smp_mflags}
-make check -C libpackagekit
-make check -C src
+#%configure --enable-dummy --with-default-backend=dummy --enable-tests --enable-local
+#make %{?_smp_mflags}
+#make check -C libpackagekit
+#make check -C src
 
 # reconfigure with testing off (smaller binaries)
 %configure --enable-yum --enable-smart --with-default-backend=yum --disable-local
diff --git a/libpackagekit/pk-client.c b/libpackagekit/pk-client.c
index 0a6c438..cab6c4f 100644
--- a/libpackagekit/pk-client.c
+++ b/libpackagekit/pk-client.c
@@ -1539,7 +1539,7 @@ pk_client_get_depends (PkClient *client, PkBitfield filters, gchar **package_ids
 	/* check the PackageIDs here to avoid a round trip if invalid */
 	ret = pk_package_ids_check (package_ids);
 	if (!ret) {
-		package_ids_temp = pk_package_ids_to_text (package_ids, ", ");
+		package_ids_temp = pk_package_ids_to_text (package_ids);
 		pk_client_error_set (error, PK_CLIENT_ERROR_INVALID_PACKAGEID,
 				     "package_ids '%s' are not valid", package_ids_temp);
 		g_free (package_ids_temp);
@@ -1603,7 +1603,7 @@ pk_client_download_packages (PkClient *client, gchar **package_ids, const gchar
         /* check the PackageIDs here to avoid a round trip if invalid */
         ret = pk_package_ids_check (package_ids);
         if (!ret) {
-                package_ids_temp = pk_package_ids_to_text (package_ids, ", ");
+                package_ids_temp = pk_package_ids_to_text (package_ids);
                 pk_client_error_set (error, PK_CLIENT_ERROR_INVALID_PACKAGEID,
                                      "package_ids '%s' are not valid", package_ids_temp);
                 g_free (package_ids_temp);
@@ -1751,7 +1751,7 @@ pk_client_get_requires (PkClient *client, PkBitfield filters, gchar **package_id
 	/* check the PackageIDs here to avoid a round trip if invalid */
 	ret = pk_package_ids_check (package_ids);
 	if (!ret) {
-		package_ids_temp = pk_package_ids_to_text (package_ids, ", ");
+		package_ids_temp = pk_package_ids_to_text (package_ids);
 		pk_client_error_set (error, PK_CLIENT_ERROR_INVALID_PACKAGEID,
 				     "package_ids '%s' are not valid", package_ids_temp);
 		g_free (package_ids_temp);
@@ -1881,7 +1881,7 @@ pk_client_get_update_detail (PkClient *client, gchar **package_ids, GError **err
 	/* check the PackageIDs here to avoid a round trip if invalid */
 	ret = pk_package_ids_check (package_ids);
 	if (!ret) {
-		package_ids_temp = pk_package_ids_to_text (package_ids, ", ");
+		package_ids_temp = pk_package_ids_to_text (package_ids);
 		pk_client_error_set (error, PK_CLIENT_ERROR_INVALID_PACKAGEID,
 				     "package_ids '%s' are not valid", package_ids_temp);
 		g_free (package_ids_temp);
@@ -2045,7 +2045,7 @@ pk_client_get_details (PkClient *client, gchar **package_ids, GError **error)
 	/* check the PackageIDs here to avoid a round trip if invalid */
 	ret = pk_package_ids_check (package_ids);
 	if (!ret) {
-		package_ids_temp = pk_package_ids_to_text (package_ids, ", ");
+		package_ids_temp = pk_package_ids_to_text (package_ids);
 		pk_client_error_set (error, PK_CLIENT_ERROR_INVALID_PACKAGEID,
 				     "package_ids '%s' are not valid", package_ids_temp);
 		g_free (package_ids_temp);
@@ -2149,7 +2149,7 @@ pk_client_get_files (PkClient *client, gchar **package_ids, GError **error)
 	/* check the PackageIDs here to avoid a round trip if invalid */
 	ret = pk_package_ids_check (package_ids);
 	if (!ret) {
-		package_ids_temp = pk_package_ids_to_text (package_ids, ", ");
+		package_ids_temp = pk_package_ids_to_text (package_ids);
 		pk_client_error_set (error, PK_CLIENT_ERROR_INVALID_PACKAGEID,
 				     "package_ids '%s' are not valid", package_ids_temp);
 		g_free (package_ids_temp);
@@ -2241,7 +2241,7 @@ pk_client_remove_packages (PkClient *client, gchar **package_ids, gboolean allow
 	/* check the PackageIDs here to avoid a round trip if invalid */
 	ret = pk_package_ids_check (package_ids);
 	if (!ret) {
-		package_ids_temp = pk_package_ids_to_text (package_ids, ", ");
+		package_ids_temp = pk_package_ids_to_text (package_ids);
 		pk_client_error_set (error, PK_CLIENT_ERROR_INVALID_PACKAGEID,
 				     "package_ids '%s' are not valid", package_ids_temp);
 		g_free (package_ids_temp);
@@ -2422,7 +2422,7 @@ pk_client_install_packages (PkClient *client, gchar **package_ids, GError **erro
 	/* check the PackageIDs here to avoid a round trip if invalid */
 	ret = pk_package_ids_check (package_ids);
 	if (!ret) {
-		package_ids_temp = pk_package_ids_to_text (package_ids, ", ");
+		package_ids_temp = pk_package_ids_to_text (package_ids);
 		pk_client_error_set (error, PK_CLIENT_ERROR_INVALID_PACKAGEID,
 				     "package_ids '%s' are not valid", package_ids_temp);
 		g_free (package_ids_temp);
@@ -2616,7 +2616,7 @@ pk_client_update_packages (PkClient *client, gchar **package_ids, GError **error
 	/* check the PackageIDs here to avoid a round trip if invalid */
 	ret = pk_package_ids_check (package_ids);
 	if (!ret) {
-		package_ids_temp = pk_package_ids_to_text (package_ids, ", ");
+		package_ids_temp = pk_package_ids_to_text (package_ids);
 		pk_client_error_set (error, PK_CLIENT_ERROR_INVALID_PACKAGEID,
 				     "package_ids '%s' are not valid", package_ids_temp);
 		g_free (package_ids_temp);
diff --git a/libpackagekit/pk-common.c b/libpackagekit/pk-common.c
index 98de613..f31f9bd 100644
--- a/libpackagekit/pk-common.c
+++ b/libpackagekit/pk-common.c
@@ -415,36 +415,12 @@ pk_strv_to_ptr_array (gchar **array)
 	return parray;
 }
 
-
-/**
- * pk_va_list_to_argv_string:
- **/
-static void
-pk_va_list_to_argv_string (GPtrArray *ptr_array, const gchar *string)
-{
-	gchar **array;
-	guint length;
-	guint i;
-
-	/* split the string up by spaces */
-	array = g_strsplit (string, "|", 0);
-
-	/* for each */
-	length = g_strv_length (array);
-	for (i=0; i<length; i++) {
-		g_ptr_array_add (ptr_array, g_strdup (array[i]));
-	}
-	g_strfreev (array);
-}
-
 /**
  * pk_va_list_to_argv:
  * @string_first: the first string
  * @args: any subsequant string's
  *
- * Form a composite string array of string, with a special twist;
- * if the entry contains a '|', then it is split as seporate parts
- * of the array.
+ * Form a composite string array of the va_list
  *
  * Return value: the string array, or %NULL if invalid
  **/
@@ -461,16 +437,14 @@ pk_va_list_to_argv (const gchar *string_first, va_list *args)
 
 	/* find how many elements we have in a temp array */
 	ptr_array = g_ptr_array_new ();
-	pk_va_list_to_argv_string (ptr_array, string_first);
+	g_ptr_array_add (ptr_array, g_strdup (string_first));
 
 	/* process all the va_list entries */
 	for (i=0;; i++) {
 		value_temp = va_arg (*args, gchar *);
-		/* end of array */
-		if (value_temp == NULL) break;
-
-		/* split the string up by spaces */
-		pk_va_list_to_argv_string (ptr_array, value_temp);
+		if (value_temp == NULL)
+			break;
+		g_ptr_array_add (ptr_array, g_strdup (value_temp));
 	}
 
 	/* convert the array to a strv type */
@@ -482,6 +456,52 @@ pk_va_list_to_argv (const gchar *string_first, va_list *args)
 	return array;
 }
 
+/**
+ * pk_strv_to_text:
+ * @array: a string array of package_id's
+ *
+ * Cats the string array of package_id's into one tab delimited string
+ *
+ * Return value: a string representation of all the package_id's.
+ **/
+gchar *
+pk_strv_to_text (gchar **array, const gchar *delimiter)
+{
+	guint i;
+	guint size;
+	GString *string;
+	gchar *string_ret;
+
+	g_return_val_if_fail (array != NULL, NULL);
+	g_return_val_if_fail (delimiter != NULL, NULL);
+
+	string = g_string_new ("");
+
+	/* print all */
+	size = g_strv_length (array);
+
+	/* shortcut */
+	if (size == 1)
+		return g_strdup (array[0]);
+
+	/* append with delimiter */
+	for (i=0; i<size; i++) {
+		g_string_append (string, array[i]);
+		g_string_append (string, delimiter);
+	}
+
+	/* ITS4: ignore, we check this for validity */
+	size = strlen (delimiter);
+
+	/* remove trailing delimiter */
+	if (string->len > size)
+		g_string_set_size (string, string->len-size);
+
+	string_ret = g_string_free (string, FALSE);
+
+	return string_ret;
+}
+
 /***************************************************************************
  ***                          MAKE CHECK TESTS                           ***
  ***************************************************************************/
@@ -507,6 +527,7 @@ pk_common_test (EggTest *test)
 {
 	gboolean ret;
 	gchar **array;
+	gchar *text;
 	gchar *text_safe;
 	gchar *present;
 	guint seconds;
@@ -550,27 +571,14 @@ pk_common_test (EggTest *test)
 	g_strfreev (array);
 
 	/************************************************************/
-	egg_test_title (test, "va_list_to_argv triple with space first");
-	array = pk_va_list_to_argv_test ("richard|phillip", "hughes", NULL);
-	if (egg_strequal (array[0], "richard") &&
-	    egg_strequal (array[1], "phillip") &&
-	    egg_strequal (array[2], "hughes") &&
-	    array[3] == NULL)
-		egg_test_success (test, NULL);
-	else
-		egg_test_failed (test, "incorrect array '%s','%s','%s'", array[0], array[1], array[2]);
-	g_strfreev (array);
-
-	/************************************************************/
-	egg_test_title (test, "va_list_to_argv triple with space second");
-	array = pk_va_list_to_argv_test ("richard", "phillip|hughes", NULL);
-	if (egg_strequal (array[0], "richard") &&
-	    egg_strequal (array[1], "phillip") &&
-	    egg_strequal (array[2], "hughes") &&
-	    array[3] == NULL)
+	egg_test_title (test, "to text");
+	array = pk_va_list_to_argv_test ("richard", "phillip", "hughes", NULL);
+	text = pk_strv_to_text (array, "\t");
+	if (egg_strequal (text, "richard\tphillip\thughes"))
 		egg_test_success (test, NULL);
 	else
-		egg_test_failed (test, "incorrect array '%s','%s','%s'", array[0], array[1], array[2]);
+		egg_test_failed (test, NULL);
+	g_free (text);
 	g_strfreev (array);
 
 	/************************************************************
diff --git a/libpackagekit/pk-common.h b/libpackagekit/pk-common.h
index aebd9d3..e3faf26 100644
--- a/libpackagekit/pk-common.h
+++ b/libpackagekit/pk-common.h
@@ -79,6 +79,9 @@ gchar		*pk_iso8601_from_date			(const GDate	*date);
 GDate		*pk_iso8601_to_date			(const gchar	*iso_date);
 gchar		*pk_get_distro_id			(void)
 							 G_GNUC_WARN_UNUSED_RESULT;
+gchar		*pk_strv_to_text			(gchar		**package_ids,
+							 const gchar	*delimiter)
+							 G_GNUC_WARN_UNUSED_RESULT;
 
 G_END_DECLS
 
diff --git a/libpackagekit/pk-package-ids.c b/libpackagekit/pk-package-ids.c
index ee34472..2c1f787 100644
--- a/libpackagekit/pk-package-ids.c
+++ b/libpackagekit/pk-package-ids.c
@@ -53,7 +53,7 @@
 gchar **
 pk_package_ids_from_id (const gchar *package_id)
 {
-	return g_strsplit (package_id, "|", 1);
+	return g_strsplit (package_id, PK_PACKAGE_IDS_DELIM, 1);
 }
 
 /**
@@ -109,9 +109,8 @@ pk_package_ids_check (gchar **package_ids)
 	for (i=0; i<size; i++) {
 		package_id = package_ids[i];
 		ret = pk_package_id_check (package_id);
-		if (!ret) {
+		if (!ret)
 			return FALSE;
-		}
 	}
 	return TRUE;
 }
@@ -164,40 +163,12 @@ pk_package_ids_size (gchar **package_ids)
  * Return value: a string representation of all the package_id's.
  **/
 gchar *
-pk_package_ids_to_text (gchar **package_ids, const gchar *delimiter)
+pk_package_ids_to_text (gchar **package_ids)
 {
-	guint i;
-	guint size;
-	GString *string;
-	gchar *string_ret;
-
-	g_return_val_if_fail (delimiter != NULL, NULL);
-
 	/* special case as this is allowed */
-	if (package_ids == NULL) {
+	if (package_ids == NULL)
 		return g_strdup ("(null)");
-	}
-
-	string = g_string_new ("");
-
-	/* print all */
-	size = g_strv_length (package_ids);
-	for (i=0; i<size; i++) {
-		g_string_append (string, package_ids[i]);
-		g_string_append (string, delimiter);
-	}
-
-	/* ITS4: ignore, we check this for validity */
-	size = strlen (delimiter);
-
-	/* remove trailing delimiter */
-	if (string->len > size) {
-		g_string_set_size (string, string->len-size);
-	}
-
-	string_ret = g_string_free (string, FALSE);
-
-	return string_ret;
+	return pk_strv_to_text (package_ids, PK_PACKAGE_IDS_DELIM);
 }
 
 /***************************************************************************
@@ -228,7 +199,6 @@ void
 pk_package_ids_test (EggTest *test)
 {
 	gboolean ret;
-	gchar *text;
 	gchar **package_ids;
 	guint size;
 
@@ -268,15 +238,6 @@ pk_package_ids_test (EggTest *test)
 	ret = pk_package_ids_print (package_ids);
 	egg_test_assert (test, ret);
 
-	/************************************************************/
-	egg_test_title (test, "to text");
-	text = pk_package_ids_to_text (package_ids, "\t");
-	if (egg_strequal (text, "foo;0.0.1;i386;fedora\tbar;0.1.1;noarch;livna"))
-		egg_test_success (test, NULL);
-	else
-		egg_test_failed (test, NULL);
-	g_free (text);
-
 	g_strfreev (package_ids);
 
 	egg_test_end (test);
diff --git a/libpackagekit/pk-package-ids.h b/libpackagekit/pk-package-ids.h
index a7cc7ee..c1a2a44 100644
--- a/libpackagekit/pk-package-ids.h
+++ b/libpackagekit/pk-package-ids.h
@@ -26,6 +26,19 @@
 
 G_BEGIN_DECLS
 
+/* rationalle:
+ *
+ * '%': breaks printf
+ * '|': used as the filename seporator
+ * '~': conary
+ * '@': conary
+ *
+ * If this has to be changed, also change:
+ * - backends/urpmi/helpers/urpmi-dispatched-backend.pl
+ * - python/packagekit/backend.py
+ */
+#define PK_PACKAGE_IDS_DELIM	"&"
+
 gchar		**pk_package_ids_from_id		(const gchar	*package_id);
 gchar		**pk_package_ids_from_array		(GPtrArray	*array);
 gchar		**pk_package_ids_from_va_list		(const gchar	*package_id_first,
@@ -34,8 +47,7 @@ gboolean	 pk_package_ids_check			(gchar		**package_ids)
 							 G_GNUC_WARN_UNUSED_RESULT;
 gboolean	 pk_package_ids_print			(gchar		**package_ids);
 guint		 pk_package_ids_size			(gchar		**package_ids);
-gchar		*pk_package_ids_to_text			(gchar		**package_ids,
-							 const gchar	*delimiter)
+gchar		*pk_package_ids_to_text			(gchar		**package_ids)
 							 G_GNUC_WARN_UNUSED_RESULT;
 
 G_END_DECLS
diff --git a/python/packagekit/backend.py b/python/packagekit/backend.py
index ff410d4..c4fefe8 100644
--- a/python/packagekit/backend.py
+++ b/python/packagekit/backend.py
@@ -29,6 +29,9 @@ sys.stdout = codecs.getwriter('utf-8')(sys.stdout)
 
 from enums import *
 
+PACKAGE_IDS_DELIM = '&'
+FILENAME_DELIM = '|'
+
 # Classes
 
 class PackageKitBaseBackend:
@@ -446,21 +449,21 @@ class PackageKitBaseBackend:
     def dispatch_command(self, cmd, args):
         if cmd == 'download-packages':
             directory = args[0]
-            pkgs = args[1:]
+            pkgs = args[1].split(PACKAGE_IDS_DELIM)
             self.download_packages(directory, pkgs)
             self.finished()
         elif cmd == 'get-depends':
             filters = args[0]
-            pkgs = args[1].split('|')
+            pkgs = args[1].split(PACKAGE_IDS_DELIM)
             recursive = args[2]
             self.get_depends(filters, pkgs, recursive)
             self.finished()
         elif cmd == 'get-details':
-            pkgs = args[0].split('|')
+            pkgs = args[0].split(PACKAGE_IDS_DELIM)
             self.get_details(pkgs)
             self.finished()
         elif cmd == 'get-files':
-            pkgs = args[0].split('|')
+            pkgs = args[0].split(PACKAGE_IDS_DELIM)
             self.get_files(pkgs)
             self.finished()
         elif cmd == 'get-packages':
@@ -473,12 +476,12 @@ class PackageKitBaseBackend:
             self.finished()
         elif cmd == 'get-requires':
             filters = args[0]
-            pkgs = args[1].split('|')
+            pkgs = args[1].split(PACKAGE_IDS_DELIM)
             recursive = args[2]
             self.get_requires(filters, pkgs, recursive)
             self.finished()
         elif cmd == 'get-update-detail':
-            pkgs = args[0].split('|')
+            pkgs = args[0].split(PACKAGE_IDS_DELIM)
             self.get_update_detail(pkgs)
             self.finished()
         elif cmd == 'get-distro-upgrades':
@@ -490,11 +493,11 @@ class PackageKitBaseBackend:
             self.finished()
         elif cmd == 'install-files':
             trusted = args[0]
-            files_to_inst = args[1:]
+            files_to_inst = args[1].split(FILENAME_DELIM)
             self.install_files(trusted, files_to_inst)
             self.finished()
         elif cmd == 'install-packages':
-            pkgs = args[0:]
+            pkgs = args[0].split(PACKAGE_IDS_DELIM)
             self.install_packages(pkgs)
             self.finished()
         elif cmd == 'install-signature':
@@ -508,7 +511,7 @@ class PackageKitBaseBackend:
             self.finished()
         elif cmd == 'remove-packages':
             allowdeps = args[0]
-            packages = args[1:]
+            packages = args[1].split(PACKAGE_IDS_DELIM)
             self.remove_packages(allowdeps, packages)
             self.finished()
         elif cmd == 'repo-enable':
@@ -524,7 +527,7 @@ class PackageKitBaseBackend:
             self.finished()
         elif cmd == 'resolve':
             filters = args[0]
-            packages = args[1:]
+            packages = args[1].split(PACKAGE_IDS_DELIM)
             self.resolve(filters, packages)
             self.finished()
         elif cmd == 'search-details':
@@ -552,7 +555,7 @@ class PackageKitBaseBackend:
             self.repo_signature_install(package)
             self.finished()
         elif cmd == 'update-packages':
-            packages = args[0:]
+            packages = args[0].split(PACKAGE_IDS_DELIM)
             self.update_packages(packages)
             self.finished()
         elif cmd == 'update-system':
diff --git a/src/pk-backend-spawn.h b/src/pk-backend-spawn.h
index e2a5459..5c320c2 100644
--- a/src/pk-backend-spawn.h
+++ b/src/pk-backend-spawn.h
@@ -34,6 +34,8 @@ G_BEGIN_DECLS
 #define PK_IS_BACKEND_SPAWN_CLASS(k)	(G_TYPE_CHECK_CLASS_TYPE ((k), PK_TYPE_BACKEND_SPAWN))
 #define PK_BACKEND_SPAWN_GET_CLASS(o)	(G_TYPE_INSTANCE_GET_CLASS ((o), PK_TYPE_BACKEND_SPAWN, PkBackendSpawnClass))
 
+#define PK_BACKEND_SPAWN_FILENAME_DELIM	"|"
+
 typedef struct PkBackendSpawnPrivate PkBackendSpawnPrivate;
 
 typedef struct
diff --git a/src/pk-interface-transaction.xml b/src/pk-interface-transaction.xml
index 09e5e70..8cc7aea 100644
--- a/src/pk-interface-transaction.xml
+++ b/src/pk-interface-transaction.xml
@@ -1943,11 +1943,9 @@
         <doc:doc>
           <doc:summary>
             <doc:para>
-              A list of package_id's that are to be updated, seporated by <literal>^</literal>.
+              A list of package_id's that are to be updated, seporated by <literal>&amp;</literal>.
               This odd delimited was chosen as <literal>\t</literal> is already being used in the
-              spawned backends, and <literal>^</literal> is a banned character in a package_id.
-              This will change in 0.3.x where <literal>updates</literal> will be a proper string
-              array field.
+              spawned backends, and <literal>&amp;</literal> is a banned character in a package_id.
             </doc:para>
           </doc:summary>
         </doc:doc>
@@ -1956,9 +1954,7 @@
         <doc:doc>
           <doc:summary>
             <doc:para>
-              A list of package_id's that are to be obsoleted, separated by <literal>^</literal>
-              This will change in 0.3.x where <literal>obsoletes</literal> will be a proper string
-              array field.
+              A list of package_id's that are to be obsoleted, separated by <literal>&amp;</literal>
             </doc:para>
           </doc:summary>
         </doc:doc>
diff --git a/src/pk-transaction.c b/src/pk-transaction.c
index 73f86dc..fdd976a 100644
--- a/src/pk-transaction.c
+++ b/src/pk-transaction.c
@@ -1385,7 +1385,7 @@ pk_transaction_download_packages (PkTransaction *transaction, gchar **package_id
 	/* check package_ids */
 	ret = pk_package_ids_check (package_ids);
 	if (!ret) {
-	        package_ids_temp = pk_package_ids_to_text (package_ids, ", ");
+	        package_ids_temp = pk_package_ids_to_text (package_ids);
 	        error = g_error_new (PK_TRANSACTION_ERROR, PK_TRANSACTION_ERROR_PACKAGE_ID_INVALID,
 	                             "The package id's '%s' are not valid", package_ids_temp);
 	        g_free (package_ids_temp);
@@ -1464,7 +1464,7 @@ pk_transaction_get_depends (PkTransaction *transaction, const gchar *filter, gch
 	g_return_if_fail (PK_IS_TRANSACTION (transaction));
 	g_return_if_fail (transaction->priv->tid != NULL);
 
-	package_ids_temp = pk_package_ids_to_text (package_ids, ", ");
+	package_ids_temp = pk_package_ids_to_text (package_ids);
 	egg_debug ("GetDepends method called: %s (recursive %i)", package_ids_temp, recursive);
 	g_free (package_ids_temp);
 
@@ -1487,7 +1487,7 @@ pk_transaction_get_depends (PkTransaction *transaction, const gchar *filter, gch
 	/* check package_ids */
 	ret = pk_package_ids_check (package_ids);
 	if (!ret) {
-		package_ids_temp = pk_package_ids_to_text (package_ids, ", ");
+		package_ids_temp = pk_package_ids_to_text (package_ids);
 		error = g_error_new (PK_TRANSACTION_ERROR, PK_TRANSACTION_ERROR_PACKAGE_ID_INVALID,
 				     "The package id's '%s' are not valid", package_ids_temp);
 		g_free (package_ids_temp);
@@ -1538,7 +1538,7 @@ pk_transaction_get_details (PkTransaction *transaction, gchar **package_ids, DBu
 	g_return_if_fail (PK_IS_TRANSACTION (transaction));
 	g_return_if_fail (transaction->priv->tid != NULL);
 
-	package_ids_temp = pk_package_ids_to_text (package_ids, ", ");
+	package_ids_temp = pk_package_ids_to_text (package_ids);
 	egg_debug ("GetDetails method called: %s", package_ids_temp);
 	g_free (package_ids_temp);
 
@@ -1554,7 +1554,7 @@ pk_transaction_get_details (PkTransaction *transaction, gchar **package_ids, DBu
 	/* check package_ids */
 	ret = pk_package_ids_check (package_ids);
 	if (!ret) {
-		package_ids_temp = pk_package_ids_to_text (package_ids, ", ");
+		package_ids_temp = pk_package_ids_to_text (package_ids);
 		error = g_error_new (PK_TRANSACTION_ERROR, PK_TRANSACTION_ERROR_PACKAGE_ID_INVALID,
 				     "The package id's '%s' are not valid", package_ids_temp);
 		g_free (package_ids_temp);
@@ -1654,7 +1654,7 @@ pk_transaction_get_files (PkTransaction *transaction, gchar **package_ids, DBusG
 	g_return_if_fail (PK_IS_TRANSACTION (transaction));
 	g_return_if_fail (transaction->priv->tid != NULL);
 
-	package_ids_temp = pk_package_ids_to_text (package_ids, ", ");
+	package_ids_temp = pk_package_ids_to_text (package_ids);
 	egg_debug ("GetFiles method called: %s", package_ids_temp);
 	g_free (package_ids_temp);
 
@@ -1670,7 +1670,7 @@ pk_transaction_get_files (PkTransaction *transaction, gchar **package_ids, DBusG
 	/* check package_ids */
 	ret = pk_package_ids_check (package_ids);
 	if (!ret) {
-		package_ids_temp = pk_package_ids_to_text (package_ids, ", ");
+		package_ids_temp = pk_package_ids_to_text (package_ids);
 		error = g_error_new (PK_TRANSACTION_ERROR, PK_TRANSACTION_ERROR_PACKAGE_ID_INVALID,
 				     "The package id's '%s' are not valid", package_ids_temp);
 		g_free (package_ids_temp);
@@ -1897,7 +1897,7 @@ pk_transaction_get_requires (PkTransaction *transaction, const gchar *filter, gc
 	g_return_if_fail (PK_IS_TRANSACTION (transaction));
 	g_return_if_fail (transaction->priv->tid != NULL);
 
-	package_ids_temp = pk_package_ids_to_text (package_ids, ", ");
+	package_ids_temp = pk_package_ids_to_text (package_ids);
 	egg_debug ("GetRequires method called: %s (recursive %i)", package_ids_temp, recursive);
 	g_free (package_ids_temp);
 
@@ -1920,7 +1920,7 @@ pk_transaction_get_requires (PkTransaction *transaction, const gchar *filter, gc
 	/* check package_ids */
 	ret = pk_package_ids_check (package_ids);
 	if (!ret) {
-		package_ids_temp = pk_package_ids_to_text (package_ids, ", ");
+		package_ids_temp = pk_package_ids_to_text (package_ids);
 		error = g_error_new (PK_TRANSACTION_ERROR, PK_TRANSACTION_ERROR_PACKAGE_ID_INVALID,
 				     "The package id's '%s' are not valid", package_ids_temp);
 		g_free (package_ids_temp);
@@ -2021,7 +2021,7 @@ pk_transaction_get_update_detail (PkTransaction *transaction, gchar **package_id
 	g_return_if_fail (PK_IS_TRANSACTION (transaction));
 	g_return_if_fail (transaction->priv->tid != NULL);
 
-	package_ids_temp = pk_package_ids_to_text (package_ids, ", ");
+	package_ids_temp = pk_package_ids_to_text (package_ids);
 	egg_debug ("GetUpdateDetail method called: %s", package_ids_temp);
 	g_free (package_ids_temp);
 
@@ -2040,7 +2040,7 @@ pk_transaction_get_update_detail (PkTransaction *transaction, gchar **package_id
 	/* check package_ids */
 	ret = pk_package_ids_check (package_ids);
 	if (!ret) {
-		package_ids_temp = pk_package_ids_to_text (package_ids, ", ");
+		package_ids_temp = pk_package_ids_to_text (package_ids);
 		error = g_error_new (PK_TRANSACTION_ERROR, PK_TRANSACTION_ERROR_PACKAGE_ID_INVALID,
 				     "The package id's '%s' are not valid", package_ids_temp);
 		g_free (package_ids_temp);
@@ -2410,7 +2410,7 @@ pk_transaction_install_files (PkTransaction *transaction, gboolean trusted,
 	g_return_if_fail (PK_IS_TRANSACTION (transaction));
 	g_return_if_fail (transaction->priv->tid != NULL);
 
-	full_paths_temp = pk_package_ids_to_text (full_paths, ", ");
+	full_paths_temp = pk_package_ids_to_text (full_paths);
 	egg_debug ("InstallFiles method called: %s (trusted %i)", full_paths_temp, trusted);
 	g_free (full_paths_temp);
 
@@ -2498,7 +2498,7 @@ pk_transaction_install_packages (PkTransaction *transaction, gchar **package_ids
 	g_return_if_fail (PK_IS_TRANSACTION (transaction));
 	g_return_if_fail (transaction->priv->tid != NULL);
 
-	package_ids_temp = pk_package_ids_to_text (package_ids, ", ");
+	package_ids_temp = pk_package_ids_to_text (package_ids);
 	egg_debug ("InstallPackages method called: %s", package_ids_temp);
 	g_free (package_ids_temp);
 
@@ -2515,7 +2515,7 @@ pk_transaction_install_packages (PkTransaction *transaction, gchar **package_ids
 	/* check package_ids */
 	ret = pk_package_ids_check (package_ids);
 	if (!ret) {
-		package_ids_temp = pk_package_ids_to_text (package_ids, ", ");
+		package_ids_temp = pk_package_ids_to_text (package_ids);
 		error = g_error_new (PK_TRANSACTION_ERROR, PK_TRANSACTION_ERROR_PACKAGE_ID_INVALID,
 				     "The package id's '%s' are not valid", package_ids_temp);
 		g_free (package_ids_temp);
@@ -2730,7 +2730,7 @@ pk_transaction_remove_packages (PkTransaction *transaction, gchar **package_ids,
 	g_return_if_fail (PK_IS_TRANSACTION (transaction));
 	g_return_if_fail (transaction->priv->tid != NULL);
 
-	package_ids_temp = pk_package_ids_to_text (package_ids, ", ");
+	package_ids_temp = pk_package_ids_to_text (package_ids);
 	egg_debug ("RemovePackages method called: %s, %i, %i", package_ids_temp, allow_deps, autoremove);
 	g_free (package_ids_temp);
 
@@ -2747,7 +2747,7 @@ pk_transaction_remove_packages (PkTransaction *transaction, gchar **package_ids,
 	/* check package_ids */
 	ret = pk_package_ids_check (package_ids);
 	if (!ret) {
-		package_ids_temp = pk_package_ids_to_text (package_ids, ", ");
+		package_ids_temp = pk_package_ids_to_text (package_ids);
 		error = g_error_new (PK_TRANSACTION_ERROR, PK_TRANSACTION_ERROR_PACKAGE_ID_INVALID,
 				     "The package id's '%s' are not valid", package_ids_temp);
 		g_free (package_ids_temp);
@@ -2949,7 +2949,7 @@ pk_transaction_resolve (PkTransaction *transaction, const gchar *filter,
 	g_return_if_fail (PK_IS_TRANSACTION (transaction));
 	g_return_if_fail (transaction->priv->tid != NULL);
 
-	packages_temp = pk_package_ids_to_text (packages, ", ");
+	packages_temp = pk_package_ids_to_text (packages);
 	egg_debug ("Resolve method called: %s, %s", filter, packages_temp);
 	g_free (packages_temp);
 
@@ -3404,7 +3404,7 @@ pk_transaction_update_packages (PkTransaction *transaction, gchar **package_ids,
 	g_return_if_fail (PK_IS_TRANSACTION (transaction));
 	g_return_if_fail (transaction->priv->tid != NULL);
 
-	package_ids_temp = pk_package_ids_to_text (package_ids, ", ");
+	package_ids_temp = pk_package_ids_to_text (package_ids);
 	egg_debug ("UpdatePackages method called: %s", package_ids_temp);
 	g_free (package_ids_temp);
 
@@ -3421,7 +3421,7 @@ pk_transaction_update_packages (PkTransaction *transaction, gchar **package_ids,
 	/* check package_ids */
 	ret = pk_package_ids_check (package_ids);
 	if (!ret) {
-		package_ids_temp = pk_package_ids_to_text (package_ids, ", ");
+		package_ids_temp = pk_package_ids_to_text (package_ids);
 		error = g_error_new (PK_TRANSACTION_ERROR, PK_TRANSACTION_ERROR_PACKAGE_ID_INVALID,
 				     "The package id's '%s' are not valid", package_ids_temp);
 		g_free (package_ids_temp);
commit 5b1bdfe6ad65c82692fb548e1b8b200cae3c0c2c
Author: Richard Hughes <richard at hughsie.com>
Date:   Fri Sep 26 13:19:30 2008 +0100

    yum: make the check for additional deps much faster in the specific case where we can emulate a transaction

diff --git a/backends/yum/yumBackend.py b/backends/yum/yumBackend.py
index 7976aa1..58a9c40 100755
--- a/backends/yum/yumBackend.py
+++ b/backends/yum/yumBackend.py
@@ -611,8 +611,7 @@ class PackageKitYumBackend(PackageKitBaseBackend, PackagekitPackage):
                             deps_list.append(txmbr.po)
             else:
                 pkg, inst = self._findPackage(package)
-                # FIXME: This is a hack, it simulates a removal of the
-                # package and return the transaction
+                # This simulates the removal of the package
                 if inst and pkg:
                     resolve_list.append(pkg)
                     txmbrs = self.yumbase.remove(po=pkg)
@@ -785,6 +784,52 @@ class PackageKitYumBackend(PackageKitBaseBackend, PackagekitPackage):
             self.yumbase.groupUnremove(grp.groupid)
         return pkgs
 
+    def _get_depends_not_installed(self, fltlist, package_ids):
+        percentage = 0
+        bump = 100 / len(package_ids)
+        deps_list = []
+        resolve_list = []
+
+        for package in package_ids:
+            self.percentage(percentage)
+            grp = self._is_meta_package(package)
+            if grp:
+                if grp.installed:
+                    self.error(ERROR_PACKAGE_ALREADY_INSTALLED, "The Group %s is already installed" % grp.groupid)
+                else:
+                    txmbr = self.yumbase.groupInstall(grp.groupid)
+                    rc, msgs =  self.yumbase.buildTransaction()
+                    if rc != 2:
+                        self.error(ERROR_DEP_RESOLUTION_FAILED, self._format_msgs(msgs))
+                    else:
+                        for txmbr in self.yumbase.tsInfo:
+                            deps_list.append(txmbr.po)
+            else:
+                pkg, inst = self._findPackage(package)
+                # This simulates the addition of the package
+                if not inst and pkg:
+                    resolve_list.append(pkg)
+                    txmbrs = self.yumbase.install(po=pkg)
+                    if txmbrs:
+                        rc, msgs =  self.yumbase.buildTransaction()
+                        if rc != 2:
+                            self.error(ERROR_DEP_RESOLUTION_FAILED, self._format_msgs(msgs))
+                        else:
+                            for txmbr in self.yumbase.tsInfo:
+                                if pkg not in deps_list:
+                                    deps_list.append(txmbr.po)
+            percentage += bump
+
+        # make unique list
+        deps_list = unique(deps_list)
+
+        # each unique name, emit
+        for pkg in deps_list:
+            package_id = self._pkg_to_id(pkg)
+            if package_id not in package_ids:
+                self.package(package_id, INFO_AVAILABLE, pkg.summary)
+        self.percentage(100)
+
     def get_depends(self, filters, package_ids, recursive_text):
         '''
         Print a list of depends for a given package
@@ -794,11 +839,17 @@ class PackageKitYumBackend(PackageKitBaseBackend, PackagekitPackage):
         self.allow_cancel(True)
         self.percentage(None)
         self.status(STATUS_INFO)
-
         fltlist = filters.split(';')
         pkgfilter = YumFilter(fltlist)
         recursive = self._text_to_boolean(recursive_text)
 
+        # before we do an install we do ~installed + recursive true,
+        # which we can emulate quicker by doing a transaction, but not
+        # executing it
+        if filters == FILTER_NOT_INSTALLED and recursive:
+            self._get_depends_not_installed (fltlist, package_ids);
+            return
+
         percentage = 0
         bump = 100 / len(package_ids)
         deps_list = []
@@ -824,7 +875,7 @@ class PackageKitYumBackend(PackageKitBaseBackend, PackagekitPackage):
 
         if grp_pkgs:
             resolve_list.extend(grp_pkgs)
-        # get the best deps
+        # get the best deps -- doing recursive is VERY slow
         deps_list = self._get_best_depends(resolve_list, recursive)
 
         # make unique list
commit e42d60023e8edc41a653bc52ea64e5900148b203
Author: Richard Hughes <richard at hughsie.com>
Date:   Fri Sep 26 09:10:16 2008 +0100

    bugfix: fix up a couple of potential crashers in PkControl if SetLocale fails

diff --git a/libpackagekit/pk-control.c b/libpackagekit/pk-control.c
index 362cee5..71ae2f1 100644
--- a/libpackagekit/pk-control.c
+++ b/libpackagekit/pk-control.c
@@ -466,15 +466,17 @@ pk_control_set_locale (PkControl *control, const gchar *tid, GError **error)
 	g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
 
 	client = pk_client_new ();
-	ret = pk_client_set_tid (client, tid, error);
+	ret = pk_client_set_tid (client, tid, &error_local);
 	if (!ret) {
-		egg_warning ("failed to set the tid: %s", (*error)->message);
+		egg_warning ("failed to set the tid: %s", error_local->message);
+		pk_control_error_set (error, PK_CONTROL_ERROR_FAILED, error_local->message);
+		g_error_free (error_local);
 		goto out;
 	}
 
 	/* get the session locale and set th transaction to be in this locale */
 	locale = setlocale (LC_ALL, NULL);
-	ret = pk_client_set_locale (client, locale, error);
+	ret = pk_client_set_locale (client, locale, &error_local);
 	if (!ret) {
 		egg_warning ("SetLocale failed :%s", error_local->message);
 		pk_control_error_set (error, PK_CONTROL_ERROR_FAILED, error_local->message);
@@ -533,7 +535,7 @@ pk_control_allocate_transaction_id (PkControl *control, gchar **tid, GError **er
 	}
 
 	/* automatically set the locale */
-	ret = pk_control_set_locale (control, tid_local, error);
+	ret = pk_control_set_locale (control, tid_local, &error_local);
 	if (!ret) {
 		egg_warning ("GetTid failed :%s", error_local->message);
 		pk_control_error_set (error, PK_CONTROL_ERROR_FAILED, error_local->message);
commit f51e2ddcefb92a727865b0982e857b1782e10fa3
Author: Piotr DrÄ…g <piotrdrag at gmail.com>
Date:   Thu Sep 25 22:27:16 2008 +0000

    Updated Polish translation
    
    Transmitted-via: Transifex (translate.fedoraproject.org)

diff --git a/po/pl.po b/po/pl.po
index 7384345..7ea8d9d 100644
--- a/po/pl.po
+++ b/po/pl.po
@@ -5,257 +5,257 @@ msgid ""
 msgstr ""
 "Project-Id-Version: pl\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2008-08-26 09:23+0000\n"
-"PO-Revision-Date: 2008-08-26 11:28+0200\n"
+"POT-Creation-Date: 2008-09-25 00:31+0000\n"
+"PO-Revision-Date: 2008-09-26 00:25+0200\n"
 "Last-Translator: Piotr DrÄ…g <piotrdrag at gmail.com>\n"
 "Language-Team: Polish <pl at li.org>\n"
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
 
-#: ../client/pk-console.c:235
+#: ../client/pk-console.c:274
 msgid "Update detail"
 msgstr "Szczegóły aktualizacji"
 
-#: ../client/pk-console.c:452
+#: ../client/pk-console.c:491
 msgid "A system restart is required"
 msgstr "Wymagane jest ponowne uruchomienie systemu"
 
-#: ../client/pk-console.c:454
+#: ../client/pk-console.c:493
 msgid "A logout and login is required"
 msgstr "Wymagane jest wylogowanie siÄ™ i ponowne zalogowanie"
 
-#: ../client/pk-console.c:456
+#: ../client/pk-console.c:495
 msgid "An application restart is required"
 msgstr "Wymagane jest ponowne uruchomienie aplikacji"
 
-#: ../client/pk-console.c:549 ../client/pk-generate-pack.c:124
+#: ../client/pk-console.c:588 ../client/pk-generate-pack.c:126
 msgid "There are multiple package matches"
 msgstr "Pasuje kilka pakietów"
 
 #. find out what package the user wants to use
-#: ../client/pk-console.c:556 ../client/pk-generate-pack.c:131
+#: ../client/pk-console.c:595 ../client/pk-generate-pack.c:133
 msgid "Please enter the package number: "
 msgstr "Proszę podać numer pakietu: "
 
-#: ../client/pk-console.c:590
+#: ../client/pk-console.c:629
 msgid "Could not find package to install"
 msgstr "Nie można znaleźć pakietu do zainstalowania"
 
-#: ../client/pk-console.c:696
+#: ../client/pk-console.c:735
 msgid "Could not find package to remove"
 msgstr "Nie można znaleźć pakietu do usunięcia"
 
-#: ../client/pk-console.c:757
+#: ../client/pk-console.c:796
 msgid "The following packages have to be removed"
 msgstr "Następujące pakiety muszą zostać usunięte"
 
 #. get user input
-#: ../client/pk-console.c:764
+#: ../client/pk-console.c:803
 msgid "Okay to remove additional packages?"
 msgstr "Usunąć dodatkowe pakiety?"
 
-#: ../client/pk-console.c:768 ../client/pk-generate-pack.c:523
+#: ../client/pk-console.c:807 ../client/pk-generate-pack.c:528
 #: ../client/pk-generate-pack-main.c:131
 msgid "Cancelled!"
 msgstr "Anulowano!"
 
-#: ../client/pk-console.c:802
+#: ../client/pk-console.c:841
 msgid "Could not find package to download"
 msgstr "Nie można znaleźć pakietu do pobrania"
 
-#: ../client/pk-console.c:853
+#: ../client/pk-console.c:893
 msgid "Could not find package to update"
 msgstr "Nie można znaleźć pakietu do zaktualizowania"
 
-#: ../client/pk-console.c:875
+#: ../client/pk-console.c:915
 msgid "Could not find what packages require"
 msgstr "Nie można znaleźć pakietów, które wymagają"
 
-#: ../client/pk-console.c:896
+#: ../client/pk-console.c:936
 msgid "Could not get dependencies for"
 msgstr "Nie można uzyskać zależności dla"
 
-#: ../client/pk-console.c:917
+#: ../client/pk-console.c:957
 msgid "Could not find details for"
 msgstr "Nie można znaleźć szczegółów dla"
 
-#: ../client/pk-console.c:940
+#: ../client/pk-console.c:980
 msgid "Could not find the files for this package"
 msgstr "Nie można znaleźć plików tego pakietu"
 
-#: ../client/pk-console.c:947
+#: ../client/pk-console.c:987
 msgid "Could not get the file list"
 msgstr "Nie można uzyskać listy plików"
 
-#: ../client/pk-console.c:966
+#: ../client/pk-console.c:1006
 msgid "Could not find the update details for"
 msgstr "Nie można znaleźć szczegółów aktualizacji dla"
 
-#: ../client/pk-console.c:1027
+#: ../client/pk-console.c:1067
 msgid "Package description"
 msgstr "Opis pakietu"
 
-#: ../client/pk-console.c:1060
+#: ../client/pk-console.c:1100
 msgid "Package files"
 msgstr "Pliki pakietu"
 
-#: ../client/pk-console.c:1068
+#: ../client/pk-console.c:1108
 msgid "No files"
 msgstr "Brak plików"
 
 #. get user input
-#: ../client/pk-console.c:1100
+#: ../client/pk-console.c:1140
 msgid "Okay to import key?"
 msgstr "Zaimportować klucz?"
 
-#: ../client/pk-console.c:1103
+#: ../client/pk-console.c:1143
 msgid "Did not import key"
 msgstr "Nie zaimportowano klucza"
 
 #. get user input
-#: ../client/pk-console.c:1143
+#: ../client/pk-console.c:1183
 msgid "Do you agree?"
 msgstr "Zgadzasz siÄ™?"
 
-#: ../client/pk-console.c:1146
+#: ../client/pk-console.c:1186
 msgid "Did not agree to licence, task will fail"
 msgstr "Nie zaakceptowano licencji, zadanie nie powiedzie siÄ™"
 
-#: ../client/pk-console.c:1175
+#: ../client/pk-console.c:1215
 msgid "The daemon crashed mid-transaction!"
 msgstr "Demon zawiesił się w połowie transakcji!"
 
 #. header
-#: ../client/pk-console.c:1228
+#: ../client/pk-console.c:1268
 msgid "PackageKit Console Interface"
 msgstr "Interfejs konsoli PackageKit"
 
-#: ../client/pk-console.c:1228
+#: ../client/pk-console.c:1268
 msgid "Subcommands:"
 msgstr "Podpolecenia:"
 
-#: ../client/pk-console.c:1338 ../client/pk-generate-pack-main.c:64
-#: ../client/pk-monitor.c:104 ../src/pk-main.c:189
+#: ../client/pk-console.c:1378 ../client/pk-generate-pack-main.c:64
+#: ../client/pk-monitor.c:118 ../src/pk-main.c:192
 msgid "Show extra debugging information"
 msgstr "Wyświetla dodatkowe informacje o debugowaniu"
 
-#: ../client/pk-console.c:1340 ../client/pk-monitor.c:106
+#: ../client/pk-console.c:1380 ../client/pk-monitor.c:120
 msgid "Show the program version and exit"
 msgstr "Wyświetla wersję programu i wyłącza"
 
-#: ../client/pk-console.c:1342
+#: ../client/pk-console.c:1382
 msgid "Set the filter, e.g. installed"
 msgstr "Ustawia filtr, np. zainstalowane"
 
-#: ../client/pk-console.c:1344
+#: ../client/pk-console.c:1384
 msgid "Exit without waiting for actions to complete"
 msgstr "Wyłącza bez oczekiwania na zakończenie działań"
 
-#: ../client/pk-console.c:1367
+#: ../client/pk-console.c:1407
 msgid "Could not connect to system DBUS."
 msgstr "Nie można połączyć się z systemowym D-Bus."
 
-#: ../client/pk-console.c:1464
+#: ../client/pk-console.c:1500
 msgid "You need to specify a search type, e.g. name"
 msgstr "Należy podać typ wyszukiwania, np. po nazwie"
 
-#: ../client/pk-console.c:1469 ../client/pk-console.c:1476
-#: ../client/pk-console.c:1483 ../client/pk-console.c:1490
-#: ../client/pk-console.c:1601 ../client/pk-console.c:1611
-#: ../client/pk-console.c:1618 ../client/pk-console.c:1625
+#: ../client/pk-console.c:1505 ../client/pk-console.c:1512
+#: ../client/pk-console.c:1519 ../client/pk-console.c:1526
+#: ../client/pk-console.c:1637 ../client/pk-console.c:1647
+#: ../client/pk-console.c:1654 ../client/pk-console.c:1661
 msgid "You need to specify a search term"
 msgstr "Należy podać termin wyszukiwania"
 
-#: ../client/pk-console.c:1495
+#: ../client/pk-console.c:1531
 msgid "Invalid search type"
 msgstr "Nieprawidłowy typ wyszukiwania"
 
-#: ../client/pk-console.c:1500
+#: ../client/pk-console.c:1536
 msgid "You need to specify a package or file to install"
 msgstr "Należy podać pakiet lub plik do zainstalowania"
 
-#: ../client/pk-console.c:1507
+#: ../client/pk-console.c:1543
 msgid "You need to specify a type, key_id and package_id"
 msgstr "Należy podać typ, key_id i package_id"
 
-#: ../client/pk-console.c:1514
+#: ../client/pk-console.c:1550
 msgid "You need to specify a package to remove"
 msgstr "Należy podać pakiet do usunięcia"
 
-#: ../client/pk-console.c:1520
+#: ../client/pk-console.c:1556
 msgid ""
 "You need to specify the destination directory and then the packages to "
 "download"
 msgstr "Należy podać katalog docelowy, a następnie pakiety do pobrania"
 
-#: ../client/pk-console.c:1525
+#: ../client/pk-console.c:1561
 msgid "Directory not found"
 msgstr "Nie znaleziono katalogu"
 
-#: ../client/pk-console.c:1531
+#: ../client/pk-console.c:1567
 msgid "You need to specify a eula-id"
 msgstr "Należy podać eula-id"
 
-#: ../client/pk-console.c:1547
+#: ../client/pk-console.c:1583
 msgid "You need to specify a package name to resolve"
 msgstr "Należy podać nazwę pakietu do rozwiązania"
 
-#: ../client/pk-console.c:1556 ../client/pk-console.c:1563
+#: ../client/pk-console.c:1592 ../client/pk-console.c:1599
 msgid "You need to specify a repo name"
 msgstr "Należy podać nazwę repozytorium"
 
-#: ../client/pk-console.c:1570
+#: ../client/pk-console.c:1606
 msgid "You need to specify a repo name/parameter and value"
 msgstr "Należy podać nazwę/parametr repozytorium i wartość"
 
-#: ../client/pk-console.c:1583
+#: ../client/pk-console.c:1619
 msgid "You need to specify a time term"
 msgstr "Należy podać termin czasu"
 
-#: ../client/pk-console.c:1588
+#: ../client/pk-console.c:1624
 msgid "You need to specify a correct role"
 msgstr "Należy podać poprawną rolę"
 
-#: ../client/pk-console.c:1593
+#: ../client/pk-console.c:1629
 msgid "Failed to get last time"
 msgstr "Uzyskanie ostatniego czasu nie powiodło się"
 
-#: ../client/pk-console.c:1632
+#: ../client/pk-console.c:1668
 msgid "You need to specify a package to find the details for"
 msgstr "Należy podać pakiet do znalezienia szczegółów dla"
 
-#: ../client/pk-console.c:1639
+#: ../client/pk-console.c:1675
 msgid "You need to specify a package to find the files for"
 msgstr "Należy podać pakiet do znalezienia plików dla"
 
-#: ../client/pk-console.c:1688
+#: ../client/pk-console.c:1724
 #, c-format
 msgid "Option '%s' not supported"
 msgstr "Opcja \"%s\" nie jest obsługiwana"
 
-#: ../client/pk-console.c:1701
+#: ../client/pk-console.c:1737
 msgid "You don't have the necessary privileges for this operation"
 msgstr "Nie posiadasz niezbędnych uprawnień dla tej operacji"
 
-#: ../client/pk-console.c:1703
+#: ../client/pk-console.c:1739
 msgid "Command failed"
 msgstr "Polecenie nie powiodło się"
 
-#: ../client/pk-generate-pack.c:115
+#: ../client/pk-generate-pack.c:117
 msgid "Could not find a package match"
 msgstr "Nie można znaleźć pasującego pakietu"
 
-#: ../client/pk-generate-pack.c:149
+#: ../client/pk-generate-pack.c:151
 msgid "failed to download: invalid package_id and/or directory"
 msgstr "pobranie nie powiodło się: nieprawidłowe package_id i/lub katalog"
 
-#: ../client/pk-generate-pack.c:230
+#: ../client/pk-generate-pack.c:232
 msgid "Could not find a valid metadata file"
 msgstr "Nie można znaleźć prawidłowego pliku metadanych"
 
 #. get user input
-#: ../client/pk-generate-pack.c:519
+#: ../client/pk-generate-pack.c:524
 msgid "Okay to download the additional packages"
 msgstr "Pobrać dodatkowe pakiety?"
 
@@ -290,16 +290,20 @@ msgstr "Utworzenie katalogu nie powiodło się"
 msgid "Failed to create pack"
 msgstr "Utworzenie pakietu serwisowego nie powiodło się"
 
-#: ../client/pk-import-desktop.c:279 ../client/pk-import-specspo.c:177
+#: ../client/pk-import-specspo.c:185
+msgid "Could not set database readonly"
+msgstr "Nie można ustawić bazy danych w tryb tylko do odczytu"
+
+#: ../client/pk-import-specspo.c:192
 #, c-format
 msgid "Could not open database: %s"
 msgstr "Nie można otworzyć bazy danych: %s"
 
-#: ../client/pk-import-desktop.c:280 ../client/pk-import-specspo.c:178
+#: ../client/pk-import-specspo.c:193
 msgid "You probably need to run this program as the root user"
 msgstr "Prawdopodobnie należy uruchomić ten program jako użytkownik root"
 
-#: ../client/pk-monitor.c:117
+#: ../client/pk-monitor.c:131
 msgid "PackageKit Monitor"
 msgstr "Monitor PackageKit"
 
@@ -402,21 +406,21 @@ msgstr "Katalog PackageKit"
 msgid "PackageKit Service Pack"
 msgstr "Pakiet serwisowy PackageKit"
 
-#: ../src/pk-main.c:83
+#: ../src/pk-main.c:85
 msgid "Startup failed due to security policies on this machine."
 msgstr ""
 "Uruchomienie nie powiodło się z powodu polityk bezpieczeństwa tego komputera."
 
-#: ../src/pk-main.c:84
+#: ../src/pk-main.c:86
 msgid "This can happen for two reasons:"
 msgstr "Mogło się to wydarzyć z dwóch powodów:"
 
-#: ../src/pk-main.c:85
+#: ../src/pk-main.c:87
 msgid "The correct user is not launching the executable (usually root)"
 msgstr ""
 "Prawidłowy użytkownik nie uruchamiania pliku wykonywalnego (zwykle root)"
 
-#: ../src/pk-main.c:86
+#: ../src/pk-main.c:88
 msgid ""
 "The org.freedesktop.PackageKit.conf file is not installed in the system /etc/"
 "dbus-1/system.d directory"
@@ -424,39 +428,39 @@ msgstr ""
 "Plik org.freedesktop.PackageKit.conf nie jest zainstalowany w katalogu "
 "systemowym /etc/dbus-1/system.d"
 
-#: ../src/pk-main.c:185
+#: ../src/pk-main.c:188
 msgid "Packaging backend to use, e.g. dummy"
 msgstr "Używany moduł przetwarzający, np. dummy"
 
-#: ../src/pk-main.c:187
+#: ../src/pk-main.c:190
 msgid "Daemonize and detach from the terminal"
 msgstr "Tworzy demona i odłącza z terminala"
 
-#: ../src/pk-main.c:191
+#: ../src/pk-main.c:194
 msgid "Disable the idle timer"
 msgstr "Wyłącza licznik czasu bezczynności"
 
-#: ../src/pk-main.c:193
+#: ../src/pk-main.c:196
 msgid "Show version and exit"
 msgstr "Wyświetla wersję i wyłącza"
 
-#: ../src/pk-main.c:195
+#: ../src/pk-main.c:198
 msgid "Exit after a small delay"
 msgstr "Wyłącza po małej przerwie"
 
-#: ../src/pk-main.c:197
+#: ../src/pk-main.c:200
 msgid "Exit after the engine has loaded"
 msgstr "Wyłącza po wczytaniu mechanizmu"
 
-#: ../src/pk-main.c:207
+#: ../src/pk-main.c:210
 msgid "PackageKit service"
 msgstr "Usługa PackageKit"
 
-#: ../src/pk-main.c:233
+#: ../src/pk-main.c:246
 msgid "Cannot connect to the system bus"
 msgstr "Nie można połączyć się z magistralą systemową"
 
-#: ../src/pk-main.c:273
+#: ../src/pk-main.c:286
 #, c-format
 msgid "Error trying to start: %s\n"
 msgstr "Błąd podczas próbowania uruchomienia: %s\n"
commit 5080f98c3c377f1669778075a9903e01572c059f
Merge: 374583f... 5300349...
Author: Richard Hughes <richard at hughsie.com>
Date:   Thu Sep 25 17:17:59 2008 +0100

    Merge branch 'master' of git+ssh://hughsie@git.packagekit.org/srv/git/PackageKit

commit 374583f52e02f957e3f7162f2547dba0913db8e8
Author: Richard Hughes <richard at hughsie.com>
Date:   Thu Sep 25 17:16:59 2008 +0100

    feature: Add a helper which can be used by GStreamer to install codecs. The conversion code was written by Bastien Nocera <bnocera at redhat.com>

diff --git a/configure.ac b/configure.ac
index 8c4baef..e5dc512 100644
--- a/configure.ac
+++ b/configure.ac
@@ -240,15 +240,11 @@ fi
 dnl ---------------------------------------------------------------------------
 dnl - Checks for contrib/packagekit-plugin
 dnl ---------------------------------------------------------------------------
-
 PKG_CHECK_MODULES(PK_BROWSER_PLUGIN, mozilla-plugin gio-unix-2.0 cairo pango gtk+-2.0 dbus-glib-1,
                   build_browser_plugin=yes, build_browser_plugin=no)
-
 AM_CONDITIONAL(PK_BUILD_BROWSER_PLUGIN, test $build_browser_plugin = "yes")
-
 AC_SUBST(PK_BROWSER_PLUGIN_CFLAGS)
 AC_SUBST(PK_BROWSER_PLUGIN_LIBS)
-
 if test $build_browser_plugin = "yes"; then
 	# Check if we have GdkAppLaunchContext (new in GTK+-2.14)
 
@@ -265,6 +261,15 @@ if test $build_browser_plugin = "yes"; then
 fi
 
 dnl ---------------------------------------------------------------------------
+dnl - Checks for contrib/gstreamer-plugin
+dnl ---------------------------------------------------------------------------
+PKG_CHECK_MODULES(PK_GSTREAMER_PLUGIN, gstreamer-0.10 glib-2.0 dbus-glib-1,
+                  build_gstreamer_plugin=yes, build_gstreamer_plugin=no)
+AM_CONDITIONAL(PK_BUILD_GSTREAMER_PLUGIN, test $build_gstreamer_plugin = "yes")
+AC_SUBST(PK_GSTREAMER_PLUGIN_CFLAGS)
+AC_SUBST(PK_GSTREAMER_PLUGIN_LIBS)
+
+dnl ---------------------------------------------------------------------------
 dnl - Other tests
 dnl ---------------------------------------------------------------------------
 AC_ARG_ENABLE(gcov, AS_HELP_STRING([--enable-gcov],[compile with coverage profiling instrumentation (gcc only)]),
@@ -519,6 +524,7 @@ docs/api/dbus/Makefile
 docs/api/version.xml
 contrib/Makefile
 contrib/packagekit-plugin/Makefile
+contrib/gstreamer-plugin/Makefile
 contrib/udev/Makefile
 contrib/yum-packagekit/Makefile
 backends/Makefile
@@ -576,6 +582,7 @@ echo "
         Networking stack:          ${with_networking_stack}
         GIO support:               ${with_gio}
         Browser plugin:            ${build_browser_plugin}
+        GStreamer plugin:          ${build_gstreamer_plugin}
 
         Backends:
         ALPM backend:              ${enable_alpm}
diff --git a/contrib/Makefile.am b/contrib/Makefile.am
index e7d1984..756855a 100644
--- a/contrib/Makefile.am
+++ b/contrib/Makefile.am
@@ -8,6 +8,10 @@ if PK_BUILD_BROWSER_PLUGIN
 SUBDIRS += packagekit-plugin
 endif
 
+if PK_BUILD_GSTREAMER_PLUGIN
+SUBDIRS += gstreamer-plugin
+endif
+
 bashcompletiondir = ${SYSCONFDIR}/bash_completion.d
 dist_bashcompletion_DATA = pk-completion.bash
 
diff --git a/contrib/PackageKit.spec.in b/contrib/PackageKit.spec.in
index f3c4147..71b7070 100644
--- a/contrib/PackageKit.spec.in
+++ b/contrib/PackageKit.spec.in
@@ -44,6 +44,7 @@ BuildRequires: intltool
 BuildRequires: gettext
 BuildRequires: xulrunner-devel
 BuildRequires: libarchive-devel
+BuildRequires: gstreamer-devel
 
 %description
 PackageKit is a D-Bus abstraction layer that allows the session user
@@ -138,6 +139,16 @@ The PackageKit browser plugin allows web sites to offer the ability to
 users to install and update packages from configured repositories
 using PackageKit.
 
+%package gstreamer-plugin
+Summary: Install GStreamer codecs using PackageKit
+Group: Development/Libraries
+Requires: gstreamer
+Requires: PackageKit-libs = %{version}-%{release}
+
+%description gstreamer-plugin
+The PackageKit GStreamer plugin allows any Gstreamer application to install
+codecs from configured repositories using PackageKit.
+
 %prep
 %setup -q
 
@@ -164,6 +175,11 @@ rm -f $RPM_BUILD_ROOT%{_libdir}/mozilla/plugins/packagekit-plugin.a
 rm -f $RPM_BUILD_ROOT%{_libdir}/mozilla/plugins/packagekit-plugin.la
 chmod 755 $RPM_BUILD_ROOT%{_libexecdir}/PackageKitDbusTest.py
 
+# create a binary that GStreamer will recognise
+pushd ${RPM_BUILD_ROOT}%{_libexecdir} > /dev/null
+ln -s pk-gstreamer-install gst-install-plugins-helper
+popd > /dev/null
+
 %find_lang %name
 
 %clean
@@ -267,6 +283,12 @@ update-mime-database %{_datadir}/mime &> /dev/null || :
 %dir %{_libdir}/mozilla/plugins
 %{_libdir}/mozilla/plugins/packagekit-plugin.so
 
+%files gstreamer-plugin
+%defattr(-,root,root,-)
+%doc README AUTHORS NEWS COPYING
+%{_libexecdir}/pk-gstreamer-install
+%{_libexecdir}/gst-install-plugins-helper
+
 %files devel
 %defattr(-,root,root,-)
 %doc README AUTHORS NEWS COPYING
diff --git a/contrib/gstreamer-plugin/.gitignore b/contrib/gstreamer-plugin/.gitignore
new file mode 100644
index 0000000..64d8ffa
--- /dev/null
+++ b/contrib/gstreamer-plugin/.gitignore
@@ -0,0 +1,5 @@
+.deps
+.libs
+*.o
+pk-gstreamer-install
+
diff --git a/contrib/gstreamer-plugin/Makefile.am b/contrib/gstreamer-plugin/Makefile.am
new file mode 100644
index 0000000..b9917fd
--- /dev/null
+++ b/contrib/gstreamer-plugin/Makefile.am
@@ -0,0 +1,38 @@
+## We require new-style dependency handling.
+AUTOMAKE_OPTIONS = 1.7
+
+NULL =
+
+INCLUDES =						\
+	$(PK_GSTREAMER_PLUGIN_CFLAGS)			\
+	-DBINDIR=\"$(bindir)\"			 	\
+	-DDATADIR=\"$(datadir)\"			\
+	-DPREFIX=\""$(prefix)"\" 			\
+	-DSYSCONFDIR=\""$(sysconfdir)"\" 		\
+	-DLIBDIR=\""$(libdir)"\" 			\
+	-DVERSION="\"$(VERSION)\"" 			\
+	-DPK_DATA=\"$(pkgdatadir)\"			\
+	-DPK_DB_DIR=\""$(PK_DB_DIR)"\" 			\
+	-DEGG_LOG_FILE=\""$(PK_LOG_DIR)/PackageKit"\"	\
+	$(NULL)
+
+libexec_PROGRAMS =					\
+	pk-gstreamer-install				\
+	$(NULL)
+
+pk_gstreamer_install_SOURCES =				\
+	pk-gstreamer-install.c				\
+	$(NULL)
+
+pk_gstreamer_install_LDADD =				\
+	$(PK_GSTREAMER_PLUGIN_LIBS)			\
+	$(NULL)
+
+clean-local:
+	rm -f *~
+
+MAINTAINERCLEANFILES =					\
+	*~			      			\
+	Makefile.in					\
+	$(NULL)
+
diff --git a/contrib/gstreamer-plugin/pk-gstreamer-install.c b/contrib/gstreamer-plugin/pk-gstreamer-install.c
new file mode 100644
index 0000000..f9ba620
--- /dev/null
+++ b/contrib/gstreamer-plugin/pk-gstreamer-install.c
@@ -0,0 +1,367 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2008 Bastien Nocera <bnocera at redhat.com>
+ * Copyright (C) 2008 Richard Hughes <richard at hughsie.com>
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <gst/gst.h>
+#include <string.h>
+#include <dbus/dbus-glib.h>
+
+typedef struct {
+	GstStructure *structure;
+	char *type_name;
+	char *codec_name;
+	char *app_name;
+} codec_info;
+
+enum {
+	FIELD_VERSION = 0,
+	FIELD_LAYER,
+	FIELD_VARIANT,
+	FIELD_SYSTEMSTREAM
+};
+
+/**
+ * pk_gst_parse_codec:
+ **/
+static codec_info *
+pk_gst_parse_codec (const char *codec)
+{
+	char **split;
+	GstStructure *s;
+	char *type_name, *caps;
+	codec_info *info;
+
+	split = g_strsplit (codec, "|", -1);
+	if (split == NULL || g_strv_length (split) != 5) {
+		g_message ("not a GStreamer codec line");
+		g_strfreev (split);
+		return NULL;
+	}
+	if (strcmp (split[0], "gstreamer") != 0 ||
+	    strcmp (split[1], "0.10") != 0) {
+		g_message ("not for GStreamer 0.10");
+		g_strfreev (split);
+		return NULL;
+	}
+
+	if (g_str_has_prefix (split[4], "uri") != FALSE) {
+		char **ss;
+
+		ss = g_strsplit (split[4], " ", 2);
+
+		info = g_new0 (codec_info, 1);
+		info->app_name = g_strdup (split[2]);
+		info->codec_name = g_strdup (split[3]);
+		info->type_name = g_strdup (ss[0]);
+		g_strfreev (ss);
+		g_strfreev (split);
+
+		return info;
+	}
+
+	{
+		char **ss;
+		ss = g_strsplit (split[4], "-", 2);
+		type_name = g_strdup (ss[0]);
+		caps = g_strdup (ss[1]);
+		g_strfreev (ss);
+	}
+
+	s = gst_structure_from_string (caps, NULL);
+	if (s == NULL) {
+		g_message ("failed to parse caps: %s", caps);
+		g_strfreev (split);
+		g_free (caps);
+		g_free (type_name);
+		return NULL;
+	}
+
+	/* remove fields that are almost always just MIN-MAX of some sort
+	 * in order to make the caps look less messy */
+	gst_structure_remove_field (s, "pixel-aspect-ratio");
+	gst_structure_remove_field (s, "framerate");
+	gst_structure_remove_field (s, "channels");
+	gst_structure_remove_field (s, "width");
+	gst_structure_remove_field (s, "height");
+	gst_structure_remove_field (s, "rate");
+	gst_structure_remove_field (s, "depth");
+	gst_structure_remove_field (s, "clock-rate");
+	gst_structure_remove_field (s, "bitrate");
+
+	info = g_new0 (codec_info, 1);
+	info->app_name = g_strdup (split[2]);
+	info->codec_name = g_strdup (split[3]);
+	info->type_name = type_name;
+	info->structure = s;
+	g_strfreev (split);
+
+	return info;
+}
+
+/**
+ * pk_gst_field_get_type:
+ **/
+static int
+pk_gst_field_get_type (const char *field_name)
+{
+	if (strstr (field_name, "version") != NULL)
+		return FIELD_VERSION;
+	if (strcmp (field_name, "layer") == 0)
+		return FIELD_LAYER;
+	if (strcmp (field_name, "systemstream") == 0)
+		return FIELD_SYSTEMSTREAM;
+	if (strcmp (field_name, "variant") == 0)
+		return FIELD_VARIANT;
+
+	return -1;
+}
+
+/**
+ * pk_gst_fields_type_compare:
+ **/
+static gint
+pk_gst_fields_type_compare (const char *a, const char *b)
+{
+	gint a_type, b_type;
+
+	a_type = pk_gst_field_get_type (a);
+	b_type = pk_gst_field_get_type (b);
+	if (a_type < b_type)
+		return -1;
+	if (b_type < a_type)
+		return 1;
+	return 0;
+}
+
+/**
+ * pk_gst_structure_to_provide:
+ **/
+static char *
+pk_gst_structure_to_provide (GstStructure *s)
+{
+	GString *string;
+	guint i, num_fields;
+	GList *fields, *l;
+
+	num_fields = gst_structure_n_fields (s);
+	fields = NULL;
+
+	for (i = 0; i < num_fields; i++) {
+		const char *field_name;
+
+		field_name = gst_structure_nth_field_name (s, i);
+		if (pk_gst_field_get_type (field_name) < 0) {
+			//g_message ("ignoring field named %s", field_name);
+			continue;
+		}
+
+		fields = g_list_insert_sorted (fields, g_strdup (field_name), (GCompareFunc) pk_gst_fields_type_compare);
+	}
+
+	string = g_string_new("");
+	for (l = fields; l != NULL; l = l->next) {
+		char *field_name;
+		GType type;
+
+		field_name = l->data;
+
+		type = gst_structure_get_field_type (s, field_name);
+		//g_message ("field is: %s, type: %s", field_name, g_type_name (type));
+
+		if (type == G_TYPE_INT) {
+			int value;
+
+			gst_structure_get_int (s, field_name, &value);
+			g_string_append_printf (string, "(%s=%d)", field_name, value);
+		} else if (type == G_TYPE_BOOLEAN) {
+			int value;
+
+			gst_structure_get_boolean (s, field_name, &value);
+			g_string_append_printf (string, "(%s=%s)", field_name, value ? "true" : "false");
+		} else if (type == G_TYPE_STRING) {
+			const char *value;
+
+			value = gst_structure_get_string (s, field_name);
+			g_string_append_printf (string, "(%s=%s)", field_name, value);
+		} else {
+			g_warning ("unhandled type! %s", g_type_name (type));
+		}
+
+		g_free (field_name);
+	}
+
+	g_list_free (fields);
+
+	return g_string_free (string, FALSE);
+}
+
+/**
+ * pk_gst_codec_free:
+ **/
+static void
+pk_gst_codec_free (codec_info *codec)
+{
+	if (codec->structure)
+		gst_structure_free (codec->structure);
+	g_free (codec->type_name);
+	g_free (codec->codec_name);
+	g_free (codec->app_name);
+}
+
+/**
+ * main:
+ **/
+int
+main (int argc, char **argv)
+{
+	DBusGConnection *connection;
+	DBusGProxy *proxy = NULL;
+	GPtrArray *array = NULL;
+	GValueArray *varray;
+	GValue *value;
+	gboolean ret;
+	GType array_type;
+	GOptionContext *context;
+	GError *error = NULL;
+	guint i;
+	gchar **codecs = NULL;
+	gint xid = 0;
+	gint retval = 1;
+
+	const GOptionEntry options[] = {
+		{ "transient-for", '\0', 0, G_OPTION_ARG_INT, &xid, "The XID of the parent window", NULL },
+		{ G_OPTION_REMAINING, '\0', 0, G_OPTION_ARG_FILENAME_ARRAY, &codecs, "GStreamer install infos", NULL },
+		{ NULL }
+	};
+
+	g_type_init ();
+	gst_init (&argc, &argv);
+
+	context = g_option_context_new ("Install missing codecs");
+	g_option_context_add_main_entries (context, options, NULL);
+
+	if (!g_option_context_parse (context, &argc, &argv, &error)) {
+		g_print ("%s\nRun '%s --help' to see a full list of available command line options.\n",
+			 error->message, argv[0]);
+		g_error_free (error);
+		goto out;
+	}
+	if (codecs == NULL) {
+		g_print ("Missing codecs information\n");
+		g_print ("Run 'with --help' to see a full list of available command line options.\n");
+		goto out;
+	}
+
+	/* get bus */
+	connection = dbus_g_bus_get (DBUS_BUS_SESSION, &error);
+	if (connection == NULL) {
+		g_print ("Could not connect to session DBUS: %s\n", error->message);
+		g_error_free (error);
+		goto out;
+	}
+
+	/* get proxy */
+	proxy = dbus_g_proxy_new_for_name (connection,
+					   "org.freedesktop.PackageKit",
+					   "/org/freedesktop/PackageKit",
+					   "org.freedesktop.PackageKit");
+	if (proxy == NULL) {
+		g_print ("Cannot connect to PackageKit session service\n");
+		goto out;
+	}
+
+
+	/* process argv */
+	array = g_ptr_array_new ();
+	for (i = 0; codecs[i] != NULL; i++) {
+		codec_info *info;
+		char *s;
+		char *type;
+
+		info = pk_gst_parse_codec (codecs[i]);
+		if (info == NULL) {
+			g_print ("skipping %s\n", codecs[i]);
+			continue;
+		}
+		if (info->structure != NULL) {
+			s = pk_gst_structure_to_provide (info->structure);
+			type = g_strdup_printf ("gstreamer0.10(%s-%s)%s", info->type_name,
+						gst_structure_get_name (info->structure), s ? s : "");
+			g_free (s);
+		} else {
+			type = g_strdup_printf ("gstreamer0.10(%s)", info->type_name);
+		}
+
+		g_message ("Codec nice name: %s", info->codec_name);
+		g_message ("%s", type);
+
+		/* create (ss) structure */
+		varray = g_value_array_new (2);
+		value = g_new0 (GValue, 1);
+		g_value_init (value, G_TYPE_STRING);
+		g_value_set_string (value, info->codec_name);
+		g_value_array_append (varray, value);
+		g_value_reset (value);
+		g_value_set_string (value, type);
+		g_value_array_append (varray, value);
+		g_value_unset (value);
+		g_free (value);
+
+		/* add to array of (ss) */
+		g_ptr_array_add (array, varray);
+
+		/* free codec structure */
+		pk_gst_codec_free (info);
+	}
+
+	/* marshall a(ss) */
+	array_type = dbus_g_type_get_collection ("GPtrArray",
+					dbus_g_type_get_struct("GValueArray",
+						G_TYPE_STRING,
+						G_TYPE_STRING,
+						G_TYPE_INVALID));
+
+	/* invoke the method */
+	ret = dbus_g_proxy_call (proxy, "InstallGStreamerCodecs", &error,
+				 G_TYPE_UINT, xid,
+				 G_TYPE_UINT, 0,
+				 array_type, array,
+				 G_TYPE_INVALID,
+				 G_TYPE_INVALID);
+	if (!ret) {
+		g_error ("Did not install codec: %s", error->message);
+		g_error_free (error);
+		goto out;
+	}
+
+	/* all okay */
+	retval = 0;
+
+out:
+	if (array != NULL) {
+		g_ptr_array_foreach (array, (GFunc) g_value_array_free, NULL);
+		g_ptr_array_free (array, TRUE);
+	}
+	if (proxy != NULL)
+		g_object_unref (proxy);
+	return 0;
+}
+
diff --git a/contrib/gstreamer-plugin/test.sh b/contrib/gstreamer-plugin/test.sh
new file mode 100644
index 0000000..403f69a
--- /dev/null
+++ b/contrib/gstreamer-plugin/test.sh
@@ -0,0 +1,2 @@
+./pk-gstreamer-install "gstreamer|0.10|totem|Windows Media Video 9 decoder|decoder-video/x-wmv, wmvversion=(int)3, fourcc=(fourcc)WVC1, format=(fourcc)WVC1" "gstreamer|0.10|totem|Windows Media Audio 9 decoder|decoder-audio/x-wma, wmaversion=(int)3, bitrate=(int)192000, depth=(int)16" "gstreamer|0.10|totem|FOOBAR protocol source|urisource-foobar (FOOBAR protocol source)"
+
commit 567000c28394f85e4d5f2e59c189be1e8b6bfba8
Author: Richard Hughes <richard at hughsie.com>
Date:   Thu Sep 25 16:50:35 2008 +0100

    trivial: enable the unit tests in the rpmbuild so we can get some decent coverage stats for the other archs

diff --git a/contrib/PackageKit.spec.in b/contrib/PackageKit.spec.in
index b22e3b1..f3c4147 100644
--- a/contrib/PackageKit.spec.in
+++ b/contrib/PackageKit.spec.in
@@ -142,11 +142,15 @@ using PackageKit.
 %setup -q
 
 %build
-%configure --enable-yum --enable-smart --with-default-backend=yum --disable-local
-
+# build and test on all architectures
+%configure --enable-dummy --with-default-backend=dummy --enable-tests --enable-local
 make %{?_smp_mflags}
-make check -C src
 make check -C libpackagekit
+make check -C src
+
+# reconfigure with testing off (smaller binaries)
+%configure --enable-yum --enable-smart --with-default-backend=yum --disable-local
+make %{?_smp_mflags}
 
 %install
 rm -rf $RPM_BUILD_ROOT
commit 530034981d1360ab0544f786d22535cc09197d54
Merge: 3efdd8f... 42a6f80...
Author: Sebastian Heinlein <devel at glatzor.de>
Date:   Thu Sep 25 17:49:26 2008 +0200

    Merge branch 'master' of git+ssh://glatzor@git.packagekit.org/srv/git/PackageKit

commit 3efdd8f9f6296eb1c3a6c56e9d57ed48f841d6a5
Author: Sebastian Heinlein <devel at glatzor.de>
Date:   Thu Sep 25 17:47:30 2008 +0200

    APT: only report repo and distro upgrade methods available if the
    corresponding python modules are installed

diff --git a/backends/apt/pk-backend-apt.c b/backends/apt/pk-backend-apt.c
index d3b5ed2..901c59c 100644
--- a/backends/apt/pk-backend-apt.c
+++ b/backends/apt/pk-backend-apt.c
@@ -20,6 +20,8 @@
  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  */
 
+#include "config.h"
+
 #include <pk-backend.h>
 #include <pk-backend-dbus.h>
 
@@ -179,6 +181,7 @@ backend_get_files (PkBackend *backend, gchar **package_ids)
 	pk_backend_dbus_get_files (dbus, package_ids);
 }
 
+#ifdef HAVE_PYTHON_META_RELEASE
 /**
  * backend_get_distro_upgrades:
  *  */
@@ -187,6 +190,7 @@ backend_get_distro_upgrades (PkBackend *backend)
 {
 	pk_backend_dbus_get_distro_upgrades (dbus);
 }
+#endif /* HAVE_PYTHON_META_RELEASE */
 
 
 /**
@@ -271,6 +275,7 @@ backend_get_packages (PkBackend *backend, PkBitfield filters)
 	        pk_backend_dbus_get_packages (dbus, filters);
 }
 
+#ifdef HAVE_PYTHON_SOFTWARE_PROPERTIES
 /**
  *  * pk_backend_get_repo_list:
  *   */
@@ -281,6 +286,17 @@ backend_get_repo_list (PkBackend *backend, PkBitfield filters)
 }
 
 /**
+ *  * pk_backend_repo_enable
+ *   */
+static void
+backend_repo_enable (PkBackend *backend, const gchar *repo_id, gboolean enable )
+{
+	        pk_backend_dbus_repo_enable (dbus, repo_id, enable);
+}
+#endif /* HAVE_PYTHON_SOFTWARE_PROPERTIES */
+
+
+/**
  *  * pk_backend_get_requires:
  *   */
 static void
@@ -316,15 +332,6 @@ backend_what_provides (PkBackend *backend, PkBitfield filters, PkProvidesEnum pr
 	        pk_backend_dbus_what_provides (dbus, filters, provides, search);
 }
 
-/**
- *  * pk_backend_repo_enable
- *   */
-static void
-backend_repo_enable (PkBackend *backend, const gchar *repo_id, gboolean enable )
-{
-	        pk_backend_dbus_repo_enable (dbus, repo_id, enable);
-}
-
 
 
 PK_BACKEND_OPTIONS (
@@ -338,10 +345,18 @@ PK_BACKEND_OPTIONS (
 	backend_download_packages,		/* download_packages */
 	backend_get_depends,			/* get_depends */
 	backend_get_details,			/* get_details */
+#ifdef HAVE_PYTHON_META_RELEASE
 	backend_get_distro_upgrades,		/* get_distro_upgrades */
+#else
+	NULL,					/* get_distro_upgrades */
+#endif /* HAVE_PYTHON_META_RELEASE */
 	backend_get_files,			/* get_files */
 	backend_get_packages,			/* get_packages */
+#ifdef HAVE_PYTHON_SOFTWARE_PROPERTIES
 	backend_get_repo_list,			/* get_repo_list */
+#else
+	NULL,					/* get_repo_list */
+#endif /* HAVE_PYTHON_SOFTWARE_PROPERTIES */
 	backend_get_requires,			/* get_requires */
 	backend_get_update_detail,		/* get_update_detail */
 	backend_get_updates,			/* get_updates */
@@ -350,7 +365,11 @@ PK_BACKEND_OPTIONS (
 	NULL,					/* install_signature */
 	backend_refresh_cache,			/* refresh_cache */
 	backend_remove_packages,		/* remove_packages */
+#ifdef HAVE_PYTHON_SOFTWARE_PROPERTIES
 	backend_repo_enable,			/* repo_enable */
+#else
+	NULL,					/* repo_enable */
+#endif /* HAVE_PYTHON_SOFTWARE_PROPERTIES */
 	NULL,					/* repo_set_data */
 	backend_resolve,			/* resolve */
 	NULL,					/* rollback */
diff --git a/configure.ac b/configure.ac
index 8c4baef..8420ba5 100644
--- a/configure.ac
+++ b/configure.ac
@@ -456,6 +456,14 @@ AC_SUBST(DEFAULT_BACKEND, "$with_default_backend")
 
 if test x$enable_apt = xyes; then
 	PY_CHECK_MOD([apt_pkg],,,AC_MSG_ERROR([Apt backend needs python-apt]))
+	PY_CHECK_MOD([UpdateManager.Core.MetaRelease],,
+		     AC_DEFINE(HAVE_PYTHON_META_RELEASE, 1,
+			       "Meta release is available"), 
+		     AC_MSG_WARN([Distro upgrade notification not supported]))
+	PY_CHECK_MOD([softwareproperties.SoftwareProperties],,
+		     AC_DEFINE(HAVE_PYTHON_SOFTWARE_PROPERTIES, 1,
+			       "Python software properties is available"),
+		     AC_MSG_WARN([Repository handling not supported]))
 fi
 
 if test x$enable_box = xyes; then
commit 42a6f80eb562b4198ba72517cb4e349100f5258d
Author: Sharuzzaman Ahmat Raslan <sharuzzaman at gmail.com>
Date:   Thu Sep 25 15:40:15 2008 +0000

    Add new Malay translation
    
    Transmitted-via: Transifex (translate.fedoraproject.org)

diff --git a/po/ms.po b/po/ms.po
new file mode 100644
index 0000000..4cbb92f
--- /dev/null
+++ b/po/ms.po
@@ -0,0 +1,488 @@
+# packagekit Bahasa Melayu (Malay) (ms)
+# Copyright (C) 2008 Fedora Project
+# This file is distributed under the same license as the packagekit package.
+# Sharuzzaman Ahmat Raslan <sharuzzaman at myrealbox.com>, 2008.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: packagekit\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2008-09-23 11:26+0000\n"
+"PO-Revision-Date: 2008-09-25 23:36+0800\n"
+"Last-Translator: Sharuzzaman Ahmat Raslan <sharuzzaman at myrealbox.com>\n"
+"Language-Team: Malay <translation-team-ms at lists.sourceforge.net>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=utf-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#: ../client/pk-console.c:274
+#, fuzzy
+msgid "Update detail"
+msgstr " Auto Kemaskini"
+
+#: ../client/pk-console.c:491
+#, fuzzy
+msgid "A system restart is required"
+msgstr "Katalaluan diperlukan, ini adalah dokumen yang dienkrip"
+
+#: ../client/pk-console.c:493
+msgid "A logout and login is required"
+msgstr ""
+
+#: ../client/pk-console.c:495
+#, fuzzy
+msgid "An application restart is required"
+msgstr "Katalaluan diperlukan, ini adalah dokumen yang dienkrip"
+
+#: ../client/pk-console.c:588
+#: ../client/pk-generate-pack.c:126
+msgid "There are multiple package matches"
+msgstr ""
+
+#. find out what package the user wants to use
+#: ../client/pk-console.c:595
+#: ../client/pk-generate-pack.c:133
+#, fuzzy
+msgid "Please enter the package number: "
+msgstr "Sila masukkan %(instkey) anda."
+
+#: ../client/pk-console.c:629
+#, fuzzy
+msgid "Could not find package to install"
+msgstr "  -P             - jangan cari dalam tersedia utk mencari pakej.\n"
+
+#: ../client/pk-console.c:735
+#, fuzzy
+msgid "Could not find package to remove"
+msgstr "  -P             - jangan cari dalam tersedia utk mencari pakej.\n"
+
+#: ../client/pk-console.c:796
+#, fuzzy
+msgid "The following packages have to be removed"
+msgstr "Memeriksa untuk membuang pakej berikut"
+
+#. get user input
+#: ../client/pk-console.c:803
+#, fuzzy
+msgid "Okay to remove additional packages?"
+msgstr "Memeriksa untuk membuang pakej berikut"
+
+#: ../client/pk-console.c:807
+#: ../client/pk-generate-pack.c:528
+#: ../client/pk-generate-pack-main.c:131
+#, fuzzy
+msgid "Cancelled!"
+msgstr "Dibatalkan"
+
+#: ../client/pk-console.c:841
+#, fuzzy
+msgid "Could not find package to download"
+msgstr "  -P             - jangan cari dalam tersedia utk mencari pakej.\n"
+
+#: ../client/pk-console.c:893
+#, fuzzy
+msgid "Could not find package to update"
+msgstr "  -P             - jangan cari dalam tersedia utk mencari pakej.\n"
+
+#: ../client/pk-console.c:915
+msgid "Could not find what packages require"
+msgstr ""
+
+#: ../client/pk-console.c:936
+#, fuzzy
+msgid "Could not get dependencies for"
+msgstr "Tidak dapat memperoleh kekunci OpenPGP."
+
+#: ../client/pk-console.c:957
+#, fuzzy
+msgid "Could not find details for"
+msgstr "Tidak dapat mencari subkekunci OpenPGP."
+
+#: ../client/pk-console.c:980
+msgid "Could not find the files for this package"
+msgstr ""
+
+#: ../client/pk-console.c:987
+#, fuzzy
+msgid "Could not get the file list"
+msgstr "Tidak dapat menulis kepada fail %s"
+
+#: ../client/pk-console.c:1006
+msgid "Could not find the update details for"
+msgstr ""
+
+#: ../client/pk-console.c:1067
+#, fuzzy
+msgid "Package description"
+msgstr "Tiada keterangan"
+
+#: ../client/pk-console.c:1100
+#, fuzzy
+msgid "Package files"
+msgstr "  -l             - senaraikan fail dalam pakej.\n"
+
+#: ../client/pk-console.c:1108
+#, fuzzy
+msgid "No files"
+msgstr "Tiada fail boleh ditukar nama dijumpai."
+
+#. get user input
+#: ../client/pk-console.c:1140
+#, fuzzy
+msgid "Okay to import key?"
+msgstr "tidak dapat mengimport fail pubkey \"%s\""
+
+#: ../client/pk-console.c:1143
+#, fuzzy
+msgid "Did not import key"
+msgstr "Tidak dapat memperoleh kekunci OpenPGP."
+
+#. get user input
+#: ../client/pk-console.c:1183
+#, fuzzy
+msgid "Do you agree?"
+msgstr "Anda ada Cekera jurupacu?"
+
+#: ../client/pk-console.c:1186
+msgid "Did not agree to licence, task will fail"
+msgstr ""
+
+#: ../client/pk-console.c:1215
+msgid "The daemon crashed mid-transaction!"
+msgstr ""
+
+#. header
+#: ../client/pk-console.c:1268
+#, fuzzy
+msgid "PackageKit Console Interface"
+msgstr "Bahasa Antaramuka Pengguna"
+
+#: ../client/pk-console.c:1268
+msgid "Subcommands:"
+msgstr ""
+
+#: ../client/pk-console.c:1378
+#: ../client/pk-generate-pack-main.c:64
+#: ../client/pk-monitor.c:118
+#: ../src/pk-main.c:189
+msgid "Show extra debugging information"
+msgstr ""
+
+#: ../client/pk-console.c:1380
+#: ../client/pk-monitor.c:120
+#, fuzzy
+msgid "Show the program version and exit"
+msgstr "Papar maklumat program, nombor versi, dan hakcipta"
+
+#: ../client/pk-console.c:1382
+#, fuzzy
+msgid "Set the filter, e.g. installed"
+msgstr " tiada pemandu dipasang."
+
+#: ../client/pk-console.c:1384
+msgid "Exit without waiting for actions to complete"
+msgstr ""
+
+#: ../client/pk-console.c:1407
+msgid "Could not connect to system DBUS."
+msgstr ""
+
+#: ../client/pk-console.c:1500
+#, fuzzy
+msgid "You need to specify a search type, e.g. name"
+msgstr "(anda tidak perlu menaip domain selepas nama)"
+
+#: ../client/pk-console.c:1505
+#: ../client/pk-console.c:1512
+#: ../client/pk-console.c:1519
+#: ../client/pk-console.c:1526
+#: ../client/pk-console.c:1637
+#: ../client/pk-console.c:1647
+#: ../client/pk-console.c:1654
+#: ../client/pk-console.c:1661
+#, fuzzy
+msgid "You need to specify a search term"
+msgstr "Anda perlu menyatakan fail untuk dibuka!"
+
+#: ../client/pk-console.c:1531
+#, fuzzy
+msgid "Invalid search type"
+msgstr "Jenis Senarai Semasa"
+
+#: ../client/pk-console.c:1536
+msgid "You need to specify a package or file to install"
+msgstr ""
+
+#: ../client/pk-console.c:1543
+msgid "You need to specify a type, key_id and package_id"
+msgstr ""
+
+#: ../client/pk-console.c:1550
+#, fuzzy
+msgid "You need to specify a package to remove"
+msgstr "Anda perlu menyatakan fail untuk dibuka!"
+
+#: ../client/pk-console.c:1556
+msgid "You need to specify the destination directory and then the packages to download"
+msgstr ""
+
+#: ../client/pk-console.c:1561
+#, fuzzy
+msgid "Directory not found"
+msgstr "Fail %s tidak dijumpai"
+
+#: ../client/pk-console.c:1567
+#, fuzzy
+msgid "You need to specify a eula-id"
+msgstr "Anda perlu menyatakan fail untuk dibuka!"
+
+#: ../client/pk-console.c:1583
+msgid "You need to specify a package name to resolve"
+msgstr ""
+
+#: ../client/pk-console.c:1592
+#: ../client/pk-console.c:1599
+#, fuzzy
+msgid "You need to specify a repo name"
+msgstr "Anda perlu menyatakan fail untuk dibuka!"
+
+#: ../client/pk-console.c:1606
+msgid "You need to specify a repo name/parameter and value"
+msgstr ""
+
+#: ../client/pk-console.c:1619
+#, fuzzy
+msgid "You need to specify a time term"
+msgstr "Anda perlu menyatakan fail untuk dibuka!"
+
+#: ../client/pk-console.c:1624
+#, fuzzy
+msgid "You need to specify a correct role"
+msgstr "Anda perlu menyatakan fail untuk dibuka!"
+
+#: ../client/pk-console.c:1629
+msgid "Failed to get last time"
+msgstr ""
+
+#: ../client/pk-console.c:1668
+msgid "You need to specify a package to find the details for"
+msgstr ""
+
+#: ../client/pk-console.c:1675
+msgid "You need to specify a package to find the files for"
+msgstr ""
+
+#: ../client/pk-console.c:1724
+#, fuzzy, c-format
+msgid "Option '%s' not supported"
+msgstr "Format Tidak Disokong"
+
+#: ../client/pk-console.c:1737
+msgid "You don't have the necessary privileges for this operation"
+msgstr ""
+
+#: ../client/pk-console.c:1739
+#, fuzzy
+msgid "Command failed"
+msgstr "Sambungan Gagal"
+
+#: ../client/pk-generate-pack.c:117
+#, fuzzy
+msgid "Could not find a package match"
+msgstr "Tidak dapat mencari subkekunci OpenPGP."
+
+#: ../client/pk-generate-pack.c:151
+msgid "failed to download: invalid package_id and/or directory"
+msgstr ""
+
+#: ../client/pk-generate-pack.c:232
+msgid "Could not find a valid metadata file"
+msgstr ""
+
+#. get user input
+#: ../client/pk-generate-pack.c:524
+msgid "Okay to download the additional packages"
+msgstr ""
+
+#: ../client/pk-generate-pack-main.c:66
+msgid "Set the path of the file with the list of packages/dependencies to be excluded"
+msgstr ""
+
+#: ../client/pk-generate-pack-main.c:111
+msgid "You need to specify the pack name and packages to be packed\n"
+msgstr ""
+
+#: ../client/pk-generate-pack-main.c:117
+msgid "Invalid name for the service pack, Specify a name with .servicepack extension\n"
+msgstr ""
+
+#: ../client/pk-generate-pack-main.c:129
+msgid "A pack with the same name already exists, do you want to overwrite it?"
+msgstr ""
+
+#: ../client/pk-generate-pack-main.c:142
+#, fuzzy
+msgid "Failed to create directory"
+msgstr "gagal untuk mencipta direktori %s: %s\n"
+
+#: ../client/pk-generate-pack-main.c:149
+#, fuzzy
+msgid "Failed to create pack"
+msgstr "gagal untuk mencipta direktori %s: %s\n"
+
+#: ../client/pk-import-desktop.c:305
+#: ../client/pk-import-specspo.c:185
+#, fuzzy, c-format
+msgid "Could not open database: %s"
+msgstr "Tak dapat membuka fail %s."
+
+#: ../client/pk-import-desktop.c:306
+#: ../client/pk-import-specspo.c:186
+msgid "You probably need to run this program as the root user"
+msgstr ""
+
+#: ../client/pk-monitor.c:131
+#, fuzzy
+msgid "PackageKit Monitor"
+msgstr "Monitor Rangkaian"
+
+#: ../client/pk-tools-common.c:51
+#, fuzzy, c-format
+msgid "Please enter a number from 1 to %i: "
+msgstr "Pilih nombor latihan dari 1 hingga 10."
+
+#: ../contrib/packagekit-plugin/src/contents.cpp:300
+#, fuzzy
+msgid "Getting package information..."
+msgstr "Lebih maklumat pada pakej %s"
+
+#: ../contrib/packagekit-plugin/src/contents.cpp:304
+#, c-format
+msgid "<span color='#%06x' underline='single' size='larger'>Run %s</span>"
+msgstr ""
+
+#: ../contrib/packagekit-plugin/src/contents.cpp:308
+#: ../contrib/packagekit-plugin/src/contents.cpp:313
+#: ../contrib/packagekit-plugin/src/contents.cpp:336
+#: ../contrib/packagekit-plugin/src/contents.cpp:340
+#, c-format
+msgid "<big>%s</big>"
+msgstr ""
+
+#: ../contrib/packagekit-plugin/src/contents.cpp:310
+#, fuzzy, c-format
+msgid ""
+"\n"
+"<small>Installed version: %s</small>"
+msgstr "Versi dipasang semasa:"
+
+#: ../contrib/packagekit-plugin/src/contents.cpp:316
+#, c-format
+msgid ""
+"\n"
+"<span color='#%06x' underline='single'>Run version %s now</span>"
+msgstr ""
+
+#: ../contrib/packagekit-plugin/src/contents.cpp:321
+#, c-format
+msgid ""
+"\n"
+"<span color='#%06x' underline='single'>Run now</span>"
+msgstr ""
+
+#: ../contrib/packagekit-plugin/src/contents.cpp:325
+#, c-format
+msgid ""
+"\n"
+"<span color='#%06x' underline='single'>Upgrade to version %s</span>"
+msgstr ""
+
+#: ../contrib/packagekit-plugin/src/contents.cpp:330
+#, c-format
+msgid "<span color='#%06x' underline='single' size='larger'>Install %s Now</span>"
+msgstr ""
+
+#: ../contrib/packagekit-plugin/src/contents.cpp:333
+#, fuzzy, c-format
+msgid ""
+"\n"
+"<small>Version: %s</small>"
+msgstr "Sejarah versi"
+
+#: ../contrib/packagekit-plugin/src/contents.cpp:337
+msgid ""
+"\n"
+"<small>No packages found for your system</small>"
+msgstr ""
+
+#: ../contrib/packagekit-plugin/src/contents.cpp:341
+#, fuzzy
+msgid ""
+"\n"
+"<small>Installing...</small>"
+msgstr "Memasang pemuatboot..."
+
+#: ../data/packagekit-catalog.xml.in.h:1
+#, fuzzy
+msgid "PackageKit Catalog"
+msgstr "Kembalikan Dari Katalog"
+
+#: ../data/packagekit-pack.xml.in.h:1
+#, fuzzy
+msgid "PackageKit Service Pack"
+msgstr "Konfigur penemuan servis"
+
+#: ../src/pk-main.c:83
+msgid "Startup failed due to security policies on this machine."
+msgstr ""
+
+#: ../src/pk-main.c:84
+msgid "This can happen for two reasons:"
+msgstr ""
+
+#: ../src/pk-main.c:85
+msgid "The correct user is not launching the executable (usually root)"
+msgstr ""
+
+#: ../src/pk-main.c:86
+msgid "The org.freedesktop.PackageKit.conf file is not installed in the system /etc/dbus-1/system.d directory"
+msgstr ""
+
+#: ../src/pk-main.c:185
+msgid "Packaging backend to use, e.g. dummy"
+msgstr ""
+
+#: ../src/pk-main.c:187
+msgid "Daemonize and detach from the terminal"
+msgstr ""
+
+#: ../src/pk-main.c:191
+#, fuzzy
+msgid "Disable the idle timer"
+msgstr "Widget penetapan pemasa"
+
+#: ../src/pk-main.c:193
+msgid "Show version and exit"
+msgstr "Papar versi dan keluar"
+
+#: ../src/pk-main.c:195
+msgid "Exit after a small delay"
+msgstr ""
+
+#: ../src/pk-main.c:197
+msgid "Exit after the engine has loaded"
+msgstr ""
+
+#: ../src/pk-main.c:207
+msgid "PackageKit service"
+msgstr "Servis PackageKit"
+
+#: ../src/pk-main.c:233
+msgid "Cannot connect to the system bus"
+msgstr ""
+
+#: ../src/pk-main.c:273
+#, c-format
+msgid "Error trying to start: %s\n"
+msgstr "Ralat cuba untuk memulakan: %s\n"
+
commit 678ae82a5b8a349cde83a92cb8873622ba5b07f0
Author: Richard Hughes <richard at hughsie.com>
Date:   Thu Sep 25 16:19:03 2008 +0100

    trivial: skip the GObjects that require packagekitd to be running if it is not already running

diff --git a/libpackagekit/pk-catalog.c b/libpackagekit/pk-catalog.c
index b793a67..1a71cce 100644
--- a/libpackagekit/pk-catalog.c
+++ b/libpackagekit/pk-catalog.c
@@ -375,12 +375,15 @@ pk_catalog_new (void)
  ***************************************************************************/
 #ifdef EGG_TEST
 #include "egg-test.h"
+#include "pk-connection.h"
 
 void
 pk_catalog_test (EggTest *test)
 {
+	PkConnection *connection;
 	PkCatalog *catalog;
 	PkPackageList *list;
+	gboolean ret;
 	gchar **filenames;
 	gchar *path;
 	guint size;
@@ -388,6 +391,15 @@ pk_catalog_test (EggTest *test)
 	if (!egg_test_start (test, "PkCatalog"))
 		return;
 
+	/* check to see if there is a daemon running */
+	connection = pk_connection_new ();
+	ret = pk_connection_valid (connection);
+	g_object_unref (connection);
+	if (!ret) {
+		egg_warning ("daemon is not running, skipping tests");
+		goto out;
+	}
+
 	/************************************************************/
 	egg_test_title (test, "get catalog");
 	catalog = pk_catalog_new ();
@@ -414,7 +426,7 @@ pk_catalog_test (EggTest *test)
 		egg_test_failed (test, NULL);
 	g_object_unref (list);
 	g_object_unref (catalog);
-
+out:
 	egg_test_end (test);
 }
 #endif
diff --git a/libpackagekit/pk-client.c b/libpackagekit/pk-client.c
index 4ade736..0a6c438 100644
--- a/libpackagekit/pk-client.c
+++ b/libpackagekit/pk-client.c
@@ -4040,6 +4040,7 @@ pk_client_test_copy_package_cb (PkClient *client, const PkPackageObj *obj, EggTe
 void
 pk_client_test (EggTest *test)
 {
+	PkConnection *connection;
 	PkClient *client;
 	PkClient *client_copy;
 	gboolean ret;
@@ -4054,6 +4055,15 @@ pk_client_test (EggTest *test)
 	if (!egg_test_start (test, "PkClient"))
 		return;
 
+	/* check to see if there is a daemon running */
+	connection = pk_connection_new ();
+	ret = pk_connection_valid (connection);
+	g_object_unref (connection);
+	if (!ret) {
+		egg_warning ("daemon is not running, skipping tests");
+		goto out;
+	}
+
 	/************************************************************/
 	egg_test_title (test, "test resolve NULL");
 	file = pk_resolve_local_path (NULL);
@@ -4305,7 +4315,7 @@ pk_client_test (EggTest *test)
 		error = NULL;
 	}
 	g_object_unref (client);
-
+out:
 	egg_test_end (test);
 }
 #endif
diff --git a/libpackagekit/pk-control.c b/libpackagekit/pk-control.c
index 5adc0eb..362cee5 100644
--- a/libpackagekit/pk-control.c
+++ b/libpackagekit/pk-control.c
@@ -927,17 +927,28 @@ pk_control_new (void)
 void
 pk_control_test (EggTest *test)
 {
+	gboolean ret;
 	PkControl *control;
+	PkConnection *connection;
 
 	if (!egg_test_start (test, "PkControl"))
 		return;
 
+	/* check to see if there is a daemon running */
+	connection = pk_connection_new ();
+	ret = pk_connection_valid (connection);
+	g_object_unref (connection);
+	if (!ret) {
+		egg_warning ("daemon is not running, skipping tests");
+		goto out;
+	}
+
 	/************************************************************/
 	egg_test_title (test, "get control");
 	control = pk_control_new ();
 	egg_test_assert (test, control != NULL);
 	g_object_unref (control);
-
+out:
 	egg_test_end (test);
 }
 #endif
diff --git a/libpackagekit/pk-task-list.c b/libpackagekit/pk-task-list.c
index 79f7a2e..04f4839 100644
--- a/libpackagekit/pk-task-list.c
+++ b/libpackagekit/pk-task-list.c
@@ -513,6 +513,7 @@ pk_task_list_new (void)
  ***************************************************************************/
 #ifdef EGG_TEST
 #include "egg-test.h"
+#include "pk-connection.h"
 
 static gboolean finished = FALSE;
 
@@ -528,6 +529,7 @@ pk_task_list_test_finished_cb (PkTaskList *tlist, PkClient *client, PkExitEnum e
 void
 pk_task_list_test (EggTest *test)
 {
+	PkConnection *connection;
 	PkTaskList *tlist;
 	PkClient *client;
 	gboolean ret;
@@ -536,6 +538,15 @@ pk_task_list_test (EggTest *test)
 	if (!egg_test_start (test, "PkTaskList"))
 		return;
 
+	/* check to see if there is a daemon running */
+	connection = pk_connection_new ();
+	ret = pk_connection_valid (connection);
+	g_object_unref (connection);
+	if (!ret) {
+		egg_warning ("daemon is not running, skipping tests");
+		goto out;
+	}
+
 	/************************************************************/
 	egg_test_title (test, "get client");
 	tlist = pk_task_list_new ();
@@ -563,7 +574,7 @@ pk_task_list_test (EggTest *test)
 
 	g_object_unref (tlist);
 	g_object_unref (client);
-
+out:
 	egg_test_end (test);
 }
 #endif
commit f1bd45184fb5a8a054de6b0595cd10cbfabfa493
Author: Richard Hughes <richard at hughsie.com>
Date:   Thu Sep 25 16:17:56 2008 +0100

    trivial: the last self check is only valid for developers as otherwise the warnings won't be shown

diff --git a/src/pk-backend.c b/src/pk-backend.c
index 5d013e7..71c92c1 100644
--- a/src/pk-backend.c
+++ b/src/pk-backend.c
@@ -2135,11 +2135,13 @@ pk_backend_test (EggTest *test)
 	egg_test_loop_wait (test, PK_BACKEND_FINISHED_ERROR_TIMEOUT + 400);
 	egg_test_loop_check (test);
 
+#ifdef PK_IS_DEVELOPER
 	egg_test_title (test, "check we enforce finished after error_code");
 	if (number_messages == 1)
 		egg_test_success (test, NULL);
 	else
 		egg_test_failed (test, "we messaged %i times!", number_messages);
+#endif
 
 	g_object_unref (backend);
 
commit 4c1164763956f858d371956a4c4d2840bcc27104
Author: Richard Hughes <richard at hughsie.com>
Date:   Thu Sep 25 16:15:25 2008 +0100

    Revert "trivial: fix up the deps for the web plugin"
    
    This reverts commit 5ce029a5383858dddc01d19ba26d61675ecee4ee.

diff --git a/configure.ac b/configure.ac
index aaa3d14..8c4baef 100644
--- a/configure.ac
+++ b/configure.ac
@@ -241,7 +241,7 @@ dnl ---------------------------------------------------------------------------
 dnl - Checks for contrib/packagekit-plugin
 dnl ---------------------------------------------------------------------------
 
-PKG_CHECK_MODULES(PK_BROWSER_PLUGIN, mozilla-plugin gio-unix-2.0 cairo pango gtk+-2.0 dbus-glib-1 gtk-x11-2.0,
+PKG_CHECK_MODULES(PK_BROWSER_PLUGIN, mozilla-plugin gio-unix-2.0 cairo pango gtk+-2.0 dbus-glib-1,
                   build_browser_plugin=yes, build_browser_plugin=no)
 
 AM_CONDITIONAL(PK_BUILD_BROWSER_PLUGIN, test $build_browser_plugin = "yes")
commit c4d83b81f8639386570f707624aaa4f508d2332f
Author: Richard Hughes <richard at hughsie.com>
Date:   Thu Sep 25 15:49:39 2008 +0100

    trivial: dist pk-spawn-dispatcher.py so we can use it in the self check library in a buildroot

diff --git a/data/tests/Makefile.am b/data/tests/Makefile.am
index 2203ebf..58bcf89 100644
--- a/data/tests/Makefile.am
+++ b/data/tests/Makefile.am
@@ -9,6 +9,7 @@ TEST_FILES =						\
 	pk-spawn-proxy.sh				\
 	pk-spawn-test-sigquit.sh			\
 	pk-spawn-test-profiling.sh			\
+	pk-spawn-dispatcher.py				\
 	$(NULL)
 
 EXTRA_DIST =						\
commit 5ce029a5383858dddc01d19ba26d61675ecee4ee
Author: Richard Hughes <richard at hughsie.com>
Date:   Thu Sep 25 15:42:24 2008 +0100

    trivial: fix up the deps for the web plugin

diff --git a/configure.ac b/configure.ac
index 8c4baef..aaa3d14 100644
--- a/configure.ac
+++ b/configure.ac
@@ -241,7 +241,7 @@ dnl ---------------------------------------------------------------------------
 dnl - Checks for contrib/packagekit-plugin
 dnl ---------------------------------------------------------------------------
 
-PKG_CHECK_MODULES(PK_BROWSER_PLUGIN, mozilla-plugin gio-unix-2.0 cairo pango gtk+-2.0 dbus-glib-1,
+PKG_CHECK_MODULES(PK_BROWSER_PLUGIN, mozilla-plugin gio-unix-2.0 cairo pango gtk+-2.0 dbus-glib-1 gtk-x11-2.0,
                   build_browser_plugin=yes, build_browser_plugin=no)
 
 AM_CONDITIONAL(PK_BUILD_BROWSER_PLUGIN, test $build_browser_plugin = "yes")
commit addef4fc8c4a748d41f188d37ff9ec350655312a
Author: Richard Hughes <richard at hughsie.com>
Date:   Thu Sep 25 15:05:39 2008 +0100

    trivial: fix up two errors missed by the regex

diff --git a/backends/yum/yumBackend.py b/backends/yum/yumBackend.py
index b93b47c..7976aa1 100755
--- a/backends/yum/yumBackend.py
+++ b/backends/yum/yumBackend.py
@@ -507,7 +507,7 @@ class PackageKitYumBackend(PackageKitBaseBackend, PackagekitPackage):
 
     def _is_meta_package(self, package_id):
         grp = None
-        if len(id.split(';')) > 1:
+        if len(package_id.split(';')) > 1:
             # Split up the id
             (name, idver, a, repo) = self.get_package_from_id(package_id)
             if repo == 'meta':
@@ -525,7 +525,7 @@ class PackageKitYumBackend(PackageKitBaseBackend, PackagekitPackage):
             return None, False
 
         # is this an real id or just an name
-        if len(id.split(';')) > 1:
+        if len(package_id.split(';')) > 1:
             # Split up the id
             (n, idver, a, d) = self.get_package_from_id(package_id)
             # get e, v, r from package id version
commit fe8c9f44fbed9a51494b028e5b7157d71a371a32
Author: Richard Hughes <richard at hughsie.com>
Date:   Thu Sep 25 15:05:06 2008 +0100

    trivial: fix up the fedora spec file

diff --git a/contrib/PackageKit.spec.in b/contrib/PackageKit.spec.in
index ca0a09e..b22e3b1 100644
--- a/contrib/PackageKit.spec.in
+++ b/contrib/PackageKit.spec.in
@@ -145,6 +145,8 @@ using PackageKit.
 %configure --enable-yum --enable-smart --with-default-backend=yum --disable-local
 
 make %{?_smp_mflags}
+make check -C src
+make check -C libpackagekit
 
 %install
 rm -rf $RPM_BUILD_ROOT
@@ -202,7 +204,6 @@ update-mime-database %{_datadir}/mime &> /dev/null || :
 %{_bindir}/pkgenpack
 %{_bindir}/packagekit-bugreport.sh
 %{_libexecdir}/pk-import-*
-%{_libexecdir}/pk-generate-*
 %exclude %{_libdir}/libpackagekit*.so.*
 %{_libdir}/packagekit-backend/libpk_backend_dummy.so
 %{_libdir}/packagekit-backend/libpk_backend_test_*.so
commit fabdbdab8b3c6dc3c94fb680344bb486dca682a0
Merge: 011ff55... 3a8dd8c...
Author: Sebastian Heinlein <devel at glatzor.de>
Date:   Thu Sep 25 16:00:54 2008 +0200

    Merge branch 'master' of git+ssh://glatzor@git.packagekit.org/srv/git/PackageKit

commit 011ff55784e6208fa8cf1b9f3fbcfda3d8a08c5d
Author: Sebastian Heinlein <devel at glatzor.de>
Date:   Thu Sep 25 16:00:33 2008 +0200

    APT: Small fixes to the test script

diff --git a/backends/apt/test.py b/backends/apt/test.py
index 00b4fd8..45223a0 100755
--- a/backends/apt/test.py
+++ b/backends/apt/test.py
@@ -104,7 +104,7 @@ class AptBackendTestCase(unittest.TestCase):
                               "contrast to apt")
         self.assertTrue(marked == blocked == [], 
                         "PackageKit didn't return all updates:"
-                        "blocked: %s, available: %s" % (blocked, marked)))
+                        "blocked: %s, available: %s" % (blocked, marked))
  
     def testResolve(self):
         """
@@ -123,7 +123,7 @@ class AptBackendTestCase(unittest.TestCase):
         if self.cache["yum"].isInstalled:
             self.pk.RemovePackages([PKG_ID], self._callback)
         self.pk.InstallPackages([PKG_ID], self._callback)
-        self.cache.open()
+        self.cache.open(None)
         self.assertTrue(self.cache["yum"].isInstalled,
                         "yum was not installed")
 
@@ -134,7 +134,7 @@ class AptBackendTestCase(unittest.TestCase):
         if not self.cache["yum"].isInstalled:
             self.pk.InstallPackages([PKG_ID], self._callback)
         self.pk.RemovePackages([PKG_ID], self._callback)
-        self.cache.open()
+        self.cache.open(None)
         self.assertFalse(self.cache["yum"].isInstalled,
                          "yum is still installed")
 
@@ -152,4 +152,5 @@ def main():
 
 if __name__ == '__main__':
     main()
+
 # vim: ts=4 et sts=4
commit 06129484f0a1b89fcc192309f2ef99a7ce81e96e
Author: Richard Hughes <richard at hughsie.com>
Date:   Thu Sep 25 14:37:46 2008 +0100

    trivial: add a chunk of self tests to detect if we get data out of cache properly

diff --git a/src/pk-transaction-list.c b/src/pk-transaction-list.c
index b1d3332..82513b0 100644
--- a/src/pk-transaction-list.c
+++ b/src/pk-transaction-list.c
@@ -736,7 +736,7 @@ pk_transaction_list_test (EggTest *test)
 		egg_test_failed (test, "got missing role");
 
 	/************************************************************/
-	egg_test_title (test, "get size one we have in queue");
+	egg_test_title (test, "get size we have in queue");
 	size = pk_transaction_list_get_size (tlist);
 	if (size == 1)
 		egg_test_success (test, NULL);
@@ -799,6 +799,68 @@ pk_transaction_list_test (EggTest *test)
 	g_free (tid);
 
 	/************************************************************
+	 ***************  Get updates from cache    *****************
+	 ************************************************************/
+	item = pk_transaction_list_test_get_item (tlist);
+	g_signal_connect (item->transaction, "finished",
+			  G_CALLBACK (pk_transaction_list_test_finished_cb), test);
+
+	pk_transaction_get_updates (item->transaction, "none", NULL);
+
+	/* wait for cached results*/
+	egg_test_loop_wait (test, 1000);
+	egg_test_loop_check (test);
+
+	/************************************************************/
+	egg_test_title (test, "make sure item has correct flags");
+	if (item->running == FALSE && item->committed == FALSE && item->finished == TRUE)
+		egg_test_success (test, NULL);
+	else
+		egg_test_failed (test, "wrong flags: running[%i] committed[%i] finished[%i]",
+				 item->running, item->committed, item->finished);
+
+	/************************************************************/
+	egg_test_title (test, "get transactions (committed, not finished) in progress (none, as cached)");
+	array = pk_transaction_list_get_array (tlist);
+	size = g_strv_length (array);
+	if (size == 0)
+		egg_test_success (test, NULL);
+	else
+		egg_test_failed (test, "size %i", size);
+	g_strfreev (array);
+
+	/************************************************************/
+	egg_test_title (test, "get size we have in queue");
+	size = pk_transaction_list_get_size (tlist);
+	if (size == 1)
+		egg_test_success (test, NULL);
+	else
+		egg_test_failed (test, "size %i", size);
+
+	/* wait for Cleanup */
+	g_timeout_add_seconds (5, (GSourceFunc) pk_transaction_list_test_delay_cb, test);
+	egg_test_loop_wait (test, 6000);
+	egg_test_loop_check (test);
+
+	/************************************************************/
+	egg_test_title (test, "get transactions (committed, not finished) in progress (none, as cached)");
+	array = pk_transaction_list_get_array (tlist);
+	size = g_strv_length (array);
+	if (size == 0)
+		egg_test_success (test, NULL);
+	else
+		egg_test_failed (test, "size %i", size);
+	g_strfreev (array);
+
+	/************************************************************/
+	egg_test_title (test, "get size we have in queue");
+	size = pk_transaction_list_get_size (tlist);
+	if (size == 0)
+		egg_test_success (test, NULL);
+	else
+		egg_test_failed (test, "size %i", size);
+
+	/************************************************************
 	 ****************  Chained transactions    ******************
 	 ************************************************************/
 
commit a84e0755ae68bcd3c5cc12eee8cf0f1bffdd2cdc
Author: Richard Hughes <richard at hughsie.com>
Date:   Thu Sep 25 14:36:49 2008 +0100

    trivial: up the timeout for the self test as we are now waiting for finished in an idle loop

diff --git a/src/pk-backend.c b/src/pk-backend.c
index 08c92a5..5d013e7 100644
--- a/src/pk-backend.c
+++ b/src/pk-backend.c
@@ -2132,7 +2132,7 @@ pk_backend_test (EggTest *test)
 	pk_backend_error_code (backend, PK_ERROR_ENUM_GPG_FAILURE, "test error");
 
 	/* wait for finished */
-	egg_test_loop_wait (test, PK_BACKEND_FINISHED_ERROR_TIMEOUT + 200);
+	egg_test_loop_wait (test, PK_BACKEND_FINISHED_ERROR_TIMEOUT + 400);
 	egg_test_loop_check (test);
 
 	egg_test_title (test, "check we enforce finished after error_code");
commit 58955c21674e37d43d7353d30ab1da3163699e94
Author: Richard Hughes <richard at hughsie.com>
Date:   Thu Sep 25 14:32:25 2008 +0100

    bugfix: finish a cached transaction in an idle loop
    
    When returning results from a cache we should always return finished in an idle
    loop so we can block and wait for a response without having to know if we need
    to wait for ::Finished()

diff --git a/src/pk-transaction.c b/src/pk-transaction.c
index db68d4d..73f86dc 100644
--- a/src/pk-transaction.c
+++ b/src/pk-transaction.c
@@ -1093,6 +1093,19 @@ pk_transaction_commit (PkTransaction *transaction)
 }
 
 /**
+ * pk_transaction_finished_idle_cb:
+ **/
+static gboolean
+pk_transaction_finished_idle_cb (PkTransaction *transaction)
+{
+	const gchar *exit_text;
+	exit_text = pk_exit_enum_to_text (PK_EXIT_ENUM_SUCCESS);
+	egg_debug ("emitting finished '%s'", exit_text);
+	g_signal_emit (transaction, signals [PK_TRANSACTION_FINISHED], 0, exit_text, 0);
+	return FALSE;
+}
+
+/**
  * pk_transaction_search_check:
  **/
 static gboolean
@@ -1236,7 +1249,6 @@ pk_transaction_accept_eula (PkTransaction *transaction, const gchar *eula_id, DB
 {
 	gboolean ret;
 	GError *error;
-	const gchar *exit_text;
 	gchar *sender;
 
 	g_return_if_fail (PK_IS_TRANSACTION (transaction));
@@ -1275,11 +1287,12 @@ pk_transaction_accept_eula (PkTransaction *transaction, const gchar *eula_id, DB
 		return;
 	}
 
-	exit_text = pk_exit_enum_to_text (PK_EXIT_ENUM_SUCCESS);
-	egg_debug ("emitting finished transaction '%s', %i", exit_text, 0);
-	g_signal_emit (transaction, signals [PK_TRANSACTION_FINISHED], 0, exit_text, 0);
+	/* we are done */
+	g_idle_add ((GSourceFunc) pk_transaction_finished_idle_cb, transaction);
 
-	dbus_g_method_return (context);
+	/* not set inside the test suite */
+	if (context != NULL)
+		dbus_g_method_return (context);
 }
 
 /**
@@ -1756,18 +1769,13 @@ pk_transaction_get_packages (PkTransaction *transaction, const gchar *filter, DB
 gboolean
 pk_transaction_get_old_transactions (PkTransaction *transaction, guint number, GError **error)
 {
-	const gchar *exit_text;
-
 	g_return_val_if_fail (PK_IS_TRANSACTION (transaction), FALSE);
 	g_return_val_if_fail (transaction->priv->tid != NULL, FALSE);
 
 	egg_debug ("GetOldTransactions method called");
 
 	pk_transaction_db_get_list (transaction->priv->transaction_db, number);
-
-	exit_text = pk_exit_enum_to_text (PK_EXIT_ENUM_SUCCESS);
-	egg_debug ("emitting finished transaction '%s', %i", exit_text, 0);
-	g_signal_emit (transaction, signals [PK_TRANSACTION_FINISHED], 0, exit_text, 0);
+	g_idle_add ((GSourceFunc) pk_transaction_finished_idle_cb, transaction);
 
 	return TRUE;
 }
@@ -2085,10 +2093,8 @@ pk_transaction_get_update_detail (PkTransaction *transaction, gchar **package_id
 
 	/* if we have nothing to do, i.e. everything was in the cache */
 	if (array->len == 0) {
-		const gchar *exit_text;
-		exit_text = pk_exit_enum_to_text (PK_EXIT_ENUM_SUCCESS);
-		egg_debug ("emitting finished '%s' as no more to process", exit_text);
-		g_signal_emit (transaction, signals [PK_TRANSACTION_FINISHED], 0, exit_text, 0);
+		/* we are done */
+		g_idle_add ((GSourceFunc) pk_transaction_finished_idle_cb, transaction);
 		goto out;
 	}
 
@@ -2112,7 +2118,9 @@ pk_transaction_get_update_detail (PkTransaction *transaction, gchar **package_id
 out:
 	g_ptr_array_foreach (array, (GFunc) g_free, NULL);
 	g_ptr_array_free (array, TRUE);
-	dbus_g_method_return (context);
+	/* not set inside the test suite */
+	if (context != NULL)
+		dbus_g_method_return (context);
 }
 
 /**
@@ -2166,7 +2174,6 @@ pk_transaction_get_updates (PkTransaction *transaction, const gchar *filter, DBu
 	if (updates_cache != NULL) {
 		const PkPackageObj *obj;
 		const gchar *info_text;
-		const gchar *exit_text;
 		guint i;
 		guint length;
 
@@ -2184,11 +2191,11 @@ pk_transaction_get_updates (PkTransaction *transaction, const gchar *filter, DBu
 		}
 
 		/* we are done */
-		exit_text = pk_exit_enum_to_text (PK_EXIT_ENUM_SUCCESS);
-		egg_debug ("emitting finished '%s'", exit_text);
-		g_signal_emit (transaction, signals [PK_TRANSACTION_FINISHED], 0, exit_text, 0);
+		g_idle_add ((GSourceFunc) pk_transaction_finished_idle_cb, transaction);
 
-		dbus_g_method_return (context);
+		/* not set inside the test suite */
+		if (context != NULL)
+			dbus_g_method_return (context);
 		return;
 	}
 
commit 9136891e84532cbc4bb21932b409476118cad07d
Author: Richard Hughes <richard at hughsie.com>
Date:   Thu Sep 25 14:21:26 2008 +0100

    trivial: use search-name and search-details in the PkTransactionList self tests, as i'll want to use get-updates further up with a cache setting check

diff --git a/src/pk-transaction-list.c b/src/pk-transaction-list.c
index 8fa7afa..b1d3332 100644
--- a/src/pk-transaction-list.c
+++ b/src/pk-transaction-list.c
@@ -833,11 +833,11 @@ pk_transaction_list_test (EggTest *test)
 			  G_CALLBACK (pk_transaction_list_test_finished_cb), test);
 
 	/* this starts one action */
-	pk_transaction_get_updates (item1->transaction, "none", NULL);
+	pk_transaction_search_details (item1->transaction, "none", "dave", NULL);
 	/* this should be chained after the first action completes */
 	pk_transaction_search_name (item2->transaction, "none", "power", NULL);
 	/* this starts be chained after the second action completes */
-	pk_transaction_get_updates (item3->transaction, "none", NULL);
+	pk_transaction_search_details (item3->transaction, "none", "paul", NULL);
 
 	/************************************************************/
 	egg_test_title (test, "get transactions (committed, not finished) in progress (all)");
commit c434c1073d9462cca520c4481bf25a141561f9b8
Author: Richard Hughes <richard at hughsie.com>
Date:   Thu Sep 25 14:19:00 2008 +0100

    trivial: check for context in more places so we can use more methods in the self check framework

diff --git a/src/pk-transaction.c b/src/pk-transaction.c
index aadd8e5..db68d4d 100644
--- a/src/pk-transaction.c
+++ b/src/pk-transaction.c
@@ -1417,7 +1417,9 @@ pk_transaction_download_packages (PkTransaction *transaction, gchar **package_id
 	}
 
 	g_free (directory);
-	dbus_g_method_return (context);
+	/* not set inside the test suite */
+	if (context != NULL)
+		dbus_g_method_return (context);
 }
 
 /**
@@ -1504,7 +1506,9 @@ pk_transaction_get_depends (PkTransaction *transaction, const gchar *filter, gch
 		return;
 	}
 
-	dbus_g_method_return (context);
+	/* not set inside the test suite */
+	if (context != NULL)
+		dbus_g_method_return (context);
 }
 
 /**
@@ -1567,7 +1571,9 @@ pk_transaction_get_details (PkTransaction *transaction, gchar **package_ids, DBu
 		return;
 	}
 
-	dbus_g_method_return (context);
+	/* not set inside the test suite */
+	if (context != NULL)
+		dbus_g_method_return (context);
 }
 
 /**
@@ -1681,7 +1687,9 @@ pk_transaction_get_files (PkTransaction *transaction, gchar **package_ids, DBusG
 		return;
 	}
 
-	dbus_g_method_return (context);
+	/* not set inside the test suite */
+	if (context != NULL)
+		dbus_g_method_return (context);
 }
 
 /**
@@ -1737,7 +1745,9 @@ pk_transaction_get_packages (PkTransaction *transaction, const gchar *filter, DB
 		return;
 	}
 
-	dbus_g_method_return (context);
+	/* not set inside the test suite */
+	if (context != NULL)
+		dbus_g_method_return (context);
 }
 
 /**
@@ -1859,7 +1869,9 @@ pk_transaction_get_repo_list (PkTransaction *transaction, const gchar *filter, D
 		return;
 	}
 
-	dbus_g_method_return (context);
+	/* not set inside the test suite */
+	if (context != NULL)
+		dbus_g_method_return (context);
 }
 
 /**
@@ -1932,7 +1944,9 @@ pk_transaction_get_requires (PkTransaction *transaction, const gchar *filter, gc
 		return;
 	}
 
-	dbus_g_method_return (context);
+	/* not set inside the test suite */
+	if (context != NULL)
+		dbus_g_method_return (context);
 }
 
 /**
@@ -2456,7 +2470,9 @@ pk_transaction_install_files (PkTransaction *transaction, gboolean trusted,
 		return;
 	}
 
-	dbus_g_method_return (context);
+	/* not set inside the test suite */
+	if (context != NULL)
+		dbus_g_method_return (context);
 	return;
 }
 
@@ -2529,7 +2545,9 @@ pk_transaction_install_packages (PkTransaction *transaction, gchar **package_ids
 		return;
 	}
 
-	dbus_g_method_return (context);
+	/* not set inside the test suite */
+	if (context != NULL)
+		dbus_g_method_return (context);
 }
 
 /**
@@ -2607,7 +2625,9 @@ pk_transaction_install_signature (PkTransaction *transaction, const gchar *sig_t
 		return;
 	}
 
-	dbus_g_method_return (context);
+	/* not set inside the test suite */
+	if (context != NULL)
+		dbus_g_method_return (context);
 }
 
 /**
@@ -2682,7 +2702,9 @@ pk_transaction_refresh_cache (PkTransaction *transaction, gboolean force, DBusGM
 		return;
 	}
 
-	dbus_g_method_return (context);
+	/* not set inside the test suite */
+	if (context != NULL)
+		dbus_g_method_return (context);
 }
 
 /**
@@ -2756,7 +2778,9 @@ pk_transaction_remove_packages (PkTransaction *transaction, gchar **package_ids,
 		return;
 	}
 
-	dbus_g_method_return (context);
+	/* not set inside the test suite */
+	if (context != NULL)
+		dbus_g_method_return (context);
 }
 
 /**
@@ -2824,7 +2848,9 @@ pk_transaction_repo_enable (PkTransaction *transaction, const gchar *repo_id, gb
 		return;
 	}
 
-	dbus_g_method_return (context);
+	/* not set inside the test suite */
+	if (context != NULL)
+		dbus_g_method_return (context);
 }
 
 /**
@@ -2894,7 +2920,9 @@ pk_transaction_repo_set_data (PkTransaction *transaction, const gchar *repo_id,
 		return;
 	}
 
-	dbus_g_method_return (context);
+	/* not set inside the test suite */
+	if (context != NULL)
+		dbus_g_method_return (context);
 }
 
 /**
@@ -2969,7 +2997,9 @@ pk_transaction_resolve (PkTransaction *transaction, const gchar *filter,
 		return;
 	}
 
-	dbus_g_method_return (context);
+	/* not set inside the test suite */
+	if (context != NULL)
+		dbus_g_method_return (context);
 }
 
 /**
@@ -3036,7 +3066,9 @@ pk_transaction_rollback (PkTransaction *transaction, const gchar *transaction_id
 		return;
 	}
 
-	dbus_g_method_return (context);
+	/* not set inside the test suite */
+	if (context != NULL)
+		dbus_g_method_return (context);
 }
 
 /**
@@ -3101,7 +3133,9 @@ pk_transaction_search_details (PkTransaction *transaction, const gchar *filter,
 		return;
 	}
 
-	dbus_g_method_return (context);
+	/* not set inside the test suite */
+	if (context != NULL)
+		dbus_g_method_return (context);
 }
 
 /**
@@ -3166,7 +3200,9 @@ pk_transaction_search_file (PkTransaction *transaction, const gchar *filter,
 		return;
 	}
 
-	dbus_g_method_return (context);
+	/* not set inside the test suite */
+	if (context != NULL)
+		dbus_g_method_return (context);
 }
 
 /**
@@ -3231,7 +3267,9 @@ pk_transaction_search_group (PkTransaction *transaction, const gchar *filter,
 		return;
 	}
 
-	dbus_g_method_return (context);
+	/* not set inside the test suite */
+	if (context != NULL)
+		dbus_g_method_return (context);
 }
 
 /**
@@ -3413,7 +3451,9 @@ pk_transaction_update_packages (PkTransaction *transaction, gchar **package_ids,
 		return;
 	}
 
-	dbus_g_method_return (context);
+	/* not set inside the test suite */
+	if (context != NULL)
+		dbus_g_method_return (context);
 }
 
 /**
@@ -3476,7 +3516,9 @@ pk_transaction_update_system (PkTransaction *transaction, DBusGMethodInvocation
 		return;
 	}
 
-	dbus_g_method_return (context);
+	/* not set inside the test suite */
+	if (context != NULL)
+		dbus_g_method_return (context);
 }
 
 /**
@@ -3551,7 +3593,9 @@ pk_transaction_what_provides (PkTransaction *transaction, const gchar *filter, c
 		return;
 	}
 
-	dbus_g_method_return (context);
+	/* not set inside the test suite */
+	if (context != NULL)
+		dbus_g_method_return (context);
 }
 
 /**
commit 08fea39e23296bfd5fc7d6262719ef9e356e4dc7
Author: Richard Hughes <richard at hughsie.com>
Date:   Thu Sep 25 14:16:30 2008 +0100

    trivial: emulate the PkEngine closer in the self check by keeping an instance of PkCache around

diff --git a/src/pk-transaction-list.c b/src/pk-transaction-list.c
index 23bbcf0..8fa7afa 100644
--- a/src/pk-transaction-list.c
+++ b/src/pk-transaction-list.c
@@ -526,6 +526,7 @@ pk_transaction_list_new (void)
 #ifdef EGG_TEST
 #include "egg-test.h"
 #include "pk-backend-internal.h"
+#include "pk-cache.h"
 
 /**
  * pk_transaction_list_test_finished_cb:
@@ -570,6 +571,7 @@ void
 pk_transaction_list_test (EggTest *test)
 {
 	PkTransactionList *tlist;
+	PkCache *cache;
 	gboolean ret;
 	gchar *tid;
 	guint size;
@@ -582,6 +584,9 @@ pk_transaction_list_test (EggTest *test)
 	if (!egg_test_start (test, "PkTransactionList"))
 		return;
 
+	/* we get a cache object to reproduce the engine having it ref'd */
+	cache = pk_cache_new ();
+
 	/************************************************************/
 	egg_test_title (test, "get a transaction list object");
 	tlist = pk_transaction_list_new ();
@@ -1007,6 +1012,7 @@ pk_transaction_list_test (EggTest *test)
 
 	g_object_unref (tlist);
 	g_object_unref (backend);
+	g_object_unref (cache);
 
 	egg_test_end (test);
 }
commit 3a8dd8c60bb1af23b7c435fd23bcd504ec89e312
Author: Richard Hughes <richard at hughsie.com>
Date:   Thu Sep 25 12:45:11 2008 +0100

    trivial: add some new CPPFLAGS to warn on using deprecated functions

diff --git a/configure.ac b/configure.ac
index 8214429..8c4baef 100644
--- a/configure.ac
+++ b/configure.ac
@@ -58,6 +58,9 @@ if test "$GCC" = "yes"; then
 	CPPFLAGS="$CPPFLAGS -Wall -Wreturn-type"
 #	CPPFLAGS="$CPPFLAGS -Wformat-security"
 	CPPFLAGS="$CPPFLAGS -Werror"
+	CPPFLAGS="$CPPFLAGS -DG_DISABLE_SINGLE_INCLUDES -DGTK_DISABLE_SINGLE_INCLUDES"
+	CPPFLAGS="$CPPFLAGS -DG_DISABLE_DEPRECATED -DGTK_DISABLE_DEPRECATED -DGDK_DISABLE_DEPRECATED"
+	CPPFLAGS="$CPPFLAGS -DGDK_MULTIHEAD_SAFE -DGTK_MULTIHEAD_SAFE"
 fi
 
 dnl ---------------------------------------------------------------------------
commit 8a5fc63c03c56b1f8078adee1a2d045ef0096d44
Author: Richard Hughes <richard at hughsie.com>
Date:   Thu Sep 25 12:44:36 2008 +0100

    trivial: don't use depricated functions

diff --git a/backends/razor/pk-backend-razor.c b/backends/razor/pk-backend-razor.c
index 9064b84..ac2d3ca 100644
--- a/backends/razor/pk-backend-razor.c
+++ b/backends/razor/pk-backend-razor.c
@@ -306,7 +306,7 @@ pk_str_case_contains (const gchar *haystack, const gchar *needle)
 
 	/* search case insensitive */
 	for (i=0; i<haystack_length - needle_length; i++) {
-		ret = g_strncasecmp (haystack+i, needle, needle_length);
+		ret = g_ascii_strncasecmp (haystack+i, needle, needle_length);
 		if (ret == 0) {
 			return TRUE;
 		}
commit 3d8266fa3e97ba7e31e56e0ddb6830d495765d4e
Merge: eee30ab... 3e6f5f9...
Author: Sebastian Heinlein <devel at glatzor.de>
Date:   Thu Sep 25 13:36:59 2008 +0200

    Merge branch 'master' of git+ssh://glatzor@git.packagekit.org/srv/git/PackageKit

commit eee30ab15aa270f90569dc498293a3241e8514bb
Merge: 79be68a... 1d322a2...
Author: Sebastian Heinlein <devel at glatzor.de>
Date:   Wed Sep 24 22:12:56 2008 +0200

    Merge branch 'master' of git+ssh://glatzor@git.packagekit.org/srv/git/PackageKit

commit 79be68ad501bb385ea199767330abdeabc8a2eef
Author: Sebastian Heinlein <devel at glatzor.de>
Date:   Wed Sep 24 22:08:32 2008 +0200

    APT: Enhance the test script to a full package client.

diff --git a/backends/apt/test.py b/backends/apt/test.py
index 19fa28c..00b4fd8 100755
--- a/backends/apt/test.py
+++ b/backends/apt/test.py
@@ -1,107 +1,155 @@
-#!/usr/bin/python
-# Licensed under the GNU General Public License Version 2
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-
-# Copyright (C) 2007
-#    Tim Lauridsen <timlau at fedoraproject.org>
-
-import sys
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+"""
+Provides unit test of the apt backend of PackageKit
+
+Copyright (C) 2008 Sebastian Heinlein <glatzor at ubuntu.com>
+
+Licensed under the GNU General Public License Version 2
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+Licensed under the GNU General Public License Version 2
+"""
+
+__author__  = "Sebastian Heinlein <devel at glatzor.de>"
+
+import os
+import shutil
+import subprocess
+import time
+import unittest
+
+import apt
 import dbus
+import gobject
+
+import apt
+import apt_pkg
+import aptDBUSBackend
 from packagekit.enums import *
+import packagekit.client
+
+PKG_ID = 'yum;3.2.12-1.2;i386;Debian'
+
+apt_pkg.InitConfig()
+root = os.path.join(os.getcwd(), "testroot")
+config = apt_pkg.Config
+config.Set("Dir", root)
+config.Set("Dir::State::status",
+           os.path.join(root, "/var/lib/dpkg/status"))
+
+class AptBackendTestCase(unittest.TestCase):
+
+    def setUp(self):
+        """
+        Setup the package client which tiggers the tests and an apt cache to
+        compare the results
+        """
+        self.running = True
+        self.pk = packagekit.client.PackageKitClient()
+        self.cache = apt.Cache()
+        self.cache.open(None)
+
+    def tearDown(self):
+        """
+        Completely remove the client interface and the cache
+        """
+        del(self.pk)
+        del(self.cache)
+
+    def _setUpChroot(self):
+        if os.path.exists("testroot/"):
+            shutil.rmtree("testroot/")
+
+    def testGetUpdates(self):
+        """
+        Perfrom a call of GetUpdates and compare the results to the ones from
+        an apt cache implementation
+
+        FIXME: Should smart be used here instead of apt?
+        """
+        # Get updates from packagekit
+        pkgs = self.pk.GetUpdates()
+        # get updates from apt 
+        self.cache.upgrade()
+        blocked = map(lambda p: p.name,
+                      filter(lambda p: p.isUpgradable and not p.markedUpgrade,
+                             self.cache))
+        marked = map(lambda p: p.name, self.cache.getChanges())
+        for p in pkgs:
+            name = p.id.split(";")[0]
+            if p.status == INFO_BLOCKED:
+                if name in blocked:
+                    blocked.remove(name)
+                else:
+                    self.fail("PackageKit reported a blocked update in "
+                              "contrast to apt")
+            else:
+                if name in marked:
+                    marked.remove(name)
+                else:
+                    self.fail("PackageKit returned an update in "
+                              "contrast to apt")
+        self.assertTrue(marked == blocked == [], 
+                        "PackageKit didn't return all updates:"
+                        "blocked: %s, available: %s" % (blocked, marked)))
+ 
+    def testResolve(self):
+        """
+        Check if PackageKit can resolve the package name xterm to a correct
+        package id
+        """
+        pkgs = self.pk.Resolve("none", "xterm")
+        self.failUnless(len(pkgs) == 1 and pkgs[0].id.startswith("xterm;"),
+                        "PackageKit returned wrong package(s) for xterm:"
+                        "%s" % pkgs)
+
+    def testInstallPackages(self):
+        """
+        Check installation of a package
+        """
+        if self.cache["yum"].isInstalled:
+            self.pk.RemovePackages([PKG_ID], self._callback)
+        self.pk.InstallPackages([PKG_ID], self._callback)
+        self.cache.open()
+        self.assertTrue(self.cache["yum"].isInstalled,
+                        "yum was not installed")
+
+    def testRemovePackages(self):
+        """
+        Check removal of a package
+        """
+        if not self.cache["yum"].isInstalled:
+            self.pk.InstallPackages([PKG_ID], self._callback)
+        self.pk.RemovePackages([PKG_ID], self._callback)
+        self.cache.open()
+        self.assertFalse(self.cache["yum"].isInstalled,
+                         "yum is still installed")
+
+    def _callback(self, status, percentage, subpercentage, elapsed,
+                  remaining, allow_cancel):
+        """
+        Callback for packagekit methods which take a long time. 
+        This method isn't currently of any use
+        """
+        return True
+
+
+def main():
+    unittest.main()
 
-PACKAGEKIT_DBUS_SERVICE = 'org.freedesktop.PackageKitAptBackend'
-PACKAGEKIT_DBUS_INTERFACE = 'org.freedesktop.PackageKitBackend'
-PACKAGEKIT_DBUS_PATH = '/org/freedesktop/PackageKitBackend'
-PKG_ID = 'xterm;232-1;i386;Debian'
-
-try:
-    bus = dbus.SystemBus()
-except dbus.DBusException, e:
-    print  "Unable to connect to dbus"
-    print "%s" %(e,)
-    sys.exit(1)
-
-try:
-    proxy = bus.get_object(PACKAGEKIT_DBUS_SERVICE, PACKAGEKIT_DBUS_PATH)
-    iface = dbus.Interface(proxy, PACKAGEKIT_DBUS_INTERFACE)
-    cmd = sys.argv[1]
-    if cmd == 'init' or cmd == 'all':
-        print "Testing Init()"
-        iface.Init()
-    if cmd == 'cancel':
-        print "Canceling"
-        iface.Cancel()
-    if cmd == 'get-updates' or cmd == 'all':
-        print "Testing GetUpdate()"
-        iface.GetUpdates()
-    if cmd == 'search-name' or cmd == 'all':
-        print "Testing SearchName(FILTER_NONE,'apt')"
-        iface.SearchName(FILTER_NONE,'apt')
-    if cmd == 'search-details' or cmd == 'all':
-        print "SearchDetails(FILTER_NONE,'dbus')"
-        iface.SearchDetails(FILTER_NONE,'dbus')
-    if cmd == 'search-group' or cmd == 'all':
-        print "Testing SearchGroup(FILTER_NONE,GROUP_GAMES)"
-        iface.SearchGroup(FILTER_NONE,GROUP_GAMES)
-    if cmd == 'search-file' or cmd == 'all':
-        print "Testing SearchFile(FILTER_NONE,'/usr/bin/yum')"
-        iface.SearchFile(FILTER_NONE,'/usr/bin/yum')
-    if cmd == 'get-requires' or cmd == 'all':
-        print "Testing GetRequires(PKG_ID,False)"
-        iface.GetRequires(PKG_ID,False)
-    if cmd == 'get-depends' or cmd == 'all':
-        print "Testing GetDepends(PKG_ID,False)"
-        iface.GetDepends(PKG_ID,False)
-    if cmd == 'refresh-cache' or cmd == 'all':
-        print "Testing RefreshCache()"
-        iface.RefreshCache()
-    if cmd == 'resolve' or cmd == 'all':
-        print "Testing Resolve(FILTER_NONE,'yum')"
-        iface.Resolve(FILTER_NONE,'yum')
-    if cmd == 'get-details' or cmd == 'all':
-        print "Testing GetDetails(PKG_ID)"
-        iface.GetDetails(PKG_ID)
-    if cmd == 'get-files' or cmd == 'all':
-        print "Testing GetFiles(PKG_ID)"
-        iface.GetFiles(PKG_ID)
-    if cmd == 'get-packages' or cmd == 'all':
-        print "Testing GetPackages(FILTER_INSTALLED,'no')"
-        iface.GetPackages(FILTER_INSTALLED,'no')
-    if cmd == 'get-repolist' or cmd == 'all':
-        print "Testing GetRepoList()"
-        iface.GetRepoList()
-    if cmd == 'get-whatprovides-mimetype' or cmd == 'all':
-        print "Testing WhatProvides mime type perl"
-        iface.WhatProvides("none", PROVIDES_MIMETYPE, "text/x-perl")
-    if cmd == 'get-whatprovides-codec' or cmd == 'all':
-        print "Testing WhatProvides codec divx"
-        iface.WhatProvides("none", PROVIDES_CODEC, 
-                           "gstreamer.net|0.10|totem|DivX MPEG-4 Version 5 "
-                           "decoder|decoder-video/x-divx, divxversion=(int)5 "
-                           "(DivX MPEG-4 Version 5 decoder)")
-    if cmd == 'get-updatedetail' or cmd == 'all':
-        print "Testing GetUpdateDetail(PKG_ID)"
-        iface.GetUpdateDetail(PKG_ID)
-    #print "Testing "
-    #iface.
-    if cmd == 'exit' or cmd == 'all':
-        print "Testing Exit()"
-        iface.Exit()
-    
-except dbus.DBusException, e:
-    print "Unable to send message on dbus"
-    print "%s" %(e,)
-    sys.exit(1)
+if __name__ == '__main__':
+    main()
+# vim: ts=4 et sts=4
commit 567bbfa09acef37a96f946781dbb16c79d8516c8
Merge: d766760... 16063ca...
Author: Sebastian Heinlein <devel at glatzor.de>
Date:   Mon Sep 22 16:55:41 2008 +0200

    Merge branch 'master' of git+ssh://glatzor@git.packagekit.org/srv/git/PackageKit

commit d76676060120391a714f58920740f55373d899b9
Author: Sebastian Heinlein <devel at glatzor.de>
Date:   Mon Sep 22 16:52:21 2008 +0200

    APT: Check if the in memory cache is insync with the file cache in
    _check_init()

diff --git a/backends/apt/aptDBUSBackend.py b/backends/apt/aptDBUSBackend.py
index a7a72bd..66e6b85 100755
--- a/backends/apt/aptDBUSBackend.py
+++ b/backends/apt/aptDBUSBackend.py
@@ -29,6 +29,7 @@ import re
 import signal
 import shutil
 import socket
+import stat
 import string
 import sys
 import time
@@ -459,6 +460,7 @@ class PackageKitAptBackend(PackageKitBaseBackend):
         self._canceled = threading.Event()
         self._canceled.clear()
         self._lock = threading.Lock()
+        self._last_cache_refresh = None
         PackageKitBaseBackend.__init__(self, bus_name, dbus_path)
 
     # Methods ( client -> engine -> backend )
@@ -1595,6 +1597,7 @@ class PackageKitAptBackend(PackageKitBaseBackend):
             self.Finished(EXIT_FAILED)
             self.Exit()
             return
+        self._last_cache_refresh = time.time()
 
     def _commit_changes(self, fetch_range=(5,50), install_range=(50,90)):
         """
@@ -1633,9 +1636,23 @@ class PackageKitAptBackend(PackageKitBaseBackend):
         Check if the backend was initialized well and try to recover from
         a broken setup
         '''
-        pklog.debug("Check apt cache and xapian database")
+        pklog.debug("Checking apt cache and xapian database")
+        pkg_cache = os.path.join(apt_pkg.Config["Dir"],
+                                 apt_pkg.Config["Dir::Cache"],
+                                 apt_pkg.Config["Dir::Cache::pkgcache"])
+        src_cache = os.path.join(apt_pkg.Config["Dir"],
+                                 apt_pkg.Config["Dir::Cache"],
+                                 apt_pkg.Config["Dir::Cache::srcpkgcache"])
+        # Check if the cache instance is of the coorect class type, contains
+        # any broken packages and if the dpkg status or apt cache files have 
+        # been changed since the last refresh
         if not isinstance(self._cache, apt.cache.Cache) or \
-           self._cache._depcache.BrokenCount > 0:
+           (self._cache._depcache.BrokenCount > 0) or \
+           (os.stat(apt_pkg.Config["Dir::State::status"])[stat.ST_MTIME] > \
+            self._last_cache_refresh) or \
+           (os.stat(pkg_cache)[stat.ST_MTIME] > self._last_cache_refresh) or \
+           (os.stat(src_cache)[stat.ST_MTIME] > self._last_cache_refresh):
+            pklog.debug("Reloading the cache is required")
             self._open_cache(prange, progress)
         else:
             self._cache.clear()
commit 95da71df60c4e6c600a7b71ca3b6e4595e6cc69f
Author: Sebastian Heinlein <devel at glatzor.de>
Date:   Sun Sep 21 12:31:16 2008 +0200

    APT: add a --root option to the backend which allows to use an
    alternative system root for package manipulation tasks

diff --git a/backends/apt/aptDBUSBackend.py b/backends/apt/aptDBUSBackend.py
index 724ff85..a7a72bd 100755
--- a/backends/apt/aptDBUSBackend.py
+++ b/backends/apt/aptDBUSBackend.py
@@ -53,6 +53,8 @@ warnings.filterwarnings(action='ignore', category=FutureWarning)
 
 PACKAGEKIT_DBUS_SERVICE = 'org.freedesktop.PackageKitAptBackend'
 
+apt_pkg.InitConfig()
+
 # Xapian database is optionally used to speed up package description search
 XAPIAN_DB_PATH = os.environ.get("AXI_DB_PATH", "/var/lib/apt-xapian-index")
 XAPIAN_DB = XAPIAN_DB_PATH + "/index"
@@ -84,6 +86,7 @@ except ImportError:
 else:
     META_RELEASE_SUPPORT = True
 
+
 # Set a timeout for the changelog download
 socket.setdefaulttimeout(2)
 
@@ -456,7 +459,6 @@ class PackageKitAptBackend(PackageKitBaseBackend):
         self._canceled = threading.Event()
         self._canceled.clear()
         self._lock = threading.Lock()
-        apt_pkg.InitConfig()
         PackageKitBaseBackend.__init__(self, bus_name, dbus_path)
 
     # Methods ( client -> engine -> backend )
@@ -2075,6 +2077,10 @@ def main():
                       action="store_true", dest="takeover",
                       help="Exit the currently running backend "
                            "(Only needed by developers)")
+    parser.add_option("-r", "--root",
+                      action="store", type="string", dest="root",
+                      help="Use the given directory as the system root "
+                           "(Only needed by developers)")
     parser.add_option("-p", "--profile",
                       action="store", type="string", dest="profile",
                       help="Store profiling stats in the given file "
@@ -2089,6 +2095,12 @@ def main():
         pklog.setLevel(logging.DEBUG)
         sys.excepthook = debug_exception
 
+    if options.root:
+        config = apt_pkg.Config
+        config.Set("Dir", options.root)
+        config.Set("Dir::State::status",
+                   os.path.join(options.root, "/var/lib/dpkg/status"))
+
     if options.takeover:
         takeover()
 
commit fa39a7757c122d7d826aa2afb3a766e332644e80
Merge: 790883b... 6cf2155...
Author: Sebastian Heinlein <devel at glatzor.de>
Date:   Sat Sep 20 09:32:38 2008 +0200

    Merge branch 'master' of git+ssh://glatzor@git.packagekit.org/srv/git/PackageKit

commit 790883bd7839f3eea09cbf5dc3ad5203caadd2f3
Merge: 77dcbc8... 5977bf8...
Author: Sebastian Heinlein <devel at glatzor.de>
Date:   Fri Sep 19 15:27:21 2008 +0200

    Merge branch 'master' of git+ssh://glatzor@git.packagekit.org/srv/git/PackageKit

commit 77dcbc856b2ec899f106d6ef8d41bf61415b9902
Merge: f27042c... 71833a1...
Author: Sebastian Heinlein <devel at glatzor.de>
Date:   Thu Sep 18 00:01:29 2008 +0200

    Merge branch 'master' of git+ssh://glatzor@git.packagekit.org/srv/git/PackageKit

commit f27042cbdd54e8cefd33f64dba1e35a6fcad1eba
Author: Sebastian Heinlein <devel at glatzor.de>
Date:   Wed Sep 17 08:12:32 2008 +0200

    APT: add a decortator which cleans up the system cache lock after
    calling a method which locks the cache

diff --git a/backends/apt/aptDBUSBackend.py b/backends/apt/aptDBUSBackend.py
index 2b467fc..724ff85 100755
--- a/backends/apt/aptDBUSBackend.py
+++ b/backends/apt/aptDBUSBackend.py
@@ -137,7 +137,21 @@ SECTION_GROUP_MAP = {
     "alien" : GROUP_UNKNOWN,
     "translations" : GROUP_LOCALIZATION,
     "metapackages" : GROUP_COLLECTIONS }
- 
+
+
+def unlock_cache_afterwards(func):
+    '''
+    Make sure that the package cache is unlocked after the decorated function
+    was called
+    '''
+    def wrapper(*args,**kwargs):
+        backend = args[0]
+        func(*args,**kwargs)
+        backend._unlock_cache()
+    wrapper.__name__ = func.__name__
+    return wrapper
+
+
 class InstallTimeOutPKError(Exception):
     pass
 
@@ -358,7 +372,7 @@ class PackageKitInstallProgress(apt.progress.InstallProgress):
         pklog.debug("PM status: %s" % status)
 
     def startUpdate(self):
-        # The apt system lock was set by _acquire_lock() before
+        # The apt system lock was set by _lock_cache() before
         apt_pkg.PkgSystemUnLock()
         self._backend.StatusChanged(STATUS_COMMIT)
         self.last_activity = time.time()
@@ -741,12 +755,13 @@ class PackageKitAptBackend(PackageKitBaseBackend):
 
     @threaded
     @async
+    @unlock_cache_afterwards
     def doUpdateSystem(self):
         '''
         Implement the {backend}-update-system functionality
         '''
         pklog.info("Upgrading system")
-        if not self._acquire_lock(): return
+        if not self._lock_cache(): return
         self.StatusChanged(STATUS_UPDATE)
         self.AllowCancel(False)
         self.PercentageChanged(0)
@@ -765,12 +780,13 @@ class PackageKitAptBackend(PackageKitBaseBackend):
 
     @threaded
     @async
+    @unlock_cache_afterwards
     def doRemovePackages(self, ids, deps=True, auto=False):
         '''
         Implement the {backend}-remove functionality
         '''
         pklog.info("Removing package(s): id %s" % ids)
-        if not self._acquire_lock(): return
+        if not self._lock_cache(): return
         self.StatusChanged(STATUS_REMOVE)
         self.AllowCancel(False)
         self.PercentageChanged(0)
@@ -983,12 +999,13 @@ class PackageKitAptBackend(PackageKitBaseBackend):
 
     @threaded
     @async
+    @unlock_cache_afterwards
     def doUpdatePackages(self, ids):
         '''
         Implement the {backend}-update functionality
         '''
         pklog.info("Updating package with id %s" % ids)
-        if not self._acquire_lock(): return
+        if not self._lock_cache(): return
         self.StatusChanged(STATUS_UPDATE)
         self.AllowCancel(False)
         self.PercentageChanged(0)
@@ -1096,12 +1113,13 @@ class PackageKitAptBackend(PackageKitBaseBackend):
  
     @threaded
     @async
+    @unlock_cache_afterwards
     def doInstallPackages(self, ids):
         '''
         Implement the {backend}-install functionality
         '''
         pklog.info("Installing package with id %s" % ids)
-        if not self._acquire_lock(): return
+        if not self._lock_cache(): return
         self.StatusChanged(STATUS_INSTALL)
         self.AllowCancel(False)
         self.PercentageChanged(0)
@@ -1142,13 +1160,14 @@ class PackageKitAptBackend(PackageKitBaseBackend):
 
     @threaded
     @async
+    @unlock_cache_afterwards
     def doInstallFiles(self, trusted, full_paths):
         '''
         Implement install-files for the apt backend
         Install local Debian package files
         '''
         pklog.info("Installing package files: %s" % full_paths)
-        if not self._acquire_lock(): return
+        if not self._lock_cache(): return
         self.StatusChanged(STATUS_INSTALL)
         self.AllowCancel(False)
         self.PercentageChanged(0)
@@ -1185,7 +1204,7 @@ class PackageKitAptBackend(PackageKitBaseBackend):
             return
         if not self._commit_changes((10,25), (25,50)): return False
         # Install the Debian package files
-        if not self._acquire_lock(): return
+        if not self._lock_cache(): return
         for deb in packages:
             try:
                 res = deb.install(PackageKitDpkgInstallProgress(self))
@@ -1209,12 +1228,13 @@ class PackageKitAptBackend(PackageKitBaseBackend):
 
     @threaded
     @async
+    @unlock_cache_afterwards
     def doRefreshCache(self, force):
         '''
         Implement the {backend}-refresh_cache functionality
         '''
         pklog.info("Refresh cache")
-        if not self._acquire_lock(): return
+        if not self._lock_cache(): return
         self.StatusChanged(STATUS_REFRESH_CACHE)
         self.last_action_time = time.time()
         self.AllowCancel(False);
@@ -1526,7 +1546,7 @@ class PackageKitAptBackend(PackageKitBaseBackend):
 
     # Helpers
 
-    def _acquire_lock(self):
+    def _lock_cache(self):
         """
         Emit an error message and return true if the apt system lock cannot
         be acquired.
@@ -1541,6 +1561,16 @@ class PackageKitAptBackend(PackageKitBaseBackend):
             return False
         return True
 
+    def _unlock_cache(self):
+        """
+        Unlock the system package cache
+        """
+        try:
+            apt_pkg.PkgSystemUnLock()
+        except SystemError:
+            return False
+        return True
+
     def _open_cache(self, prange=(0,100), progress=True):
         '''
         (Re)Open the APT cache


More information about the PackageKit-commit mailing list