[packagekit] packagekit: Branch 'master' - 24 commits

Richard Hughes hughsient at kemper.freedesktop.org
Tue Feb 26 10:28:19 PST 2008


 backends/apt2/HACKING                             |    5 
 backends/apt2/README                              |   23 
 backends/apt2/TODO                                |   70 ++
 backends/apt2/aptDBUSBackend.py                   |  735 +++++++++-------------
 backends/apt2/pk-backend-apt2.c                   |   59 +
 backends/zypp/pk-backend-zypp.cpp                 |   98 ++
 backends/zypp/zypp-utils.cpp                      |   86 +-
 backends/zypp/zypp-utils.h                        |   15 
 client/pk-console.c                               |    3 
 data/org.freedesktop.PackageKit.conf.in           |   12 
 data/org.freedesktop.PackageKitAptBackend.conf.in |    5 
 data/org.freedesktop.PackageKitYumBackend.conf.in |    5 
 docs/html/pk-faq.html                             |   66 -
 docs/spec/pk-introduction.xml                     |   61 +
 14 files changed, 678 insertions(+), 565 deletions(-)

New commits:
commit 67028c532c027b41913e1966d98beeca25b7fd22
Author: Robin Norwood <rnorwood at redhat.com>
Date:   Tue Feb 26 12:34:22 2008 -0500

    DBUS denies by default, no need to be explicit about it.

diff --git a/data/org.freedesktop.PackageKitAptBackend.conf.in b/data/org.freedesktop.PackageKitAptBackend.conf.in
index 7e34eee..0a485ec 100644
--- a/data/org.freedesktop.PackageKitAptBackend.conf.in
+++ b/data/org.freedesktop.PackageKitAptBackend.conf.in
@@ -12,10 +12,5 @@
     <allow send_destination="org.freedesktop.PackageKitAptBackend"/>
     <allow send_interface="org.freedesktop.PackageKitBackend"/>
   </policy>
-  <policy context="default">
-    <deny own="org.freedesktop.PackageKitAptBackend"/>
-    <deny send_destination="org.freedesktop.PackageKitAptBackend"/>
-    <deny send_interface="org.freedesktop.PackageKitBackend"/>
-  </policy>
 </busconfig>
 
diff --git a/data/org.freedesktop.PackageKitYumBackend.conf.in b/data/org.freedesktop.PackageKitYumBackend.conf.in
index b511943..e51e4ad 100644
--- a/data/org.freedesktop.PackageKitYumBackend.conf.in
+++ b/data/org.freedesktop.PackageKitYumBackend.conf.in
@@ -12,10 +12,5 @@
     <allow send_destination="org.freedesktop.PackageKitYumBackend"/>
     <allow send_interface="org.freedesktop.PackageKitBackend"/>
   </policy>
-  <policy context="default">
-    <deny own="org.freedesktop.PackageKitYumBackend"/>
-    <deny send_destination="org.freedesktop.PackageKitYumBackend"/>
-    <deny send_interface="org.freedesktop.PackageKitBackend"/>
-  </policy>
 </busconfig>
 
commit 270883846c4f2b94e36eb6d65a5bf6ef2a24066f
Merge: 5d4b1b3... da5081b...
Author: Robin Norwood <rnorwood at redhat.com>
Date:   Tue Feb 26 12:26:27 2008 -0500

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

commit 5d4b1b3a75d3e5bbbd44cc3c3d9fd03434d178ca
Author: Robin Norwood <rnorwood at redhat.com>
Date:   Tue Feb 26 12:21:23 2008 -0500

    Changes recommended by davidz for better security.  at_console is dangerous.

diff --git a/data/org.freedesktop.PackageKit.conf.in b/data/org.freedesktop.PackageKit.conf.in
index 708f2eb..633494a 100644
--- a/data/org.freedesktop.PackageKit.conf.in
+++ b/data/org.freedesktop.PackageKit.conf.in
@@ -14,18 +14,8 @@
     <allow own="org.freedesktop.PackageKit"/>
   </policy>
 
-  <!-- Allow anyone to invoke methods on the Manager and Device interfaces -->
+ <!-- Allow anyone to call into the service - we'll reject callers using PolicyKit -->
   <policy context="default">
-    <deny send_interface="org.freedesktop.PackageKit"/>
-  </policy>
-
-  <!-- This will not work if pam_console support is not enabled -->
-  <policy at_console="true">
-    <allow send_interface="org.freedesktop.PackageKit"/>
-  </policy>
-
-  <!-- You can change this to a more suitable user, or make per-group -->
-  <policy user="0">
     <allow send_interface="org.freedesktop.PackageKit"/>
   </policy>
 
commit da5081b55c3caaee9eb9afe12a7aa0e3b73c6746
Merge: 897b021... 8b3979e...
Author: Stefan Haas <shaas at suse.de>
Date:   Tue Feb 26 11:08:13 2008 +0100

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

commit 897b021d208df0da3be16f9108bb1be48fe9337f
Author: Stefan Haas <shaas at suse.de>
Date:   Tue Feb 26 11:07:41 2008 +0100

    added search group

diff --git a/backends/zypp/pk-backend-zypp.cpp b/backends/zypp/pk-backend-zypp.cpp
index e1cb8c2..8612cc7 100644
--- a/backends/zypp/pk-backend-zypp.cpp
+++ b/backends/zypp/pk-backend-zypp.cpp
@@ -33,10 +33,8 @@
 #include <zypp/ResPoolProxy.h>
 #include <zypp/ui/Selectable.h>
 #include <zypp/Patch.h>
-#include <zypp/Selection.h>
 #include <zypp/Package.h>
 #include <zypp/Pattern.h>
-#include <zypp/Language.h>
 #include <zypp/Product.h>
 #include <zypp/Repository.h>
 #include <zypp/RepoManager.h>
@@ -52,7 +50,6 @@
 #include <zypp/target/rpm/RpmException.h>
 
 #include <zypp/sat/Solvable.h>
-#include <zypp/sat/Capabilities.h>
 
 #include <map>
 #include <list>
@@ -84,6 +81,11 @@ typedef struct {
 } FindData;
 
 typedef struct {
+	gchar *pkGroup;
+	gchar *filter;
+} GroupData;
+
+typedef struct {
 	gchar *name;
 	gchar *filter;
 } ResolveData;
