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

Richard Hughes hughsient at kemper.freedesktop.org
Wed May 5 09:27:43 PDT 2010


 backends/yum/Yum.conf             |   24 ++
 backends/yum/yumBackend.py        |   15 +
 backends/zypp/pk-backend-zypp.cpp |  225 +++++++++++--------------
 backends/zypp/zypp-events.h       |    2 
 backends/zypp/zypp-utils.cpp      |  212 +++++++++++++++++------
 backends/zypp/zypp-utils.h        |   26 ++
 contrib/cron/Makefile.am          |    2 
 lib/packagekit-glib2/pk-message.c |   34 +++
 lib/packagekit-glib2/pk-message.h |    5 
 src/pk-backend.c                  |    9 +
 src/pk-cache.c                    |   53 +++--
 src/pk-cache.h                    |   10 -
 src/pk-transaction.c              |  341 +++++++++++++++++++++-----------------
 13 files changed, 599 insertions(+), 359 deletions(-)

New commits:
commit 47baf7c5b13f869eb9cc0a802faaf41d24ca71e3
Author: Richard Hughes <richard at hughsie.com>
Date:   Wed May 5 17:12:23 2010 +0100

    Fix the permission of /etc/sysconfig/packagekit-background to be non-executable

diff --git a/contrib/cron/Makefile.am b/contrib/cron/Makefile.am
index 42ab26b..a950847 100644
--- a/contrib/cron/Makefile.am
+++ b/contrib/cron/Makefile.am
@@ -2,7 +2,7 @@ cronfiledir = ${SYSCONFDIR}/cron.daily
 cronfile_SCRIPTS = packagekit-background.cron
 
 crondatadir = ${SYSCONFDIR}/sysconfig
-crondata_SCRIPTS = packagekit-background
+crondata_DATA = packagekit-background
 
 EXTRA_DIST =						\
 	packagekit-background				\
diff --git a/contrib/cron/packagekit-background b/contrib/cron/packagekit-background
old mode 100755
new mode 100644
commit da05605256722c25e7560844c8a8273b084c0be1
Author: Michael Meeks <michael.meeks at novell.com>
Date:   Wed May 5 16:36:13 2010 +0100

    Get the final 'finished' signal right on remove
    Simulation
      + use the new hint:simulation boolean
      + add all simulation variants
      + cleanup previous simulation var usage
    Remove un-used DEPS enums, and backend variable

diff --git a/backends/zypp/pk-backend-zypp.cpp b/backends/zypp/pk-backend-zypp.cpp
index 3ae0d43..5664cb9 100644
--- a/backends/zypp/pk-backend-zypp.cpp
+++ b/backends/zypp/pk-backend-zypp.cpp
@@ -67,16 +67,6 @@ enum PkgSearchType {
 	SEARCH_TYPE_RESOLVE = 3
 };
 
