org.openmoko.april-update: 82f7f16eaf281073f9ad22db54d12cda5d9e4bbf

oe at monotone.openmoko.org oe at monotone.openmoko.org
Mon May 19 20:31:18 CEST 2008


revision:            82f7f16eaf281073f9ad22db54d12cda5d9e4bbf
date:                2008-05-19T17:33:59
author:              julian_chu at openmoko.com
branch:              org.openmoko.april-update
changelog:

Change revision of packagekit.
To make it buildable, add a patch to it.

In next time we update the packagekit version, this patch doesn't need anymore.
( it should enter in upstream)


manifest:
format_version "1"

new_manifest [446721b7a3644450350448e1585142a885d4cab3]

old_revision [351bffef8e49c1f7cd9078067b74ce91361a1230]

add_file "packages/packagekit/files/d1e096c3267c1c9492041382b954e9327bc8bbec.patch"
 content [3f6aeebb5d160701e6668a69f935978eca1ce3e5]

patch "conf/distro/include/sane-srcrevs.inc"
 from [31946f0f79f0bc829893d6218a66ceb88a01c3b2]
   to [12ee6fdf6e7ea39bbac6764c1464c053eae524eb]

patch "packages/packagekit/packagekit_git.bb"
 from [d1b9bdd3d88e67835cab9f7b7bb6155fc89f2362]
   to [87d921eb998dab5f586a8f64d30c9921be03d5eb]
