opkg: update to 0.1.4
authorKoen Kooi <koen@openembedded.org>
Sat, 31 May 2008 10:30:22 +0000 (10:30 +0000)
committerKoen Kooi <koen@openembedded.org>
Sat, 31 May 2008 10:30:22 +0000 (10:30 +0000)
packagekit: update to 0.2.1 to match opkg API (with addional patch from openmoko)

conf/distro/include/sane-srcrevs.inc
packages/opkg/opkg-native_svn.bb
packages/opkg/opkg-nogpg_svn.bb
packages/opkg/opkg.inc
packages/packagekit/files/d1e096c3267c1c9492041382b954e9327bc8bbec.patch [new file with mode: 0644]
packages/packagekit/files/pk-nodocs.patch [new file with mode: 0644]
packages/packagekit/packagekit_git.bb

index d255844..8b91857 100644 (file)
@@ -152,11 +152,11 @@ SRCREV_pn-openmoko-toolchain-scripts ?= "3767"
 SRCREV_pn-openmoko-worldclock2 ?= "3365"
 SRCREV_pn-openocd ?= "517"
 SRCREV_pn-openocd-native ?= "517"
-SRCREV_pn-opkg ?= "4247"
-SRCREV_pn-opkg-native ?= "4247"
-SRCREV_pn-opkg-sdk ?= "4247"
+SRCREV_pn-opkg ?= "4452"
+SRCREV_pn-opkg-native ?= "4452"
+SRCREV_pn-opkg-sdk ?= "4452"
 SRCREV_pn-oprofileui ?= "160"
-SRCREV_pn-packagekit ?= "74a3b7e3f3bc8627c23349e0b0d8429fd5f53fc6"
+SRCREV_pn-packagekit ?= "ebbbfa191257861bd19bd47ba646dce590b51858"
 SRCREV_pn-psplash ?= "249"
 SRCREV_pn-pty-forward-native ?= "4214"
 SRCREV_pn-python-odeviced ?= "2f02576532b52732251b3c530a09e4c08685a911"
index bc38d51..57c6e61 100644 (file)
@@ -7,4 +7,10 @@ target_libdir := "${libdir}"
 
 inherit native
 
+# The nogpg version isn't getting much love and has an unused variable which trips up -Werror
+do_configure_prepend() {
+        sed -i -e s:-Werror::g ${S}/libopkg/Makefile.am
+}
+
+
 EXTRA_OECONF += "--with-opkglibdir=${target_libdir} --disable-gpg"
index aa16b55..3a7a0ee 100644 (file)
@@ -7,4 +7,9 @@ SRCREV = "${SRCREV_pn-opkg}"
 
 EXTRA_OECONF += "--disable-gpg"
 
+# The nogpg version isn't getting much love and has an unused variable which trips up -Werror
+do_configure_prepend() {
+       sed -i -e s:-Werror::g ${S}/libopkg/Makefile.am
+}
+
 DEFAULT_PREFERENCE = "-1"
index 50816ef..104e0fd 100644 (file)
@@ -3,7 +3,7 @@ DESCRIPTION_libopkg = "Opkg Package Manager Library"
 SECTION = "base"
 LICENSE = "GPL"
 DEPENDS = "curl gpgme"
-PV = "0.1+svnr${SRCREV}"
+PV = "0.1.4+svnr${SRCREV}"
 
 SRC_URI = "svn://svn.openmoko.org/trunk/src/target/;module=opkg;proto=http \
            file://fix_endianness.patch;patch=1;maxrev=4246"
diff --git a/packages/packagekit/files/d1e096c3267c1c9492041382b954e9327bc8bbec.patch b/packages/packagekit/files/d1e096c3267c1c9492041382b954e9327bc8bbec.patch
new file mode 100644 (file)
index 0000000..f050a50
--- /dev/null
@@ -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@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@server:port
++#
++# ProxyHTTP=username:password@server.lan:8080
++# ProxyFTP=username:password@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@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@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@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@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@server:port "
++                         "ftp_proxy=username:password@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);
diff --git a/packages/packagekit/files/pk-nodocs.patch b/packages/packagekit/files/pk-nodocs.patch
new file mode 100644 (file)
index 0000000..c775128
--- /dev/null
@@ -0,0 +1,10 @@
+--- /tmp/Makefile.am   2008-05-31 12:17:08.492193028 +0200
++++ git/Makefile.am    2008-05-31 12:17:18.884499290 +0200
+@@ -16,7 +16,6 @@
+       client                                          \
+       backends                                        \
+       python                                          \
+-      docs                                            \
+       $(NULL)
+ clean-local :
index b2d7ea8..5ed193a 100644 (file)
@@ -4,11 +4,13 @@ PRIORITY = "optional"
 LICENSE = "GPL"
 DEPENDS = "dbus (>= 1.1.1) dbus-glib glib-2.0 sqlite3 opkg intltool intltool-native (>= 0.37.1)"
 RDEPENDS_${PN} = "opkg"
-PV = "0.1+git${SRCREV}"
+PV = "0.2.1+git${SRCREV}"
 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=1 \
+          file://pk-nodocs.patch;patch=1"
 
 S = "${WORKDIR}/git"