-enum DepsType {
-	DEPS_TYPE_DEPENDS = 0,
-	DEPS_TYPE_REQUIRES = 1
-};
-
-enum DepsBehavior {
-	DEPS_ALLOW = 0,
-	DEPS_NO_ALLOW = 1
-};
-
 /**
  * A map to keep track of the EventDirector objects for
  * each zypp backend that is created.
@@ -446,7 +436,6 @@ backend_get_depends_thread (PkBackend *backend)
 static void
 backend_get_depends (PkBackend *backend, PkBitfield filters, gchar **package_ids, gboolean recursive)
 {
-	pk_backend_set_uint (backend, "type", DEPS_TYPE_DEPENDS);
 	pk_backend_thread_create (backend, backend_get_depends_thread);
 }
 
@@ -831,6 +820,15 @@ backend_install_files (PkBackend *backend, gboolean only_trusted, gchar **full_p
 	pk_backend_thread_create (backend, backend_install_files_thread);
 }
 
+/**
+  * backend_simulate_install_files
+  */
+static void
+backend_simulate_install_files (PkBackend *backend, gchar **full_paths)
+{
+	pk_backend_thread_create (backend, backend_install_files_thread);
+}
+
 static gboolean
 backend_get_update_detail_thread (PkBackend *backend)
 {
@@ -1086,6 +1084,15 @@ backend_install_packages (PkBackend *backend, gboolean only_trusted, gchar **pac
 	pk_backend_thread_create (backend, backend_install_packages_thread);
 }
 
+/**
+ * backend_simulate_install_packages:
+ */
+static void
+backend_simulate_install_packages (PkBackend *backend, gchar **package_ids)
+{
+	pk_backend_thread_create (backend, backend_install_packages_thread);
+}
+
 static gboolean
 backend_install_signature_thread (PkBackend *backend)
 {
@@ -1110,7 +1117,6 @@ static gboolean
 backend_remove_packages_thread (PkBackend *backend)
 {
 	gchar **package_ids;
-	gboolean simulate;
 	std::vector<zypp::PoolItem> *items = new std::vector<zypp::PoolItem> ();
 
 	pk_backend_set_status (backend, PK_STATUS_ENUM_REMOVE);
@@ -1126,7 +1132,6 @@ backend_remove_packages_thread (PkBackend *backend)
 	target->load ();
 	pk_backend_set_percentage (backend, 10);
 
-	simulate = pk_backend_get_bool (backend, "simulate");
 	package_ids = pk_backend_get_strv (backend, "package_ids");
 	if (!pk_package_ids_check (package_ids)) {
 		return zypp_backend_finished_error (
@@ -1152,7 +1157,7 @@ backend_remove_packages_thread (PkBackend *backend)
 
 	try
 	{
-		if (!zypp_perform_execution (backend, REMOVE, TRUE, simulate)) {
+		if (!zypp_perform_execution (backend, REMOVE, TRUE)) {
 			//reset the status of the marked packages
 			for (std::vector<zypp::PoolItem>::iterator it = items->begin (); it != items->end (); it++) {
 				it->statusReset();
@@ -1184,15 +1189,12 @@ backend_remove_packages_thread (PkBackend *backend)
 static void
 backend_remove_packages (PkBackend *backend, gchar **package_ids, gboolean allow_deps, gboolean autoremove)
 {
-	pk_backend_set_bool (backend, "simulate", false);
-	pk_backend_set_uint (backend, "allow_deps", allow_deps == TRUE ? DEPS_ALLOW : DEPS_NO_ALLOW);
 	pk_backend_thread_create (backend, backend_remove_packages_thread);
 }
 
 static void
 backend_simulate_remove_packages (PkBackend *backend, gchar **packages, gboolean autoremove)
 {
-	pk_backend_set_bool (backend, "simulate", true);
 	pk_backend_thread_create (backend, backend_remove_packages_thread);
 }
 
@@ -1621,12 +1623,21 @@ backend_update_packages_thread (PkBackend *backend)
 }
 
 /**
-  *backend_update_packages
+  * backend_update_packages
+  */
+static void
+backend_update_packages (PkBackend *backend, gboolean only_trusted, gchar **package_ids)
+{
+	pk_backend_thread_create (backend, backend_update_packages_thread);
+}
+
+/**
+  * backend_simulate_update_packages
   */
 static void
-backend_update_packages(PkBackend *backend, gboolean only_trusted, gchar **package_ids)
+backend_simulate_update_packages (PkBackend *backend, gchar **package_ids)
 {
-	pk_backend_thread_create(backend, backend_update_packages_thread);
+	pk_backend_thread_create (backend, backend_update_packages_thread);
 }
 
 static gboolean
@@ -1877,9 +1888,9 @@ extern "C" PK_BACKEND_OPTIONS (
 	backend_update_packages,		/* update_packages */
 	backend_update_system,			/* update_system */
 	backend_what_provides,			/* what_provides */
-	NULL,					/* simulate_install_files */
-	NULL,					/* simulate_install_packages */
+	backend_simulate_install_files,		/* simulate_install_files */
+	backend_simulate_install_packages,	/* simulate_install_packages */
 	backend_simulate_remove_packages,	/* simulate_remove_packages */
-	NULL					/* simulate_update_packages */
+	backend_simulate_update_packages	/* simulate_update_packages */
 );
 
diff --git a/backends/zypp/zypp-events.h b/backends/zypp/zypp-events.h
index b651b00..2dca996 100644
--- a/backends/zypp/zypp-events.h
+++ b/backends/zypp/zypp-events.h
@@ -244,7 +244,7 @@ struct RemoveResolvableReportReceiver : public zypp::callback::ReceiveReport<zyp
 	virtual void finish (zypp::Resolvable::constPtr resolvable, Error error, const std::string &reason)
 	{
 		if (_package_id != NULL) {
-			pk_backend_package (_backend, PK_INFO_ENUM_AVAILABLE, _package_id, "");
+			pk_backend_package (_backend, PK_INFO_ENUM_FINISHED, _package_id, "");
 			clear_package_id ();
 		}
 	}
diff --git a/backends/zypp/zypp-utils.cpp b/backends/zypp/zypp-utils.cpp
index c7efaaf..772a783 100644
--- a/backends/zypp/zypp-utils.cpp
+++ b/backends/zypp/zypp-utils.cpp
@@ -729,10 +729,10 @@ zypp_get_restart (PkRestartEnum &restart, zypp::Patch::constPtr patch)
 }
 
 gboolean
-zypp_perform_execution (PkBackend *backend, PerformType type,
-			gboolean force, gboolean simulate)
+zypp_perform_execution (PkBackend *backend, PerformType type, gboolean force)
 {
 	gboolean ret = FALSE;
+	gboolean simulate = pk_backend_get_bool (backend, "hint:simulate");
 
         try {
                 zypp::ZYpp::Ptr zypp = get_zypp ();
diff --git a/backends/zypp/zypp-utils.h b/backends/zypp/zypp-utils.h
index ad13a66..f432129 100644
--- a/backends/zypp/zypp-utils.h
+++ b/backends/zypp/zypp-utils.h
@@ -179,10 +179,9 @@ std::set<zypp::PoolItem> * zypp_get_patches ();
 gboolean zypp_get_restart (PkRestartEnum &restart, zypp::Patch::constPtr patch);
 
 /**
-  * perform changes in pool to the system
+  * simulate, or perform changes in pool to the system
   */
-gboolean zypp_perform_execution (PkBackend *backend, PerformType type,
-				 gboolean force, gboolean simulate = FALSE);
+gboolean zypp_perform_execution (PkBackend *backend, PerformType type, gboolean force);
 
 /**
  * should we omit a solvable from a result because of filtering ?
commit fd0e004814e659cd471216c4fdf8b1393a5229e4
Author: Michael Meeks <michael.meeks at novell.com>
Date:   Wed May 5 16:35:25 2010 +0100

    add hint:simulate boolean on the backend, set for all simulation
    methods, to increase code re-use and simplicity in the backends.

diff --git a/src/pk-backend.c b/src/pk-backend.c
index 168d63e..2fb6c15 100644
--- a/src/pk-backend.c
+++ b/src/pk-backend.c
@@ -2838,6 +2838,7 @@ pk_backend_install_packages (PkBackend *backend, gboolean only_trusted, gchar **
 	pk_backend_set_role_internal (backend, PK_ROLE_ENUM_INSTALL_PACKAGES);
 	pk_store_set_bool (backend->priv->store, "only_trusted", only_trusted);
 	pk_store_set_strv (backend->priv->store, "package_ids", package_ids);
+	pk_backend_set_bool (backend, "hint:simulate", false);
 	backend->priv->desc->install_packages (backend, only_trusted, package_ids);
 }
 
@@ -2864,6 +2865,7 @@ pk_backend_install_files (PkBackend *backend, gboolean only_trusted, gchar **ful
 	pk_backend_set_role_internal (backend, PK_ROLE_ENUM_INSTALL_FILES);
 	pk_store_set_bool (backend->priv->store, "only_trusted", only_trusted);
 	pk_store_set_strv (backend->priv->store, "full_paths", full_paths);
+	pk_backend_set_bool (backend, "hint:simulate", false);
 	backend->priv->desc->install_files (backend, only_trusted, full_paths);
 }
 
@@ -2890,6 +2892,7 @@ pk_backend_remove_packages (PkBackend *backend, gchar **package_ids, gboolean al
 	pk_store_set_strv (backend->priv->store, "package_ids", package_ids);
 	pk_store_set_bool (backend->priv->store, "allow_deps", allow_deps);
 	pk_store_set_bool (backend->priv->store, "autoremove", autoremove);
+	pk_backend_set_bool (backend, "hint:simulate", false);
 	backend->priv->desc->remove_packages (backend, package_ids, allow_deps, autoremove);
 }
 
@@ -2980,6 +2983,7 @@ pk_backend_update_packages (PkBackend *backend, gboolean only_trusted, gchar **p
 	pk_backend_set_role_internal (backend, PK_ROLE_ENUM_UPDATE_PACKAGES);
 	pk_store_set_bool (backend->priv->store, "only_trusted", only_trusted);
 	pk_store_set_strv (backend->priv->store, "package_ids", package_ids);
+	pk_backend_set_bool (backend, "hint:simulate", false);
 	backend->priv->desc->update_packages (backend, only_trusted, package_ids);
 }
 
@@ -2992,6 +2996,7 @@ pk_backend_update_system (PkBackend *backend, gboolean only_trusted)
 	g_return_if_fail (PK_IS_BACKEND (backend));
 	pk_backend_set_role_internal (backend, PK_ROLE_ENUM_UPDATE_SYSTEM);
 	pk_store_set_bool (backend->priv->store, "only_trusted", only_trusted);
+	pk_backend_set_bool (backend, "hint:simulate", false);
 	backend->priv->desc->update_system (backend, only_trusted);
 }
 
@@ -3069,6 +3074,7 @@ pk_backend_simulate_install_files (PkBackend *backend, gchar **full_paths)
 	g_return_if_fail (PK_IS_BACKEND (backend));
 	pk_backend_set_role_internal (backend, PK_ROLE_ENUM_SIMULATE_INSTALL_FILES);
 	pk_store_set_strv (backend->priv->store, "full_paths", full_paths);
+	pk_backend_set_bool (backend, "hint:simulate", true);
 	backend->priv->desc->simulate_install_files (backend, full_paths);
 }
 
@@ -3081,6 +3087,7 @@ pk_backend_simulate_install_packages (PkBackend *backend, gchar **package_ids)
 	g_return_if_fail (PK_IS_BACKEND (backend));
 	pk_backend_set_role_internal (backend, PK_ROLE_ENUM_SIMULATE_INSTALL_PACKAGES);
 	pk_store_set_strv (backend->priv->store, "package_ids", package_ids);
+	pk_backend_set_bool (backend, "hint:simulate", true);
 	backend->priv->desc->simulate_install_packages (backend, package_ids);
 }
 
@@ -3094,6 +3101,7 @@ pk_backend_simulate_remove_packages (PkBackend *backend, gchar **package_ids, gb
 	pk_backend_set_role_internal (backend, PK_ROLE_ENUM_SIMULATE_REMOVE_PACKAGES);
 	pk_store_set_strv (backend->priv->store, "package_ids", package_ids);
 	pk_store_set_bool (backend->priv->store, "autoremove", autoremove);
+	pk_backend_set_bool (backend, "hint:simulate", true);
 	backend->priv->desc->simulate_remove_packages (backend, package_ids, autoremove);
 }
 
@@ -3106,6 +3114,7 @@ pk_backend_simulate_update_packages (PkBackend *backend, gchar **package_ids)
 	g_return_if_fail (PK_IS_BACKEND (backend));
 	pk_backend_set_role_internal (backend, PK_ROLE_ENUM_SIMULATE_UPDATE_PACKAGES);
 	pk_store_set_strv (backend->priv->store, "package_ids", package_ids);
+	pk_backend_set_bool (backend, "hint:simulate", true);
 	backend->priv->desc->simulate_update_packages (backend, package_ids);
 }
 
commit 6b6217db4451d2a7f3c1a0e506e4b0902fef8e02
Author: Richard Hughes <richard at hughsie.com>
Date:   Wed May 5 15:33:19 2010 +0100

    yum: Move the list of infrastructure packages that are updated first to the config file

diff --git a/backends/yum/Yum.conf b/backends/yum/Yum.conf
index 87b42e6..2985c7a 100644
--- a/backends/yum/Yum.conf
+++ b/backends/yum/Yum.conf
@@ -25,6 +25,18 @@ DisabledPlugins=rpm-warm-cache;remove-with-leaves;auto-update-debuginfo
 # default=yum;rpm;glibc;PackageKit
 SystemPackages=yum;rpm;glibc;PackageKit
 
+# Packages that should be updated before any other packages
+#
+# Some packages like rpm and yum actually update the system, and should
+# probably be installed first. This prevents bugs in these components from
+# blocking the auto-install of updates.
+#
+# If these packages depend on any other updates, then these are considered
+# infrastructure packages too, and are included in the update viewer.
+#
+# default=PackageKit;yum;rpm
+InfrastructurePackages=PackageKit;yum;rpm
+
 # Yum is slow, and we can use Zif to accelerate some simple transactions
 #
 # Yum is written in python, and we therefor have to execute a new process and
diff --git a/backends/yum/yumBackend.py b/backends/yum/yumBackend.py
index 529e680..f6bb16d 100755
--- a/backends/yum/yumBackend.py
+++ b/backends/yum/yumBackend.py
@@ -238,6 +238,7 @@ class PackageKitYumBackend(PackageKitBaseBackend, PackagekitPackage):
         try:
             config.read('/etc/PackageKit/Yum.conf')
             self.system_packages = config.get('Backend', 'SystemPackages').split(';')
+            self.infra_packages = config.get('Backend', 'InfrastructurePackages').split(';')
         except Exception, e:
             raise PkError(ERROR_REPO_CONFIGURATION_ERROR, "Failed to load Yum.conf: %s" % _to_unicode(e))
 
@@ -2561,8 +2562,7 @@ class PackageKitYumBackend(PackageKitBaseBackend, PackagekitPackage):
         # some packages should be updated before the others
         infra_pkgs = []
         for pkg in pkgs:
-            infra_packages = ['PackageKit', 'yum', 'rpm']
-            if pkg.name in infra_packages or pkg.name.partition('-')[0] in infra_packages:
+            if pkg.name in self.infra_packages or pkg.name.partition('-')[0] in self.infra_packages:
                 infra_pkgs.append(pkg)
         if len(infra_pkgs) > 0:
             if len(infra_pkgs) < len(pkgs):
commit 3ee0c8596761fc7c93498cf48642c627566d281b
Author: Richard Hughes <richard at hughsie.com>
Date:   Wed May 5 15:27:08 2010 +0100

    yum: Move the list of system packages that cannot be removed to the config file

diff --git a/backends/yum/Yum.conf b/backends/yum/Yum.conf
index 2cfb6dd..87b42e6 100644
--- a/backends/yum/Yum.conf
+++ b/backends/yum/Yum.conf
@@ -13,6 +13,18 @@
 # default=rpm-warm-cache;remove-with-leaves;auto-update-debuginfo
 DisabledPlugins=rpm-warm-cache;remove-with-leaves;auto-update-debuginfo
 
+# Packages that should not be removable with PackageKit
+#
+# This simple package list specifies packages that PackageKit cannot remove
+# in fear of breaking the users system.
+#
+# It can still install or update these packages (of which the latter may
+# actually remove the old package just after installing a new one) and this
+# list just stops an errant "pkcon remove glibc" from destroying the system.
+#
+# default=yum;rpm;glibc;PackageKit
+SystemPackages=yum;rpm;glibc;PackageKit
+
 # Yum is slow, and we can use Zif to accelerate some simple transactions
 #
 # Yum is written in python, and we therefor have to execute a new process and
diff --git a/backends/yum/yumBackend.py b/backends/yum/yumBackend.py
index c88e0b7..529e680 100755
--- a/backends/yum/yumBackend.py
+++ b/backends/yum/yumBackend.py
@@ -233,6 +233,14 @@ class PackageKitYumBackend(PackageKitBaseBackend, PackagekitPackage):
         except PkError, e:
             self.error(e.code, e.details)
 
+        # load the config file
+        config = ConfigParser.ConfigParser()
+        try:
+            config.read('/etc/PackageKit/Yum.conf')
+            self.system_packages = config.get('Backend', 'SystemPackages').split(';')
+        except Exception, e:
+            raise PkError(ERROR_REPO_CONFIGURATION_ERROR, "Failed to load Yum.conf: %s" % _to_unicode(e))
+
         # get the lock early
         if lock:
             self.doLock()
@@ -2327,8 +2335,7 @@ class PackageKitYumBackend(PackageKitBaseBackend, PackagekitPackage):
             else:
                 for txmbr in self.yumbase.tsInfo:
                     pkg = txmbr.po
-                    system_packages = ['yum', 'rpm', 'glibc', 'PackageKit']
-                    if pkg.name in system_packages:
+                    if pkg.name in self.system_packages:
                         self.error(ERROR_CANNOT_REMOVE_SYSTEM_PACKAGE, "The package %s is essential to correct operation and cannot be removed using this tool." % pkg.name, exit=False)
                         return
             try:
commit 69454c649087495d5850a3817abfc18deb78d370
Author: Richard Hughes <richard at hughsie.com>
Date:   Wed May 5 15:14:08 2010 +0100

    Ensure the daemon emits Message() signals when replaying the cached GetUpdates data

diff --git a/src/pk-cache.c b/src/pk-cache.c
index 207c8f8..8272b32 100644
--- a/src/pk-cache.c
+++ b/src/pk-cache.c
@@ -37,50 +37,65 @@
 struct PkCachePrivate
 {
 	PkConf			*conf;
-	gboolean		 use_update_cache;
-	GPtrArray		*updates_cache;
+	gboolean		 use_cache;
+	PkResults		*get_updates;
 };
 
 G_DEFINE_TYPE (PkCache, pk_cache, G_TYPE_OBJECT)
 static gpointer pk_cache_object = NULL;
 
 /**
- * pk_cache_get_updates:
+ * pk_cache_get_results:
  **/
-GPtrArray *
-pk_cache_get_updates (PkCache *cache)
+PkResults *
+pk_cache_get_results (PkCache *cache, PkRoleEnum role)
 {
 	g_return_val_if_fail (PK_IS_CACHE (cache), NULL);
 
 	/* do not use */
-	if (!cache->priv->use_update_cache) {
+	if (!cache->priv->use_cache) {
 		egg_debug ("not using cache");
 		return NULL;
 	}
 
-	return cache->priv->updates_cache;
+	/* only support GetUpdates */
+	if (role != PK_ROLE_ENUM_GET_UPDATES) {
+		egg_debug ("only caching update lists");
+		return FALSE;
+	}
+
+	return cache->priv->get_updates;
 }
 
 /**
- * pk_cache_set_updates:
+ * pk_cache_set_results:
+ *
+ * If you add to this method to support other calls than GetUpdates then be sure
+ * to add the required signals to pk_transaction_try_emit_cache().
  **/
 gboolean
-pk_cache_set_updates (PkCache *cache, GPtrArray *list)
+pk_cache_set_results (PkCache *cache, PkRoleEnum role, PkResults *results)
 {
 	g_return_val_if_fail (PK_IS_CACHE (cache), FALSE);
-	g_return_val_if_fail (list != NULL, FALSE);
+	g_return_val_if_fail (results != NULL, FALSE);
 
 	/* do not use */
-	if (!cache->priv->use_update_cache) {
+	if (!cache->priv->use_cache) {
 		egg_debug ("not using cache");
 		return FALSE;
 	}
 
+	/* only support GetUpdates */
+	if (role != PK_ROLE_ENUM_GET_UPDATES) {
+		egg_debug ("only caching update lists");
+		return FALSE;
+	}
+
 	/* do this in case we have old data */
 	pk_cache_invalidate (cache);
 
 	egg_debug ("reffing updates cache");
-	cache->priv->updates_cache = g_ptr_array_ref (list);
+	cache->priv->get_updates = g_object_ref (results);
 	return TRUE;
 }
 
@@ -93,9 +108,9 @@ pk_cache_invalidate (PkCache *cache)
 	g_return_val_if_fail (PK_IS_CACHE (cache), FALSE);
 
 	egg_debug ("unreffing updates cache");
-	if (cache->priv->updates_cache != NULL) {
-		g_ptr_array_unref (cache->priv->updates_cache);
-		cache->priv->updates_cache = NULL;
+	if (cache->priv->get_updates != NULL) {
+		g_object_unref (cache->priv->get_updates);
+		cache->priv->get_updates = NULL;
 	}
 	return TRUE;
 }
@@ -110,8 +125,8 @@ pk_cache_finalize (GObject *object)
 	g_return_if_fail (PK_IS_CACHE (object));
 	cache = PK_CACHE (object);
 
-	if (cache->priv->updates_cache != NULL)
-		g_ptr_array_unref (cache->priv->updates_cache);
+	if (cache->priv->get_updates != NULL)
+		g_object_unref (cache->priv->get_updates);
 
 	G_OBJECT_CLASS (pk_cache_parent_class)->finalize (object);
 }
@@ -138,9 +153,9 @@ static void
 pk_cache_init (PkCache *cache)
 {
 	cache->priv = PK_CACHE_GET_PRIVATE (cache);
-	cache->priv->updates_cache = NULL;
+	cache->priv->get_updates = NULL;
 	cache->priv->conf = pk_conf_new ();
-	cache->priv->use_update_cache = pk_conf_get_bool (cache->priv->conf, "UseUpdateCache");
+	cache->priv->use_cache = pk_conf_get_bool (cache->priv->conf, "UseUpdateCache");
 }
 
 /**
diff --git a/src/pk-cache.h b/src/pk-cache.h
index f5366a5..391d5e9 100644
--- a/src/pk-cache.h
+++ b/src/pk-cache.h
@@ -23,6 +23,8 @@
 #define __PK_CACHE_H
 
 #include <glib-object.h>
+#include <packagekit-glib2/pk-results.h>
+#include <packagekit-glib2/pk-enum.h>
 
 G_BEGIN_DECLS
 
@@ -49,9 +51,11 @@ typedef struct
 GType		 pk_cache_get_type		(void);
 PkCache		*pk_cache_new			(void);
 
-GPtrArray	*pk_cache_get_updates		(PkCache	*cache);
-gboolean	 pk_cache_set_updates		(PkCache	*cache,
-						 GPtrArray	*list);
+PkResults	*pk_cache_get_results		(PkCache	*cache,
+						 PkRoleEnum	 role);
+gboolean	 pk_cache_set_results		(PkCache	*cache,
+						 PkRoleEnum	 role,
+						 PkResults	*results);
 gboolean	 pk_cache_invalidate		(PkCache	*cache);
 
 G_END_DECLS
diff --git a/src/pk-transaction.c b/src/pk-transaction.c
index d4da443..bd60170 100644
--- a/src/pk-transaction.c
+++ b/src/pk-transaction.c
@@ -300,11 +300,11 @@ static gboolean
 pk_transaction_finish_invalidate_caches (PkTransaction *transaction)
 {
 	gchar *transaction_id;
-	GPtrArray *array;
+	PkTransactionPrivate *priv = transaction->priv;
 
 	g_return_val_if_fail (PK_IS_TRANSACTION (transaction), FALSE);
 
-	g_object_get (transaction->priv->backend,
+	g_object_get (priv->backend,
 		      "transaction-id", &transaction_id,
 		      NULL);
 	if (transaction_id == NULL) {
@@ -312,27 +312,23 @@ pk_transaction_finish_invalidate_caches (PkTransaction *transaction)
 		return FALSE;
 	}
 
-	/* copy this into the cache if we are getting updates */
-	if (transaction->priv->role == PK_ROLE_ENUM_GET_UPDATES) {
-		array = pk_results_get_package_array (transaction->priv->results);
-		pk_cache_set_updates (transaction->priv->cache, array);
-		g_ptr_array_unref (array);
-	}
+	/* copy this into the cache */
+	pk_cache_set_results (priv->cache, priv->role, priv->results);
 
 	/* could the update list have changed? */
-	if (transaction->priv->role == PK_ROLE_ENUM_UPDATE_SYSTEM ||
-	    transaction->priv->role == PK_ROLE_ENUM_UPDATE_PACKAGES ||
-	    transaction->priv->role == PK_ROLE_ENUM_REMOVE_PACKAGES ||
-	    transaction->priv->role == PK_ROLE_ENUM_REPO_ENABLE ||
-	    transaction->priv->role == PK_ROLE_ENUM_REPO_SET_DATA ||
-	    transaction->priv->role == PK_ROLE_ENUM_REFRESH_CACHE) {
+	if (priv->role == PK_ROLE_ENUM_UPDATE_SYSTEM ||
+	    priv->role == PK_ROLE_ENUM_UPDATE_PACKAGES ||
+	    priv->role == PK_ROLE_ENUM_REMOVE_PACKAGES ||
+	    priv->role == PK_ROLE_ENUM_REPO_ENABLE ||
+	    priv->role == PK_ROLE_ENUM_REPO_SET_DATA ||
+	    priv->role == PK_ROLE_ENUM_REFRESH_CACHE) {
 
 		/* the cached list is no longer valid */
 		egg_debug ("invalidating caches");
-		pk_cache_invalidate (transaction->priv->cache);
+		pk_cache_invalidate (priv->cache);
 
 		/* this needs to be done after a small delay */
-		pk_notify_wait_updates_changed (transaction->priv->notify,
+		pk_notify_wait_updates_changed (priv->notify,
 						PK_TRANSACTION_UPDATES_CHANGED_TIMEOUT);
 	}
 	g_free (transaction_id);
@@ -850,6 +846,9 @@ pk_transaction_finished_cb (PkBackend *backend, PkExitEnum exit_enum, PkTransact
 		pk_transaction_extra_clear_firmware_requests (transaction->priv->transaction_extra);
 	}
 
+	/* save this so we know if the cache is valid */
+	pk_results_set_exit_code (transaction->priv->results, exit_enum);
+
 	/* if we did not send this, ensure the GUI has the right state */
 	if (transaction->priv->allow_cancel)
 		pk_transaction_allow_cancel_emit (transaction, FALSE);
@@ -1431,8 +1430,9 @@ pk_transaction_update_detail_cb (PkBackend *backend, PkUpdateDetail *item, PkTra
 static gboolean
 pk_transaction_pre_transaction_checks (PkTransaction *transaction, gchar **package_ids, GError **error)
 {
-	GPtrArray *updates;
+	GPtrArray *updates = NULL;
 	PkPackage *item;
+	PkResults *results;
 	guint i;
 	guint j = 0;
 	guint length = 0;
@@ -1441,43 +1441,45 @@ pk_transaction_pre_transaction_checks (PkTransaction *transaction, gchar **packa
 	gchar **package_ids_security = NULL;
 	gchar *package_id;
 	PkInfoEnum info;
+	PkTransactionPrivate *priv = transaction->priv;
 
 	/* only do this for update actions, FIXME: need to get cached updtae list for update */
-	if (transaction->priv->role == PK_ROLE_ENUM_UPDATE_PACKAGES) {
-		success = pk_transaction_extra_applications_are_running (transaction->priv->transaction_extra, package_ids, error);
+	if (priv->role == PK_ROLE_ENUM_UPDATE_PACKAGES) {
+		success = pk_transaction_extra_applications_are_running (priv->transaction_extra, package_ids, error);
 		if (!success)
 			goto out;
 	}
 
 	/* check we have anything to process */
 	if (package_ids == NULL) {
-		egg_debug ("no package_ids for %s", pk_role_enum_to_string (transaction->priv->role));
+		egg_debug ("no package_ids for %s", pk_role_enum_to_string (priv->role));
 		goto out;
 	}
 
 	/* only do this for update actions */
-	if (transaction->priv->role != PK_ROLE_ENUM_UPDATE_SYSTEM &&
-	    transaction->priv->role != PK_ROLE_ENUM_UPDATE_PACKAGES &&
-	    transaction->priv->role != PK_ROLE_ENUM_INSTALL_PACKAGES) {
+	if (priv->role != PK_ROLE_ENUM_UPDATE_SYSTEM &&
+	    priv->role != PK_ROLE_ENUM_UPDATE_PACKAGES &&
+	    priv->role != PK_ROLE_ENUM_INSTALL_PACKAGES) {
 		egg_debug ("doing nothing, as not update or install");
 		goto out;
 	}
 
 	/* do we want to enable this codepath? */
-	ret = pk_conf_get_bool (transaction->priv->conf, "CheckSharedLibrariesInUse");
+	ret = pk_conf_get_bool (priv->conf, "CheckSharedLibrariesInUse");
 	if (!ret) {
 		egg_warning ("not checking for library restarts");
 		goto out;
 	}
 
 	/* do we have a cache */
-	updates = pk_cache_get_updates (transaction->priv->cache);
-	if (updates == NULL) {
+	results = pk_cache_get_results (priv->cache, PK_ROLE_ENUM_GET_UPDATES);
+	if (results == NULL) {
 		egg_warning ("no updates cache");
 		goto out;
 	}
 
 	/* find security update packages */
+	updates = pk_results_get_package_array (results);
 	for (i=0; i<updates->len; i++) {
 		item = g_ptr_array_index (updates, i);
 		g_object_get (item,
@@ -1512,7 +1514,7 @@ pk_transaction_pre_transaction_checks (PkTransaction *transaction, gchar **packa
 
 
 	/* is a security update we are installing */
-	if (transaction->priv->role == PK_ROLE_ENUM_INSTALL_PACKAGES) {
+	if (priv->role == PK_ROLE_ENUM_INSTALL_PACKAGES) {
 		ret = FALSE;
 
 		/* do any of the packages we are updating match */
@@ -1533,12 +1535,14 @@ pk_transaction_pre_transaction_checks (PkTransaction *transaction, gchar **packa
 	}
 
 	/* find files in security updates */
-	ret = pk_transaction_extra_check_library_restart_pre (transaction->priv->transaction_extra, package_ids_security);
+	ret = pk_transaction_extra_check_library_restart_pre (priv->transaction_extra, package_ids_security);
 	if (!ret) {
 		egg_debug ("could not check the library list");
 		goto out;
 	}
 out:
+	if (updates != NULL)
+		g_ptr_array_unref (updates);
 	g_strfreev (package_ids_security);
 	return success;
 }
@@ -1554,43 +1558,44 @@ pk_transaction_set_session_state (PkTransaction *transaction, GError **error)
 	gchar *proxy_http = NULL;
 	gchar *proxy_ftp = NULL;
 	gchar *root = NULL;
+	PkTransactionPrivate *priv = transaction->priv;
 
 	/* get session */
-	session = pk_dbus_get_session (transaction->priv->dbus, transaction->priv->sender);
+	session = pk_dbus_get_session (priv->dbus, priv->sender);
 	if (session == NULL) {
 		g_set_error_literal (error, 1, 0, "failed to get the session");
 		goto out;
 	}
 
 	/* get from database */
-	ret = pk_transaction_db_get_proxy (transaction->priv->transaction_db, transaction->priv->uid, session, &proxy_http, &proxy_ftp);
+	ret = pk_transaction_db_get_proxy (priv->transaction_db, priv->uid, session, &proxy_http, &proxy_ftp);
 	if (!ret) {
 		g_set_error_literal (error, 1, 0, "failed to get the proxy from the database");
 		goto out;
 	}
 
 	/* try to set the new proxy */
-	ret = pk_backend_set_proxy (transaction->priv->backend, proxy_http, proxy_ftp);
+	ret = pk_backend_set_proxy (priv->backend, proxy_http, proxy_ftp);
 	if (!ret) {
 		g_set_error_literal (error, 1, 0, "failed to set the proxy");
 		goto out;
 	}
 
 	/* get from database */
-	ret = pk_transaction_db_get_root (transaction->priv->transaction_db, transaction->priv->uid, session, &root);
+	ret = pk_transaction_db_get_root (priv->transaction_db, priv->uid, session, &root);
 	if (!ret) {
 		g_set_error_literal (error, 1, 0, "failed to get the root from the database");
 		goto out;
 	}
 
 	/* try to set the new proxy */
-	ret = pk_backend_set_root (transaction->priv->backend, root);
+	ret = pk_backend_set_root (priv->backend, root);
 	if (!ret) {
 		g_set_error_literal (error, 1, 0, "failed to set the root");
 		goto out;
 	}
 	egg_debug ("using http_proxy=%s, ftp_proxy=%s, root=%s for %i:%s",
-		   proxy_http, proxy_ftp, root, transaction->priv->uid, session);
+		   proxy_http, proxy_ftp, root, priv->uid, session);
 out:
 	g_free (proxy_http);
 	g_free (proxy_ftp);
@@ -1625,10 +1630,10 @@ pk_transaction_set_running (PkTransaction *transaction)
 	PkTransactionPrivate *priv = PK_TRANSACTION_GET_PRIVATE (transaction);
 
 	g_return_val_if_fail (PK_IS_TRANSACTION (transaction), FALSE);
-	g_return_val_if_fail (transaction->priv->tid != NULL, FALSE);
+	g_return_val_if_fail (priv->tid != NULL, FALSE);
 
 	/* prepare for use; the transaction list ensures this is safe */
-	pk_backend_reset (transaction->priv->backend);
+	pk_backend_reset (priv->backend);
 
 	/* assign */
 	g_object_set (priv->backend,
@@ -1679,68 +1684,68 @@ pk_transaction_set_running (PkTransaction *transaction)
 	}
 
 	/* might have to reset again if we used the backend */
-	pk_backend_reset (transaction->priv->backend);
+	pk_backend_reset (priv->backend);
 
 	/* connect up the signals */
-	transaction->priv->signal_allow_cancel =
-		g_signal_connect (transaction->priv->backend, "allow-cancel",
+	priv->signal_allow_cancel =
+		g_signal_connect (priv->backend, "allow-cancel",
 				  G_CALLBACK (pk_transaction_allow_cancel_cb), transaction);
-	transaction->priv->signal_details =
-		g_signal_connect (transaction->priv->backend, "details",
+	priv->signal_details =
+		g_signal_connect (priv->backend, "details",
 				  G_CALLBACK (pk_transaction_details_cb), transaction);
-	transaction->priv->signal_error_code =
-		g_signal_connect (transaction->priv->backend, "error-code",
+	priv->signal_error_code =
+		g_signal_connect (priv->backend, "error-code",
 				  G_CALLBACK (pk_transaction_error_code_cb), transaction);
-	transaction->priv->signal_files =
-		g_signal_connect (transaction->priv->backend, "files",
+	priv->signal_files =
+		g_signal_connect (priv->backend, "files",
 				  G_CALLBACK (pk_transaction_files_cb), transaction);
-	transaction->priv->signal_distro_upgrade =
-		g_signal_connect (transaction->priv->backend, "distro-upgrade",
+	priv->signal_distro_upgrade =
+		g_signal_connect (priv->backend, "distro-upgrade",
 				  G_CALLBACK (pk_transaction_distro_upgrade_cb), transaction);
-	transaction->priv->signal_finished =
-		g_signal_connect (transaction->priv->backend, "finished",
+	priv->signal_finished =
+		g_signal_connect (priv->backend, "finished",
 				  G_CALLBACK (pk_transaction_finished_cb), transaction);
-	transaction->priv->signal_message =
-		g_signal_connect (transaction->priv->backend, "message",
+	priv->signal_message =
+		g_signal_connect (priv->backend, "message",
 				  G_CALLBACK (pk_transaction_message_cb), transaction);
-	transaction->priv->signal_package =
-		g_signal_connect (transaction->priv->backend, "package",
+	priv->signal_package =
+		g_signal_connect (priv->backend, "package",
 				  G_CALLBACK (pk_transaction_package_cb), transaction);
-	transaction->priv->signal_progress_changed =
-		g_signal_connect (transaction->priv->backend, "progress-changed",
+	priv->signal_progress_changed =
+		g_signal_connect (priv->backend, "progress-changed",
 				  G_CALLBACK (pk_transaction_progress_changed_cb), transaction);
-	transaction->priv->signal_repo_detail =
-		g_signal_connect (transaction->priv->backend, "repo-detail",
+	priv->signal_repo_detail =
+		g_signal_connect (priv->backend, "repo-detail",
 				  G_CALLBACK (pk_transaction_repo_detail_cb), transaction);
-	transaction->priv->signal_repo_signature_required =
-		g_signal_connect (transaction->priv->backend, "repo-signature-required",
+	priv->signal_repo_signature_required =
+		g_signal_connect (priv->backend, "repo-signature-required",
 				  G_CALLBACK (pk_transaction_repo_signature_required_cb), transaction);
-	transaction->priv->signal_eula_required =
-		g_signal_connect (transaction->priv->backend, "eula-required",
+	priv->signal_eula_required =
+		g_signal_connect (priv->backend, "eula-required",
 				  G_CALLBACK (pk_transaction_eula_required_cb), transaction);
-	transaction->priv->signal_media_change_required =
-		g_signal_connect (transaction->priv->backend, "media-change-required",
+	priv->signal_media_change_required =
+		g_signal_connect (priv->backend, "media-change-required",
 				  G_CALLBACK (pk_transaction_media_change_required_cb), transaction);
-	transaction->priv->signal_require_restart =
-		g_signal_connect (transaction->priv->backend, "require-restart",
+	priv->signal_require_restart =
+		g_signal_connect (priv->backend, "require-restart",
 				  G_CALLBACK (pk_transaction_require_restart_cb), transaction);
-	transaction->priv->signal_status_changed =
-		g_signal_connect (transaction->priv->backend, "status-changed",
+	priv->signal_status_changed =
+		g_signal_connect (priv->backend, "status-changed",
 				  G_CALLBACK (pk_transaction_status_changed_cb), transaction);
-	transaction->priv->signal_update_detail =
-		g_signal_connect (transaction->priv->backend, "update-detail",
+	priv->signal_update_detail =
+		g_signal_connect (priv->backend, "update-detail",
 				  G_CALLBACK (pk_transaction_update_detail_cb), transaction);
-	transaction->priv->signal_category =
-		g_signal_connect (transaction->priv->backend, "category",
+	priv->signal_category =
+		g_signal_connect (priv->backend, "category",
 				  G_CALLBACK (pk_transaction_category_cb), transaction);
-	transaction->priv->signal_speed =
-		g_signal_connect (transaction->priv->backend, "notify::speed",
+	priv->signal_speed =
+		g_signal_connect (priv->backend, "notify::speed",
 				  G_CALLBACK (pk_transaction_speed_cb), transaction);
 
 	/* mark running */
-	transaction->priv->running = TRUE;
-	transaction->priv->has_been_run = TRUE;
-	transaction->priv->allow_cancel = FALSE;
+	priv->running = TRUE;
+	priv->has_been_run = TRUE;
+	priv->allow_cancel = FALSE;
 
 	/* reset after the pre-transaction checks */
 	pk_backend_set_percentage (priv->backend, PK_BACKEND_PERCENTAGE_INVALID);
@@ -1933,21 +1938,22 @@ G_GNUC_WARN_UNUSED_RESULT static gboolean
 pk_transaction_commit (PkTransaction *transaction)
 {
 	gboolean ret;
+	PkTransactionPrivate *priv = transaction->priv;
 
 	g_return_val_if_fail (PK_IS_TRANSACTION (transaction), FALSE);
-	g_return_val_if_fail (transaction->priv->tid != NULL, FALSE);
+	g_return_val_if_fail (priv->tid != NULL, FALSE);
 
 	/* set the idle really early as this affects scheduling */
-	if (transaction->priv->background == PK_HINT_ENUM_TRUE ||
-	    transaction->priv->background == PK_HINT_ENUM_FALSE) {
-		pk_transaction_list_set_background (transaction->priv->transaction_list,
-					      transaction->priv->tid,
-					      transaction->priv->background);
+	if (priv->background == PK_HINT_ENUM_TRUE ||
+	    priv->background == PK_HINT_ENUM_FALSE) {
+		pk_transaction_list_set_background (priv->transaction_list,
+					      priv->tid,
+					      priv->background);
 	}
 
 	/* commit, so it appears in the JobList */
-	ret = pk_transaction_list_commit (transaction->priv->transaction_list,
-					  transaction->priv->tid);
+	ret = pk_transaction_list_commit (priv->transaction_list,
+					  priv->tid);
 	if (!ret) {
 		pk_transaction_release_tid (transaction);
 		egg_warning ("failed to commit (job not run?)");
@@ -1955,29 +1961,29 @@ pk_transaction_commit (PkTransaction *transaction)
 	}
 
 	/* only save into the database for useful stuff */
-	if (transaction->priv->role == PK_ROLE_ENUM_UPDATE_SYSTEM ||
-	    transaction->priv->role == PK_ROLE_ENUM_REMOVE_PACKAGES ||
-	    transaction->priv->role == PK_ROLE_ENUM_INSTALL_PACKAGES ||
-	    transaction->priv->role == PK_ROLE_ENUM_UPDATE_PACKAGES) {
+	if (priv->role == PK_ROLE_ENUM_UPDATE_SYSTEM ||
+	    priv->role == PK_ROLE_ENUM_REMOVE_PACKAGES ||
+	    priv->role == PK_ROLE_ENUM_INSTALL_PACKAGES ||
+	    priv->role == PK_ROLE_ENUM_UPDATE_PACKAGES) {
 
 		/* add to database */
-		pk_transaction_db_add (transaction->priv->transaction_db, transaction->priv->tid);
+		pk_transaction_db_add (priv->transaction_db, priv->tid);
 
 		/* save role in the database */
-		pk_transaction_db_set_role (transaction->priv->transaction_db, transaction->priv->tid, transaction->priv->role);
+		pk_transaction_db_set_role (priv->transaction_db, priv->tid, priv->role);
 
 		/* save uid */
-		pk_transaction_db_set_uid (transaction->priv->transaction_db, transaction->priv->tid, transaction->priv->uid);
+		pk_transaction_db_set_uid (priv->transaction_db, priv->tid, priv->uid);
 
 #ifdef USE_SECURITY_POLKIT
 		/* save cmdline in db */
-		if (transaction->priv->cmdline != NULL)
-			pk_transaction_db_set_cmdline (transaction->priv->transaction_db, transaction->priv->tid, transaction->priv->cmdline);
+		if (priv->cmdline != NULL)
+			pk_transaction_db_set_cmdline (priv->transaction_db, priv->tid, priv->cmdline);
 #endif
 
 		/* report to syslog */
-		pk_syslog_add (transaction->priv->syslog, PK_SYSLOG_TYPE_INFO, "new %s transaction %s scheduled from uid %i",
-			       pk_role_enum_to_string (transaction->priv->role), transaction->priv->tid, transaction->priv->uid);
+		pk_syslog_add (priv->syslog, PK_SYSLOG_TYPE_INFO, "new %s transaction %s scheduled from uid %i",
+			       pk_role_enum_to_string (priv->role), priv->tid, priv->uid);
 	}
 	return TRUE;
 }
@@ -2178,13 +2184,14 @@ pk_transaction_action_obtain_authorization_finished_cb (GObject *source_object,
 	gboolean ret;
 	gchar *message;
 	GError *error = NULL;
+	PkTransactionPrivate *priv = transaction->priv;
 
 	/* finish the call */
-	result = polkit_authority_check_authorization_finish (transaction->priv->authority, res, &error);
-	transaction->priv->waiting_for_auth = FALSE;
+	result = polkit_authority_check_authorization_finish (priv->authority, res, &error);
+	priv->waiting_for_auth = FALSE;
 
 	/* failed because the request was cancelled */
-	ret = g_cancellable_is_cancelled (transaction->priv->cancellable);
+	ret = g_cancellable_is_cancelled (priv->cancellable);
 	if (ret) {
 		/* emit an ::StatusChanged, ::ErrorCode() and then ::Finished() */
 		pk_transaction_status_changed_emit (transaction, PK_STATUS_ENUM_FINISHED);
@@ -2216,7 +2223,7 @@ pk_transaction_action_obtain_authorization_finished_cb (GObject *source_object,
 						"Failed to obtain authentication.");
 		pk_transaction_finished_emit (transaction, PK_EXIT_ENUM_FAILED, 0);
 
-		pk_syslog_add (transaction->priv->syslog, PK_SYSLOG_TYPE_AUTH, "uid %i failed to obtain auth", transaction->priv->uid);
+		pk_syslog_add (priv->syslog, PK_SYSLOG_TYPE_AUTH, "uid %i failed to obtain auth", priv->uid);
 		goto out;
 	}
 
@@ -2229,7 +2236,7 @@ pk_transaction_action_obtain_authorization_finished_cb (GObject *source_object,
 	}
 
 	/* log success too */
-	pk_syslog_add (transaction->priv->syslog, PK_SYSLOG_TYPE_AUTH, "uid %i obtained auth", transaction->priv->uid);
+	pk_syslog_add (priv->syslog, PK_SYSLOG_TYPE_AUTH, "uid %i obtained auth", priv->uid);
 out:
 	if (result != NULL)
 		g_object_unref (result);
@@ -2321,13 +2328,14 @@ pk_transaction_obtain_authorization (PkTransaction *transaction, gboolean only_t
 	const gchar *action_id;
 	gboolean ret = FALSE;
 	gchar *package_ids = NULL;
+	PkTransactionPrivate *priv = transaction->priv;
 
-	g_return_val_if_fail (transaction->priv->sender != NULL, FALSE);
+	g_return_val_if_fail (priv->sender != NULL, FALSE);
 
 	/* we should always have subject */
-	if (transaction->priv->subject == NULL) {
+	if (priv->subject == NULL) {
 		g_set_error (error, PK_TRANSACTION_ERROR, PK_TRANSACTION_ERROR_REFUSED_BY_POLICY,
-				      "subject %s not found", transaction->priv->sender);
+				      "subject %s not found", priv->sender);
 		goto out;
 	}
 
@@ -2342,39 +2350,39 @@ pk_transaction_obtain_authorization (PkTransaction *transaction, gboolean only_t
 	}
 
 	/* log */
-	pk_syslog_add (transaction->priv->syslog, PK_SYSLOG_TYPE_AUTH, "uid %i is trying to obtain %s auth (only_trusted:%i)", transaction->priv->uid, action_id, only_trusted);
+	pk_syslog_add (priv->syslog, PK_SYSLOG_TYPE_AUTH, "uid %i is trying to obtain %s auth (only_trusted:%i)", priv->uid, action_id, only_trusted);
 
 	/* emit status for GUIs */
 	pk_transaction_status_changed_emit (transaction, PK_STATUS_ENUM_WAITING_FOR_AUTH);
 	pk_transaction_progress_changed_emit (transaction, PK_BACKEND_PERCENTAGE_INVALID, PK_BACKEND_PERCENTAGE_INVALID, 0, 0);
 
 	/* check subject */
-	transaction->priv->waiting_for_auth = TRUE;
+	priv->waiting_for_auth = TRUE;
 
 	/* insert details about the authorization */
 	details = polkit_details_new ();
-	polkit_details_insert (details, "role", pk_role_enum_to_string (transaction->priv->role));
-	polkit_details_insert (details, "only-trusted", transaction->priv->cached_only_trusted ? "true" : "false");
+	polkit_details_insert (details, "role", pk_role_enum_to_string (priv->role));
+	polkit_details_insert (details, "only-trusted", priv->cached_only_trusted ? "true" : "false");
 
 	/* do we have package details? */
-	if (transaction->priv->cached_package_id != NULL)
-		package_ids = g_strdup (transaction->priv->cached_package_id);
-	else if (transaction->priv->cached_package_ids != NULL)
-		package_ids = pk_package_ids_to_string (transaction->priv->cached_package_ids);
+	if (priv->cached_package_id != NULL)
+		package_ids = g_strdup (priv->cached_package_id);
+	else if (priv->cached_package_ids != NULL)
+		package_ids = pk_package_ids_to_string (priv->cached_package_ids);
 
 	/* save optional stuff */
 	if (package_ids != NULL)
 		polkit_details_insert (details, "package_ids", package_ids);
-	if (transaction->priv->cmdline != NULL)
-		polkit_details_insert (details, "cmdline", transaction->priv->cmdline);
+	if (priv->cmdline != NULL)
+		polkit_details_insert (details, "cmdline", priv->cmdline);
 
 	/* do authorization async */
-	polkit_authority_check_authorization (transaction->priv->authority,
-					      transaction->priv->subject,
+	polkit_authority_check_authorization (priv->authority,
+					      priv->subject,
 					      action_id,
 					      details,
 					      POLKIT_CHECK_AUTHORIZATION_FLAGS_ALLOW_USER_INTERACTION,
-					      transaction->priv->cancellable,
+					      priv->cancellable,
 					      (GAsyncReadyCallback) pk_transaction_action_obtain_authorization_finished_cb,
 					      transaction);
 
@@ -3387,6 +3395,71 @@ pk_transaction_get_update_detail (PkTransaction *transaction, gchar **package_id
 }
 
 /**
+ * pk_transaction_try_emit_cache:
+ **/
+static gboolean
+pk_transaction_try_emit_cache (PkTransaction *transaction)
+{
+	PkResults *results;
+	gboolean ret = FALSE;
+	GPtrArray *package_array;
+	GPtrArray *message_array;
+	PkPackage *package;
+	PkMessage *message;
+	PkExitEnum exit_enum;
+	guint i;
+
+	/* get results */
+	results = pk_cache_get_results (transaction->priv->cache, transaction->priv->role);
+	if (results == NULL)
+		goto out;
+
+	/* failed last time */
+	exit_enum = pk_results_get_exit_code (results);
+	if (exit_enum != PK_EXIT_ENUM_SUCCESS) {
+		egg_warning ("failed last time with: %s", pk_exit_enum_to_string (exit_enum));
+		goto out;
+	}
+
+	egg_debug ("we have cached data we should use");
+
+	/* packages */
+	package_array = pk_results_get_package_array (results);
+	for (i=0; i<package_array->len; i++) {
+		package = g_ptr_array_index (package_array, i);
+		g_signal_emit (transaction, signals[SIGNAL_PACKAGE], 0,
+			       pk_info_enum_to_string (pk_package_get_info (package)),
+			       pk_package_get_id (package),
+			       pk_package_get_summary (package));
+	}
+
+	/* messages */
+	message_array = pk_results_get_message_array (results);
+	for (i=0; i<message_array->len; i++) {
+		message = g_ptr_array_index (message_array, i);
+		g_signal_emit (transaction, signals[SIGNAL_MESSAGE], 0,
+			       pk_message_enum_to_string (pk_message_get_kind (message)),
+			       pk_message_get_details (message));
+	}
+
+	/* success */
+	ret = TRUE;
+
+	/* set finished */
+	pk_transaction_status_changed_emit (transaction, PK_STATUS_ENUM_FINISHED);
+
+	/* we are done */
+	g_idle_add ((GSourceFunc) pk_transaction_finished_idle_cb, transaction);
+
+out:
+	if (package_array != NULL)
+		g_ptr_array_unref (package_array);
+	if (message_array != NULL)
+		g_ptr_array_unref (message_array);
+	return ret;
+}
+
+/**
  * pk_transaction_get_updates:
  **/
 void
@@ -3394,7 +3467,6 @@ pk_transaction_get_updates (PkTransaction *transaction, const gchar *filter, DBu
 {
 	gboolean ret;
 	GError *error = NULL;
-	GPtrArray *updates_cache;
 
 	g_return_if_fail (PK_IS_TRANSACTION (transaction));
 	g_return_if_fail (transaction->priv->tid != NULL);
@@ -3431,39 +3503,8 @@ pk_transaction_get_updates (PkTransaction *transaction, const gchar *filter, DBu
 	pk_transaction_set_role (transaction, PK_ROLE_ENUM_GET_UPDATES);
 
 	/* try and reuse cache */
-	updates_cache = pk_cache_get_updates (transaction->priv->cache);
-	if (updates_cache != NULL) {
-		PkPackage *item;
-		const gchar *info_text;
-		guint i;
-		PkInfoEnum info;
-		gchar *package_id;
-		gchar *summary;
-
-		egg_debug ("we have cached data (%i) we should use!", updates_cache->len);
-
-		/* emulate the backend */
-		for (i=0; i<updates_cache->len; i++) {
-			item = g_ptr_array_index (updates_cache, i);
-			g_object_get (item,
-				      "info", &info,
-				      "package-id", &package_id,
-				      "summary", &summary,
-				      NULL);
-			info_text = pk_info_enum_to_string (info);
-			egg_debug ("emitting package");
-			g_signal_emit (transaction, signals[SIGNAL_PACKAGE], 0,
-				       info_text, package_id, summary);
-			g_free (package_id);
-			g_free (summary);
-		}
-
-		/* set finished */
-		pk_transaction_status_changed_emit (transaction, PK_STATUS_ENUM_FINISHED);
-
-		/* we are done */
-		g_idle_add ((GSourceFunc) pk_transaction_finished_idle_cb, transaction);
-
+	ret = pk_transaction_try_emit_cache (transaction);
+	if (ret) {
 		/* not set inside the test suite */
 		if (context != NULL)
 			dbus_g_method_return (context);
commit 05bd618c58d3feb3190ed3005591acf40de44b3c
Author: Richard Hughes <richard at hughsie.com>
Date:   Wed May 5 15:13:07 2010 +0100

    glib: Add C accessors for PkMessage

diff --git a/lib/packagekit-glib2/pk-message.c b/lib/packagekit-glib2/pk-message.c
index c9c12f6..96beb0e 100644
--- a/lib/packagekit-glib2/pk-message.c
+++ b/lib/packagekit-glib2/pk-message.c
@@ -62,6 +62,40 @@ enum {
 G_DEFINE_TYPE (PkMessage, pk_message, PK_TYPE_SOURCE)
 
 /**
+ * pk_message_get_kind:
+ * @message: a valid #PkMessage instance
+ *
+ * Gets the message kind
+ *
+ * Return value: the %PkMessageEnum
+ *
+ * Since: 0.6.4
+ **/
+PkMessageEnum
+pk_message_get_kind (PkMessage *message)
+{
+	g_return_val_if_fail (PK_IS_MESSAGE (message), PK_MESSAGE_ENUM_UNKNOWN);
+	return message->priv->type;
+}
+
+/**
+ * pk_message_get_details:
+ * @message: a valid #PkMessage instance
+ *
+ * Gets the message details.
+ *
+ * Return value: the details, or %NULL if unset
+ *
+ * Since: 0.6.4
+ **/
+const gchar *
+pk_message_get_details (PkMessage *message)
+{
+	g_return_val_if_fail (PK_IS_MESSAGE (message), NULL);
+	return message->priv->details;
+}
+
+/**
  * pk_message_get_property:
  **/
 static void
diff --git a/lib/packagekit-glib2/pk-message.h b/lib/packagekit-glib2/pk-message.h
index 53cd8ab..c329bf0 100644
--- a/lib/packagekit-glib2/pk-message.h
+++ b/lib/packagekit-glib2/pk-message.h
@@ -29,6 +29,7 @@
 #include <glib-object.h>
 
 #include <packagekit-glib2/pk-source.h>
+#include <packagekit-glib2/pk-enum.h>
 
 G_BEGIN_DECLS
 
@@ -63,6 +64,10 @@ struct _PkMessageClass
 GType		 pk_message_get_type		(void);
 PkMessage	*pk_message_new			(void);
 
+/* accessors */
+const gchar	*pk_message_get_details		(PkMessage	*message);
+PkMessageEnum	 pk_message_get_kind		(PkMessage	*message);
+
 G_END_DECLS
 
 #endif /* __PK_MESSAGE_H */
commit abaf46fa7bce3a7eb65ddb294d03b988871b03e4
Author: Michael Meeks <michael.meeks at novell.com>
Date:   Wed May 5 15:00:52 2010 +0100

    Tweak filtering to ensure that we never emit both 'installed' and
    'available' for a given package name/ver/arch - even if it is also
    available for re-installation.

diff --git a/backends/zypp/pk-backend-zypp.cpp b/backends/zypp/pk-backend-zypp.cpp
index 7df342f..3ae0d43 100644
--- a/backends/zypp/pk-backend-zypp.cpp
+++ b/backends/zypp/pk-backend-zypp.cpp
@@ -1234,6 +1234,7 @@ backend_resolve_thread (PkBackend *backend)
 			}
 			pkgs.push_back (*it);
 		}
+		delete (v);
 
 		/* 'newest' filter support */
 		if (pk_bitfield_contain (_filters, PK_FILTER_ENUM_NEWEST)) {
@@ -1243,14 +1244,7 @@ backend_resolve_thread (PkBackend *backend)
 			pkgs.erase (std::find (pkgs.begin (), pkgs.end(), newest));
 		}
 
-		delete (v);
-
-		/* Emit callbacks */
-		for (std::vector<zypp::sat::Solvable>::iterator it = pkgs.begin (); it != pkgs.end (); it++) {
-			PkInfoEnum info = it->isSystem () ? PK_INFO_ENUM_INSTALLED : PK_INFO_ENUM_AVAILABLE;
-			zypp_backend_package (backend, info, *it,
-					    it->lookupStrAttribute (zypp::sat::SolvAttr::summary).c_str ());
-		}
+		zypp_emit_filtered_packages_in_list (backend, pkgs);
 
 		if (pkgs.size() < 1) {
 			return zypp_backend_finished_error (
diff --git a/backends/zypp/zypp-utils.cpp b/backends/zypp/zypp-utils.cpp
index 184776f..c7efaaf 100644
--- a/backends/zypp/zypp-utils.cpp
+++ b/backends/zypp/zypp-utils.cpp
@@ -563,25 +563,64 @@ zypp_filter_solvable (PkBitfield filters, const zypp::sat::Solvable &item)
 	return FALSE;
 }
 
+/*
+ * Emit signals for the packages, -but- if we have an installed package
+ * we don't notify the client that the package is also available, since
+ * PK doesn't handle re-installs (by some quirk).
+ */
 void
 zypp_emit_filtered_packages_in_list (PkBackend *backend, const std::vector<zypp::sat::Solvable> &v)
 {
-	PkBitfield filters = (PkBitfield) pk_backend_get_uint (backend, "filters");
+	typedef std::vector<zypp::sat::Solvable>::const_iterator sat_it_t;
 
-	for (std::vector<zypp::sat::Solvable>::const_iterator it = v.begin ();
-			it != v.end (); it++) {
+	// FIXME: we should move the 'NEWEST' handling here from _resolve_thread
+	//        that will require calculating 'newest' per package name.
+
+	std::vector<zypp::sat::Solvable> installed;
+	PkBitfield filters = (PkBitfield) pk_backend_get_uint (backend, "filters");
 
-		if (zypp_filter_solvable (filters, *it))
+	// always emit system installed packages first
+	for (sat_it_t it = v.begin (); it != v.end (); it++) {
+		if (!it->isSystem() ||
+		    zypp_filter_solvable (filters, *it))
 			continue;
-		zypp_backend_package (backend, 
-				      it->isSystem() == true ?
-				      PK_INFO_ENUM_INSTALLED :
-				      PK_INFO_ENUM_AVAILABLE,
-				      *it,
+
+		zypp_backend_package (backend, PK_INFO_ENUM_INSTALLED, *it,
 				      it->lookupStrAttribute (zypp::sat::SolvAttr::summary).c_str ());
+		installed.push_back (*it);
+	}
+
+	// then available packages later
+	for (sat_it_t it = v.begin (); it != v.end (); it++) {
+		gboolean match;
+
+		if (it->isSystem() ||
+		    zypp_filter_solvable (filters, *it))
+			continue;
+
+		match = FALSE;
+		for (sat_it_t i = installed.begin (); !match && i != installed.end (); i++) {
+			match = it->sameNVRA (*i) && 
+				!(!zypp::isKind<zypp::SrcPackage>(*it) ^
+				  !zypp::isKind<zypp::SrcPackage>(*i));
+		}
+		if (!match) {
+			zypp_backend_package (backend, PK_INFO_ENUM_AVAILABLE, *it,
+					      it->lookupStrAttribute (zypp::sat::SolvAttr::summary).c_str ());
+		}
 	}
 }
 
+void
+zypp_backend_package (PkBackend *backend, PkInfoEnum info,
+		      const zypp::sat::Solvable &pkg,
+		      const char *opt_summary)
+{
+	gchar *id = zypp_build_package_id_from_resolvable (pkg);
+	pk_backend_package (backend, info, id, opt_summary);
+	g_free (id);
+}
+
 /**
  * The following method was taken directly from zypper code
  *
@@ -992,16 +1031,6 @@ zypp_backend_finished_error (PkBackend  *backend, PkErrorEnum err_code,
 }
 
 void
-zypp_backend_package (PkBackend *backend, PkInfoEnum info,
-		      const zypp::sat::Solvable &pkg,
-		      const char *opt_summary)
-{
-	gchar *id = zypp_build_package_id_from_resolvable (pkg);
-	pk_backend_package (backend, info, id, opt_summary);
-	g_free (id);
-}
-
-void
 zypp_backend_pool_item_notify (PkBackend  *backend,
 			       const zypp::PoolItem &item)
 {
commit 5e4d31e813c8c92396b5abb933083283b379a7ce
Author: Michael Meeks <michael.meeks at novell.com>
Date:   Wed May 5 09:20:59 2010 +0100

    fix whitespace foo

diff --git a/backends/zypp/pk-backend-zypp.cpp b/backends/zypp/pk-backend-zypp.cpp
index eea7461..7df342f 100644
--- a/backends/zypp/pk-backend-zypp.cpp
+++ b/backends/zypp/pk-backend-zypp.cpp
@@ -1184,7 +1184,7 @@ backend_remove_packages_thread (PkBackend *backend)
 static void
 backend_remove_packages (PkBackend *backend, gchar **package_ids, gboolean allow_deps, gboolean autoremove)
 {
-	pk_backend_set_bool(backend, "simulate", false);
+	pk_backend_set_bool (backend, "simulate", false);
 	pk_backend_set_uint (backend, "allow_deps", allow_deps == TRUE ? DEPS_ALLOW : DEPS_NO_ALLOW);
 	pk_backend_thread_create (backend, backend_remove_packages_thread);
 }
@@ -1192,7 +1192,7 @@ backend_remove_packages (PkBackend *backend, gchar **package_ids, gboolean allow
 static void
 backend_simulate_remove_packages (PkBackend *backend, gchar **packages, gboolean autoremove)
 {
-	pk_backend_set_bool(backend, "simulate", true);
+	pk_backend_set_bool (backend, "simulate", true);
 	pk_backend_thread_create (backend, backend_remove_packages_thread);
 }
 
diff --git a/backends/zypp/zypp-utils.cpp b/backends/zypp/zypp-utils.cpp
index d1e9ec4..184776f 100644
--- a/backends/zypp/zypp-utils.cpp
+++ b/backends/zypp/zypp-utils.cpp
@@ -1019,7 +1019,6 @@ zypp_backend_pool_item_notify (PkBackend  *backend,
 
 	// FIXME: do we need more heavy lifting here cf. zypper's
 	// Summary.cc (readPool) to generate _DOWNGRADING types ?
-	
 	if (status != PK_INFO_ENUM_UNKNOWN) {
 		const std::string &summary = item.resolvable ()->summary ();
 		zypp_backend_package (backend, status, item.resolvable()->satSolvable(), summary.c_str ());
commit bb7eec4024e25ccd936b8c58b51e6724eabe0430
Author: Michael Meeks <michael.meeks at novell.com>
Date:   Tue May 4 22:00:35 2010 +0100

    Factor pool item change notification out into zypp_backend_pool_item_notify.
    Simplify get_requires_thread.
    zypp_perform_execution
      + add 'simulate' parameter
      + improve resetting of parameters on exit
      + improve exception handling
    Implement simulated package removal

diff --git a/backends/zypp/pk-backend-zypp.cpp b/backends/zypp/pk-backend-zypp.cpp
index d14392b..eea7461 100644
--- a/backends/zypp/pk-backend-zypp.cpp
+++ b/backends/zypp/pk-backend-zypp.cpp
@@ -199,28 +199,11 @@ backend_get_requires_thread (PkBackend *backend)
 		// look for packages which would be uninstalled
 		for (zypp::ResPool::byKind_iterator it = pool.byKindBegin (zypp::ResKind::package);
 				it != pool.byKindEnd (zypp::ResKind::package); it++) {
-			PkInfoEnum status = PK_INFO_ENUM_UNKNOWN;
-
-			gboolean hit = FALSE;
 
-			if (it->status ().isToBeUninstalled ()) {
-				status = PK_INFO_ENUM_REMOVING;
-				hit = TRUE;
-			} else if (it->status ().isToBeInstalled ()) {
-				status = PK_INFO_ENUM_INSTALLING;
-				hit = TRUE;
-			} else if (it->status ().isToBeUninstalledDueToUpgrade ()) {
-				status = PK_INFO_ENUM_UPDATING;
-				hit = TRUE;
-			} else if (it->status ().isToBeUninstalledDueToObsolete ()) {
-				status = PK_INFO_ENUM_OBSOLETING;
-				hit = TRUE;
+			if (!zypp_filter_solvable (_filters, it->resolvable()->satSolvable())) {
+				zypp_backend_pool_item_notify (backend, *it);
 			}
 
-			if (hit && !zypp_filter_solvable (_filters, it->resolvable()->satSolvable())) {
-				zypp_backend_package (backend, status, it->resolvable()->satSolvable(),
-						      it->resolvable ()->summary ().c_str ());
-			}
 			it->statusReset ();
 		}
 
@@ -1127,6 +1110,7 @@ static gboolean
 backend_remove_packages_thread (PkBackend *backend)
 {
 	gchar **package_ids;
+	gboolean simulate;
 	std::vector<zypp::PoolItem> *items = new std::vector<zypp::PoolItem> ();
 
 	pk_backend_set_status (backend, PK_STATUS_ENUM_REMOVE);
@@ -1142,6 +1126,7 @@ backend_remove_packages_thread (PkBackend *backend)
 	target->load ();
 	pk_backend_set_percentage (backend, 10);
 
+	simulate = pk_backend_get_bool (backend, "simulate");
 	package_ids = pk_backend_get_strv (backend, "package_ids");
 	if (!pk_package_ids_check (package_ids)) {
 		return zypp_backend_finished_error (
@@ -1167,7 +1152,7 @@ backend_remove_packages_thread (PkBackend *backend)
 
 	try
 	{
-		if (!zypp_perform_execution (backend, REMOVE, TRUE)){
+		if (!zypp_perform_execution (backend, REMOVE, TRUE, simulate)) {
 			//reset the status of the marked packages
 			for (std::vector<zypp::PoolItem>::iterator it = items->begin (); it != items->end (); it++) {
 				it->statusReset();
@@ -1199,10 +1184,18 @@ backend_remove_packages_thread (PkBackend *backend)
 static void
 backend_remove_packages (PkBackend *backend, gchar **package_ids, gboolean allow_deps, gboolean autoremove)
 {
+	pk_backend_set_bool(backend, "simulate", false);
 	pk_backend_set_uint (backend, "allow_deps", allow_deps == TRUE ? DEPS_ALLOW : DEPS_NO_ALLOW);
 	pk_backend_thread_create (backend, backend_remove_packages_thread);
 }
 
+static void
+backend_simulate_remove_packages (PkBackend *backend, gchar **packages, gboolean autoremove)
+{
+	pk_backend_set_bool(backend, "simulate", true);
+	pk_backend_thread_create (backend, backend_remove_packages_thread);
+}
+
 static gboolean
 backend_resolve_thread (PkBackend *backend)
 {
@@ -1892,7 +1885,7 @@ extern "C" PK_BACKEND_OPTIONS (
 	backend_what_provides,			/* what_provides */
 	NULL,					/* simulate_install_files */
 	NULL,					/* simulate_install_packages */
-	NULL,					/* simulate_remove_packages */
+	backend_simulate_remove_packages,	/* simulate_remove_packages */
 	NULL					/* simulate_update_packages */
 );
 
diff --git a/backends/zypp/zypp-utils.cpp b/backends/zypp/zypp-utils.cpp
index bc28016..d1e9ec4 100644
--- a/backends/zypp/zypp-utils.cpp
+++ b/backends/zypp/zypp-utils.cpp
@@ -690,8 +690,11 @@ zypp_get_restart (PkRestartEnum &restart, zypp::Patch::constPtr patch)
 }
 
 gboolean
-zypp_perform_execution (PkBackend *backend, PerformType type, gboolean force)
+zypp_perform_execution (PkBackend *backend, PerformType type,
+			gboolean force, gboolean simulate)
 {
+	gboolean ret = FALSE;
+
         try {
                 zypp::ZYpp::Ptr zypp = get_zypp ();
 
@@ -732,8 +735,8 @@ zypp_perform_execution (PkBackend *backend, PerformType type, gboolean force)
 
 			pk_backend_error_code (backend, PK_ERROR_ENUM_DEP_RESOLUTION_FAILED, emsg);
 			g_free (emsg);
-			zypp->resolver ()->setForceResolve (FALSE);
-			return FALSE;
+
+			goto exit;
 		}
 
                 switch (type) {
@@ -748,9 +751,20 @@ zypp_perform_execution (PkBackend *backend, PerformType type, gboolean force)
                                 break;
                 };
 
+		zypp::ResPool pool = zypp::ResPool::instance ();
+		if (simulate) {
+
+			for (zypp::ResPool::const_iterator it = pool.begin (); it != pool.end (); it++) {
+				zypp_backend_pool_item_notify (backend, *it);
+				it->statusReset ();
+			}
+
+			ret = TRUE;
+			goto exit;
+		}
+
 		// look for licenses to confirm
 
-		zypp::ResPool pool = zypp::ResPool::instance ();
 		for (zypp::ResPool::const_iterator it = pool.begin (); it != pool.end (); it++) {
 			if (it->status ().isToBeInstalled () && !(it->satSolvable ().lookupStrAttribute (zypp::sat::SolvAttr::eula).empty ())) {
 				gchar *eula_id = g_strdup ((*it)->name ().c_str ());
@@ -765,7 +779,7 @@ zypp_perform_execution (PkBackend *backend, PerformType type, gboolean force)
 					pk_backend_error_code (backend, PK_ERROR_ENUM_NO_LICENSE_AGREEMENT, "You've to agree/decline a license");
 					g_free (package_id);
 					g_free (eula_id);
-					return FALSE;
+					goto exit;
 				}
 				g_free (eula_id);
 			}
@@ -821,27 +835,28 @@ zypp_perform_execution (PkBackend *backend, PerformType type, gboolean force)
 					emsg);
 
 			g_free (emsg);
-			zypp->resolver ()->setForceResolve (FALSE);
-                        return FALSE;
+			goto exit;
                 }
 
-		zypp->resolver ()->setForceResolve (FALSE);
-		if (type == UPDATE) {
-			zypp->resolver ()->setIgnoreAlreadyRecommended (FALSE);
-		}
-
+		ret = TRUE;
         } catch (const zypp::repo::RepoNotFoundException &ex) {
 		pk_backend_error_code (backend, PK_ERROR_ENUM_REPO_NOT_FOUND, ex.asUserString().c_str() );
-		return FALSE;
 	} catch (const zypp::target::rpm::RpmException &ex) {
 		pk_backend_error_code (backend, PK_ERROR_ENUM_PACKAGE_DOWNLOAD_FAILED, ex.asUserString().c_str () );
-		return FALSE;
 	} catch (const zypp::Exception &ex) {
 		pk_backend_error_code (backend, PK_ERROR_ENUM_INTERNAL_ERROR, ex.asUserString().c_str() );
-		return FALSE;
 	}
 
-        return TRUE;
+ exit:
+	/* reset the various options */
+        try {
+                zypp::ZYpp::Ptr zypp = get_zypp ();
+		zypp->resolver ()->setForceResolve (FALSE);
+		if (type == UPDATE)
+			zypp->resolver ()->setIgnoreAlreadyRecommended (FALSE);
+	} catch (const zypp::Exception &ex) { /* we tried */ }
+
+        return ret;
 }
 
 gchar **
@@ -986,6 +1001,31 @@ zypp_backend_package (PkBackend *backend, PkInfoEnum info,
 	g_free (id);
 }
 
+void
+zypp_backend_pool_item_notify (PkBackend  *backend,
+			       const zypp::PoolItem &item)
+{
+	PkInfoEnum status = PK_INFO_ENUM_UNKNOWN;
+
+	if (item.status ().isToBeUninstalled ()) {
+		status = PK_INFO_ENUM_REMOVING;
+	} else if (item.status ().isToBeInstalled ()) {
+		status = PK_INFO_ENUM_INSTALLING;
+	} else if (item.status ().isToBeUninstalledDueToUpgrade ()) {
+		status = PK_INFO_ENUM_UPDATING;
+	} else if (item.status ().isToBeUninstalledDueToObsolete ()) {
+		status = PK_INFO_ENUM_OBSOLETING;
+	}
+
+	// FIXME: do we need more heavy lifting here cf. zypper's
+	// Summary.cc (readPool) to generate _DOWNGRADING types ?
+	
+	if (status != PK_INFO_ENUM_UNKNOWN) {
+		const std::string &summary = item.resolvable ()->summary ();
+		zypp_backend_package (backend, status, item.resolvable()->satSolvable(), summary.c_str ());
+	}
+}
+
 gchar *
 zypp_build_package_id_from_resolvable (const zypp::sat::Solvable &resolvable)
 {
diff --git a/backends/zypp/zypp-utils.h b/backends/zypp/zypp-utils.h
index 7883a26..ad13a66 100644
--- a/backends/zypp/zypp-utils.h
+++ b/backends/zypp/zypp-utils.h
@@ -181,7 +181,8 @@ gboolean zypp_get_restart (PkRestartEnum &restart, zypp::Patch::constPtr patch);
 /**
   * perform changes in pool to the system
   */
-gboolean zypp_perform_execution (PkBackend *backend, PerformType type, gboolean force);
+gboolean zypp_perform_execution (PkBackend *backend, PerformType type,
+				 gboolean force, gboolean simulate = FALSE);
 
 /**
  * should we omit a solvable from a result because of filtering ?
@@ -222,6 +223,12 @@ void     zypp_backend_package (PkBackend *backend, PkInfoEnum info,
 			       const char *opt_summary);
 
 /**
+  * helper to emit pk package status signals based on a ResPool object
+  */
+void     zypp_backend_pool_item_notify (PkBackend  *backend,
+					const zypp::PoolItem &item);
+
+/**
   * helper to compare a version + architecture, with source arch mangling.
   */
 gboolean zypp_ver_and_arch_equal (const zypp::sat::Solvable &pkg,
commit dce84081ae19287a308d16eaf622fbeb69c9a9fa
Merge: c7f9942... 3357269...
Author: Richard Hughes <richard at hughsie.com>
Date:   Wed May 5 09:00:09 2010 +0100

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

commit 3357269f56c4725d6ca60f0ec7e3b8dbe5390539
Author: Michael Meeks <michael.meeks at novell.com>
Date:   Tue May 4 17:08:54 2010 +0100

    whitespace cleans wrt. }else{

diff --git a/backends/zypp/pk-backend-zypp.cpp b/backends/zypp/pk-backend-zypp.cpp
index 13209b6..d14392b 100644
--- a/backends/zypp/pk-backend-zypp.cpp
+++ b/backends/zypp/pk-backend-zypp.cpp
@@ -206,13 +206,13 @@ backend_get_requires_thread (PkBackend *backend)
 			if (it->status ().isToBeUninstalled ()) {
 				status = PK_INFO_ENUM_REMOVING;
 				hit = TRUE;
-			}else if (it->status ().isToBeInstalled ()) {
+			} else if (it->status ().isToBeInstalled ()) {
 				status = PK_INFO_ENUM_INSTALLING;
 				hit = TRUE;
-			}else if (it->status ().isToBeUninstalledDueToUpgrade ()) {
+			} else if (it->status ().isToBeUninstalledDueToUpgrade ()) {
 				status = PK_INFO_ENUM_UPDATING;
 				hit = TRUE;
-			}else if (it->status ().isToBeUninstalledDueToObsolete ()) {
+			} else if (it->status ().isToBeUninstalledDueToObsolete ()) {
 				status = PK_INFO_ENUM_OBSOLETING;
 				hit = TRUE;
 			}
@@ -691,11 +691,11 @@ backend_get_updates_thread (PkBackend *backend)
 			zypp::Patch::constPtr patch = zypp::asKind<zypp::Patch>(res);
 			if (patch->category () == "recommended") {
 				infoEnum = PK_INFO_ENUM_IMPORTANT;
-			}else if (patch->category () == "optional") {
+			} else if (patch->category () == "optional") {
 				infoEnum = PK_INFO_ENUM_LOW;
-			}else if (patch->category () == "security") {
+			} else if (patch->category () == "security") {
 				infoEnum = PK_INFO_ENUM_SECURITY;
-			}else if (patch->category () == "distupgrade") {
+			} else if (patch->category () == "distupgrade") {
 				continue;
 			} else {
 				infoEnum = PK_INFO_ENUM_NORMAL;
@@ -1671,16 +1671,16 @@ backend_repo_set_data_thread (PkBackend *backend)
 			manager.addRepository (repo);
 
 		// remove a repo
-		}else if (g_ascii_strcasecmp (parameter, "remove") == 0) {
+		} else if (g_ascii_strcasecmp (parameter, "remove") == 0) {
 			repo = manager.getRepositoryInfo (repo_id);
 			manager.removeRepository (repo);
 		// set autorefresh of a repo true/false
-		}else if (g_ascii_strcasecmp (parameter, "refresh") == 0) {
+		} else if (g_ascii_strcasecmp (parameter, "refresh") == 0) {
 			repo = manager.getRepositoryInfo (repo_id);
 
 			if (g_ascii_strcasecmp (value, "true") == 0) {
 				repo.setAutorefresh (TRUE);
-			}else if (g_ascii_strcasecmp (value, "false") == 0) {
+			} else if (g_ascii_strcasecmp (value, "false") == 0) {
 				repo.setAutorefresh (FALSE);
 			} else {
 				pk_backend_message (backend, PK_MESSAGE_ENUM_PARAMETER_INVALID, "Autorefresh a repo: Enter true or false");
@@ -1688,28 +1688,28 @@ backend_repo_set_data_thread (PkBackend *backend)
 			}
 
 			manager.modifyRepository (repo_id, repo);
-		}else if (g_ascii_strcasecmp (parameter, "keep") == 0) {
+		} else if (g_ascii_strcasecmp (parameter, "keep") == 0) {
 			repo = manager.getRepositoryInfo (repo_id);
 
 			if (g_ascii_strcasecmp (value, "true") == 0) {
 				repo.setKeepPackages (TRUE);
-			}else if (g_ascii_strcasecmp (value, "false") == 0) {
+			} else if (g_ascii_strcasecmp (value, "false") == 0) {
 				repo.setKeepPackages (FALSE);
-			}else {
+			} else {
 				pk_backend_message (backend, PK_MESSAGE_ENUM_PARAMETER_INVALID, "Keep downloaded packages: Enter true or false");
 				bReturn = FALSE;
 			}
 
 			manager.modifyRepository (repo_id, repo);
-		}else if (g_ascii_strcasecmp (parameter, "url") == 0) {
+		} else if (g_ascii_strcasecmp (parameter, "url") == 0) {
 			repo = manager.getRepositoryInfo (repo_id);
 			repo.setBaseUrl (zypp::Url(value));
 			manager.modifyRepository (repo_id, repo);
-		}else if (g_ascii_strcasecmp (parameter, "name") == 0) {
+		} else if (g_ascii_strcasecmp (parameter, "name") == 0) {
 			repo = manager.getRepositoryInfo (repo_id);
 			repo.setName(value);
 			manager.modifyRepository (repo_id, repo);
-		}else if (g_ascii_strcasecmp (parameter, "prio") == 0) {
+		} else if (g_ascii_strcasecmp (parameter, "prio") == 0) {
 			repo = manager.getRepositoryInfo (repo_id);
 			gint prio = 0;
 			gint length = strlen (value);
diff --git a/backends/zypp/zypp-utils.cpp b/backends/zypp/zypp-utils.cpp
index 29e0822..bc28016 100644
--- a/backends/zypp/zypp-utils.cpp
+++ b/backends/zypp/zypp-utils.cpp
@@ -267,7 +267,7 @@ zypp_get_group (zypp::sat::Solvable item)
                 zypp::target::rpm::RpmHeader::constPtr rpmHeader = zypp_get_rpmHeader (item.name (), item.edition ());
                 group = rpmHeader->tag_group ();
 
-        }else{
+        } else {
                 group = item.lookupStrAttribute (zypp::sat::SolvAttr::group);
         }
         std::transform(group.begin(), group.end(), group.begin(), tolower);
@@ -446,7 +446,7 @@ zypp_signature_required (PkBackend *backend, const zypp::PublicKey &key)
         	                key.created ().asString ().c_str (),
                 	        PK_SIGTYPE_ENUM_GPG);
 		pk_backend_error_code (backend, PK_ERROR_ENUM_GPG_FAILURE, "Signature verification for Repository %s failed", _repoName);
-	}else{
+	} else {
 		ok = TRUE;
 	}
 
@@ -475,7 +475,7 @@ zypp_signature_required (PkBackend *backend, const std::string &file, const std:
         	                "UNKNOWN",
                 	        PK_SIGTYPE_ENUM_GPG);
 		pk_backend_error_code (backend, PK_ERROR_ENUM_GPG_FAILURE, "Signature verification for Repository %s failed", _repoName);
-	}else{
+	} else {
 		ok = TRUE;
 	}
 
@@ -504,7 +504,7 @@ zypp_signature_required (PkBackend *backend, const std::string &file)
                         	"UNKNOWN",
 	                        PK_SIGTYPE_ENUM_GPG);
 		pk_backend_error_code (backend, PK_ERROR_ENUM_GPG_FAILURE, "Signature verification for Repository %s failed", _repoName);
-	}else{
+	} else {
 		ok = TRUE;
 	}
 
@@ -628,7 +628,7 @@ zypp_get_updates (std::string repo)
                         continue;
 		if (repo.empty ()) {
 	                pks->insert (candidate);
-		}else{
+		} else {
 			if (candidate->repoInfo ().alias ().compare (repo) != 0)
 				pks->insert (candidate);
 		}
@@ -787,7 +787,7 @@ zypp_perform_execution (PkBackend *backend, PerformType type, gboolean force)
 			for (zypp::ZYppCommitResult::PoolItemList::iterator it = errors.begin (); it != errors.end (); it++){
 				if (emsg == NULL) {
 					emsg = g_strdup ((*it)->name ().c_str ());
-				}else{
+				} else {
 					tmpmsg = emsg;
 					emsg = g_strconcat (emsg, "\n", (*it)->name ().c_str (), NULL);
 					g_free (tmpmsg);
@@ -798,7 +798,7 @@ zypp_perform_execution (PkBackend *backend, PerformType type, gboolean force)
 			for (zypp::ZYppCommitResult::PoolItemList::iterator it = remaining.begin (); it != remaining.end (); it++){
 				if (emsg == NULL) {
 					emsg = g_strdup ((*it)->name ().c_str ());
-				}else{
+				} else {
 					tmpmsg = emsg;
 					emsg = g_strconcat (emsg, "\n", (*it)->name ().c_str (), NULL);
 					g_free (tmpmsg);
@@ -809,7 +809,7 @@ zypp_perform_execution (PkBackend *backend, PerformType type, gboolean force)
 			for (zypp::ZYppCommitResult::PoolItemList::iterator it = srcremaining.begin (); it != srcremaining.end (); it++){
 				if (emsg == NULL) {
 					emsg = g_strdup ((*it)->name ().c_str ());
-				}else{
+				} else {
 					tmpmsg = emsg;
 					emsg = g_strconcat (emsg, "\n", (*it)->name ().c_str (), NULL);
 					g_free (tmpmsg);
@@ -936,7 +936,7 @@ zypp_refresh_cache (PkBackend *backend, gboolean force)
 		} catch (const zypp::Exception &ex) {
 			if (repo_messages == NULL) {
 				repo_messages = g_strdup_printf ("%s: %s%s", repo.alias ().c_str (), ex.asUserString ().c_str (), "\n");
-			}else{
+			} else {
 				repo_messages = g_strdup_printf ("%s%s: %s%s", repo_messages, repo.alias ().c_str (), ex.asUserString ().c_str (), "\n");
 			}
 			if (repo_messages == NULL || !g_utf8_validate (repo_messages, -1, NULL))
commit 6d14bcf136484b8fa73bcd10f6e2ebaeeb3e9d9e
Author: Michael Meeks <michael.meeks at novell.com>
Date:   Tue May 4 17:05:16 2010 +0100

    introduce a pseudo-architecture "source" to distinguish source
    packages from binary ones of the same name and version.

diff --git a/backends/zypp/zypp-utils.cpp b/backends/zypp/zypp-utils.cpp
index d9d3737..29e0822 100644
--- a/backends/zypp/zypp-utils.cpp
+++ b/backends/zypp/zypp-utils.cpp
@@ -408,19 +408,6 @@ zypp_get_package_by_id (const gchar *package_id)
 	return package;
 }
 
-gchar *
-zypp_build_package_id_from_resolvable (const zypp::sat::Solvable &resolvable)
-{
-	gchar *package_id;
-
-	package_id = pk_package_id_build (resolvable.name ().c_str (),
-					  resolvable.edition ().asString ().c_str (),
-					  resolvable.arch ().asString ().c_str (),
-					  resolvable.repository (). alias().c_str ());
-
-	return package_id;
-}
-
 zypp::RepoInfo
 zypp_get_Repository (PkBackend *backend, const gchar *alias)
 {
@@ -999,6 +986,25 @@ zypp_backend_package (PkBackend *backend, PkInfoEnum info,
 	g_free (id);
 }
 
+gchar *
+zypp_build_package_id_from_resolvable (const zypp::sat::Solvable &resolvable)
+{
+	gchar *package_id;
+	const char *arch;
+
+	if (zypp::isKind<zypp::SrcPackage>(resolvable))
+		arch = "source";
+	else
+		arch = resolvable.arch ().asString ().c_str ();
+
+	package_id = pk_package_id_build (
+		resolvable.name ().c_str (),
+		resolvable.edition ().asString ().c_str (),
+		arch, resolvable.repository ().alias().c_str ());
+
+	return package_id;
+}
+
 gboolean
 zypp_ver_and_arch_equal (const zypp::sat::Solvable &pkg,
 			 const char *name, const char *arch)
@@ -1007,6 +1013,10 @@ zypp_ver_and_arch_equal (const zypp::sat::Solvable &pkg,
 	if (g_strcmp0 (ver.c_str (), name))
 	    return FALSE;
 
+	if (arch && !strcmp (arch, "source")) {
+		return zypp::isKind<zypp::SrcPackage>(pkg);
+	}
+
 	const zypp::Arch &parch = pkg.arch();
 	if (g_strcmp0 (parch.c_str(), arch))
 		return FALSE;
commit 3abbf4b3aaf664cbe96304a80c3aa9fa69632279
Author: Michael Meeks <michael.meeks at novell.com>
Date:   Tue May 4 16:53:41 2010 +0100

    share the version / architecture comparison code into zypp_ver_and_arch_equal
    fix associated leaks.
    Update backend's advertised filter flags

diff --git a/backends/zypp/pk-backend-zypp.cpp b/backends/zypp/pk-backend-zypp.cpp
index ce42eb7..13209b6 100644
--- a/backends/zypp/pk-backend-zypp.cpp
+++ b/backends/zypp/pk-backend-zypp.cpp
@@ -277,11 +277,9 @@ backend_get_filters (PkBackend *backend)
 {
 	return pk_bitfield_from_enums (
 		PK_FILTER_ENUM_INSTALLED,
-		PK_FILTER_ENUM_NOT_INSTALLED,
 		PK_FILTER_ENUM_ARCH,
-		PK_FILTER_ENUM_NOT_ARCH,
+		PK_FILTER_ENUM_NEWEST,
 		PK_FILTER_ENUM_SOURCE,
-		PK_FILTER_ENUM_NOT_SOURCE,
 		-1);
 }
 
@@ -497,15 +495,11 @@ backend_get_details_thread (PkBackend *backend)
 		zypp::sat::Solvable package;
 		for (std::vector<zypp::sat::Solvable>::iterator it = v->begin ();
 				it != v->end (); it++) {
-			gchar *version = g_strdup (it->edition ().asString ().c_str ());
-			gchar *arch = g_strdup (it->arch ().c_str ());
-
-			if (strcmp (id_parts[PK_PACKAGE_ID_VERSION], version) == 0 && strcmp (id_parts[PK_PACKAGE_ID_ARCH], arch) == 0) {
+			if (zypp_ver_and_arch_equal (*it, id_parts[PK_PACKAGE_ID_VERSION],
+						     id_parts[PK_PACKAGE_ID_ARCH])) {
 				package = *it;
 				break;
 			}
-			g_free (version);
-			g_free (arch);
 		}
 		delete (v);
 		delete (v2);
@@ -1054,8 +1048,8 @@ backend_install_packages_thread (PkBackend *backend)
 			// Choose the PoolItem with the right architecture and version
 			for (zypp::ui::Selectable::available_iterator it = selectable->availableBegin ();
 					it != selectable->availableEnd (); it++) {
-				if (strcmp ((*it)->edition ().asString ().c_str (), id_parts[PK_PACKAGE_ID_VERSION]) == 0
-						&& strcmp ((*it)->arch ().c_str (), id_parts[PK_PACKAGE_ID_ARCH]) == 0 ) {
+				if (zypp_ver_and_arch_equal (it->satSolvable(), id_parts[PK_PACKAGE_ID_VERSION],
+							     id_parts[PK_PACKAGE_ID_ARCH])) {
 					hit = true;
 					// set status to ToBeInstalled
 					it->status ().setToBeInstalled (zypp::ResStatus::USER);
diff --git a/backends/zypp/zypp-utils.cpp b/backends/zypp/zypp-utils.cpp
index 8d2f8fe..d9d3737 100644
--- a/backends/zypp/zypp-utils.cpp
+++ b/backends/zypp/zypp-utils.cpp
@@ -395,14 +395,11 @@ zypp_get_package_by_id (const gchar *package_id)
 
 	for (std::vector<zypp::sat::Solvable>::iterator it = v->begin ();
 			it != v->end (); it++) {
-		gchar *version = g_strdup (it->edition ().c_str ());
-		gchar *arch = g_strdup (it->arch ().c_str ());
-		if (strcmp (id_parts[PK_PACKAGE_ID_VERSION], version) == 0 && strcmp (id_parts[PK_PACKAGE_ID_ARCH], arch) == 0) {
+		if (zypp_ver_and_arch_equal (*it, id_parts[PK_PACKAGE_ID_VERSION],
+					     id_parts[PK_PACKAGE_ID_ARCH])) {
 			package = *it;
 			break;
 		}
-		g_free (version);
-		g_free (arch);
 	}
 
 	delete (v);
@@ -1001,3 +998,18 @@ zypp_backend_package (PkBackend *backend, PkInfoEnum info,
 	pk_backend_package (backend, info, id, opt_summary);
 	g_free (id);
 }
+
+gboolean
+zypp_ver_and_arch_equal (const zypp::sat::Solvable &pkg,
+			 const char *name, const char *arch)
+{
+	const std::string &ver = pkg.edition ().asString();
+	if (g_strcmp0 (ver.c_str (), name))
+	    return FALSE;
+
+	const zypp::Arch &parch = pkg.arch();
+	if (g_strcmp0 (parch.c_str(), arch))
+		return FALSE;
+
+	return TRUE;
+}
diff --git a/backends/zypp/zypp-utils.h b/backends/zypp/zypp-utils.h
index 0847110..7883a26 100644
--- a/backends/zypp/zypp-utils.h
+++ b/backends/zypp/zypp-utils.h
@@ -221,5 +221,12 @@ void     zypp_backend_package (PkBackend *backend, PkInfoEnum info,
 			       const zypp::sat::Solvable &pkg,
 			       const char *opt_summary);
 
+/**
+  * helper to compare a version + architecture, with source arch mangling.
+  */
+gboolean zypp_ver_and_arch_equal (const zypp::sat::Solvable &pkg,
+				   const char *name, const char *arch);
+
+
 #endif // _ZYPP_UTILS_H_
 
commit 70d18b3bc674cca9ca65c05eaf23d43b2bf3f1c5
Author: Michael Meeks <michael.meeks at novell.com>
Date:   Tue May 4 15:30:25 2010 +0100

    Yes it is a better idea to use a strong package version compare
    instead of a string compare.

diff --git a/backends/zypp/pk-backend-zypp.cpp b/backends/zypp/pk-backend-zypp.cpp
index 45519e6..ce42eb7 100644
--- a/backends/zypp/pk-backend-zypp.cpp
+++ b/backends/zypp/pk-backend-zypp.cpp
@@ -1235,20 +1235,14 @@ backend_resolve_thread (PkBackend *backend)
 
 		/* Filter the list of packages with this name to 'pkgs' */
 		for (std::vector<zypp::sat::Solvable>::iterator it = v->begin (); it != v->end (); it++) {
-			if (zypp_filter_solvable (_filters, *it))
-				continue;
 
-			if (*it == zypp::sat::Solvable::noSolvable) {
-				egg_debug ("WARNING - changed behaviour - filtering pseudo-system pkgs!");
+			if (zypp_filter_solvable (_filters, *it) ||
+			    *it == zypp::sat::Solvable::noSolvable)
 				continue;
-			}
 
-			if (newest == zypp::sat::Solvable::noSolvable)
+			if (newest == zypp::sat::Solvable::noSolvable) {
 				newest = *it;
-			else if (it->edition().match (newest.edition()) > 0) {
-				egg_debug ("TESTME: '%s' > '%s'",
-					   it->asString().c_str(),
-					   newest.asString().c_str());
+			} else if (it->edition().match (newest.edition()) > 0) {
 				newest = *it;
 			}
 			pkgs.push_back (*it);
commit cbe307ba6f97a512b6c6b3da5917a747128f1dab
Author: Michael Meeks <michael.meeks at novell.com>
Date:   Tue May 4 15:26:03 2010 +0100

    Wrap pk_backend_package, use the wrapper to simplify the code,
    and fix leaks in getrequires, resolve and what_provides.

diff --git a/backends/zypp/pk-backend-zypp.cpp b/backends/zypp/pk-backend-zypp.cpp
index 3aa56fd..45519e6 100644
--- a/backends/zypp/pk-backend-zypp.cpp
+++ b/backends/zypp/pk-backend-zypp.cpp
@@ -218,10 +218,8 @@ backend_get_requires_thread (PkBackend *backend)
 			}
 
 			if (hit && !zypp_filter_solvable (_filters, it->resolvable()->satSolvable())) {
-				gchar *package_id;
-				package_id = zypp_build_package_id_from_resolvable (it->resolvable()->satSolvable());
-				pk_backend_package (backend, status, package_id, it->resolvable ()->summary ().c_str ());
-				g_free (package_id);
+				zypp_backend_package (backend, status, it->resolvable()->satSolvable(),
+						      it->resolvable ()->summary ().c_str ());
 			}
 			it->statusReset ();
 		}
@@ -443,13 +441,8 @@ backend_get_depends_thread (PkBackend *backend)
 				   zypp_filter_solvable (_filters, it->second) ? "don't add" : "add" );
 
 			if (!zypp_filter_solvable (_filters, it->second)) {
-				gchar *package_id_temp;
-
-				package_id_temp = zypp_build_package_id_from_resolvable (it->second);
-				pk_backend_package (backend, info,
-						    package_id_temp,
-						    item->summary ().c_str());
-				g_free (package_id_temp);
+				zypp_backend_package (backend, info, it->second,
+						      item->summary ().c_str());
 			}
 		}
 
@@ -716,13 +709,12 @@ backend_get_updates_thread (PkBackend *backend)
 		}
 
 		if (!zypp_filter_solvable (_filters, res->satSolvable())) {
-			gchar *package_id = zypp_build_package_id_from_resolvable (res->satSolvable ());
-			pk_backend_package (backend, infoEnum, package_id, res->summary ().c_str ());
 			// some package descriptions generate markup parse failures
 			// causing the update to show empty package lines, comment for now
 			// res->summary ().c_str ());
 			// Test if this still happens!
-			g_free (package_id);
+			zypp_backend_package (backend, infoEnum, res->satSolvable (),
+					      res->summary ().c_str ());
 		}
 	}
 
@@ -1274,11 +1266,8 @@ backend_resolve_thread (PkBackend *backend)
 
 		/* Emit callbacks */
 		for (std::vector<zypp::sat::Solvable>::iterator it = pkgs.begin (); it != pkgs.end (); it++) {
-			const gchar *package_id = zypp_build_package_id_from_resolvable (*it);
 			PkInfoEnum info = it->isSystem () ? PK_INFO_ENUM_INSTALLED : PK_INFO_ENUM_AVAILABLE;
-			pk_backend_package (backend,
-					    info,
-					    package_id,
+			zypp_backend_package (backend, info, *it,
 					    it->lookupStrAttribute (zypp::sat::SolvAttr::summary).c_str ());
 		}
 
@@ -1839,25 +1828,19 @@ backend_what_provides_thread (PkBackend *backend)
 			}
 
 			if (hit && !zypp_filter_solvable (_filters, it->resolvable()->satSolvable())) {
-				gchar *package_id;
-
-				package_id = zypp_build_package_id_from_resolvable (it->resolvable()->satSolvable());
-				pk_backend_package (backend, status, package_id, it->resolvable ()->summary ().c_str ());
-
-				g_free (package_id);
+				zypp_backend_package (backend, status, it->resolvable()->satSolvable(),
+						      it->resolvable ()->summary ().c_str ());
 			}
 			it->statusReset ();
 		}
 		solver.setIgnoreAlreadyRecommended (FALSE);
-	}else{
-		for(zypp::sat::WhatProvides::const_iterator it = prov.begin (); it != prov.end (); it++) {
-
+	} else {
+		for (zypp::sat::WhatProvides::const_iterator it = prov.begin (); it != prov.end (); it++) {
 			if (zypp_filter_solvable (_filters, *it))
 				continue;
 			
-			gchar *package_id = zypp_build_package_id_from_resolvable (*it);
 			PkInfoEnum info = it->isSystem () ? PK_INFO_ENUM_INSTALLED : PK_INFO_ENUM_AVAILABLE;
-			pk_backend_package (backend, info, package_id, it->lookupStrAttribute (zypp::sat::SolvAttr::summary).c_str ());
+			zypp_backend_package (backend, info, *it, it->lookupStrAttribute (zypp::sat::SolvAttr::summary).c_str ());
 		}
 	}
 
diff --git a/backends/zypp/zypp-utils.cpp b/backends/zypp/zypp-utils.cpp
index ffcdde6..8d2f8fe 100644
--- a/backends/zypp/zypp-utils.cpp
+++ b/backends/zypp/zypp-utils.cpp
@@ -586,18 +586,15 @@ zypp_emit_filtered_packages_in_list (PkBackend *backend, const std::vector<zypp:
 
 	for (std::vector<zypp::sat::Solvable>::const_iterator it = v.begin ();
 			it != v.end (); it++) {
-		gchar *package_id = zypp_build_package_id_from_resolvable (*it);
 
 		if (zypp_filter_solvable (filters, *it))
 			continue;
-
-		pk_backend_package (backend,
-			    it->isSystem() == true ?
-				PK_INFO_ENUM_INSTALLED :
-				PK_INFO_ENUM_AVAILABLE,
-			    package_id,
-			    it->lookupStrAttribute (zypp::sat::SolvAttr::summary).c_str ());
-		g_free (package_id);
+		zypp_backend_package (backend, 
+				      it->isSystem() == true ?
+				      PK_INFO_ENUM_INSTALLED :
+				      PK_INFO_ENUM_AVAILABLE,
+				      *it,
+				      it->lookupStrAttribute (zypp::sat::SolvAttr::summary).c_str ());
 	}
 }
 
@@ -994,3 +991,13 @@ zypp_backend_finished_error (PkBackend  *backend, PkErrorEnum err_code,
 
 	return FALSE;
 }
+
+void
+zypp_backend_package (PkBackend *backend, PkInfoEnum info,
+		      const zypp::sat::Solvable &pkg,
+		      const char *opt_summary)
+{
+	gchar *id = zypp_build_package_id_from_resolvable (pkg);
+	pk_backend_package (backend, info, id, opt_summary);
+	g_free (id);
+}
diff --git a/backends/zypp/zypp-utils.h b/backends/zypp/zypp-utils.h
index 58d3b6b..0847110 100644
--- a/backends/zypp/zypp-utils.h
+++ b/backends/zypp/zypp-utils.h
@@ -191,7 +191,7 @@ gboolean zypp_filter_solvable (PkBitfield filters, const zypp::sat::Solvable &it
 /**
  * apply filters to a list.
  */
-void zypp_emit_filtered_packages_in_list (PkBackend *backend, const std::vector<zypp::sat::Solvable> &list);
+void     zypp_emit_filtered_packages_in_list (PkBackend *backend, const std::vector<zypp::sat::Solvable> &list);
 
 /**
   * convert a std::set<zypp::sat::Solvable to gchar ** array
@@ -214,5 +214,12 @@ gboolean zypp_refresh_cache (PkBackend *backend, gboolean force);
 gboolean zypp_backend_finished_error (PkBackend  *backend, PkErrorEnum err_code,
 				      const char *format, ...);
 
+/**
+  * helper to emit pk package signals for a backend for a zypp solvable
+  */
+void     zypp_backend_package (PkBackend *backend, PkInfoEnum info,
+			       const zypp::sat::Solvable &pkg,
+			       const char *opt_summary);
+
 #endif // _ZYPP_UTILS_H_
 
commit dc2dfa2d1949c27418320936799ba9a23eed3962
Author: Michael Meeks <michael.meeks at novell.com>
Date:   Tue May 4 15:05:51 2010 +0100

    Fix multiple bugs in 'resolve'
      + resolve should return all matching results, not just one
      + it needs to support the 'NEWEST' filter
    
    Also remove all manual calls to pk_package_id_build, and update
    signature to zypp_build_package_id_from_resolvable to help.

diff --git a/backends/zypp/pk-backend-zypp.cpp b/backends/zypp/pk-backend-zypp.cpp
index 0e0e3ac..3aa56fd 100644
--- a/backends/zypp/pk-backend-zypp.cpp
+++ b/backends/zypp/pk-backend-zypp.cpp
@@ -219,13 +219,8 @@ backend_get_requires_thread (PkBackend *backend)
 
 			if (hit && !zypp_filter_solvable (_filters, it->resolvable()->satSolvable())) {
 				gchar *package_id;
-				package_id = pk_package_id_build ( it->resolvable ()->name ().c_str(),
-						it->resolvable ()->edition ().asString ().c_str(),
-						it->resolvable ()->arch ().c_str(),
-						it->resolvable ()->repoInfo().alias ().c_str ());
-
+				package_id = zypp_build_package_id_from_resolvable (it->resolvable()->satSolvable());
 				pk_backend_package (backend, status, package_id, it->resolvable ()->summary ().c_str ());
-
 				g_free (package_id);
 			}
 			it->statusReset ();
@@ -450,10 +445,7 @@ backend_get_depends_thread (PkBackend *backend)
 			if (!zypp_filter_solvable (_filters, it->second)) {
 				gchar *package_id_temp;
 
-				package_id_temp = pk_package_id_build (it->second.name ().c_str(),
-								       it->second.edition ().asString ().c_str(),
-								       it->second.arch ().c_str(),
-								       it->second.repository ().alias ().c_str());
+				package_id_temp = zypp_build_package_id_from_resolvable (it->second);
 				pk_backend_package (backend, info,
 						    package_id_temp,
 						    item->summary ().c_str());
@@ -1233,47 +1225,68 @@ backend_resolve_thread (PkBackend *backend)
 
 	pk_backend_set_status (backend, PK_STATUS_ENUM_QUERY);
 
-	for (uint i = 0; i < g_strv_length(package_ids); i++) {
+	for (uint i = 0; i < g_strv_length (package_ids); i++) {
 		std::vector<zypp::sat::Solvable> *v;
-		std::vector<zypp::sat::Solvable> *v2;
+
+		/* Build a list of packages with this name */
 		v = zypp_get_packages_by_name (package_ids[i], zypp::ResKind::package, TRUE);
-		v2 = zypp_get_packages_by_name (package_ids[i], zypp::ResKind::srcpackage, TRUE);
 
-		v->insert (v->end (), v2->begin (), v2->end ());
+		if (!pk_bitfield_contain (_filters, PK_FILTER_ENUM_NOT_SOURCE)) {
+			std::vector<zypp::sat::Solvable> *src;
+			src = zypp_get_packages_by_name (package_ids[i], zypp::ResKind::srcpackage, TRUE);
+			v->insert (v->end (), src->begin (), src->end ());
+			delete (src);
+		}
 
-		zypp::sat::Solvable package;
-		for (std::vector<zypp::sat::Solvable>::iterator it = v->begin ();
-				it != v->end (); it++) {
+		zypp::sat::Solvable newest;
+		std::vector<zypp::sat::Solvable> pkgs;
+
+		/* Filter the list of packages with this name to 'pkgs' */
+		for (std::vector<zypp::sat::Solvable>::iterator it = v->begin (); it != v->end (); it++) {
 			if (zypp_filter_solvable (_filters, *it))
 				continue;
 
-			const char *version = it->edition ().asString ().c_str ();
-			if (package == zypp::sat::Solvable::noSolvable) {
-				package = *it;
-			} else if (g_ascii_strcasecmp (version, package.edition ().asString ().c_str ()) > 0) {
-				package = *it;
+			if (*it == zypp::sat::Solvable::noSolvable) {
+				egg_debug ("WARNING - changed behaviour - filtering pseudo-system pkgs!");
+				continue;
+			}
+
+			if (newest == zypp::sat::Solvable::noSolvable)
+				newest = *it;
+			else if (it->edition().match (newest.edition()) > 0) {
+				egg_debug ("TESTME: '%s' > '%s'",
+					   it->asString().c_str(),
+					   newest.asString().c_str());
+				newest = *it;
 			}
+			pkgs.push_back (*it);
+		}
+
+		/* 'newest' filter support */
+		if (pk_bitfield_contain (_filters, PK_FILTER_ENUM_NEWEST)) {
+			pkgs.clear();
+			pkgs.push_back (newest);
+		} else if (pk_bitfield_contain (_filters, PK_FILTER_ENUM_NOT_NEWEST)) {
+			pkgs.erase (std::find (pkgs.begin (), pkgs.end(), newest));
 		}
 
 		delete (v);
-		delete (v2);
 
-		if (package == NULL) {
+		/* Emit callbacks */
+		for (std::vector<zypp::sat::Solvable>::iterator it = pkgs.begin (); it != pkgs.end (); it++) {
+			const gchar *package_id = zypp_build_package_id_from_resolvable (*it);
+			PkInfoEnum info = it->isSystem () ? PK_INFO_ENUM_INSTALLED : PK_INFO_ENUM_AVAILABLE;
+			pk_backend_package (backend,
+					    info,
+					    package_id,
+					    it->lookupStrAttribute (zypp::sat::SolvAttr::summary).c_str ());
+		}
+
+		if (pkgs.size() < 1) {
 			return zypp_backend_finished_error (
 				backend, PK_ERROR_ENUM_PACKAGE_NOT_FOUND,
 				"couldn't find package");
 		}
-
-		if (zypp_filter_solvable (_filters, package))
-			continue;
-
-		const gchar *package_id = zypp_build_package_id_from_resolvable (package);
-		PkInfoEnum info = package.isSystem () ? PK_INFO_ENUM_INSTALLED : PK_INFO_ENUM_AVAILABLE;
-
-		pk_backend_package (backend,
-				    info,
-				    package_id,
-				    package.lookupStrAttribute (zypp::sat::SolvAttr::summary).c_str ());
 	}
 
 	pk_backend_finished (backend);
@@ -1827,11 +1840,8 @@ backend_what_provides_thread (PkBackend *backend)
 
 			if (hit && !zypp_filter_solvable (_filters, it->resolvable()->satSolvable())) {
 				gchar *package_id;
-				package_id = pk_package_id_build ( it->resolvable ()->name ().c_str(),
-						it->resolvable ()->edition ().asString ().c_str(),
-						it->resolvable ()->arch ().c_str(),
-						it->resolvable ()->repoInfo().alias ().c_str ());
 
+				package_id = zypp_build_package_id_from_resolvable (it->resolvable()->satSolvable());
 				pk_backend_package (backend, status, package_id, it->resolvable ()->summary ().c_str ());
 
 				g_free (package_id);
diff --git a/backends/zypp/zypp-utils.cpp b/backends/zypp/zypp-utils.cpp
index 03aeed4..ffcdde6 100644
--- a/backends/zypp/zypp-utils.cpp
+++ b/backends/zypp/zypp-utils.cpp
@@ -412,7 +412,7 @@ zypp_get_package_by_id (const gchar *package_id)
 }
 
 gchar *
-zypp_build_package_id_from_resolvable (zypp::sat::Solvable resolvable)
+zypp_build_package_id_from_resolvable (const zypp::sat::Solvable &resolvable)
 {
 	gchar *package_id;
 
@@ -543,6 +543,8 @@ zypp_filter_solvable (PkBitfield filters, const zypp::sat::Solvable &item)
 	if (!filters)
 		return FALSE;
 
+	//const gchar * myarch = zypp::ZConfig::defaultSystemArchitecture().asString().c_str();
+
 	for (guint i = 0; i < PK_FILTER_ENUM_LAST; i++) {
 		if ((filters & pk_bitfield_value (i)) == 0)
 			continue;
@@ -567,8 +569,11 @@ zypp_filter_solvable (PkBitfield filters, const zypp::sat::Solvable &item)
 		if (i == PK_FILTER_ENUM_NOT_SOURCE && zypp::isKind<zypp::SrcPackage>(item)) {
 			return TRUE;
 		}
-		//const gchar * myarch = zypp::ZConfig::defaultSystemArchitecture().asString().c_str();
-		//egg_debug ("my default arch is %s", myarch);
+
+		// FIXME: add enums
+		// PK_FILTER_ENUM_DEVELOPMENT,
+		// PK_FILTER_ENUM_NOT_DEVELOPMENT,
+
 	}
 
 	return FALSE;
diff --git a/backends/zypp/zypp-utils.h b/backends/zypp/zypp-utils.h
index ad2cda6..58d3b6b 100644
--- a/backends/zypp/zypp-utils.h
+++ b/backends/zypp/zypp-utils.h
@@ -135,7 +135,7 @@ zypp::sat::Solvable zypp_get_package_by_id (const gchar *package_id);
  * Build a package_id from the specified resolvable.  The returned
  * gchar * should be freed with g_free ().
  */
-gchar * zypp_build_package_id_from_resolvable (zypp::sat::Solvable resolvable);
+gchar * zypp_build_package_id_from_resolvable (const zypp::sat::Solvable &resolvable);
 
 /**
   * Get the RepoInfo


More information about the PackageKit-commit mailing list