-------------- next part --------------
#
#
# add_file "packages/packagekit/files/d1e096c3267c1c9492041382b954e9327bc8bbec.patch"
#  content [3f6aeebb5d160701e6668a69f935978eca1ce3e5]
# 
# patch "conf/distro/include/sane-srcrevs.inc"
#  from [31946f0f79f0bc829893d6218a66ceb88a01c3b2]
#    to [12ee6fdf6e7ea39bbac6764c1464c053eae524eb]
# 
# patch "packages/packagekit/packagekit_git.bb"
#  from [d1b9bdd3d88e67835cab9f7b7bb6155fc89f2362]
#    to [87d921eb998dab5f586a8f64d30c9921be03d5eb]
#
============================================================
--- packages/packagekit/files/d1e096c3267c1c9492041382b954e9327bc8bbec.patch	3f6aeebb5d160701e6668a69f935978eca1ce3e5
+++ packages/packagekit/files/d1e096c3267c1c9492041382b954e9327bc8bbec.patch	3f6aeebb5d160701e6668a69f935978eca1ce3e5
@@ -0,0 +1,2938 @@
+diff --git a/backends/alpm/pk-backend-alpm.c b/backends/alpm/pk-backend-alpm.c
+index 3270e42..45e7a44 100644
+--- a/backends/alpm/pk-backend-alpm.c
++++ b/backends/alpm/pk-backend-alpm.c
+@@ -895,7 +895,7 @@ backend_get_repo_list (PkBackend *backend, PkFilterEnum filters)
+ static gboolean
+ backend_install_files_thread (PkBackend *backend)
+ {
+-	pk_backend_no_percentage_updates (backend);
++	pk_backend_set_percentage (backend, PK_BACKEND_PERCENTAGE_INVALID);
+ 
+ 	gchar **full_paths = pk_backend_get_strv (backend, "full_paths");
+ 
+@@ -1050,7 +1050,7 @@ backend_install_packages (PkBackend *backend, gchar **package_ids)
+ static gboolean
+ backend_refresh_cache_thread (PkBackend *backend)
+ {
+-	pk_backend_no_percentage_updates (backend);
++	pk_backend_set_percentage (backend, PK_BACKEND_PERCENTAGE_INVALID);
+ 
+ 	if (alpm_trans_init (PM_TRANS_TYPE_SYNC, PM_TRANS_FLAG_NOSCRIPTLET, cb_trans_evt, cb_trans_conv, cb_trans_progress) != 0) {
+ 		pk_backend_error_code (backend, PK_ERROR_ENUM_TRANSACTION_ERROR, alpm_strerror (pm_errno));
+diff --git a/backends/apt/pk-apt-build-db.cpp b/backends/apt/pk-apt-build-db.cpp
+index d47c348..885275d 100644
+--- a/backends/apt/pk-apt-build-db.cpp
++++ b/backends/apt/pk-apt-build-db.cpp
+@@ -40,7 +40,7 @@ void apt_build_db(PkBackend * backend, sqlite3 *db)
+ 	sqlite3_stmt *package = NULL;
+ 
+ 	pk_backend_set_status(backend, PK_STATUS_ENUM_QUERY);
+-	pk_backend_no_percentage_updates(backend);
++	pk_backend_set_percentage (backend, PK_BACKEND_PERCENTAGE_INVALID);
+ 
+ 	sdir = g_build_filename(_config->Find("Dir").c_str(),_config->Find("Dir::State").c_str(),_config->Find("Dir::State::lists").c_str(), NULL);
+ 	dir = g_dir_open(sdir,0,&error);
+diff --git a/backends/apt/pk-sqlite-pkg-cache.cpp b/backends/apt/pk-sqlite-pkg-cache.cpp
+index 770fcdf..1bf9a50 100644
+--- a/backends/apt/pk-sqlite-pkg-cache.cpp
++++ b/backends/apt/pk-sqlite-pkg-cache.cpp
+@@ -81,7 +81,7 @@ sqlite_search_packages_thread (PkBackend *backend)
+ 	const gchar *search;
+ 
+ 	pk_backend_set_status(backend, PK_STATUS_ENUM_QUERY);
+-	pk_backend_no_percentage_updates(backend);
++	pk_backend_set_percentage (backend, PK_BACKEND_PERCENTAGE_INVALID);
+ 	type = pk_backend_get_uint (backend, "type");
+ 	search = pk_backend_get_string (backend, "search");
+ 
+@@ -176,7 +176,7 @@ sqlite_get_details_thread (PkBackend *backend)
+ 	}
+ 
+ 	pk_backend_set_status(backend, PK_STATUS_ENUM_QUERY);
+-	pk_backend_no_percentage_updates(backend);
++	pk_backend_set_percentage (backend, PK_BACKEND_PERCENTAGE_INVALID);
+ 
+ 	pk_debug("finding %s", pi->name);
+ 
+diff --git a/backends/box/pk-backend-box.c b/backends/box/pk-backend-box.c
+index b7b8167..9263781 100644
+--- a/backends/box/pk-backend-box.c
++++ b/backends/box/pk-backend-box.c
+@@ -138,7 +138,7 @@ backend_find_packages_thread (PkBackend *backend)
+ 		filter_box = filter_box | PKG_SEARCH_DETAILS;
+ 	}
+ 
+-	pk_backend_no_percentage_updates (backend);
++	pk_backend_set_percentage (backend, PK_BACKEND_PERCENTAGE_INVALID);
+ 
+ 	db = db_open();
+ 
+diff --git a/backends/dummy/pk-backend-dummy.c b/backends/dummy/pk-backend-dummy.c
+index 49d4e5a..2df445e 100644
+--- a/backends/dummy/pk-backend-dummy.c
++++ b/backends/dummy/pk-backend-dummy.c
+@@ -254,7 +254,7 @@ static void
+ backend_get_updates (PkBackend *backend, PkFilterEnum filters)
+ {
+ 	pk_backend_set_status (backend, PK_STATUS_ENUM_QUERY);
+-	pk_backend_no_percentage_updates (backend);
++	pk_backend_set_percentage (backend, PK_BACKEND_PERCENTAGE_INVALID);
+ 	/* check network state */
+ 	if (!pk_backend_is_online (backend)) {
+ 		pk_backend_error_code (backend, PK_ERROR_ENUM_NO_NETWORK, "Cannot check when offline");
+@@ -268,6 +268,8 @@ static gboolean
+ backend_install_timeout (gpointer data)
+ {
+ 	PkBackend *backend = (PkBackend *) data;
++	guint sub_percent;
++
+ 	if (_progress_percentage == 100) {
+ 		pk_backend_finished (backend);
+ 		return FALSE;
+@@ -283,9 +285,18 @@ backend_install_timeout (gpointer data)
+ 		pk_backend_package (backend, PK_INFO_ENUM_INSTALLING,
+ 				    "gtkhtml2-devel;2.19.1-0.fc8;i386;fedora",
+ 				    "Devel files for gtkhtml");
++		/* this duplicate package should be ignored */
++		pk_backend_package (backend, PK_INFO_ENUM_INSTALLING,
++				    "gtkhtml2-devel;2.19.1-0.fc8;i386;fedora", NULL);
+ 		pk_backend_set_status (backend, PK_STATUS_ENUM_INSTALL);
+ 	}
+-	_progress_percentage += 10;
++	if (_progress_percentage > 30 && _progress_percentage < 50) {
++		sub_percent = ((gfloat) (_progress_percentage - 30.0f) / 20.0f) * 100.0f;
++		pk_backend_set_sub_percentage (backend, sub_percent);
++	} else {
++		pk_backend_set_sub_percentage (backend, PK_BACKEND_PERCENTAGE_INVALID);
++	}
++	_progress_percentage += 1;
+ 	pk_backend_set_percentage (backend, _progress_percentage);
+ 	return TRUE;
+ }
+@@ -348,7 +359,7 @@ backend_install_packages (PkBackend *backend, gchar **package_ids)
+ 	pk_backend_package (backend, PK_INFO_ENUM_DOWNLOADING,
+ 			    "gtkhtml2;2.19.1-4.fc8;i386;fedora",
+ 			    "An HTML widget for GTK+ 2.0");
+-	_signal_timeout = g_timeout_add (1000, backend_install_timeout, backend);
++	_signal_timeout = g_timeout_add (100, backend_install_timeout, backend);
+ }
+ 
+ /**
+@@ -526,7 +537,7 @@ backend_search_name_timeout (gpointer data)
+ static void
+ backend_search_name (PkBackend *backend, PkFilterEnum filters, const gchar *search)
+ {
+-	pk_backend_no_percentage_updates (backend);
++	pk_backend_set_percentage (backend, PK_BACKEND_PERCENTAGE_INVALID);
+ 	pk_backend_set_allow_cancel (backend, TRUE);
+ 	pk_backend_set_status (backend, PK_STATUS_ENUM_QUERY);
+ 	_signal_timeout = g_timeout_add (2000, backend_search_name_timeout, backend);
+diff --git a/backends/opkg/pk-backend-opkg.c b/backends/opkg/pk-backend-opkg.c
+index ecc97be..7649bab 100644
+--- a/backends/opkg/pk-backend-opkg.c
++++ b/backends/opkg/pk-backend-opkg.c
+@@ -155,6 +155,38 @@ pk_opkg_progress_cb (opkg_t *opkg, const opkg_progress_data_t *pdata, void *data
+ 		return;
+ 
+ 	pk_backend_set_percentage (backend, pdata->percentage);
++	if (pdata->package)
++	{
++		gchar *uid;
++		opkg_package_t *pkg = pdata->package;
++		gint status = PK_INFO_ENUM_UNKNOWN;
++
++		uid = g_strdup_printf ("%s;%s;%s;",
++			pkg->name, pkg->version, pkg->architecture);
++
++		if (pdata->action == OPKG_DOWNLOAD)
++			status = PK_INFO_ENUM_DOWNLOADING;
++		else if (pdata->action == OPKG_INSTALL)
++			status = PK_INFO_ENUM_INSTALLING;
++		else if (pdata->action == OPKG_REMOVE)
++			status = PK_INFO_ENUM_REMOVING;
++
++		pk_backend_package (backend, status, uid, pkg->description);
++		g_free (uid);
++	}
++
++	switch (pdata->action)
++	{
++	case OPKG_DOWNLOAD:
++		pk_backend_set_status (backend, PK_STATUS_ENUM_DOWNLOAD);
++		break;
++	case OPKG_INSTALL:
++		pk_backend_set_status (backend, PK_STATUS_ENUM_INSTALL);
++		break;
++	case OPKG_REMOVE:
++		pk_backend_set_status (backend, PK_STATUS_ENUM_REMOVE);
++		break;
++	}
+ }
+ 
+ static gboolean
+@@ -163,8 +195,12 @@ backend_refresh_cache_thread (PkBackend *backend)
+ 	int ret;
+ 
+ 	ret = opkg_update_package_lists (opkg, pk_opkg_progress_cb, backend);
++
+ 	if (ret) {
+-		opkg_unknown_error (backend, ret, "Refreshing cache");
++		if (ret == OPKG_DOWNLOAD_FAILED)
++			pk_backend_error_code (backend, PK_ERROR_ENUM_REPO_NOT_AVAILABLE, NULL);
++		else
++			opkg_unknown_error (backend, ret, "Refreshing cache");
+ 	}
+ 	pk_backend_finished (backend);
+ 
+@@ -178,7 +214,7 @@ static void
+ backend_refresh_cache (PkBackend *backend, gboolean force)
+ {
+ 	pk_backend_set_status (backend, PK_STATUS_ENUM_REFRESH_CACHE);
+-	pk_backend_no_percentage_updates (backend);
++	pk_backend_set_percentage (backend, PK_BACKEND_PERCENTAGE_INVALID);
+ 
+ 
+ 	pk_backend_thread_create (backend, backend_refresh_cache_thread);
+@@ -279,7 +315,7 @@ backend_search_name (PkBackend *backend, PkFilterEnum filters, const gchar *sear
+ 
+ 
+ 	pk_backend_set_status (backend, PK_STATUS_ENUM_QUERY);
+-	pk_backend_no_percentage_updates (backend);
++	pk_backend_set_percentage (backend, PK_BACKEND_PERCENTAGE_INVALID);
+ 
+ 	params = g_new0 (SearchParams, 1);
+ 	params->filters = filters;
+@@ -301,7 +337,7 @@ backend_search_description (PkBackend *backend, PkFilterEnum filters, const gcha
+ 
+ 
+ 	pk_backend_set_status (backend, PK_STATUS_ENUM_QUERY);
+-	pk_backend_no_percentage_updates (backend);
++	pk_backend_set_percentage (backend, PK_BACKEND_PERCENTAGE_INVALID);
+ 
+ 	params = g_new0 (SearchParams, 1);
+ 	params->filters = filters;
+@@ -320,7 +356,7 @@ backend_search_group (PkBackend *backend, PkFilterEnum filters, const gchar *sea
+ 
+ 
+ 	pk_backend_set_status (backend, PK_STATUS_ENUM_QUERY);
+-	pk_backend_no_percentage_updates (backend);
++	pk_backend_set_percentage (backend, PK_BACKEND_PERCENTAGE_INVALID);
+ 
+ 	params = g_new0 (SearchParams, 1);
+ 	params->filters = filters;
+@@ -337,30 +373,52 @@ static gboolean
+ backend_install_packages_thread (PkBackend *backend)
+ {
+ 	PkPackageId *pi;
+-	gint err;
+-	const gchar *package_id;
++	gint err, i;
++	gchar **package_ids;
+ 
+-	package_id = pk_backend_get_string (backend, "pkid");
+-	pk_backend_package (backend, PK_INFO_ENUM_INSTALLING, package_id, NULL);
++	package_ids = pk_backend_get_strv (backend, "pkids");
+ 
+-	pi = pk_package_id_new_from_string (package_id);
++	err = 0;
++
++	for (i = 0; package_ids[i]; i++)
++	{
++		pk_backend_package (backend, PK_INFO_ENUM_INSTALLING, package_ids[0], NULL);
+ 
+-	err = opkg_install_package (opkg, pi->name, pk_opkg_progress_cb, backend);
+-	if (err != 0)
+-		opkg_unknown_error (backend, err, "Install");
++		pi = pk_package_id_new_from_string (package_ids[0]);
++
++		err = opkg_install_package (opkg, pi->name, pk_opkg_progress_cb, backend);
++		switch (err)
++		{
++		case OPKG_NO_ERROR:
++			break;
++		case OPKG_DEPENDANCIES_FAILED:
++			pk_backend_error_code (backend, PK_ERROR_ENUM_DEP_RESOLUTION_FAILED, NULL);
++			break;
++		case OPKG_PACKAGE_ALREADY_INSTALLED:
++			pk_backend_error_code (backend, PK_ERROR_ENUM_PACKAGE_ALREADY_INSTALLED, NULL);
++			break;
++		case OPKG_PACKAGE_NOT_AVAILABLE:
++			pk_backend_error_code (backend, PK_ERROR_ENUM_PACKAGE_NOT_FOUND, NULL);
++			break;
++		default:
++			opkg_unknown_error (backend, err, "Install");
++		}
++		pk_package_id_free (pi);
++		if (err != 0)
++			break;
++	}
+ 
+-	pk_package_id_free (pi);
+ 	pk_backend_finished (backend);
+ 	return (err == 0);
+ }
+ 
+ static void
+-backend_install_packages (PkBackend *backend, gchar **package_id)
++backend_install_packages (PkBackend *backend, gchar **package_ids)
+ {
+-	pk_backend_no_percentage_updates (backend);
++	pk_backend_set_percentage (backend, PK_BACKEND_PERCENTAGE_INVALID);
+ 	pk_backend_set_status (backend, PK_STATUS_ENUM_INSTALL);
+ 
+-	pk_backend_set_string (backend, "pkid", package_id[0]);
++	pk_backend_set_strv (backend, "pkids", package_ids);
+ 
+ 	pk_backend_thread_create (backend, backend_install_packages_thread);
+ }
+@@ -369,7 +427,7 @@ static gboolean
+ backend_remove_packages_thread (PkBackend *backend)
+ {
+ 	PkPackageId *pi;
+-	gint err;
++	gint err, i;
+ 	gchar **package_ids;
+ 	gboolean allow_deps;
+ 	gboolean autoremove;
+@@ -382,19 +440,34 @@ backend_remove_packages_thread (PkBackend *backend)
+ 	autoremove = GPOINTER_TO_INT (data[2]);
+ 	g_free (data);
+ 
+-	pi = pk_package_id_new_from_string (package_ids[0]);
+-	pk_backend_package (backend, PK_INFO_ENUM_REMOVING, package_ids[0], NULL);
+-
+ 	opkg_set_option (opkg, "autoremove", &autoremove);
+ 	opkg_set_option (opkg, "force_removal_of_dependent_packages", &allow_deps);
+ 
+-	err = opkg_remove_package (opkg, pi->name, pk_opkg_progress_cb, backend);
++	err = 0;
+ 
+-	/* TODO: improve error reporting */
+-	if (err != 0)
+-		opkg_unknown_error (backend, err, "Remove");
++	for (i = 0; package_ids[i]; i++)
++	{
++		pi = pk_package_id_new_from_string (package_ids[0]);
++		pk_backend_package (backend, PK_INFO_ENUM_REMOVING, package_ids[0], NULL);
++
++		err = opkg_remove_package (opkg, pi->name, pk_opkg_progress_cb, backend);
++
++		switch (err)
++		{
++		case OPKG_NO_ERROR:
++			break;
++		case OPKG_PACKAGE_NOT_INSTALLED:
++			pk_backend_error_code (backend, PK_ERROR_ENUM_PACKAGE_NOT_INSTALLED, NULL);
++			break;
++		default:
++			opkg_unknown_error (backend, err, "Remove");
++		}
++		pk_package_id_free (pi);
++
++		if (err != 0)
++			break;
++	}
+ 
+-	pk_package_id_free (pi);
+ 	pk_backend_finished (backend);
+ 	return (err == 0);
+ }
+@@ -405,7 +478,7 @@ backend_remove_packages (PkBackend *backend, gchar **package_ids, gboolean allow
+ 	gpointer *params;
+ 
+ 	pk_backend_set_status (backend, PK_STATUS_ENUM_REMOVE);
+-	pk_backend_no_percentage_updates (backend);
++	pk_backend_set_percentage (backend, PK_BACKEND_PERCENTAGE_INVALID);
+ 
+ 	/* params is a small array we can pack our thread parameters into */
+ 	params = g_new0 (gpointer, 2);
+@@ -450,7 +523,7 @@ static void
+ backend_update_system (PkBackend *backend)
+ {
+ 	pk_backend_set_status (backend, PK_STATUS_ENUM_UPDATE);
+-	pk_backend_no_percentage_updates (backend);
++	pk_backend_set_percentage (backend, PK_BACKEND_PERCENTAGE_INVALID);
+ 
+ 	pk_backend_thread_create (backend, backend_update_system_thread);
+ }
+@@ -478,8 +551,14 @@ backend_update_package_thread (PkBackend *backend)
+ 	}
+ 
+ 	err = opkg_upgrade_package (opkg, pi->name, pk_opkg_progress_cb, backend);
+-
+-	if (err != 0) {
++	switch (err)
++	{
++	case OPKG_NO_ERROR:
++		break;
++	case OPKG_PACKAGE_NOT_INSTALLED:
++		pk_backend_error_code (backend, PK_ERROR_ENUM_PACKAGE_NOT_INSTALLED, NULL);
++		break;
++	default:
+ 		opkg_unknown_error (backend, err, "Update package");
+ 	}
+ 
+@@ -494,7 +573,7 @@ backend_update_packages (PkBackend *backend, gchar **package_ids)
+ 	gint i;
+ 
+ 	pk_backend_set_status (backend, PK_STATUS_ENUM_UPDATE);
+-	pk_backend_no_percentage_updates (backend);
++	pk_backend_set_percentage (backend, PK_BACKEND_PERCENTAGE_INVALID);
+ 
+ 	for (i = 0; package_ids[i]; i++) {
+ 		pk_backend_set_string (backend, "pkgid", package_ids[i]);
+@@ -536,7 +615,7 @@ static void
+ backend_get_updates (PkBackend *backend, PkFilterEnum filters)
+ {
+ 	pk_backend_set_status (backend, PK_STATUS_ENUM_UPDATE);
+-	pk_backend_no_percentage_updates (backend);
++	pk_backend_set_percentage (backend, PK_BACKEND_PERCENTAGE_INVALID);
+ 
+ 	pk_backend_thread_create (backend, backend_get_updates_thread);
+ }
+@@ -572,19 +651,26 @@ backend_get_details_thread (PkBackend *backend)
+ 	if (pi == NULL)
+ 	{
+ 		pk_backend_error_code (backend, PK_ERROR_ENUM_PACKAGE_ID_INVALID, "invalid package id");
+-		pk_package_id_free (pi);
++		pk_backend_finished (backend);
+ 		return FALSE;
+ 	}
+ 
+ 
+ 	pkg = opkg_find_package (opkg, pi->name, pi->version, pi->arch, pi->data);
++	pk_package_id_free (pi);
++
++	if (!pkg)
++	{
++		pk_backend_error_code (backend, PK_ERROR_ENUM_PACKAGE_NOT_FOUND, NULL);
++		pk_backend_finished (backend);
++		return FALSE;
++	}
+ 
+ 	newid = g_strdup_printf ("%s;%s;%s;%s", pkg->name, pkg->version, pkg->architecture, pkg->repository);
+ 
+ 	pk_backend_details (backend, newid, NULL, 0, pkg->description, pkg->url, pkg->size);
+ 
+ 	g_free (newid);
+-	pk_package_id_free (pi);
+ 	pk_backend_finished (backend);
+ 	return TRUE;
+ }
+@@ -592,7 +678,7 @@ backend_get_details_thread (PkBackend *backend)
+ static void
+ backend_get_details (PkBackend *backend, const gchar *package_id)
+ {
+-	pk_backend_no_percentage_updates (backend);
++	pk_backend_set_percentage (backend, PK_BACKEND_PERCENTAGE_INVALID);
+ 	pk_backend_thread_create (backend, backend_get_details_thread);
+ }
+ 
+diff --git a/backends/test/pk-backend-test-dbus.c b/backends/test/pk-backend-test-dbus.c
+index 5dfea32..76686dc 100644
+--- a/backends/test/pk-backend-test-dbus.c
++++ b/backends/test/pk-backend-test-dbus.c
+@@ -36,7 +36,7 @@ static void
+ backend_search_name (PkBackend *backend, PkFilterEnum filters, const gchar *search)
+ {
+ 	pk_backend_set_allow_cancel (backend, TRUE);
+-	pk_backend_no_percentage_updates (backend);
++	pk_backend_set_percentage (backend, PK_BACKEND_PERCENTAGE_INVALID);
+ 	pk_backend_dbus_search_name (dbus, filters, search);
+ }
+ 
+diff --git a/backends/test/pk-backend-test-spawn.c b/backends/test/pk-backend-test-spawn.c
+index 2958c05..584f44c 100644
+--- a/backends/test/pk-backend-test-spawn.c
++++ b/backends/test/pk-backend-test-spawn.c
+@@ -35,7 +35,7 @@ backend_search_name (PkBackend *backend, PkFilterEnum filters, const gchar *sear
+ {
+ 	gchar *filters_text;
+ 	pk_backend_set_allow_cancel (backend, TRUE);
+-	pk_backend_no_percentage_updates (backend);
++	pk_backend_set_percentage (backend, PK_BACKEND_PERCENTAGE_INVALID);
+ 	filters_text = pk_filter_enums_to_text (filters);
+ 	pk_backend_spawn_helper (spawn, "search-name.sh", filters_text, search, NULL);
+ 	g_free (filters_text);
+diff --git a/backends/test/pk-backend-test-succeed.c b/backends/test/pk-backend-test-succeed.c
+index 17cdc6e..c046c1d 100644
+--- a/backends/test/pk-backend-test-succeed.c
++++ b/backends/test/pk-backend-test-succeed.c
+@@ -236,7 +236,7 @@ backend_search_name_timeout (gpointer data)
+ static void
+ backend_search_name (PkBackend *backend, PkFilterEnum filters, const gchar *search)
+ {
+-	pk_backend_no_percentage_updates (backend);
++	pk_backend_set_percentage (backend, PK_BACKEND_PERCENTAGE_INVALID);
+ 	g_timeout_add (200000, backend_search_name_timeout, backend);
+ }
+ 
+diff --git a/backends/yum/helpers/yumBackend.py b/backends/yum/helpers/yumBackend.py
+index f76e27c..5b2da8f 100644
+--- a/backends/yum/helpers/yumBackend.py
++++ b/backends/yum/helpers/yumBackend.py
+@@ -801,6 +801,8 @@ class PackageKitYumBackend(PackageKitBaseBackend):
+         old_throttle = self.yumbase.conf.throttle
+         self.yumbase.conf.throttle = "60%" # Set bandwidth throttle to 60%
+                                            # to avoid taking all the system's bandwidth.
++        old_skip_broken = self.yumbase.conf.skip_broken
++        self.yumbase.conf.skip_broken = 1
+ 
+         try:
+             txmbr = self.yumbase.update() # Add all updates to Transaction
+@@ -812,6 +814,7 @@ class PackageKitYumBackend(PackageKitBaseBackend):
+             self.error(ERROR_NO_PACKAGES_TO_UPDATE,"Nothing to do")
+ 
+         self.yumbase.conf.throttle = old_throttle
++        self.yumbase.conf.skip_broken = old_skip_broken
+ 
+     def refresh_cache(self):
+         '''
+@@ -905,7 +908,7 @@ class PackageKitYumBackend(PackageKitBaseBackend):
+         if txmbrs:
+             self._runYumTransaction()
+         else:
+-            self.error(ERROR_PACKAGE_ALREADY_INSTALLED,"This package could not be installed as it is already installed")
++            self.error(ERROR_PACKAGE_ALREADY_INSTALLED,"The package is already installed")
+ 
+     def _checkForNewer(self,po):
+         pkgs = self.yumbase.pkgSack.returnNewestByName(name=po.name)
+@@ -1003,7 +1006,7 @@ class PackageKitYumBackend(PackageKitBaseBackend):
+             return False
+ 
+         if self._is_inst(po):
+-            self.error(ERROR_PACKAGE_ALREADY_INSTALLED, "%s is already installed" % str(po))
++            self.error(ERROR_PACKAGE_ALREADY_INSTALLED, "The package %s is already installed" % str(po))
+             return False
+ 
+         if len(self.yumbase.conf.exclude) > 0:
+diff --git a/backends/yum2/helpers/testyum2.py b/backends/yum2/helpers/testyum2.py
+index cdec507..85b47f9 100755
+--- a/backends/yum2/helpers/testyum2.py
++++ b/backends/yum2/helpers/testyum2.py
+@@ -80,7 +80,7 @@ try:
+         #iface.GetPackages(FILTER_INSTALLED,'no')
+     if cmd == 'get-repolist' or cmd == 'all':
+         print "Testing GetRepoList()"
+-        iface.GetRepoList()
++        iface.GetRepoList("")
+     if cmd == 'get-updatedetail' or cmd == 'all':
+         print "Testing GetUpdateDetail(PKG_ID)"
+         iface.GetUpdateDetail(PKG_ID)
+diff --git a/backends/yum2/helpers/yumDBUSBackend.py b/backends/yum2/helpers/yumDBUSBackend.py
+index 9cfed94..29f5b03 100755
+--- a/backends/yum2/helpers/yumDBUSBackend.py
++++ b/backends/yum2/helpers/yumDBUSBackend.py
+@@ -434,7 +434,7 @@ class PackageKitYumBackend(PackageKitBaseBackend):
+         try:
+             pkgGroupDict = self._buildGroupDict()
+             fltlist = filters.split(';')
+-            found = {}
++            installed_nevra = [] # yum returns packages as available even when installed
+ 
+             if not FILTER_NOT_INSTALLED in fltlist:
+                 # Check installed for group
+@@ -450,21 +450,31 @@ class PackageKitYumBackend(PackageKitBaseBackend):
+                             group = groupMap[cg]           # use the pk group name, instead of yum 'category/group'
+                     if group == key:
+                         if self._do_extra_filtering(pkg, fltlist):
+-                            self._show_package(pkg, INFO_INSTALLED)
++                            package_list.append((pkg,INFO_INSTALLED))
++                    installed_nevra.append(self._get_nevra(pkg))                        
++
+             if not FILTER_INSTALLED in fltlist:
+                 # Check available for group
+                 for pkg in self.yumbase.pkgSack:
+                     if self._cancel_check("Search cancelled."):
+                         # _cancel_check() sets the error message, unlocks yum, and calls Finished()
+                         return
+-                    group = GROUP_OTHER
+-                    if pkgGroupDict.has_key(pkg.name):
+-                        cg = pkgGroupDict[pkg.name]
+-                        if groupMap.has_key(cg):
+-                            group = groupMap[cg]
+-                    if group == key:
+-                        if self._do_extra_filtering(pkg, fltlist):
+-                            self._show_package(pkg, INFO_AVAILABLE)
++
++                    nevra = self._get_nevra(pkg)
++                    if nevra not in installed_nevra:
++                        group = GROUP_OTHER
++                        if pkgGroupDict.has_key(pkg.name):
++                            cg = pkgGroupDict[pkg.name]
++                            if groupMap.has_key(cg):
++                                group = groupMap[cg]
++                        if group == key:
++                            if self._do_extra_filtering(pkg, fltlist):
++                                package_list.append((pkg,INFO_AVAILABLE))
++
++        except yum.Errors.GroupsError,e:
++            self._unlock_yum()
++            self.ErrorCode(ERROR_GROUP_NOT_FOUND, str(e))
++            self.Finished(EXIT_FAILED)
+         except yum.Errors.RepoError,e:
+             self.Message(MESSAGE_NOTICE, "The package cache is invalid and is being rebuilt.")
+             self._refresh_yum_cache()
+@@ -473,6 +483,14 @@ class PackageKitYumBackend(PackageKitBaseBackend):
+ 
+             return
+ 
++        # basename filter if specified
++        if FILTER_BASENAME in fltlist:
++            for (pkg,status) in self._basename_filter(package_list):
++                self._show_package(pkg,status)
++        else:
++            for (pkg,status) in package_list:
++                self._show_package(pkg,status)
++
+         self._unlock_yum()
+         self.Finished(EXIT_SUCCESS)
+ 
+@@ -724,6 +742,11 @@ class PackageKitYumBackend(PackageKitBaseBackend):
+             #we might have a rounding error
+             self.PercentageChanged(100)
+ 
++        except yum.Errors.RepoError,e:
++            self._unlock_yum()
++            self.ErrorCode(ERROR_REPO_CONFIGURATION_ERROR,str(e))
++            self.Finished(EXIT_FAILED)
++            self.Exit()
+         except yum.Errors.YumBaseError, e:
+             self._unlock_yum()
+             # This should be a better-defined error, but I'm not sure
+@@ -837,6 +860,7 @@ class PackageKitYumBackend(PackageKitBaseBackend):
+         Needed to be implemented in a sub class
+         '''
+         if inst_file.endswith('.src.rpm'):
++            self._unlock_yum()
+             self.ErrorCode(ERROR_CANNOT_INSTALL_SOURCE_PACKAGE,'Backend will not install a src rpm file')
+             self.Finished(EXIT_FAILED)
+             return
+@@ -1385,30 +1409,30 @@ class PackageKitYumBackend(PackageKitBaseBackend):
+             res = self.yumbase.searchGenerator(searchlist, [key])
+             fltlist = filters.split(';')
+ 
+-            available = []
+-            count = 1
++            seen_nevra = [] # yum returns packages as available even when installed
++            pkg_list = [] # only do the second iteration on not installed pkgs
++            package_list = [] #we can't do emitting as found if we are post-processing
++
+             for (pkg,values) in res:
+                 if self._cancel_check("Search cancelled."):
+                     return False
+                 # are we installed?
+                 if pkg.repo.id == 'installed':
+-                    if FILTER_NOT_INSTALLED not in fltlist:
+-                        if self._do_extra_filtering(pkg,fltlist):
+-                            count+=1
+-                            if count > 100:
+-                                break
+-                            self._show_package(pkg, INFO_INSTALLED)
++                    if self._do_extra_filtering(pkg,fltlist):
++                        package_list.append((pkg,INFO_INSTALLED))
++                        seen_nevra.append(self._get_nevra(pkg))
+                 else:
+-                    available.append(pkg)
++                    pkg_list.append(pkg)
+ 
+-            # Now show available packages.
+-            if FILTER_INSTALLED not in fltlist:
+-                for pkg in available:
+-                    if self._cancel_check("Search cancelled."):
+-                        return False
+-                    if self._do_extra_filtering(pkg,fltlist):
+-                        self._show_package(pkg, INFO_AVAILABLE)
++            for pkg in pkg_list:
++                if self._cancel_check("Search cancelled."):
++                    return False
+ 
++                nevra = self._get_nevra(pkg)
++                if nevra not in seen_nevra:
++                    if self._do_extra_filtering(pkg,fltlist):
++                        package_list.append((pkg,INFO_AVAILABLE))
++                        seen_nevra.append(self._get_nevra(pkg))
+         except yum.Errors.RepoError,e:
+             self.Message(MESSAGE_NOTICE, "The package cache is invalid and is being rebuilt.")
+             self._refresh_yum_cache()
+@@ -1417,13 +1441,22 @@ class PackageKitYumBackend(PackageKitBaseBackend):
+ 
+             return False
+ 
++        # basename filter if specified
++        if FILTER_BASENAME in fltlist:
++            for (pkg,status) in self._basename_filter(package_list):
++                self._show_package(pkg,status)
++        else:
++            for (pkg,status) in package_list:
++                self._show_package(pkg,status)
++
+         return True
+ 
+     def _do_extra_filtering(self,pkg,filterList):
+         ''' do extra filtering (gui,devel etc) '''
+         for filter in filterList:
+             if filter in (FILTER_INSTALLED, FILTER_NOT_INSTALLED):
+-                continue
++                if not self._do_installed_filtering(filter,pkg):
++                    return False
+             elif filter in (FILTER_GUI, FILTER_NOT_GUI):
+                 if not self._do_gui_filtering(filter, pkg):
+                     return False
+@@ -1433,11 +1466,17 @@ class PackageKitYumBackend(PackageKitBaseBackend):
+             elif filter in (FILTER_FREE, FILTER_NOT_FREE):
+                 if not self._do_free_filtering(filter, pkg):
+                     return False
+-            elif filter in (FILTER_BASENAME, FILTER_NOT_BASENAME):
+-                if not self._do_basename_filtering(filter, pkg):
+-                    return False
+         return True
+ 
++    def _do_installed_filtering(self,flt,pkg):
++        isInstalled = False
++        if flt == FILTER_INSTALLED:
++            wantInstalled = True
++        else:
++            wantInstalled = False
++        isInstalled = pkg.repo.id == 'installed'
++        return isInstalled == wantInstalled
++
+     def _do_gui_filtering(self,flt,pkg):
+         isGUI = False
+         if flt == FILTER_GUI:
+@@ -1477,32 +1516,7 @@ class PackageKitYumBackend(PackageKitBaseBackend):
+ 
+         return isFree == wantFree
+ 
+-    def _do_basename_filtering(self,flt,pkg):
+-        if flt == FILTER_BASENAME:
+-            wantBase = True
+-        else:
+-            wantBase = False
+-
+-        isBase = self._check_basename(pkg)
+-
+-        return isBase == wantBase
+ 
+-    def _check_basename(self, pkg):
+-        '''
+-        If a package does not have a source rpm (If that ever
+-        happens), or it does have a source RPM, and the package's name
+-        is the same as the source RPM's name, then we assume it is the
+-        'base' package.
+-        '''
+-        basename = pkg.name
+-
+-        if pkg.sourcerpm:
+-            basename = rpmUtils.miscutils.splitFilename(pkg.sourcerpm)[0]
+-
+-        if basename == pkg.name:
+-            return True
+-
+-        return False
+ 
+     def _is_development_repo(self, repo):
+         if repo.endswith('-debuginfo'):
+@@ -1576,28 +1590,41 @@ class PackageKitYumBackend(PackageKitBaseBackend):
+         '''
+         find a package based on a package id (name;version;arch;repoid)
+         '''
+-        # Split up the id
+-        (n,idver,a,d) = self.get_package_from_id(id)
+-        # get e,v,r from package id version
+-        e,v,r = self._getEVR(idver)
++        # is this an real id or just an name
++        if len(id.split(';')) > 1:
++            # Split up the id
++            (n,idver,a,d) = self.get_package_from_id(id)
++            # get e,v,r from package id version
++            e,v,r = self._getEVR(idver)
++        else:
++            n = id
++            e = v = r = a = None
+         # search the rpmdb for the nevra
+         pkgs = self.yumbase.rpmdb.searchNevra(name=n,epoch=e,ver=v,rel=r,arch=a)
+-        # if the package is found, then return it
++        # if the package is found, then return it (do not have to match the repo_id)
+         if len(pkgs) != 0:
+             return pkgs[0],True
+         # search the pkgSack for the nevra
+-        pkgs = self.yumbase.pkgSack.searchNevra(name=n,epoch=e,ver=v,rel=r,arch=a)
+-        # if the package is found, then return it
+-        if len(pkgs) != 0:
+-            return pkgs[0],False
+-        else:
++        try:
++            pkgs = self.yumbase.pkgSack.searchNevra(name=n,epoch=e,ver=v,rel=r,arch=a)
++        except yum.Errors.RepoError,e:
++            self.error(ERROR_REPO_NOT_AVAILABLE,str(e))
++        # nothing found
++        if len(pkgs) == 0:
+             return None,False
++        # one NEVRA in a single repo
++        if len(pkgs) == 1:
++            return pkgs[0],False
++        # we might have the same NEVRA in multiple repos, match by repo name
++        for pkg in pkgs:
++            if d == pkg.repoid:
++                return pkg,False
++        # repo id did not match
++        return None,False
+ 
+     def _is_inst(self,pkg):
+         return self.yumbase.rpmdb.installed(po=pkg)
+ 
+-
+-
+     def _installable(self, pkg, ematch=False):
+ 
+         """check if the package is reasonably installable, true/false"""
+@@ -1764,6 +1791,57 @@ class PackageKitYumBackend(PackageKitBaseBackend):
+             return INFO_ENHANCEMENT
+         else:
+             return INFO_UNKNOWN
++    def _is_main_package(self,repo):
++        if repo.endswith('-debuginfo'):
++            return False
++        if repo.endswith('-devel'):
++            return False
++        if repo.endswith('-libs'):
++            return False
++        return True
++
++    def _basename_filter(self,package_list):
++        '''
++        Filter the list so that the number of packages are reduced.
++        This is done by only displaying gtk2 rather than gtk2-devel, gtk2-debuginfo, etc.
++        This imlementation is done by comparing the SRPM name, and if not falling back
++        to the first entry.
++        We have to fall back else we don't emit packages where the SRPM does not produce a
++        RPM with the same name, for instance, mono produces mono-core, mono-data and mono-winforms.
++        @package_list: a (pkg,status) list of packages
++        A new list is returned that has been filtered
++        '''
++        base_list = []
++        output_list = []
++        base_list_already_got = []
++
++        #find out the srpm name and add to a new array of compound data
++        for (pkg,status) in package_list:
++            if pkg.sourcerpm:
++                base = rpmUtils.miscutils.splitFilename(pkg.sourcerpm)[0]
++                base_list.append ((pkg,status,base,pkg.version));
++            else:
++                base_list.append ((pkg,status,'nosrpm',pkg.version));
++
++        #find all the packages that match thier basename name (done seporately so we get the "best" match)
++        for (pkg,status,base,version) in base_list:
++            if base == pkg.name and (base,version) not in base_list_already_got:
++                output_list.append((pkg,status))
++                base_list_already_got.append ((base,version))
++
++        #for all the ones not yet got, can we match against a non devel match?
++        for (pkg,status,base,version) in base_list:
++            if (base,version) not in base_list_already_got:
++                if self._is_main_package(pkg.name):
++                    output_list.append((pkg,status))
++                    base_list_already_got.append ((base,version))
++
++        #add the remainder of the packages, which should just be the single debuginfo's
++        for (pkg,status,base,version) in base_list:
++            if (base,version) not in base_list_already_got:
++                output_list.append((pkg,status))
++                base_list_already_got.append ((base,version))
++        return output_list
+ 
+     def _get_obsoleted(self,name):
+         obsoletes = self.yumbase.up.getObsoletesTuples( newest=1 )
+diff --git a/backends/zypp/pk-backend-zypp.cpp b/backends/zypp/pk-backend-zypp.cpp
+index 746da82..15c4b4f 100644
+--- a/backends/zypp/pk-backend-zypp.cpp
++++ b/backends/zypp/pk-backend-zypp.cpp
+@@ -1170,7 +1170,7 @@ backend_find_packages_thread (PkBackend *backend)
+ 	mode = pk_backend_get_uint (backend, "mode");
+ 
+ 	pk_backend_set_status (backend, PK_STATUS_ENUM_QUERY);
+-	pk_backend_no_percentage_updates (backend);
++	pk_backend_set_percentage (backend, PK_BACKEND_PERCENTAGE_INVALID);
+ 
+ 	std::vector<zypp::sat::Solvable> *v = new std::vector<zypp::sat::Solvable>;
+ 	std::vector<zypp::sat::Solvable> *v2 = new std::vector<zypp::sat::Solvable>;
+diff --git a/client/pk-console.c b/client/pk-console.c
+index 8f69068..5a05a8e 100644
+--- a/client/pk-console.c
++++ b/client/pk-console.c
+@@ -50,7 +50,7 @@ static gboolean awaiting_space = FALSE;
+ static gboolean trusted = TRUE;
+ static guint timer_id = 0;
+ static guint percentage_last = 0;
+-static gchar *filename = NULL;
++static gchar **files_cache = NULL;
+ static PkControl *control = NULL;
+ static PkClient *client = NULL;
+ static PkClient *client_task = NULL;
+@@ -494,6 +494,12 @@ pk_console_perhaps_resolve (PkClient *client, PkFilterEnum filter, const gchar *
+ 		return g_strdup (package);
+ 	}
+ 
++	ret = pk_client_reset (client_task, error);
++	if (ret == FALSE) {
++		pk_warning ("failed to reset client task");
++		return NULL;
++	}
++
+ 	/* we need to resolve it */
+ 	ret = pk_client_resolve (client_task, filter, package, error);
+ 	if (ret == FALSE) {
+@@ -549,20 +555,93 @@ pk_console_perhaps_resolve (PkClient *client, PkFilterEnum filter, const gchar *
+ }
+ 
+ /**
+- * pk_console_install_package:
++ * pk_console_install_stuff:
+  **/
+ static gboolean
+-pk_console_install_package (PkClient *client, const gchar *package, GError **error)
++pk_console_install_stuff (PkClient *client, gchar **packages, GError **error)
+ {
+-	gboolean ret;
+-	gchar *package_id;
+-	package_id = pk_console_perhaps_resolve (client, PK_FILTER_ENUM_NOT_INSTALLED, package, error);
+-	if (package_id == NULL) {
+-		g_print ("%s\n", _("Could not find a package with that name to install, or package already installed"));
+-		return FALSE;
++	gboolean ret = TRUE;
++	gboolean is_local;
++	gchar *package_id = NULL;
++	gchar **package_ids = NULL;
++	gchar **files = NULL;
++	guint i;
++	guint length;
++	GPtrArray *array_packages;
++	GPtrArray *array_files;
++
++	array_packages = g_ptr_array_new ();
++	array_files = g_ptr_array_new ();
++	length = g_strv_length (packages);
++	for (i=2; i<length; i++) {
++		is_local = g_file_test (packages[i], G_FILE_TEST_EXISTS);
++		if (is_local) {
++			g_ptr_array_add (array_files, g_strdup (packages[i]));
++		} else {
++			package_id = pk_console_perhaps_resolve (client, PK_FILTER_ENUM_NOT_INSTALLED, packages[i], error);
++			if (package_id == NULL) {
++				g_print ("%s\n", _("Could not find a package with that name to install, or package already installed"));
++				ret = FALSE;
++				break;
++			}
++			g_ptr_array_add (array_packages, package_id);
++		}
+ 	}
+-	ret = pk_client_install_package (client, package_id, error);
+-	g_free (package_id);
++
++	/* one of the resolves failed */
++	if (!ret) {
++		pk_warning ("resolve failed");
++		goto out;
++	}
++
++
++	/* any to process? */
++	if (array_packages->len > 0) {
++		/* convert to strv */
++		package_ids = pk_ptr_array_to_argv (array_packages);
++
++		/* reset */
++		ret = pk_client_reset (client, error);
++		if (!ret) {
++			pk_warning ("failed to reset");
++			goto out;
++		}
++
++		ret = pk_client_install_package (client, package_id, error);
++		if (!ret) {
++			pk_warning ("failed to install packages");
++			goto out;
++		}
++	}
++
++	/* any to process? */
++	if (array_files->len > 0) {
++		/* convert to strv */
++		files = pk_ptr_array_to_argv (array_files);
++
++		/* save for untrusted callback */
++		g_strfreev (files_cache);
++		files_cache = g_strdupv (files);
++
++		/* reset */
++		ret = pk_client_reset (client, error);
++		if (!ret) {
++			pk_warning ("failed to reset");
++			goto out;
++		}
++
++		ret = pk_client_install_files (client, trusted, files, error);
++		if (!ret) {
++			pk_warning ("failed to install files");
++			goto out;
++		}
++	}
++
++out:
++	g_strfreev (package_ids);
++	g_strfreev (files);
++	g_ptr_array_free (array_files, TRUE);
++	g_ptr_array_free (array_packages, TRUE);
+ 	return ret;
+ }
+ 
+@@ -570,16 +649,16 @@ pk_console_install_package (PkClient *client, const gchar *package, GError **err
+  * pk_console_remove_only:
+  **/
+ static gboolean
+-pk_console_remove_only (PkClient *client, const gchar *package_id, gboolean force, gboolean autoremove, GError **error)
++pk_console_remove_only (PkClient *client, gchar **package_ids, gboolean force, GError **error)
+ {
+ 	gboolean ret;
+ 
+-	pk_debug ("remove %s", package_id);
++	pk_debug ("remove+ %s", package_ids[0]);
+ 	ret = pk_client_reset (client, error);
+ 	if (!ret) {
+ 		return ret;
+ 	}
+-	return pk_client_remove_package (client, package_id, force, autoremove, error);
++	return pk_client_remove_packages (client, package_ids, force, FALSE, error);
+ }
+ 
+ /**
+@@ -625,64 +704,99 @@ pk_console_get_prompt (const gchar *question, gboolean defaultyes)
+ }
+ 
+ /**
+- * pk_console_remove_package:
++ * pk_console_remove_packages:
+  **/
+ static gboolean
+-pk_console_remove_package (PkClient *client, const gchar *package, GError **error)
++pk_console_remove_packages (PkClient *client, gchar **packages, GError **error)
+ {
+ 	gchar *package_id;
+-	gboolean ret;
+-	guint length;
++	gboolean ret = TRUE;
+ 	PkPackageItem *item;
+ 	PkPackageId *ident;
+-	guint i;
++	guint i, j;
++	guint size;
++	guint length;
+ 	gboolean remove;
++	GPtrArray *array;
++	gchar **package_ids = NULL;
++	PkPackageList *list;
++
++	array = g_ptr_array_new ();
++	list = pk_package_list_new ();
++	length = g_strv_length (packages);
++	for (i=2; i<length; i++) {
++		package_id = pk_console_perhaps_resolve (client, PK_FILTER_ENUM_INSTALLED, packages[i], error);
++		if (package_id == NULL) {
++			g_print ("%s:%s\n", _("Could not find a package to remove"), packages[i]);
++			ret = FALSE;
++			break;
++		}
++		g_ptr_array_add (array, g_strdup (package_id));
++		pk_debug ("resolved to %s", package_id);
++		g_free (package_id);
++	}
+ 
+-	package_id = pk_console_perhaps_resolve (client, PK_FILTER_ENUM_INSTALLED, package, error);
+-	if (package_id == NULL) {
+-		g_print ("%s\n", _("Could not find a package with that name to remove"));
+-		return FALSE;
++	/* one of the resolves failed */
++	if (!ret) {
++		goto out;
+ 	}
+ 
++	/* convert to strv */
++	package_ids = pk_ptr_array_to_argv (array);
++
+ 	/* are we dumb and can't check for requires? */
+ 	if (!pk_enums_contain (roles, PK_ROLE_ENUM_GET_REQUIRES)) {
+ 		/* no, just try to remove it without deps */
+-		ret = pk_console_remove_only (client, package_id, FALSE, FALSE, error);
+-		g_free (package_id);
+-		return ret;
++		ret = pk_console_remove_only (client, package_ids, FALSE, error);
++		goto out;
+ 	}
+ 
+-	/* see if any packages require this one */
+-	ret = pk_client_reset (client_task, error);
+-	if (!ret) {
+-		pk_warning ("failed to reset");
+-		return FALSE;
++	/* get the requires packages for each package_id */
++	length = g_strv_length (package_ids);
++	for (i=0; i<length; i++) {
++		ret = pk_client_reset (client_task, error);
++		if (!ret) {
++			pk_warning ("failed to reset");
++			break;
++		}
++
++		pk_debug ("Getting installed requires for %s", package_ids[i]);
++		/* see if any packages require this one */
++		ret = pk_client_get_requires (client_task, PK_FILTER_ENUM_INSTALLED, package_ids[i], TRUE, error);
++		if (!ret) {
++			pk_warning ("failed to get requires");
++			break;
++		}
++
++		/* see how many packages there are */
++		size = pk_client_package_buffer_get_size (client_task);
++		for (j=0; j<size; j++) {
++			item = pk_client_package_buffer_get_item (client_task, j);
++			pk_package_list_add_item (list, item);
++		}
+ 	}
+ 
+-	pk_debug ("Getting installed requires for %s", package_id);
+-	ret = pk_client_get_requires (client_task, PK_FILTER_ENUM_INSTALLED, package_id, TRUE, error);
++	/* one of the get-requires failed */
+ 	if (!ret) {
+-		return FALSE;
++		goto out;
+ 	}
+ 
+-	/* see how many packages there are */
+-	length = pk_client_package_buffer_get_size (client_task);
+-
+ 	/* if there are no required packages, just do the remove */
++	length = pk_package_list_get_size (list);
+ 	if (length == 0) {
+ 		pk_debug ("no requires");
+-		ret = pk_console_remove_only (client, package_id, FALSE, FALSE, error);
+-		g_free (package_id);
+-		return ret;
++		ret = pk_console_remove_only (client, package_ids, FALSE, error);
++		goto out;
+ 	}
+ 
++
+ 	/* present this to the user */
+ 	if (awaiting_space) {
+ 		g_print ("\n");
+ 	}
+ 	g_print ("%s:\n", _("The following packages have to be removed"));
+ 	for (i=0; i<length; i++) {
+-		item = pk_client_package_buffer_get_item (client_task, i);
++		item = pk_package_list_get_item (list, i);
+ 		ident = pk_package_id_new_from_string (item->package_id);
+ 		g_print ("%i\t%s-%s\n", i, ident->name, ident->version);
+ 		pk_package_id_free (ident);
+@@ -694,14 +808,17 @@ pk_console_remove_package (PkClient *client, const gchar *package, GError **erro
+ 	/* we chickened out */
+ 	if (remove == FALSE) {
+ 		g_print ("%s\n", _("Cancelled!"));
+-		g_free (package_id);
+-		return FALSE;
++		ret = FALSE;
++		goto out;
+ 	}
+ 
+ 	/* remove all the stuff */
+-	ret = pk_console_remove_only (client, package_id, TRUE, FALSE, error);
+-	g_free (package_id);
++	ret = pk_console_remove_only (client, package_ids, TRUE, error);
+ 
++out:
++	g_object_unref (list);
++	g_strfreev (package_ids);
++	g_ptr_array_free (array, TRUE);
+ 	return ret;
+ }
+ 
+@@ -840,7 +957,7 @@ pk_console_error_code_cb (PkClient *client, PkErrorCodeEnum error_code, const gc
+ 	    error_code == PK_ERROR_ENUM_MISSING_GPG_SIGNATURE && trusted) {
+ 		pk_debug ("need to try again with trusted FALSE");
+ 		trusted = FALSE;
+-		ret = pk_client_install_file (client_install_files, trusted, filename, &error);
++		ret = pk_client_install_files (client_install_files, trusted, files_cache, &error);
+ 		/* we succeeded, so wait for the requeue */
+ 		if (!ret) {
+ 			pk_warning ("failed to install file second time: %s", error->message);
+@@ -1153,7 +1270,6 @@ main (int argc, char *argv[])
+ 	const gchar *value = NULL;
+ 	const gchar *details = NULL;
+ 	const gchar *parameter = NULL;
+-	PkRoleEnum roles;
+ 	PkGroupEnum groups;
+ 	gchar *text;
+ 	ret = FALSE;
+@@ -1324,15 +1440,7 @@ main (int argc, char *argv[])
+ 			g_print (_("You need to specify a package or file to install"));
+ 			goto out;
+ 		}
+-		/* is it a local file? */
+-		ret = g_file_test (value, G_FILE_TEST_EXISTS);
+-		if (ret) {
+-			ret = pk_client_install_file (client, trusted, value, &error);
+-			/* we need this for the untrusted try */
+-			filename = g_strdup (value);
+-		} else {
+-			ret = pk_console_install_package (client, value, &error);
+-		}
++		ret = pk_console_install_stuff (client, argv, &error);
+ 
+ 	} else if (strcmp (mode, "install-sig") == 0) {
+ 		if (value == NULL || details == NULL || parameter == NULL) {
+@@ -1346,7 +1454,7 @@ main (int argc, char *argv[])
+ 			g_print (_("You need to specify a package to remove"));
+ 			goto out;
+ 		}
+-		ret = pk_console_remove_package (client, value, &error);
++		ret = pk_console_remove_packages (client, argv, &error);
+ 
+ 	} else if (strcmp (mode, "accept-eula") == 0) {
+ 		if (value == NULL) {
+@@ -1465,9 +1573,9 @@ main (int argc, char *argv[])
+ 		ret = pk_client_get_packages (client, filters, &error);
+ 
+ 	} else if (strcmp (mode, "get-actions") == 0) {
+-		roles = pk_control_get_actions (control);
+ 		text = pk_role_enums_to_text (roles);
+-		g_print ("roles=%s\n", text);
++		g_strdelimit (text, ";", '\n');
++		g_print ("%s\n", text);
+ 		g_free (text);
+ 		maybe_sync = FALSE;
+ 		/* these can never fail */
+@@ -1476,7 +1584,8 @@ main (int argc, char *argv[])
+ 	} else if (strcmp (mode, "get-filters") == 0) {
+ 		filters = pk_control_get_filters (control);
+ 		text = pk_filter_enums_to_text (filters);
+-		g_print ("filters=%s\n", text);
++		g_strdelimit (text, ";", '\n');
++		g_print ("%s\n", text);
+ 		g_free (text);
+ 		maybe_sync = FALSE;
+ 		/* these can never fail */
+@@ -1485,7 +1594,8 @@ main (int argc, char *argv[])
+ 	} else if (strcmp (mode, "get-groups") == 0) {
+ 		groups = pk_control_get_groups (control);
+ 		text = pk_group_enums_to_text (groups);
+-		g_print ("groups=%s\n", text);
++		g_strdelimit (text, ";", '\n');
++		g_print ("%s\n", text);
+ 		g_free (text);
+ 		maybe_sync = FALSE;
+ 		/* these can never fail */
+@@ -1525,7 +1635,7 @@ out:
+ 	g_free (options_help);
+ 	g_free (filter);
+ 	g_free (summary);
+-	g_free (filename);
++	g_strfreev (files_cache);
+ 	g_object_unref (control);
+ 	g_object_unref (client);
+ 	g_object_unref (client_task);
+diff --git a/configure.ac b/configure.ac
+index 9d734e1..f614d2b 100644
+--- a/configure.ac
++++ b/configure.ac
+@@ -535,7 +535,7 @@ if test x$enable_box = xyes; then
+ fi
+ 
+ if test x$enable_opkg = xyes; then
+-	PKG_CHECK_MODULES(OPKG, libopkg = 0.1.3)
++	PKG_CHECK_MODULES(OPKG, libopkg = 0.1.4)
+ 	AC_SUBST(OPKG_CFLAGS)
+ 	AC_SUBST(OPKG_LIBS)
+ fi
+diff --git a/contrib/yum-packagekit/refresh-packagekit.py b/contrib/yum-packagekit/refresh-packagekit.py
+index 9c0bdf4..b440539 100644
+--- a/contrib/yum-packagekit/refresh-packagekit.py
++++ b/contrib/yum-packagekit/refresh-packagekit.py
+@@ -35,7 +35,7 @@ def posttrans_hook(conduit):
+                                           '/org/freedesktop/PackageKit')
+         packagekit_iface = dbus.Interface(packagekit_proxy, 'org.freedesktop.PackageKit')
+         packagekit_iface.StateHasChanged('posttrans')
+-    except dbus.DBusException, e:
++    except Exception, e:
+         conduit.info(2, "Unable to send message to PackageKit")
+         conduit.info(6, "%s" %(e,))
+ 
+diff --git a/data/tests/Makefile.am b/data/tests/Makefile.am
+index d15dd6c..6935e66 100644
+--- a/data/tests/Makefile.am
++++ b/data/tests/Makefile.am
+@@ -5,6 +5,7 @@ NULL =
+ 
+ TEST_FILES =						\
+ 	pk-spawn-test.sh				\
++	pk-spawn-proxy.sh				\
+ 	pk-spawn-test-sigquit.sh			\
+ 	pk-spawn-test-profiling.sh			\
+ 	$(NULL)
+diff --git a/data/tests/pk-spawn-proxy.sh b/data/tests/pk-spawn-proxy.sh
+new file mode 100755
+index 0000000..57774f1
+--- /dev/null
++++ b/data/tests/pk-spawn-proxy.sh
+@@ -0,0 +1,20 @@
++#!/bin/bash
++# Copyright (C) 2008 Richard Hughes <richard at hughsie.com>
++# Licensed under the GNU General Public License Version 2
++# This program is free software; you can redistribute it and/or modify
++# it under the terms of the GNU General Public License as published by
++# the Free Software Foundation; either version 2 of the License, or
++# (at your option) any later version.
++
++if [ -z "${http_proxy}" ]; then
++	echo "no http proxy"
++	exit 1
++fi
++
++if [ -z "${ftp_proxy}" ]; then
++	echo "no ftp proxy"
++	exit 1
++fi
++
++echo -e "percentage\t100"
++
+diff --git a/docs/html/index.html b/docs/html/index.html
+index 7270eb7..d60f825 100644
+--- a/docs/html/index.html
++++ b/docs/html/index.html
+@@ -9,9 +9,9 @@
+ 
+ <table align="center" class="title">
+ <tr>
+- <td><img src="img/packagekit.png" alt="[img]"/></td>
++ <td><img src="img/packagekit.png" alt=""/></td>
+  <td width="95%" valign="middle"><p class="title">PackageKit Main Page</p></td>
+- <td><img src="img/packagekit.png" alt="[img]"/></td>
++ <td><img src="img/packagekit.png" alt=""/></td>
+ </tr>
+ </table>
+ 
+@@ -20,10 +20,10 @@
+ <table align="center" cellpadding="5px" border="0">
+ 
+ <tr>
+- <td align="center"><a href="pk-intro.html"><img src="img/large-accessories-text-editor.png" width="128" alt="[img]"/></a></td>
+- <td align="center"><a href="pk-using.html"><img src="img/large-preferences-system.png" width="128" alt="[img]"/></a></td>
+- <td align="center"><a href="pk-download.html"><img src="img/large-dialog-information.png" width="128" alt="[img]"/></a></td>
+- <td align="center"><a href="pk-screenshots.html"><img src="img/large-emblem-photos.png" width="128" alt="[img]"/></a></td>
++ <td align="center"><a href="pk-intro.html"><img src="img/large-accessories-text-editor.png" width="128" alt=""/></a></td>
++ <td align="center"><a href="pk-using.html"><img src="img/large-preferences-system.png" width="128" alt=""/></a></td>
++ <td align="center"><a href="pk-download.html"><img src="img/large-dialog-information.png" width="128" alt=""/></a></td>
++ <td align="center"><a href="pk-screenshots.html"><img src="img/large-emblem-photos.png" width="128" alt=""/></a></td>
+ </tr>
+ <tr>
+  <td><p class="indextitle"><a href="pk-intro.html" class="indextitle">What is<br/>PackageKit?</a></p></td>
+@@ -32,10 +32,10 @@
+  <td><p class="indextitle"><a href="pk-screenshots.html" class="indextitle">Screenshots</a></p></td>
+ </tr>
+ <tr>
+- <td align="center"><a href="pk-authors.html"><img src="img/large-authors.png" width="128" alt="[img]"/></a></td>
+- <td align="center"><a href="pk-bugs.html"><img src="img/large-applications-development.png" width="128" alt="[img]"/></a></td>
+- <td align="center"><a href="pk-help.html"><img src="img/large-system-users.png" width="128" alt="[img]"/></a></td>
+- <td align="center"><a href="pk-faq.html"><img src="img/large-help-browser.png" width="128" alt="[img]"/></a></td>
++ <td align="center"><a href="pk-authors.html"><img src="img/large-authors.png" width="128" alt=""/></a></td>
++ <td align="center"><a href="pk-bugs.html"><img src="img/large-applications-development.png" width="128" alt=""/></a></td>
++ <td align="center"><a href="pk-help.html"><img src="img/large-system-users.png" width="128" alt=""/></a></td>
++ <td align="center"><a href="pk-faq.html"><img src="img/large-help-browser.png" width="128" alt=""/></a></td>
+ </tr>
+ <tr>
+  <td><p class="indextitle"><a href="pk-authors.html" class="indextitle">Who develops<br/>PackageKit?</a></p></td>
+diff --git a/docs/html/pk-authors.html b/docs/html/pk-authors.html
+index 08289ad..607a7a4 100644
+--- a/docs/html/pk-authors.html
++++ b/docs/html/pk-authors.html
+@@ -9,9 +9,9 @@
+ 
+ <table align="center" class="title">
+ <tr>
+- <td><img src="img/packagekit.png" alt="[img]"/></td>
++ <td><img src="img/packagekit.png" alt=""/></td>
+  <td width="95%" valign="middle"><p class="title">Who develops PackageKit?</p></td>
+- <td><img src="img/packagekit.png" alt="[img]"/></td>
++ <td><img src="img/packagekit.png" alt=""/></td>
+ </tr>
+ </table>
+ 
+@@ -22,7 +22,7 @@
+ <table cellpadding="10">
+ <tr>
+  <td>
+-  <img src="img/author-hughsie.png" alt="[img]"/><!-- image should be 120px wide -->
++  <img src="img/author-hughsie.png" alt=""/><!-- image should be 120px wide -->
+  </td>
+  <td>
+   <h2>Richard Hughes</h2>
+@@ -48,7 +48,7 @@
+ 
+ <tr>
+  <td>
+-  <img src="img/author-kenvandine.png" alt="[img]"/><!-- image should be 120px wide -->
++  <img src="img/author-kenvandine.png" alt=""/><!-- image should be 120px wide -->
+  </td>
+  <td>
+   <h2>Ken VanDine</h2>
+@@ -66,7 +66,7 @@
+ 
+ <tr>
+  <td>
+-  <img src="img/author-btimothy.png" alt="[img]"/><!-- image should be 120px wide -->
++  <img src="img/author-btimothy.png" alt=""/><!-- image should be 120px wide -->
+  </td>
+  <td>
+   <h2>Boyd Timothy</h2>
+@@ -84,7 +84,7 @@
+ 
+ <tr>
+  <td>
+-  <img src="img/author-rnorwood.png" alt="[img]"/><!-- image should be 120px wide -->
++  <img src="img/author-rnorwood.png" alt=""/><!-- image should be 120px wide -->
+  </td>
+  <td>
+   <h2>Robin Norwood</h2>
+@@ -101,7 +101,7 @@
+ 
+ <tr>
+  <td>
+-  <img src="img/author-tomparker.png" alt="[img]"/><!-- image should be 120px wide -->
++  <img src="img/author-tomparker.png" alt=""/><!-- image should be 120px wide -->
+  </td>
+  <td>
+   <h2>Tom Parker</h2>
+@@ -118,7 +118,7 @@
+ 
+ <tr>
+  <td>
+-  <img src="img/author-timlau.png" alt="[img]"/><!-- image should be 120px wide -->
++  <img src="img/author-timlau.png" alt=""/><!-- image should be 120px wide -->
+  </td>
+  <td>
+   <h2>Tim Lauridsen</h2>
+@@ -139,7 +139,7 @@
+ 
+ <tr>
+  <td>
+-  <img src="img/author-lmacken.png" alt="[img]"/>
++  <img src="img/author-lmacken.png" alt=""/>
+  </td>
+  <td>
+   <h2>Luke Macken</h2>
+@@ -154,7 +154,7 @@
+ 
+ <tr>
+  <td>
+-  <img src="img/author-grzegorzdabrowski.png" alt="[img]"/><!-- image should be 120px wide -->
++  <img src="img/author-grzegorzdabrowski.png" alt=""/><!-- image should be 120px wide -->
+  </td>
+  <td>
+   <h2>Grzegorz DÄ…browski</h2>
+@@ -173,7 +173,7 @@
+ 
+ <tr>
+  <td>
+-  <img src="img/author-caglar.png" alt="[img]"/><!-- image should be 120px wide -->
++  <img src="img/author-caglar.png" alt=""/><!-- image should be 120px wide -->
+  </td>
+  <td>
+   <h2>S.Çağlar Onur</h2>
+@@ -195,7 +195,7 @@
+ 
+ <tr>
+  <td>
+-  <img src="img/author-elliot.png" alt="[img]"/>
++  <img src="img/author-elliot.png" alt=""/>
+  </td>
+  <td>
+   <h2>Elliot Peele</h2>
+@@ -210,7 +210,7 @@
+ 
+ <tr>
+  <td>
+-  <img src="img/author-jbowes.png" alt="[img]"/><!-- image should be 120px wide -->
++  <img src="img/author-jbowes.png" alt=""/><!-- image should be 120px wide -->
+  </td>
+  <td>
+   <h2>James Bowes</h2>
+@@ -227,7 +227,7 @@
+ 
+ <tr>
+  <td>
+-  <img src="img/author-unknown.png" alt="[img]"/><!-- image should be 120px wide -->
++  <img src="img/author-unknown.png" alt=""/><!-- image should be 120px wide -->
+  </td>
+  <td>
+   <h2>Thomas Wood</h2>
+@@ -247,7 +247,7 @@
+ 
+ <tr>
+  <td>
+-  <img src="img/author-unknown.png" alt="[img]"/><!-- image should be 120px wide -->
++  <img src="img/author-unknown.png" alt=""/><!-- image should be 120px wide -->
+  </td>
+  <td>
+   <h2>Scott Reeves</h2>
+diff --git a/docs/html/pk-bugs.html b/docs/html/pk-bugs.html
+index 89f7c48..2ee12ea 100644
+--- a/docs/html/pk-bugs.html
++++ b/docs/html/pk-bugs.html
+@@ -9,9 +9,9 @@
+ 
+ <table align="center" class="title">
+ <tr>
+- <td><img src="img/packagekit.png" alt="[img]"/></td>
++ <td><img src="img/packagekit.png" alt=""/></td>
+  <td width="95%" valign="middle"><p class="title">Reporting Bugs</p></td>
+- <td><img src="img/packagekit.png" alt="[img]"/></td>
++ <td><img src="img/packagekit.png" alt=""/></td>
+ </tr>
+ </table>
+ 
+diff --git a/docs/html/pk-download.html b/docs/html/pk-download.html
+index 6f796b8..0cdc85c 100644
+--- a/docs/html/pk-download.html
++++ b/docs/html/pk-download.html
+@@ -9,9 +9,9 @@
+ 
+ <table align="center" class="title">
+ <tr>
+- <td><img src="img/packagekit.png" alt="[img]"/></td>
++ <td><img src="img/packagekit.png" alt=""/></td>
+  <td width="95%" valign="middle"><p class="title">Where can I download it?</p></td>
+- <td><img src="img/packagekit.png" alt="[img]"/></td>
++ <td><img src="img/packagekit.png" alt=""/></td>
+ </tr>
+ </table>
+ 
+diff --git a/docs/html/pk-faq.html b/docs/html/pk-faq.html
+index a25e2b7..efa8344 100644
+--- a/docs/html/pk-faq.html
++++ b/docs/html/pk-faq.html
+@@ -9,9 +9,9 @@
+ 
+ <table align="center" class="title">
+ <tr>
+- <td><center><img src="img/packagekit.png" alt="[img]"/></center></td>
++ <td><center><img src="img/packagekit.png" alt=""/></center></td>
+  <td width="95%" valign="middle"><p class="title">Frequently Asked Questions</p></td>
+- <td><center><img src="img/packagekit.png" alt="[img]"/></center></td>
++ <td><center><img src="img/packagekit.png" alt=""/></center></td>
+ </tr>
+ </table>
+ 
+@@ -22,6 +22,7 @@
+ <h2>Table Of Contents</h2>
+ <ul>
+ <li><a href="#how-complete">How complete are the backends?</a></li>
++<li><a href="#run-as-root">When run as root, gpk-application and pkcon do not work!</a></li>
+ <li><a href="#session-system">Why is there a session service and and a system service?</a></li>
+ <li><a href="#session-methods">How do I use PackageKit in my application?</a></li>
+ <li><a href="#rawhide-updates">Why don't I get update details with Fedora Rawhide?</a></li>
+@@ -565,6 +566,19 @@
+ </table>
+ 
+ <hr>
++<h3><a name="run-as-root">When run as root, <code>gpk-application</code> and <code>pkcon</code> do not work!</a></h3>
++<p>
++GTK+ tools should not be run as the root user, <b>PERIOD</b>.
++Any GTK+ program run as the root user is a massive security hole -- GTK+ just isn't designed with
++this in mind.
++There are <b>numerous</b> attack vectors when running as root, and programs shouldn't do such
++insane and insecure things.
++</p>
++<p>
++Please see <a href="http://www.gtk.org/setuid.html">the GTK+ explanation</a> for more rationale.
++</p>
++
++<hr>
+ <h3><a name="session-system">Why is there a session service <b>and</b> and a system service?</a></h3>
+ <p>
+ PackageKit runs a process <code>packagekitd</code> that is a daemon that runs per-system.
+diff --git a/docs/html/pk-help.html b/docs/html/pk-help.html
+index 5b44d50..5bc7827 100644
+--- a/docs/html/pk-help.html
++++ b/docs/html/pk-help.html
+@@ -9,9 +9,9 @@
+ 
+ <table align="center" class="title">
+ <tr>
+- <td><img src="img/packagekit.png" alt="[img]"/></td>
++ <td><img src="img/packagekit.png" alt=""/></td>
+  <td width="95%" valign="middle"><p class="title">How can I help?</p></td>
+- <td><img src="img/packagekit.png" alt="[img]"/></td>
++ <td><img src="img/packagekit.png" alt=""/></td>
+ </tr>
+ </table>
+ 
+@@ -72,9 +72,9 @@ as for instructions!
+ <b>0.2.2</b> - To be released June 2008
+ </p>
+ <ul>
+-<li>Multiple package install and remove from pkcon <i>(0%)</i></li>
++<li>Network proxy server support <i>(70%)</i></li>
++<li>Multiple package install and remove from pkcon <i>(80%)</i></li>
+ <li>NetworkManager integration so we can detect GPRS (and modem) connections. <i>(10%)</i></li>
+-<li>Filter for source packages. <i>(0%)</i></li>
+ </ul>
+ <p>
+ <b>0.2.3</b> - To be released July 2008
+@@ -84,6 +84,12 @@ as for instructions!
+ <li>Multiple package installs from gpk-application <i>(0%)</i></li>
+ <li>Ignoring packages from the update viewer per-session <i>(10%)</i></li>
+ </ul>
++<p>
++<b>0.3.0</b> - To be released December 2008
++</p>
++<ul>
++<li>More composite types <code>s</code> to <code>as</code> <i>(0%)</i></li>
++</ul>
+ 
+ <p>Back to the <a href="index.html">main page</a></p>
+ 
+diff --git a/docs/html/pk-intro.html b/docs/html/pk-intro.html
+index c42be21..64f72fc 100644
+--- a/docs/html/pk-intro.html
++++ b/docs/html/pk-intro.html
+@@ -9,9 +9,9 @@
+ 
+ <table align="center" class="title">
+ <tr>
+- <td><img src="img/packagekit.png" alt="[img]"/></td>
++ <td><img src="img/packagekit.png" alt=""/></td>
+  <td width="95%" valign="middle"><p class="title">What is PackageKit?</p></td>
+- <td><img src="img/packagekit.png" alt="[img]"/></td>
++ <td><img src="img/packagekit.png" alt=""/></td>
+ </tr>
+ </table>
+ 
+diff --git a/docs/html/pk-screenshots.html b/docs/html/pk-screenshots.html
+index 78bd01f..5c7d4fa 100644
+--- a/docs/html/pk-screenshots.html
++++ b/docs/html/pk-screenshots.html
+@@ -9,9 +9,9 @@
+ 
+ <table align="center" class="title">
+ <tr>
+- <td><center><img src="img/packagekit.png" alt="[img]"/></center></td>
++ <td><center><img src="img/packagekit.png" alt=""/></center></td>
+  <td width="95%" valign="middle"><p class="title">Screenshots</p></td>
+- <td><center><img src="img/packagekit.png" alt="[img]"/></center></td>
++ <td><center><img src="img/packagekit.png" alt=""/></center></td>
+ </tr>
+ </table>
+ 
+@@ -26,77 +26,77 @@
+ 
+ <h1><a name="gnome">GNOME Screenshots</a></h1>
+ 
+-<center><img src="img/gpk-application-search.png" alt="[img]"/></center>
++<center><img src="img/gpk-application-search.png" alt=""/></center>
+ <p class="caption">Add/Remove Software search</p>
+ 
+-<center><img src="img/gpk-application-groups.png" alt="[img]"/></center>
++<center><img src="img/gpk-application-groups.png" alt=""/></center>
+ <p class="caption">Add/Remove Software groups</p>
+ 
+-<center><img src="img/gpk-log.png" alt="[img]"/></center>
++<center><img src="img/gpk-log.png" alt=""/></center>
+ <p class="caption">Transaction viewer</p>
+ 
+-<center><img src="img/gpk-updates-overview.png" alt="[img]"/></center>
++<center><img src="img/gpk-updates-overview.png" alt=""/></center>
+ <p class="caption">Update viewer overview</p>
+ 
+-<center><img src="img/gpk-updates.png" alt="[img]"/></center>
++<center><img src="img/gpk-updates.png" alt=""/></center>
+ <p class="caption">Update viewer</p>
+ 
+-<center><img src="img/gpk-prefs.png" alt="[img]"/></center>
++<center><img src="img/gpk-prefs.png" alt=""/></center>
+ <p class="caption">Auto update preferences</p>
+ 
+-<center><img src="img/gpk-progress.png" alt="[img]"/></center>
++<center><img src="img/gpk-progress.png" alt=""/></center>
+ <p class="caption">Progress dialog</p>
+ 
+-<center><img src="img/gpk-added-deps.png" alt="[img]"/></center>
++<center><img src="img/gpk-added-deps.png" alt=""/></center>
+ <p class="caption">Added check warning</p>
+ 
+-<center><img src="img/gpk-eula.png" alt="[img]"/></center>
++<center><img src="img/gpk-eula.png" alt=""/></center>
+ <p class="caption">EULA dialog</p>
+ 
+-<center><img src="img/gpk-remove-confirm.png" alt="[img]"/></center>
++<center><img src="img/gpk-remove-confirm.png" alt=""/></center>
+ <p class="caption">Remove check warning</p>
+ 
+-<center><img src="img/gpk-repo-auth.png" alt="[img]"/></center>
++<center><img src="img/gpk-repo-auth.png" alt=""/></center>
+ <p class="caption">Repository authentication</p>
+ 
+-<center><img src="img/gpk-repo.png" alt="[img]"/></center>
++<center><img src="img/gpk-repo.png" alt=""/></center>
+ <p class="caption">Repository viewer</p>
+ 
+-<center><img src="img/gpk-backend-status.png" alt="[img]"/></center>
++<center><img src="img/gpk-backend-status.png" alt=""/></center>
+ <p class="caption">PackageKit backend status</p>
+ 
+-<center><img src="img/gpk-updates-warning.png" alt="[img]"/></center>
++<center><img src="img/gpk-updates-warning.png" alt=""/></center>
+ <p class="caption">Libnotify updates warning</p>
+ 
+-<center><img src="img/gpk-waiting.png" alt="[img]"/></center>
++<center><img src="img/gpk-waiting.png" alt=""/></center>
+ <p class="caption">Tasks waiting</p>
+ 
+-<center><img src="img/gpk-battery.png" alt="[img]"/></center>
++<center><img src="img/gpk-battery.png" alt=""/></center>
+ <p class="caption">Intergration with gnome-power-manager</p>
+ 
+-<center><img src="img/gpk-inhibit.png" alt="[img]"/></center>
++<center><img src="img/gpk-inhibit.png" alt=""/></center>
+ <p class="caption">Inhibit with gnome-power-manager</p>
+ 
+-<center><img src="img/gpk-require-restart.png" alt="[img]"/></center>
++<center><img src="img/gpk-require-restart.png" alt=""/></center>
+ <p class="caption">We sometimes need to do a restart</p>
+ 
+-<center><img src="img/gpk-auto-update.png" alt="[img]"/></center>
++<center><img src="img/gpk-auto-update.png" alt=""/></center>
+ <p class="caption">Auto update install dialog</p>
+ 
+ <h1><a name="kde">KDE Screenshots</a></h1>
+ 
+-<center><img src="img/kpk-search.png" alt="[img]"/></center>
++<center><img src="img/kpk-search.png" alt=""/></center>
+ <p class="caption">KPackageKit Searching</p>
+ 
+-<center><img src="img/kpk-information.png" alt="[img]"/></center>
++<center><img src="img/kpk-information.png" alt=""/></center>
+ <p class="caption">KPackageKit Package Information</p>
+ 
+-<center><img src="img/pk-opensuse-updater.png" alt="[img]"/></center>
++<center><img src="img/pk-opensuse-updater.png" alt=""/></center>
+ <p class="caption">OpenSuse Updater</p>
+ 
+ <h1><a name="moko">OpenMoko Screenshots</a></h1>
+ 
+-<center><img src="img/assassin.png" alt="[img]"/></center>
++<center><img src="img/assassin.png" alt=""/></center>
+ <p class="caption">Assassin</p>
+ 
+ <p>Back to the <a href="index.html">main page</a></p>
+diff --git a/docs/html/pk-using.html b/docs/html/pk-using.html
+index cc455c7..b2b028e 100644
+--- a/docs/html/pk-using.html
++++ b/docs/html/pk-using.html
+@@ -9,9 +9,9 @@
+ 
+ <table align="center" class="title">
+ <tr>
+- <td><img src="img/packagekit.png" alt="[img]"/></td>
++ <td><img src="img/packagekit.png" alt=""/></td>
+  <td width="95%" valign="middle"><p class="title">How do I use PackageKit?</p></td>
+- <td><img src="img/packagekit.png" alt="[img]"/></td>
++ <td><img src="img/packagekit.png" alt=""/></td>
+ </tr>
+ </table>
+ 
+diff --git a/docs/spec/pk-concepts.xml b/docs/spec/pk-concepts.xml
+index 312c5a4..0b75b10 100644
+--- a/docs/spec/pk-concepts.xml
++++ b/docs/spec/pk-concepts.xml
+@@ -127,6 +127,13 @@
+               This allows the used to choose non-native packages if a multi-lib policy is allowed.
+             </entry>
+           </row>
++          <row>
++            <entry><literal>source</literal> or <literal>~source</literal></entry>
++            <entry>
++              The source filter will only return source packages.
++              These are typically useful when rebuilding other packages.
++            </entry>
++          </row>
+         </tbody>
+       </tgroup>
+     </informaltable>
+diff --git a/etc/PackageKit.conf.in b/etc/PackageKit.conf.in
+index a6af99b..8f9bd57 100644
+--- a/etc/PackageKit.conf.in
++++ b/etc/PackageKit.conf.in
+@@ -31,3 +31,13 @@ ShutdownTimeout=300
+ # default=@defaultbackend@
+ DefaultBackend=@defaultbackend@
+ 
++# Proxy settings, uncomment as required
++#
++# NOTE: PackageKit does not use these settings, they are passed to backends.
++# Backends may ignore these values, or they may be updated from the session.
++#
++# They are in the format username:password at server:port
++#
++# ProxyHTTP=username:password at server.lan:8080
++# ProxyFTP=username:password at server.lan:21
++
+diff --git a/libpackagekit/Makefile.am b/libpackagekit/Makefile.am
+index 6b8c6b8..aeafe44 100644
+--- a/libpackagekit/Makefile.am
++++ b/libpackagekit/Makefile.am
+@@ -37,6 +37,7 @@ libpackagekit_include_HEADERS =					\
+ 	pk-connection.h						\
+ 	pk-package-id.h						\
+ 	pk-package-ids.h					\
++	pk-package-item.h					\
+ 	pk-package-list.h					\
+ 	pk-enum.h						\
+ 	pk-common.h						\
+@@ -59,6 +60,8 @@ libpackagekit_la_SOURCES =					\
+ 	pk-package-id.h						\
+ 	pk-package-ids.c					\
+ 	pk-package-ids.h					\
++	pk-package-item.c					\
++	pk-package-item.h					\
+ 	pk-package-list.c					\
+ 	pk-package-list.h					\
+ 	pk-enum.h						\
+diff --git a/libpackagekit/pk-enum.c b/libpackagekit/pk-enum.c
+index b5b6ac3..5743dcb 100644
+--- a/libpackagekit/pk-enum.c
++++ b/libpackagekit/pk-enum.c
+@@ -193,6 +193,8 @@ static PkEnumMatch enum_filter[] = {
+ 	{PK_FILTER_ENUM_NOT_NEWEST,		"~newest"},
+ 	{PK_FILTER_ENUM_ARCH,			"arch"},
+ 	{PK_FILTER_ENUM_NOT_ARCH,		"~arch"},
++	{PK_FILTER_ENUM_SOURCE,			"source"},
++	{PK_FILTER_ENUM_NOT_SOURCE,		"~source"},
+ 	{0, NULL}
+ };
+ 
+diff --git a/libpackagekit/pk-enum.h b/libpackagekit/pk-enum.h
+index 33e8a91..e616b64 100644
+--- a/libpackagekit/pk-enum.h
++++ b/libpackagekit/pk-enum.h
+@@ -182,7 +182,9 @@ typedef enum {
+ 	PK_FILTER_ENUM_NOT_NEWEST		= 1 << 15,
+ 	PK_FILTER_ENUM_ARCH			= 1 << 16,
+ 	PK_FILTER_ENUM_NOT_ARCH			= 1 << 17,
+-	PK_FILTER_ENUM_UNKNOWN			= 1 << 18
++	PK_FILTER_ENUM_SOURCE			= 1 << 18,
++	PK_FILTER_ENUM_NOT_SOURCE		= 1 << 19,
++	PK_FILTER_ENUM_UNKNOWN			= 1 << 20
+ } PkFilterEnum;
+ 
+ /**
+diff --git a/libpackagekit/pk-package-item.c b/libpackagekit/pk-package-item.c
+new file mode 100644
+index 0000000..87905dc
+--- /dev/null
++++ b/libpackagekit/pk-package-item.c
+@@ -0,0 +1,190 @@
++/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
++ *
++ * Copyright (C) 2007-2008 Richard Hughes <richard at hughsie.com>
++ *
++ * Licensed under the GNU General Public License Version 2
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
++ */
++
++/**
++ * SECTION:pk-package-item
++ * @short_description: A cached Package structure
++ *
++ * These provide a way to query and store a single package.
++ */
++
++#include "config.h"
++
++#include <stdlib.h>
++#include <stdio.h>
++#include <time.h>
++#include <errno.h>
++
++#include <string.h>
++#include <sys/time.h>
++#include <sys/types.h>
++#ifdef HAVE_UNISTD_H
++#include <unistd.h>
++#endif /* HAVE_UNISTD_H */
++
++#include <glib/gi18n.h>
++
++#include "pk-debug.h"
++#include "pk-common.h"
++#include "pk-package-item.h"
++
++/**
++ * pk_package_item_new:
++ **/
++PkPackageItem *
++pk_package_item_new (PkInfoEnum info, const gchar *package_id, const gchar *summary)
++{
++	PkPackageItem *item;
++
++	g_return_val_if_fail (package_id != NULL, FALSE);
++
++	pk_debug ("adding to cache item package %s, %s, %s", pk_info_enum_to_text (info), package_id, summary);
++	item = g_new0 (PkPackageItem, 1);
++	item->info = info;
++	item->package_id = g_strdup (package_id);
++	item->summary = g_strdup (summary);
++	return item;
++}
++
++/**
++ * pk_package_item_free:
++ **/
++gboolean
++pk_package_item_free (PkPackageItem *item)
++{
++	if (item == NULL) {
++		return FALSE;
++	}
++	g_free (item->package_id);
++	g_free (item->summary);
++	g_free (item);
++	return TRUE;
++}
++
++/**
++ * pk_package_item_equal:
++ *
++ * Only compares the package_id's and the info enum
++ **/
++gboolean
++pk_package_item_equal (PkPackageItem *item1, PkPackageItem *item2)
++{
++	if (item1 == NULL || item2 == NULL) {
++		return FALSE;
++	}
++	return (item1->info == item2->info &&
++		pk_strequal (item1->package_id, item2->package_id));
++}
++
++/**
++ * pk_package_item_copy:
++ *
++ * Copy a PkPackageItem
++ **/
++PkPackageItem *
++pk_package_item_copy (PkPackageItem *item)
++{
++	g_return_val_if_fail (item != NULL, NULL);
++	return pk_package_item_new (item->info, item->package_id, item->summary);
++}
++
++/***************************************************************************
++ ***                          MAKE CHECK TESTS                           ***
++ ***************************************************************************/
++#ifdef PK_BUILD_TESTS
++#include <libselftest.h>
++
++void
++libst_package_item (LibSelfTest *test)
++{
++	PkPackageItem *item1;
++	PkPackageItem *item2;
++	PkPackageItem *item3;
++	gboolean ret;
++
++	if (libst_start (test, "PkPackageItem", CLASS_AUTO) == FALSE) {
++		return;
++	}
++
++	/************************************************************/
++	libst_title (test, "add entry");
++	item1 = pk_package_item_new (PK_INFO_ENUM_INSTALLED, "gnome;1.23;i386;data", "GNOME!");
++	if (item1 != NULL) {
++		libst_success (test, NULL);
++	} else {
++		libst_failed (test, NULL);
++	}
++
++	/************************************************************/
++	libst_title (test, "add entry");
++	item2 = pk_package_item_new (PK_INFO_ENUM_INSTALLED, "gnome;1.23;i386;data", "GNOME foo!");
++	if (item2 != NULL) {
++		libst_success (test, NULL);
++	} else {
++		libst_failed (test, NULL);
++	}
++
++	/************************************************************/
++	libst_title (test, "copy entry");
++	item3 = pk_package_item_copy (item2);
++	if (item3 != NULL) {
++		libst_success (test, NULL);
++	} else {
++		libst_failed (test, NULL);
++	}
++
++	/************************************************************/
++	libst_title (test, "check equal");
++	ret = pk_package_item_equal (item1, item3);
++	if (ret) {
++		libst_success (test, NULL);
++	} else {
++		libst_failed (test, NULL);
++	}
++
++	pk_package_item_free (item2);
++	pk_package_item_free (item3);
++
++	/************************************************************/
++	libst_title (test, "add entry");
++	item2 = pk_package_item_new (PK_INFO_ENUM_INSTALLED, "gnome-do;1.23;i386;data", "GNOME doo!");
++	if (item2 != NULL) {
++		libst_success (test, NULL);
++	} else {
++		libst_failed (test, NULL);
++	}
++
++	/************************************************************/
++	libst_title (test, "check !equal");
++	ret = pk_package_item_equal (item1, item2);
++	if (!ret) {
++		libst_success (test, NULL);
++	} else {
++		libst_failed (test, NULL);
++	}
++
++	pk_package_item_free (item1);
++	pk_package_item_free (item2);
++
++	libst_end (test);
++}
++#endif
++
+diff --git a/libpackagekit/pk-package-item.h b/libpackagekit/pk-package-item.h
+new file mode 100644
+index 0000000..c41a6ea
+--- /dev/null
++++ b/libpackagekit/pk-package-item.h
+@@ -0,0 +1,48 @@
++/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
++ *
++ * Copyright (C) 2008 Richard Hughes <richard at hughsie.com>
++ *
++ * Licensed under the GNU General Public License Version 2
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
++ */
++
++#ifndef __PK_PACKAGE_ITEM_H
++#define __PK_PACKAGE_ITEM_H
++
++#include <glib-object.h>
++#include <pk-enum.h>
++
++/**
++ * PkPackageItem:
++ *
++ * A cached store for the complete Package object
++ */
++typedef struct {
++	PkInfoEnum		 info;
++	gchar			*package_id;
++	gchar			*summary;
++} PkPackageItem;
++
++PkPackageItem	*pk_package_item_new			(PkInfoEnum		 info,
++							 const gchar		*package_id,
++							 const gchar		*summary);
++gboolean	 pk_package_item_free			(PkPackageItem		*item);
++PkPackageItem	*pk_package_item_copy			(PkPackageItem		*item);
++gboolean	 pk_package_item_equal			(PkPackageItem		*item1,
++							 PkPackageItem		*item2);
++
++#endif /* __PK_PACKAGE_ITEM_H */
++
+diff --git a/libpackagekit/pk-package-list.c b/libpackagekit/pk-package-list.c
+index b0a1a71..5d95e1b 100644
+--- a/libpackagekit/pk-package-list.c
++++ b/libpackagekit/pk-package-list.c
+@@ -45,6 +45,7 @@
+ #include "pk-debug.h"
+ #include "pk-common.h"
+ #include "pk-package-id.h"
++#include "pk-package-item.h"
+ #include "pk-package-list.h"
+ 
+ static void     pk_package_list_class_init	(PkPackageListClass *klass);
+@@ -77,16 +78,42 @@ pk_package_list_add (PkPackageList *plist, PkInfoEnum info, const gchar *package
+ 	g_return_val_if_fail (package_id != NULL, FALSE);
+ 
+ 	pk_debug ("adding to cache array package %s, %s, %s", pk_info_enum_to_text (info), package_id, summary);
+-	item = g_new0 (PkPackageItem, 1);
+-	item->info = info;
+-	item->package_id = g_strdup (package_id);
+-	item->summary = g_strdup (summary);
++	item = pk_package_item_new (info, package_id, summary);
+ 	g_ptr_array_add (plist->priv->array, item);
+ 
+ 	return TRUE;
+ }
+ 
+ /**
++ * pk_package_list_add_item:
++ *
++ * Makes a deep copy, and adds to the array
++ **/
++gboolean
++pk_package_list_add_item (PkPackageList *plist, PkPackageItem *item)
++{
++	gboolean ret;
++	PkPackageItem *item_new;
++
++	g_return_val_if_fail (PK_IS_PACKAGE_LIST (plist), FALSE);
++	g_return_val_if_fail (item != NULL, FALSE);
++
++	ret = pk_package_list_contains_item (plist, item);
++	if (ret) {
++		pk_debug ("already added item");
++		return FALSE;
++	}
++
++	pk_debug ("adding to cache array package %s, %s, %s",
++		  pk_info_enum_to_text (item->info), item->package_id, item->summary);
++
++	item_new = pk_package_item_copy (item);
++	g_ptr_array_add (plist->priv->array, item_new);
++
++	return TRUE;
++}
++
++/**
+  * pk_package_list_get_string:
+  **/
+ gchar *
+@@ -152,9 +179,7 @@ pk_package_list_clear (PkPackageList *plist)
+ 
+ 	while (plist->priv->array->len > 0) {
+ 		item = g_ptr_array_index (plist->priv->array, 0);
+-		g_free (item->package_id);
+-		g_free (item->summary);
+-		g_free (item);
++		pk_package_item_free (item);
+ 		g_ptr_array_remove_index_fast (plist->priv->array, 0);
+ 	}
+ 	return TRUE;
+@@ -186,6 +211,31 @@ pk_package_list_contains (PkPackageList *plist, const gchar *package_id)
+ }
+ 
+ /**
++ * pk_package_list_contains_item:
++ **/
++gboolean
++pk_package_list_contains_item (PkPackageList *plist, PkPackageItem *item)
++{
++	PkPackageItem *item_temp;
++	guint i;
++	guint length;
++	gboolean ret = FALSE;
++
++	g_return_val_if_fail (PK_IS_PACKAGE_LIST (plist), FALSE);
++	g_return_val_if_fail (item != NULL, FALSE);
++
++	length = plist->priv->array->len;
++	for (i=0; i<length; i++) {
++		item_temp = g_ptr_array_index (plist->priv->array, i);
++		ret = pk_package_item_equal (item_temp, item);
++		if (ret) {
++			break;
++		}
++	}
++	return ret;
++}
++
++/**
+  * pk_package_list_class_init:
+  * @klass: The PkPackageListClass
+  **/
+diff --git a/libpackagekit/pk-package-list.h b/libpackagekit/pk-package-list.h
+index 9178f77..9734af4 100644
+--- a/libpackagekit/pk-package-list.h
++++ b/libpackagekit/pk-package-list.h
+@@ -25,6 +25,8 @@
+ #include <glib-object.h>
+ #include <pk-enum.h>
+ 
++#include "pk-package-item.h"
++
+ G_BEGIN_DECLS
+ 
+ #define PK_TYPE_PACKAGE_LIST		(pk_package_list_get_type ())
+@@ -49,26 +51,18 @@ struct _PkPackageListClass
+ 	GObjectClass	parent_class;
+ };
+ 
+-/**
+- * PkPackageItem:
+- *
+- * A cached store for the complete Package object
+- */
+-typedef struct
+-{
+-	PkInfoEnum		 info;
+-	gchar			*package_id;
+-	gchar			*summary;
+-} PkPackageItem;
+-
+ GType		 pk_package_list_get_type		(void) G_GNUC_CONST;
+ PkPackageList	*pk_package_list_new			(void);
+ gboolean	 pk_package_list_add			(PkPackageList		*plist,
+ 							 PkInfoEnum		 info,
+ 							 const gchar		*package_id,
+ 							 const gchar		*summary);
++gboolean	 pk_package_list_add_item		(PkPackageList		*plist,
++							 PkPackageItem		*item);
+ gboolean	 pk_package_list_contains		(PkPackageList		*plist,
+ 							 const gchar		*package_id);
++gboolean	 pk_package_list_contains_item		(PkPackageList		*plist,
++							 PkPackageItem		*item);
+ gchar		*pk_package_list_get_string		(PkPackageList		*plist)
+ 							 G_GNUC_WARN_UNUSED_RESULT;
+ guint		 pk_package_list_get_size		(PkPackageList		*plist);
+diff --git a/libpackagekit/pk-self-test.c b/libpackagekit/pk-self-test.c
+index 62e225b..bf151fb 100644
+--- a/libpackagekit/pk-self-test.c
++++ b/libpackagekit/pk-self-test.c
+@@ -29,6 +29,7 @@
+ /* prototypes */
+ void libst_package_id (LibSelfTest *test);
+ void libst_package_ids (LibSelfTest *test);
++void libst_package_item (LibSelfTest *test);
+ void libst_package_list (LibSelfTest *test);
+ void libst_enum (LibSelfTest *test);
+ void libst_common (LibSelfTest *test);
+@@ -51,6 +52,7 @@ main (int argc, char **argv)
+ 	libst_common (&test);
+ 	libst_package_id (&test);
+ 	libst_package_ids (&test);
++	libst_package_item (&test);
+ 	libst_package_list (&test);
+ 	libst_enum (&test);
+ 	libst_extra (&test);
+diff --git a/python/packagekit/daemonBackend.py b/python/packagekit/daemonBackend.py
+index 3711f01..5253b39 100644
+--- a/python/packagekit/daemonBackend.py
++++ b/python/packagekit/daemonBackend.py
+@@ -789,6 +789,21 @@ class PackageKitBaseBackend(dbus.service.Object):
+         self.Finished(EXIT_FAILED)
+ 
+     @dbus.service.method(PACKAGEKIT_DBUS_INTERFACE,
++                         in_signature='ss', out_signature='')
++    def SetProxy(self, proxy_http, proxy_ftp):
++        '''
++        Set the proxy
++        '''
++        pklog.info("SetProxy(%s, %s)" % (proxy_http, proxy_ftp))
++        self.doSetProxy(proxy_http, proxy_ftp)
++
++    def doSetProxy(self, proxy_http, proxy_ftp):
++        '''
++        Should be replaced in the corresponding backend sub class
++        '''
++        # do not use Finished() in this method
++
++    @dbus.service.method(PACKAGEKIT_DBUS_INTERFACE,
+                          in_signature='s', out_signature='')
+     def InstallPublicKey(self, keyurl):
+         '''
+diff --git a/src/pk-backend-dbus.c b/src/pk-backend-dbus.c
+index b06e584..4c6837a 100644
+--- a/src/pk-backend-dbus.c
++++ b/src/pk-backend-dbus.c
+@@ -123,16 +123,6 @@ pk_backend_dbus_sub_percentage_changed_cb (DBusGProxy *proxy, guint sub_percenta
+ }
+ 
+ /**
+- * pk_backend_dbus_no_percentage_updates_cb:
+- **/
+-static void
+-pk_backend_dbus_no_percentage_updates_cb (DBusGProxy *proxy, PkBackendDbus *backend_dbus)
+-{
+-	pk_debug ("got signal");
+-	pk_backend_no_percentage_updates (backend_dbus->priv->backend);
+-}
+-
+-/**
+  * pk_backend_dbus_package_cb:
+  **/
+ static void
+@@ -325,8 +315,6 @@ pk_backend_dbus_remove_callbacks (PkBackendDbus *backend_dbus)
+ 					G_CALLBACK (pk_backend_dbus_percentage_changed_cb), backend_dbus);
+ 	dbus_g_proxy_disconnect_signal (proxy, "SubPercentageChanged",
+ 					G_CALLBACK (pk_backend_dbus_sub_percentage_changed_cb), backend_dbus);
+-	dbus_g_proxy_disconnect_signal (proxy, "NoPercentageChanged",
+-					G_CALLBACK (pk_backend_dbus_no_percentage_updates_cb), backend_dbus);
+ 	dbus_g_proxy_disconnect_signal (proxy, "Package",
+ 					G_CALLBACK (pk_backend_dbus_package_cb), backend_dbus);
+ 	dbus_g_proxy_disconnect_signal (proxy, "Details",
+@@ -353,6 +341,31 @@ pk_backend_dbus_remove_callbacks (PkBackendDbus *backend_dbus)
+ }
+ 
+ /**
++ * pk_backend_dbus_set_proxy:
++ **/
++static gboolean
++pk_backend_dbus_set_proxy (PkBackendDbus *backend_dbus, const gchar *proxy_http, const gchar *proxy_ftp)
++{
++	gboolean ret;
++	GError *error = NULL;
++
++	g_return_val_if_fail (PK_IS_BACKEND_DBUS (backend_dbus), FALSE);
++	g_return_val_if_fail (backend_dbus->priv->proxy != NULL, FALSE);
++
++	/* new sync method call */
++	pk_backend_dbus_time_reset (backend_dbus);
++	ret = dbus_g_proxy_call (backend_dbus->priv->proxy, "SetProxy", &error,
++				 G_TYPE_STRING, proxy_http,
++				 G_TYPE_STRING, proxy_ftp,
++				 G_TYPE_INVALID, G_TYPE_INVALID);
++	if (error != NULL) {
++		pk_warning ("%s", error->message);
++		g_error_free (error);
++	}
++	return ret;
++}
++
++/**
+  * pk_backend_dbus_set_name:
+  **/
+ gboolean
+@@ -385,7 +398,6 @@ pk_backend_dbus_set_name (PkBackendDbus *backend_dbus, const gchar *service)
+ 				 G_TYPE_UINT, G_TYPE_INVALID);
+ 	dbus_g_proxy_add_signal (proxy, "SubPercentageChanged",
+ 				 G_TYPE_UINT, G_TYPE_INVALID);
+-	dbus_g_proxy_add_signal (proxy, "NoPercentageChanged", G_TYPE_INVALID);
+ 	dbus_g_proxy_add_signal (proxy, "Package",
+ 				 G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_INVALID);
+ 	dbus_g_proxy_add_signal (proxy, "Details",
+@@ -424,8 +436,6 @@ pk_backend_dbus_set_name (PkBackendDbus *backend_dbus, const gchar *service)
+ 				     G_CALLBACK (pk_backend_dbus_percentage_changed_cb), backend_dbus, NULL);
+ 	dbus_g_proxy_connect_signal (proxy, "SubPercentageChanged",
+ 				     G_CALLBACK (pk_backend_dbus_sub_percentage_changed_cb), backend_dbus, NULL);
+-	dbus_g_proxy_connect_signal (proxy, "NoPercentageChanged",
+-				     G_CALLBACK (pk_backend_dbus_no_percentage_updates_cb), backend_dbus, NULL);
+ 	dbus_g_proxy_connect_signal (proxy, "Package",
+ 				     G_CALLBACK (pk_backend_dbus_package_cb), backend_dbus, NULL);
+ 	dbus_g_proxy_connect_signal (proxy, "Details",
+@@ -465,6 +475,18 @@ pk_backend_dbus_set_name (PkBackendDbus *backend_dbus, const gchar *service)
+ 		pk_backend_finished (backend_dbus->priv->backend);
+ 		g_error_free (error);
+ 	}
++
++	/* set the proxy */
++	if (ret) {
++		gchar *proxy_http;
++		gchar *proxy_ftp;
++		proxy_http = pk_backend_get_proxy_http (backend_dbus->priv->backend);
++		proxy_ftp = pk_backend_get_proxy_http (backend_dbus->priv->backend);
++		pk_backend_dbus_set_proxy (backend_dbus, proxy_http, proxy_ftp);
++		g_free (proxy_http);
++		g_free (proxy_ftp);
++	}
++
+ 	if (ret) {
+ 		pk_backend_dbus_time_check (backend_dbus);
+ 	}
+diff --git a/src/pk-backend-internal.h b/src/pk-backend-internal.h
+index 2213fed..2bffaff 100644
+--- a/src/pk-backend-internal.h
++++ b/src/pk-backend-internal.h
+@@ -59,6 +59,9 @@ gboolean	 pk_backend_reset			(PkBackend	*backend);
+ gboolean	 pk_backend_set_name			(PkBackend	*backend,
+ 							 const gchar	*name)
+ 							 G_GNUC_WARN_UNUSED_RESULT;
++gboolean	 pk_backend_set_proxy			(PkBackend	*backend,
++							 const gchar	*proxy_http,
++							 const gchar	*proxy_ftp);
+ gchar		*pk_backend_get_name			(PkBackend	*backend)
+ 							 G_GNUC_WARN_UNUSED_RESULT;
+ gboolean	 pk_backend_get_backend_detail		(PkBackend	*backend,
+diff --git a/src/pk-backend-spawn.c b/src/pk-backend-spawn.c
+index f9e8b68..f9c9f12 100644
+--- a/src/pk-backend-spawn.c
++++ b/src/pk-backend-spawn.c
+@@ -313,7 +313,7 @@ pk_backend_spawn_parse_stdout (PkBackendSpawn *backend_spawn, const gchar *line)
+ 			ret = FALSE;
+ 			goto out;
+ 		}
+-		pk_backend_no_percentage_updates (backend_spawn->priv->backend);
++		pk_backend_set_percentage (backend_spawn->priv->backend, PK_BACKEND_PERCENTAGE_INVALID);
+ 	} else if (pk_strequal (command, "repo-signature-required")) {
+ 
+ 		if (size != 9+99) {
+@@ -440,6 +440,44 @@ pk_backend_spawn_helper_new (PkBackendSpawn *backend_spawn)
+ }
+ 
+ /**
++ * pk_backend_spawn_get_envp:
++ *
++ * Return all the environment variables the script will need
++ **/
++static gchar **
++pk_backend_spawn_get_envp (PkBackendSpawn *backend_spawn)
++{
++	gchar **envp;
++	gchar *value;
++	gchar *line;
++	GPtrArray *array;
++
++	array = g_ptr_array_new ();
++
++	/* http_proxy */
++	value = pk_backend_get_proxy_http (backend_spawn->priv->backend);
++	if (!pk_strzero (value)) {
++		line = g_strdup_printf ("%s=%s", "http_proxy", value);
++		pk_debug ("setting evp '%s'", line);
++		g_ptr_array_add (array, line);
++	}
++	g_free (value);
++
++	/* ftp_proxy */
++	value = pk_backend_get_proxy_ftp (backend_spawn->priv->backend);
++	if (!pk_strzero (value)) {
++		line = g_strdup_printf ("%s=%s", "ftp_proxy", value);
++		pk_debug ("setting evp '%s'", line);
++		g_ptr_array_add (array, line);
++	}
++	g_free (value);
++
++	envp = pk_ptr_array_to_argv (array);
++	g_ptr_array_free (array, TRUE);
++	return envp;
++}
++
++/**
+  * pk_backend_spawn_helper_va_list:
+  **/
+ static gboolean
+@@ -448,6 +486,7 @@ pk_backend_spawn_helper_va_list (PkBackendSpawn *backend_spawn, const gchar *exe
+ 	gboolean ret;
+ 	gchar *filename;
+ 	gchar **argv;
++	gchar **envp;
+ 
+ 	g_return_val_if_fail (PK_IS_BACKEND_SPAWN (backend_spawn), FALSE);
+ 
+@@ -476,7 +515,8 @@ pk_backend_spawn_helper_va_list (PkBackendSpawn *backend_spawn, const gchar *exe
+ 	argv[0] = g_strdup (filename);
+ 
+ 	pk_backend_spawn_helper_new (backend_spawn);
+-	ret = pk_spawn_argv (backend_spawn->priv->spawn, argv);
++	envp = pk_backend_spawn_get_envp (backend_spawn);
++	ret = pk_spawn_argv (backend_spawn->priv->spawn, argv, envp);
+ 	if (!ret) {
+ 		pk_backend_spawn_helper_delete (backend_spawn);
+ 		pk_backend_error_code (backend_spawn->priv->backend, PK_ERROR_ENUM_INTERNAL_ERROR,
+diff --git a/src/pk-backend.c b/src/pk-backend.c
+index 225c488..37ed024 100644
+--- a/src/pk-backend.c
++++ b/src/pk-backend.c
+@@ -33,6 +33,7 @@
+ #include <glib/gprintf.h>
+ #include <pk-network.h>
+ 
++#include "pk-package-item.h"
+ #include "pk-debug.h"
+ #include "pk-common.h"
+ #include "pk-marshal.h"
+@@ -44,13 +45,6 @@
+ #define PK_BACKEND_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), PK_TYPE_BACKEND, PkBackendPrivate))
+ 
+ /**
+- * PK_BACKEND_PERCENTAGE_INVALID:
+- *
+- * The unknown percentage value
+- */
+-#define PK_BACKEND_PERCENTAGE_INVALID		101
+-
+-/**
+  * PK_BACKEND_PERCENTAGE_DEFAULT:
+  *
+  * The default percentage value, should never be emitted, but should be
+@@ -84,12 +78,15 @@ struct _PkBackendPrivate
+ 	GHashTable		*eulas;
+ 	gchar			*name;
+ 	gchar			*c_tid;
++	gchar			*proxy_http;
++	gchar			*proxy_ftp;
+ 	gboolean		 locked;
+ 	gboolean		 set_error;
+ 	gboolean		 set_signature;
+ 	gboolean		 set_eula;
+ 	gboolean		 has_sent_package;
+ 	PkNetwork		*network;
++	PkPackageItem		*last_package;
+ 	PkRoleEnum		 role; /* this never changes for the lifetime of a transaction */
+ 	PkStatusEnum		 status; /* this changes */
+ 	PkExitEnum		 exit;
+@@ -592,6 +589,44 @@ out:
+ }
+ 
+ /**
++ * pk_backend_set_proxy:
++ **/
++gboolean
++pk_backend_set_proxy (PkBackend	*backend, const gchar *proxy_http, const gchar *proxy_ftp)
++{
++	g_return_val_if_fail (PK_IS_BACKEND (backend), FALSE);
++	g_free (backend->priv->proxy_http);
++	g_free (backend->priv->proxy_ftp);
++	backend->priv->proxy_http = g_strdup (proxy_http);
++	backend->priv->proxy_ftp = g_strdup (proxy_ftp);
++	return TRUE;
++}
++
++/**
++ * pk_backend_get_proxy_http:
++ *
++ * Return value: proxy string in the form username:password at server:port
++ **/
++gchar *
++pk_backend_get_proxy_http (PkBackend *backend)
++{
++	g_return_val_if_fail (PK_IS_BACKEND (backend), NULL);
++	return g_strdup (backend->priv->proxy_http);
++}
++
++/**
++ * pk_backend_get_proxy_ftp:
++ *
++ * Return value: proxy string in the form username:password at server:port
++ **/
++gchar *
++pk_backend_get_proxy_ftp (PkBackend *backend)
++{
++	g_return_val_if_fail (PK_IS_BACKEND (backend), NULL);
++	return g_strdup (backend->priv->proxy_ftp);
++}
++
++/**
+  * pk_backend_lock:
+  *
+  * Responsible for initialising the external backend object.
+@@ -803,35 +838,6 @@ pk_backend_set_sub_percentage (PkBackend *backend, guint percentage)
+ }
+ 
+ /**
+- * pk_backend_no_percentage_updates:
+- **/
+-gboolean
+-pk_backend_no_percentage_updates (PkBackend *backend)
+-{
+-	g_return_val_if_fail (PK_IS_BACKEND (backend), FALSE);
+-	g_return_val_if_fail (backend->priv->locked != FALSE, FALSE);
+-
+-	/* have we already set an error? */
+-	if (backend->priv->set_error) {
+-		pk_warning ("already set error, cannot process");
+-		return FALSE;
+-	}
+-
+-	/* set the same twice? */
+-	if (backend->priv->last_percentage == PK_BACKEND_PERCENTAGE_INVALID) {
+-		pk_debug ("duplicate set of %i", PK_BACKEND_PERCENTAGE_INVALID);
+-		return FALSE;
+-	}
+-
+-	/* invalidate previous percentage */
+-	backend->priv->last_percentage = PK_BACKEND_PERCENTAGE_INVALID;
+-
+-	/* emit the progress changed signal */
+-	pk_backend_emit_progress_changed (backend);
+-	return TRUE;
+-}
+-
+-/**
+  * pk_backend_set_status:
+  **/
+ gboolean
+@@ -901,11 +907,26 @@ gboolean
+ pk_backend_package (PkBackend *backend, PkInfoEnum info, const gchar *package_id, const gchar *summary)
+ {
+ 	gchar *summary_safe;
++	PkPackageItem *item;
++	gboolean ret;
+ 
+ 	g_return_val_if_fail (PK_IS_BACKEND (backend), FALSE);
+ 	g_return_val_if_fail (package_id != NULL, FALSE);
+ 	g_return_val_if_fail (backend->priv->locked != FALSE, FALSE);
+ 
++	/* check against the old one */
++	item = pk_package_item_new (info, package_id, summary);
++	ret = pk_package_item_equal (item, backend->priv->last_package);
++	if (ret) {
++		pk_package_item_free (item);
++		pk_debug ("skipping duplicate %s", package_id);
++		return FALSE;
++	}
++	/* update the 'last' package */
++	pk_package_item_free (backend->priv->last_package);
++	backend->priv->last_package = pk_package_item_copy (item);
++	pk_package_item_free (item);
++
+ 	/* have we already set an error? */
+ 	if (backend->priv->set_error) {
+ 		pk_warning ("already set error, cannot process");
+@@ -1689,6 +1710,8 @@ pk_backend_finalize (GObject *object)
+ 	pk_debug ("backend finalise");
+ 
+ 	pk_backend_reset (backend);
++	g_free (backend->priv->proxy_http);
++	g_free (backend->priv->proxy_ftp);
+ 	g_free (backend->priv->name);
+ 	g_free (backend->priv->c_tid);
+ 	g_object_unref (backend->priv->time);
+@@ -1818,6 +1841,7 @@ pk_backend_reset (PkBackend *backend)
+ 
+ 	/* TODO: need to wait for Finished() if running */
+ 
++	pk_package_item_free (backend->priv->last_package);
+ 	backend->priv->set_error = FALSE;
+ 	backend->priv->set_signature = FALSE;
+ 	backend->priv->set_eula = FALSE;
+@@ -1825,6 +1849,7 @@ pk_backend_reset (PkBackend *backend)
+ 	backend->priv->finished = FALSE;
+ 	backend->priv->has_sent_package = FALSE;
+ 	backend->priv->thread = NULL;
++	backend->priv->last_package = NULL;
+ 	backend->priv->status = PK_STATUS_ENUM_UNKNOWN;
+ 	backend->priv->exit = PK_EXIT_ENUM_UNKNOWN;
+ 	backend->priv->role = PK_ROLE_ENUM_UNKNOWN;
+@@ -1855,8 +1880,11 @@ pk_backend_init (PkBackend *backend)
+ 	backend->priv->handle = NULL;
+ 	backend->priv->name = NULL;
+ 	backend->priv->c_tid = NULL;
++	backend->priv->proxy_http = NULL;
++	backend->priv->proxy_ftp = NULL;
+ 	backend->priv->file_changed_func = NULL;
+ 	backend->priv->file_changed_data = NULL;
++	backend->priv->last_package = NULL;
+ 	backend->priv->locked = FALSE;
+ 	backend->priv->signal_finished = 0;
+ 	backend->priv->signal_error_timeout = 0;
+diff --git a/src/pk-backend.h b/src/pk-backend.h
+index 95b7fa8..fb17e3c 100644
+--- a/src/pk-backend.h
++++ b/src/pk-backend.h
+@@ -30,6 +30,13 @@
+ 
+ G_BEGIN_DECLS
+ 
++/**
++ * PK_BACKEND_PERCENTAGE_INVALID:
++ *
++ * The unknown percentage value
++ */
++#define PK_BACKEND_PERCENTAGE_INVALID		101
++
+ typedef struct _PkBackend PkBackend;
+ 
+ /* set the state */
+@@ -51,7 +58,6 @@ gboolean	 pk_backend_set_sub_percentage		(PkBackend	*backend,
+ 							 guint		 percentage);
+ gboolean	 pk_backend_set_exit_code		(PkBackend	*backend,
+ 							 PkExitEnum	 exit);
+-gboolean	 pk_backend_no_percentage_updates	(PkBackend	*backend);
+ gboolean	 pk_backend_set_transaction_data	(PkBackend	*backend,
+ 							 const gchar	*data);
+ 
+@@ -66,6 +72,8 @@ gboolean	 pk_backend_get_progress		(PkBackend	*backend,
+ 							 guint		*elapsed,
+ 							 guint		*remaining);
+ guint		 pk_backend_get_runtime			(PkBackend	*backend);
++gchar		*pk_backend_get_proxy_ftp		(PkBackend	*backend);
++gchar		*pk_backend_get_proxy_http		(PkBackend	*backend);
+ 
+ /* signal helpers */
+ gboolean	 pk_backend_finished			(PkBackend	*backend);
+diff --git a/src/pk-engine.c b/src/pk-engine.c
+index db81d36..028a0d0 100644
+--- a/src/pk-engine.c
++++ b/src/pk-engine.c
+@@ -101,6 +101,7 @@ struct PkEnginePrivate
+ 	PkNetwork		*network;
+ 	PkSecurity		*security;
+ 	PkNotify		*notify;
++	PkConf			*conf;
+ 	PkFileMonitor		*file_monitor;
+ 	PkRoleEnum		 actions;
+ 	PkGroupEnum		 groups;
+@@ -579,10 +580,15 @@ pk_engine_init (PkEngine *engine)
+ 	DBusGConnection *connection;
+ 	gboolean ret;
+ 	gchar *filename;
++	gchar *proxy_http;
++	gchar *proxy_ftp;
+ 
+ 	engine->priv = PK_ENGINE_GET_PRIVATE (engine);
+ 	engine->priv->restart_schedule = FALSE;
+ 
++	/* use the config file */
++	engine->priv->conf = pk_conf_new ();
++
+ 	/* setup the backend backend */
+ 	engine->priv->backend = pk_backend_new ();
+ 	g_signal_connect (engine->priv->backend, "finished",
+@@ -639,6 +645,13 @@ pk_engine_init (PkEngine *engine)
+ 			  G_CALLBACK (pk_engine_file_monitor_changed_cb), engine);
+ 	g_free (filename);
+ 
++	/* set the proxy */
++	proxy_http = pk_conf_get_string (engine->priv->conf, "ProxyHTTP");
++	proxy_ftp = pk_conf_get_string (engine->priv->conf, "ProxyFTP");
++	pk_backend_set_proxy (engine->priv->backend, proxy_http, proxy_ftp);
++	g_free (proxy_http);
++	g_free (proxy_ftp);
++
+ 	engine->priv->transaction_list = pk_transaction_list_new ();
+ 	g_signal_connect (engine->priv->transaction_list, "changed",
+ 			  G_CALLBACK (pk_engine_transaction_list_changed_cb), engine);
+@@ -696,6 +709,7 @@ pk_engine_finalize (GObject *object)
+ 	g_object_unref (engine->priv->notify);
+ 	g_object_unref (engine->priv->backend);
+ 	g_object_unref (engine->priv->cache);
++	g_object_unref (engine->priv->conf);
+ 
+ 	G_OBJECT_CLASS (pk_engine_parent_class)->finalize (object);
+ }
+diff --git a/src/pk-network-unix.c b/src/pk-network-unix.c
+index 11c23a2..74b266c 100644
+--- a/src/pk-network-unix.c
++++ b/src/pk-network-unix.c
+@@ -138,6 +138,11 @@ pk_network_unix_get_network_state (PkNetworkUnix *network_unix)
+ 			continue;
+ 		}
+ 
++		/* is loopback? */
++		if (pk_strequal (sections[0], "lo")) {
++			continue;
++		}
++
+ 		/* is correct parameters? */
+ 		number_sections = g_strv_length (sections);
+ 		if (number_sections != 11) {
+@@ -145,9 +150,8 @@ pk_network_unix_get_network_state (PkNetworkUnix *network_unix)
+ 			continue;
+ 		}
+ 
+-		/* is MTU and gateway nonzero? */
+-		if (!pk_strequal (sections[8], "0") &&
+-		    !pk_strequal (sections[2], "00000000")) {
++		/* is gateway nonzero? */
++		if (!pk_strequal (sections[2], "00000000")) {
+ 			pk_debug ("interface %s is valid", sections[0]);
+ 			online = TRUE;
+ 		}
+diff --git a/src/pk-network.c b/src/pk-network.c
+index 9656958..0ad839e 100644
+--- a/src/pk-network.c
++++ b/src/pk-network.c
+@@ -39,6 +39,7 @@
+ #ifdef HAVE_UNISTD_H
+ #include <unistd.h>
+ #endif /* HAVE_UNISTD_H */
++#include <libgbus.h>
+ 
+ #include <glib/gi18n.h>
+ 
+@@ -67,6 +68,7 @@ struct _PkNetworkPrivate
+ 	PkNetworkNm		*net_nm;
+ 	PkNetworkUnix		*net_unix;
+ 	PkConf			*conf;
++	LibGBus			*nm_bus;
+ };
+ 
+ enum {
+@@ -154,6 +156,7 @@ pk_network_class_init (PkNetworkClass *klass)
+ static void
+ pk_network_init (PkNetwork *network)
+ {
++	gboolean nm_alive;
+ 	network->priv = PK_NETWORK_GET_PRIVATE (network);
+ 	network->priv->conf = pk_conf_new ();
+ 	network->priv->net_nm = pk_network_nm_new ();
+@@ -167,6 +170,17 @@ pk_network_init (PkNetwork *network)
+ 	network->priv->use_nm = pk_conf_get_bool (network->priv->conf, "UseNetworkManager");
+ 	network->priv->use_unix = pk_conf_get_bool (network->priv->conf, "UseNetworkHeuristic");
+ 
++	/* check if NM is on the bus */
++	network->priv->nm_bus = libgbus_new ();
++	libgbus_assign (network->priv->nm_bus, LIBGBUS_SYSTEM, "org.freedesktop.NetworkManager");
++	nm_alive = libgbus_is_connected (network->priv->nm_bus);
++
++	/* NetworkManager isn't up, so we can't use it */
++	if (network->priv->use_nm && !nm_alive) {
++		pk_warning ("UseNetworkManager true, but org.freedesktop.NetworkManager not up");
++		network->priv->use_nm = FALSE;
++	}
++
+ #if !PK_BUILD_NETWORKMANAGER
+ 	/* check we can actually use the default */
+ 	if (network->priv->use_nm) {
+@@ -190,6 +204,7 @@ pk_network_finalize (GObject *object)
+ 
+ 	g_return_if_fail (network->priv != NULL);
+ 	g_object_unref (network->priv->conf);
++	g_object_unref (network->priv->nm_bus);
+ 	g_object_unref (network->priv->net_nm);
+ 	g_object_unref (network->priv->net_unix);
+ 	G_OBJECT_CLASS (pk_network_parent_class)->finalize (object);
+diff --git a/src/pk-spawn.c b/src/pk-spawn.c
+index 9b415b1..c4622f9 100644
+--- a/src/pk-spawn.c
++++ b/src/pk-spawn.c
+@@ -273,7 +273,7 @@ pk_spawn_kill (PkSpawn *spawn)
+  *
+  **/
+ gboolean
+-pk_spawn_argv (PkSpawn *spawn, gchar **argv)
++pk_spawn_argv (PkSpawn *spawn, gchar **argv, gchar **envp)
+ {
+ 	gboolean ret;
+ 
+@@ -284,7 +284,7 @@ pk_spawn_argv (PkSpawn *spawn, gchar **argv)
+ 	spawn->priv->finished = FALSE;
+ 
+ 	/* create spawned object for tracking */
+-	ret = g_spawn_async_with_pipes (NULL, argv, NULL,
++	ret = g_spawn_async_with_pipes (NULL, argv, envp,
+ 				 G_SPAWN_DO_NOT_REAP_CHILD | G_SPAWN_SEARCH_PATH,
+ 				 NULL, NULL, &spawn->priv->child_pid,
+ 				 NULL, /* stdin */
+@@ -484,6 +484,7 @@ libst_spawn (LibSelfTest *test)
+ 	gboolean ret;
+ 	gchar *path;
+ 	gchar **argv;
++	gchar **envp;
+ 
+ 	if (libst_start (test, "PkSpawn", CLASS_AUTO) == FALSE) {
+ 		return;
+@@ -496,7 +497,7 @@ libst_spawn (LibSelfTest *test)
+ 	libst_title (test, "make sure return error for missing file");
+ 	mexit = BAD_EXIT;
+ 	argv = g_strsplit ("pk-spawn-test-xxx.sh", " ", 0);
+-	ret = pk_spawn_argv (spawn, argv);
++	ret = pk_spawn_argv (spawn, argv, NULL);
+ 	g_strfreev (argv);
+ 	if (ret == FALSE) {
+ 		libst_success (test, "failed to run invalid file");
+@@ -517,7 +518,7 @@ libst_spawn (LibSelfTest *test)
+ 	mexit = -1;
+ 	path = pk_test_get_data ("pk-spawn-test.sh");
+ 	argv = g_strsplit (path, " ", 0);
+-	ret = pk_spawn_argv (spawn, argv);
++	ret = pk_spawn_argv (spawn, argv, NULL);
+ 	g_free (path);
+ 	g_strfreev (argv);
+ 	if (ret) {
+@@ -558,11 +559,34 @@ libst_spawn (LibSelfTest *test)
+ 	new_spawn_object (test, &spawn);
+ 
+ 	/************************************************************/
++	libst_title (test, "make sure we set the proxy");
++	mexit = -1;
++	path = pk_test_get_data ("pk-spawn-proxy.sh");
++	argv = g_strsplit (path, " ", 0);
++	envp = g_strsplit ("http_proxy=username:password at server:port "
++			   "ftp_proxy=username:password at server:port", " ", 0);
++	ret = pk_spawn_argv (spawn, argv, envp);
++	g_free (path);
++	g_strfreev (argv);
++	if (ret) {
++		libst_success (test, "ran correct file");
++	} else {
++		libst_failed (test, "did not run helper");
++	}
++
++	/* wait for finished */
++	libst_loopwait (test, 10000);
++	libst_loopcheck (test);
++
++	/* get new object */
++	new_spawn_object (test, &spawn);
++
++	/************************************************************/
+ 	libst_title (test, "make sure run correct helper, and kill it");
+ 	mexit = BAD_EXIT;
+ 	path = pk_test_get_data ("pk-spawn-test.sh");
+ 	argv = g_strsplit (path, " ", 0);
+-	ret = pk_spawn_argv (spawn, argv);
++	ret = pk_spawn_argv (spawn, argv, NULL);
+ 	g_free (path);
+ 	g_strfreev (argv);
+ 	if (ret) {
+@@ -592,7 +616,7 @@ libst_spawn (LibSelfTest *test)
+ 	mexit = BAD_EXIT;
+ 	path = pk_test_get_data ("pk-spawn-test-sigquit.sh");
+ 	argv = g_strsplit (path, " ", 0);
+-	ret = pk_spawn_argv (spawn, argv);
++	ret = pk_spawn_argv (spawn, argv, NULL);
+ 	g_free (path);
+ 	g_strfreev (argv);
+ 	if (ret) {
+@@ -618,7 +642,7 @@ libst_spawn (LibSelfTest *test)
+ 	libst_title (test, "run lots of data for profiling");
+ 	path = pk_test_get_data ("pk-spawn-test-profiling.sh");
+ 	argv = g_strsplit (path, " ", 0);
+-	ret = pk_spawn_argv (spawn, argv);
++	ret = pk_spawn_argv (spawn, argv, NULL);
+ 	g_free (path);
+ 	g_strfreev (argv);
+ 	if (ret) {
+diff --git a/src/pk-spawn.h b/src/pk-spawn.h
+index 1b20fef..0e58859 100644
+--- a/src/pk-spawn.h
++++ b/src/pk-spawn.h
+@@ -52,7 +52,8 @@ GType		 pk_spawn_get_type		  	(void) G_GNUC_CONST;
+ PkSpawn		*pk_spawn_new				(void);
+ 
+ gboolean	 pk_spawn_argv				(PkSpawn	*spawn,
+-							 gchar		**argv)
++							 gchar		**argv,
++							 gchar		**envp)
+ 							 G_GNUC_WARN_UNUSED_RESULT;
+ gboolean	 pk_spawn_kill				(PkSpawn	*spawn);
+ 
============================================================
--- conf/distro/include/sane-srcrevs.inc	31946f0f79f0bc829893d6218a66ceb88a01c3b2
+++ conf/distro/include/sane-srcrevs.inc	12ee6fdf6e7ea39bbac6764c1464c053eae524eb
@@ -153,7 +153,7 @@ SRCREV_pn-oprofileui ?= "160"
 SRCREV_pn-opkg-native ?= "4247"
 SRCREV_pn-opkg-sdk ?= "4247"
 SRCREV_pn-oprofileui ?= "160"
-SRCREV_pn-packagekit ?= "432046796fa420f57ab6c71081f7ba14e9a92574"
+SRCREV_pn-packagekit ?= "ebbbfa191257861bd19bd47ba646dce590b51858"
 SRCREV_pn-psplash ?= "249"
 SRCREV_pn-pty-forward-native ?= "4214"
 SRCREV_pn-py-odeviced ?= "190"
============================================================
--- packages/packagekit/packagekit_git.bb	d1b9bdd3d88e67835cab9f7b7bb6155fc89f2362
+++ packages/packagekit/packagekit_git.bb	87d921eb998dab5f586a8f64d30c9921be03d5eb
@@ -8,7 +8,8 @@ SRC_URI = "git://anongit.freedesktop.org
 PR = "r8"
 
 SRC_URI = "git://anongit.freedesktop.org/git/packagekit;protocol=git \
-           file://disable-docbook2man.patch;patch=1"
+           file://disable-docbook2man.patch;patch=1 \
+           file://d1e096c3267c1c9492041382b954e9327bc8bbec.patch;patch=0"
 
 S = "${WORKDIR}/git"
 
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.openmoko.org/pipermail/commitlog/attachments/20080519/92619807/attachment.htm 


More information about the commitlog mailing list