@@ -401,18 +403,12 @@ backend_get_description_thread (PkBackendThread *thread, gpointer data)
 	}
         
         try {
-                PkGroupEnum group = zypp_get_group (package);
+                PkGroupEnum group = get_enum_group (package);
 
                 // currently it is necessary to access the rpmDB directly to get infos like size for already installed packages
                 if (package->isSystem ()){
-                        zypp::Target_Ptr target;
 
-                        zypp::ZYpp::Ptr zypp;
-                        zypp = get_zypp ();
-
-                        target = zypp->target ();
-  
-                        zypp::target::rpm::RpmDb &rpm = target->rpmDb (); 
+                        zypp::target::rpm::RpmDb &rpm = zypp_get_rpmDb (); 
                         rpm.initDatabase();
                         zypp::target::rpm::RpmHeader::constPtr rpmHeader;
                         rpm.getData (package-> name (), package->edition (), rpmHeader);
@@ -1157,6 +1153,77 @@ backend_search_details (PkBackend *backend, const gchar *filter, const gchar *se
 	find_packages (backend, search, filter, SEARCH_TYPE_DETAILS);
 }
 
+static gboolean
+backend_search_group_thread (PkBackendThread *thread, gpointer data)
+{
+        GroupData *d = (GroupData*) data;
+        
+        PkBackend *backend;
+        backend = pk_backend_thread_get_backend (thread);
+
+	if (d->pkGroup == NULL) {
+		pk_backend_error_code (backend, PK_ERROR_ENUM_GROUP_NOT_FOUND, "Group is invalid.");
+		g_free (d->filter);
+                g_free (d->pkGroup);
+		g_free (d);
+		pk_backend_finished (backend);
+		return FALSE;
+	}
+        
+	pk_backend_set_percentage (backend, 0);
+
+        zypp::ResPool pool = zypp_build_pool(true);
+
+	pk_backend_set_percentage (backend, 30);
+
+        std::vector<zypp::PoolItem> *v = new std::vector<zypp::PoolItem> ();
+
+        zypp::target::rpm::RpmDb &rpm = zypp_get_rpmDb ();         
+        rpm.initDatabase ();                                      
+
+        fprintf(stderr,"\n__________________________%s___________________________\n",d->pkGroup);
+
+        for (zypp::ResPool::byKind_iterator it = pool.byKindBegin (zypp::ResKind::package); it != pool.byKindEnd (zypp::ResKind::package); it++) {
+                  if (g_strrstr (zypp_get_group (*it, rpm), d->pkGroup))
+                          v->push_back(*it);
+        }
+
+        rpm.closeDatabase ();                                     
+	pk_backend_set_percentage (backend, 70);
+
+        zypp_emit_packages_in_list (backend ,v);
+
+        delete (v);
+        
+	pk_backend_set_percentage (backend, 100);
+
+        g_free (d->filter);
+        g_free (d->pkGroup);
+        g_free (d);
+	pk_backend_finished (backend);
+
+        return TRUE;
+} 
+
+/**
+ * backend_search_group:
+ */
+static void
+backend_search_group (PkBackend *backend, const gchar *filter, const gchar *pkGroup)
+{
+        g_return_if_fail (backend != NULL);
+
+        GroupData *data = g_new0(GroupData, 1);
+        if (data == NULL) {
+                pk_backend_error_code(backend, PK_ERROR_ENUM_OOM, "Failed to allocate memory in backend_search_group");
+                pk_backend_finished (backend);
+        } else {
+                data->pkGroup = g_strdup(pkGroup);
+                data->filter = g_strdup(filter);
+                pk_backend_thread_create (thread, backend_search_group_thread, data);
+        }
+}
+
 /**
  * backend_search_file:
  */
@@ -1278,14 +1345,9 @@ backend_get_files_thread (PkBackendThread *thread, gpointer data) {
 
         std::string temp;
         if (package->isSystem ()){
-                zypp::Target_Ptr target;
-
-               	zypp::ZYpp::Ptr zypp;
-              	zypp = get_zypp ();
 
-               	target = zypp->target ();
                 try {
-                        zypp::target::rpm::RpmDb &rpm = target->rpmDb (); 
+                        zypp::target::rpm::RpmDb &rpm = zypp_get_rpmDb (); 
                         rpm.initDatabase();
                         zypp::target::rpm::RpmHeader::constPtr rpmHeader;
                         rpm.getData (package-> name (), package->edition (), rpmHeader);
@@ -1469,7 +1531,7 @@ extern "C" PK_BACKEND_OPTIONS (
 	NULL,					/* rollback */
 	backend_search_details,			/* search_details */
 	backend_search_file,			/* search_file */
-	NULL,					/* search_group */
+	backend_search_group,    		/* search_group */
 	backend_search_name,			/* search_name */
 	NULL,					/* update_package */
 	NULL,					/* update_system */
diff --git a/backends/zypp/zypp-utils.cpp b/backends/zypp/zypp-utils.cpp
index b810b80..702ecf5 100644
--- a/backends/zypp/zypp-utils.cpp
+++ b/backends/zypp/zypp-utils.cpp
@@ -121,73 +121,91 @@ zypp_build_local_pool ()
 
 }
 
-PkGroupEnum
-zypp_get_group (zypp::ResObject::constPtr item)
+zypp::target::rpm::RpmDb&
+zypp_get_rpmDb()
+{
+        zypp::ZYpp::Ptr zypp = get_zypp ();
+        zypp::Target_Ptr target = zypp->target ();
+
+        zypp::target::rpm::RpmDb &rpm = target->rpmDb ();
+
+        return rpm;
+}
+
+gchar*
+zypp_get_group (zypp::ResObject::constPtr item, zypp::target::rpm::RpmDb &rpm)
 {
-        PkGroupEnum pkGroup = PK_GROUP_ENUM_UNKNOWN;
         std::string group;
 
         if (item->isSystem ()) {
-                zypp::ZYpp::Ptr zypp = get_zypp ();
-                zypp::Target_Ptr target = zypp->target ();
-
-                zypp::target::rpm::RpmDb &rpm = target->rpmDb ();
-                rpm.initDatabase ();
 
                 zypp::target::rpm::RpmHeader::constPtr rpmHeader;
                 rpm.getData (item->name (), item->edition (), rpmHeader);
                 group = rpmHeader->tag_group ();
 
-                rpm.closeDatabase ();
-       
         }else{
                 zypp::Package::constPtr pkg = zypp::asKind<zypp::Package>(item);
                 group = pkg->group ();
         }
+        std::transform(group.begin(), group.end(), group.begin(), tolower);
+        return (gchar*)group.c_str ();
+}
 
+PkGroupEnum
+get_enum_group (zypp::ResObject::constPtr item)
+{
+        
+        zypp::target::rpm::RpmDb &rpm = zypp_get_rpmDb ();
+        rpm.initDatabase ();
+
+        std::string group (zypp_get_group (item, rpm));
+
+        rpm.closeDatabase ();
+
+        PkGroupEnum pkGroup = PK_GROUP_ENUM_UNKNOWN;
         // TODO Look for a faster and nice way to do this conversion
 
-        if (group.find ("Amusements") != std::string::npos) {
+        if (group.find ("amusements") != std::string::npos) {
                 pkGroup = PK_GROUP_ENUM_GAMES;
-        } else if (group.find ("Development") != std::string::npos) {
+        } else if (group.find ("development") != std::string::npos) {
                 pkGroup = PK_GROUP_ENUM_PROGRAMMING;
-        } else if (group.find ("Hardware") != std::string::npos) {
+        } else if (group.find ("hardware") != std::string::npos) {
                 pkGroup = PK_GROUP_ENUM_SYSTEM;
-        } else if (group.find ("Archiving") != std::string::npos 
-                  || group.find("Clustering") != std::string::npos
-                  || group.find("System/Monitoring") != std::string::npos
-                  || group.find("Databases") != std::string::npos
-                  || group.find("System/Management") != std::string::npos) {
+        } else if (group.find ("archiving") != std::string::npos 
+                  || group.find("clustering") != std::string::npos
+                  || group.find("system/monitoring") != std::string::npos
+                  || group.find("databases") != std::string::npos
+                  || group.find("system/management") != std::string::npos) {
                 pkGroup = PK_GROUP_ENUM_ADMIN_TOOLS;
-        } else if (group.find ("Graphics") != std::string::npos) {
+        } else if (group.find ("graphics") != std::string::npos) {
                 pkGroup = PK_GROUP_ENUM_GRAPHICS;
-        } else if (group.find ("Mulitmedia") != std::string::npos) {
+        } else if (group.find ("mulitmedia") != std::string::npos) {
                 pkGroup = PK_GROUP_ENUM_MULTIMEDIA;
-        } else if (group.find ("") != std::string::npos) {
+        } else if (group.find ("network") != std::string::npos) {
                 pkGroup = PK_GROUP_ENUM_NETWORK;
-        } else if (group.find ("Office") != std::string::npos 
-                  || group.find("Text") != std::string::npos
-                  || group.find("Editors") != std::string::npos) {
+        } else if (group.find ("office") != std::string::npos 
+                  || group.find("text") != std::string::npos
+                  || group.find("editors") != std::string::npos) {
                 pkGroup = PK_GROUP_ENUM_OFFICE;
-        } else if (group.find ("Publishing") != std::string::npos) {
+        } else if (group.find ("publishing") != std::string::npos) {
                 pkGroup = PK_GROUP_ENUM_PUBLISHING;
-        } else if (group.find ("Security") != std::string::npos) {
+        } else if (group.find ("security") != std::string::npos) {
                 pkGroup = PK_GROUP_ENUM_SECURITY;
-        } else if (group.find ("Telephony") != std::string::npos) {
+        } else if (group.find ("telephony") != std::string::npos) {
                 pkGroup = PK_GROUP_ENUM_COMMUNICATION;
-        } else if (group.find ("GNOME") != std::string::npos) {
+        } else if (group.find ("gnome") != std::string::npos) {
                 pkGroup = PK_GROUP_ENUM_DESKTOP_GNOME;
-        } else if (group.find ("KDE") != std::string::npos) {
+        } else if (group.find ("kde") != std::string::npos) {
                 pkGroup = PK_GROUP_ENUM_DESKTOP_KDE;
-        } else if (group.find ("XFCE") != std::string::npos) {
+        } else if (group.find ("xfce") != std::string::npos) {
                 pkGroup = PK_GROUP_ENUM_DESKTOP_XFCE;
-        } else if (group.find ("GUI/Other") != std::string::npos) {
+        } else if (group.find ("gui/other") != std::string::npos) {
                 pkGroup = PK_GROUP_ENUM_DESKTOP_OTHER;
-        } else if (group.find ("Localization") != std::string::npos) {
+        } else if (group.find ("localization") != std::string::npos) {
                 pkGroup = PK_GROUP_ENUM_LOCALIZATION;
-        } else if (group.find ("System") != std::string::npos) {
+        } else if (group.find ("system") != std::string::npos) {
                 pkGroup = PK_GROUP_ENUM_SYSTEM;
-        } else if (group.find ("Scientific") != std::string::npos) {
+        } else if (group.find ("scientific") != std::string::npos) {
                 pkGroup = PK_GROUP_ENUM_EDUCATION;
         }
 
diff --git a/backends/zypp/zypp-utils.h b/backends/zypp/zypp-utils.h
index 5365cca..345e576 100644
--- a/backends/zypp/zypp-utils.h
+++ b/backends/zypp/zypp-utils.h
@@ -20,7 +20,6 @@ typedef zypp::ResObject::constPtr	ZyppObject;
 typedef zypp::Package::constPtr		ZyppPackage;
 typedef zypp::Patch::constPtr		ZyppPatch;
 typedef zypp::Pattern::constPtr		ZyppPattern;
-typedef zypp::Language::constPtr	ZyppLanguage;
 //inline ZyppPackage tryCastToZyppPkg (ZyppObject obj)
 //	{ return zypp::dynamic_pointer_cast <const zypp::Package> (obj); }
 typedef std::set<zypp::PoolItem> Candidates;
@@ -41,9 +40,19 @@ zypp::ResPool zypp_build_pool (gboolean include_local);
 zypp::ResPool zypp_build_local_pool ();
 
 /**
-  * Return the PkGroupEnum of the given PoolItem.
+  * Return the rpm-Database
   */
-PkGroupEnum zypp_get_group (zypp::ResObject::constPtr item);
+zypp::target::rpm::RpmDb& zypp_get_rpmDb();
+
+/**
+  * Return the gchar of the given PoolItem.
+  */
+gchar* zypp_get_group (zypp::ResObject::constPtr item, zypp::target::rpm::RpmDb &rpm);
+
+/**
+  * Return the PkEnumGroup of the given PoolItem.
+  */
+PkGroupEnum get_enum_group (zypp::ResObject::constPtr item);
 
 /**
  * Returns a list of packages that match the specified package_name.
commit 8b3979e870c19b85df62c3baea75912168aa0255
Merge: 99ab4d8... 3365491...
Author: Richard Hughes <richard at hughsie.com>
Date:   Tue Feb 26 01:35:33 2008 +0100

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

commit 3365491597ccaaec4138640fd4944c7ead9ff2fd
Author: Sebastian Heinlein <sebi at glatzor.de>
Date:   Tue Feb 26 01:32:55 2008 +0100

    * APT-DBUS: Exit if the cache cannot be opened

diff --git a/backends/apt2/aptDBUSBackend.py b/backends/apt2/aptDBUSBackend.py
index 737cc99..5f8898a 100755
--- a/backends/apt2/aptDBUSBackend.py
+++ b/backends/apt2/aptDBUSBackend.py
@@ -408,12 +408,14 @@ class PackageKitAptBackend(PackageKitBaseBackend):
         except:
             self.ErrorCode(ERROR_NO_CACHE, "Package cache could not be opened")
             self.Finished(EXIT_FAILED)
+            self.Exit()
             return
         self.doUnlock()
         if self._cache._depcache.BrokenCount > 0:
             self.ErrorCode(ERROR_INTERNAL_ERROR,
                            "Not all dependecies can be satisfied")
             self.Finished(EXIT_FAILED)
+            self.Exit()
             return
 
     def get_id_from_package(self, pkg, installed=False):
commit 99ab4d875d48aab25b4fd23b69a98a06b04a1e86
Author: Richard Hughes <richard at hughsie.com>
Date:   Tue Feb 26 01:05:32 2008 +0100

    two trivial fixes to pkcon

diff --git a/client/pk-console.c b/client/pk-console.c
index 29ed65a..9fe41a4 100644
--- a/client/pk-console.c
+++ b/client/pk-console.c
@@ -470,6 +470,7 @@ pk_console_remove_only (PkClient *client, const gchar *package_id, gboolean forc
 
 	pk_debug ("remove %s", package_id);
 	pk_client_reset (client);
+	pk_client_set_synchronous (client, TRUE);
 	ret = pk_client_remove_package (client, package_id, force);
 	/* ick, we failed so pretend we didn't do the action */
 	if (ret == FALSE) {
@@ -1108,6 +1109,8 @@ main (int argc, char *argv[])
 	client_task = pk_client_new ();
 	pk_client_set_use_buffer (client_task, TRUE);
 	pk_client_set_synchronous (client_task, TRUE);
+	g_signal_connect (client_task, "finished",
+			  G_CALLBACK (pk_console_finished_cb), NULL);
 
 	role_list = pk_client_get_actions (client);
 	pk_debug ("actions=%s", pk_enum_list_to_string (role_list));
commit a183631ae3c050585aa1c6c1debcef2d3d7d7a27
Author: Sebastian Heinlein <sebi at glatzor.de>
Date:   Tue Feb 26 00:44:21 2008 +0100

    Revert "* APT-DBUS: clean up DBus configuration"
    
    This reverts commit 7ae907986354005b73ffd66662e8a8d9becced56.

diff --git a/data/org.freedesktop.PackageKit.conf.in b/data/org.freedesktop.PackageKit.conf.in
index 7ce58be..708f2eb 100644
--- a/data/org.freedesktop.PackageKit.conf.in
+++ b/data/org.freedesktop.PackageKit.conf.in
@@ -14,22 +14,19 @@
     <allow own="org.freedesktop.PackageKit"/>
   </policy>
 
-  <!-- Forbid anyone to invoke methods on the Manager and Device interfaces -->
+  <!-- Allow anyone to invoke methods on the Manager and Device interfaces -->
   <policy context="default">
     <deny send_interface="org.freedesktop.PackageKit"/>
-    <deny send_destination="org.freedesktop.PackageKit"/>
   </policy>
 
   <!-- This will not work if pam_console support is not enabled -->
   <policy at_console="true">
     <allow send_interface="org.freedesktop.PackageKit"/>
-    <allow send_destination="org.freedesktop.PackageKit"/>
   </policy>
 
   <!-- You can change this to a more suitable user, or make per-group -->
-  <policy group="packagekit">
+  <policy user="0">
     <allow send_interface="org.freedesktop.PackageKit"/>
-    <allow send_destination="org.freedesktop.PackageKit"/>
   </policy>
 
 </busconfig>
commit 1a43950da4f719b8ee1afb8c986aa43a7c0ddbe3
Merge: 565990b... b5c0b78...
Author: Sebastian Heinlein <sebi at glatzor.de>
Date:   Tue Feb 26 00:42:39 2008 +0100

    Merge branch 'train'

commit b5c0b786c325f48120b2647e6f8659ae845e9de1
Author: Sebastian Heinlein <sebi at glatzor.de>
Date:   Tue Feb 26 00:35:06 2008 +0100

    * APT-DBUS: add actual system manipulation methods
     - add methods to the backend: Refresh, InstallPackage, RemovePackage,
       UpdateSystem, _find_package_by_id
     - try to handle headless installations in PackageKitInstallProgress
     - update the FAQ accordingly

diff --git a/backends/apt2/aptDBUSBackend.py b/backends/apt2/aptDBUSBackend.py
index 99f5bf6..737cc99 100755
--- a/backends/apt2/aptDBUSBackend.py
+++ b/backends/apt2/aptDBUSBackend.py
@@ -20,7 +20,9 @@ __state__   = "experimental"
 
 import logging
 import os
+import pty
 import re
+import time
 import warnings
 
 import apt
@@ -49,6 +51,9 @@ DEFAULT_SEARCH_FLAGS = (xapian.QueryParser.FLAG_BOOLEAN |
                         xapian.QueryParser.FLAG_BOOLEAN_ANY_CASE)
 
 class PackageKitOpProgress(apt.progress.OpProgress):
+    '''
+    Handle the cache opening process
+    '''
     def __init__(self, backend):
         self._backend = backend
         apt.progress.OpProgress.__init__(self)
@@ -61,41 +66,95 @@ class PackageKitOpProgress(apt.progress.OpProgress):
         self._backend.PercentageChanged(100)
 
 class PackageKitFetchProgress(apt.progress.FetchProgress):
+    '''
+    Handle the package download process
+    '''
     def __init__(self, backend):
         self._backend = backend
         apt.progress.FetchProgress.__init__(self)
     # FetchProgress callbacks
     def pulse(self):
+        self._backend.StatusChanged(STATUS_DOWNLOAD)
+        percent = ((self.currentBytes + self.currentItems)*100.0)/float(self.totalBytes+self.totalItems)
+        self._backend.PercentageChanged(int(percent))
         apt.progress.FetchProgress.pulse(self)
-        self._backend.percentage(self.percent)
         return True
 
     def stop(self):
-        self._backend.percentage(100)
+        self._backend.PercentageChanged(100)
 
     def mediaChange(self, medium, drive):
         #FIXME: use the Message method to notify the user
         self._backend.error(ERROR_INTERNAL_ERROR,
-                "Medium change needed")
+                            "Medium change needed")
 
 class PackageKitInstallProgress(apt.progress.InstallProgress):
+    '''
+    Handle the installation and removal process. Bits taken from
+    DistUpgradeViewNonInteractive.
+    '''
     def __init__(self, backend):
         apt.progress.InstallProgress.__init__(self)
+        self._backend = backend
+        self.timeout = 900
+
+    def statusChange(self, pkg, percent, status):
+        self._backend.PercentageChanged(int(percent))
+        #FIXME: should represent the status better (install, remove, preparing)
+        self._backend.StatusChanged(STATUS_INSTALL)
+        if (self.last_activity + self.timeout) < time.time():
+            logging.critical("Sending Crtl+C. Inactivity of %s "
+                             "seconds (%s)" % (self.timeout, self.status))
+            os.write(self.master_fd,chr(3))
+
+    def startUpdate(self):
+        self.last_activity = time.time()
+
+    def updateInterface(self):
+        apt.progress.InstallProgress.updateInterface(self)
+        #FIXME: what is the best timeout?
+
+    def fork(self):
+        logging.debug("doing a pty.fork()")
+        (self.pid, self.master_fd) = pty.fork()
+        if self.pid != 0:
+            logging.debug("pid is: %s" % self.pid)
+        return self.pid
+
+    def conffile(self, current, new):
+        logging.warning("Config file prompt: '%s'" % current)
+        # looks like we have a race here *sometimes*
+        time.sleep(5)
+        try:
+            # don't overwrite
+            os.write(self.master_fd,"n\n")
+        except Exception, e:
+            logging.error(e)
+
 
 class PackageKitAptBackend(PackageKitBaseBackend):
+    '''
+    PackageKit backend for apt
+    '''
     def __init__(self, bus_name, dbus_path):
         log.info("Initializing backend")
         PackageKitBaseBackend.__init__(self, bus_name, dbus_path)
         self._cache = None
         self._xapian = None
+        # Avoid questions from the maintainer scripts as far as possible
+        os.environ["DEBIAN_FRONTEND"] = "noninteractive"
+        os.environ["APT_LISTCHANGES_FRONTEND"] = "none"
+
 
     # Methods ( client -> engine -> backend )
 
     @dbus.service.method(PACKAGEKIT_DBUS_INTERFACE,
                          in_signature='', out_signature='')
     def Init(self):
+        self.last_action_time = time.time()
         log.info("Initializing cache")
-        self._cache = apt.Cache(PackageKitOpProgress(self))
+        self.StatusChanged(STATUS_SETUP)
+        self._open_cache()
         self._xapian = xapian.Database(XAPIANDB)
 
     @dbus.service.method(PACKAGEKIT_DBUS_INTERFACE,
@@ -110,13 +169,14 @@ class PackageKitAptBackend(PackageKitBaseBackend):
         Implement the apt2-search-name functionality
         '''
         log.info("Searching for package name: %s" % search)
+        self.last_action_time = time.time()
         self.AllowCancel(True)
         self.NoPercentageUpdates()
 
         self.StatusChanged(STATUS_QUERY)
 
         for pkg in self._cache:
-            if search in pkg.name and self._package_is_visible(pkg, filters):
+            if search in pkg.name and self._is_package_visible(pkg, filters):
                 self._emit_package(pkg)
         self.Finished(EXIT_SUCCESS)
 
@@ -128,6 +188,7 @@ class PackageKitAptBackend(PackageKitBaseBackend):
         Implement the apt2-search-details functionality
         '''
         log.info("Searching for package name: %s" % search)
+        self.last_action_time = time.time()
         self.AllowCancel(True)
         self.NoPercentageUpdates()
         self.StatusChanged(STATUS_QUERY)
@@ -143,7 +204,7 @@ class PackageKitAptBackend(PackageKitBaseBackend):
             name = m[xapian.MSET_DOCUMENT].get_data()
             if self._cache.has_key(name):
                 pkg = self._cache[name]
-                if self._package_is_visible(pkg) == True:
+                if self._is_package_visible(pkg, filters) == True:
                     self._emit_package(pkg)
 
         self.Finished(EXIT_SUCCESS)
@@ -155,6 +216,7 @@ class PackageKitAptBackend(PackageKitBaseBackend):
         '''
         Implement the {backend}-get-update functionality
         '''
+        self.last_action_time = time.time()
         self.AllowCancel(True)
         self.NoPercentageUpdates()
         self.StatusChanged(STATUS_INFO)
@@ -169,6 +231,7 @@ class PackageKitAptBackend(PackageKitBaseBackend):
         '''
         Implement the {backend}-get-description functionality
         '''
+        self.last_action_time = time.time()
         self.AllowCancel(True)
         self.NoPercentageUpdates()
         self.StatusChanged(STATUS_INFO)
@@ -206,27 +269,156 @@ class PackageKitAptBackend(PackageKitBaseBackend):
     @dbus.service.method(PACKAGEKIT_DBUS_INTERFACE,
                          in_signature='', out_signature='')
     def Unlock(self):
+        self.last_action_time = time.time()
         self.doUnlock()
 
     def doUnlock(self):
         if self.isLocked():
-            PackageKitBaseBackend.doUnlock(self)
-
+            self._locked = False
 
     @dbus.service.method(PACKAGEKIT_DBUS_INTERFACE,
                          in_signature='', out_signature='')
     def Lock(self):
+        self.last_action_time = time.time()
         self.doLock()
 
     def doLock(self):
-        pass
+        self._locked = True
+
+    @dbus.service.method(PACKAGEKIT_DBUS_INTERFACE,
+                         in_signature='', out_signature='')
+    def UpdateSystem(self):
+        '''
+        Implement the {backend}-update-system functionality
+        '''
+        #FIXME: Better exception and error handling
+        #FIXME: Distupgrade or Upgrade?
+        #FIXME: Handle progress in a more sane way
+        log.info("Upgrading system")
+        self.last_action_time = time.time()
+        self.StatusChanged(STATUS_UPDATE)
+        self.AllowCancel(False)
+        self.PercentageChanged(0)
+        try:
+            self._cache.upgrade(distUpgrade=True)
+            self._cache.commit(PackageKitFetchProgress(self),
+                               PackageKitInstallProgress(self))
+        except:
+            self.ErrorCode(ERROR_INTERNAL_ERROR, "Upgrade failed")
+            self.Finished(EXIT_FAILED)
+            self._open_cache()
+            return
+        self._open_cache()
+        self.Finished(EXIT_SUCCESS)
+
+    @dbus.service.method(PACKAGEKIT_DBUS_INTERFACE,
+                         in_signature='sb', out_signature='')
+    def RemovePackage(self, id, deps=True):
+        '''
+        Implement the {backend}-remove functionality
+        '''
+        #FIXME: Better exception and error handling
+        #FIXME: Handle progress in a more sane way
+        log.info("Removing package with id %s" % id)
+        self.last_action_time = time.time()
+        self.StatusChanged(STATUS_REMOVE)
+        self.AllowCancel(False)
+        self.PercentageChanged(0)
+        pkg = self._find_package_by_id(id)
+        name = pkg.name[:]
+        try:
+            pkg.markDelete()
+            self._cache.commit(PackageKitFetchProgress(self),
+                               PackageKitInstallProgress(self))
+        except:
+            self.ErrorCode(ERROR_INTERNAL_ERROR, "Removal failed")
+            self.Finished(EXIT_FAILED)
+            self._open_cache()
+            return
+        # FIXME: handle error
+        self._open_cache()
+        if not self._cache.has_key(name) or not self._cache[name].isInstalled:
+            self.Finished(EXIT_SUCCESS)
+        else:
+            self.ErrorCode(ERROR_INTERNAL_ERROR, "Removal failed")
+            self.Finished(EXIT_FAILED)
+
+    @dbus.service.method(PACKAGEKIT_DBUS_INTERFACE,
+                         in_signature='s', out_signature='')
+    def InstallPackage(self, id):
+        '''
+        Implement the {backend}-install functionality
+        '''
+        #FIXME: Exception and error handling
+        #FIXME: Handle progress in a more sane way
+        log.info("Installing package with id %s" % id)
+        self.last_action_time = time.time()
+        self.StatusChanged(STATUS_INSTALL)
+        self.PercentageChanged(0)
+        self.AllowCancel(False)
+        pkg = self._find_package_by_id(id)
+        name = pkg.name[:]
+        try:
+            pkg.markInstall()
+            self._cache.commit(PackageKitFetchProgress(self),
+                               PackageKitInstallProgress(self))
+        except:
+            self.ErrorCode(ERROR_INTERNAL_ERROR, "Installation failed")
+            self.Finished(EXIT_FAILED)
+            self._open_cache()
+            return
+        self._open_cache()
+        if self._cache.has_key(name) and self._cache[name].isInstalled:
+            self.Finished(EXIT_SUCCESS)
+        else:
+            self.ErrorCode(ERROR_INTERNAL_ERROR, "Installation failed")
+            self.Finished(EXIT_FAILED)
+
+    @dbus.service.method(PACKAGEKIT_DBUS_INTERFACE,
+                         in_signature='b', out_signature='')
+    def RefreshCache(self, force):
+        '''
+        Implement the {backend}-refresh_cache functionality
+        '''
+        self.last_action_time = time.time()
+        self.AllowCancel(True);
+        self.PercentageChanged(0)
+        self.StatusChanged(STATUS_REFRESH_CACHE)
+        try:
+            self._cache.update(PackageKitFetchProgress(self))
+        except:
+            self._open_cache()
+            self.ErrorCode(ERROR_NO_CACHE,
+                           "Package cache could not be opened")
+            self.Finished(EXIT_FAILED)
+            return
+        self._open_cache()
+        self.Finished(EXIT_SUCCESS)
 
-    #
     # Helpers
-    #
+
+    def _open_cache(self):
+        '''
+        (Re)Open the APT cache
+        '''
+        self.StatusChanged(STATUS_REFRESH_CACHE)
+        self.doLock()
+        try:
+            self._cache = apt.Cache(PackageKitOpProgress(self))
+        except:
+            self.ErrorCode(ERROR_NO_CACHE, "Package cache could not be opened")
+            self.Finished(EXIT_FAILED)
+            return
+        self.doUnlock()
+        if self._cache._depcache.BrokenCount > 0:
+            self.ErrorCode(ERROR_INTERNAL_ERROR,
+                           "Not all dependecies can be satisfied")
+            self.Finished(EXIT_FAILED)
+            return
+
     def get_id_from_package(self, pkg, installed=False):
         '''
-        Returns the id of the installation candidate of a core
+        Return the id of the installation candidate of a core
         apt package. If installed is set to True the id of the currently
         installed package will be returned.
         '''
@@ -240,19 +432,19 @@ class PackageKitAptBackend(PackageKitBaseBackend):
         id = self._get_package_id(pkg.name, pkgver, pkg.architecture, origin)
         return id
 
-    def _emit_package(self, pkg, installed=False):
+    def _emit_package(self, pkg):
         '''
         Send the Package signal for a given apt package
         '''
-        id = self.get_id_from_package(pkg, installed)
-        if installed and pkg.isInstalled:
+        id = self.get_id_from_package(pkg)
+        if pkg.isInstalled:
             status = INFO_INSTALLED
         else:
             status = INFO_AVAILABLE
         summary = pkg.summary
         self.Package(status, id, summary)
 
-    def _package_is_visible(self, pkg, filters):
+    def _is_package_visible(self, pkg, filters):
         '''
         Return True if the package should be shown in the user interface
         '''
@@ -284,6 +476,17 @@ class PackageKitAptBackend(PackageKitBaseBackend):
         return pkg.name.endswith("-dev") or pkg.name.endswith("-dbg") or \
                pkg.section.split('/')[-1].lower() in ['devel', 'libdevel']
 
+    def _find_package_by_id(self, id):
+        '''
+        Return a package matching to the given package id
+        '''
+        # FIXME: Perform more checks
+        name, version, arch, data = self.get_package_from_id(id)
+        if self._cache.has_key(name):
+            return self._cache[name]
+        else:
+            return None
+
 
 if __name__ == '__main__':
     loop = dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)
diff --git a/backends/apt2/pk-backend-apt2.c b/backends/apt2/pk-backend-apt2.c
index 1d0a02c..eb1fd53 100644
--- a/backends/apt2/pk-backend-apt2.c
+++ b/backends/apt2/pk-backend-apt2.c
@@ -147,12 +147,12 @@ backend_install_package (PkBackend *backend, const gchar *package_id)
 
 /**
  * backend_refresh_cache:
- *
+ * */
 static void
 backend_refresh_cache (PkBackend *backend, gboolean force)
 {
 	g_return_if_fail (backend != NULL);
-	g_return_if_fail (spawn != NULL);
+	g_return_if_fail (dbus != NULL);
 
 	// check network state
 	if (pk_network_is_online (network) == FALSE) {
@@ -161,8 +161,8 @@ backend_refresh_cache (PkBackend *backend, gboolean force)
 		return;
 	}
 
-	pk_backend_spawn_helper (spawn, "refresh-cache.py", NULL);
-} */
+	pk_backend_dbus_refresh_cache(dbus, force);
+} 
 
 /**
  * pk_backend_remove_package:
@@ -196,14 +196,14 @@ backend_update_package (PkBackend *backend, const gchar *package_id)
 
 /**
  * pk_backend_update_system:
- *
+ * */
 static void
 backend_update_system (PkBackend *backend)
 {
 	g_return_if_fail (backend != NULL);
-	g_return_if_fail (spawn != NULL);
-	pk_backend_spawn_helper (spawn, "update-system.py", NULL);
-} */
+	g_return_if_fail (dbus != NULL);
+        pk_backend_dbus_update_system (dbus);
+}
 
 /**
  * pk_backend_resolve:
@@ -228,6 +228,28 @@ backend_get_repo_list (PkBackend *backend)
 } */
 
 /**
+ * backend_install_package
+ *  */
+static void
+backend_install_package (PkBackend *backend, const gchar *package_id)
+{
+        g_return_if_fail (backend != NULL);
+        g_return_if_fail (dbus != NULL);
+        pk_backend_dbus_install_package (dbus, package_id);
+}
+
+/**
+ * backend_remove_package
+ *  */
+static void
+backend_remove_package (PkBackend *backend, const gchar *package_id, gboolean allow_deps)
+{
+        g_return_if_fail (backend != NULL);
+        g_return_if_fail (dbus != NULL);
+        pk_backend_dbus_remove_package (dbus, package_id, allow_deps);
+}
+
+/**
  * backend_get_description:
  *  */
 static void
@@ -274,10 +296,10 @@ PK_BACKEND_OPTIONS (
 	NULL,					/* get_requires */
 	NULL,					/* get_update_detail */
 	backend_get_updates,			/* get_updates */
-	NULL,					/* install_package */
+	backend_install_package,		/* install_package */
 	NULL,					/* install_file */
-	NULL,					/* refresh_cache */
-	NULL,					/* remove_package */
+	backend_refresh_cache,			/* refresh_cache */
+	backend_remove_package,			/* remove_package */
 	NULL,					/* resolve */
 	NULL,					/* rollback */
 	backend_search_details,			/* search_details */
@@ -285,7 +307,7 @@ PK_BACKEND_OPTIONS (
 	NULL,					/* search_group */
 	backend_search_name,			/* search_name */
 	NULL,					/* update_package */
-	NULL,					/* update_system */
+	backend_update_system,			/* update_system */
 	NULL,					/* get_repo_list */
 	NULL,					/* repo_enable */
 	NULL,					/* repo_set_data */
diff --git a/docs/html/pk-faq.html b/docs/html/pk-faq.html
index 95aeb21..a62ecca 100644
--- a/docs/html/pk-faq.html
+++ b/docs/html/pk-faq.html
@@ -25,17 +25,17 @@
                   | conary | yum | apt | apt2 | box | alpm | smart | pisi | zypp |
 ---------------------------------------------------------------------------
 Resolve           |   X    |  X  |     |      |  X  |      |   X   |   X  |   X  |
-RefreshCache      |   X    |  X  |  X  |      |  X  |      |   X   |   X  |      |
+RefreshCache      |   X    |  X  |  X  |  X   |  X  |      |   X   |   X  |      |
  \Force           |        |     |     |      |     |      |       |      |      |
 GetUpdates        |   X    |  X  |     |  X   |  X  |      |   X   |   X  |      |
-UpdateSystem      |   X    |  X  |     |      |  X  |      |   X   |   X  |      |
+UpdateSystem      |   X    |  X  |     |  X   |  X  |      |   X   |   X  |      |
 SearchName        |   X    |  X  |  X  |  X   |  X  |  X   |   X   |   X  |   X  |
 SearchDetails     |        |  X  |  X  |  X   |  X  |      |   X   |   X  |      |
 SearchFile        |        |  X  |     |      |  X  |      |       |   X  |      |
 SearchGroup       |        |  X  |     |      |     |      |       |   X  |      |
-InstallPackage    |   X    |  X  |     |      |  X  |  X   |   X   |   X  |   X  |
+InstallPackage    |   X    |  X  |     |  X   |  X  |  X   |   X   |   X  |   X  |
 InstallFile       |        |  X  |     |      |  X  |      |   X   |   X  |      |
-RemovePackage     |   X    |  X  |     |      |  X  |  X   |   X   |   X  |      |
+RemovePackage     |   X    |  X  |     |  X   |  X  |  X   |   X   |   X  |      |
 UpdatePackage     |   X    |  X  |     |      |  X  |      |   X   |   X  |      |
 GetDepends        |        |  X  |     |      |  X  |      |   X   |   X  |      |
  \Recursive       |        |     |     |      |     |      |       |      |      |
commit 7ae907986354005b73ffd66662e8a8d9becced56
Author: Sebastian Heinlein <sebi at glatzor.de>
Date:   Tue Feb 26 00:33:49 2008 +0100

    * APT-DBUS: clean up DBus configuration
      - introduce a policykit group
      - add policy for the destination

diff --git a/data/org.freedesktop.PackageKit.conf.in b/data/org.freedesktop.PackageKit.conf.in
index 708f2eb..7ce58be 100644
--- a/data/org.freedesktop.PackageKit.conf.in
+++ b/data/org.freedesktop.PackageKit.conf.in
@@ -14,19 +14,22 @@
     <allow own="org.freedesktop.PackageKit"/>
   </policy>
 
-  <!-- Allow anyone to invoke methods on the Manager and Device interfaces -->
+  <!-- Forbid anyone to invoke methods on the Manager and Device interfaces -->
   <policy context="default">
     <deny send_interface="org.freedesktop.PackageKit"/>
+    <deny send_destination="org.freedesktop.PackageKit"/>
   </policy>
 
   <!-- This will not work if pam_console support is not enabled -->
   <policy at_console="true">
     <allow send_interface="org.freedesktop.PackageKit"/>
+    <allow send_destination="org.freedesktop.PackageKit"/>
   </policy>
 
   <!-- You can change this to a more suitable user, or make per-group -->
-  <policy user="0">
+  <policy group="packagekit">
     <allow send_interface="org.freedesktop.PackageKit"/>
+    <allow send_destination="org.freedesktop.PackageKit"/>
   </policy>
 
 </busconfig>
commit 565990b5e0ba9128fe4e7247ba77da2a939e2266
Merge: 8aad2e1... 6470f64...
Author: Robin Norwood <rnorwood at redhat.com>
Date:   Mon Feb 25 12:08:36 2008 -0500

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

commit 8aad2e100ea27577c5b4aa946c288a2447d50f26
Author: Robin Norwood <rnorwood at redhat.com>
Date:   Mon Feb 25 12:06:05 2008 -0500

    Fix a few things in pk-introduction, and add a section about DBUS backends.

diff --git a/docs/spec/pk-introduction.xml b/docs/spec/pk-introduction.xml
index c8869ca..9ab9720 100644
--- a/docs/spec/pk-introduction.xml
+++ b/docs/spec/pk-introduction.xml
@@ -8,13 +8,13 @@
     <title>Overall Description</title>
 
     <para>
-      PackageKit is a small open source systems abstracts out common package
+      PackageKit is a small open source system that abstracts out common package
       management tasks such as:
     </para>
     <itemizedlist>
       <listitem>
         <para>
-          Checking for updates and installing in the background.
+          Checking for updates and installing them in the background.
         </para>
       </listitem>
       <listitem>
@@ -25,7 +25,7 @@
     </itemizedlist>
 
     <para>
-      PackageKit is a modular design with an asynchronous API for client programs,
+      PackageKit has a modular design with an asynchronous API for client programs,
       a flexible queuing module, and run-time selectable backends.
     </para>
 
@@ -47,11 +47,16 @@
         A backend is just a compiled <literal>.so</literal> object that is
         loaded at run-time and provides an interface to the underlying package
         commands.
-        A backend converts an async request into either a new thread which
-        in the same process, or using external "glue" files that can be written
-        in any language.
+        A backend converts an async request into either a new thread
+        in the same process, executes external "glue" files that
+        can be written in any language, or uses DBUS to signal a
+        daemon process to handle the request.
       </para>
       <para>
+	Backends do not have to support all of the commands supported
+        by PackageKit.  Each backend advertises the commands and
+        options it supports, and the frontend will only show UI
+        elements for those commands.
         Please see the <literal>html/pk-faq.html</literal> file for the current
         status of the existing backends.
         Backend maintainers, please keep this file updated.
@@ -61,12 +66,12 @@
     <sect2 id="introduction-backends-compiled-backends">
       <title>Compiled backends</title>
       <para>
-        If you have got a C or C++ binding for your package system then you can
-        use a compiled backend, which is more efficient than using helpers as
-        described below.
-        You can include the headers in the backend (with extra libraries) and
-        then just write the simple code to interface with the set methods of
-        PackageKit.
+        If you have a C or C++ binding for your package system then
+        you can use a compiled backend, which is more efficient than
+        using helpers as described below.
+        You can include the headers in the backend (with extra
+        libraries) and then just write the simple code to interface
+        with the methods of PackageKit.
         A C example can be found in <literal>backends/box</literal> and a
         C++ example in <literal>backends/apt</literal>.
       </para>
@@ -83,7 +88,7 @@
     <sect2 id="introduction-backends-helpers">
       <title>Backends with helpers</title>
       <para>
-        If you do not have a C or C++ language binding PackageKit executes
+        If you do not have a C or C++ language binding, PackageKit executes
         helper scripts written in pretty much any language.
         It then watches the standard out and standard error and parses the
         output into compiled backend commands.
@@ -113,6 +118,36 @@
         and paste in the compiled part of the backend.
       </para>
     </sect2>
+
+    <sect2 id="introduction-backends-dbus">
+      <title>DBUS-based backends</title>
+      <para>
+        Backend helpers communicating over standard out and standard
+        error are easy to write, but can have some performance
+        problems.  For instance, if your packages system has to do a
+        lot of work when it starts up and shuts down, performance in
+        the UI may suffer.  In these cases, you can use a persistant
+        backend daemon that communicates to the C backend over DBUS.
+      </para>
+      <para>
+        Your daemon will be started by DBUS, and should be responsible
+        for it's own thread management.  It should receive an Init
+        signal when the C backend starts, and an Exit signal before it
+        exits.  The C backend should also send Lock and signals before
+        a command is executed, and Unlock after it completes
+        successfully.  You should also consider adding a timeout value
+        to your daemon so that it will exit after a set time with no
+        activity from the C backend.  That way the daemon will still
+        exit even if the C backend crashes for some reason.
+      </para>
+      <para>
+        Again, like the helper backends described above, a compiled
+        backend stub is needed.  An example of a DBUS backend written
+        in python can be found in <literal>backends/yum2</literal>,
+        along with a compiled stub written in C.
+      </para>
+    </sect2>
+
   </sect1>
 
   <sect1 id="introduction-ideas">
commit 6470f6413a345ed02d373474cc347beee4e5e0f8
Author: Scott Reeves <sreeves at novell.com>
Date:   Mon Feb 25 09:08:11 2008 -0700

    fix to build with newer libzyp (4.2.9)

diff --git a/backends/zypp/pk-backend-zypp.cpp b/backends/zypp/pk-backend-zypp.cpp
index e1cb8c2..cc3614c 100644
--- a/backends/zypp/pk-backend-zypp.cpp
+++ b/backends/zypp/pk-backend-zypp.cpp
@@ -33,10 +33,8 @@
 #include <zypp/ResPoolProxy.h>
 #include <zypp/ui/Selectable.h>
 #include <zypp/Patch.h>
-#include <zypp/Selection.h>
 #include <zypp/Package.h>
 #include <zypp/Pattern.h>
-#include <zypp/Language.h>
 #include <zypp/Product.h>
 #include <zypp/Repository.h>
 #include <zypp/RepoManager.h>
@@ -52,7 +50,6 @@
 #include <zypp/target/rpm/RpmException.h>
 
 #include <zypp/sat/Solvable.h>
-#include <zypp/sat/Capabilities.h>
 
 #include <map>
 #include <list>
diff --git a/backends/zypp/zypp-utils.h b/backends/zypp/zypp-utils.h
index 5365cca..094c066 100644
--- a/backends/zypp/zypp-utils.h
+++ b/backends/zypp/zypp-utils.h
@@ -20,7 +20,6 @@ typedef zypp::ResObject::constPtr	ZyppObject;
 typedef zypp::Package::constPtr		ZyppPackage;
 typedef zypp::Patch::constPtr		ZyppPatch;
 typedef zypp::Pattern::constPtr		ZyppPattern;
-typedef zypp::Language::constPtr	ZyppLanguage;
 //inline ZyppPackage tryCastToZyppPkg (ZyppObject obj)
 //	{ return zypp::dynamic_pointer_cast <const zypp::Package> (obj); }
 typedef std::set<zypp::PoolItem> Candidates;
commit f748f6dc4677580f69a78fed70c815d81ba77a4a
Author: Sebastian Heinlein <sebi at glatzor.de>
Date:   Mon Feb 25 16:09:35 2008 +0100

    * APT-DBUS: Add a HACKING file and add an issue to the TODO

diff --git a/backends/apt2/HACKING b/backends/apt2/HACKING
new file mode 100644
index 0000000..2b99c5d
--- /dev/null
+++ b/backends/apt2/HACKING
@@ -0,0 +1,5 @@
+The backend can be tested by running it as root from the source code
+repository. Make sure to kill packagekitd before to force a reintializing
+of the cache:
+
+  killall packagekitd; python aptDBUSBackend.py 
diff --git a/backends/apt2/TODO b/backends/apt2/TODO
index 334a8c1..bee2f3d 100644
--- a/backends/apt2/TODO
+++ b/backends/apt2/TODO
@@ -64,5 +64,7 @@ TODO:
     - translations 				=> localization
   The following could not be maped: science, documentation, electronics
   Are there any derivates with additional sections?
+
+ * Fix the dbus policy. Should we require at_console for searching?
  
 DONE:
commit aaa1cd4c3c28061c4e67f893aa6c48b2e4e48386
Author: Sebastian Heinlein <sebi at glatzor.de>
Date:   Mon Feb 25 16:06:18 2008 +0100

    * APT-DBUS: add a TODO and README

diff --git a/backends/apt2/README b/backends/apt2/README
new file mode 100644
index 0000000..0a3da6e
--- /dev/null
+++ b/backends/apt2/README
@@ -0,0 +1,23 @@
+The name of this backend is apt2.
+
+It supports apt which is mainly used by Debian and its derivates. In contrast to
+the backend called apt this one uses DBus for the communication with the 
+packagekit daemon. This allows to perform actions without having to reopen
+the cache for each one.
+
+To provide a tremendously fast search function a Xapian database is used.
+It is provided by Enrico Zini's apt-xapian-index. Debtags will be used to 
+enhance the quality of the search results further.
+
+A list of implemented functions are listed in the PackageKit FAQ:
+
+http://www.packagekit.org/pk-faq.html
+
+You can find packages for Ubuntu here:
+
+https://www.launchpad.net/~packagekit/+ppa
+
+Packages for Debian Unstable will be provided soon.
+
+Feel free to send comments or bug reports to the PackageKit mailing list
+or to the author.
diff --git a/backends/apt2/TODO b/backends/apt2/TODO
new file mode 100644
index 0000000..334a8c1
--- /dev/null
+++ b/backends/apt2/TODO
@@ -0,0 +1,68 @@
+ISSUES:
+
+ * Support delayed or hidden debconf questions
+
+Unresolved issues can be discussed at the following wiki page:
+http://wiki.debian.org/PackageKit
+
+
+TODO:
+
+ * Implement all open backend methods. A list of implemented backend methods 
+   can be found in PackageKit FAQ or in pk-backend-apt2.c.
+
+ * Blacklist packages requiring input on the terminal and try to change
+   the Debian policy in the long run. Way of automation?
+ 
+ * Allow to inject alternative apt.package.Package classes into the
+   cache to support PackageKit and distribution specific needs
+   (e.g. when is a package called free or supported)
+
+ * Allow to reinject debtags into the search results to get 
+   similar software which not matches on the search terms
+
+ * Index file list and add properties for package name and section to
+   the xapian database to also make use of it in search group and 
+   search name (do we want this?)
+
+ * Map Debian/Ubuntu sections to PackageKit groups:
+    - admin : System Administration 		=> admin-tools
+    - base : Base System 			=> system
+    - comm : Communication			=> communication
+    - devel : Development 			=> programming
+    - doc : Documentation			=> ???
+    - editors : Editors				=> accessoires
+    - electronics : Electronics			=> other
+    - embedded : Embedded Devices		=> system
+    - games : Games and Amusement 		=> games
+    - gnome : GNOME Desktop Environment		=> desktop-gnome
+    - graphics : Graphics			=> graphics
+    - hamradio : Amateur Radio			=> communication
+    - interpreters : Interpreted Computer L.	=> programming
+    - kde : KDE Desktop Environment		=> desktop-kde
+    - libdevel : Libraries - Development	=> programming
+    - libs : Libraries				=> system
+    - mail : Email				=> internet
+    - math : Mathematics			=> ??? science/education
+    - misc : Miscellaneous - Text Based		=> other
+    - net : Networkinga				=> network
+    - news : Newsgroup				=> internet
+    - oldlibs : Libraries - Old			=> legacy
+    - otherosfs : Cross Platform		=> system
+    - perl : Perl Programming Language		=> programming
+    - python : Python Programming Language	=> programming
+    - science : Science				=> ??? science/education
+    - shells : Shells				=> system
+    - sound : Multimedia			=> multimedia
+    - tex : TeX Authoring			=> publishing
+    - text : Word Processing			=> publishing
+    - utils : Utilities				=> accessoires
+    - web : World Wide Web			=> internet
+    - x11 : Miscellaneous  - Graphical		=> desktop-other
+    - unknown : Unknown				=> unknown
+    - alien : Converted From RPM by Alien"	=> unknown
+    - translations 				=> localization
+  The following could not be maped: science, documentation, electronics
+  Are there any derivates with additional sections?
+ 
+DONE:
commit 9c0f340bf66a2a5e70501df0342b396f360e332d
Author: Sebastian Heinlein <sebi at glatzor.de>
Date:   Mon Feb 25 15:21:43 2008 +0100

    * Add the apt2 backend to the status overview

diff --git a/docs/html/pk-faq.html b/docs/html/pk-faq.html
index 05c0148..95aeb21 100644
--- a/docs/html/pk-faq.html
+++ b/docs/html/pk-faq.html
@@ -22,45 +22,45 @@
 <h3>How complete are the backends?</h3>
 <h4>Methods</h4>
 <pre>
-                  | conary | yum | apt | box | alpm | smart | pisi | zypp |
+                  | conary | yum | apt | apt2 | box | alpm | smart | pisi | zypp |
 ---------------------------------------------------------------------------
-Resolve           |   X    |  X  |     |  X  |      |   X   |   X  |   X  |
-RefreshCache      |   X    |  X  |  X  |  X  |      |   X   |   X  |      |
- \Force           |        |     |     |     |      |       |      |      |
-GetUpdates        |   X    |  X  |     |  X  |      |   X   |   X  |      |
-UpdateSystem      |   X    |  X  |     |  X  |      |   X   |   X  |      |
-SearchName        |   X    |  X  |  X  |  X  |  X   |   X   |   X  |   X  |
-SearchDetails     |        |  X  |  X  |  X  |      |   X   |   X  |      |
-SearchFile        |        |  X  |     |  X  |      |       |   X  |      |
-SearchGroup       |        |  X  |     |     |      |       |   X  |      |
-InstallPackage    |   X    |  X  |     |  X  |  X   |   X   |   X  |   X  |
-InstallFile       |        |  X  |     |  X  |      |   X   |   X  |      |
-RemovePackage     |   X    |  X  |     |  X  |  X   |   X   |   X  |      |
-UpdatePackage     |   X    |  X  |     |  X  |      |   X   |   X  |      |
-GetDepends        |        |  X  |     |  X  |      |   X   |   X  |      |
- \Recursive       |        |     |     |     |      |       |      |      |
-GetRequires       |   X    |  X  |     |  X  |      |       |   X  |      |
- \Recursive       |        |     |     |     |      |       |      |      |
-GetDescription    |   X    |  X  |  X  |  X  |      |   X   |   X  |      |
-GetFiles          |   X    |  X  |     |  X  |      |   X   |   X  |      |
-GetUpdateDetail   |        |  X  |     |     |      |       |      |      |
-GetRepoList       |        |  X  |     |  X  |  X   |   X   |   X  |   X  |
-RepoEnable        |        |  X  |     |  X  |      |   X   |      |   X  |
-RepoSetData       |        |  X  |     |  X  |      |       |   X  |      |
-Cancel            |   X    |  X  |     |     |      |       |   X  |      |
-ServicePack       |        |     |     |     |      |       |      |      |
+Resolve           |   X    |  X  |     |      |  X  |      |   X   |   X  |   X  |
+RefreshCache      |   X    |  X  |  X  |      |  X  |      |   X   |   X  |      |
+ \Force           |        |     |     |      |     |      |       |      |      |
+GetUpdates        |   X    |  X  |     |  X   |  X  |      |   X   |   X  |      |
+UpdateSystem      |   X    |  X  |     |      |  X  |      |   X   |   X  |      |
+SearchName        |   X    |  X  |  X  |  X   |  X  |  X   |   X   |   X  |   X  |
+SearchDetails     |        |  X  |  X  |  X   |  X  |      |   X   |   X  |      |
+SearchFile        |        |  X  |     |      |  X  |      |       |   X  |      |
+SearchGroup       |        |  X  |     |      |     |      |       |   X  |      |
+InstallPackage    |   X    |  X  |     |      |  X  |  X   |   X   |   X  |   X  |
+InstallFile       |        |  X  |     |      |  X  |      |   X   |   X  |      |
+RemovePackage     |   X    |  X  |     |      |  X  |  X   |   X   |   X  |      |
+UpdatePackage     |   X    |  X  |     |      |  X  |      |   X   |   X  |      |
+GetDepends        |        |  X  |     |      |  X  |      |   X   |   X  |      |
+ \Recursive       |        |     |     |      |     |      |       |      |      |
+GetRequires       |   X    |  X  |     |      |  X  |      |       |   X  |      |
+ \Recursive       |        |     |     |      |     |      |       |      |      |
+GetDescription    |   X    |  X  |  X  |  X   |  X  |      |   X   |   X  |      |
+GetFiles          |   X    |  X  |     |      |  X  |      |   X   |   X  |      |
+GetUpdateDetail   |        |  X  |     |      |     |      |       |      |      |
+GetRepoList       |        |  X  |     |      |  X  |  X   |   X   |   X  |   X  |
+RepoEnable        |        |  X  |     |      |  X  |      |   X   |      |   X  |
+RepoSetData       |        |  X  |     |      |  X  |      |       |   X  |      |
+Cancel            |   X    |  X  |     |      |     |      |       |   X  |      |
+ServicePack       |        |     |     |      |     |      |       |      |      |
 </pre>
 
 <h4>Filters</h4>
 <pre>
-                  | conary | yum | apt | box | alpm | smart | pisi | zypp |
+                  | conary | yum | apt | apt2 | box | alpm | smart | pisi | zypp |
 ---------------------------------------------------------------------------
-Installed         |   X    |  X  |  X  |  X  |  X   |   X   |   X  |      |
-Development       |        |  X  |  X  |  X  |      |       |      |      |
-GUI               |        |  X  |  X  |  X  |      |       |   X  |      |
-Free              |        |     |     |     |      |       |      |      |
-Visible           |        |     |     |     |      |       |      |      |
-Supported         |        |     |     |     |      |       |      |      |
+Installed         |   X    |  X  |  X  |  X   |  X  |  X   |   X   |   X  |      |
+Development       |        |  X  |  X  |  x   |  X  |      |       |      |      |
+GUI               |        |  X  |  X  |  X   |  X  |      |       |   X  |      |
+Free              |        |     |     |      |     |      |       |      |      |
+Visible           |        |     |     |      |     |      |       |      |      |
+Supported         |        |     |     |      |     |      |       |      |      |
 </pre>
 
 <h3>Why doesn't PackageKit work with SELinux?</h3>
commit 660cc4c44a6a5ae5cb4178436a2c72923721cfde
Author: Sebastian Heinlein <sebi at glatzor.de>
Date:   Mon Feb 25 14:58:35 2008 +0100

    * APT-DBUS: Readd the filtering method. Should be moved to a modified
                apt.package.Package class to allow easy overrides by differnet
    	    distributions

diff --git a/backends/apt2/aptDBUSBackend.py b/backends/apt2/aptDBUSBackend.py
index a169925..99f5bf6 100755
--- a/backends/apt2/aptDBUSBackend.py
+++ b/backends/apt2/aptDBUSBackend.py
@@ -116,7 +116,7 @@ class PackageKitAptBackend(PackageKitBaseBackend):
         self.StatusChanged(STATUS_QUERY)
 
         for pkg in self._cache:
-            if search in pkg.name:
+            if search in pkg.name and self._package_is_visible(pkg, filters):
                 self._emit_package(pkg)
         self.Finished(EXIT_SUCCESS)
 
@@ -142,7 +142,9 @@ class PackageKitAptBackend(PackageKitBaseBackend):
         for m in matches:
             name = m[xapian.MSET_DOCUMENT].get_data()
             if self._cache.has_key(name):
-                self._emit_package(self._cache[name])
+                pkg = self._cache[name]
+                if self._package_is_visible(pkg) == True:
+                    self._emit_package(pkg)
 
         self.Finished(EXIT_SUCCESS)
 
@@ -250,6 +252,39 @@ class PackageKitAptBackend(PackageKitBaseBackend):
         summary = pkg.summary
         self.Package(status, id, summary)
 
+    def _package_is_visible(self, pkg, filters):
+        '''
+        Return True if the package should be shown in the user interface
+        '''
+        #FIXME: Needs to be optmized
+        if filters == 'none':
+            return True
+        if FILTER_INSTALLED in filters and not pkg.isInstalled:
+            return False
+        if FILTER_NOT_INSTALLED in filters and pkg.isInstalled:
+            return False
+        if FILTER_GUI in filters and not self._package_has_gui(pkg):
+            return False
+        if FILTER_NOT_GUI in filters and self._package_has_gui(pkg):
+            return False
+        if FILTER_DEVELOPMENT in filters and not self._package_is_devel(pkg):
+            return False
+        if FILTER_NOT_DEVELOPMENT in filters and self._package_is_devel(pkg):
+            return False
+        return True
+
+    def _package_has_gui(self, pkg):
+        #FIXME: should go to a modified Package class
+        #FIXME: take application data into account. perhaps checking for 
+        #       property in the xapian database
+        return pkg.section.split('/')[-1].lower() in ['x11', 'gnome', 'kde']
+
+    def _package_is_devel(self, pkg):
+        #FIXME: should go to a modified Package class
+        return pkg.name.endswith("-dev") or pkg.name.endswith("-dbg") or \
+               pkg.section.split('/')[-1].lower() in ['devel', 'libdevel']
+
+
 if __name__ == '__main__':
     loop = dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)
     bus = dbus.SystemBus(mainloop=loop)
commit fdc4f85371acb85a88fa865de330ccd47637c136
Author: Sebastian Heinlein <sebi at glatzor.de>
Date:   Mon Feb 25 13:02:11 2008 +0100

    * APT-DBUS:
      - Implement SearchDetails using the xapian database. Currently no
        reinjection using detags is done.
      - Fix the removed re import

diff --git a/backends/apt2/aptDBUSBackend.py b/backends/apt2/aptDBUSBackend.py
index f61119f..a169925 100755
--- a/backends/apt2/aptDBUSBackend.py
+++ b/backends/apt2/aptDBUSBackend.py
@@ -19,12 +19,15 @@ __author__  = "Sebastian Heinlein <devel at glatzor.de>"
 __state__   = "experimental"
 
 import logging
+import os
+import re
 import warnings
 
 import apt
 import dbus
 import dbus.service
 import dbus.mainloop.glib
+import xapian
 
 from packagekit.daemonBackend import PACKAGEKIT_DBUS_INTERFACE, PACKAGEKIT_DBUS_PATH, PackageKitBaseBackend, PackagekitProgress
 from packagekit.enums import *
@@ -37,6 +40,14 @@ warnings.filterwarnings(action='ignore', category=FutureWarning)
 
 PACKAGEKIT_DBUS_SERVICE = 'org.freedesktop.PackageKitAptBackend'
 
+XAPIANDBPATH = os.environ.get("AXI_DB_PATH", "/var/lib/apt-xapian-index")
+XAPIANDB = XAPIANDBPATH + "/index"
+XAPIANDBVALUES = XAPIANDBPATH + "/values"
+DEFAULT_SEARCH_FLAGS = (xapian.QueryParser.FLAG_BOOLEAN |
+                        xapian.QueryParser.FLAG_PHRASE |
+                        xapian.QueryParser.FLAG_LOVEHATE |
+                        xapian.QueryParser.FLAG_BOOLEAN_ANY_CASE)
+
 class PackageKitOpProgress(apt.progress.OpProgress):
     def __init__(self, backend):
         self._backend = backend
@@ -76,6 +87,7 @@ class PackageKitAptBackend(PackageKitBaseBackend):
         log.info("Initializing backend")
         PackageKitBaseBackend.__init__(self, bus_name, dbus_path)
         self._cache = None
+        self._xapian = None
 
     # Methods ( client -> engine -> backend )
 
@@ -83,7 +95,8 @@ class PackageKitAptBackend(PackageKitBaseBackend):
                          in_signature='', out_signature='')
     def Init(self):
         log.info("Initializing cache")
-        self._cache = apt.Cache(PackageKitProgress(self))
+        self._cache = apt.Cache(PackageKitOpProgress(self))
+        self._xapian = xapian.Database(XAPIANDB)
 
     @dbus.service.method(PACKAGEKIT_DBUS_INTERFACE,
                          in_signature='', out_signature='')
@@ -94,7 +107,7 @@ class PackageKitAptBackend(PackageKitBaseBackend):
                          in_signature='ss', out_signature='')
     def SearchName(self, filters, search):
         '''
-        Implement the {backend}-search-name functionality
+        Implement the apt2-search-name functionality
         '''
         log.info("Searching for package name: %s" % search)
         self.AllowCancel(True)
@@ -109,6 +122,32 @@ class PackageKitAptBackend(PackageKitBaseBackend):
 
 
     @dbus.service.method(PACKAGEKIT_DBUS_INTERFACE,
+                         in_signature='ss', out_signature='')
+    def SearchDetails(self, filters, search):
+        '''
+        Implement the apt2-search-details functionality
+        '''
+        log.info("Searching for package name: %s" % search)
+        self.AllowCancel(True)
+        self.NoPercentageUpdates()
+        self.StatusChanged(STATUS_QUERY)
+
+        self._xapian.reopen()
+        parser = xapian.QueryParser()
+        query = parser.parse_query(unicode(search),
+                                   DEFAULT_SEARCH_FLAGS)
+        enquire = xapian.Enquire(self._xapian)
+        enquire.set_query(query)
+        matches = enquire.get_mset(0, 1000)
+        for m in matches:
+            name = m[xapian.MSET_DOCUMENT].get_data()
+            if self._cache.has_key(name):
+                self._emit_package(self._cache[name])
+
+        self.Finished(EXIT_SUCCESS)
+
+
+    @dbus.service.method(PACKAGEKIT_DBUS_INTERFACE,
                          in_signature='', out_signature='')
     def GetUpdates(self):
         '''
diff --git a/backends/apt2/pk-backend-apt2.c b/backends/apt2/pk-backend-apt2.c
index 2b695f2..1d0a02c 100644
--- a/backends/apt2/pk-backend-apt2.c
+++ b/backends/apt2/pk-backend-apt2.c
@@ -239,6 +239,17 @@ backend_get_description (PkBackend *backend, const gchar *package_id)
 }
 
 /**
+ *  * pk_backend_search_details:
+ *   */
+static void
+backend_search_details (PkBackend *backend, const gchar *filter, const gchar *search)
+{
+        g_return_if_fail (backend != NULL);
+        g_return_if_fail (dbus != NULL);
+        pk_backend_dbus_search_details (dbus, filter, search);
+}
+
+/**
  *  * pk_backend_search_name:
  *   */
 static void
@@ -269,7 +280,7 @@ PK_BACKEND_OPTIONS (
 	NULL,					/* remove_package */
 	NULL,					/* resolve */
 	NULL,					/* rollback */
-	NULL,					/* search_details */
+	backend_search_details,			/* search_details */
 	NULL,					/* search_file */
 	NULL,					/* search_group */
 	backend_search_name,			/* search_name */
commit 9a7e93fc8c774bd673ccdb0e6311b740e9e841a9
Author: Sebastian Heinlein <sebi at glatzor.de>
Date:   Mon Feb 25 12:13:24 2008 +0100

    * APT-DBUS: Use the logging module and add some basic information about
                the author and the current status

diff --git a/backends/apt2/aptDBUSBackend.py b/backends/apt2/aptDBUSBackend.py
index ad3bf32..f61119f 100755
--- a/backends/apt2/aptDBUSBackend.py
+++ b/backends/apt2/aptDBUSBackend.py
@@ -15,11 +15,13 @@ the Free Software Foundation; either version 2 of the License, or
 (at your option) any later version.
 """
 
+__author__  = "Sebastian Heinlein <devel at glatzor.de>"
+__state__   = "experimental"
+
+import logging
 import warnings
-warnings.filterwarnings(action='ignore', category=FutureWarning)
 
 import apt
-
 import dbus
 import dbus.service
 import dbus.mainloop.glib
@@ -27,6 +29,12 @@ import dbus.mainloop.glib
 from packagekit.daemonBackend import PACKAGEKIT_DBUS_INTERFACE, PACKAGEKIT_DBUS_PATH, PackageKitBaseBackend, PackagekitProgress
 from packagekit.enums import *
 
+logging.basicConfig()
+log = logging.getLogger("aptDBUSBackend")
+log.setLevel(logging.DEBUG)
+
+warnings.filterwarnings(action='ignore', category=FutureWarning)
+
 PACKAGEKIT_DBUS_SERVICE = 'org.freedesktop.PackageKitAptBackend'
 
 class PackageKitOpProgress(apt.progress.OpProgress):
@@ -65,6 +73,7 @@ class PackageKitInstallProgress(apt.progress.InstallProgress):
 
 class PackageKitAptBackend(PackageKitBaseBackend):
     def __init__(self, bus_name, dbus_path):
+        log.info("Initializing backend")
         PackageKitBaseBackend.__init__(self, bus_name, dbus_path)
         self._cache = None
 
@@ -73,6 +82,7 @@ class PackageKitAptBackend(PackageKitBaseBackend):
     @dbus.service.method(PACKAGEKIT_DBUS_INTERFACE,
                          in_signature='', out_signature='')
     def Init(self):
+        log.info("Initializing cache")
         self._cache = apt.Cache(PackageKitProgress(self))
 
     @dbus.service.method(PACKAGEKIT_DBUS_INTERFACE,
@@ -86,6 +96,7 @@ class PackageKitAptBackend(PackageKitBaseBackend):
         '''
         Implement the {backend}-search-name functionality
         '''
+        log.info("Searching for package name: %s" % search)
         self.AllowCancel(True)
         self.NoPercentageUpdates()
 
commit 71f159150ed55c9fd9d2ae54e52c17f3385ec258
Author: Sebastian Heinlein <sebi at glatzor.de>
Date:   Mon Feb 25 11:56:55 2008 +0100

    * APT-DBUS: great clean up to represent our current status more clearly

diff --git a/backends/apt2/aptDBUSBackend.py b/backends/apt2/aptDBUSBackend.py
index 7396f45..ad3bf32 100755
--- a/backends/apt2/aptDBUSBackend.py
+++ b/backends/apt2/aptDBUSBackend.py
@@ -15,22 +15,10 @@ the Free Software Foundation; either version 2 of the License, or
 (at your option) any later version.
 """
 
-from sets import Set
-import sys
-import os
-from os.path import join,exists
-from os import system
-import re
-from urlparse import urlparse
 import warnings
 warnings.filterwarnings(action='ignore', category=FutureWarning)
 
 import apt
-from apt.debfile import DebPackage
-import apt_inst
-import apt_pkg
-from aptsources.distro import get_distro
-from aptsources.sourceslist import SourcesList
 
 import dbus
 import dbus.service
@@ -41,152 +29,6 @@ from packagekit.enums import *
 
 PACKAGEKIT_DBUS_SERVICE = 'org.freedesktop.PackageKitAptBackend'
 
-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 __setParent(self,pkg):
-        for x in ["_pkg","_depcache","_records"]:
-            setattr(self,x,getattr(pkg,x))
-
-    def __init__(self, backend, pkg, data="",version=[]):
-        self.__setParent(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_INTERNAL_ERROR,"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_INTERNAL_ERROR,
-                            "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 PackageKitOpProgress(apt.progress.OpProgress):
     def __init__(self, backend):
         self._backend = backend
@@ -358,271 +200,6 @@ class PackageKitAptBackend(PackageKitBaseBackend):
         summary = pkg.summary
         self.Package(status, id, summary)
 
-
-    # FIXME: Needs to be ported
-
-    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, force):
-        '''
-        Implement the {backend}-refresh_cache functionality
-        '''
-        self.status(STATUS_REFRESH_CACHE)
-        try:
-            res = self._cache.update(PackageKitProgress(self))
-        except Exception, error_message:
-             self.error(ERROR_INTERNAL_ERROR,
-                        "Failed to fetch the following items:\n%s" % error_message)
-        return res
-
-    def resolve(self, name):
-        '''
-        Implement the {backend}-resolve functionality
-        '''
-        self.status(STATUS_INFO)
-        try:
-            pkg = Package(self,self._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._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,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._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._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._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._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):
-        '''
-        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_INTERNAL_ERROR, "Problem while trying to save repo settings to %s: %s"%(e.filename,e.strerror))
-
-    def install_file (self, inst_file):
-        '''
-        Implement the {backend}-install_file 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._cache[n],version=deps[n])
-           if not p.isInstalled:
-               p.markInstall()
-        assert self._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_INTERNAL_ERROR,"Can't install package")
-
-    ### Helpers ###
-    def _do_search(self, filters, condition):
-        filters = filters.split(';')
-        size = len(self._cache)
-        percentage = 0
-        for i, pkg in enumerate(self._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
-
 if __name__ == '__main__':
     loop = dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)
     bus = dbus.SystemBus(mainloop=loop)
commit 89358198b4b749807ca87f7fc412d884c9d99cec
Merge: 92c4c08... f945389...
Author: Sebastian Heinlein <sebi at glatzor.de>
Date:   Mon Feb 25 11:53:42 2008 +0100

    Merge branch 'master' into train

commit 92c4c08b0426c04bb3d416c20696ae45c51468dc
Author: Sebastian Heinlein <sebi at glatzor.de>
Date:   Sun Feb 24 09:53:32 2008 +0100

    * APT-DBUS: use different Progress classes to follow the design of apt

diff --git a/backends/apt2/aptDBUSBackend.py b/backends/apt2/aptDBUSBackend.py
index 998b4dc..7396f45 100755
--- a/backends/apt2/aptDBUSBackend.py
+++ b/backends/apt2/aptDBUSBackend.py
@@ -187,19 +187,22 @@ class Package(apt.Package):
             return True
         return False
 
-class PackageKitProgress(apt.progress.OpProgress, apt.progress.FetchProgress):
+class PackageKitOpProgress(apt.progress.OpProgress):
     def __init__(self, backend):
         self._backend = backend
         apt.progress.OpProgress.__init__(self)
-        apt.progress.FetchProgress.__init__(self)
 
     # OpProgress callbacks
     def update(self, percent):
-        pass
+        self._backend.PercentageChanged(int(percent))
 
     def done(self):
-        pass
+        self._backend.PercentageChanged(100)
 
+class PackageKitFetchProgress(apt.progress.FetchProgress):
+    def __init__(self, backend):
+        self._backend = backend
+        apt.progress.FetchProgress.__init__(self)
     # FetchProgress callbacks
     def pulse(self):
         apt.progress.FetchProgress.pulse(self)
@@ -210,9 +213,14 @@ class PackageKitProgress(apt.progress.OpProgress, apt.progress.FetchProgress):
         self._backend.percentage(100)
 
     def mediaChange(self, medium, drive):
+        #FIXME: use the Message method to notify the user
         self._backend.error(ERROR_INTERNAL_ERROR,
                 "Medium change needed")
 
+class PackageKitInstallProgress(apt.progress.InstallProgress):
+    def __init__(self, backend):
+        apt.progress.InstallProgress.__init__(self)
+
 class PackageKitAptBackend(PackageKitBaseBackend):
     def __init__(self, bus_name, dbus_path):
         PackageKitBaseBackend.__init__(self, bus_name, dbus_path)



More information about the PackageKit mailing list