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

Richard Hughes hughsient at kemper.freedesktop.org
Wed Mar 24 09:11:57 PDT 2010


 RELEASE                                          |   10 
 backends/apt/aptBackend.py                       |   30 
 backends/aptcc/apt.cpp                           |  174 -
 backends/aptcc/apt.h                             |    4 
 backends/aptcc/aptcc_show_broken.cpp             |  199 -
 backends/aptcc/aptcc_show_broken.h               |    8 
 backends/aptcc/pk-backend-aptcc.cpp              |   38 
 backends/conary/XMLCache.py                      |   87 
 backends/conary/conaryBackend.py                 |  216 -
 backends/conary/conaryCallback.py                |  457 ---
 backends/conary/conaryProgress.py                |    6 
 backends/conary/conarypk.py                      |    3 
 backends/conary/generateXML.py                   |   30 
 backends/conary/pk-backend-conary.c              |   63 
 backends/entropy/entropyBackend.py               |   10 
 backends/smart/smartBackend.py                   |    9 
 backends/test/pk-backend-test-succeed.c          |    2 
 backends/yum/Makefile.am                         |   81 
 backends/yum/Yum.conf                            |   26 
 backends/yum/libzif/egg-debug.c                  |    1 
 backends/yum/libzif/egg-debug.h                  |    1 
 backends/yum/libzif/egg-string.c                 |    1 
 backends/yum/libzif/egg-string.h                 |    1 
 backends/yum/libzif/zif-completion.c             |  664 +++++
 backends/yum/libzif/zif-completion.h             |   79 
 backends/yum/libzif/zif-config.c                 |  808 ++++++
 backends/yum/libzif/zif-config.h                 |   92 
 backends/yum/libzif/zif-depend.c                 |  175 +
 backends/yum/libzif/zif-depend.h                 |   62 
 backends/yum/libzif/zif-download.c               |  441 +++
 backends/yum/libzif/zif-download.h               |   78 
 backends/yum/libzif/zif-groups.c                 |  474 +++
 backends/yum/libzif/zif-groups.h                 |   80 
 backends/yum/libzif/zif-lock.c                   |  458 +++
 backends/yum/libzif/zif-lock.h                   |   78 
 backends/yum/libzif/zif-monitor.c                |  257 +
 backends/yum/libzif/zif-monitor.h                |   71 
 backends/yum/libzif/zif-package-local.c          |  694 +++++
 backends/yum/libzif/zif-package-local.h          |   71 
 backends/yum/libzif/zif-package-remote.c         |  226 +
 backends/yum/libzif/zif-package-remote.h         |   69 
 backends/yum/libzif/zif-package.c                | 1359 ++++++++++
 backends/yum/libzif/zif-package.h                |  165 +
 backends/yum/libzif/zif-repo-md-comps.c          |  977 +++++++
 backends/yum/libzif/zif-repo-md-comps.h          |   78 
 backends/yum/libzif/zif-repo-md-filelists.c      |  449 +++
 backends/yum/libzif/zif-repo-md-filelists.h      |   68 
 backends/yum/libzif/zif-repo-md-metalink.c       |  503 +++
 backends/yum/libzif/zif-repo-md-metalink.h       |   68 
 backends/yum/libzif/zif-repo-md-mirrorlist.c     |  347 ++
 backends/yum/libzif/zif-repo-md-mirrorlist.h     |   67 
 backends/yum/libzif/zif-repo-md-primary.c        |  749 +++++
 backends/yum/libzif/zif-repo-md-primary.h        |  113 
 backends/yum/libzif/zif-repo-md.c                |  931 +++++++
 backends/yum/libzif/zif-repo-md.h                |  149 +
 backends/yum/libzif/zif-repos.c                  |  638 ++++
 backends/yum/libzif/zif-repos.h                  |   88 
 backends/yum/libzif/zif-self-test.c              |   82 
 backends/yum/libzif/zif-store-array.c            |  838 ++++++
 backends/yum/libzif/zif-store-array.h            |  151 +
 backends/yum/libzif/zif-store-local.c            | 1290 +++++++++
 backends/yum/libzif/zif-store-local.h            |   68 
 backends/yum/libzif/zif-store-remote.c           | 2976 +++++++++++++++++++++++
 backends/yum/libzif/zif-store-remote.h           |   96 
 backends/yum/libzif/zif-store.c                  |  600 ++++
 backends/yum/libzif/zif-store.h                  |  215 +
 backends/yum/libzif/zif-string.c                 |  197 +
 backends/yum/libzif/zif-string.h                 |   44 
 backends/yum/libzif/zif-utils.c                  |  793 ++++++
 backends/yum/libzif/zif-utils.h                  |   74 
 backends/yum/libzif/zif.h                        |   46 
 backends/yum/pk-backend-yum.c                    | 1859 +++++++++++++-
 backends/yum/yum-comps-groups.conf               |    2 
 backends/yum/yumBackend.py                       |  169 -
 client/pk-console.c                              |    6 
 configure.ac                                     |   67 
 contrib/PackageKit.spec.in                       |   38 
 contrib/command-not-found/CommandNotFound.conf   |    8 
 contrib/command-not-found/pk-command-not-found.c |   21 
 data/pk-upgrade-distro.sh                        |   10 
 docs/html/pk-download.html                       |    2 
 etc/PackageKit.conf.in                           |   12 
 lib/packagekit-glib2/pk-client-sync.h            |    6 
 lib/packagekit-glib2/pk-client.c                 |   43 
 lib/packagekit-glib2/pk-console-shared.c         |   13 
 lib/packagekit-glib2/pk-console-shared.h         |    6 
 lib/packagekit-glib2/pk-control-sync.h           |    6 
 lib/packagekit-glib2/pk-enum.c                   |    1 
 lib/packagekit-glib2/pk-enum.h                   |    1 
 lib/packagekit-glib2/pk-package-ids.h            |    4 
 lib/packagekit-glib2/pk-package-sack-sync.h      |    6 
 lib/packagekit-glib2/pk-package-sack.c           |  125 
 lib/packagekit-glib2/pk-package-sack.h           |    9 
 lib/packagekit-glib2/pk-results.c                |   25 
 lib/packagekit-glib2/pk-task-sync.h              |    4 
 lib/packagekit-glib2/pk-task.c                   |   81 
 lib/packagekit-qt/src/transactionprivate.cpp     |    2 
 lib/python/packagekit/backend.py                 |   21 
 lib/python/packagekit/client.py                  |    2 
 po/da.po                                         |  114 
 po/es.po                                         |  137 -
 po/nl.po                                         |  112 
 po/pl.po                                         |  112 
 po/pt.po                                         |  297 +-
 po/ru.po                                         |  539 ++--
 po/sr.po                                         |  426 +--
 po/sr at latin.po                                   |  426 +--
 po/sv.po                                         |  822 +++---
 po/uk.po                                         |  792 +++---
 po/zh_TW.po                                      |  803 +++---
 src/Makefile.am                                  |    6 
 src/egg-debug.c                                  |    1 
 src/gdb.sh                                       |   23 
 src/pk-backend-internal.h                        |    1 
 src/pk-backend-spawn.c                           |   31 
 src/pk-backend-spawn.h                           |    1 
 src/pk-backend.c                                 |   87 
 src/pk-backend.h                                 |    4 
 src/pk-network-stack-nm.c                        |   38 
 src/pk-spawn.c                                   |   83 
 src/pk-store.c                                   |   72 
 src/pk-transaction-extra.c                       |   28 
 src/pk-transaction.c                             |    5 
 123 files changed, 24668 insertions(+), 3394 deletions(-)

New commits:
commit 6c32d907318f81ba7e4b0e477ebe3de2d7f6c906
Author: Richard Hughes <richard at hughsie.com>
Date:   Tue Mar 23 13:41:23 2010 +0000

    CNF: add a boolean configure variable 'SimilarNameSearch' to allow skipping swizzle testing. Fixes #27246

diff --git a/contrib/command-not-found/CommandNotFound.conf b/contrib/command-not-found/CommandNotFound.conf
index a6ff9fa..b43831e 100644
--- a/contrib/command-not-found/CommandNotFound.conf
+++ b/contrib/command-not-found/CommandNotFound.conf
@@ -34,6 +34,14 @@ MultipleMatch=warn
 # default=true
 SoftwareSourceSearch=true
 
+# Controls if the tool should look for similar command names and suggest
+# those instead.
+#
+# Allowed values are 'true' or 'false'
+#
+# default=true
+SimilarNameSearch=true
+
 # Controls what to do when a single package install is found for
 # a missing command.
 # For instance, 'make' prompts the user to install automake-1.8
diff --git a/contrib/command-not-found/pk-command-not-found.c b/contrib/command-not-found/pk-command-not-found.c
index 931ef19..a07da45 100644
--- a/contrib/command-not-found/pk-command-not-found.c
+++ b/contrib/command-not-found/pk-command-not-found.c
@@ -51,6 +51,7 @@ typedef struct {
 	PkCnfPolicy	 single_install;
 	PkCnfPolicy	 multiple_install;
 	gboolean	 software_source_search;
+	gboolean	 similar_name_search;
 	gchar		**locations;
 } PkCnfPolicyConfig;
 
@@ -512,6 +513,7 @@ pk_cnf_get_config (void)
 	config->single_install = PK_CNF_POLICY_UNKNOWN;
 	config->multiple_install = PK_CNF_POLICY_UNKNOWN;
 	config->software_source_search = FALSE;
+	config->similar_name_search = FALSE;
 	config->locations = NULL;
 
 	/* load file */
@@ -530,6 +532,7 @@ pk_cnf_get_config (void)
 	config->single_install = pk_cnf_get_policy_from_file (file, "SingleInstall");
 	config->multiple_install = pk_cnf_get_policy_from_file (file, "MultipleInstall");
 	config->software_source_search = g_key_file_get_boolean (file, "CommandNotFound", "SoftwareSourceSearch", NULL);
+	config->similar_name_search = g_key_file_get_boolean (file, "CommandNotFound", "SimilarNameSearch", NULL);
 	config->locations = g_key_file_get_string_list (file, "CommandNotFound", "SearchLocations", NULL, NULL);
 
 	/* fallback */
@@ -692,14 +695,22 @@ main (int argc, char *argv[])
 		goto out;
 	}
 
-	/* generate swizzles */
-	array = pk_cnf_find_alternatives (argv[1], len);
-
 	/* TRANSLATORS: the prefix of all the output telling the user why it's not executing */
 	g_printerr ("%s ", _("Command not found."));
 
+	/* user is not allowing CNF to do anything useful */
+	if (!config->software_source_search &&
+	    !config->similar_name_search) {
+		retval = EXIT_COMMAND_NOT_FOUND;
+		goto out;
+	}
+
+	/* generate swizzles */
+	if (config->similar_name_search)
+		array = pk_cnf_find_alternatives (argv[1], len);
+
 	/* one exact possibility */
-	if (array->len == 1) {
+	if (array != NULL && array->len == 1) {
 		possible = g_ptr_array_index (array, 0);
 		if (config->single_match == PK_CNF_POLICY_WARN) {
 			/* TRANSLATORS: tell the user what we think the command is */
@@ -724,7 +735,7 @@ main (int argc, char *argv[])
 		goto out;
 
 	/* multiple choice */
-	} else if (array->len > 1) {
+	} else if (array != NULL && array->len > 1) {
 		if (config->multiple_match == PK_CNF_POLICY_WARN) {
 			/* TRANSLATORS: show the user a list of commands that they could have meant */
 			g_printerr ("%s:\n", _("Similar commands are:"));
commit 981d1ccb3a079a689861e7ef61df715eedc8a57a
Author: Richard Hughes <richard at hughsie.com>
Date:   Mon Mar 22 17:14:11 2010 +0000

    Add some missing G_BEGIN_DECLS and G_END_DECLS to fix including from C++
    
    Should hopefully fix rh#572467

diff --git a/lib/packagekit-glib2/pk-client-sync.h b/lib/packagekit-glib2/pk-client-sync.h
index 213e470..abfb2a2 100644
--- a/lib/packagekit-glib2/pk-client-sync.h
+++ b/lib/packagekit-glib2/pk-client-sync.h
@@ -27,6 +27,8 @@
 #include <packagekit-glib2/pk-bitfield.h>
 #include <packagekit-glib2/pk-progress.h>
 
+G_BEGIN_DECLS
+
 PkResults	*pk_client_resolve			(PkClient		*client,
 							 PkBitfield		 filters,
 							 gchar			**packages,
@@ -291,7 +293,7 @@ PkProgress	*pk_client_get_progress			(PkClient		*client,
 							 GCancellable		*cancellable,
 							 GError			**error);
 
-#endif /* __PK_CLIENT_SYNC_H */
-
+G_END_DECLS
 
+#endif /* __PK_CLIENT_SYNC_H */
 
diff --git a/lib/packagekit-glib2/pk-console-shared.h b/lib/packagekit-glib2/pk-console-shared.h
index 618b869..a027741 100644
--- a/lib/packagekit-glib2/pk-console-shared.h
+++ b/lib/packagekit-glib2/pk-console-shared.h
@@ -27,6 +27,8 @@
 #include <packagekit-glib2/pk-bitfield.h>
 #include <packagekit-glib2/pk-enum.h>
 
+G_BEGIN_DECLS
+
 void		 pk_console_test			(gpointer	 user_data);
 guint		 pk_console_get_number			(const gchar	*question,
 							 guint		 maxnum);
@@ -45,7 +47,7 @@ const gchar	*pk_info_enum_to_localised_past		(PkInfoEnum	 info);
 const gchar	*pk_info_enum_to_localised_present	(PkInfoEnum	 info);
 const gchar	*pk_role_enum_to_localised_present	(PkRoleEnum	 role);
 
-#endif /* __PK_CONSOLE_SHARED_H */
-
+G_END_DECLS
 
+#endif /* __PK_CONSOLE_SHARED_H */
 
diff --git a/lib/packagekit-glib2/pk-control-sync.h b/lib/packagekit-glib2/pk-control-sync.h
index cb8b677..73592a4 100644
--- a/lib/packagekit-glib2/pk-control-sync.h
+++ b/lib/packagekit-glib2/pk-control-sync.h
@@ -25,6 +25,8 @@
 #include <glib.h>
 #include <packagekit-glib2/pk-control.h>
 
+G_BEGIN_DECLS
+
 gboolean	 pk_control_get_properties		(PkControl		*control,
 							 GCancellable		*cancellable,
 							 GError			**error);
@@ -34,8 +36,8 @@ gchar		**pk_control_get_transaction_list	(PkControl		*control,
 gboolean	 pk_control_suggest_daemon_quit		(PkControl		*control,
 							 GCancellable		*cancellable,
 							 GError			**error);
-
-#endif /* __PK_CONTROL_SYNC_H */
+G_END_DECLS
 
 
+#endif /* __PK_CONTROL_SYNC_H */
 
diff --git a/lib/packagekit-glib2/pk-package-sack-sync.h b/lib/packagekit-glib2/pk-package-sack-sync.h
index 9445644..778bacc 100644
--- a/lib/packagekit-glib2/pk-package-sack-sync.h
+++ b/lib/packagekit-glib2/pk-package-sack-sync.h
@@ -25,6 +25,8 @@
 #include <glib.h>
 #include <packagekit-glib2/pk-package-sack.h>
 
+G_BEGIN_DECLS
+
 gboolean	 pk_package_sack_resolve		(PkPackageSack		*package_sack,
 							 GCancellable		*cancellable,
 							 GError			**error);
@@ -35,7 +37,7 @@ gboolean	 pk_package_sack_get_update_detail	(PkPackageSack		*package_sack,
 							 GCancellable		*cancellable,
 							 GError			**error);
 
-#endif /* __PK_PACKAGE_SACK_SYNC_H */
-
+G_END_DECLS
 
+#endif /* __PK_PACKAGE_SACK_SYNC_H */
 
diff --git a/lib/packagekit-glib2/pk-task-sync.h b/lib/packagekit-glib2/pk-task-sync.h
index 8d80a8a..e192e2a 100644
--- a/lib/packagekit-glib2/pk-task-sync.h
+++ b/lib/packagekit-glib2/pk-task-sync.h
@@ -27,6 +27,8 @@
 #include <packagekit-glib2/pk-task.h>
 #include <packagekit-glib2/pk-progress.h>
 
+G_BEGIN_DECLS
+
 PkResults	*pk_task_remove_packages_sync		(PkTask			*task,
 							 gchar			**package_ids,
 							 gboolean		 allow_deps,
@@ -63,5 +65,7 @@ PkResults	*pk_task_update_system_sync		(PkTask			*task,
 							 gpointer		 progress_user_data,
 							 GError			**error);
 
+G_END_DECLS
+
 #endif /* __PK_TASK_SYNC_H */
 
commit cdec669fd682f76ba392d71df375b72a02895b0d
Author: Richard Hughes <richard at hughsie.com>
Date:   Mon Mar 22 16:41:32 2010 +0000

    trivial: do not print a verbose debug statement in egg_debug_post_parse_hook()

diff --git a/contrib/PackageKit.spec.in b/contrib/PackageKit.spec.in
index b8e3182..d6b3b16 100644
--- a/contrib/PackageKit.spec.in
+++ b/contrib/PackageKit.spec.in
@@ -15,7 +15,6 @@ License:   GPLv2+
 Group:     System Environment/Libraries
 URL:       http://www.packagekit.org
 Source0:   http://www.packagekit.org/releases/%{name}-%{version}.tar.gz
-BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
 
 Requires: dbus >= %{dbus_version}
 Requires: dbus-glib >= %{dbus_glib_version}
diff --git a/src/egg-debug.c b/src/egg-debug.c
index 64655a2..340ccd0 100644
--- a/src/egg-debug.c
+++ b/src/egg-debug.c
@@ -431,7 +431,6 @@ egg_debug_post_parse_hook (GOptionContext *context, GOptionGroup *group, gpointe
 	_modules_array = egg_debug_strv_split_to_ptr_array (_modules);
 	_functions_array = egg_debug_strv_split_to_ptr_array (_functions);
 	_console = (isatty (fileno (stdout)) == 1);
-	egg_debug ("Verbose debugging %i (on console %i)", _verbose, _console);
 
 	/* run this function on cleanup */
 	atexit (egg_debug_free);
commit 301575ee6c62b72208c319d0de73554e3e7e373e
Author: Daniel Nicoletti <dantti85-pk at yahoo.com.br>
Date:   Fri Mar 19 00:23:03 2010 -0300

    pk-qt: Fixed UpdateState enum

diff --git a/lib/packagekit-qt/src/transactionprivate.cpp b/lib/packagekit-qt/src/transactionprivate.cpp
index be2a946..f3e4c06 100644
--- a/lib/packagekit-qt/src/transactionprivate.cpp
+++ b/lib/packagekit-qt/src/transactionprivate.cpp
@@ -146,7 +146,7 @@ void TransactionPrivate::updateDetail(const QString& pid, const QString& updates
 	i.restart = (Enum::Restart)Util::enumFromString<Enum>(restart, "Restart", "Restart");
 	i.updateText = updateText;
 	i.changelog = changelog;
-	i.state = (Enum::UpdateState)Util::enumFromString<Enum>(state, "UpdateState", "Update");
+	i.state = (Enum::UpdateState)Util::enumFromString<Enum>(state, "UpdateState", "UpdateState");
 	i.issued = QDateTime::fromString(issued, Qt::ISODate);
 	i.updated = QDateTime::fromString(updated, Qt::ISODate);
 
commit e78ba8f77c9dfa4fbbb0b2dc63cdb3173ce4ceb1
Author: Daniel Nicoletti <dantti85-pk at yahoo.com.br>
Date:   Thu Mar 18 18:07:18 2010 -0300

    * Fix Kubuntu support for upgrade (using env var exported by KPackageKit)
     Patch by Jonathan Riddell

diff --git a/data/pk-upgrade-distro.sh b/data/pk-upgrade-distro.sh
old mode 100755
new mode 100644
index 7236e97..0badcb3
--- a/data/pk-upgrade-distro.sh
+++ b/data/pk-upgrade-distro.sh
@@ -24,12 +24,10 @@ if [ -e /etc/fedora-release ]; then
 		xdg-open http://fedoraproject.org/en/get-fedora
 	fi
 elif [ "$DISTRO" = "Ubuntu" ]; then
-	if [ -e /usr/bin/do-release-upgrade ]; then
-		if [ "$DESKTOP" = "kde" ]; then
-			PATH=`kde4-config --path exe` kdesu -- "/usr/bin/do-release-upgrade -d -m desktop -f kde -p"
-		else
-			gksu "/usr/bin/do-release-upgrade -m desktop -f gtk -p"
-		fi
+	if [ -e /usr/share/pyshared/UpdateManager/DistUpgradeFetcherKDE.py ] && [ "$DESKTOP" = "kde" ]; then
+		PATH=`kde4-config --path exe` kdesu -- "python /usr/share/pyshared/UpdateManager/DistUpgradeFetcherKDE.py"
+	elif [ -e /usr/bin/do-release-upgrade ]; then
+			gksu "/usr/bin/do-release-upgrade -m desktop"
 	elif [ "$DESKTOP" = "kde" ]; then
 		xdg-open http://www.kubuntu.org/getkubuntu
 	else
commit 1bcaf457b92eecd069da34b7a4b143743e298a00
Author: Richard Hughes <richard at hughsie.com>
Date:   Thu Mar 18 11:39:26 2010 +0000

    Never exit the daemon, even when we hit a race in PkSpawn - just cleanup, warn, and continue

diff --git a/src/pk-spawn.c b/src/pk-spawn.c
index 7da4242..568377a 100644
--- a/src/pk-spawn.c
+++ b/src/pk-spawn.c
@@ -601,8 +601,10 @@ pk_spawn_argv (PkSpawn *spawn, gchar **argv, gchar **envp)
 	fcntl (spawn->priv->stderr_fd, F_SETFL, O_NONBLOCK);
 
 	/* sanity check */
-	if (spawn->priv->poll_id != 0)
-		egg_error ("trying to set timeout when already set");
+	if (spawn->priv->poll_id != 0) {
+		egg_warning ("trying to set timeout when already set");
+		g_source_remove (spawn->priv->poll_id);
+	}
 
 	/* poll quickly */
 	spawn->priv->poll_id = g_timeout_add (PK_SPAWN_POLL_DELAY, (GSourceFunc) pk_spawn_check_child, spawn);
commit 7ba0793015e19ff6f7e532cd9d92364212217984
Author: Richard Hughes <richard at hughsie.com>
Date:   Wed Mar 17 21:44:07 2010 +0000

    trivial: be less verbose when we are cleaning up after a script that does not do finished

diff --git a/src/pk-backend-internal.h b/src/pk-backend-internal.h
index 61ce5c5..d7d4e0a 100644
--- a/src/pk-backend-internal.h
+++ b/src/pk-backend-internal.h
@@ -74,6 +74,7 @@ PkBitfield	 pk_backend_get_groups			(PkBackend	*backend);
 PkBitfield	 pk_backend_get_filters			(PkBackend	*backend);
 PkBitfield	 pk_backend_get_roles			(PkBackend	*backend);
 gchar		*pk_backend_get_mime_types		(PkBackend	*backend);
+gboolean	 pk_backend_has_set_error_code		(PkBackend	*backend);
 gboolean	 pk_backend_is_implemented		(PkBackend	*backend,
 							 PkRoleEnum	 role);
 gchar		*pk_backend_get_accepted_eula_string	(PkBackend	*backend);
diff --git a/src/pk-backend-spawn.c b/src/pk-backend-spawn.c
index 66e7d3f..bc182da 100644
--- a/src/pk-backend-spawn.c
+++ b/src/pk-backend-spawn.c
@@ -561,6 +561,7 @@ out:
 static void
 pk_backend_spawn_exit_cb (PkSpawn *spawn, PkSpawnExitType exit_enum, PkBackendSpawn *backend_spawn)
 {
+	gboolean ret;
 	g_return_if_fail (PK_IS_BACKEND_SPAWN (backend_spawn));
 
 	/* if we force killed the process, set an error */
@@ -579,9 +580,12 @@ pk_backend_spawn_exit_cb (PkSpawn *spawn, PkSpawnExitType exit_enum, PkBackendSp
 	/* only emit if not finished */
 	if (!backend_spawn->priv->finished) {
 		egg_warning ("script exited without doing finished");
-		pk_backend_error_code (backend_spawn->priv->backend, PK_ERROR_ENUM_INTERNAL_ERROR,
-				       "The backend exited unexpectedly. "
-				       "This is a serious error as the spawned backend did not complete the pending transaction.");
+		ret = pk_backend_has_set_error_code (backend_spawn->priv->backend);
+		if (!ret) {
+			pk_backend_error_code (backend_spawn->priv->backend, PK_ERROR_ENUM_INTERNAL_ERROR,
+					       "The backend exited unexpectedly. "
+					       "This is a serious error as the spawned backend did not complete the pending transaction.");
+		}
 		pk_backend_finished (backend_spawn->priv->backend);
 	}
 }
diff --git a/src/pk-backend.c b/src/pk-backend.c
index c4072e4..82ab420 100644
--- a/src/pk-backend.c
+++ b/src/pk-backend.c
@@ -1854,6 +1854,15 @@ out:
 }
 
 /**
+ * pk_backend_has_set_error_code:
+ **/
+gboolean
+pk_backend_has_set_error_code (PkBackend *backend)
+{
+	return backend->priv->set_error;
+}
+
+/**
  * pk_backend_set_allow_cancel:
  **/
 gboolean
@@ -1939,7 +1948,6 @@ pk_backend_set_exit_code (PkBackend *backend, PkExitEnum exit_enum)
 		egg_warning ("already set exit status: old=%s, new=%s",
 			    pk_exit_enum_to_string (backend->priv->exit),
 			    pk_exit_enum_to_string (exit_enum));
-		egg_debug_backtrace ();
 		return FALSE;
 	}
 
diff --git a/src/pk-spawn.c b/src/pk-spawn.c
index 87eb981..7da4242 100644
--- a/src/pk-spawn.c
+++ b/src/pk-spawn.c
@@ -260,13 +260,12 @@ pk_spawn_check_child (PkSpawn *spawn)
 
 		/* get the exit code */
 		retval = WEXITSTATUS (status);
-		egg_debug ("the child exited with return code %i", retval);
 		if (retval == 0) {
 			egg_debug ("the child exited with success");
 			if (spawn->priv->exit == PK_SPAWN_EXIT_TYPE_UNKNOWN)
 				spawn->priv->exit = PK_SPAWN_EXIT_TYPE_SUCCESS;
 		} else {
-			egg_warning ("something has gone very wrong: the child exited with return code %i", retval);
+			egg_warning ("the child exited with return code %i", retval);
 			if (spawn->priv->exit == PK_SPAWN_EXIT_TYPE_UNKNOWN)
 				spawn->priv->exit = PK_SPAWN_EXIT_TYPE_FAILED;
 		}
diff --git a/src/pk-transaction-extra.c b/src/pk-transaction-extra.c
index 492d82f..d252c89 100644
--- a/src/pk-transaction-extra.c
+++ b/src/pk-transaction-extra.c
@@ -80,13 +80,14 @@ G_DEFINE_TYPE (PkTransactionExtra, pk_transaction_extra, G_TYPE_OBJECT)
 static void
 pk_transaction_extra_finished_cb (PkBackend *backend, PkExitEnum exit_enum, PkTransactionExtra *extra)
 {
-	if (exit_enum != PK_EXIT_ENUM_SUCCESS) {
-		egg_warning ("%s failed with exit code: %s",
-			     pk_role_enum_to_string (pk_backend_get_role (backend)),
-			     pk_exit_enum_to_string (exit_enum));
-	}
-	if (g_main_loop_is_running (extra->priv->loop))
+	if (g_main_loop_is_running (extra->priv->loop)) {
+		if (exit_enum != PK_EXIT_ENUM_SUCCESS) {
+			egg_warning ("%s failed with exit code: %s",
+				     pk_role_enum_to_string (pk_backend_get_role (backend)),
+				     pk_exit_enum_to_string (exit_enum));
+		}
 		g_main_loop_quit (extra->priv->loop);
+	}
 }
 
 /**
commit 5f92c6d07083e0fc761934bf4488245b46dea3df
Author: Richard Hughes <richard at hughsie.com>
Date:   Wed Mar 17 21:20:35 2010 +0000

    python: do not call finished before exiting the script due to an error
    
    Python takes an _enormous_ amount of time to exit, and leaves a
    huge race when you try to change a dispatcher because of an error.
    
    Leave PackageKit to clean up for us in this case.

diff --git a/lib/python/packagekit/backend.py b/lib/python/packagekit/backend.py
index f1bf2df..aa78aaa 100644
--- a/lib/python/packagekit/backend.py
+++ b/lib/python/packagekit/backend.py
@@ -135,8 +135,11 @@ class PackageKitBaseBackend:
         print "error\t%s\t%s" % (err, description)
         sys.stdout.flush()
         if exit:
-            print "finished"
-            sys.stdout.flush()
+            # Paradoxically, we don't want to print "finished" to stdout here.
+            # Python takes an _enormous_ amount of time to exit, and leaves a
+            # huge race when you try to change a dispatcher because of an error.
+            #
+            # Leave PackageKit to clean up for us in this case.
             sys.exit(1)
 
     def message(self, typ, msg):
commit fc7a7f87b07cdd1134b990f31e84888ecfd0d415
Author: Richard Hughes <richard at hughsie.com>
Date:   Wed Mar 17 21:19:14 2010 +0000

    trivial: print an error to the console if the PkTransactionError action fails to run

diff --git a/src/pk-transaction-extra.c b/src/pk-transaction-extra.c
index 9d1b4b6..492d82f 100644
--- a/src/pk-transaction-extra.c
+++ b/src/pk-transaction-extra.c
@@ -80,6 +80,11 @@ G_DEFINE_TYPE (PkTransactionExtra, pk_transaction_extra, G_TYPE_OBJECT)
 static void
 pk_transaction_extra_finished_cb (PkBackend *backend, PkExitEnum exit_enum, PkTransactionExtra *extra)
 {
+	if (exit_enum != PK_EXIT_ENUM_SUCCESS) {
+		egg_warning ("%s failed with exit code: %s",
+			     pk_role_enum_to_string (pk_backend_get_role (backend)),
+			     pk_exit_enum_to_string (exit_enum));
+	}
 	if (g_main_loop_is_running (extra->priv->loop))
 		g_main_loop_quit (extra->priv->loop);
 }
commit b455e2c8d1ddd1d8ba81703aa895b8d4d56d378e
Author: Richard Hughes <richard at hughsie.com>
Date:   Wed Mar 17 20:59:06 2010 +0000

    trivial: poll in a 10ms delay when killing the backend, to avoid the noticable delay when switching dispatchers

diff --git a/src/pk-spawn.c b/src/pk-spawn.c
index 5b5880e..87eb981 100644
--- a/src/pk-spawn.c
+++ b/src/pk-spawn.c
@@ -461,13 +461,15 @@ pk_spawn_exit (PkSpawn *spawn)
 		 * If we run the loop, other idle events can be processed,
 		 * and this includes sending data to a new instance,
 		 * which of course will fail as the 'old' script is exiting */
-		g_usleep (100*1000); /* 100 ms */
+		g_usleep (10*1000); /* 10 ms */
 		ret = pk_spawn_check_child (spawn);
-	} while (ret && count++ < 50);
+	} while (ret && count++ < 500);
 
 	/* the script exited okay */
-	if (count < 50)
+	if (count < 500)
 		ret = TRUE;
+	else
+		egg_warning ("failed to exit script");
 out:
 	spawn->priv->is_sending_exit = FALSE;
 	return ret;
commit d7ab5d0d48a9c970c3d4a5f7ac4fb2d83b74ea0d
Author: Richard Hughes <richard at hughsie.com>
Date:   Wed Mar 17 20:58:17 2010 +0000

    Be more careful when testing the value of waitpid() to try to debug a problem where the backend appears to exit

diff --git a/src/pk-spawn.c b/src/pk-spawn.c
index b31c749..5b5880e 100644
--- a/src/pk-spawn.c
+++ b/src/pk-spawn.c
@@ -179,7 +179,9 @@ pk_spawn_exit_type_enum_to_string (PkSpawnExitType type)
 static gboolean
 pk_spawn_check_child (PkSpawn *spawn)
 {
+	pid_t pid;
 	int status;
+	gint retval;
 	static guint limit_printing = 0;
 
 	/* this shouldn't happen */
@@ -206,8 +208,20 @@ pk_spawn_check_child (PkSpawn *spawn)
 		egg_debug ("polling child_pid=%i (1/20)", spawn->priv->child_pid);
 
 	/* check if the child exited */
-	if (waitpid (spawn->priv->child_pid, &status, WNOHANG) != spawn->priv->child_pid)
+	pid = waitpid (spawn->priv->child_pid, &status, WNOHANG);
+	if (pid == -1) {
+		egg_warning ("failed to get the child PID data for %i", spawn->priv->child_pid);
+		return TRUE;
+	}
+	if (pid == 0) {
+		/* process still exist, but has not changed state */
 		return TRUE;
+	}
+	if (pid != spawn->priv->child_pid) {
+		egg_warning ("some other process id was returned: got %i and wanted %i",
+			     pid, spawn->priv->child_pid);
+		return TRUE;
+	}
 
 	/* disconnect the poll as there will be no more updates */
 	if (spawn->priv->poll_id > 0) {
@@ -224,13 +238,38 @@ pk_spawn_check_child (PkSpawn *spawn)
 	spawn->priv->stderr_fd = -1;
 	spawn->priv->child_pid = -1;
 
-	if (WEXITSTATUS (status) > 0) {
-		egg_debug ("Running fork failed with return value %d", WEXITSTATUS (status));
-		if (spawn->priv->exit == PK_SPAWN_EXIT_TYPE_UNKNOWN)
-			spawn->priv->exit = PK_SPAWN_EXIT_TYPE_FAILED;
+	/* use this to detect SIGKILL and SIGQUIT */
+	if (WIFSIGNALED (status)) {
+		retval = WTERMSIG (status);
+		if (retval == SIGQUIT) {
+			egg_debug ("the child process was terminated by SIGQUIT");
+			spawn->priv->exit = PK_SPAWN_EXIT_TYPE_SIGQUIT;
+		} else if (retval == SIGKILL) {
+			egg_debug ("the child process was terminated by SIGKILL");
+			spawn->priv->exit = PK_SPAWN_EXIT_TYPE_SIGKILL;
+		} else {
+			egg_warning ("the child process was terminated by signal %i", WTERMSIG (status));
+			spawn->priv->exit = PK_SPAWN_EXIT_TYPE_SIGKILL;
+		}
 	} else {
-		if (spawn->priv->exit == PK_SPAWN_EXIT_TYPE_UNKNOWN)
-			spawn->priv->exit = PK_SPAWN_EXIT_TYPE_SUCCESS;
+		/* check we are dead and buried */
+		if (!WIFEXITED (status)) {
+			egg_warning ("the process did not exit, but waitpid() returned!");
+			return TRUE;
+		}
+
+		/* get the exit code */
+		retval = WEXITSTATUS (status);
+		egg_debug ("the child exited with return code %i", retval);
+		if (retval == 0) {
+			egg_debug ("the child exited with success");
+			if (spawn->priv->exit == PK_SPAWN_EXIT_TYPE_UNKNOWN)
+				spawn->priv->exit = PK_SPAWN_EXIT_TYPE_SUCCESS;
+		} else {
+			egg_warning ("something has gone very wrong: the child exited with return code %i", retval);
+			if (spawn->priv->exit == PK_SPAWN_EXIT_TYPE_UNKNOWN)
+				spawn->priv->exit = PK_SPAWN_EXIT_TYPE_FAILED;
+		}
 	}
 
 	/* officially done, although no signal yet */
commit 40b1c10fc0ea87f7a62b891487d38a49a2405093
Author: Richard Hughes <richard at hughsie.com>
Date:   Wed Mar 17 20:57:08 2010 +0000

    trivial: fix up a few comments in PkSpawn

diff --git a/src/pk-spawn.c b/src/pk-spawn.c
index f831435..b31c749 100644
--- a/src/pk-spawn.c
+++ b/src/pk-spawn.c
@@ -269,7 +269,7 @@ pk_spawn_sigkill_cb (PkSpawn *spawn)
 		return FALSE;
 	}
 
-	/* we won't overwrite this if not unknown */
+	/* set this in case the script catches the signal and exits properly */
 	spawn->priv->exit = PK_SPAWN_EXIT_TYPE_SIGKILL;
 
 	egg_debug ("sending SIGKILL %i", spawn->priv->child_pid);
@@ -302,6 +302,9 @@ pk_spawn_is_running (PkSpawn *spawn)
  * pk_spawn_kill:
  *
  * We send SIGQUIT and after a few ms SIGKILL (if allowed)
+ *
+ * IMPORTANT: This is not a syncronous operation, and client programs will need
+ * to wait for the ::exit signal.
  **/
 gboolean
 pk_spawn_kill (PkSpawn *spawn)
@@ -323,7 +326,7 @@ pk_spawn_kill (PkSpawn *spawn)
 		return FALSE;
 	}
 
-	/* we won't overwrite this if not unknown */
+	/* set this in case the script catches the signal and exits properly */
 	spawn->priv->exit = PK_SPAWN_EXIT_TYPE_SIGQUIT;
 
 	egg_debug ("sending SIGQUIT %i", spawn->priv->child_pid);
@@ -407,8 +410,10 @@ pk_spawn_exit (PkSpawn *spawn)
 	/* send command */
 	spawn->priv->is_sending_exit = TRUE;
 	ret = pk_spawn_send_stdin (spawn, "exit");
-	if (!ret)
+	if (!ret) {
+		egg_warning ("failed to send exit");
 		goto out;
+	}
 
 	/* block until the previous script exited */
 	do {
commit 6de3cf2754f707551c364c375f5aa75c9b38c45d
Author: Richard Hughes <richard at hughsie.com>
Date:   Wed Mar 17 20:27:36 2010 +0000

    Do not finish the transaction with success when the spawned backend does an non-finished exit

diff --git a/src/pk-backend-spawn.c b/src/pk-backend-spawn.c
index 2074364..66e7d3f 100644
--- a/src/pk-backend-spawn.c
+++ b/src/pk-backend-spawn.c
@@ -570,10 +570,18 @@ pk_backend_spawn_exit_cb (PkSpawn *spawn, PkSpawnExitType exit_enum, PkBackendSp
 				       "Process had to be killed to be cancelled");
 	}
 
+	if (exit_enum == PK_SPAWN_EXIT_TYPE_DISPATCHER_EXIT ||
+	    exit_enum == PK_SPAWN_EXIT_TYPE_DISPATCHER_CHANGED) {
+		egg_debug ("dispatcher exited, nothing to see here");
+		return;
+	}
+
 	/* only emit if not finished */
-	if (!backend_spawn->priv->finished &&
-	    exit_enum != PK_SPAWN_EXIT_TYPE_DISPATCHER_CHANGED) {
+	if (!backend_spawn->priv->finished) {
 		egg_warning ("script exited without doing finished");
+		pk_backend_error_code (backend_spawn->priv->backend, PK_ERROR_ENUM_INTERNAL_ERROR,
+				       "The backend exited unexpectedly. "
+				       "This is a serious error as the spawned backend did not complete the pending transaction.");
 		pk_backend_finished (backend_spawn->priv->backend);
 	}
 }
commit cf240718d70ba94ae9ede9cc3afdca749c9ff12f
Author: Richard Hughes <richard at hughsie.com>
Date:   Wed Mar 17 20:25:36 2010 +0000

    yum: display the location of the config file used when loading

diff --git a/backends/yum/pk-backend-yum.c b/backends/yum/pk-backend-yum.c
index 52ecfe7..e273372 100644
--- a/backends/yum/pk-backend-yum.c
+++ b/backends/yum/pk-backend-yum.c
@@ -616,6 +616,7 @@ backend_initialize (PkBackend *backend)
 	GFile *file;
 	GError *error = NULL;
 	GKeyFile *key_file = NULL;
+	gchar *config_file = NULL;
 
 	/* create private area */
 	priv = g_new0 (PkBackendYumPrivate, 1);
@@ -639,7 +640,9 @@ backend_initialize (PkBackend *backend)
 
 	/* read the config file */
 	key_file = g_key_file_new ();
-	ret = g_key_file_load_from_file (key_file, SYSCONFDIR "/PackageKit/Yum.conf", G_KEY_FILE_NONE, &error);
+	config_file = g_build_filename (SYSCONFDIR, "PackageKit", "Yum.conf", NULL);
+	egg_debug ("loading configuration from %s", config_file);
+	ret = g_key_file_load_from_file (key_file, config_file, G_KEY_FILE_NONE, &error);
 	if (!ret) {
 		pk_backend_error_code (backend, PK_ERROR_ENUM_REPO_CONFIGURATION_ERROR, "failed to load Yum.conf: %s", error->message);
 		g_error_free (error);
@@ -722,6 +725,7 @@ backend_initialize (PkBackend *backend)
 	/* profile */
 	backend_profile ("read groups");
 out:
+	g_free (config_file);
 	g_key_file_free (key_file);
 	g_object_unref (file);
 }
commit b5d4f689c77ef07df3c73e919d2d62cc03c11bac
Author: Richard Hughes <richard at hughsie.com>
Date:   Wed Mar 17 19:09:52 2010 +0000

    glib: ensure we remove CLEANUP and FINISHED packages from the package sack before we run the simulate callback

diff --git a/lib/packagekit-glib2/pk-task.c b/lib/packagekit-glib2/pk-task.c
index 4469527..e6d4834 100644
--- a/lib/packagekit-glib2/pk-task.c
+++ b/lib/packagekit-glib2/pk-task.c
@@ -197,6 +197,20 @@ pk_task_do_async_action (PkTaskState *state)
 }
 
 /**
+ * pk_task_package_filter_cb:
+ **/
+static gboolean
+pk_task_package_filter_cb (PkPackage *package, gpointer user_data)
+{
+	PkInfoEnum info;
+	info = pk_package_get_info (package);
+	if (info == PK_INFO_ENUM_CLEANUP ||
+	    info == PK_INFO_ENUM_FINISHED)
+		return FALSE;
+	return TRUE;
+}
+
+/**
  * pk_task_simulate_ready_cb:
  **/
 static void
@@ -276,13 +290,18 @@ pk_task_simulate_ready_cb (GObject *source_object, GAsyncResult *res, PkTaskStat
 	/* get data */
 	sack = pk_results_get_package_sack (results);
 
+	/* remove all the cleanup and finished packages */
+	pk_package_sack_remove_by_filter (sack, pk_task_package_filter_cb, state);
+
 	/* remove all the original packages from the sack */
 	if (state->package_ids != NULL) {
 		length = g_strv_length (state->package_ids);
 		for (i=0; i<length; i++)
 			pk_package_sack_remove_package_by_id (sack, state->package_ids[i]);
+	}
 
-		/* remove packages from the array that will not be useful */
+	/* remove packages from the array that will not be useful */
+	if (state->package_ids != NULL) {
 		array = pk_results_get_package_array (results);
 		while (idx < array->len) {
 			item = g_ptr_array_index (array, idx);
commit 944392eaecc399cb9db92c7b34917c47c052cb26
Author: Richard Hughes <richard at hughsie.com>
Date:   Wed Mar 17 19:07:18 2010 +0000

    glib: add some self tests for pk_package_sack_remove_by_filter()

diff --git a/lib/packagekit-glib2/pk-package-sack.c b/lib/packagekit-glib2/pk-package-sack.c
index 3dada82..29e895b 100644
--- a/lib/packagekit-glib2/pk-package-sack.c
+++ b/lib/packagekit-glib2/pk-package-sack.c
@@ -355,18 +355,21 @@ pk_package_sack_remove_by_filter (PkPackageSack *sack, PkPackageSackFilterFunc f
 {
 	gboolean ret = FALSE;
 	PkPackage *package;
-	guint i;
+	gint i;
 	PkPackageSackPrivate *priv = sack->priv;
 
 	g_return_val_if_fail (PK_IS_PACKAGE_SACK (sack), FALSE);
 	g_return_val_if_fail (filter_cb != NULL, FALSE);
 
 	/* add each that matches the info enum */
-	for (i = 0; i < priv->array->len; i++) {
+	for (i = 0; i < (gint) priv->array->len; i++) {
 		package = g_ptr_array_index (priv->array, i);
 		if (!filter_cb (package, user_data)) {
 			ret = TRUE;
 			pk_package_sack_remove_package (sack, package);
+
+			/* ensure we pick up subsequent matches */
+			i--;
 		}
 	}
 	return ret;
@@ -1158,6 +1161,19 @@ pk_package_sack_test_update_detail_cb (GObject *object, GAsyncResult *res, EggTe
 	egg_test_loop_quit (test);
 }
 
+/**
+ * pk_package_sack_test_filter_cb:
+ **/
+static gboolean
+pk_package_sack_test_filter_cb (PkPackage *package, gpointer user_data)
+{
+	PkInfoEnum info;
+	info = pk_package_get_info (package);
+	if (info == PK_INFO_ENUM_UNKNOWN)
+		return FALSE;
+	return TRUE;
+}
+
 void
 pk_package_sack_test (gpointer user_data)
 {
@@ -1290,6 +1306,18 @@ pk_package_sack_test (gpointer user_data)
 	ret = pk_package_sack_remove_package_by_id (sack, "powertop;1.8-1.fc8;i386;fedora");
 	egg_test_assert (test, !ret);
 
+	/************************************************************/
+	egg_test_title (test, "remove by filter");
+	pk_package_sack_add_package_by_id (sack, "powertop;1.8-1.fc8;i386;fedora", NULL);
+	pk_package_sack_add_package_by_id (sack, "powertop-debuginfo;1.8-1.fc8;i386;fedora", NULL);
+	ret = pk_package_sack_remove_by_filter (sack, pk_package_sack_test_filter_cb, test);
+	egg_test_assert (test, ret);
+
+	/************************************************************/
+	egg_test_title (test, "check all removed");
+	size = pk_package_sack_get_size (sack);
+	egg_test_assert (test, (size == 0));
+
 	g_object_unref (sack);
 	egg_test_end (test);
 }
commit 4916a0fb4513cff22bd4d9c3189713b7f3c3ca25
Author: Richard Hughes <richard at hughsie.com>
Date:   Wed Mar 17 17:28:35 2010 +0000

    glib: do not generate a PkPackageSack from the package array, instead add packages as they appear
    
    This clears the bug where the new PkPackageSack has packages present
    that we're just removed...

diff --git a/lib/packagekit-glib2/pk-results.c b/lib/packagekit-glib2/pk-results.c
index dcff6bb..30c25c3 100644
--- a/lib/packagekit-glib2/pk-results.c
+++ b/lib/packagekit-glib2/pk-results.c
@@ -67,6 +67,7 @@ struct _PkResultsPrivate
 	GPtrArray		*media_change_required_array;
 	GPtrArray		*repo_detail_array;
 	GPtrArray		*message_array;
+	PkPackageSack		*package_sack;
 };
 
 enum {
@@ -182,6 +183,7 @@ pk_results_add_package (PkResults *results, PkPackage *item)
 	}
 
 	/* copy and add to array */
+	pk_package_sack_add_package (results->priv->package_sack, item);
 	g_ptr_array_add (results->priv->package_array, g_object_ref (item));
 
 	return TRUE;
@@ -553,32 +555,15 @@ pk_results_get_package_array (PkResults *results)
  *
  * Gets a package sack from the transaction.
  *
- * Return value: A #PkPackageSack of data.
+ * Return value: A #PkPackageSack of data, g_object_unref() to free.
  *
  * Since: 0.5.2
  **/
 PkPackageSack *
 pk_results_get_package_sack (PkResults *results)
 {
-	PkPackage *package;
-	PkPackageSack *sack;
-	GPtrArray *array;
-	guint i;
-
 	g_return_val_if_fail (PK_IS_RESULTS (results), NULL);
-
-	/* create a new sack */
-	sack = pk_package_sack_new ();
-
-	/* go through each of the bare packages */
-	array = results->priv->package_array;
-	for (i=0; i<array->len; i++) {
-		package = g_ptr_array_index (array, i);
-		pk_package_sack_add_package (sack, g_object_ref (package));
-		g_object_unref (package);
-	}
-
-	return sack;
+	return g_object_ref (results->priv->package_sack);
 }
 
 /**
@@ -884,6 +869,7 @@ pk_results_init (PkResults *results)
 	results->priv->progress = NULL;
 	results->priv->error_code = NULL;
 	results->priv->package_array = g_ptr_array_new_with_free_func ((GDestroyNotify) g_object_unref);
+	results->priv->package_sack = pk_package_sack_new ();
 	results->priv->details_array = g_ptr_array_new_with_free_func ((GDestroyNotify) g_object_unref);
 	results->priv->update_detail_array = g_ptr_array_new_with_free_func ((GDestroyNotify) g_object_unref);
 	results->priv->category_array = g_ptr_array_new_with_free_func ((GDestroyNotify) g_object_unref);
@@ -920,6 +906,7 @@ pk_results_finalize (GObject *object)
 	g_ptr_array_unref (priv->media_change_required_array);
 	g_ptr_array_unref (priv->repo_detail_array);
 	g_ptr_array_unref (priv->message_array);
+	g_object_unref (priv->package_sack);
 	if (results->priv->progress != NULL)
 		g_object_unref (results->priv->progress);
 	if (results->priv->error_code != NULL)
commit 4e88f66d890d787a629f38ca48d68ffe45d46574
Author: Richard Hughes <richard at hughsie.com>
Date:   Wed Mar 17 17:26:39 2010 +0000

    glib: add pk_package_sack_filter() and pk_package_sack_remove_by_filter()

diff --git a/lib/packagekit-glib2/pk-package-sack.c b/lib/packagekit-glib2/pk-package-sack.c
index aac9b4e..3dada82 100644
--- a/lib/packagekit-glib2/pk-package-sack.c
+++ b/lib/packagekit-glib2/pk-package-sack.c
@@ -181,6 +181,42 @@ pk_package_sack_filter_by_info (PkPackageSack *sack, PkInfoEnum info)
 }
 
 /**
+ * pk_package_sack_filter:
+ * @sack: a valid #PkPackageSack instance
+ * @filter_cb: a #PkPackageSackFilterFunc, which returns %TRUE for the #PkPackage's to add
+ * @user_data: user data to pass to @filter_cb
+ *
+ * Returns a new package sack which only matches packages that return %TRUE
+ * from the filter function.
+ *
+ * Return value: a new #PkPackageSack, free with g_object_unref()
+ *
+ * Since: 0.6.3
+ **/
+PkPackageSack *
+pk_package_sack_filter (PkPackageSack *sack, PkPackageSackFilterFunc filter_cb, gpointer user_data)
+{
+	PkPackageSack *results;
+	PkPackage *package;
+	guint i;
+	PkPackageSackPrivate *priv = sack->priv;
+
+	g_return_val_if_fail (PK_IS_PACKAGE_SACK (sack), NULL);
+	g_return_val_if_fail (filter_cb != NULL, NULL);
+
+	/* create new sack */
+	results = pk_package_sack_new ();
+
+	/* add each that matches the info enum */
+	for (i = 0; i < priv->array->len; i++) {
+		package = g_ptr_array_index (priv->array, i);
+		if (filter_cb (package, user_data))
+			pk_package_sack_add_package (results, package);
+	}
+	return results;
+}
+
+/**
  * pk_package_sack_add_package:
  * @sack: a valid #PkPackageSack instance
  * @package: a valid #PkPackage instance
@@ -302,6 +338,41 @@ pk_package_sack_remove_package_by_id (PkPackageSack *sack, const gchar *package_
 }
 
 /**
+ * pk_package_sack_remove_by_filter:
+ * @sack: a valid #PkPackageSack instance
+ * @filter_cb: a #PkPackageSackFilterFunc, which returns %TRUE for the #PkPackage's to retain
+ * @user_data: user data to pass to @filter_cb
+ *
+ * Removes from the package sack any packages that return %FALSE from the filter
+ * function.
+ *
+ * Return value: %TRUE if a package was removed from the sack
+ *
+ * Since: 0.6.3
+ **/
+gboolean
+pk_package_sack_remove_by_filter (PkPackageSack *sack, PkPackageSackFilterFunc filter_cb, gpointer user_data)
+{
+	gboolean ret = FALSE;
+	PkPackage *package;
+	guint i;
+	PkPackageSackPrivate *priv = sack->priv;
+
+	g_return_val_if_fail (PK_IS_PACKAGE_SACK (sack), FALSE);
+	g_return_val_if_fail (filter_cb != NULL, FALSE);
+
+	/* add each that matches the info enum */
+	for (i = 0; i < priv->array->len; i++) {
+		package = g_ptr_array_index (priv->array, i);
+		if (!filter_cb (package, user_data)) {
+			ret = TRUE;
+			pk_package_sack_remove_package (sack, package);
+		}
+	}
+	return ret;
+}
+
+/**
  * pk_package_sack_find_by_id:
  * @sack: a valid #PkPackageSack instance
  * @package_id: a package_id descriptor
diff --git a/lib/packagekit-glib2/pk-package-sack.h b/lib/packagekit-glib2/pk-package-sack.h
index fd306c8..0fbaa1f 100644
--- a/lib/packagekit-glib2/pk-package-sack.h
+++ b/lib/packagekit-glib2/pk-package-sack.h
@@ -80,6 +80,9 @@ GType		 pk_package_sack_get_type		(void);
 PkPackageSack	*pk_package_sack_new			(void);
 void		 pk_package_sack_test			(gpointer		 user_data);
 
+typedef gboolean (*PkPackageSackFilterFunc)		(PkPackage		*package,
+							 gpointer		 user_data);
+
 /* managing the array */
 void		 pk_package_sack_clear			(PkPackageSack		*sack);
 gchar		**pk_package_sack_get_ids		(PkPackageSack		*sack);
@@ -96,10 +99,16 @@ gboolean	 pk_package_sack_remove_package		(PkPackageSack		*sack,
 							 PkPackage		*package);
 gboolean	 pk_package_sack_remove_package_by_id	(PkPackageSack		*sack,
 							 const gchar		*package_id);
+gboolean	 pk_package_sack_remove_by_filter	(PkPackageSack		*sack,
+							 PkPackageSackFilterFunc filter_cb,
+							 gpointer		 user_data);
 PkPackage	*pk_package_sack_find_by_id		(PkPackageSack		*sack,
 							 const gchar		*package_id);
 PkPackageSack	*pk_package_sack_filter_by_info		(PkPackageSack		*sack,
 							 PkInfoEnum		 info);
+PkPackageSack	*pk_package_sack_filter			(PkPackageSack		*sack,
+							 PkPackageSackFilterFunc filter_cb,
+							 gpointer		 user_data);
 guint64		 pk_package_sack_get_total_bytes	(PkPackageSack		*sack);
 
 gboolean	 pk_package_sack_merge_generic_finish	(PkPackageSack		*sack,
commit 77db664167c406afea590526bc0762241c02fb44
Author: Richard Hughes <richard at hughsie.com>
Date:   Wed Mar 17 17:04:50 2010 +0000

    trivial: use the const package data to reduce the number of g_strdup and g_free's we do when sorting a large list of packages

diff --git a/lib/packagekit-glib2/pk-package-sack.c b/lib/packagekit-glib2/pk-package-sack.c
index af61ed6..aac9b4e 100644
--- a/lib/packagekit-glib2/pk-package-sack.c
+++ b/lib/packagekit-glib2/pk-package-sack.c
@@ -379,17 +379,11 @@ pk_package_sack_sort_compare_package_id_func (PkPackage **a, PkPackage **b)
 static gint
 pk_package_sack_sort_compare_summary_func (PkPackage **a, PkPackage **b)
 {
-	gint retval;
-	gchar *summary1;
-	gchar *summary2;
-
-	g_object_get (*a, "summary", &summary1, NULL);
-	g_object_get (*b, "summary", &summary2, NULL);
-	retval = g_strcmp0 (summary1, summary2);
-
-	g_free (summary1);
-	g_free (summary2);
-	return retval;
+	const gchar *summary1;
+	const gchar *summary2;
+	summary1 = pk_package_get_summary (*a);
+	summary2 = pk_package_get_summary (*b);
+	return g_strcmp0 (summary1, summary2);
 }
 
 /**
@@ -398,12 +392,10 @@ pk_package_sack_sort_compare_summary_func (PkPackage **a, PkPackage **b)
 static gint
 pk_package_sack_sort_compare_info_func (PkPackage **a, PkPackage **b)
 {
-	PkInfoEnum *info1;
-	PkInfoEnum *info2;
-
-	g_object_get (*a, "info", &info1, NULL);
-	g_object_get (*b, "info", &info2, NULL);
-
+	PkInfoEnum info1;
+	PkInfoEnum info2;
+	info1 = pk_package_get_info (*a);
+	info2 = pk_package_get_info (*b);
 	if (info1 == info2)
 		return 0;
 	else if (info1 > info2)
commit 3fe8ab433623faf5f40681e06ebc9d4fbefcd64b
Author: kmilos <kmilos at fedoraproject.org>
Date:   Tue Mar 16 20:46:09 2010 +0000

    l10n: Updates to Serbian (Latin) (sr at latin) translation
    
    Transmitted-via: Transifex (translate.fedoraproject.org)

diff --git a/po/sr at latin.po b/po/sr at latin.po
index afc120b..bb9bd90 100644
--- a/po/sr at latin.po
+++ b/po/sr at latin.po
@@ -11,15 +11,15 @@ msgid ""
 msgstr ""
 "Project-Id-Version: PackageKit\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2009-12-06 20:02+0000\n"
-"PO-Revision-Date: 2009-11-28 20:48-0000\n"
+"POT-Creation-Date: 2010-03-16 19:09+0000\n"
+"PO-Revision-Date: 2010-03-16 20:40+0100\n"
 "Last-Translator: Miloš Komarčević <kmilos at gmail.com>\n"
-"Language-Team: Serbian <fedora-trans-sr at redhat.com>\n"
+"Language-Team: Serbian <trans-sr at lists.fedoraproject.org>\n"
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%"
-"10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n"
+"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%"
+"10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n"
 
 #. TRANSLATORS: this is an atomic transaction
 #. TRANSLATORS: the role is the point of the transaction, e.g. update-system
@@ -47,7 +47,7 @@ msgstr "Netačno"
 
 #. TRANSLATORS: this is the transactions role, e.g. "update-system"
 #. TRANSLATORS: the trasaction role, e.g. update-system
-#: ../client/pk-console.c:181 ../src/pk-polkit-action-lookup.c:336
+#: ../client/pk-console.c:181 ../src/pk-polkit-action-lookup.c:332
 msgid "Role"
 msgstr "Radnja"
 
@@ -62,7 +62,7 @@ msgstr "(sekundi)"
 
 #. TRANSLATORS: this is The command line used to do the action
 #. TRANSLATORS: the command line of the thing that wants the authentication
-#: ../client/pk-console.c:190 ../src/pk-polkit-action-lookup.c:350
+#: ../client/pk-console.c:190 ../src/pk-polkit-action-lookup.c:346
 msgid "Command line"
 msgstr "Komandna linija"
 
@@ -143,7 +143,7 @@ msgstr "Više o nadgradnji:"
 #: ../client/pk-console.c:346 ../client/pk-console.c:616
 #: ../lib/packagekit-glib2/pk-task-text.c:126
 #: ../lib/packagekit-glib2/pk-task-text.c:208
-#: ../src/pk-polkit-action-lookup.c:361
+#: ../src/pk-polkit-action-lookup.c:357
 msgid "Package"
 msgid_plural "Packages"
 msgstr[0] "Paket"
@@ -203,7 +203,7 @@ msgstr "Izdato"
 
 #. TRANSLATORS: details about the update, date the update was updated
 #. TRANSLATORS: The action of the package, in past tense
-#: ../client/pk-console.c:389 ../lib/packagekit-glib2/pk-console-shared.c:510
+#: ../client/pk-console.c:389 ../lib/packagekit-glib2/pk-console-shared.c:511
 msgid "Updated"
 msgstr "Datum ažuriranja"
 
@@ -273,40 +273,44 @@ msgid "Status"
 msgstr "Status"
 
 #. TRANSLATORS: the results from the transaction
-#: ../client/pk-console.c:678
+#: ../client/pk-console.c:679
 msgid "Results:"
 msgstr "Rezultati:"
 
 #. TRANSLATORS: we failed to get any results, which is pretty fatal in my book
-#: ../client/pk-console.c:685
+#: ../client/pk-console.c:686
 msgid "Fatal error"
 msgstr "Kobna greška"
 
 #. TRANSLATORS: the transaction failed in a way we could not expect
-#: ../client/pk-console.c:694
+#: ../client/pk-console.c:695
 #: ../contrib/command-not-found/pk-command-not-found.c:432
 #: ../contrib/command-not-found/pk-command-not-found.c:603
 msgid "The transaction failed"
 msgstr "Transakcija nije uspela"
 
 #. TRANSLATORS: print a message when there are no updates
-#: ../client/pk-console.c:721
+#: ../client/pk-console.c:726
 msgid "There are no updates available at this time."
 msgstr "Trenutno nema dostupnih ažuriranja."
 
+#: ../client/pk-console.c:749
+msgid "There are no upgrades available at this time."
+msgstr "Trenutno nema dostupnih nadgradnji."
+
 #. TRANSLATORS: a package needs to restart their system
-#: ../client/pk-console.c:808
+#: ../client/pk-console.c:816
 msgid "Please restart the computer to complete the update."
 msgstr "Neophodno je ponovno pokretanje sistema radi završetka ažuriranja."
 
 #. TRANSLATORS: a package needs to restart the session
-#: ../client/pk-console.c:811
+#: ../client/pk-console.c:819
 msgid "Please logout and login to complete the update."
 msgstr ""
 "Neophodno je odjavljivanje i ponovna prijava radi završetka ažuriranja."
 
 #. TRANSLATORS: a package needs to restart their system (due to security)
-#: ../client/pk-console.c:814
+#: ../client/pk-console.c:822
 msgid ""
 "Please restart the computer to complete the update as important security "
 "updates have been installed."
@@ -315,7 +319,7 @@ msgstr ""
 "instalirana važna bezbednosna ažuriranja."
 
 #. TRANSLATORS: a package needs to restart the session (due to security)
-#: ../client/pk-console.c:817
+#: ../client/pk-console.c:825
 msgid ""
 "Please logout and login to complete the update as important security updates "
 "have been installed."
@@ -323,20 +327,30 @@ msgstr ""
 "Neophodno je odjavljivanje i ponovna prijava radi završetka ažuriranja jer "
 "su instalirana važna bezbednosna ažuriranja."
 
+#. TRANSLATORS: The user used 'pkcon install dave.rpm' rather than 'pkcon install-local dave.rpm'
+#: ../client/pk-console.c:851
+#, c-format
+msgid ""
+"Extected package name, actually got file. Try using 'pkcon install-local %s' "
+"instead."
+msgstr ""
+"Očekivano je ime paketa, ustvari je dobijena datoteka. Pokušajte da "
+"upotrebite „pkcon install-local %s“ namesto."
+
 #. TRANSLATORS: There was an error getting the list of files for the package. The detailed error follows
-#: ../client/pk-console.c:840
+#: ../client/pk-console.c:859
 #, c-format
 msgid "This tool could not find any available package: %s"
 msgstr "Ova alatka nije mogla pronaći nikakve dostupne pakete: %s"
 
 #. TRANSLATORS: There was an error getting the list of files for the package. The detailed error follows
-#: ../client/pk-console.c:868
+#: ../client/pk-console.c:887
 #, c-format
 msgid "This tool could not find the installed package: %s"
 msgstr "Ova alatka nije mogla pronaći instalirani paket: %s"
 
 #. TRANSLATORS: There was an error getting the list of files for the package. The detailed error follows
-#: ../client/pk-console.c:896 ../client/pk-console.c:924
+#: ../client/pk-console.c:915 ../client/pk-console.c:943
 #, c-format
 msgid "This tool could not find the package: %s"
 msgstr "Ova alatka nije mogla pronaći paket: %s"
@@ -345,190 +359,190 @@ msgstr "Ova alatka nije mogla pronaći paket: %s"
 #. TRANSLATORS: There was an error getting the dependencies for the package. The detailed error follows
 #. TRANSLATORS: There was an error getting the details about the package. The detailed error follows
 #. TRANSLATORS: The package name was not found in any software sources. The detailed error follows
-#: ../client/pk-console.c:952 ../client/pk-console.c:980
-#: ../client/pk-console.c:1008 ../client/pk-console.c:1036
-#: ../client/pk-console.c:1064
+#: ../client/pk-console.c:971 ../client/pk-console.c:999
+#: ../client/pk-console.c:1027 ../client/pk-console.c:1055
+#: ../client/pk-console.c:1083
 #, c-format
 msgid "This tool could not find all the packages: %s"
 msgstr "Ova alatka nije pronašla sve pakete: %s"
 
 #. TRANSLATORS: This is when the daemon crashed, and we are up shit creek without a paddle
-#: ../client/pk-console.c:1093
+#: ../client/pk-console.c:1112
 msgid "The daemon crashed mid-transaction!"
 msgstr "Uslužni program se iznenada prekinuo!"
 
 #. TRANSLATORS: This is the header to the --help menu
-#: ../client/pk-console.c:1127
+#: ../client/pk-console.c:1146
 msgid "PackageKit Console Interface"
 msgstr "Tekstualno sučelje programa PaketKit"
 
 #. these are commands we can use with pkcon
-#: ../client/pk-console.c:1129
+#: ../client/pk-console.c:1148
 msgid "Subcommands:"
 msgstr "Naredbe:"
 
 #. TRANSLATORS: we keep a database updated with the time that an action was last executed
-#: ../client/pk-console.c:1208
+#: ../client/pk-console.c:1227
 msgid "Failed to get the time since this action was last completed"
 msgstr "Datum poslednjeg izvršavanja ove radnje nije pronađen"
 
 #. TRANSLATORS: command line argument, just show the version string
-#: ../client/pk-console.c:1244 ../client/pk-monitor.c:280
+#: ../client/pk-console.c:1263 ../client/pk-monitor.c:306
 msgid "Show the program version and exit"
 msgstr "Prikaži verziju programa i završi rad"
 
 #. TRANSLATORS: command line argument, use a filter to narrow down results
-#: ../client/pk-console.c:1247
+#: ../client/pk-console.c:1266
 msgid "Set the filter, e.g. installed"
 msgstr "Namesti filter, npr. instalirani"
 
 #. TRANSLATORS: command line argument, work asynchronously
-#: ../client/pk-console.c:1250
+#: ../client/pk-console.c:1269
 msgid "Exit without waiting for actions to complete"
 msgstr "Završi rad bez čekanja da se poslovi završe"
 
 #. command line argument, do we ask questions
-#: ../client/pk-console.c:1253
+#: ../client/pk-console.c:1272
 #: ../contrib/debuginfo-install/pk-debuginfo-install.c:527
 msgid "Install the packages without asking for confirmation"
 msgstr "Instaliraj pakete bez pitanja za potvrdu"
 
 #. TRANSLATORS: command line argument, this command is not a priority
-#: ../client/pk-console.c:1256
+#: ../client/pk-console.c:1275
 msgid "Run the command using idle network bandwidth and also using less power"
 msgstr ""
 "Izvrši naredbu koristeći neiskorišćeni mrežni opseg i takođe trošeći manje "
 "energije"
 
 #. TRANSLATORS: command line argument, just output without fancy formatting
-#: ../client/pk-console.c:1259
+#: ../client/pk-console.c:1278
 msgid ""
 "Print to screen a machine readable output, rather than using animated widgets"
 msgstr ""
 "Štampaj izlaz čitljiv mašini na ekranu, umesto upotrebe animiranih vidžeta"
 
 #. TRANSLATORS: we failed to contact the daemon
-#: ../client/pk-console.c:1281
+#: ../client/pk-console.c:1300
 msgid "Failed to contact PackageKit"
 msgstr "Neuspešno kontaktiranje PaketKita."
 
 #. TRANSLATORS: The user specified an incorrect filter
-#: ../client/pk-console.c:1339
+#: ../client/pk-console.c:1358
 msgid "The filter specified was invalid"
 msgstr "Navedeni filter nije ispravan"
 
 #. TRANSLATORS: a search type can be name, details, file, etc
-#: ../client/pk-console.c:1358
+#: ../client/pk-console.c:1377
 msgid "A search type is required, e.g. name"
 msgstr "Morate navesti vrstu pretrage, npr. po imenu"
 
 #. TRANSLATORS: the user needs to provide a search term
-#: ../client/pk-console.c:1365 ../client/pk-console.c:1377
-#: ../client/pk-console.c:1389 ../client/pk-console.c:1401
+#: ../client/pk-console.c:1384 ../client/pk-console.c:1396
+#: ../client/pk-console.c:1408 ../client/pk-console.c:1420
 msgid "A search term is required"
 msgstr "Morate navesti termin za pretragu"
 
 #. TRANSLATORS: the search type was provided, but invalid
-#: ../client/pk-console.c:1411
+#: ../client/pk-console.c:1430
 msgid "Invalid search type"
 msgstr "Neispravna vrsta pretrage"
 
 #. TRANSLATORS: the user did not specify what they wanted to install
-#: ../client/pk-console.c:1417
+#: ../client/pk-console.c:1436
 msgid "A package name to install is required"
 msgstr "Neophodno je ime paketa za instalaciju"
 
 #. TRANSLATORS: the user did not specify what they wanted to install
-#: ../client/pk-console.c:1426
+#: ../client/pk-console.c:1445
 msgid "A filename to install is required"
 msgstr "Neophodno je ime datoteke za instalaciju"
 
 #. TRANSLATORS: geeky error, 99.9999% of users won't see this
-#: ../client/pk-console.c:1438
+#: ../client/pk-console.c:1457
 msgid "A type, key_id and package_id are required"
 msgstr "Morate navesti vrstu, IB ključa i IB paketa (key_id i package_id)"
 
 #. TRANSLATORS: the user did not specify what they wanted to remove
-#: ../client/pk-console.c:1449
+#: ../client/pk-console.c:1468
 msgid "A package name to remove is required"
 msgstr "Morate navesti naziv paketa za uklanjanje"
 
 #. TRANSLATORS: the user did not specify anything about what to download or where
-#: ../client/pk-console.c:1458
+#: ../client/pk-console.c:1477
 msgid "A destination directory and the package names to download are required"
 msgstr "Neophodni su odredišni direktorijum i imena paketa za preuzimanje"
 
 #. TRANSLATORS: the directory does not exist, so we can't continue
-#: ../client/pk-console.c:1465
+#: ../client/pk-console.c:1484
 msgid "Directory not found"
 msgstr "Direktorijum nije nađen"
 
 #. TRANSLATORS: geeky error, 99.9999% of users won't see this
-#: ../client/pk-console.c:1474
+#: ../client/pk-console.c:1493
 msgid "A licence identifier (eula-id) is required"
 msgstr "Morete navesti identifikator licence (eula-id)"
 
 #. TRANSLATORS: geeky error, 99.9999% of users won't see this
-#: ../client/pk-console.c:1485
+#: ../client/pk-console.c:1504
 msgid "A transaction identifier (tid) is required"
 msgstr "Morate navesti identifikator transakcije (tid)"
 
 #. TRANSLATORS: The user did not specify a package name
-#: ../client/pk-console.c:1506
+#: ../client/pk-console.c:1525
 msgid "A package name to resolve is required"
 msgstr "Morate navesti ime paketa za razrešavanje"
 
 #. TRANSLATORS: The user did not specify a repository (software source) name
-#: ../client/pk-console.c:1517 ../client/pk-console.c:1528
+#: ../client/pk-console.c:1536 ../client/pk-console.c:1547
 msgid "A repository name is required"
 msgstr "Morate navesti ime riznice"
 
 #. TRANSLATORS: The user didn't provide any data
-#: ../client/pk-console.c:1539
+#: ../client/pk-console.c:1558
 msgid "A repo name, parameter and value are required"
 msgstr "Morate navesti ime, parametar i vrednost riznice"
 
 #. TRANSLATORS: The user didn't specify what action to use
-#: ../client/pk-console.c:1556
+#: ../client/pk-console.c:1575
 msgid "An action, e.g. 'update-system' is required"
 msgstr "Morate navesti radnju, npr. „update-system“ (ažuriranje sistema)"
 
 #. TRANSLATORS: The user specified an invalid action
-#: ../client/pk-console.c:1563
+#: ../client/pk-console.c:1582
 msgid "A correct role is required"
 msgstr "Morate navesti važeću radnju"
 
 #. TRANSLATORS: The user did not provide a package name
 #. TRANSLATORS: This is when the user fails to supply the package name
-#: ../client/pk-console.c:1573 ../client/pk-console.c:1588
-#: ../client/pk-console.c:1597 ../client/pk-console.c:1617
-#: ../client/pk-console.c:1626 ../client/pk-generate-pack.c:298
+#: ../client/pk-console.c:1592 ../client/pk-console.c:1607
+#: ../client/pk-console.c:1616 ../client/pk-console.c:1636
+#: ../client/pk-console.c:1645 ../client/pk-generate-pack.c:316
 msgid "A package name is required"
 msgstr "Morate navesti ime paketa"
 
 #. TRANSLATORS: each package "provides" certain things, e.g. mime(gstreamer-decoder-mp3), the user didn't specify it
-#: ../client/pk-console.c:1606
+#: ../client/pk-console.c:1625
 msgid "A package provide string is required"
 msgstr "Morate navesti „provide“ niz (šta paket pruža)"
 
 #. TRANSLATORS: The user tried to use an unsupported option on the command line
-#: ../client/pk-console.c:1686
+#: ../client/pk-console.c:1705
 #, c-format
 msgid "Option '%s' is not supported"
 msgstr "Opcija „%s“ nije podržana"
 
 #. TRANSLATORS: Generic failure of what they asked to do
-#: ../client/pk-console.c:1696
+#: ../client/pk-console.c:1715
 msgid "Command failed"
 msgstr "Naredba nije uspela"
 
 #. TRANSLATORS: we can exclude certain packages (glibc) when we know they'll exist on the target
-#: ../client/pk-generate-pack.c:237
+#: ../client/pk-generate-pack.c:255
 msgid "Set the file name of dependencies to be excluded"
 msgstr "Postavite ime datoteke za međuzavisnosti koje će biti izostavljene"
 
 #. TRANSLATORS: the output location
-#: ../client/pk-generate-pack.c:240
+#: ../client/pk-generate-pack.c:258
 msgid ""
 "The output file or directory (the current directory is used if ommitted)"
 msgstr ""
@@ -536,43 +550,43 @@ msgstr ""
 "naveden)"
 
 #. TRANSLATORS: put a list of packages in the pack
-#: ../client/pk-generate-pack.c:243
+#: ../client/pk-generate-pack.c:261
 msgid "The package to be put into the service pack"
 msgstr "Paketi koji će biti stavljeni u servisni skup"
 
 #. TRANSLATORS: put all pending updates in the pack
-#: ../client/pk-generate-pack.c:246
+#: ../client/pk-generate-pack.c:264
 msgid "Put all updates available in the service pack"
 msgstr "Stavi sva ažuriranja u servisni skup"
 
 #. TRANSLATORS: This is when the user fails to supply the correct arguments
-#: ../client/pk-generate-pack.c:282
+#: ../client/pk-generate-pack.c:300
 msgid "Neither --package or --updates option selected."
 msgstr "Ni jedna od opcija --package ili --updates nije izabrana."
 
 #. TRANSLATORS: This is when the user fails to supply just one argument
-#: ../client/pk-generate-pack.c:290
+#: ../client/pk-generate-pack.c:308
 msgid "Both options selected."
 msgstr "Obe opcije izabrane."
 
 #. TRANSLATORS: This is when the user fails to supply the output
-#: ../client/pk-generate-pack.c:306
+#: ../client/pk-generate-pack.c:324
 msgid "A output directory or file name is required"
 msgstr "Morate navesti ime izlazne datoteke ili direktorijuma"
 
 #. TRANSLATORS: This is when the dameon is not-installed/broken and fails to startup
-#: ../client/pk-generate-pack.c:324
+#: ../client/pk-generate-pack.c:342
 msgid "The dameon failed to startup"
 msgstr "Demon nije uspeo da se pokrene"
 
 #. TRANSLATORS: This is when the backend doesn't have the capability to get-depends
 #. TRANSLATORS: This is when the backend doesn't have the capability to download
-#: ../client/pk-generate-pack.c:335 ../client/pk-generate-pack.c:341
+#: ../client/pk-generate-pack.c:353 ../client/pk-generate-pack.c:359
 msgid "The package manager cannot perform this type of operation."
 msgstr "Upravnik paketa ne može izvršiti ovu vrstu radnje."
 
 #. TRANSLATORS: This is when the distro didn't include libarchive support into PK
-#: ../client/pk-generate-pack.c:348
+#: ../client/pk-generate-pack.c:366
 msgid ""
 "Service packs cannot be created as PackageKit was not built with libarchive "
 "support."
@@ -581,64 +595,64 @@ msgstr ""
 "sa podrškom za libarchive."
 
 #. TRANSLATORS: the user specified an absolute path, but didn't get the extension correct
-#: ../client/pk-generate-pack.c:359
+#: ../client/pk-generate-pack.c:377
 msgid "If specifying a file, the service pack name must end with"
 msgstr "Ako navodite datoteku, naziv servisnog paketa se mora završiti sa"
 
 #. TRANSLATORS: This is when file already exists
-#: ../client/pk-generate-pack.c:375
+#: ../client/pk-generate-pack.c:393
 msgid "A pack with the same name already exists, do you want to overwrite it?"
 msgstr "Skup sa istim nazivom već postoji, da li ga želite presnimiti?"
 
 #. TRANSLATORS: This is when the pack was not overwritten
-#: ../client/pk-generate-pack.c:378
+#: ../client/pk-generate-pack.c:396
 msgid "The pack was not overwritten."
 msgstr "Skup nije presnimljen."
 
 #. TRANSLATORS: This is when the temporary directory cannot be created, the directory name follows
-#: ../client/pk-generate-pack.c:391
+#: ../client/pk-generate-pack.c:409
 msgid "Failed to create directory:"
 msgstr "Neuspelo pravljenje direktorijuma:"
 
 #. TRANSLATORS: This is when the list of packages from the remote computer cannot be opened
-#: ../client/pk-generate-pack.c:403
+#: ../client/pk-generate-pack.c:421
 msgid "Failed to open package list."
 msgstr "Neuspešno otvaranje spiska paketa."
 
 #. TRANSLATORS: The package name is being matched up to available packages
-#: ../client/pk-generate-pack.c:412
+#: ../client/pk-generate-pack.c:430
 msgid "Finding package name."
 msgstr "Pronalaženje imena paketa."
 
 #. TRANSLATORS: This is when the package cannot be found in any software source. The detailed error follows
-#: ../client/pk-generate-pack.c:416
+#: ../client/pk-generate-pack.c:434
 #, c-format
 msgid "Failed to find package '%s': %s"
 msgstr "Nisam mogao da pronađem paket „%s“: %s"
 
 #. TRANSLATORS: This is telling the user we are in the process of making the pack
-#: ../client/pk-generate-pack.c:424
+#: ../client/pk-generate-pack.c:442
 msgid "Creating service pack..."
 msgstr "Pravim servisnu grupu..."
 
 #. TRANSLATORS: we succeeded in making the file
-#: ../client/pk-generate-pack.c:439
+#: ../client/pk-generate-pack.c:457
 #, c-format
 msgid "Service pack created '%s'"
 msgstr "Servisna grupa je napravljena „%s“"
 
 #. TRANSLATORS: we failed to make te file
-#: ../client/pk-generate-pack.c:444
+#: ../client/pk-generate-pack.c:462
 #, c-format
 msgid "Failed to create '%s': %s"
 msgstr "Neuspelo pravljenje „%s“: %s"
 
-#: ../client/pk-monitor.c:210
+#: ../client/pk-monitor.c:236
 msgid "Failed to get daemon state"
 msgstr "Neuspeo pokušaj dobavljanja stanja demona"
 
 #. TRANSLATORS: this is a program that monitors PackageKit
-#: ../client/pk-monitor.c:296
+#: ../client/pk-monitor.c:322
 msgid "PackageKit Monitor"
 msgstr "PaketKit redar"
 
@@ -764,29 +778,29 @@ msgid "Please choose a command to run"
 msgstr "Izaberite naredbu za pokretanje"
 
 #. TRANSLATORS: tell the user what package provides the command
-#: ../contrib/command-not-found/pk-command-not-found.c:766
+#: ../contrib/command-not-found/pk-command-not-found.c:764
 msgid "The package providing this file is:"
 msgstr "Paket koji pruža ovu datoteku je:"
 
 #. TRANSLATORS: as the user if we want to install a package to provide the command
-#: ../contrib/command-not-found/pk-command-not-found.c:771
+#: ../contrib/command-not-found/pk-command-not-found.c:769
 #, c-format
 msgid "Install package '%s' to provide command '%s'?"
 msgstr "Da instaliram paket „%s“ koji pruža naredbu „%s“?"
 
 #. TRANSLATORS: Show the user a list of packages that provide this command
-#: ../contrib/command-not-found/pk-command-not-found.c:795
+#: ../contrib/command-not-found/pk-command-not-found.c:793
 msgid "Packages providing this file are:"
 msgstr "Paketi koji pružaju ovu datoteku su:"
 
 #. TRANSLATORS: Show the user a list of packages that they can install to provide this command
-#: ../contrib/command-not-found/pk-command-not-found.c:805
+#: ../contrib/command-not-found/pk-command-not-found.c:803
 msgid "Suitable packages are:"
 msgstr "Prikladni paketi su:"
 
 #. get selection
 #. TRANSLATORS: ask the user to choose a file to install
-#: ../contrib/command-not-found/pk-command-not-found.c:814
+#: ../contrib/command-not-found/pk-command-not-found.c:812
 msgid "Please choose a package to install"
 msgstr "Izaberite paket za instalaciju"
 
@@ -956,7 +970,7 @@ msgstr "Ne instaliram pakete u režimu simulacije"
 #. TRANSLATORS: we are now installing the debuginfo packages we found earlier
 #. TRANSLATORS: transaction state, installing packages
 #: ../contrib/debuginfo-install/pk-debuginfo-install.c:862
-#: ../lib/packagekit-glib2/pk-console-shared.c:282
+#: ../lib/packagekit-glib2/pk-console-shared.c:283
 #, c-format
 msgid "Installing packages"
 msgstr "Instaliram pakete"
@@ -986,92 +1000,92 @@ msgid "Disabled %i debugging sources."
 msgstr "Isključeno je %i izvora za otklon grešaka."
 
 #. TRANSLATORS: couldn't open device to write
-#: ../contrib/device-rebind/pk-device-rebind.c:61
+#: ../contrib/device-rebind/pk-device-rebind.c:62
 msgid "Failed to open file"
 msgstr "Neuspelo otvaranje datoteke"
 
 #. TRANSLATORS: could not write to the device
-#: ../contrib/device-rebind/pk-device-rebind.c:70
+#: ../contrib/device-rebind/pk-device-rebind.c:71
 msgid "Failed to write to the file"
 msgstr "Neuspešno zapisivanje u datoteku"
 
 #. TRANSLATORS: we failed to release the current driver
-#: ../contrib/device-rebind/pk-device-rebind.c:110
-#: ../contrib/device-rebind/pk-device-rebind.c:147
+#: ../contrib/device-rebind/pk-device-rebind.c:111
+#: ../contrib/device-rebind/pk-device-rebind.c:148
 msgid "Failed to write to device"
 msgstr "Neuspešno zapisivanje na uređaj"
 
 #. TRANSLATORS: the device could not be found in sysfs
-#: ../contrib/device-rebind/pk-device-rebind.c:175
+#: ../contrib/device-rebind/pk-device-rebind.c:176
 msgid "Device could not be found"
 msgstr "Uređaj nije mogao biti pronađen"
 
 #. TRANSLATORS: we failed to release the current driver
-#: ../contrib/device-rebind/pk-device-rebind.c:202
+#: ../contrib/device-rebind/pk-device-rebind.c:203
 msgid "Failed to unregister driver"
 msgstr "Neuspela deregistracija upravljačkog programa"
 
 #. TRANSLATORS: we failed to bind the old driver
-#: ../contrib/device-rebind/pk-device-rebind.c:211
+#: ../contrib/device-rebind/pk-device-rebind.c:212
 msgid "Failed to register driver"
 msgstr "Neuspela registracija upravljačkog programa"
 
 #. TRANSLATORS: user did not specify a device sysfs path that exists
-#: ../contrib/device-rebind/pk-device-rebind.c:260
+#: ../contrib/device-rebind/pk-device-rebind.c:261
 msgid "Device path not found"
 msgstr "Putanja uređaja nije nađena"
 
 #. TRANSLATORS: user did not specify a valid device sysfs path
-#: ../contrib/device-rebind/pk-device-rebind.c:268
+#: ../contrib/device-rebind/pk-device-rebind.c:269
 msgid "Incorrect device path specified"
 msgstr "Navedena je neispravna putanja uređaja"
 
-#: ../contrib/device-rebind/pk-device-rebind.c:293
+#: ../contrib/device-rebind/pk-device-rebind.c:294
 msgid "Show extra debugging information"
 msgstr "Prikaži dodatne podatke za otklon grešaka"
 
 #. command line argument, simulate what would be done, but don't actually do it
-#: ../contrib/device-rebind/pk-device-rebind.c:296
+#: ../contrib/device-rebind/pk-device-rebind.c:297
 msgid "Don't actually touch the hardware, only simulate what would be done"
 msgstr "Nemoj u stvari da diraš hardver, samo simuliraj šta bi se uradilo"
 
 #. TRANSLATORS: command line option: a list of files to install
-#: ../contrib/device-rebind/pk-device-rebind.c:299
+#: ../contrib/device-rebind/pk-device-rebind.c:300
 msgid "Device paths"
 msgstr "Putanje uređaja"
 
 #. TRANSLATORS: tool that gets called when the device needs reloading after installing firmware
-#: ../contrib/device-rebind/pk-device-rebind.c:314
+#: ../contrib/device-rebind/pk-device-rebind.c:315
 msgid "PackageKit Device Reloader"
 msgstr "PaketKit program za ponovno učitavanje uređaja"
 
 #. TRANSLATORS: user did not specify a valid device sysfs path
-#: ../contrib/device-rebind/pk-device-rebind.c:322
+#: ../contrib/device-rebind/pk-device-rebind.c:323
 msgid "You need to specify at least one valid device path"
 msgstr "Morate navesti barem jednu ispravnu putanju uređaja"
 
 #. TRANSLATORS: user did not specify a valid device sysfs path
-#: ../contrib/device-rebind/pk-device-rebind.c:332
+#: ../contrib/device-rebind/pk-device-rebind.c:333
 msgid "This script can only be used by the root user"
 msgstr "Ovu skriptu može koristiti samo „root“ korisnik"
 
 #. TRANSLATORS: we're going to verify the path first
-#: ../contrib/device-rebind/pk-device-rebind.c:341
+#: ../contrib/device-rebind/pk-device-rebind.c:342
 msgid "Verifying device path"
 msgstr "Proveravam putanju uređaja"
 
 #. TRANSLATORS: user did not specify a device sysfs path that exists
-#: ../contrib/device-rebind/pk-device-rebind.c:346
+#: ../contrib/device-rebind/pk-device-rebind.c:347
 msgid "Failed to verify device path"
 msgstr "Neuspela provera putanje uređaja"
 
 #. TRANSLATORS: we're going to try
-#: ../contrib/device-rebind/pk-device-rebind.c:360
+#: ../contrib/device-rebind/pk-device-rebind.c:361
 msgid "Attempting to rebind device"
 msgstr "Pokušavam da ponovo vežem uređaj"
 
 #. TRANSLATORS: we failed to release the current driver
-#: ../contrib/device-rebind/pk-device-rebind.c:365
+#: ../contrib/device-rebind/pk-device-rebind.c:366
 msgid "Failed to rebind device"
 msgstr "Neuspelo ponovno vezivanje uređaja"
 
@@ -1093,7 +1107,7 @@ msgid "Please enter a number from 1 to %i: "
 msgstr "Unesite broj između 1 i %i: "
 
 #. TRANSLATORS: more than one package could be found that matched, to follow is a list of possible packages
-#: ../lib/packagekit-glib2/pk-console-shared.c:183
+#: ../lib/packagekit-glib2/pk-console-shared.c:185
 msgid "More than one package matches:"
 msgstr "Postoji više paketa koji odgovaraju upitu:"
 
@@ -1103,448 +1117,448 @@ msgid "Please choose the correct package: "
 msgstr "Izaberite željeni paket: "
 
 #. TRANSLATORS: This is when the transaction status is not known
-#: ../lib/packagekit-glib2/pk-console-shared.c:250
+#: ../lib/packagekit-glib2/pk-console-shared.c:251
 msgid "Unknown state"
 msgstr "Nepoznato stanje"
 
 #. TRANSLATORS: transaction state, the daemon is in the process of starting
-#: ../lib/packagekit-glib2/pk-console-shared.c:254
+#: ../lib/packagekit-glib2/pk-console-shared.c:255
 msgid "Starting"
 msgstr "Pokretanje"
 
 #. TRANSLATORS: transaction state, the transaction is waiting for another to complete
-#: ../lib/packagekit-glib2/pk-console-shared.c:258
+#: ../lib/packagekit-glib2/pk-console-shared.c:259
 msgid "Waiting in queue"
 msgstr "ÄŒekanje u redu"
 
 #. TRANSLATORS: transaction state, just started
-#: ../lib/packagekit-glib2/pk-console-shared.c:262
+#: ../lib/packagekit-glib2/pk-console-shared.c:263
 msgid "Running"
 msgstr "Izvršavanje"
 
 #. TRANSLATORS: transaction state, is querying data
-#: ../lib/packagekit-glib2/pk-console-shared.c:266
+#: ../lib/packagekit-glib2/pk-console-shared.c:267
 msgid "Querying"
 msgstr "Ispitivanje"
 
 #. TRANSLATORS: transaction state, getting data from a server
-#: ../lib/packagekit-glib2/pk-console-shared.c:270
+#: ../lib/packagekit-glib2/pk-console-shared.c:271
 msgid "Getting information"
 msgstr "Dobavljanje podataka"
 
 #. TRANSLATORS: transaction state, removing packages
-#: ../lib/packagekit-glib2/pk-console-shared.c:274
+#: ../lib/packagekit-glib2/pk-console-shared.c:275
 msgid "Removing packages"
 msgstr "Uklanjanje paketa"
 
 #. TRANSLATORS: transaction state, downloading package files
 #. TRANSLATORS: The role of the transaction, in present tense
-#: ../lib/packagekit-glib2/pk-console-shared.c:278
-#: ../lib/packagekit-glib2/pk-console-shared.c:656
+#: ../lib/packagekit-glib2/pk-console-shared.c:279
+#: ../lib/packagekit-glib2/pk-console-shared.c:657
 msgid "Downloading packages"
 msgstr "Preuzimanje paketa"
 
 #. TRANSLATORS: transaction state, refreshing internal lists
-#: ../lib/packagekit-glib2/pk-console-shared.c:286
+#: ../lib/packagekit-glib2/pk-console-shared.c:287
 msgid "Refreshing software list"
 msgstr "Osvežavanje spiska softvera"
 
 #. TRANSLATORS: transaction state, installing updates
-#: ../lib/packagekit-glib2/pk-console-shared.c:290
+#: ../lib/packagekit-glib2/pk-console-shared.c:291
 msgid "Installing updates"
 msgstr "Instaliranje ažuriranja"
 
 #. TRANSLATORS: transaction state, removing old packages, and cleaning config files
-#: ../lib/packagekit-glib2/pk-console-shared.c:294
+#: ../lib/packagekit-glib2/pk-console-shared.c:295
 msgid "Cleaning up packages"
 msgstr "Čišćenje paketa"
 
 #. TRANSLATORS: transaction state, obsoleting old packages
-#: ../lib/packagekit-glib2/pk-console-shared.c:298
+#: ../lib/packagekit-glib2/pk-console-shared.c:299
 msgid "Obsoleting packages"
 msgstr "Prevazilazim pakete"
 
 #. TRANSLATORS: transaction state, checking the transaction before we do it
-#: ../lib/packagekit-glib2/pk-console-shared.c:302
+#: ../lib/packagekit-glib2/pk-console-shared.c:303
 msgid "Resolving dependencies"
 msgstr "Razrešavanje zavisnosti"
 
 #. TRANSLATORS: transaction state, checking if we have all the security keys for the operation
-#: ../lib/packagekit-glib2/pk-console-shared.c:306
+#: ../lib/packagekit-glib2/pk-console-shared.c:307
 msgid "Checking signatures"
 msgstr "Provera potpisa"
 
 #. TRANSLATORS: transaction state, when we return to a previous system state
 #. TRANSLATORS: The role of the transaction, in present tense
-#: ../lib/packagekit-glib2/pk-console-shared.c:310
-#: ../lib/packagekit-glib2/pk-console-shared.c:616
+#: ../lib/packagekit-glib2/pk-console-shared.c:311
+#: ../lib/packagekit-glib2/pk-console-shared.c:617
 msgid "Rolling back"
 msgstr "Vraćanje unazad"
 
 #. TRANSLATORS: transaction state, when we're doing a test transaction
-#: ../lib/packagekit-glib2/pk-console-shared.c:314
+#: ../lib/packagekit-glib2/pk-console-shared.c:315
 msgid "Testing changes"
 msgstr "Isprobavanje promena"
 
 #. TRANSLATORS: transaction state, when we're writing to the system package database
-#: ../lib/packagekit-glib2/pk-console-shared.c:318
+#: ../lib/packagekit-glib2/pk-console-shared.c:319
 msgid "Committing changes"
 msgstr "Å aljem promene"
 
 #. TRANSLATORS: transaction state, requesting data from a server
-#: ../lib/packagekit-glib2/pk-console-shared.c:322
+#: ../lib/packagekit-glib2/pk-console-shared.c:323
 msgid "Requesting data"
 msgstr "Zahtevam podatke"
 
 #. TRANSLATORS: transaction state, all done!
-#: ../lib/packagekit-glib2/pk-console-shared.c:326
+#: ../lib/packagekit-glib2/pk-console-shared.c:327
 msgid "Finished"
 msgstr "Završeno"
 
 #. TRANSLATORS: transaction state, in the process of cancelling
-#: ../lib/packagekit-glib2/pk-console-shared.c:330
+#: ../lib/packagekit-glib2/pk-console-shared.c:331
 msgid "Cancelling"
 msgstr "Otkazivanje"
 
 #. TRANSLATORS: transaction state, downloading metadata
-#: ../lib/packagekit-glib2/pk-console-shared.c:334
+#: ../lib/packagekit-glib2/pk-console-shared.c:335
 msgid "Downloading repository information"
 msgstr "Preuzimam podatke o riznici"
 
 #. TRANSLATORS: transaction state, downloading metadata
-#: ../lib/packagekit-glib2/pk-console-shared.c:338
+#: ../lib/packagekit-glib2/pk-console-shared.c:339
 msgid "Downloading list of packages"
 msgstr "Preuzimanje spiska paketa"
 
 #. TRANSLATORS: transaction state, downloading metadata
-#: ../lib/packagekit-glib2/pk-console-shared.c:342
+#: ../lib/packagekit-glib2/pk-console-shared.c:343
 msgid "Downloading file lists"
 msgstr "Preuzimanje spiskova datoteka"
 
 #. TRANSLATORS: transaction state, downloading metadata
-#: ../lib/packagekit-glib2/pk-console-shared.c:346
+#: ../lib/packagekit-glib2/pk-console-shared.c:347
 msgid "Downloading lists of changes"
 msgstr "Preuzimanje spiskova promena"
 
 #. TRANSLATORS: transaction state, downloading metadata
-#: ../lib/packagekit-glib2/pk-console-shared.c:350
+#: ../lib/packagekit-glib2/pk-console-shared.c:351
 msgid "Downloading groups"
 msgstr "Preuzimanje grupa"
 
 #. TRANSLATORS: transaction state, downloading metadata
-#: ../lib/packagekit-glib2/pk-console-shared.c:354
+#: ../lib/packagekit-glib2/pk-console-shared.c:355
 msgid "Downloading update information"
 msgstr "Preuzimanje podataka o ažuriranju"
 
 #. TRANSLATORS: transaction state, repackaging delta files
-#: ../lib/packagekit-glib2/pk-console-shared.c:358
+#: ../lib/packagekit-glib2/pk-console-shared.c:359
 msgid "Repackaging files"
 msgstr "Prepakivanje datoteka"
 
 #. TRANSLATORS: transaction state, loading databases
-#: ../lib/packagekit-glib2/pk-console-shared.c:362
+#: ../lib/packagekit-glib2/pk-console-shared.c:363
 msgid "Loading cache"
 msgstr "Učitavanje keša"
 
 #. TRANSLATORS: transaction state, scanning for running processes
-#: ../lib/packagekit-glib2/pk-console-shared.c:366
+#: ../lib/packagekit-glib2/pk-console-shared.c:367
 msgid "Scanning applications"
 msgstr "Pretražujem programe"
 
 #. TRANSLATORS: transaction state, generating a list of packages installed on the system
-#: ../lib/packagekit-glib2/pk-console-shared.c:370
+#: ../lib/packagekit-glib2/pk-console-shared.c:371
 msgid "Generating package lists"
 msgstr "Pravljenje spiskova paketa"
 
 #. TRANSLATORS: transaction state, when we're waiting for the native tools to exit
-#: ../lib/packagekit-glib2/pk-console-shared.c:374
+#: ../lib/packagekit-glib2/pk-console-shared.c:375
 msgid "Waiting for package manager lock"
 msgstr "Čekanje na zaključavanje upravnika paketa"
 
 #. TRANSLATORS: transaction state, waiting for user to type in a password
-#: ../lib/packagekit-glib2/pk-console-shared.c:378
+#: ../lib/packagekit-glib2/pk-console-shared.c:379
 msgid "Waiting for authentication"
 msgstr "ÄŒekanje na autentifikaciju"
 
 #. TRANSLATORS: transaction state, we are updating the list of processes
-#: ../lib/packagekit-glib2/pk-console-shared.c:382
+#: ../lib/packagekit-glib2/pk-console-shared.c:383
 msgid "Updating running applications"
 msgstr "Ažuriram pokrenute programe"
 
 #. TRANSLATORS: transaction state, we are checking executable files currently in use
-#: ../lib/packagekit-glib2/pk-console-shared.c:386
+#: ../lib/packagekit-glib2/pk-console-shared.c:387
 msgid "Checking applications in use"
 msgstr "Proveravam programe u upotrebi"
 
 #. TRANSLATORS: transaction state, we are checking for libraries currently in use
-#: ../lib/packagekit-glib2/pk-console-shared.c:390
+#: ../lib/packagekit-glib2/pk-console-shared.c:391
 msgid "Checking libraries in use"
 msgstr "Proveravam biblioteke u upotrebi"
 
 #. TRANSLATORS: transaction state, we are copying package files before or after the transaction
-#: ../lib/packagekit-glib2/pk-console-shared.c:394
+#: ../lib/packagekit-glib2/pk-console-shared.c:395
 msgid "Copying files"
 msgstr "Umnožavanje datoteka"
 
 #. TRANSLATORS: The type of update
-#: ../lib/packagekit-glib2/pk-console-shared.c:412
+#: ../lib/packagekit-glib2/pk-console-shared.c:413
 msgid "Trivial"
 msgstr "Trivijalno"
 
 #. TRANSLATORS: The type of update
-#: ../lib/packagekit-glib2/pk-console-shared.c:416
+#: ../lib/packagekit-glib2/pk-console-shared.c:417
 msgid "Normal"
 msgstr "Obično"
 
 #. TRANSLATORS: The type of update
-#: ../lib/packagekit-glib2/pk-console-shared.c:420
+#: ../lib/packagekit-glib2/pk-console-shared.c:421
 msgid "Important"
 msgstr "Važno"
 
 #. TRANSLATORS: The type of update
-#: ../lib/packagekit-glib2/pk-console-shared.c:424
+#: ../lib/packagekit-glib2/pk-console-shared.c:425
 msgid "Security"
 msgstr "Bezbednosno"
 
 #. TRANSLATORS: The type of update
-#: ../lib/packagekit-glib2/pk-console-shared.c:428
+#: ../lib/packagekit-glib2/pk-console-shared.c:429
 msgid "Bug fix "
 msgstr "Ispravka greške"
 
 #. TRANSLATORS: The type of update
-#: ../lib/packagekit-glib2/pk-console-shared.c:432
+#: ../lib/packagekit-glib2/pk-console-shared.c:433
 msgid "Enhancement"
 msgstr "Poboljšanje"
 
 #. TRANSLATORS: The type of update
-#: ../lib/packagekit-glib2/pk-console-shared.c:436
+#: ../lib/packagekit-glib2/pk-console-shared.c:437
 msgid "Blocked"
 msgstr "Blokirano"
 
 #. TRANSLATORS: The state of a package
 #. TRANSLATORS: The action of the package, in past tense
-#: ../lib/packagekit-glib2/pk-console-shared.c:441
-#: ../lib/packagekit-glib2/pk-console-shared.c:514
+#: ../lib/packagekit-glib2/pk-console-shared.c:442
+#: ../lib/packagekit-glib2/pk-console-shared.c:515
 msgid "Installed"
 msgstr "Instaliran"
 
 #. TRANSLATORS: The state of a package, i.e. not installed
-#: ../lib/packagekit-glib2/pk-console-shared.c:446
+#: ../lib/packagekit-glib2/pk-console-shared.c:447
 msgid "Available"
 msgstr "Dostupan"
 
 #. TRANSLATORS: The action of the package, in present tense
-#: ../lib/packagekit-glib2/pk-console-shared.c:464
+#: ../lib/packagekit-glib2/pk-console-shared.c:465
 msgid "Downloading"
 msgstr "Preuzimanje"
 
 #. TRANSLATORS: The action of the package, in present tense
-#: ../lib/packagekit-glib2/pk-console-shared.c:468
+#: ../lib/packagekit-glib2/pk-console-shared.c:469
 msgid "Updating"
 msgstr "Ažuriranje"
 
 #. TRANSLATORS: The action of the package, in present tense
 #. TRANSLATORS: The role of the transaction, in present tense
-#: ../lib/packagekit-glib2/pk-console-shared.c:472
-#: ../lib/packagekit-glib2/pk-console-shared.c:592
+#: ../lib/packagekit-glib2/pk-console-shared.c:473
+#: ../lib/packagekit-glib2/pk-console-shared.c:593
 msgid "Installing"
 msgstr "Instalacija"
 
 #. TRANSLATORS: The action of the package, in present tense
 #. TRANSLATORS: The role of the transaction, in present tense
-#: ../lib/packagekit-glib2/pk-console-shared.c:476
-#: ../lib/packagekit-glib2/pk-console-shared.c:588
+#: ../lib/packagekit-glib2/pk-console-shared.c:477
+#: ../lib/packagekit-glib2/pk-console-shared.c:589
 msgid "Removing"
 msgstr "Uklanjanje"
 
 #. TRANSLATORS: The action of the package, in present tense
-#: ../lib/packagekit-glib2/pk-console-shared.c:480
+#: ../lib/packagekit-glib2/pk-console-shared.c:481
 msgid "Cleaning up"
 msgstr "Čišćenje"
 
 #. TRANSLATORS: The action of the package, in present tense
-#: ../lib/packagekit-glib2/pk-console-shared.c:484
+#: ../lib/packagekit-glib2/pk-console-shared.c:485
 msgid "Obsoleting"
 msgstr "Prevazilaženje"
 
 #. TRANSLATORS: The action of the package, in present tense
-#: ../lib/packagekit-glib2/pk-console-shared.c:488
+#: ../lib/packagekit-glib2/pk-console-shared.c:489
 msgid "Reinstalling"
 msgstr "Ponovna instalacija"
 
 #. TRANSLATORS: The action of the package, in past tense
-#: ../lib/packagekit-glib2/pk-console-shared.c:506
+#: ../lib/packagekit-glib2/pk-console-shared.c:507
 msgid "Downloaded"
 msgstr "Preuzet"
 
 #. TRANSLATORS: The action of the package, in past tense
-#: ../lib/packagekit-glib2/pk-console-shared.c:518
+#: ../lib/packagekit-glib2/pk-console-shared.c:519
 msgid "Removed"
 msgstr "Uklonjen"
 
 #. TRANSLATORS: The action of the package, in past tense
-#: ../lib/packagekit-glib2/pk-console-shared.c:522
+#: ../lib/packagekit-glib2/pk-console-shared.c:523
 msgid "Cleaned up"
 msgstr "Očišćen"
 
 #. TRANSLATORS: The action of the package, in past tense
-#: ../lib/packagekit-glib2/pk-console-shared.c:526
+#: ../lib/packagekit-glib2/pk-console-shared.c:527
 msgid "Obsoleted"
 msgstr "Prevaziđen"
 
 #. TRANSLATORS: The action of the package, in past tense
-#: ../lib/packagekit-glib2/pk-console-shared.c:530
+#: ../lib/packagekit-glib2/pk-console-shared.c:531
 msgid "Reinstalled"
 msgstr "Ponovo instaliran"
 
 #. TRANSLATORS: The role of the transaction, in present tense
-#: ../lib/packagekit-glib2/pk-console-shared.c:548
+#: ../lib/packagekit-glib2/pk-console-shared.c:549
 msgid "Unknown role type"
 msgstr "Nepoznata vrsta radnje"
 
 #. TRANSLATORS: The role of the transaction, in present tense
-#: ../lib/packagekit-glib2/pk-console-shared.c:552
+#: ../lib/packagekit-glib2/pk-console-shared.c:553
 msgid "Getting dependencies"
 msgstr "Dobavljanje zavisnosti"
 
 #. TRANSLATORS: The role of the transaction, in present tense
-#: ../lib/packagekit-glib2/pk-console-shared.c:556
+#: ../lib/packagekit-glib2/pk-console-shared.c:557
 msgid "Getting update details"
 msgstr "Dobavljanje detalja o ažuriranju"
 
 #. TRANSLATORS: The role of the transaction, in present tense
-#: ../lib/packagekit-glib2/pk-console-shared.c:560
+#: ../lib/packagekit-glib2/pk-console-shared.c:561
 msgid "Getting details"
 msgstr "Dobavljanje detalja"
 
 #. TRANSLATORS: The role of the transaction, in present tense
-#: ../lib/packagekit-glib2/pk-console-shared.c:564
+#: ../lib/packagekit-glib2/pk-console-shared.c:565
 msgid "Getting requires"
 msgstr "Dobavljam zahtevanja"
 
 #. TRANSLATORS: The role of the transaction, in present tense
-#: ../lib/packagekit-glib2/pk-console-shared.c:568
+#: ../lib/packagekit-glib2/pk-console-shared.c:569
 msgid "Getting updates"
 msgstr "Dobavljam ažuriranja"
 
 #. TRANSLATORS: The role of the transaction, in present tense
-#: ../lib/packagekit-glib2/pk-console-shared.c:572
+#: ../lib/packagekit-glib2/pk-console-shared.c:573
 msgid "Searching by details"
 msgstr "Pretražujem po detaljima"
 
 #. TRANSLATORS: The role of the transaction, in present tense
-#: ../lib/packagekit-glib2/pk-console-shared.c:576
+#: ../lib/packagekit-glib2/pk-console-shared.c:577
 msgid "Searching by file"
 msgstr "Pretražujem po datotekama"
 
 #. TRANSLATORS: The role of the transaction, in present tense
-#: ../lib/packagekit-glib2/pk-console-shared.c:580
+#: ../lib/packagekit-glib2/pk-console-shared.c:581
 msgid "Searching groups"
 msgstr "Pretražujem po grupama"
 
 #. TRANSLATORS: The role of the transaction, in present tense
-#: ../lib/packagekit-glib2/pk-console-shared.c:584
+#: ../lib/packagekit-glib2/pk-console-shared.c:585
 msgid "Searching by name"
 msgstr "Pretražujem po imenu"
 
 #. TRANSLATORS: The role of the transaction, in present tense
-#: ../lib/packagekit-glib2/pk-console-shared.c:596
+#: ../lib/packagekit-glib2/pk-console-shared.c:597
 msgid "Installing files"
 msgstr "Instaliram datoteke"
 
 #. TRANSLATORS: The role of the transaction, in present tense
-#: ../lib/packagekit-glib2/pk-console-shared.c:600
+#: ../lib/packagekit-glib2/pk-console-shared.c:601
 msgid "Refreshing cache"
 msgstr "Osvežavam keš"
 
 #. TRANSLATORS: The role of the transaction, in present tense
-#: ../lib/packagekit-glib2/pk-console-shared.c:604
+#: ../lib/packagekit-glib2/pk-console-shared.c:605
 msgid "Updating packages"
 msgstr "Ažuriranje paketa"
 
 #. TRANSLATORS: The role of the transaction, in present tense
-#: ../lib/packagekit-glib2/pk-console-shared.c:608
+#: ../lib/packagekit-glib2/pk-console-shared.c:609
 msgid "Updating system"
 msgstr "Ažuriranje sistema"
 
 #. TRANSLATORS: The role of the transaction, in present tense
-#: ../lib/packagekit-glib2/pk-console-shared.c:612
+#: ../lib/packagekit-glib2/pk-console-shared.c:613
 msgid "Canceling"
 msgstr "Otkazivanje"
 
 #. TRANSLATORS: The role of the transaction, in present tense
-#: ../lib/packagekit-glib2/pk-console-shared.c:620
+#: ../lib/packagekit-glib2/pk-console-shared.c:621
 msgid "Getting repositories"
 msgstr "Dobavljanje riznica"
 
 #. TRANSLATORS: The role of the transaction, in present tense
-#: ../lib/packagekit-glib2/pk-console-shared.c:624
+#: ../lib/packagekit-glib2/pk-console-shared.c:625
 msgid "Enabling repository"
 msgstr "Uključivanje riznice"
 
 #. TRANSLATORS: The role of the transaction, in present tense
-#: ../lib/packagekit-glib2/pk-console-shared.c:628
+#: ../lib/packagekit-glib2/pk-console-shared.c:629
 msgid "Setting data"
 msgstr "Postavljanje podataka"
 
 #. TRANSLATORS: The role of the transaction, in present tense
-#: ../lib/packagekit-glib2/pk-console-shared.c:632
+#: ../lib/packagekit-glib2/pk-console-shared.c:633
 msgid "Resolving"
 msgstr "Razrešavanje"
 
 #. TRANSLATORS: The role of the transaction, in present tense
-#: ../lib/packagekit-glib2/pk-console-shared.c:636
+#: ../lib/packagekit-glib2/pk-console-shared.c:637
 msgid "Getting file list"
 msgstr "Dobavljanje spiska datoteka"
 
 #. TRANSLATORS: The role of the transaction, in present tense
-#: ../lib/packagekit-glib2/pk-console-shared.c:640
+#: ../lib/packagekit-glib2/pk-console-shared.c:641
 msgid "Getting provides"
 msgstr "Dobavljanje pružanja"
 
 #. TRANSLATORS: The role of the transaction, in present tense
-#: ../lib/packagekit-glib2/pk-console-shared.c:644
+#: ../lib/packagekit-glib2/pk-console-shared.c:645
 msgid "Installing signature"
 msgstr "Instaliranje potpisa"
 
 #. TRANSLATORS: The role of the transaction, in present tense
-#: ../lib/packagekit-glib2/pk-console-shared.c:648
+#: ../lib/packagekit-glib2/pk-console-shared.c:649
 msgid "Getting packages"
 msgstr "Dobavljanje paketa"
 
 #. TRANSLATORS: The role of the transaction, in present tense
-#: ../lib/packagekit-glib2/pk-console-shared.c:652
+#: ../lib/packagekit-glib2/pk-console-shared.c:653
 msgid "Accepting EULA"
 msgstr "Prihvatanje licence"
 
 #. TRANSLATORS: The role of the transaction, in present tense
-#: ../lib/packagekit-glib2/pk-console-shared.c:660
+#: ../lib/packagekit-glib2/pk-console-shared.c:661
 msgid "Getting upgrades"
 msgstr "Dobavljanje nadgradnji"
 
 #. TRANSLATORS: The role of the transaction, in present tense
-#: ../lib/packagekit-glib2/pk-console-shared.c:664
+#: ../lib/packagekit-glib2/pk-console-shared.c:665
 msgid "Getting categories"
 msgstr "Dobavljanje kategorija"
 
 #. TRANSLATORS: The role of the transaction, in present tense
-#: ../lib/packagekit-glib2/pk-console-shared.c:668
+#: ../lib/packagekit-glib2/pk-console-shared.c:669
 msgid "Getting transactions"
 msgstr "Dobavljanje transakcija"
 
 #. TRANSLATORS: The role of the transaction, in present tense
-#: ../lib/packagekit-glib2/pk-console-shared.c:672
-#: ../lib/packagekit-glib2/pk-console-shared.c:676
+#: ../lib/packagekit-glib2/pk-console-shared.c:673
+#: ../lib/packagekit-glib2/pk-console-shared.c:677
 msgid "Simulating install"
 msgstr "Simuliranje instalacije"
 
 #. TRANSLATORS: The role of the transaction, in present tense
-#: ../lib/packagekit-glib2/pk-console-shared.c:680
+#: ../lib/packagekit-glib2/pk-console-shared.c:681
 msgid "Simulating remove"
 msgstr "Simuliranje uklanjanja"
 
 #. TRANSLATORS: The role of the transaction, in present tense
-#: ../lib/packagekit-glib2/pk-console-shared.c:684
+#: ../lib/packagekit-glib2/pk-console-shared.c:685
 msgid "Simulating update"
 msgstr "Simuliranje ažuriranja"
 
@@ -1964,19 +1978,13 @@ msgid "Do not install these packages unless you are sure it is safe to do so."
 msgstr ""
 "Nemojte instalirati ove pakete osim ako niste sigurni da je to bezbedno."
 
-#. TRANSLATORS: warn the user that all bets are off
-#: ../src/pk-polkit-action-lookup.c:202
-msgid "Malicious software can damage your computer or cause other harm."
-msgstr ""
-"Zlonameran softver može pokvariti vaš računar ili izazvati drugu štetu."
-
 #. TRANSLATORS: too many packages to list each one
-#: ../src/pk-polkit-action-lookup.c:277
+#: ../src/pk-polkit-action-lookup.c:273
 msgid "Many packages"
 msgstr "Mnogo paketa"
 
 #. TRANSLATORS: if the transaction is forced to install only trusted packages
-#: ../src/pk-polkit-action-lookup.c:343
+#: ../src/pk-polkit-action-lookup.c:339
 msgid "Only trusted"
 msgstr "Samo poverljive"
 
@@ -2008,6 +2016,10 @@ msgstr "Opcije za otklon grešaka"
 msgid "Show debugging options"
 msgstr "Prikaži opcije za otklon grešaka"
 
+#~ msgid "Malicious software can damage your computer or cause other harm."
+#~ msgstr ""
+#~ "Zlonameran softver može pokvariti vaš računar ili izazvati drugu štetu."
+
 #~ msgid "Please restart the application as it is being used."
 #~ msgstr "Neophodno je ponovno pokretanje programa pošto je u upotrebi."
 
commit 08300f1a4c84ca0950e2fe5f4e3b6e94c2717db8
Author: kmilos <kmilos at fedoraproject.org>
Date:   Tue Mar 16 20:44:07 2010 +0000

    l10n: Updates to Serbian (sr) translation
    
    Transmitted-via: Transifex (translate.fedoraproject.org)

diff --git a/po/sr.po b/po/sr.po
index a242215..bc292ac 100644
--- a/po/sr.po
+++ b/po/sr.po
@@ -11,15 +11,15 @@ msgid ""
 msgstr ""
 "Project-Id-Version: PackageKit\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2009-12-06 20:02+0000\n"
-"PO-Revision-Date: 2009-11-28 20:48-0000\n"
+"POT-Creation-Date: 2010-03-16 19:09+0000\n"
+"PO-Revision-Date: 2010-03-16 20:40+0100\n"
 "Last-Translator: Miloš Komarčević <kmilos at gmail.com>\n"
-"Language-Team: Serbian <fedora-trans-sr at redhat.com>\n"
+"Language-Team: Serbian <trans-sr at lists.fedoraproject.org>\n"
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%"
-"10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n"
+"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%"
+"10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n"
 
 #. TRANSLATORS: this is an atomic transaction
 #. TRANSLATORS: the role is the point of the transaction, e.g. update-system
@@ -47,7 +47,7 @@ msgstr "Нетачно"
 
 #. TRANSLATORS: this is the transactions role, e.g. "update-system"
 #. TRANSLATORS: the trasaction role, e.g. update-system
-#: ../client/pk-console.c:181 ../src/pk-polkit-action-lookup.c:336
+#: ../client/pk-console.c:181 ../src/pk-polkit-action-lookup.c:332
 msgid "Role"
 msgstr "Радња"
 
@@ -62,7 +62,7 @@ msgstr "(секунди)"
 
 #. TRANSLATORS: this is The command line used to do the action
 #. TRANSLATORS: the command line of the thing that wants the authentication
-#: ../client/pk-console.c:190 ../src/pk-polkit-action-lookup.c:350
+#: ../client/pk-console.c:190 ../src/pk-polkit-action-lookup.c:346
 msgid "Command line"
 msgstr "Командна линија"
 
@@ -143,7 +143,7 @@ msgstr "Више о надградњи:"
 #: ../client/pk-console.c:346 ../client/pk-console.c:616
 #: ../lib/packagekit-glib2/pk-task-text.c:126
 #: ../lib/packagekit-glib2/pk-task-text.c:208
-#: ../src/pk-polkit-action-lookup.c:361
+#: ../src/pk-polkit-action-lookup.c:357
 msgid "Package"
 msgid_plural "Packages"
 msgstr[0] "Пакет"
@@ -203,7 +203,7 @@ msgstr "Издато"
 
 #. TRANSLATORS: details about the update, date the update was updated
 #. TRANSLATORS: The action of the package, in past tense
-#: ../client/pk-console.c:389 ../lib/packagekit-glib2/pk-console-shared.c:510
+#: ../client/pk-console.c:389 ../lib/packagekit-glib2/pk-console-shared.c:511
 msgid "Updated"
 msgstr "Датум ажурирања"
 
@@ -273,39 +273,43 @@ msgid "Status"
 msgstr "Статус"
 
 #. TRANSLATORS: the results from the transaction
-#: ../client/pk-console.c:678
+#: ../client/pk-console.c:679
 msgid "Results:"
 msgstr "Резултати:"
 
 #. TRANSLATORS: we failed to get any results, which is pretty fatal in my book
-#: ../client/pk-console.c:685
+#: ../client/pk-console.c:686
 msgid "Fatal error"
 msgstr "Кобна грешка"
 
 #. TRANSLATORS: the transaction failed in a way we could not expect
-#: ../client/pk-console.c:694
+#: ../client/pk-console.c:695
 #: ../contrib/command-not-found/pk-command-not-found.c:432
 #: ../contrib/command-not-found/pk-command-not-found.c:603
 msgid "The transaction failed"
 msgstr "Трансакција није успела"
 
 #. TRANSLATORS: print a message when there are no updates
-#: ../client/pk-console.c:721
+#: ../client/pk-console.c:726
 msgid "There are no updates available at this time."
 msgstr "Тренутно нема доступних ажурирања."
 
+#: ../client/pk-console.c:749
+msgid "There are no upgrades available at this time."
+msgstr "Тренутно нема доступних надградњи."
+
 #. TRANSLATORS: a package needs to restart their system
-#: ../client/pk-console.c:808
+#: ../client/pk-console.c:816
 msgid "Please restart the computer to complete the update."
 msgstr "Неопходно је поновно покретање система ради завршетка ажурирања."
 
 #. TRANSLATORS: a package needs to restart the session
-#: ../client/pk-console.c:811
+#: ../client/pk-console.c:819
 msgid "Please logout and login to complete the update."
 msgstr "Неопходно је одјављивање и поновна пријава ради завршетка ажурирања."
 
 #. TRANSLATORS: a package needs to restart their system (due to security)
-#: ../client/pk-console.c:814
+#: ../client/pk-console.c:822
 msgid ""
 "Please restart the computer to complete the update as important security "
 "updates have been installed."
@@ -314,7 +318,7 @@ msgstr ""
 "инсталирана важна безбедносна ажурирања."
 
 #. TRANSLATORS: a package needs to restart the session (due to security)
-#: ../client/pk-console.c:817
+#: ../client/pk-console.c:825
 msgid ""
 "Please logout and login to complete the update as important security updates "
 "have been installed."
@@ -322,20 +326,30 @@ msgstr ""
 "Неопходно је одјављивање и поновна пријава ради завршетка ажурирања јер су "
 "инсталирана важна безбедносна ажурирања."
 
+#. TRANSLATORS: The user used 'pkcon install dave.rpm' rather than 'pkcon install-local dave.rpm'
+#: ../client/pk-console.c:851
+#, c-format
+msgid ""
+"Extected package name, actually got file. Try using 'pkcon install-local %s' "
+"instead."
+msgstr ""
+"Очекивано је име пакета, уствари је добијена датотека. Покушајте да "
+"употребите „pkcon install-local %s“ наместо."
+
 #. TRANSLATORS: There was an error getting the list of files for the package. The detailed error follows
-#: ../client/pk-console.c:840
+#: ../client/pk-console.c:859
 #, c-format
 msgid "This tool could not find any available package: %s"
 msgstr "Ова алатка није могла пронаћи никакве доступне пакете: %s"
 
 #. TRANSLATORS: There was an error getting the list of files for the package. The detailed error follows
-#: ../client/pk-console.c:868
+#: ../client/pk-console.c:887
 #, c-format
 msgid "This tool could not find the installed package: %s"
 msgstr "Ова алатка није могла пронаћи инсталирани пакет: %s"
 
 #. TRANSLATORS: There was an error getting the list of files for the package. The detailed error follows
-#: ../client/pk-console.c:896 ../client/pk-console.c:924
+#: ../client/pk-console.c:915 ../client/pk-console.c:943
 #, c-format
 msgid "This tool could not find the package: %s"
 msgstr "Ова алатка није могла пронаћи пакет: %s"
@@ -344,190 +358,190 @@ msgstr "Ова алатка није могла пронаћи пакет: %s"
 #. TRANSLATORS: There was an error getting the dependencies for the package. The detailed error follows
 #. TRANSLATORS: There was an error getting the details about the package. The detailed error follows
 #. TRANSLATORS: The package name was not found in any software sources. The detailed error follows
-#: ../client/pk-console.c:952 ../client/pk-console.c:980
-#: ../client/pk-console.c:1008 ../client/pk-console.c:1036
-#: ../client/pk-console.c:1064
+#: ../client/pk-console.c:971 ../client/pk-console.c:999
+#: ../client/pk-console.c:1027 ../client/pk-console.c:1055
+#: ../client/pk-console.c:1083
 #, c-format
 msgid "This tool could not find all the packages: %s"
 msgstr "Ова алатка није пронашла све пакете: %s"
 
 #. TRANSLATORS: This is when the daemon crashed, and we are up shit creek without a paddle
-#: ../client/pk-console.c:1093
+#: ../client/pk-console.c:1112
 msgid "The daemon crashed mid-transaction!"
 msgstr "Услужни програм се изненада прекинуо!"
 
 #. TRANSLATORS: This is the header to the --help menu
-#: ../client/pk-console.c:1127
+#: ../client/pk-console.c:1146
 msgid "PackageKit Console Interface"
 msgstr "Текстуално сучеље програма ПакетКит"
 
 #. these are commands we can use with pkcon
-#: ../client/pk-console.c:1129
+#: ../client/pk-console.c:1148
 msgid "Subcommands:"
 msgstr "Наредбе:"
 
 #. TRANSLATORS: we keep a database updated with the time that an action was last executed
-#: ../client/pk-console.c:1208
+#: ../client/pk-console.c:1227
 msgid "Failed to get the time since this action was last completed"
 msgstr "Датум последњег извршавања ове радње није пронађен"
 
 #. TRANSLATORS: command line argument, just show the version string
-#: ../client/pk-console.c:1244 ../client/pk-monitor.c:280
+#: ../client/pk-console.c:1263 ../client/pk-monitor.c:306
 msgid "Show the program version and exit"
 msgstr "Прикажи верзију програма и заврши рад"
 
 #. TRANSLATORS: command line argument, use a filter to narrow down results
-#: ../client/pk-console.c:1247
+#: ../client/pk-console.c:1266
 msgid "Set the filter, e.g. installed"
 msgstr "Намести филтер, нпр. инсталирани"
 
 #. TRANSLATORS: command line argument, work asynchronously
-#: ../client/pk-console.c:1250
+#: ../client/pk-console.c:1269
 msgid "Exit without waiting for actions to complete"
 msgstr "Заврши рад без чекања да се послови заврше"
 
 #. command line argument, do we ask questions
-#: ../client/pk-console.c:1253
+#: ../client/pk-console.c:1272
 #: ../contrib/debuginfo-install/pk-debuginfo-install.c:527
 msgid "Install the packages without asking for confirmation"
 msgstr "Инсталирај пакете без питања за потврду"
 
 #. TRANSLATORS: command line argument, this command is not a priority
-#: ../client/pk-console.c:1256
+#: ../client/pk-console.c:1275
 msgid "Run the command using idle network bandwidth and also using less power"
 msgstr ""
 "Изврши наредбу користећи неискоришћени мрежни опсег и такође трошећи мање "
 "енергије"
 
 #. TRANSLATORS: command line argument, just output without fancy formatting
-#: ../client/pk-console.c:1259
+#: ../client/pk-console.c:1278
 msgid ""
 "Print to screen a machine readable output, rather than using animated widgets"
 msgstr ""
 "Штампај излаз читљив машини на екрану, уместо употребе анимираних виџета"
 
 #. TRANSLATORS: we failed to contact the daemon
-#: ../client/pk-console.c:1281
+#: ../client/pk-console.c:1300
 msgid "Failed to contact PackageKit"
 msgstr "Неуспешно контактирање ПакетКита."
 
 #. TRANSLATORS: The user specified an incorrect filter
-#: ../client/pk-console.c:1339
+#: ../client/pk-console.c:1358
 msgid "The filter specified was invalid"
 msgstr "Наведени филтер није исправан"
 
 #. TRANSLATORS: a search type can be name, details, file, etc
-#: ../client/pk-console.c:1358
+#: ../client/pk-console.c:1377
 msgid "A search type is required, e.g. name"
 msgstr "Морате навести врсту претраге, нпр. по имену"
 
 #. TRANSLATORS: the user needs to provide a search term
-#: ../client/pk-console.c:1365 ../client/pk-console.c:1377
-#: ../client/pk-console.c:1389 ../client/pk-console.c:1401
+#: ../client/pk-console.c:1384 ../client/pk-console.c:1396
+#: ../client/pk-console.c:1408 ../client/pk-console.c:1420
 msgid "A search term is required"
 msgstr "Морате навести термин за претрагу"
 
 #. TRANSLATORS: the search type was provided, but invalid
-#: ../client/pk-console.c:1411
+#: ../client/pk-console.c:1430
 msgid "Invalid search type"
 msgstr "Неисправна врста претраге"
 
 #. TRANSLATORS: the user did not specify what they wanted to install
-#: ../client/pk-console.c:1417
+#: ../client/pk-console.c:1436
 msgid "A package name to install is required"
 msgstr "Неопходно је име пакета за инсталацију"
 
 #. TRANSLATORS: the user did not specify what they wanted to install
-#: ../client/pk-console.c:1426
+#: ../client/pk-console.c:1445
 msgid "A filename to install is required"
 msgstr "Неопходно је име датотеке за инсталацију"
 
 #. TRANSLATORS: geeky error, 99.9999% of users won't see this
-#: ../client/pk-console.c:1438
+#: ../client/pk-console.c:1457
 msgid "A type, key_id and package_id are required"
 msgstr "Морате навести врсту, ИБ кључа и ИБ пакета (key_id и package_id)"
 
 #. TRANSLATORS: the user did not specify what they wanted to remove
-#: ../client/pk-console.c:1449
+#: ../client/pk-console.c:1468
 msgid "A package name to remove is required"
 msgstr "Морате навести назив пакета за уклањање"
 
 #. TRANSLATORS: the user did not specify anything about what to download or where
-#: ../client/pk-console.c:1458
+#: ../client/pk-console.c:1477
 msgid "A destination directory and the package names to download are required"
 msgstr "Неопходни су одредишни директоријум и имена пакета за преузимање"
 
 #. TRANSLATORS: the directory does not exist, so we can't continue
-#: ../client/pk-console.c:1465
+#: ../client/pk-console.c:1484
 msgid "Directory not found"
 msgstr "Директоријум није нађен"
 
 #. TRANSLATORS: geeky error, 99.9999% of users won't see this
-#: ../client/pk-console.c:1474
+#: ../client/pk-console.c:1493
 msgid "A licence identifier (eula-id) is required"
 msgstr "Морете навести идентификатор лиценце (eula-id)"
 
 #. TRANSLATORS: geeky error, 99.9999% of users won't see this
-#: ../client/pk-console.c:1485
+#: ../client/pk-console.c:1504
 msgid "A transaction identifier (tid) is required"
 msgstr "Морате навести идентификатор трансакције (tid)"
 
 #. TRANSLATORS: The user did not specify a package name
-#: ../client/pk-console.c:1506
+#: ../client/pk-console.c:1525
 msgid "A package name to resolve is required"
 msgstr "Морате навести име пакета за разрешавање"
 
 #. TRANSLATORS: The user did not specify a repository (software source) name
-#: ../client/pk-console.c:1517 ../client/pk-console.c:1528
+#: ../client/pk-console.c:1536 ../client/pk-console.c:1547
 msgid "A repository name is required"
 msgstr "Морате навести име ризнице"
 
 #. TRANSLATORS: The user didn't provide any data
-#: ../client/pk-console.c:1539
+#: ../client/pk-console.c:1558
 msgid "A repo name, parameter and value are required"
 msgstr "Морате навести име, параметар и вредност ризнице"
 
 #. TRANSLATORS: The user didn't specify what action to use
-#: ../client/pk-console.c:1556
+#: ../client/pk-console.c:1575
 msgid "An action, e.g. 'update-system' is required"
 msgstr "Морате навести радњу, нпр. „update-system“ (ажурирање система)"
 
 #. TRANSLATORS: The user specified an invalid action
-#: ../client/pk-console.c:1563
+#: ../client/pk-console.c:1582
 msgid "A correct role is required"
 msgstr "Морате навести важећу радњу"
 
 #. TRANSLATORS: The user did not provide a package name
 #. TRANSLATORS: This is when the user fails to supply the package name
-#: ../client/pk-console.c:1573 ../client/pk-console.c:1588
-#: ../client/pk-console.c:1597 ../client/pk-console.c:1617
-#: ../client/pk-console.c:1626 ../client/pk-generate-pack.c:298
+#: ../client/pk-console.c:1592 ../client/pk-console.c:1607
+#: ../client/pk-console.c:1616 ../client/pk-console.c:1636
+#: ../client/pk-console.c:1645 ../client/pk-generate-pack.c:316
 msgid "A package name is required"
 msgstr "Морате навести име пакета"
 
 #. TRANSLATORS: each package "provides" certain things, e.g. mime(gstreamer-decoder-mp3), the user didn't specify it
-#: ../client/pk-console.c:1606
+#: ../client/pk-console.c:1625
 msgid "A package provide string is required"
 msgstr "Морате навести „provide“ низ (шта пакет пружа)"
 
 #. TRANSLATORS: The user tried to use an unsupported option on the command line
-#: ../client/pk-console.c:1686
+#: ../client/pk-console.c:1705
 #, c-format
 msgid "Option '%s' is not supported"
 msgstr "Опција „%s“ није подржана"
 
 #. TRANSLATORS: Generic failure of what they asked to do
-#: ../client/pk-console.c:1696
+#: ../client/pk-console.c:1715
 msgid "Command failed"
 msgstr "Наредба није успела"
 
 #. TRANSLATORS: we can exclude certain packages (glibc) when we know they'll exist on the target
-#: ../client/pk-generate-pack.c:237
+#: ../client/pk-generate-pack.c:255
 msgid "Set the file name of dependencies to be excluded"
 msgstr "Поставите име датотеке за међузависности које ће бити изостављене"
 
 #. TRANSLATORS: the output location
-#: ../client/pk-generate-pack.c:240
+#: ../client/pk-generate-pack.c:258
 msgid ""
 "The output file or directory (the current directory is used if ommitted)"
 msgstr ""
@@ -535,43 +549,43 @@ msgstr ""
 "наведен)"
 
 #. TRANSLATORS: put a list of packages in the pack
-#: ../client/pk-generate-pack.c:243
+#: ../client/pk-generate-pack.c:261
 msgid "The package to be put into the service pack"
 msgstr "Пакети који ће бити стављени у сервисни скуп"
 
 #. TRANSLATORS: put all pending updates in the pack
-#: ../client/pk-generate-pack.c:246
+#: ../client/pk-generate-pack.c:264
 msgid "Put all updates available in the service pack"
 msgstr "Стави сва ажурирања у сервисни скуп"
 
 #. TRANSLATORS: This is when the user fails to supply the correct arguments
-#: ../client/pk-generate-pack.c:282
+#: ../client/pk-generate-pack.c:300
 msgid "Neither --package or --updates option selected."
 msgstr "Ни једна од опција --package или --updates није изабрана."
 
 #. TRANSLATORS: This is when the user fails to supply just one argument
-#: ../client/pk-generate-pack.c:290
+#: ../client/pk-generate-pack.c:308
 msgid "Both options selected."
 msgstr "Обе опције изабране."
 
 #. TRANSLATORS: This is when the user fails to supply the output
-#: ../client/pk-generate-pack.c:306
+#: ../client/pk-generate-pack.c:324
 msgid "A output directory or file name is required"
 msgstr "Морате навести име излазне датотеке или директоријума"
 
 #. TRANSLATORS: This is when the dameon is not-installed/broken and fails to startup
-#: ../client/pk-generate-pack.c:324
+#: ../client/pk-generate-pack.c:342
 msgid "The dameon failed to startup"
 msgstr "Демон није успео да се покрене"
 
 #. TRANSLATORS: This is when the backend doesn't have the capability to get-depends
 #. TRANSLATORS: This is when the backend doesn't have the capability to download
-#: ../client/pk-generate-pack.c:335 ../client/pk-generate-pack.c:341
+#: ../client/pk-generate-pack.c:353 ../client/pk-generate-pack.c:359
 msgid "The package manager cannot perform this type of operation."
 msgstr "Управник пакета не може извршити ову врсту радње."
 
 #. TRANSLATORS: This is when the distro didn't include libarchive support into PK
-#: ../client/pk-generate-pack.c:348
+#: ../client/pk-generate-pack.c:366
 msgid ""
 "Service packs cannot be created as PackageKit was not built with libarchive "
 "support."
@@ -580,64 +594,64 @@ msgstr ""
 "подршком за libarchive."
 
 #. TRANSLATORS: the user specified an absolute path, but didn't get the extension correct
-#: ../client/pk-generate-pack.c:359
+#: ../client/pk-generate-pack.c:377
 msgid "If specifying a file, the service pack name must end with"
 msgstr "Ако наводите датотеку, назив сервисног пакета се мора завршити са"
 
 #. TRANSLATORS: This is when file already exists
-#: ../client/pk-generate-pack.c:375
+#: ../client/pk-generate-pack.c:393
 msgid "A pack with the same name already exists, do you want to overwrite it?"
 msgstr "Скуп са истим називом већ постоји, да ли га желите преснимити?"
 
 #. TRANSLATORS: This is when the pack was not overwritten
-#: ../client/pk-generate-pack.c:378
+#: ../client/pk-generate-pack.c:396
 msgid "The pack was not overwritten."
 msgstr "Скуп није преснимљен."
 
 #. TRANSLATORS: This is when the temporary directory cannot be created, the directory name follows
-#: ../client/pk-generate-pack.c:391
+#: ../client/pk-generate-pack.c:409
 msgid "Failed to create directory:"
 msgstr "Неуспело прављење директоријума:"
 
 #. TRANSLATORS: This is when the list of packages from the remote computer cannot be opened
-#: ../client/pk-generate-pack.c:403
+#: ../client/pk-generate-pack.c:421
 msgid "Failed to open package list."
 msgstr "Неуспешно отварање списка пакета."
 
 #. TRANSLATORS: The package name is being matched up to available packages
-#: ../client/pk-generate-pack.c:412
+#: ../client/pk-generate-pack.c:430
 msgid "Finding package name."
 msgstr "Проналажење имена пакета."
 
 #. TRANSLATORS: This is when the package cannot be found in any software source. The detailed error follows
-#: ../client/pk-generate-pack.c:416
+#: ../client/pk-generate-pack.c:434
 #, c-format
 msgid "Failed to find package '%s': %s"
 msgstr "Нисам могао да пронађем пакет „%s“: %s"
 
 #. TRANSLATORS: This is telling the user we are in the process of making the pack
-#: ../client/pk-generate-pack.c:424
+#: ../client/pk-generate-pack.c:442
 msgid "Creating service pack..."
 msgstr "Правим сервисну групу..."
 
 #. TRANSLATORS: we succeeded in making the file
-#: ../client/pk-generate-pack.c:439
+#: ../client/pk-generate-pack.c:457
 #, c-format
 msgid "Service pack created '%s'"
 msgstr "Сервисна група је направљена „%s“"
 
 #. TRANSLATORS: we failed to make te file
-#: ../client/pk-generate-pack.c:444
+#: ../client/pk-generate-pack.c:462
 #, c-format
 msgid "Failed to create '%s': %s"
 msgstr "Неуспело прављење „%s“: %s"
 
-#: ../client/pk-monitor.c:210
+#: ../client/pk-monitor.c:236
 msgid "Failed to get daemon state"
 msgstr "Неуспео покушај добављања стања демона"
 
 #. TRANSLATORS: this is a program that monitors PackageKit
-#: ../client/pk-monitor.c:296
+#: ../client/pk-monitor.c:322
 msgid "PackageKit Monitor"
 msgstr "ПакетКит редар"
 
@@ -763,29 +777,29 @@ msgid "Please choose a command to run"
 msgstr "Изаберите наредбу за покретање"
 
 #. TRANSLATORS: tell the user what package provides the command
-#: ../contrib/command-not-found/pk-command-not-found.c:766
+#: ../contrib/command-not-found/pk-command-not-found.c:764
 msgid "The package providing this file is:"
 msgstr "Пакет који пружа ову датотеку је:"
 
 #. TRANSLATORS: as the user if we want to install a package to provide the command
-#: ../contrib/command-not-found/pk-command-not-found.c:771
+#: ../contrib/command-not-found/pk-command-not-found.c:769
 #, c-format
 msgid "Install package '%s' to provide command '%s'?"
 msgstr "Да инсталирам пакет „%s“ који пружа наредбу „%s“?"
 
 #. TRANSLATORS: Show the user a list of packages that provide this command
-#: ../contrib/command-not-found/pk-command-not-found.c:795
+#: ../contrib/command-not-found/pk-command-not-found.c:793
 msgid "Packages providing this file are:"
 msgstr "Пакети који пружају ову датотеку су:"
 
 #. TRANSLATORS: Show the user a list of packages that they can install to provide this command
-#: ../contrib/command-not-found/pk-command-not-found.c:805
+#: ../contrib/command-not-found/pk-command-not-found.c:803
 msgid "Suitable packages are:"
 msgstr "Прикладни пакети су:"
 
 #. get selection
 #. TRANSLATORS: ask the user to choose a file to install
-#: ../contrib/command-not-found/pk-command-not-found.c:814
+#: ../contrib/command-not-found/pk-command-not-found.c:812
 msgid "Please choose a package to install"
 msgstr "Изаберите пакет за инсталацију"
 
@@ -955,7 +969,7 @@ msgstr "Не инсталирам пакете у режиму симулаци
 #. TRANSLATORS: we are now installing the debuginfo packages we found earlier
 #. TRANSLATORS: transaction state, installing packages
 #: ../contrib/debuginfo-install/pk-debuginfo-install.c:862
-#: ../lib/packagekit-glib2/pk-console-shared.c:282
+#: ../lib/packagekit-glib2/pk-console-shared.c:283
 #, c-format
 msgid "Installing packages"
 msgstr "Инсталирам пакете"
@@ -985,92 +999,92 @@ msgid "Disabled %i debugging sources."
 msgstr "Искључено је %i извора за отклон грешака."
 
 #. TRANSLATORS: couldn't open device to write
-#: ../contrib/device-rebind/pk-device-rebind.c:61
+#: ../contrib/device-rebind/pk-device-rebind.c:62
 msgid "Failed to open file"
 msgstr "Неуспело отварање датотеке"
 
 #. TRANSLATORS: could not write to the device
-#: ../contrib/device-rebind/pk-device-rebind.c:70
+#: ../contrib/device-rebind/pk-device-rebind.c:71
 msgid "Failed to write to the file"
 msgstr "Неуспешно записивање у датотеку"
 
 #. TRANSLATORS: we failed to release the current driver
-#: ../contrib/device-rebind/pk-device-rebind.c:110
-#: ../contrib/device-rebind/pk-device-rebind.c:147
+#: ../contrib/device-rebind/pk-device-rebind.c:111
+#: ../contrib/device-rebind/pk-device-rebind.c:148
 msgid "Failed to write to device"
 msgstr "Неуспешно записивање на уређај"
 
 #. TRANSLATORS: the device could not be found in sysfs
-#: ../contrib/device-rebind/pk-device-rebind.c:175
+#: ../contrib/device-rebind/pk-device-rebind.c:176
 msgid "Device could not be found"
 msgstr "Уређај није могао бити пронађен"
 
 #. TRANSLATORS: we failed to release the current driver
-#: ../contrib/device-rebind/pk-device-rebind.c:202
+#: ../contrib/device-rebind/pk-device-rebind.c:203
 msgid "Failed to unregister driver"
 msgstr "Неуспела дерегистрација управљачког програма"
 
 #. TRANSLATORS: we failed to bind the old driver
-#: ../contrib/device-rebind/pk-device-rebind.c:211
+#: ../contrib/device-rebind/pk-device-rebind.c:212
 msgid "Failed to register driver"
 msgstr "Неуспела регистрација управљачког програма"
 
 #. TRANSLATORS: user did not specify a device sysfs path that exists
-#: ../contrib/device-rebind/pk-device-rebind.c:260
+#: ../contrib/device-rebind/pk-device-rebind.c:261
 msgid "Device path not found"
 msgstr "Путања уређаја није нађена"
 
 #. TRANSLATORS: user did not specify a valid device sysfs path
-#: ../contrib/device-rebind/pk-device-rebind.c:268
+#: ../contrib/device-rebind/pk-device-rebind.c:269
 msgid "Incorrect device path specified"
 msgstr "Наведена је неисправна путања уређаја"
 
-#: ../contrib/device-rebind/pk-device-rebind.c:293
+#: ../contrib/device-rebind/pk-device-rebind.c:294
 msgid "Show extra debugging information"
 msgstr "Прикажи додатне податке за отклон грешака"
 
 #. command line argument, simulate what would be done, but don't actually do it
-#: ../contrib/device-rebind/pk-device-rebind.c:296
+#: ../contrib/device-rebind/pk-device-rebind.c:297
 msgid "Don't actually touch the hardware, only simulate what would be done"
 msgstr "Немој у ствари да дираш хардвер, само симулирај шта би се урадило"
 
 #. TRANSLATORS: command line option: a list of files to install
-#: ../contrib/device-rebind/pk-device-rebind.c:299
+#: ../contrib/device-rebind/pk-device-rebind.c:300
 msgid "Device paths"
 msgstr "Путање уређаја"
 
 #. TRANSLATORS: tool that gets called when the device needs reloading after installing firmware
-#: ../contrib/device-rebind/pk-device-rebind.c:314
+#: ../contrib/device-rebind/pk-device-rebind.c:315
 msgid "PackageKit Device Reloader"
 msgstr "ПакетКит програм за поновно учитавање уређаја"
 
 #. TRANSLATORS: user did not specify a valid device sysfs path
-#: ../contrib/device-rebind/pk-device-rebind.c:322
+#: ../contrib/device-rebind/pk-device-rebind.c:323
 msgid "You need to specify at least one valid device path"
 msgstr "Морате навести барем једну исправну путању уређаја"
 
 #. TRANSLATORS: user did not specify a valid device sysfs path
-#: ../contrib/device-rebind/pk-device-rebind.c:332
+#: ../contrib/device-rebind/pk-device-rebind.c:333
 msgid "This script can only be used by the root user"
 msgstr "Ову скрипту може користити само „root“ корисник"
 
 #. TRANSLATORS: we're going to verify the path first
-#: ../contrib/device-rebind/pk-device-rebind.c:341
+#: ../contrib/device-rebind/pk-device-rebind.c:342
 msgid "Verifying device path"
 msgstr "Проверавам путању уређаја"
 
 #. TRANSLATORS: user did not specify a device sysfs path that exists
-#: ../contrib/device-rebind/pk-device-rebind.c:346
+#: ../contrib/device-rebind/pk-device-rebind.c:347
 msgid "Failed to verify device path"
 msgstr "Неуспела провера путање уређаја"
 
 #. TRANSLATORS: we're going to try
-#: ../contrib/device-rebind/pk-device-rebind.c:360
+#: ../contrib/device-rebind/pk-device-rebind.c:361
 msgid "Attempting to rebind device"
 msgstr "Покушавам да поново вежем уређај"
 
 #. TRANSLATORS: we failed to release the current driver
-#: ../contrib/device-rebind/pk-device-rebind.c:365
+#: ../contrib/device-rebind/pk-device-rebind.c:366
 msgid "Failed to rebind device"
 msgstr "Неуспело поновно везивање уређаја"
 
@@ -1092,7 +1106,7 @@ msgid "Please enter a number from 1 to %i: "
 msgstr "Унесите број између 1 и %i: "
 
 #. TRANSLATORS: more than one package could be found that matched, to follow is a list of possible packages
-#: ../lib/packagekit-glib2/pk-console-shared.c:183
+#: ../lib/packagekit-glib2/pk-console-shared.c:185
 msgid "More than one package matches:"
 msgstr "Постоји више пакета који одговарају упиту:"
 
@@ -1102,448 +1116,448 @@ msgid "Please choose the correct package: "
 msgstr "Изаберите жељени пакет: "
 
 #. TRANSLATORS: This is when the transaction status is not known
-#: ../lib/packagekit-glib2/pk-console-shared.c:250
+#: ../lib/packagekit-glib2/pk-console-shared.c:251
 msgid "Unknown state"
 msgstr "Непознато стање"
 
 #. TRANSLATORS: transaction state, the daemon is in the process of starting
-#: ../lib/packagekit-glib2/pk-console-shared.c:254
+#: ../lib/packagekit-glib2/pk-console-shared.c:255
 msgid "Starting"
 msgstr "Покретање"
 
 #. TRANSLATORS: transaction state, the transaction is waiting for another to complete
-#: ../lib/packagekit-glib2/pk-console-shared.c:258
+#: ../lib/packagekit-glib2/pk-console-shared.c:259
 msgid "Waiting in queue"
 msgstr "Чекање у реду"
 
 #. TRANSLATORS: transaction state, just started
-#: ../lib/packagekit-glib2/pk-console-shared.c:262
+#: ../lib/packagekit-glib2/pk-console-shared.c:263
 msgid "Running"
 msgstr "Извршавање"
 
 #. TRANSLATORS: transaction state, is querying data
-#: ../lib/packagekit-glib2/pk-console-shared.c:266
+#: ../lib/packagekit-glib2/pk-console-shared.c:267
 msgid "Querying"
 msgstr "Испитивање"
 
 #. TRANSLATORS: transaction state, getting data from a server
-#: ../lib/packagekit-glib2/pk-console-shared.c:270
+#: ../lib/packagekit-glib2/pk-console-shared.c:271
 msgid "Getting information"
 msgstr "Добављање података"
 
 #. TRANSLATORS: transaction state, removing packages
-#: ../lib/packagekit-glib2/pk-console-shared.c:274
+#: ../lib/packagekit-glib2/pk-console-shared.c:275
 msgid "Removing packages"
 msgstr "Уклањање пакета"
 
 #. TRANSLATORS: transaction state, downloading package files
 #. TRANSLATORS: The role of the transaction, in present tense
-#: ../lib/packagekit-glib2/pk-console-shared.c:278
-#: ../lib/packagekit-glib2/pk-console-shared.c:656
+#: ../lib/packagekit-glib2/pk-console-shared.c:279
+#: ../lib/packagekit-glib2/pk-console-shared.c:657
 msgid "Downloading packages"
 msgstr "Преузимање пакета"
 
 #. TRANSLATORS: transaction state, refreshing internal lists
-#: ../lib/packagekit-glib2/pk-console-shared.c:286
+#: ../lib/packagekit-glib2/pk-console-shared.c:287
 msgid "Refreshing software list"
 msgstr "Освежавање списка софтвера"
 
 #. TRANSLATORS: transaction state, installing updates
-#: ../lib/packagekit-glib2/pk-console-shared.c:290
+#: ../lib/packagekit-glib2/pk-console-shared.c:291
 msgid "Installing updates"
 msgstr "Инсталирање ажурирања"
 
 #. TRANSLATORS: transaction state, removing old packages, and cleaning config files
-#: ../lib/packagekit-glib2/pk-console-shared.c:294
+#: ../lib/packagekit-glib2/pk-console-shared.c:295
 msgid "Cleaning up packages"
 msgstr "Чишћење пакета"
 
 #. TRANSLATORS: transaction state, obsoleting old packages
-#: ../lib/packagekit-glib2/pk-console-shared.c:298
+#: ../lib/packagekit-glib2/pk-console-shared.c:299
 msgid "Obsoleting packages"
 msgstr "Превазилазим пакете"
 
 #. TRANSLATORS: transaction state, checking the transaction before we do it
-#: ../lib/packagekit-glib2/pk-console-shared.c:302
+#: ../lib/packagekit-glib2/pk-console-shared.c:303
 msgid "Resolving dependencies"
 msgstr "Разрешавање зависности"
 
 #. TRANSLATORS: transaction state, checking if we have all the security keys for the operation
-#: ../lib/packagekit-glib2/pk-console-shared.c:306
+#: ../lib/packagekit-glib2/pk-console-shared.c:307
 msgid "Checking signatures"
 msgstr "Провера потписа"
 
 #. TRANSLATORS: transaction state, when we return to a previous system state
 #. TRANSLATORS: The role of the transaction, in present tense
-#: ../lib/packagekit-glib2/pk-console-shared.c:310
-#: ../lib/packagekit-glib2/pk-console-shared.c:616
+#: ../lib/packagekit-glib2/pk-console-shared.c:311
+#: ../lib/packagekit-glib2/pk-console-shared.c:617
 msgid "Rolling back"
 msgstr "Враћање уназад"
 
 #. TRANSLATORS: transaction state, when we're doing a test transaction
-#: ../lib/packagekit-glib2/pk-console-shared.c:314
+#: ../lib/packagekit-glib2/pk-console-shared.c:315
 msgid "Testing changes"
 msgstr "Испробавање промена"
 
 #. TRANSLATORS: transaction state, when we're writing to the system package database
-#: ../lib/packagekit-glib2/pk-console-shared.c:318
+#: ../lib/packagekit-glib2/pk-console-shared.c:319
 msgid "Committing changes"
 msgstr "Шаљем промене"
 
 #. TRANSLATORS: transaction state, requesting data from a server
-#: ../lib/packagekit-glib2/pk-console-shared.c:322
+#: ../lib/packagekit-glib2/pk-console-shared.c:323
 msgid "Requesting data"
 msgstr "Захтевам податке"
 
 #. TRANSLATORS: transaction state, all done!
-#: ../lib/packagekit-glib2/pk-console-shared.c:326
+#: ../lib/packagekit-glib2/pk-console-shared.c:327
 msgid "Finished"
 msgstr "Завршено"
 
 #. TRANSLATORS: transaction state, in the process of cancelling
-#: ../lib/packagekit-glib2/pk-console-shared.c:330
+#: ../lib/packagekit-glib2/pk-console-shared.c:331
 msgid "Cancelling"
 msgstr "Отказивање"
 
 #. TRANSLATORS: transaction state, downloading metadata
-#: ../lib/packagekit-glib2/pk-console-shared.c:334
+#: ../lib/packagekit-glib2/pk-console-shared.c:335
 msgid "Downloading repository information"
 msgstr "Преузимам податке о ризници"
 
 #. TRANSLATORS: transaction state, downloading metadata
-#: ../lib/packagekit-glib2/pk-console-shared.c:338
+#: ../lib/packagekit-glib2/pk-console-shared.c:339
 msgid "Downloading list of packages"
 msgstr "Преузимање списка пакета"
 
 #. TRANSLATORS: transaction state, downloading metadata
-#: ../lib/packagekit-glib2/pk-console-shared.c:342
+#: ../lib/packagekit-glib2/pk-console-shared.c:343
 msgid "Downloading file lists"
 msgstr "Преузимање спискова датотека"
 
 #. TRANSLATORS: transaction state, downloading metadata
-#: ../lib/packagekit-glib2/pk-console-shared.c:346
+#: ../lib/packagekit-glib2/pk-console-shared.c:347
 msgid "Downloading lists of changes"
 msgstr "Преузимање спискова промена"
 
 #. TRANSLATORS: transaction state, downloading metadata
-#: ../lib/packagekit-glib2/pk-console-shared.c:350
+#: ../lib/packagekit-glib2/pk-console-shared.c:351
 msgid "Downloading groups"
 msgstr "Преузимање група"
 
 #. TRANSLATORS: transaction state, downloading metadata
-#: ../lib/packagekit-glib2/pk-console-shared.c:354
+#: ../lib/packagekit-glib2/pk-console-shared.c:355
 msgid "Downloading update information"
 msgstr "Преузимање података о ажурирању"
 
 #. TRANSLATORS: transaction state, repackaging delta files
-#: ../lib/packagekit-glib2/pk-console-shared.c:358
+#: ../lib/packagekit-glib2/pk-console-shared.c:359
 msgid "Repackaging files"
 msgstr "Препакивање датотека"
 
 #. TRANSLATORS: transaction state, loading databases
-#: ../lib/packagekit-glib2/pk-console-shared.c:362
+#: ../lib/packagekit-glib2/pk-console-shared.c:363
 msgid "Loading cache"
 msgstr "Учитавање кеша"
 
 #. TRANSLATORS: transaction state, scanning for running processes
-#: ../lib/packagekit-glib2/pk-console-shared.c:366
+#: ../lib/packagekit-glib2/pk-console-shared.c:367
 msgid "Scanning applications"
 msgstr "Претражујем програме"
 
 #. TRANSLATORS: transaction state, generating a list of packages installed on the system
-#: ../lib/packagekit-glib2/pk-console-shared.c:370
+#: ../lib/packagekit-glib2/pk-console-shared.c:371
 msgid "Generating package lists"
 msgstr "Прављење спискова пакета"
 
 #. TRANSLATORS: transaction state, when we're waiting for the native tools to exit
-#: ../lib/packagekit-glib2/pk-console-shared.c:374
+#: ../lib/packagekit-glib2/pk-console-shared.c:375
 msgid "Waiting for package manager lock"
 msgstr "Чекање на закључавање управника пакета"
 
 #. TRANSLATORS: transaction state, waiting for user to type in a password
-#: ../lib/packagekit-glib2/pk-console-shared.c:378
+#: ../lib/packagekit-glib2/pk-console-shared.c:379
 msgid "Waiting for authentication"
 msgstr "Чекање на аутентификацију"
 
 #. TRANSLATORS: transaction state, we are updating the list of processes
-#: ../lib/packagekit-glib2/pk-console-shared.c:382
+#: ../lib/packagekit-glib2/pk-console-shared.c:383
 msgid "Updating running applications"
 msgstr "Ажурирам покренуте програме"
 
 #. TRANSLATORS: transaction state, we are checking executable files currently in use
-#: ../lib/packagekit-glib2/pk-console-shared.c:386
+#: ../lib/packagekit-glib2/pk-console-shared.c:387
 msgid "Checking applications in use"
 msgstr "Проверавам програме у употреби"
 
 #. TRANSLATORS: transaction state, we are checking for libraries currently in use
-#: ../lib/packagekit-glib2/pk-console-shared.c:390
+#: ../lib/packagekit-glib2/pk-console-shared.c:391
 msgid "Checking libraries in use"
 msgstr "Проверавам библиотеке у употреби"
 
 #. TRANSLATORS: transaction state, we are copying package files before or after the transaction
-#: ../lib/packagekit-glib2/pk-console-shared.c:394
+#: ../lib/packagekit-glib2/pk-console-shared.c:395
 msgid "Copying files"
 msgstr "Умножавање датотека"
 
 #. TRANSLATORS: The type of update
-#: ../lib/packagekit-glib2/pk-console-shared.c:412
+#: ../lib/packagekit-glib2/pk-console-shared.c:413
 msgid "Trivial"
 msgstr "Тривијално"
 
 #. TRANSLATORS: The type of update
-#: ../lib/packagekit-glib2/pk-console-shared.c:416
+#: ../lib/packagekit-glib2/pk-console-shared.c:417
 msgid "Normal"
 msgstr "Обично"
 
 #. TRANSLATORS: The type of update
-#: ../lib/packagekit-glib2/pk-console-shared.c:420
+#: ../lib/packagekit-glib2/pk-console-shared.c:421
 msgid "Important"
 msgstr "Важно"
 
 #. TRANSLATORS: The type of update
-#: ../lib/packagekit-glib2/pk-console-shared.c:424
+#: ../lib/packagekit-glib2/pk-console-shared.c:425
 msgid "Security"
 msgstr "Безбедносно"
 
 #. TRANSLATORS: The type of update
-#: ../lib/packagekit-glib2/pk-console-shared.c:428
+#: ../lib/packagekit-glib2/pk-console-shared.c:429
 msgid "Bug fix "
 msgstr "Исправка грешке"
 
 #. TRANSLATORS: The type of update
-#: ../lib/packagekit-glib2/pk-console-shared.c:432
+#: ../lib/packagekit-glib2/pk-console-shared.c:433
 msgid "Enhancement"
 msgstr "Побољшање"
 
 #. TRANSLATORS: The type of update
-#: ../lib/packagekit-glib2/pk-console-shared.c:436
+#: ../lib/packagekit-glib2/pk-console-shared.c:437
 msgid "Blocked"
 msgstr "Блокирано"
 
 #. TRANSLATORS: The state of a package
 #. TRANSLATORS: The action of the package, in past tense
-#: ../lib/packagekit-glib2/pk-console-shared.c:441
-#: ../lib/packagekit-glib2/pk-console-shared.c:514
+#: ../lib/packagekit-glib2/pk-console-shared.c:442
+#: ../lib/packagekit-glib2/pk-console-shared.c:515
 msgid "Installed"
 msgstr "Инсталиран"
 
 #. TRANSLATORS: The state of a package, i.e. not installed
-#: ../lib/packagekit-glib2/pk-console-shared.c:446
+#: ../lib/packagekit-glib2/pk-console-shared.c:447
 msgid "Available"
 msgstr "Доступан"
 
 #. TRANSLATORS: The action of the package, in present tense
-#: ../lib/packagekit-glib2/pk-console-shared.c:464
+#: ../lib/packagekit-glib2/pk-console-shared.c:465
 msgid "Downloading"
 msgstr "Преузимање"
 
 #. TRANSLATORS: The action of the package, in present tense
-#: ../lib/packagekit-glib2/pk-console-shared.c:468
+#: ../lib/packagekit-glib2/pk-console-shared.c:469
 msgid "Updating"
 msgstr "Ажурирање"
 
 #. TRANSLATORS: The action of the package, in present tense
 #. TRANSLATORS: The role of the transaction, in present tense
-#: ../lib/packagekit-glib2/pk-console-shared.c:472
-#: ../lib/packagekit-glib2/pk-console-shared.c:592
+#: ../lib/packagekit-glib2/pk-console-shared.c:473
+#: ../lib/packagekit-glib2/pk-console-shared.c:593
 msgid "Installing"
 msgstr "Инсталација"
 
 #. TRANSLATORS: The action of the package, in present tense
 #. TRANSLATORS: The role of the transaction, in present tense
-#: ../lib/packagekit-glib2/pk-console-shared.c:476
-#: ../lib/packagekit-glib2/pk-console-shared.c:588
+#: ../lib/packagekit-glib2/pk-console-shared.c:477
+#: ../lib/packagekit-glib2/pk-console-shared.c:589
 msgid "Removing"
 msgstr "Уклањање"
 
 #. TRANSLATORS: The action of the package, in present tense
-#: ../lib/packagekit-glib2/pk-console-shared.c:480
+#: ../lib/packagekit-glib2/pk-console-shared.c:481
 msgid "Cleaning up"
 msgstr "Чишћење"
 
 #. TRANSLATORS: The action of the package, in present tense
-#: ../lib/packagekit-glib2/pk-console-shared.c:484
+#: ../lib/packagekit-glib2/pk-console-shared.c:485
 msgid "Obsoleting"
 msgstr "Превазилажење"
 
 #. TRANSLATORS: The action of the package, in present tense
-#: ../lib/packagekit-glib2/pk-console-shared.c:488
+#: ../lib/packagekit-glib2/pk-console-shared.c:489
 msgid "Reinstalling"
 msgstr "Поновна инсталација"
 
 #. TRANSLATORS: The action of the package, in past tense
-#: ../lib/packagekit-glib2/pk-console-shared.c:506
+#: ../lib/packagekit-glib2/pk-console-shared.c:507
 msgid "Downloaded"
 msgstr "Преузет"
 
 #. TRANSLATORS: The action of the package, in past tense
-#: ../lib/packagekit-glib2/pk-console-shared.c:518
+#: ../lib/packagekit-glib2/pk-console-shared.c:519
 msgid "Removed"
 msgstr "Уклоњен"
 
 #. TRANSLATORS: The action of the package, in past tense
-#: ../lib/packagekit-glib2/pk-console-shared.c:522
+#: ../lib/packagekit-glib2/pk-console-shared.c:523
 msgid "Cleaned up"
 msgstr "Очишћен"
 
 #. TRANSLATORS: The action of the package, in past tense
-#: ../lib/packagekit-glib2/pk-console-shared.c:526
+#: ../lib/packagekit-glib2/pk-console-shared.c:527
 msgid "Obsoleted"
 msgstr "Превазиђен"
 
 #. TRANSLATORS: The action of the package, in past tense
-#: ../lib/packagekit-glib2/pk-console-shared.c:530
+#: ../lib/packagekit-glib2/pk-console-shared.c:531
 msgid "Reinstalled"
 msgstr "Поново инсталиран"
 
 #. TRANSLATORS: The role of the transaction, in present tense
-#: ../lib/packagekit-glib2/pk-console-shared.c:548
+#: ../lib/packagekit-glib2/pk-console-shared.c:549
 msgid "Unknown role type"
 msgstr "Непозната врста радње"
 
 #. TRANSLATORS: The role of the transaction, in present tense
-#: ../lib/packagekit-glib2/pk-console-shared.c:552
+#: ../lib/packagekit-glib2/pk-console-shared.c:553
 msgid "Getting dependencies"
 msgstr "Добављање зависности"
 
 #. TRANSLATORS: The role of the transaction, in present tense
-#: ../lib/packagekit-glib2/pk-console-shared.c:556
+#: ../lib/packagekit-glib2/pk-console-shared.c:557
 msgid "Getting update details"
 msgstr "Добављање детаља о ажурирању"
 
 #. TRANSLATORS: The role of the transaction, in present tense
-#: ../lib/packagekit-glib2/pk-console-shared.c:560
+#: ../lib/packagekit-glib2/pk-console-shared.c:561
 msgid "Getting details"
 msgstr "Добављање детаља"
 
 #. TRANSLATORS: The role of the transaction, in present tense
-#: ../lib/packagekit-glib2/pk-console-shared.c:564
+#: ../lib/packagekit-glib2/pk-console-shared.c:565
 msgid "Getting requires"
 msgstr "Добављам захтевања"
 
 #. TRANSLATORS: The role of the transaction, in present tense
-#: ../lib/packagekit-glib2/pk-console-shared.c:568
+#: ../lib/packagekit-glib2/pk-console-shared.c:569
 msgid "Getting updates"
 msgstr "Добављам ажурирања"
 
 #. TRANSLATORS: The role of the transaction, in present tense
-#: ../lib/packagekit-glib2/pk-console-shared.c:572
+#: ../lib/packagekit-glib2/pk-console-shared.c:573
 msgid "Searching by details"
 msgstr "Претражујем по детаљима"
 
 #. TRANSLATORS: The role of the transaction, in present tense
-#: ../lib/packagekit-glib2/pk-console-shared.c:576
+#: ../lib/packagekit-glib2/pk-console-shared.c:577
 msgid "Searching by file"
 msgstr "Претражујем по датотекама"
 
 #. TRANSLATORS: The role of the transaction, in present tense
-#: ../lib/packagekit-glib2/pk-console-shared.c:580
+#: ../lib/packagekit-glib2/pk-console-shared.c:581
 msgid "Searching groups"
 msgstr "Претражујем по групама"
 
 #. TRANSLATORS: The role of the transaction, in present tense
-#: ../lib/packagekit-glib2/pk-console-shared.c:584
+#: ../lib/packagekit-glib2/pk-console-shared.c:585
 msgid "Searching by name"
 msgstr "Претражујем по имену"
 
 #. TRANSLATORS: The role of the transaction, in present tense
-#: ../lib/packagekit-glib2/pk-console-shared.c:596
+#: ../lib/packagekit-glib2/pk-console-shared.c:597
 msgid "Installing files"
 msgstr "Инсталирам датотеке"
 
 #. TRANSLATORS: The role of the transaction, in present tense
-#: ../lib/packagekit-glib2/pk-console-shared.c:600
+#: ../lib/packagekit-glib2/pk-console-shared.c:601
 msgid "Refreshing cache"
 msgstr "Освежавам кеш"
 
 #. TRANSLATORS: The role of the transaction, in present tense
-#: ../lib/packagekit-glib2/pk-console-shared.c:604
+#: ../lib/packagekit-glib2/pk-console-shared.c:605
 msgid "Updating packages"
 msgstr "Ажурирање пакета"
 
 #. TRANSLATORS: The role of the transaction, in present tense
-#: ../lib/packagekit-glib2/pk-console-shared.c:608
+#: ../lib/packagekit-glib2/pk-console-shared.c:609
 msgid "Updating system"
 msgstr "Ажурирање система"
 
 #. TRANSLATORS: The role of the transaction, in present tense
-#: ../lib/packagekit-glib2/pk-console-shared.c:612
+#: ../lib/packagekit-glib2/pk-console-shared.c:613
 msgid "Canceling"
 msgstr "Отказивање"
 
 #. TRANSLATORS: The role of the transaction, in present tense
-#: ../lib/packagekit-glib2/pk-console-shared.c:620
+#: ../lib/packagekit-glib2/pk-console-shared.c:621
 msgid "Getting repositories"
 msgstr "Добављање ризница"
 
 #. TRANSLATORS: The role of the transaction, in present tense
-#: ../lib/packagekit-glib2/pk-console-shared.c:624
+#: ../lib/packagekit-glib2/pk-console-shared.c:625
 msgid "Enabling repository"
 msgstr "Укључивање ризнице"
 
 #. TRANSLATORS: The role of the transaction, in present tense
-#: ../lib/packagekit-glib2/pk-console-shared.c:628
+#: ../lib/packagekit-glib2/pk-console-shared.c:629
 msgid "Setting data"
 msgstr "Постављање података"
 
 #. TRANSLATORS: The role of the transaction, in present tense
-#: ../lib/packagekit-glib2/pk-console-shared.c:632
+#: ../lib/packagekit-glib2/pk-console-shared.c:633
 msgid "Resolving"
 msgstr "Разрешавање"
 
 #. TRANSLATORS: The role of the transaction, in present tense
-#: ../lib/packagekit-glib2/pk-console-shared.c:636
+#: ../lib/packagekit-glib2/pk-console-shared.c:637
 msgid "Getting file list"
 msgstr "Добављање списка датотека"
 
 #. TRANSLATORS: The role of the transaction, in present tense
-#: ../lib/packagekit-glib2/pk-console-shared.c:640
+#: ../lib/packagekit-glib2/pk-console-shared.c:641
 msgid "Getting provides"
 msgstr "Добављање пружања"
 
 #. TRANSLATORS: The role of the transaction, in present tense
-#: ../lib/packagekit-glib2/pk-console-shared.c:644
+#: ../lib/packagekit-glib2/pk-console-shared.c:645
 msgid "Installing signature"
 msgstr "Инсталирање потписа"
 
 #. TRANSLATORS: The role of the transaction, in present tense
-#: ../lib/packagekit-glib2/pk-console-shared.c:648
+#: ../lib/packagekit-glib2/pk-console-shared.c:649
 msgid "Getting packages"
 msgstr "Добављање пакета"
 
 #. TRANSLATORS: The role of the transaction, in present tense
-#: ../lib/packagekit-glib2/pk-console-shared.c:652
+#: ../lib/packagekit-glib2/pk-console-shared.c:653
 msgid "Accepting EULA"
 msgstr "Прихватање лиценце"
 
 #. TRANSLATORS: The role of the transaction, in present tense
-#: ../lib/packagekit-glib2/pk-console-shared.c:660
+#: ../lib/packagekit-glib2/pk-console-shared.c:661
 msgid "Getting upgrades"
 msgstr "Добављање надградњи"
 
 #. TRANSLATORS: The role of the transaction, in present tense
-#: ../lib/packagekit-glib2/pk-console-shared.c:664
+#: ../lib/packagekit-glib2/pk-console-shared.c:665
 msgid "Getting categories"
 msgstr "Добављање категорија"
 
 #. TRANSLATORS: The role of the transaction, in present tense
-#: ../lib/packagekit-glib2/pk-console-shared.c:668
+#: ../lib/packagekit-glib2/pk-console-shared.c:669
 msgid "Getting transactions"
 msgstr "Добављање трансакција"
 
 #. TRANSLATORS: The role of the transaction, in present tense
-#: ../lib/packagekit-glib2/pk-console-shared.c:672
-#: ../lib/packagekit-glib2/pk-console-shared.c:676
+#: ../lib/packagekit-glib2/pk-console-shared.c:673
+#: ../lib/packagekit-glib2/pk-console-shared.c:677
 msgid "Simulating install"
 msgstr "Симулирање инсталације"
 
 #. TRANSLATORS: The role of the transaction, in present tense
-#: ../lib/packagekit-glib2/pk-console-shared.c:680
+#: ../lib/packagekit-glib2/pk-console-shared.c:681
 msgid "Simulating remove"
 msgstr "Симулирање уклањања"
 
 #. TRANSLATORS: The role of the transaction, in present tense
-#: ../lib/packagekit-glib2/pk-console-shared.c:684
+#: ../lib/packagekit-glib2/pk-console-shared.c:685
 msgid "Simulating update"
 msgstr "Симулирање ажурирања"
 
@@ -1963,19 +1977,13 @@ msgid "Do not install these packages unless you are sure it is safe to do so."
 msgstr ""
 "Немојте инсталирати ове пакете осим ако нисте сигурни да је то безбедно."
 
-#. TRANSLATORS: warn the user that all bets are off
-#: ../src/pk-polkit-action-lookup.c:202
-msgid "Malicious software can damage your computer or cause other harm."
-msgstr ""
-"Злонамеран софтвер може покварити ваш рачунар или изазвати другу штету."
-
 #. TRANSLATORS: too many packages to list each one
-#: ../src/pk-polkit-action-lookup.c:277
+#: ../src/pk-polkit-action-lookup.c:273
 msgid "Many packages"
 msgstr "Много пакета"
 
 #. TRANSLATORS: if the transaction is forced to install only trusted packages
-#: ../src/pk-polkit-action-lookup.c:343
+#: ../src/pk-polkit-action-lookup.c:339
 msgid "Only trusted"
 msgstr "Само поверљиве"
 
@@ -2007,6 +2015,10 @@ msgstr "Опције за отклон грешака"
 msgid "Show debugging options"
 msgstr "Прикажи опције за отклон грешака"
 
+#~ msgid "Malicious software can damage your computer or cause other harm."
+#~ msgstr ""
+#~ "Злонамеран софтвер може покварити ваш рачунар или изазвати другу штету."
+
 #~ msgid "Please restart the application as it is being used."
 #~ msgstr "Неопходно је поновно покретање програма пошто је у употреби."
 
commit e8689b781d92c80c570d8119df901951c72b94ea
Author: Richard Hughes <richard at hughsie.com>
Date:   Tue Mar 16 16:47:29 2010 +0000

    yum: use libzif to get the update lists, although disable this until we can load the update descriptions too

diff --git a/backends/yum/libzif/zif-package-local.c b/backends/yum/libzif/zif-package-local.c
index 0dc1111..d0a5cde 100644
--- a/backends/yum/libzif/zif-package-local.c
+++ b/backends/yum/libzif/zif-package-local.c
@@ -167,7 +167,8 @@ zif_package_local_id_from_header (Header header)
 {
 	gchar *package_id;
 	const gchar *name = NULL;
-	const gchar *epoch = NULL;
+	guint epoch = 0;
+	guint *epoch_p = NULL;
 	const gchar *version = NULL;
 	const gchar *release = NULL;
 	const gchar *arch = NULL;
@@ -177,7 +178,7 @@ zif_package_local_id_from_header (Header header)
 	if (headerGet(header, RPMTAG_NAME, &value, HEADERGET_DEFAULT))
 		name = rpmtdGetString (&value);
 	if (headerGet(header, RPMTAG_EPOCH, &value, HEADERGET_DEFAULT))
-		epoch = rpmtdGetString (&value);
+		epoch_p = rpmtdGetUint32 (&value);
 	if (headerGet(header, RPMTAG_VERSION, &value, HEADERGET_DEFAULT))
 		version = rpmtdGetString (&value);
 	if (headerGet(header, RPMTAG_RELEASE, &value, HEADERGET_DEFAULT))
@@ -185,15 +186,12 @@ zif_package_local_id_from_header (Header header)
 	if (headerGet(header, RPMTAG_ARCH, &value, HEADERGET_DEFAULT))
 		arch = rpmtdGetString (&value);
 
-	/* trivial */
-	if (epoch == NULL) {
-		package_id = zif_package_id_from_nevra (name, NULL, version, release, arch, "installed");
-		goto out;
-	}
+	/* if we got a value, then dereference it */
+	if (epoch_p != NULL)
+		epoch = *epoch_p;
 
-	/* with epoch */
+	/* with or without epoch */
 	package_id = zif_package_id_from_nevra (name, epoch, version, release, arch, "installed");
-out:
 	return package_id;
 }
 
diff --git a/backends/yum/libzif/zif-package-remote.c b/backends/yum/libzif/zif-package-remote.c
index a95ade6..63813ba 100644
--- a/backends/yum/libzif/zif-package-remote.c
+++ b/backends/yum/libzif/zif-package-remote.c
@@ -35,6 +35,7 @@
 #include <stdlib.h>
 
 #include "egg-debug.h"
+#include "egg-string.h"
 
 #include "zif-utils.h"
 #include "zif-package-remote.h"
@@ -76,12 +77,13 @@ zif_package_remote_set_from_repo (ZifPackageRemote *pkg, guint length, gchar **t
 {
 	guint i;
 	const gchar *name = NULL;
-	const gchar *epoch = NULL;
+	guint epoch = 0;
 	const gchar *version = NULL;
 	const gchar *release = NULL;
 	const gchar *arch = NULL;
 	gchar *package_id;
 	ZifString *string;
+	gboolean ret;
 
 	g_return_val_if_fail (ZIF_IS_PACKAGE_REMOTE (pkg), FALSE);
 	g_return_val_if_fail (type != NULL, FALSE);
@@ -93,7 +95,9 @@ zif_package_remote_set_from_repo (ZifPackageRemote *pkg, guint length, gchar **t
 		if (g_strcmp0 (type[i], "name") == 0) {
 			name = data[i];
 		} else if (g_strcmp0 (type[i], "epoch") == 0) {
-			epoch = data[i];
+			ret = egg_strtouint (data[i], &epoch);
+			if (!ret)
+				egg_warning ("failed to parse epoch %s", data[i]);
 		} else if (g_strcmp0 (type[i], "version") == 0) {
 			version = data[i];
 		} else if (g_strcmp0 (type[i], "release") == 0) {
@@ -132,6 +136,7 @@ zif_package_remote_set_from_repo (ZifPackageRemote *pkg, guint length, gchar **t
 			egg_warning ("unrecognized: %s=%s", type[i], data[i]);
 		}
 	}
+
 	zif_package_set_installed (ZIF_PACKAGE (pkg), FALSE);
 	package_id = zif_package_id_from_nevra (name, epoch, version, release, arch, repo_id);
 	zif_package_set_id (ZIF_PACKAGE (pkg), package_id);
diff --git a/backends/yum/libzif/zif-package.c b/backends/yum/libzif/zif-package.c
index a8ae396..d0e9b3f 100644
--- a/backends/yum/libzif/zif-package.c
+++ b/backends/yum/libzif/zif-package.c
@@ -515,6 +515,24 @@ zif_package_get_id (ZifPackage *package)
 }
 
 /**
+ * zif_package_get_name:
+ * @package: the #ZifPackage object
+ *
+ * Gets the package name.
+ *
+ * Return value: the package name.
+ *
+ * Since: 0.0.1
+ **/
+const gchar *
+zif_package_get_name (ZifPackage *package)
+{
+	g_return_val_if_fail (ZIF_IS_PACKAGE (package), NULL);
+	g_return_val_if_fail (package->priv->package_id != NULL, NULL);
+	return package->priv->package_id_split[PK_PACKAGE_ID_NAME];
+}
+
+/**
  * zif_package_get_package_id:
  * @package: the #ZifPackage object
  *
diff --git a/backends/yum/libzif/zif-package.h b/backends/yum/libzif/zif-package.h
index b626e28..69a6319 100644
--- a/backends/yum/libzif/zif-package.h
+++ b/backends/yum/libzif/zif-package.h
@@ -90,6 +90,7 @@ ZifPackage		*zif_package_new		(void);
 
 /* public getters */
 const gchar		*zif_package_get_id		(ZifPackage	*package);
+const gchar		*zif_package_get_name		(ZifPackage	*package);
 ZifString		*zif_package_get_summary	(ZifPackage	*package,
 							 GError		**error);
 ZifString		*zif_package_get_description	(ZifPackage	*package,
diff --git a/backends/yum/libzif/zif-store-remote.c b/backends/yum/libzif/zif-store-remote.c
index 4c2b8cb..138638d 100644
--- a/backends/yum/libzif/zif-store-remote.c
+++ b/backends/yum/libzif/zif-store-remote.c
@@ -2042,6 +2042,50 @@ out:
 }
 
 /**
+ * zif_store_remote_filter_newest:
+ **/
+static void
+zif_store_remote_filter_newest (GPtrArray *packages)
+{
+	guint i;
+	GHashTable *hash;
+	ZifPackage *package;
+	ZifPackage *package_tmp;
+	const gchar *name;
+
+	/* use a hash so it's O(n) not O(n^2) */
+	hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref);
+	for (i=0; i<packages->len; i++) {
+		package = ZIF_PACKAGE (g_ptr_array_index (packages, i));
+		name = zif_package_get_name (package);
+		package_tmp = g_hash_table_lookup (hash, name);
+
+		/* does not already exist */
+		if (package_tmp == NULL) {
+			g_hash_table_insert (hash, g_strdup (name), g_object_ref (package));
+			continue;
+		}
+
+		/* the new package is older */
+		if (zif_package_compare (package, package_tmp) < 0) {
+			egg_debug ("%s is older than %s, so ignoring it",
+				   zif_package_get_id (package), zif_package_get_id (package_tmp));
+			g_ptr_array_remove_index_fast (packages, i);
+			continue;
+		}
+
+		egg_debug ("removing %s", zif_package_get_id (package_tmp));
+		egg_debug ("adding %s", zif_package_get_id (package));
+
+		/* remove the old one */
+		g_hash_table_remove (hash, zif_package_get_name (package_tmp));
+		g_hash_table_insert (hash, g_strdup (name), g_object_ref (package));
+		g_ptr_array_remove_fast (packages, package_tmp);
+	}
+	g_hash_table_unref (hash);
+}
+
+/**
  * zif_store_remote_get_updates:
  **/
 static GPtrArray *
@@ -2105,6 +2149,9 @@ zif_store_remote_get_updates (ZifStore *store, GCancellable *cancellable, ZifCom
 	}
 	egg_debug ("searching with %i packages", packages->len);
 
+	/* remove any packages that are not newest (think kernel) */
+	zif_store_remote_filter_newest (packages);
+
 	/* this section done */
 	zif_completion_done (completion);
 
diff --git a/backends/yum/libzif/zif-utils.c b/backends/yum/libzif/zif-utils.c
index 276f4bf..a384cd8 100644
--- a/backends/yum/libzif/zif-utils.c
+++ b/backends/yum/libzif/zif-utils.c
@@ -146,7 +146,7 @@ zif_list_print_array (GPtrArray *array)
 /**
  * zif_package_id_from_header:
  * @name: The package name, e.g. "hal"
- * @epoch: The package epoch, e.g. "1" or %NULL
+ * @epoch: The package epoch, e.g. 1 or 0 for none.
  * @version: The package version, e.g. "1.0.0"
  * @release: The package release, e.g. "2"
  * @arch: The package architecture, e.g. "i386"
@@ -159,16 +159,16 @@ zif_list_print_array (GPtrArray *array)
  * Since: 0.0.1
  **/
 gchar *
-zif_package_id_from_nevra (const gchar *name, const gchar *epoch, const gchar *version, const gchar *release, const gchar *arch, const gchar *data)
+zif_package_id_from_nevra (const gchar *name, guint epoch, const gchar *version, const gchar *release, const gchar *arch, const gchar *data)
 {
 	gchar *version_compound;
 	gchar *package_id;
 
 	/* do we include an epoch? */
-	if (epoch == NULL || epoch[0] == '0')
+	if (epoch == 0)
 		version_compound = g_strdup_printf ("%s-%s", version, release);
 	else
-		version_compound = g_strdup_printf ("%s:%s-%s", epoch, version, release);
+		version_compound = g_strdup_printf ("%i:%s-%s", epoch, version, release);
 
 	package_id = pk_package_id_build (name, version_compound, arch, data);
 	g_free (version_compound);
@@ -654,16 +654,7 @@ zif_utils_test (EggTest *test)
 	 ****************           NEVRA          ******************
 	 ************************************************************/
 	egg_test_title (test, "no epoch");
-	package_id = zif_package_id_from_nevra ("kernel", NULL, "0.0.1", "1", "i386", "fedora");
-	if (egg_strequal (package_id, "kernel;0.0.1-1;i386;fedora"))
-		egg_test_success (test, NULL);
-	else
-		egg_test_failed (test, "incorrect package_id '%s'", package_id);
-	g_free (package_id);
-
-	/************************************************************/
-	egg_test_title (test, "epoch zero");
-	package_id = zif_package_id_from_nevra ("kernel", "0", "0.0.1", "1", "i386", "fedora");
+	package_id = zif_package_id_from_nevra ("kernel", 0, "0.0.1", "1", "i386", "fedora");
 	if (egg_strequal (package_id, "kernel;0.0.1-1;i386;fedora"))
 		egg_test_success (test, NULL);
 	else
@@ -672,7 +663,7 @@ zif_utils_test (EggTest *test)
 
 	/************************************************************/
 	egg_test_title (test, "epoch value");
-	package_id = zif_package_id_from_nevra ("kernel", "2", "0.0.1", "1", "i386", "fedora");
+	package_id = zif_package_id_from_nevra ("kernel", 2, "0.0.1", "1", "i386", "fedora");
 	if (egg_strequal (package_id, "kernel;2:0.0.1-1;i386;fedora"))
 		egg_test_success (test, NULL);
 	else
diff --git a/backends/yum/libzif/zif-utils.h b/backends/yum/libzif/zif-utils.h
index 3bb474a..239eb11 100644
--- a/backends/yum/libzif/zif-utils.h
+++ b/backends/yum/libzif/zif-utils.h
@@ -49,7 +49,7 @@ void		 zif_debug_crash		(void);
 GQuark		 zif_utils_error_quark		(void);
 void		 zif_list_print_array		(GPtrArray	*array);
 gchar		*zif_package_id_from_nevra	(const gchar	*name,
-						 const gchar	*epoch,
+						 guint		 epoch,
 						 const gchar	*version,
 						 const gchar	*release,
 						 const gchar	*arch,
diff --git a/backends/yum/pk-backend-yum.c b/backends/yum/pk-backend-yum.c
index 112e11f..52ecfe7 100644
--- a/backends/yum/pk-backend-yum.c
+++ b/backends/yum/pk-backend-yum.c
@@ -1419,15 +1419,97 @@ backend_get_requires (PkBackend *backend, PkBitfield filters, gchar **package_id
 }
 
 /**
+ * backend_get_updates_thread:
+ */
+static gboolean
+backend_get_updates_thread (PkBackend *backend)
+{
+	PkBitfield filters = (PkBitfield) pk_backend_get_uint (backend, "filters");
+	GPtrArray *store_array = NULL;
+	ZifCompletion *completion_local;
+	GPtrArray *array = NULL;
+	GPtrArray *result = NULL;
+	gboolean ret;
+	GError *error = NULL;
+	pk_backend_set_status (backend, PK_STATUS_ENUM_QUERY);
+
+	/* get lock */
+	ret = backend_get_lock (backend);
+	if (!ret) {
+		egg_warning ("failed to get lock");
+		goto out;
+	}
+
+	/* set the network state */
+	backend_setup_network (backend);
+
+	/* setup completion */
+	zif_completion_reset (priv->completion);
+	zif_completion_set_number_steps (priv->completion, 2);
+
+	/* get a store_array of remote stores */
+	store_array = zif_store_array_new ();
+	completion_local = zif_completion_get_child (priv->completion);
+	ret = zif_store_array_add_remote_enabled (store_array, priv->cancellable, completion_local, &error);
+	if (!ret) {
+		pk_backend_error_code (backend, PK_ERROR_ENUM_INTERNAL_ERROR, "failed to add enabled stores: %s\n", error->message);
+		g_error_free (error);
+		goto out;
+	}
+
+	/* this section done */
+	zif_completion_done (priv->completion);
+
+	/* get updates */
+	completion_local = zif_completion_get_child (priv->completion);
+	array = zif_store_array_get_updates (store_array, (ZifStoreArrayErrorCb) backend_error_handler_cb, backend,
+					     priv->cancellable, completion_local, &error);
+	if (array == NULL) {
+		pk_backend_error_code (backend, PK_ERROR_ENUM_INTERNAL_ERROR, "failed to get updates: %s\n", error->message);
+		g_error_free (error);
+		goto out;
+	}
+
+	/* this section done */
+	zif_completion_done (priv->completion);
+
+	/* filter */
+	result = backend_filter_package_array (array, filters);
+
+	/* done */
+	pk_backend_set_percentage (backend, 100);
+
+	/* emit */
+	backend_emit_package_array (backend, result);
+
+out:
+	backend_unlock (backend);
+	pk_backend_finished (backend);
+	if (array != NULL)
+		g_ptr_array_unref (array);
+	if (result != NULL)
+		g_ptr_array_unref (result);
+	if (store_array != NULL)
+		g_ptr_array_unref (store_array);
+
+	return TRUE;
+}
+
+/**
  * backend_get_updates:
  */
 static void
 backend_get_updates (PkBackend *backend, PkBitfield filters)
 {
-	gchar *filters_text;
-	filters_text = pk_filter_bitfield_to_string (filters);
-	pk_backend_spawn_helper (priv->spawn,  "yumBackend.py", "get-updates", filters_text, NULL);
-	g_free (filters_text);
+	/* it seems some people are not ready for the awesomeness */
+	if (TRUE || !priv->use_zif) {
+		gchar *filters_text;
+		filters_text = pk_filter_bitfield_to_string (filters);
+		pk_backend_spawn_helper (priv->spawn,  "yumBackend.py", "get-updates", filters_text, NULL);
+		g_free (filters_text);
+		return;
+	}
+	pk_backend_thread_create (backend, backend_get_updates_thread);
 }
 
 /**
commit 5e45e40df3591f3bd0eee3a37607bdc2c34fe79e
Author: Richard Hughes <richard at hughsie.com>
Date:   Tue Mar 16 15:09:12 2010 +0000

    yum: use libzif when doing WhatProvides
    
    No massive speed increase this time, it's been done so we
    have precise control over when the network is accessed

diff --git a/backends/yum/libzif/zif-package-remote.c b/backends/yum/libzif/zif-package-remote.c
index b36322c..a95ade6 100644
--- a/backends/yum/libzif/zif-package-remote.c
+++ b/backends/yum/libzif/zif-package-remote.c
@@ -129,7 +129,7 @@ zif_package_remote_set_from_repo (ZifPackageRemote *pkg, guint length, gchar **t
 			zif_package_set_location_href (ZIF_PACKAGE (pkg), string);
 			zif_string_unref (string);
 		} else {
-			egg_warning ("unregognised: %s=%s", type[i], data[i]);
+			egg_warning ("unrecognized: %s=%s", type[i], data[i]);
 		}
 	}
 	zif_package_set_installed (ZIF_PACKAGE (pkg), FALSE);
diff --git a/backends/yum/libzif/zif-package.c b/backends/yum/libzif/zif-package.c
index 4b47d2a..a8ae396 100644
--- a/backends/yum/libzif/zif-package.c
+++ b/backends/yum/libzif/zif-package.c
@@ -929,7 +929,7 @@ zif_package_get_provides (ZifPackage *package, GError **error)
 	g_return_val_if_fail (error == NULL || *error == NULL, NULL);
 
 	/* not exists */
-	if (package->priv->requires == NULL) {
+	if (package->priv->provides == NULL) {
 		ret = zif_package_ensure_data (package, ZIF_PACKAGE_ENSURE_TYPE_PROVIDES, error);
 		if (!ret)
 			return NULL;
diff --git a/backends/yum/libzif/zif-repo-md-primary.c b/backends/yum/libzif/zif-repo-md-primary.c
index 6d418e7..612cbf7 100644
--- a/backends/yum/libzif/zif-repo-md-primary.c
+++ b/backends/yum/libzif/zif-repo-md-primary.c
@@ -135,7 +135,8 @@ zif_repo_md_primary_sqlite_create_package_cb (void *data, gint argc, gchar **arg
  * zif_repo_md_primary_search:
  **/
 static GPtrArray *
-zif_repo_md_primary_search (ZifRepoMdPrimary *md, const gchar *pred, GCancellable *cancellable, ZifCompletion *completion, GError **error)
+zif_repo_md_primary_search (ZifRepoMdPrimary *md, const gchar *pred,
+			    GCancellable *cancellable, ZifCompletion *completion, GError **error)
 {
 	gchar *statement = NULL;
 	gchar *error_msg = NULL;
@@ -336,6 +337,173 @@ zif_repo_md_primary_search_pkgid (ZifRepoMdPrimary *md, const gchar *search, GCa
 }
 
 /**
+ * zif_repo_md_primary_search_pkgkey:
+ * @md: the #ZifRepoMdPrimary object
+ * @pkgkey: the package key, unique to this sqlite file
+ * @cancellable: a #GCancellable which is used to cancel tasks, or %NULL
+ * @completion: a #ZifCompletion to use for progress reporting
+ * @error: a #GError which is used on failure, or %NULL
+ *
+ * Finds all packages that match the given pkgId.
+ *
+ * Return value: an array of #ZifPackageRemote's
+ *
+ * Since: 0.0.1
+ **/
+GPtrArray *
+zif_repo_md_primary_search_pkgkey (ZifRepoMdPrimary *md, guint pkgkey,
+				   GCancellable *cancellable, ZifCompletion *completion, GError **error)
+{
+	gchar *pred;
+	GPtrArray *array;
+
+	g_return_val_if_fail (ZIF_IS_REPO_MD_PRIMARY (md), NULL);
+	g_return_val_if_fail (error == NULL || *error == NULL, NULL);
+
+	/* search with predicate */
+	pred = g_strdup_printf ("WHERE pkgKey = '%i'", pkgkey);
+	array = zif_repo_md_primary_search (md, pred, cancellable, completion, error);
+	g_free (pred);
+
+	return array;
+}
+
+/**
+ * zif_repo_md_primary_sqlite_pkgkey_cb:
+ **/
+static gint
+zif_repo_md_primary_sqlite_pkgkey_cb (void *data, gint argc, gchar **argv, gchar **col_name)
+{
+	gint i;
+	guint pkgkey;
+	gboolean ret;
+	GPtrArray *array = (GPtrArray *) data;
+
+	/* get the ID */
+	for (i=0; i<argc; i++) {
+		if (g_strcmp0 (col_name[i], "pkgKey") == 0) {
+			ret = egg_strtouint (argv[i], &pkgkey);
+			if (ret)
+				g_ptr_array_add (array, GUINT_TO_POINTER (pkgkey));
+			else
+				egg_warning ("could not parse pkgKey '%s'", argv[i]);
+		} else {
+			egg_warning ("unrecognized: %s=%s", col_name[i], argv[i]);
+		}
+	}
+	return 0;
+}
+
+/**
+ * zif_repo_md_primary_what_provides:
+ * @md: the #ZifRepoMdPrimary object
+ * @search: the provide, e.g. "mimehandler(application/ogg)"
+ * @cancellable: a #GCancellable which is used to cancel tasks, or %NULL
+ * @completion: a #ZifCompletion to use for progress reporting
+ * @error: a #GError which is used on failure, or %NULL
+ *
+ * Finds all packages that match the given provide.
+ *
+ * Return value: an array of #ZifPackageRemote's
+ *
+ * Since: 0.0.1
+ **/
+GPtrArray *
+zif_repo_md_primary_what_provides (ZifRepoMdPrimary *md, const gchar *search,
+				   GCancellable *cancellable, ZifCompletion *completion, GError **error)
+{
+	gchar *statement = NULL;
+	gchar *error_msg = NULL;
+	gint rc;
+	gboolean ret;
+	GError *error_local = NULL;
+	GPtrArray *array = NULL;
+	GPtrArray *array_tmp = NULL;
+	GPtrArray *pkgkey_array = NULL;
+	guint i;
+	guint pkgkey;
+	ZifCompletion *completion_local;
+	ZifCompletion *completion_loop;
+	ZifPackage *package;
+
+	/* setup completion */
+	if (md->priv->loaded)
+		zif_completion_set_number_steps (completion, 2);
+	else
+		zif_completion_set_number_steps (completion, 3);
+
+	/* if not already loaded, load */
+	if (!md->priv->loaded) {
+		completion_local = zif_completion_get_child (completion);
+		ret = zif_repo_md_load (ZIF_REPO_MD (md), cancellable, completion_local, &error_local);
+		if (!ret) {
+			g_set_error (error, ZIF_REPO_MD_ERROR, ZIF_REPO_MD_ERROR_FAILED_TO_LOAD,
+				     "failed to load repo_md_primary file: %s", error_local->message);
+			g_error_free (error_local);
+			goto out;
+		}
+
+		/* this section done */
+		zif_completion_done (completion);
+	}
+
+	/* create data struct we can pass to the callback */
+	pkgkey_array = g_ptr_array_new ();
+	statement = g_strdup_printf ("SELECT pkgKey FROM provides WHERE name = '%s'", search);
+	rc = sqlite3_exec (md->priv->db, statement, zif_repo_md_primary_sqlite_pkgkey_cb, pkgkey_array, &error_msg);
+	if (rc != SQLITE_OK) {
+		g_set_error (error, ZIF_REPO_MD_ERROR, ZIF_REPO_MD_ERROR_BAD_SQL,
+			     "SQL error: %s\n", error_msg);
+		sqlite3_free (error_msg);
+		goto out;
+	}
+
+	/* this section done */
+	zif_completion_done (completion);
+
+	/* output array */
+	array = g_ptr_array_new_with_free_func ((GDestroyNotify) g_object_unref);
+
+	/* resolve each pkgkey to a package */
+	completion_local = zif_completion_get_child (completion);
+	if (pkgkey_array->len > 0)
+		zif_completion_set_number_steps (completion_local, pkgkey_array->len);
+	for (i=0; i<pkgkey_array->len; i++) {
+		pkgkey = GPOINTER_TO_UINT (g_ptr_array_index (pkgkey_array, i));
+
+		/* get packages for pkgKey */
+		completion_loop = zif_completion_get_child (completion_local);
+		array_tmp = zif_repo_md_primary_search_pkgkey (md, pkgkey, cancellable, completion, error);
+		if (array_tmp == NULL) {
+			g_ptr_array_unref (array);
+			array = NULL;
+			goto out;
+		}
+
+		/* check we only got one result */
+		if (array_tmp->len == 0) {
+			egg_warning ("no package for pkgKey %i", pkgkey);
+		} else if (array_tmp->len > 1 || array_tmp->len == 0) {
+			egg_warning ("more than one package for pkgKey %i", pkgkey);
+		} else {
+			package = g_ptr_array_index (array_tmp, 0);
+			g_ptr_array_add (array, g_object_ref (package));
+		}
+
+		/* clear array */
+		g_ptr_array_unref (array_tmp);
+	}
+
+	/* this section done */
+	zif_completion_done (completion);
+out:
+	g_free (statement);
+	if (pkgkey_array != NULL)
+		g_ptr_array_unref (pkgkey_array);
+	return array;
+}
+
+/**
  * zif_repo_md_primary_find_package:
  * @md: the #ZifRepoMdPrimary object
  * @package_id: the PackageId to match
diff --git a/backends/yum/libzif/zif-repo-md-primary.h b/backends/yum/libzif/zif-repo-md-primary.h
index a48df46..8b96ffa 100644
--- a/backends/yum/libzif/zif-repo-md-primary.h
+++ b/backends/yum/libzif/zif-repo-md-primary.h
@@ -82,6 +82,16 @@ GPtrArray	*zif_repo_md_primary_search_pkgid	(ZifRepoMdPrimary	*md,
 							 GCancellable		*cancellable,
 							 ZifCompletion		*completion,
 							 GError			**error);
+GPtrArray	*zif_repo_md_primary_search_pkgkey	(ZifRepoMdPrimary	*md,
+							 guint			 pkgkey,
+							 GCancellable		*cancellable,
+							 ZifCompletion		*completion,
+							 GError			**error);
+GPtrArray	*zif_repo_md_primary_what_provides	(ZifRepoMdPrimary	*md,
+							 const gchar		*search,
+							 GCancellable		*cancellable,
+							 ZifCompletion		*completion,
+							 GError			**error);
 GPtrArray	*zif_repo_md_primary_resolve		(ZifRepoMdPrimary	*md,
 							 const gchar		*search,
 							 GCancellable		*cancellable,
diff --git a/backends/yum/libzif/zif-store-remote.c b/backends/yum/libzif/zif-store-remote.c
index 51285e1..4c2b8cb 100644
--- a/backends/yum/libzif/zif-store-remote.c
+++ b/backends/yum/libzif/zif-store-remote.c
@@ -2158,10 +2158,13 @@ out:
  * zif_store_remote_what_provides:
  **/
 static GPtrArray *
-zif_store_remote_what_provides (ZifStore *store, const gchar *search, GCancellable *cancellable, ZifCompletion *completion, GError **error)
+zif_store_remote_what_provides (ZifStore *store, const gchar *search,
+				GCancellable *cancellable, ZifCompletion *completion, GError **error)
 {
 	gboolean ret;
 	GError *error_local = NULL;
+	GPtrArray *array = NULL;
+	ZifCompletion *completion_local;
 	ZifStoreRemote *remote = ZIF_STORE_REMOTE (store);
 
 	/* not locked */
@@ -2172,19 +2175,36 @@ zif_store_remote_what_provides (ZifStore *store, const gchar *search, GCancellab
 		goto out;
 	}
 
+	/* setup completion */
+	if (remote->priv->loaded_metadata)
+		zif_completion_set_number_steps (completion, 1);
+	else
+		zif_completion_set_number_steps (completion, 2);
+
 	/* load metadata */
 	if (!remote->priv->loaded_metadata) {
-		ret = zif_store_remote_load_metadata (remote, cancellable, completion, &error_local);
+		completion_local = zif_completion_get_child (completion);
+		ret = zif_store_remote_load_metadata (remote, cancellable, completion_local, &error_local);
 		if (!ret) {
 			g_set_error (error, ZIF_STORE_ERROR, ZIF_STORE_ERROR_FAILED,
 				     "failed to load xml: %s", error_local->message);
 			g_error_free (error_local);
 			goto out;
 		}
+
+		/* this section done */
+		zif_completion_done (completion);
 	}
-	//FIXME: load other MD
+
+	/* get details */
+	completion_local = zif_completion_get_child (completion);
+	array = zif_repo_md_primary_what_provides (ZIF_REPO_MD_PRIMARY (remote->priv->md_primary), search,
+						   cancellable, completion_local, error);
+
+	/* this section done */
+	zif_completion_done (completion);
 out:
-	return g_ptr_array_new_with_free_func ((GDestroyNotify) g_object_unref);
+	return array;
 }
 
 /**
diff --git a/backends/yum/pk-backend-yum.c b/backends/yum/pk-backend-yum.c
index eb6d7af..112e11f 100644
--- a/backends/yum/pk-backend-yum.c
+++ b/backends/yum/pk-backend-yum.c
@@ -1968,15 +1968,54 @@ backend_repo_set_data (PkBackend *backend, const gchar *repo_id, const gchar *pa
 static void
 backend_what_provides (PkBackend *backend, PkBitfield filters, PkProvidesEnum provides, gchar **values)
 {
-	gchar *filters_text;
-	gchar *search;
-	const gchar *provides_text;
-	provides_text = pk_provides_enum_to_string (provides);
-	filters_text = pk_filter_bitfield_to_string (filters);
-	search = g_strjoinv ("&", values);
-	pk_backend_spawn_helper (priv->spawn, "yumBackend.py", "what-provides", filters_text, provides_text, search, NULL);
-	g_free (filters_text);
-	g_free (search);
+	guint i;
+	guint len;
+	gchar **search = NULL;
+	GPtrArray *array = NULL;
+	gchar *search_tmp;
+
+	/* it seems some people are not ready for the awesomeness */
+	if (!priv->use_zif) {
+		gchar *filters_text;
+		const gchar *provides_text;
+		provides_text = pk_provides_enum_to_string (provides);
+		filters_text = pk_filter_bitfield_to_string (filters);
+		search_tmp = g_strjoinv ("&", values);
+		pk_backend_spawn_helper (priv->spawn, "yumBackend.py", "what-provides", filters_text, provides_text, search_tmp, NULL);
+		g_free (filters_text);
+		g_free (search_tmp);
+		return;
+	}
+
+	/* iter on each provide string, and wrap it with the fedora prefix */
+	len = g_strv_length (values);
+	array = g_ptr_array_new_with_free_func (g_free);
+	for (i=0; i<len; i++) {
+		if (provides == PK_PROVIDES_ENUM_CODEC) {
+			g_ptr_array_add (array, g_strdup_printf ("gstreamer0.10(%s)", values[i]));
+		} else if (provides == PK_PROVIDES_ENUM_FONT) {
+			g_ptr_array_add (array, g_strdup_printf ("font(%s)", values[i]));
+		} else if (provides == PK_PROVIDES_ENUM_MIMETYPE) {
+			g_ptr_array_add (array, g_strdup_printf ("mimehandler(%s)", values[i]));
+		} else if (provides == PK_PROVIDES_ENUM_POSTSCRIPT_DRIVER) {
+			g_ptr_array_add (array, g_strdup_printf ("postscriptdriver(%s)", values[i]));
+		} else if (provides == PK_PROVIDES_ENUM_ANY) {
+			g_ptr_array_add (array, g_strdup_printf ("gstreamer0.10(%s)", values[i]));
+			g_ptr_array_add (array, g_strdup_printf ("font(%s)", values[i]));
+			g_ptr_array_add (array, g_strdup_printf ("mimehandler(%s)", values[i]));
+			g_ptr_array_add (array, g_strdup_printf ("postscriptdriver(%s)", values[i]));
+		} else {
+			pk_backend_error_code (backend, PK_ERROR_ENUM_PROVIDE_TYPE_NOT_SUPPORTED,
+					       "provide type %s not supported", pk_provides_enum_to_string (provides));
+		}
+	}
+
+	/* set the search terms and run */
+	search = pk_ptr_array_to_strv (array);
+	pk_backend_set_strv (backend, "search", search);
+	pk_backend_thread_create (backend, backend_search_thread);
+	g_strfreev (search);
+	g_ptr_array_unref (array);
 }
 
 /**
commit 07e28edd2af6768aeebc9346cffb16bd8d4c8e2a
Author: Richard Hughes <richard at hughsie.com>
Date:   Tue Mar 16 15:07:08 2010 +0000

    trivial: add one more error enum, PK_ERROR_ENUM_PROVIDE_TYPE_NOT_SUPPORTED

diff --git a/lib/packagekit-glib2/pk-enum.c b/lib/packagekit-glib2/pk-enum.c
index 475d5f0..9d0e678 100644
--- a/lib/packagekit-glib2/pk-enum.c
+++ b/lib/packagekit-glib2/pk-enum.c
@@ -193,6 +193,7 @@ static const PkEnumMatch enum_error[] = {
 	{PK_ERROR_ENUM_PACKAGE_FAILED_TO_REMOVE, "package-failed-to-remove"},
 	{PK_ERROR_ENUM_UPDATE_FAILED_DUE_TO_RUNNING_PROCESS, "failed-due-to-running-process"},
 	{PK_ERROR_ENUM_PACKAGE_DATABASE_CHANGED, "package-database-changed"},
+	{PK_ERROR_ENUM_PROVIDE_TYPE_NOT_SUPPORTED, "provide-type-not-supported"},
 	{0, NULL}
 };
 
diff --git a/lib/packagekit-glib2/pk-enum.h b/lib/packagekit-glib2/pk-enum.h
index 9fdb6ad..72fbea9 100644
--- a/lib/packagekit-glib2/pk-enum.h
+++ b/lib/packagekit-glib2/pk-enum.h
@@ -359,6 +359,7 @@ typedef enum {
 	PK_ERROR_ENUM_PACKAGE_FAILED_TO_REMOVE,
 	PK_ERROR_ENUM_UPDATE_FAILED_DUE_TO_RUNNING_PROCESS,
 	PK_ERROR_ENUM_PACKAGE_DATABASE_CHANGED,
+	PK_ERROR_ENUM_PROVIDE_TYPE_NOT_SUPPORTED,
 	PK_ERROR_ENUM_LAST
 } PkErrorEnum;
 
commit bc014c395cb23c1a6b4b201dc7b8f57b096d8c4b
Author: Richard Hughes <richard at hughsie.com>
Date:   Tue Mar 16 15:03:24 2010 +0000

    trivial: allow PkStore values to be changed by the backend if required

diff --git a/src/pk-store.c b/src/pk-store.c
index e460732..9b39c1f 100644
--- a/src/pk-store.c
+++ b/src/pk-store.c
@@ -48,7 +48,8 @@ G_DEFINE_TYPE (PkStore, pk_store, G_TYPE_OBJECT)
 gboolean
 pk_store_set_string (PkStore *store, const gchar *key, const gchar *data)
 {
-	gpointer value;
+	gboolean ret;
+
 	g_return_val_if_fail (PK_IS_STORE (store), FALSE);
 	g_return_val_if_fail (key != NULL, FALSE);
 
@@ -57,11 +58,10 @@ pk_store_set_string (PkStore *store, const gchar *key, const gchar *data)
 		return FALSE;
 
 	/* does already exist? */
-	value = g_hash_table_lookup (store->priv->hash_string, (gpointer) key);
-	if (value != NULL) {
-		egg_warning ("already set data for %s", key);
-		return FALSE;
-	}
+	ret = g_hash_table_remove (store->priv->hash_string, key);
+	if (ret)
+		egg_debug ("already set data for %s, so removing", key);
+
 	egg_debug ("saving '%s' for %s", data, key);
 	g_hash_table_insert (store->priv->hash_string, g_strdup (key), (gpointer) g_strdup (data));
 	return TRUE;
@@ -73,7 +73,8 @@ pk_store_set_string (PkStore *store, const gchar *key, const gchar *data)
 gboolean
 pk_store_set_strv (PkStore *store, const gchar *key, gchar **data)
 {
-	gpointer value;
+	gboolean ret;
+
 	g_return_val_if_fail (PK_IS_STORE (store), FALSE);
 	g_return_val_if_fail (key != NULL, FALSE);
 
@@ -82,11 +83,10 @@ pk_store_set_strv (PkStore *store, const gchar *key, gchar **data)
 		return FALSE;
 
 	/* does already exist? */
-	value = g_hash_table_lookup (store->priv->hash_strv, (gpointer) key);
-	if (value != NULL) {
-		egg_warning ("already set data for %s", key);
-		return FALSE;
-	}
+	ret = g_hash_table_remove (store->priv->hash_strv, key);
+	if (ret)
+		egg_debug ("already set data for %s, so removing", key);
+
 	egg_debug ("saving %p for %s", data, key);
 	g_hash_table_insert (store->priv->hash_strv, g_strdup (key), (gpointer) g_strdupv (data));
 	return TRUE;
@@ -98,7 +98,8 @@ pk_store_set_strv (PkStore *store, const gchar *key, gchar **data)
 gboolean
 pk_store_set_array (PkStore *store, const gchar *key, GPtrArray *data)
 {
-	gpointer value;
+	gboolean ret;
+
 	g_return_val_if_fail (PK_IS_STORE (store), FALSE);
 	g_return_val_if_fail (key != NULL, FALSE);
 
@@ -107,11 +108,10 @@ pk_store_set_array (PkStore *store, const gchar *key, GPtrArray *data)
 		return FALSE;
 
 	/* does already exist? */
-	value = g_hash_table_lookup (store->priv->hash_array, (gpointer) key);
-	if (value != NULL) {
-		egg_warning ("already set data for %s", key);
-		return FALSE;
-	}
+	ret = g_hash_table_remove (store->priv->hash_array, key);
+	if (ret)
+		egg_debug ("already set data for %s, so removing", key);
+
 	egg_debug ("saving %p for %s", data, key);
 	g_hash_table_insert (store->priv->hash_array, g_strdup (key), (gpointer) data);
 	return TRUE;
@@ -123,16 +123,16 @@ pk_store_set_array (PkStore *store, const gchar *key, GPtrArray *data)
 gboolean
 pk_store_set_uint (PkStore *store, const gchar *key, guint data)
 {
-	gpointer value;
+	gboolean ret;
+
 	g_return_val_if_fail (PK_IS_STORE (store), FALSE);
 	g_return_val_if_fail (key != NULL, FALSE);
 
 	/* does already exist? */
-	value = g_hash_table_lookup (store->priv->hash_pointer, (gpointer) key);
-	if (value != NULL) {
-		egg_warning ("already set data for %s", key);
-		return FALSE;
-	}
+	ret = g_hash_table_remove (store->priv->hash_pointer, key);
+	if (ret)
+		egg_debug ("already set data for %s, so removing", key);
+
 	egg_debug ("saving %i for %s", data, key);
 	g_hash_table_insert (store->priv->hash_pointer, g_strdup (key), GINT_TO_POINTER (data+1));
 	return TRUE;
@@ -144,16 +144,16 @@ pk_store_set_uint (PkStore *store, const gchar *key, guint data)
 gboolean
 pk_store_set_bool (PkStore *store, const gchar *key, gboolean data)
 {
-	gpointer value;
+	gboolean ret;
+
 	g_return_val_if_fail (PK_IS_STORE (store), FALSE);
 	g_return_val_if_fail (key != NULL, FALSE);
 
 	/* does already exist? */
-	value = g_hash_table_lookup (store->priv->hash_pointer, (gpointer) key);
-	if (value != NULL) {
-		egg_warning ("already set data for %s", key);
-		return FALSE;
-	}
+	ret = g_hash_table_remove (store->priv->hash_pointer, key);
+	if (ret)
+		egg_debug ("already set data for %s, so removing", key);
+
 	egg_debug ("saving %i for %s", data, key);
 	g_hash_table_insert (store->priv->hash_pointer, g_strdup (key), GINT_TO_POINTER (data+1));
 	return TRUE;
@@ -165,17 +165,17 @@ pk_store_set_bool (PkStore *store, const gchar *key, gboolean data)
 gboolean
 pk_store_set_pointer (PkStore *store, const gchar *key, gpointer data)
 {
-	gpointer value;
+	gboolean ret;
+
 	g_return_val_if_fail (PK_IS_STORE (store), FALSE);
 	g_return_val_if_fail (key != NULL, FALSE);
 	g_return_val_if_fail (data != NULL, FALSE);
 
 	/* does already exist? */
-	value = g_hash_table_lookup (store->priv->hash_pointer, (gpointer) key);
-	if (value != NULL) {
-		egg_warning ("already set data for %s", key);
-		return FALSE;
-	}
+	ret = g_hash_table_remove (store->priv->hash_pointer, key);
+	if (ret)
+		egg_debug ("already set data for %s, so removing", key);
+
 	egg_debug ("saving %p for %s", data, key);
 	g_hash_table_insert (store->priv->hash_pointer, g_strdup (key), GINT_TO_POINTER(GPOINTER_TO_INT(data)+1));
 	return TRUE;
commit 043b776ac73ec527b49dbc1337829c0f09201703
Author: Richard Hughes <richard at hughsie.com>
Date:   Tue Mar 16 13:23:13 2010 +0000

    yum: if we failed to resolve deps in a simulate pass, then don't just return empty package list

diff --git a/backends/yum/yumBackend.py b/backends/yum/yumBackend.py
index e2a7928..42dc70c 100755
--- a/backends/yum/yumBackend.py
+++ b/backends/yum/yumBackend.py
@@ -2074,6 +2074,14 @@ class PackageKitYumBackend(PackageKitBaseBackend, PackagekitPackage):
                 retmsg = 'package could not be removed, as other packages depend on it'
                 raise PkError(ERROR_DEP_RESOLUTION_FAILED, retmsg)
 
+        # we did not succeed
+        if rc != 2:
+            if message.find ("is needed by") != -1:
+                raise PkError(ERROR_DEP_RESOLUTION_FAILED, message)
+            if message.find ("empty transaction") != -1:
+                raise PkError(ERROR_NO_PACKAGES_TO_UPDATE, message)
+            raise PkError(ERROR_TRANSACTION_ERROR, message)
+
         # abort now we have the package list
         if only_simulate:
             package_list = []
@@ -2087,14 +2095,6 @@ class PackageKitYumBackend(PackageKitBaseBackend, PackagekitPackage):
             self.percentage(100)
             return
 
-        # we did not succeed
-        if rc != 2:
-            if message.find ("is needed by") != -1:
-                raise PkError(ERROR_DEP_RESOLUTION_FAILED, message)
-            if message.find ("empty transaction") != -1:
-                raise PkError(ERROR_NO_PACKAGES_TO_UPDATE, message)
-            raise PkError(ERROR_TRANSACTION_ERROR, message)
-
         try:
             rpmDisplay = PackageKitCallback(self)
             callback = ProcessTransPackageKitCallback(self)
commit 6adcc075d192bbc861488aeab95ae2b398824e63
Author: ruigo <ruigo at fedoraproject.org>
Date:   Tue Mar 16 14:18:44 2010 +0000

    l10n: Updates to Portuguese (pt) translation
    
    Transmitted-via: Transifex (translate.fedoraproject.org)

diff --git a/po/pt.po b/po/pt.po
index 7279652..c378ba8 100644
--- a/po/pt.po
+++ b/po/pt.po
@@ -3,10 +3,10 @@ msgid ""
 msgstr ""
 "Project-Id-Version: packagekit\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2010-02-23 11:23+0000\n"
-"PO-Revision-Date: 2010-02-23 12:21+0100\n"
+"POT-Creation-Date: 2010-03-16 14:09+0000\n"
+"PO-Revision-Date: 2010-03-16 14:16+0100\n"
 "Last-Translator: Rui Gouveia <rui.gouveia at gmail.com>\n"
-"Language-Team: fedora-trans-pt at redhat.com\n"
+"Language-Team: trans-pt at fedoraproject.org\n"
 "Language: pt\n"
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
@@ -198,7 +198,7 @@ msgstr "Emitido"
 
 #. TRANSLATORS: details about the update, date the update was updated
 #. TRANSLATORS: The action of the package, in past tense
-#: ../client/pk-console.c:389 ../lib/packagekit-glib2/pk-console-shared.c:510
+#: ../client/pk-console.c:389 ../lib/packagekit-glib2/pk-console-shared.c:511
 msgid "Updated"
 msgstr "Actualizado"
 
@@ -289,19 +289,23 @@ msgstr "A transacção falhou"
 msgid "There are no updates available at this time."
 msgstr "Não existem atualizações disponíveis neste momento."
 
+#: ../client/pk-console.c:749
+msgid "There are no upgrades available at this time."
+msgstr "Não existem atualizações disponíveis neste momento."
+
 #. TRANSLATORS: a package needs to restart their system
-#: ../client/pk-console.c:814
+#: ../client/pk-console.c:816
 msgid "Please restart the computer to complete the update."
 msgstr "Por favor, reinicie o computador para completar a actualização."
 
 #. TRANSLATORS: a package needs to restart the session
-#: ../client/pk-console.c:817
+#: ../client/pk-console.c:819
 msgid "Please logout and login to complete the update."
 msgstr ""
 "Por favor, termine e volte a iniciar a sessão para completar a actualização."
 
 #. TRANSLATORS: a package needs to restart their system (due to security)
-#: ../client/pk-console.c:820
+#: ../client/pk-console.c:822
 msgid ""
 "Please restart the computer to complete the update as important security "
 "updates have been installed."
@@ -310,7 +314,7 @@ msgstr ""
 "instaladas importantes actualizações de segurança."
 
 #. TRANSLATORS: a package needs to restart the session (due to security)
-#: ../client/pk-console.c:823
+#: ../client/pk-console.c:825
 msgid ""
 "Please logout and login to complete the update as important security updates "
 "have been installed."
@@ -319,7 +323,7 @@ msgstr ""
 "pois foram instaladas importantes actualizações de segurança."
 
 #. TRANSLATORS: The user used 'pkcon install dave.rpm' rather than 'pkcon install-local dave.rpm'
-#: ../client/pk-console.c:849
+#: ../client/pk-console.c:851
 #, c-format
 msgid ""
 "Extected package name, actually got file. Try using 'pkcon install-local %s' "
@@ -329,19 +333,19 @@ msgstr ""
 "utilizar 'pkcon install-local %s'."
 
 #. TRANSLATORS: There was an error getting the list of files for the package. The detailed error follows
-#: ../client/pk-console.c:857
+#: ../client/pk-console.c:859
 #, c-format
 msgid "This tool could not find any available package: %s"
 msgstr "Esta ferramenta não conseguiu encontrar nenhum pacote disponível: %s"
 
 #. TRANSLATORS: There was an error getting the list of files for the package. The detailed error follows
-#: ../client/pk-console.c:885
+#: ../client/pk-console.c:887
 #, c-format
 msgid "This tool could not find the installed package: %s"
 msgstr "Esta ferramenta não conseguiu encontrar o pacote instalado: %s"
 
 #. TRANSLATORS: There was an error getting the list of files for the package. The detailed error follows
-#: ../client/pk-console.c:913 ../client/pk-console.c:941
+#: ../client/pk-console.c:915 ../client/pk-console.c:943
 #, c-format
 msgid "This tool could not find the package: %s"
 msgstr "Esta ferramenta não conseguiu encontrar o pacote: %s"
@@ -350,185 +354,184 @@ msgstr "Esta ferramenta não conseguiu encontrar o pacote: %s"
 #. TRANSLATORS: There was an error getting the dependencies for the package. The detailed error follows
 #. TRANSLATORS: There was an error getting the details about the package. The detailed error follows
 #. TRANSLATORS: The package name was not found in any software sources. The detailed error follows
-#: ../client/pk-console.c:969 ../client/pk-console.c:997
-#: ../client/pk-console.c:1025 ../client/pk-console.c:1053
-#: ../client/pk-console.c:1081
+#: ../client/pk-console.c:971 ../client/pk-console.c:999
+#: ../client/pk-console.c:1027 ../client/pk-console.c:1055
+#: ../client/pk-console.c:1083
 #, c-format
 msgid "This tool could not find all the packages: %s"
 msgstr "Esta ferramenta não conseguiu encontrar todos os pacotes: %s"
 
 #. TRANSLATORS: This is when the daemon crashed, and we are up shit creek without a paddle
-#: ../client/pk-console.c:1110
+#: ../client/pk-console.c:1112
 msgid "The daemon crashed mid-transaction!"
 msgstr "O daemon morreu a meio de uma transacção!"
 
 #. TRANSLATORS: This is the header to the --help menu
-#: ../client/pk-console.c:1144
+#: ../client/pk-console.c:1146
 msgid "PackageKit Console Interface"
 msgstr "Consola do PackaheKit"
 
 #. these are commands we can use with pkcon
-#: ../client/pk-console.c:1146
+#: ../client/pk-console.c:1148
 msgid "Subcommands:"
 msgstr "Sub-comandos:"
 
 #. TRANSLATORS: we keep a database updated with the time that an action was last executed
-#: ../client/pk-console.c:1225
+#: ../client/pk-console.c:1227
 msgid "Failed to get the time since this action was last completed"
 msgstr ""
 "Não foi possível obter a hora da última vez que esta acção foi concluída"
 
 #. TRANSLATORS: command line argument, just show the version string
-#: ../client/pk-console.c:1261 ../client/pk-monitor.c:306
+#: ../client/pk-console.c:1263 ../client/pk-monitor.c:306
 msgid "Show the program version and exit"
 msgstr "Mostrar a versão da aplicação e terminar"
 
 #. TRANSLATORS: command line argument, use a filter to narrow down results
-#: ../client/pk-console.c:1264
+#: ../client/pk-console.c:1266
 msgid "Set the filter, e.g. installed"
 msgstr "Configurar o filtro, exemplo, instalado"
 
 #. TRANSLATORS: command line argument, work asynchronously
-#: ../client/pk-console.c:1267
+#: ../client/pk-console.c:1269
 msgid "Exit without waiting for actions to complete"
 msgstr "Sair sem esperar que as acções completem"
 
 #. command line argument, do we ask questions
-#: ../client/pk-console.c:1270
+#: ../client/pk-console.c:1272
 #: ../contrib/debuginfo-install/pk-debuginfo-install.c:527
 msgid "Install the packages without asking for confirmation"
 msgstr "Instalar os pacotes sem pedir por confirmação"
 
 #. TRANSLATORS: command line argument, this command is not a priority
-#: ../client/pk-console.c:1273
+#: ../client/pk-console.c:1275
 msgid "Run the command using idle network bandwidth and also using less power"
 msgstr ""
 "Executar o comando utilizando períodos de inactividade da rede e também "
 "utilizando menos energia"
 
 #. TRANSLATORS: command line argument, just output without fancy formatting
-#: ../client/pk-console.c:1276
+#: ../client/pk-console.c:1278
 msgid ""
-"Print to screen a machine readable output, rather than using animated "
-"widgets"
+"Print to screen a machine readable output, rather than using animated widgets"
 msgstr ""
 "Escrever no ecrã o resultado legível, ao invés de utilizar objectos animados"
 
 #. TRANSLATORS: we failed to contact the daemon
-#: ../client/pk-console.c:1298
+#: ../client/pk-console.c:1300
 msgid "Failed to contact PackageKit"
 msgstr "Falhou o contacto com o PackageKit"
 
 #. TRANSLATORS: The user specified an incorrect filter
-#: ../client/pk-console.c:1356
+#: ../client/pk-console.c:1358
 msgid "The filter specified was invalid"
 msgstr "O filtro especificado era inválido"
 
 #. TRANSLATORS: a search type can be name, details, file, etc
-#: ../client/pk-console.c:1375
+#: ../client/pk-console.c:1377
 msgid "A search type is required, e.g. name"
 msgstr "Um tipo de pesquisa é necessário. Por exemplo, nome"
 
 #. TRANSLATORS: the user needs to provide a search term
-#: ../client/pk-console.c:1382 ../client/pk-console.c:1394
-#: ../client/pk-console.c:1406 ../client/pk-console.c:1418
+#: ../client/pk-console.c:1384 ../client/pk-console.c:1396
+#: ../client/pk-console.c:1408 ../client/pk-console.c:1420
 msgid "A search term is required"
 msgstr "Um termo de pesquisa é necessário"
 
 #. TRANSLATORS: the search type was provided, but invalid
-#: ../client/pk-console.c:1428
+#: ../client/pk-console.c:1430
 msgid "Invalid search type"
 msgstr "Tipo de pesquisa inválida"
 
 #. TRANSLATORS: the user did not specify what they wanted to install
-#: ../client/pk-console.c:1434
+#: ../client/pk-console.c:1436
 msgid "A package name to install is required"
 msgstr "É necessário indicar um nome de pacote a instalar"
 
 #. TRANSLATORS: the user did not specify what they wanted to install
-#: ../client/pk-console.c:1443
+#: ../client/pk-console.c:1445
 msgid "A filename to install is required"
 msgstr "É necessário um nome de ficheiro a instalar"
 
 #. TRANSLATORS: geeky error, 99.9999% of users won't see this
-#: ../client/pk-console.c:1455
+#: ../client/pk-console.c:1457
 msgid "A type, key_id and package_id are required"
 msgstr "São necessários um tipo, id de chave e id de pacote"
 
 #. TRANSLATORS: the user did not specify what they wanted to remove
-#: ../client/pk-console.c:1466
+#: ../client/pk-console.c:1468
 msgid "A package name to remove is required"
 msgstr "É necessário um nome de pacote para remover"
 
 #. TRANSLATORS: the user did not specify anything about what to download or where
-#: ../client/pk-console.c:1475
+#: ../client/pk-console.c:1477
 msgid "A destination directory and the package names to download are required"
 msgstr ""
 "São necessários uma directoria de destino assim como os nomes dos pacotes a "
 "transferir"
 
 #. TRANSLATORS: the directory does not exist, so we can't continue
-#: ../client/pk-console.c:1482
+#: ../client/pk-console.c:1484
 msgid "Directory not found"
 msgstr "Directório não encontrado"
 
 #. TRANSLATORS: geeky error, 99.9999% of users won't see this
-#: ../client/pk-console.c:1491
+#: ../client/pk-console.c:1493
 msgid "A licence identifier (eula-id) is required"
 msgstr "É necessário um identificador de licença (eula-id)"
 
 #. TRANSLATORS: geeky error, 99.9999% of users won't see this
-#: ../client/pk-console.c:1502
+#: ../client/pk-console.c:1504
 msgid "A transaction identifier (tid) is required"
 msgstr "É necessário um identificador de transacção (tid)"
 
 #. TRANSLATORS: The user did not specify a package name
-#: ../client/pk-console.c:1523
+#: ../client/pk-console.c:1525
 msgid "A package name to resolve is required"
 msgstr "É necessário indicar um nome de pacote"
 
 #. TRANSLATORS: The user did not specify a repository (software source) name
-#: ../client/pk-console.c:1534 ../client/pk-console.c:1545
+#: ../client/pk-console.c:1536 ../client/pk-console.c:1547
 msgid "A repository name is required"
 msgstr "É obrigatório um nome de repositório"
 
 #. TRANSLATORS: The user didn't provide any data
-#: ../client/pk-console.c:1556
+#: ../client/pk-console.c:1558
 msgid "A repo name, parameter and value are required"
 msgstr "É necessário indicar um repositório, parâmetro e valor"
 
 #. TRANSLATORS: The user didn't specify what action to use
-#: ../client/pk-console.c:1573
+#: ../client/pk-console.c:1575
 msgid "An action, e.g. 'update-system' is required"
 msgstr "É necessária uma acção, por exemplo 'update-system'"
 
 #. TRANSLATORS: The user specified an invalid action
-#: ../client/pk-console.c:1580
+#: ../client/pk-console.c:1582
 msgid "A correct role is required"
 msgstr "É necessária uma função correcta"
 
 #. TRANSLATORS: The user did not provide a package name
 #. TRANSLATORS: This is when the user fails to supply the package name
-#: ../client/pk-console.c:1590 ../client/pk-console.c:1605
-#: ../client/pk-console.c:1614 ../client/pk-console.c:1634
-#: ../client/pk-console.c:1643 ../client/pk-generate-pack.c:316
+#: ../client/pk-console.c:1592 ../client/pk-console.c:1607
+#: ../client/pk-console.c:1616 ../client/pk-console.c:1636
+#: ../client/pk-console.c:1645 ../client/pk-generate-pack.c:316
 msgid "A package name is required"
 msgstr "É obrigatório um nome de pacote"
 
 #. TRANSLATORS: each package "provides" certain things, e.g. mime(gstreamer-decoder-mp3), the user didn't specify it
-#: ../client/pk-console.c:1623
+#: ../client/pk-console.c:1625
 msgid "A package provide string is required"
 msgstr ""
 "É necessário especificar a string que define o que o pacote disponibiliza"
 
 #. TRANSLATORS: The user tried to use an unsupported option on the command line
-#: ../client/pk-console.c:1703
+#: ../client/pk-console.c:1705
 #, c-format
 msgid "Option '%s' is not supported"
 msgstr "A opção '%s' não é suportada"
 
 #. TRANSLATORS: Generic failure of what they asked to do
-#: ../client/pk-console.c:1713
+#: ../client/pk-console.c:1715
 msgid "Command failed"
 msgstr "Comando falhou"
 
@@ -969,7 +972,7 @@ msgstr "No modo de simulação não se instalam pacotes"
 #. TRANSLATORS: we are now installing the debuginfo packages we found earlier
 #. TRANSLATORS: transaction state, installing packages
 #: ../contrib/debuginfo-install/pk-debuginfo-install.c:862
-#: ../lib/packagekit-glib2/pk-console-shared.c:282
+#: ../lib/packagekit-glib2/pk-console-shared.c:283
 #, c-format
 msgid "Installing packages"
 msgstr "A instalar pacotes"
@@ -1106,7 +1109,7 @@ msgid "Please enter a number from 1 to %i: "
 msgstr "Por favor insira um número de 1 a %i: "
 
 #. TRANSLATORS: more than one package could be found that matched, to follow is a list of possible packages
-#: ../lib/packagekit-glib2/pk-console-shared.c:183
+#: ../lib/packagekit-glib2/pk-console-shared.c:185
 msgid "More than one package matches:"
 msgstr "Mais do que um pacote corresponde:"
 
@@ -1116,448 +1119,448 @@ msgid "Please choose the correct package: "
 msgstr "Por favor, escolha o pacote correcto:"
 
 #. TRANSLATORS: This is when the transaction status is not known
-#: ../lib/packagekit-glib2/pk-console-shared.c:250
+#: ../lib/packagekit-glib2/pk-console-shared.c:251
 msgid "Unknown state"
 msgstr "Estado desconhecido"
 
 #. TRANSLATORS: transaction state, the daemon is in the process of starting
-#: ../lib/packagekit-glib2/pk-console-shared.c:254
+#: ../lib/packagekit-glib2/pk-console-shared.c:255
 msgid "Starting"
 msgstr "A iniciar"
 
 #. TRANSLATORS: transaction state, the transaction is waiting for another to complete
-#: ../lib/packagekit-glib2/pk-console-shared.c:258
+#: ../lib/packagekit-glib2/pk-console-shared.c:259
 msgid "Waiting in queue"
 msgstr "A aguardar na fila"
 
 #. TRANSLATORS: transaction state, just started
-#: ../lib/packagekit-glib2/pk-console-shared.c:262
+#: ../lib/packagekit-glib2/pk-console-shared.c:263
 msgid "Running"
 msgstr "A executar"
 
 #. TRANSLATORS: transaction state, is querying data
-#: ../lib/packagekit-glib2/pk-console-shared.c:266
+#: ../lib/packagekit-glib2/pk-console-shared.c:267
 msgid "Querying"
 msgstr "A consultar"
 
 #. TRANSLATORS: transaction state, getting data from a server
-#: ../lib/packagekit-glib2/pk-console-shared.c:270
+#: ../lib/packagekit-glib2/pk-console-shared.c:271
 msgid "Getting information"
 msgstr "A obter informação"
 
 #. TRANSLATORS: transaction state, removing packages
-#: ../lib/packagekit-glib2/pk-console-shared.c:274
+#: ../lib/packagekit-glib2/pk-console-shared.c:275
 msgid "Removing packages"
 msgstr "A remover pacotes"
 
 #. TRANSLATORS: transaction state, downloading package files
 #. TRANSLATORS: The role of the transaction, in present tense
-#: ../lib/packagekit-glib2/pk-console-shared.c:278
-#: ../lib/packagekit-glib2/pk-console-shared.c:656
+#: ../lib/packagekit-glib2/pk-console-shared.c:279
+#: ../lib/packagekit-glib2/pk-console-shared.c:657
 msgid "Downloading packages"
 msgstr "A transferir pacotes"
 
 #. TRANSLATORS: transaction state, refreshing internal lists
-#: ../lib/packagekit-glib2/pk-console-shared.c:286
+#: ../lib/packagekit-glib2/pk-console-shared.c:287
 msgid "Refreshing software list"
 msgstr "A actualizar a lista de software"
 
 #. TRANSLATORS: transaction state, installing updates
-#: ../lib/packagekit-glib2/pk-console-shared.c:290
+#: ../lib/packagekit-glib2/pk-console-shared.c:291
 msgid "Installing updates"
 msgstr "A instalar actualizações"
 
 #. TRANSLATORS: transaction state, removing old packages, and cleaning config files
-#: ../lib/packagekit-glib2/pk-console-shared.c:294
+#: ../lib/packagekit-glib2/pk-console-shared.c:295
 msgid "Cleaning up packages"
 msgstr "A limpar pacotes"
 
 #. TRANSLATORS: transaction state, obsoleting old packages
-#: ../lib/packagekit-glib2/pk-console-shared.c:298
+#: ../lib/packagekit-glib2/pk-console-shared.c:299
 msgid "Obsoleting packages"
 msgstr "A tornar pacotes obsoletos"
 
 #. TRANSLATORS: transaction state, checking the transaction before we do it
-#: ../lib/packagekit-glib2/pk-console-shared.c:302
+#: ../lib/packagekit-glib2/pk-console-shared.c:303
 msgid "Resolving dependencies"
 msgstr "A resolver dependências"
 
 #. TRANSLATORS: transaction state, checking if we have all the security keys for the operation
-#: ../lib/packagekit-glib2/pk-console-shared.c:306
+#: ../lib/packagekit-glib2/pk-console-shared.c:307
 msgid "Checking signatures"
 msgstr "A verificar assinaturas"
 
 #. TRANSLATORS: transaction state, when we return to a previous system state
 #. TRANSLATORS: The role of the transaction, in present tense
-#: ../lib/packagekit-glib2/pk-console-shared.c:310
-#: ../lib/packagekit-glib2/pk-console-shared.c:616
+#: ../lib/packagekit-glib2/pk-console-shared.c:311
+#: ../lib/packagekit-glib2/pk-console-shared.c:617
 msgid "Rolling back"
 msgstr "A reverter"
 
 #. TRANSLATORS: transaction state, when we're doing a test transaction
-#: ../lib/packagekit-glib2/pk-console-shared.c:314
+#: ../lib/packagekit-glib2/pk-console-shared.c:315
 msgid "Testing changes"
 msgstr "A testar alterações"
 
 #. TRANSLATORS: transaction state, when we're writing to the system package database
-#: ../lib/packagekit-glib2/pk-console-shared.c:318
+#: ../lib/packagekit-glib2/pk-console-shared.c:319
 msgid "Committing changes"
 msgstr "A aplicar alterações"
 
 #. TRANSLATORS: transaction state, requesting data from a server
-#: ../lib/packagekit-glib2/pk-console-shared.c:322
+#: ../lib/packagekit-glib2/pk-console-shared.c:323
 msgid "Requesting data"
 msgstr "A pedir dados"
 
 #. TRANSLATORS: transaction state, all done!
-#: ../lib/packagekit-glib2/pk-console-shared.c:326
+#: ../lib/packagekit-glib2/pk-console-shared.c:327
 msgid "Finished"
 msgstr "Terminado"
 
 #. TRANSLATORS: transaction state, in the process of cancelling
-#: ../lib/packagekit-glib2/pk-console-shared.c:330
+#: ../lib/packagekit-glib2/pk-console-shared.c:331
 msgid "Cancelling"
 msgstr "A cancelar"
 
 #. TRANSLATORS: transaction state, downloading metadata
-#: ../lib/packagekit-glib2/pk-console-shared.c:334
+#: ../lib/packagekit-glib2/pk-console-shared.c:335
 msgid "Downloading repository information"
 msgstr "A transferir informação dos repositórios"
 
 #. TRANSLATORS: transaction state, downloading metadata
-#: ../lib/packagekit-glib2/pk-console-shared.c:338
+#: ../lib/packagekit-glib2/pk-console-shared.c:339
 msgid "Downloading list of packages"
 msgstr "A transferir lista de pacotes"
 
 #. TRANSLATORS: transaction state, downloading metadata
-#: ../lib/packagekit-glib2/pk-console-shared.c:342
+#: ../lib/packagekit-glib2/pk-console-shared.c:343
 msgid "Downloading file lists"
 msgstr "A transferir listas de ficheiros"
 
 #. TRANSLATORS: transaction state, downloading metadata
-#: ../lib/packagekit-glib2/pk-console-shared.c:346
+#: ../lib/packagekit-glib2/pk-console-shared.c:347
 msgid "Downloading lists of changes"
 msgstr "A transferir listas de alterações"
 
 #. TRANSLATORS: transaction state, downloading metadata
-#: ../lib/packagekit-glib2/pk-console-shared.c:350
+#: ../lib/packagekit-glib2/pk-console-shared.c:351
 msgid "Downloading groups"
 msgstr "A transferir grupos"
 
 #. TRANSLATORS: transaction state, downloading metadata
-#: ../lib/packagekit-glib2/pk-console-shared.c:354
+#: ../lib/packagekit-glib2/pk-console-shared.c:355
 msgid "Downloading update information"
 msgstr "A transferir informações de actualizações"
 
 #. TRANSLATORS: transaction state, repackaging delta files
-#: ../lib/packagekit-glib2/pk-console-shared.c:358
+#: ../lib/packagekit-glib2/pk-console-shared.c:359
 msgid "Repackaging files"
 msgstr "A empacotar ficheiros novamente"
 
 #. TRANSLATORS: transaction state, loading databases
-#: ../lib/packagekit-glib2/pk-console-shared.c:362
+#: ../lib/packagekit-glib2/pk-console-shared.c:363
 msgid "Loading cache"
 msgstr "A carregar cache"
 
 #. TRANSLATORS: transaction state, scanning for running processes
-#: ../lib/packagekit-glib2/pk-console-shared.c:366
+#: ../lib/packagekit-glib2/pk-console-shared.c:367
 msgid "Scanning applications"
 msgstr "A analisar aplicações"
 
 #. TRANSLATORS: transaction state, generating a list of packages installed on the system
-#: ../lib/packagekit-glib2/pk-console-shared.c:370
+#: ../lib/packagekit-glib2/pk-console-shared.c:371
 msgid "Generating package lists"
 msgstr "A gerar lista de pacotes"
 
 #. TRANSLATORS: transaction state, when we're waiting for the native tools to exit
-#: ../lib/packagekit-glib2/pk-console-shared.c:374
+#: ../lib/packagekit-glib2/pk-console-shared.c:375
 msgid "Waiting for package manager lock"
 msgstr "A esperar pelo bloqueio do gestor de pacotes"
 
 #. TRANSLATORS: transaction state, waiting for user to type in a password
-#: ../lib/packagekit-glib2/pk-console-shared.c:378
+#: ../lib/packagekit-glib2/pk-console-shared.c:379
 msgid "Waiting for authentication"
 msgstr "À espera de autenticação"
 
 #. TRANSLATORS: transaction state, we are updating the list of processes
-#: ../lib/packagekit-glib2/pk-console-shared.c:382
+#: ../lib/packagekit-glib2/pk-console-shared.c:383
 msgid "Updating running applications"
 msgstr "A actualizar aplicações em execução"
 
 #. TRANSLATORS: transaction state, we are checking executable files currently in use
-#: ../lib/packagekit-glib2/pk-console-shared.c:386
+#: ../lib/packagekit-glib2/pk-console-shared.c:387
 msgid "Checking applications in use"
 msgstr "A verificar aplicações em uso"
 
 #. TRANSLATORS: transaction state, we are checking for libraries currently in use
-#: ../lib/packagekit-glib2/pk-console-shared.c:390
+#: ../lib/packagekit-glib2/pk-console-shared.c:391
 msgid "Checking libraries in use"
 msgstr "A verificar bibliotecas em uso"
 
 #. TRANSLATORS: transaction state, we are copying package files before or after the transaction
-#: ../lib/packagekit-glib2/pk-console-shared.c:394
+#: ../lib/packagekit-glib2/pk-console-shared.c:395
 msgid "Copying files"
 msgstr "A copiar ficheiros"
 
 #. TRANSLATORS: The type of update
-#: ../lib/packagekit-glib2/pk-console-shared.c:412
+#: ../lib/packagekit-glib2/pk-console-shared.c:413
 msgid "Trivial"
 msgstr "Trivial"
 
 #. TRANSLATORS: The type of update
-#: ../lib/packagekit-glib2/pk-console-shared.c:416
+#: ../lib/packagekit-glib2/pk-console-shared.c:417
 msgid "Normal"
 msgstr "Normal"
 
 #. TRANSLATORS: The type of update
-#: ../lib/packagekit-glib2/pk-console-shared.c:420
+#: ../lib/packagekit-glib2/pk-console-shared.c:421
 msgid "Important"
 msgstr "Importante"
 
 #. TRANSLATORS: The type of update
-#: ../lib/packagekit-glib2/pk-console-shared.c:424
+#: ../lib/packagekit-glib2/pk-console-shared.c:425
 msgid "Security"
 msgstr "Segurança"
 
 #. TRANSLATORS: The type of update
-#: ../lib/packagekit-glib2/pk-console-shared.c:428
+#: ../lib/packagekit-glib2/pk-console-shared.c:429
 msgid "Bug fix "
 msgstr "Correcção de erro"
 
 #. TRANSLATORS: The type of update
-#: ../lib/packagekit-glib2/pk-console-shared.c:432
+#: ../lib/packagekit-glib2/pk-console-shared.c:433
 msgid "Enhancement"
 msgstr "Melhoramentos"
 
 #. TRANSLATORS: The type of update
-#: ../lib/packagekit-glib2/pk-console-shared.c:436
+#: ../lib/packagekit-glib2/pk-console-shared.c:437
 msgid "Blocked"
 msgstr "Bloqueado"
 
 #. TRANSLATORS: The state of a package
 #. TRANSLATORS: The action of the package, in past tense
-#: ../lib/packagekit-glib2/pk-console-shared.c:441
-#: ../lib/packagekit-glib2/pk-console-shared.c:514
+#: ../lib/packagekit-glib2/pk-console-shared.c:442
+#: ../lib/packagekit-glib2/pk-console-shared.c:515
 msgid "Installed"
 msgstr "Instalado"
 
 #. TRANSLATORS: The state of a package, i.e. not installed
-#: ../lib/packagekit-glib2/pk-console-shared.c:446
+#: ../lib/packagekit-glib2/pk-console-shared.c:447
 msgid "Available"
 msgstr "Disponível"
 
 #. TRANSLATORS: The action of the package, in present tense
-#: ../lib/packagekit-glib2/pk-console-shared.c:464
+#: ../lib/packagekit-glib2/pk-console-shared.c:465
 msgid "Downloading"
 msgstr "A transferir"
 
 #. TRANSLATORS: The action of the package, in present tense
-#: ../lib/packagekit-glib2/pk-console-shared.c:468
+#: ../lib/packagekit-glib2/pk-console-shared.c:469
 msgid "Updating"
 msgstr "A actualizar"
 
 #. TRANSLATORS: The action of the package, in present tense
 #. TRANSLATORS: The role of the transaction, in present tense
-#: ../lib/packagekit-glib2/pk-console-shared.c:472
-#: ../lib/packagekit-glib2/pk-console-shared.c:592
+#: ../lib/packagekit-glib2/pk-console-shared.c:473
+#: ../lib/packagekit-glib2/pk-console-shared.c:593
 msgid "Installing"
 msgstr "A instalar"
 
 #. TRANSLATORS: The action of the package, in present tense
 #. TRANSLATORS: The role of the transaction, in present tense
-#: ../lib/packagekit-glib2/pk-console-shared.c:476
-#: ../lib/packagekit-glib2/pk-console-shared.c:588
+#: ../lib/packagekit-glib2/pk-console-shared.c:477
+#: ../lib/packagekit-glib2/pk-console-shared.c:589
 msgid "Removing"
 msgstr "A remover"
 
 #. TRANSLATORS: The action of the package, in present tense
-#: ../lib/packagekit-glib2/pk-console-shared.c:480
+#: ../lib/packagekit-glib2/pk-console-shared.c:481
 msgid "Cleaning up"
 msgstr "A limpar"
 
 #. TRANSLATORS: The action of the package, in present tense
-#: ../lib/packagekit-glib2/pk-console-shared.c:484
+#: ../lib/packagekit-glib2/pk-console-shared.c:485
 msgid "Obsoleting"
 msgstr "A torna obsoleto"
 
 #. TRANSLATORS: The action of the package, in present tense
-#: ../lib/packagekit-glib2/pk-console-shared.c:488
+#: ../lib/packagekit-glib2/pk-console-shared.c:489
 msgid "Reinstalling"
 msgstr "A reinstalar"
 
 #. TRANSLATORS: The action of the package, in past tense
-#: ../lib/packagekit-glib2/pk-console-shared.c:506
+#: ../lib/packagekit-glib2/pk-console-shared.c:507
 msgid "Downloaded"
 msgstr "Transferido"
 
 #. TRANSLATORS: The action of the package, in past tense
-#: ../lib/packagekit-glib2/pk-console-shared.c:518
+#: ../lib/packagekit-glib2/pk-console-shared.c:519
 msgid "Removed"
 msgstr "Removido"
 
 #. TRANSLATORS: The action of the package, in past tense
-#: ../lib/packagekit-glib2/pk-console-shared.c:522
+#: ../lib/packagekit-glib2/pk-console-shared.c:523
 msgid "Cleaned up"
 msgstr "Limpo"
 
 #. TRANSLATORS: The action of the package, in past tense
-#: ../lib/packagekit-glib2/pk-console-shared.c:526
+#: ../lib/packagekit-glib2/pk-console-shared.c:527
 msgid "Obsoleted"
 msgstr "obsoleto"
 
 #. TRANSLATORS: The action of the package, in past tense
-#: ../lib/packagekit-glib2/pk-console-shared.c:530
+#: ../lib/packagekit-glib2/pk-console-shared.c:531
 msgid "Reinstalled"
 msgstr "Reinstalado"
 
 #. TRANSLATORS: The role of the transaction, in present tense
-#: ../lib/packagekit-glib2/pk-console-shared.c:548
+#: ../lib/packagekit-glib2/pk-console-shared.c:549
 msgid "Unknown role type"
 msgstr "Tipo de perfil desconhecido"
 
 #. TRANSLATORS: The role of the transaction, in present tense
-#: ../lib/packagekit-glib2/pk-console-shared.c:552
+#: ../lib/packagekit-glib2/pk-console-shared.c:553
 msgid "Getting dependencies"
 msgstr "A obter dependências"
 
 #. TRANSLATORS: The role of the transaction, in present tense
-#: ../lib/packagekit-glib2/pk-console-shared.c:556
+#: ../lib/packagekit-glib2/pk-console-shared.c:557
 msgid "Getting update details"
 msgstr "A obter detalhes da actualização"
 
 #. TRANSLATORS: The role of the transaction, in present tense
-#: ../lib/packagekit-glib2/pk-console-shared.c:560
+#: ../lib/packagekit-glib2/pk-console-shared.c:561
 msgid "Getting details"
 msgstr "A obter detalhes"
 
 #. TRANSLATORS: The role of the transaction, in present tense
-#: ../lib/packagekit-glib2/pk-console-shared.c:564
+#: ../lib/packagekit-glib2/pk-console-shared.c:565
 msgid "Getting requires"
 msgstr "A obter obrigatórios"
 
 #. TRANSLATORS: The role of the transaction, in present tense
-#: ../lib/packagekit-glib2/pk-console-shared.c:568
+#: ../lib/packagekit-glib2/pk-console-shared.c:569
 msgid "Getting updates"
 msgstr "A obter actualizações"
 
 #. TRANSLATORS: The role of the transaction, in present tense
-#: ../lib/packagekit-glib2/pk-console-shared.c:572
+#: ../lib/packagekit-glib2/pk-console-shared.c:573
 msgid "Searching by details"
 msgstr "A pesquisar por detalhes"
 
 #. TRANSLATORS: The role of the transaction, in present tense
-#: ../lib/packagekit-glib2/pk-console-shared.c:576
+#: ../lib/packagekit-glib2/pk-console-shared.c:577
 msgid "Searching by file"
 msgstr "A pesquisar por ficheiro"
 
 #. TRANSLATORS: The role of the transaction, in present tense
-#: ../lib/packagekit-glib2/pk-console-shared.c:580
+#: ../lib/packagekit-glib2/pk-console-shared.c:581
 msgid "Searching groups"
 msgstr "A pesquisar por grupos"
 
 #. TRANSLATORS: The role of the transaction, in present tense
-#: ../lib/packagekit-glib2/pk-console-shared.c:584
+#: ../lib/packagekit-glib2/pk-console-shared.c:585
 msgid "Searching by name"
 msgstr "A pesquisar por nome"
 
 #. TRANSLATORS: The role of the transaction, in present tense
-#: ../lib/packagekit-glib2/pk-console-shared.c:596
+#: ../lib/packagekit-glib2/pk-console-shared.c:597
 msgid "Installing files"
 msgstr "A instalar ficheiros"
 
 #. TRANSLATORS: The role of the transaction, in present tense
-#: ../lib/packagekit-glib2/pk-console-shared.c:600
+#: ../lib/packagekit-glib2/pk-console-shared.c:601
 msgid "Refreshing cache"
 msgstr "A actualizar a cache"
 
 #. TRANSLATORS: The role of the transaction, in present tense
-#: ../lib/packagekit-glib2/pk-console-shared.c:604
+#: ../lib/packagekit-glib2/pk-console-shared.c:605
 msgid "Updating packages"
 msgstr "A actualizar pacotes"
 
 #. TRANSLATORS: The role of the transaction, in present tense
-#: ../lib/packagekit-glib2/pk-console-shared.c:608
+#: ../lib/packagekit-glib2/pk-console-shared.c:609
 msgid "Updating system"
 msgstr "A actualizar sistema"
 
 #. TRANSLATORS: The role of the transaction, in present tense
-#: ../lib/packagekit-glib2/pk-console-shared.c:612
+#: ../lib/packagekit-glib2/pk-console-shared.c:613
 msgid "Canceling"
 msgstr "A cancelar"
 
 #. TRANSLATORS: The role of the transaction, in present tense
-#: ../lib/packagekit-glib2/pk-console-shared.c:620
+#: ../lib/packagekit-glib2/pk-console-shared.c:621
 msgid "Getting repositories"
 msgstr "A obter repositórios"
 
 #. TRANSLATORS: The role of the transaction, in present tense
-#: ../lib/packagekit-glib2/pk-console-shared.c:624
+#: ../lib/packagekit-glib2/pk-console-shared.c:625
 msgid "Enabling repository"
 msgstr "A activar repositórios"
 
 #. TRANSLATORS: The role of the transaction, in present tense
-#: ../lib/packagekit-glib2/pk-console-shared.c:628
+#: ../lib/packagekit-glib2/pk-console-shared.c:629
 msgid "Setting data"
 msgstr "A definir dados"
 
 #. TRANSLATORS: The role of the transaction, in present tense
-#: ../lib/packagekit-glib2/pk-console-shared.c:632
+#: ../lib/packagekit-glib2/pk-console-shared.c:633
 msgid "Resolving"
 msgstr "A resolver"
 
 #. TRANSLATORS: The role of the transaction, in present tense
-#: ../lib/packagekit-glib2/pk-console-shared.c:636
+#: ../lib/packagekit-glib2/pk-console-shared.c:637
 msgid "Getting file list"
 msgstr "A obter a lista de ficheiros"
 
 #. TRANSLATORS: The role of the transaction, in present tense
-#: ../lib/packagekit-glib2/pk-console-shared.c:640
+#: ../lib/packagekit-glib2/pk-console-shared.c:641
 msgid "Getting provides"
 msgstr "A obter a lista de disponibilizações"
 
 #. TRANSLATORS: The role of the transaction, in present tense
-#: ../lib/packagekit-glib2/pk-console-shared.c:644
+#: ../lib/packagekit-glib2/pk-console-shared.c:645
 msgid "Installing signature"
 msgstr "A instalar assinatura"
 
 #. TRANSLATORS: The role of the transaction, in present tense
-#: ../lib/packagekit-glib2/pk-console-shared.c:648
+#: ../lib/packagekit-glib2/pk-console-shared.c:649
 msgid "Getting packages"
 msgstr "A obter pacotes"
 
 #. TRANSLATORS: The role of the transaction, in present tense
-#: ../lib/packagekit-glib2/pk-console-shared.c:652
+#: ../lib/packagekit-glib2/pk-console-shared.c:653
 msgid "Accepting EULA"
 msgstr "A aceitar EULA (Acordo de Licenciamento para Utilizadores Finais)"
 
 #. TRANSLATORS: The role of the transaction, in present tense
-#: ../lib/packagekit-glib2/pk-console-shared.c:660
+#: ../lib/packagekit-glib2/pk-console-shared.c:661
 msgid "Getting upgrades"
 msgstr "A obter actualizações"
 
 #. TRANSLATORS: The role of the transaction, in present tense
-#: ../lib/packagekit-glib2/pk-console-shared.c:664
+#: ../lib/packagekit-glib2/pk-console-shared.c:665
 msgid "Getting categories"
 msgstr "A obter categorias"
 
 #. TRANSLATORS: The role of the transaction, in present tense
-#: ../lib/packagekit-glib2/pk-console-shared.c:668
+#: ../lib/packagekit-glib2/pk-console-shared.c:669
 msgid "Getting transactions"
 msgstr "A obter transacções"
 
 #. TRANSLATORS: The role of the transaction, in present tense
-#: ../lib/packagekit-glib2/pk-console-shared.c:672
-#: ../lib/packagekit-glib2/pk-console-shared.c:676
+#: ../lib/packagekit-glib2/pk-console-shared.c:673
+#: ../lib/packagekit-glib2/pk-console-shared.c:677
 msgid "Simulating install"
 msgstr "A simular instalação"
 
 #. TRANSLATORS: The role of the transaction, in present tense
-#: ../lib/packagekit-glib2/pk-console-shared.c:680
+#: ../lib/packagekit-glib2/pk-console-shared.c:681
 msgid "Simulating remove"
 msgstr "A simular remoção"
 
 #. TRANSLATORS: The role of the transaction, in present tense
-#: ../lib/packagekit-glib2/pk-console-shared.c:684
+#: ../lib/packagekit-glib2/pk-console-shared.c:685
 msgid "Simulating update"
 msgstr "A simular actualização"
 
commit eb20d300cb325181160078e9bd72810a8bb60385
Author: Richard Hughes <richard at hughsie.com>
Date:   Tue Mar 16 10:32:53 2010 +0000

    yum: ensure we can create repomd for empty repos when using libzif

diff --git a/backends/yum/libzif/zif-package.c b/backends/yum/libzif/zif-package.c
index a82654c..4b47d2a 100644
--- a/backends/yum/libzif/zif-package.c
+++ b/backends/yum/libzif/zif-package.c
@@ -734,6 +734,13 @@ zif_package_get_filename (ZifPackage *package, GError **error)
 	g_return_val_if_fail (package->priv->package_id_split != NULL, NULL);
 	g_return_val_if_fail (error == NULL || *error == NULL, NULL);
 
+	/* doesn't make much sense */
+	if (package->priv->installed) {
+		g_set_error_literal (error, ZIF_PACKAGE_ERROR, ZIF_PACKAGE_ERROR_FAILED,
+				     "cannot get remote filename for installed package");
+		return NULL;
+	}
+
 	/* not exists */
 	if (package->priv->location_href == NULL) {
 		g_set_error (error, ZIF_PACKAGE_ERROR, ZIF_PACKAGE_ERROR_FAILED,
diff --git a/backends/yum/libzif/zif-store-remote.c b/backends/yum/libzif/zif-store-remote.c
index f76e41a..51285e1 100644
--- a/backends/yum/libzif/zif-store-remote.c
+++ b/backends/yum/libzif/zif-store-remote.c
@@ -349,6 +349,22 @@ out:
 }
 
 /**
+ * zif_store_remote_ensure_parent_dir_exists:
+ **/
+static gboolean
+zif_store_remote_ensure_parent_dir_exists (const gchar *filename, GError **error)
+{
+	gchar *dirname = NULL;
+	dirname = g_path_get_dirname (filename);
+	if (!g_file_test (dirname, G_FILE_TEST_EXISTS)) {
+		egg_debug ("creating directory %s", dirname);
+		g_mkdir_with_parents (dirname, 0777);
+	}
+	g_free (dirname);
+	return TRUE;
+}
+
+/**
  * zif_store_remote_download:
  * @store: the #ZifStoreRemote object
  * @filename: the completion filename to download, e.g. "Packages/hal-0.0.1.rpm"
@@ -376,7 +392,6 @@ zif_store_remote_download (ZifStoreRemote *store, const gchar *filename, const g
 	GError *error_local = NULL;
 	gchar *filename_local = NULL;
 	gchar *basename = NULL;
-	gchar *dirname = NULL;
 	const gchar *baseurl;
 	ZifCompletion *completion_local;
 
@@ -436,11 +451,9 @@ zif_store_remote_download (ZifStoreRemote *store, const gchar *filename, const g
 	filename_local = g_build_filename (directory, basename, NULL);
 
 	/* ensure path is valid */
-	dirname = g_path_get_dirname (filename);
-	if (!g_file_test (dirname, G_FILE_TEST_EXISTS)) {
-		egg_debug ("creating directory %s", dirname);
-		g_mkdir_with_parents (dirname, 0777);
-	}
+	ret = zif_store_remote_ensure_parent_dir_exists (filename_local, error);
+	if (!ret)
+		goto out;
 
 	/* try to use all uris */
 	len = store->priv->baseurls->len;
@@ -478,7 +491,6 @@ zif_store_remote_download (ZifStoreRemote *store, const gchar *filename, const g
 	}
 out:
 	g_free (basename);
-	g_free (dirname);
 	g_free (filename_local);
 	return ret;
 }
@@ -513,6 +525,11 @@ zif_store_remote_add_metalink (ZifStoreRemote *store, GCancellable *cancellable,
 	if (!ret) {
 		completion_local = zif_completion_get_child (completion);
 
+		/* ensure path is valid */
+		ret = zif_store_remote_ensure_parent_dir_exists (filename, error);
+		if (!ret)
+			goto out;
+
 		/* download object directly, as we don't have the repo setup yet */
 		download = zif_download_new ();
 		ret = zif_download_file (download, store->priv->metalink, filename, cancellable, completion_local, &error_local);
@@ -588,6 +605,11 @@ zif_store_remote_add_mirrorlist (ZifStoreRemote *store, GCancellable *cancellabl
 	if (!ret) {
 		completion_local = zif_completion_get_child (completion);
 
+		/* ensure path is valid */
+		ret = zif_store_remote_ensure_parent_dir_exists (filename, error);
+		if (!ret)
+			goto out;
+
 		/* download object directly, as we don't have the repo setup yet */
 		download = zif_download_new ();
 		ret = zif_download_file (download, store->priv->mirrorlist, filename, cancellable, completion_local, &error_local);
@@ -739,7 +761,7 @@ zif_store_remote_load_metadata (ZifStoreRemote *store, GCancellable *cancellable
 		/* download new file */
 		completion_local = zif_completion_get_child (completion);
 		store->priv->loaded_metadata = TRUE;
-		ret = zif_store_remote_download (store, store->priv->repomd_filename, store->priv->directory, cancellable, completion_local, &error_local);
+		ret = zif_store_remote_download (store, "repodata/repomd.xml", store->priv->directory, cancellable, completion_local, &error_local);
 		store->priv->loaded_metadata = FALSE;
 		if (!ret) {
 			g_set_error (error, ZIF_STORE_ERROR, ZIF_STORE_ERROR_FAILED,
commit 2dcceeefe6790e7bdeab4e3fd98b032a19067541
Author: Richard Hughes <richard at hughsie.com>
Date:   Tue Mar 16 10:16:31 2010 +0000

    yum: gently nudge the backend to exit if we're waiting for the lock, rather than kill it

diff --git a/backends/yum/pk-backend-yum.c b/backends/yum/pk-backend-yum.c
index cea97cf..eb6d7af 100644
--- a/backends/yum/pk-backend-yum.c
+++ b/backends/yum/pk-backend-yum.c
@@ -149,7 +149,7 @@ backend_get_lock (PkBackend *backend)
 	GError *error = NULL;
 
 	/* quit the spawned backend rather than waiting for it to time out */
-	pk_backend_spawn_kill (priv->spawn);
+	pk_backend_spawn_exit (priv->spawn);
 
 	for (i=0; i<YUM_BACKEND_LOCKING_RETRIES; i++) {
 
diff --git a/src/pk-backend-spawn.c b/src/pk-backend-spawn.c
index 74f4c88..2074364 100644
--- a/src/pk-backend-spawn.c
+++ b/src/pk-backend-spawn.c
@@ -888,6 +888,8 @@ pk_backend_spawn_set_name (PkBackendSpawn *backend_spawn, const gchar *name)
 
 /**
  * pk_backend_spawn_kill:
+ *
+ * A forceful exit, useful for aborting scripts
  **/
 gboolean
 pk_backend_spawn_kill (PkBackendSpawn *backend_spawn)
@@ -898,6 +900,19 @@ pk_backend_spawn_kill (PkBackendSpawn *backend_spawn)
 }
 
 /**
+ * pk_backend_spawn_exit:
+ *
+ * A gentle nudge to an idle backend that it should be shut down
+ **/
+gboolean
+pk_backend_spawn_exit (PkBackendSpawn *backend_spawn)
+{
+	g_return_val_if_fail (PK_IS_BACKEND_SPAWN (backend_spawn), FALSE);
+	pk_spawn_exit (backend_spawn->priv->spawn);
+	return TRUE;
+}
+
+/**
  * pk_backend_spawn_helper:
  **/
 gboolean
diff --git a/src/pk-backend-spawn.h b/src/pk-backend-spawn.h
index cab02f5..627161e 100644
--- a/src/pk-backend-spawn.h
+++ b/src/pk-backend-spawn.h
@@ -55,6 +55,7 @@ PkBackendSpawn	*pk_backend_spawn_new			(void);
 gboolean	 pk_backend_spawn_helper		(PkBackendSpawn	*backend_spawn,
 							 const gchar	*first_element, ...);
 gboolean	 pk_backend_spawn_kill			(PkBackendSpawn	*backend_spawn);
+gboolean	 pk_backend_spawn_exit			(PkBackendSpawn	*backend_spawn);
 const gchar	*pk_backend_spawn_get_name		(PkBackendSpawn	*backend_spawn);
 gboolean	 pk_backend_spawn_set_name		(PkBackendSpawn	*backend_spawn,
 							 const gchar	*name);
commit 71732de3d461fc39c84aa6013a4bdaa5a5cc5f98
Author: Richard Hughes <richard at hughsie.com>
Date:   Tue Mar 16 08:39:39 2010 +0000

    glib: fix up a critical warning when installing a file, not a package

diff --git a/lib/packagekit-glib2/pk-task.c b/lib/packagekit-glib2/pk-task.c
index d30bfa3..4469527 100644
--- a/lib/packagekit-glib2/pk-task.c
+++ b/lib/packagekit-glib2/pk-task.c
@@ -277,46 +277,48 @@ pk_task_simulate_ready_cb (GObject *source_object, GAsyncResult *res, PkTaskStat
 	sack = pk_results_get_package_sack (results);
 
 	/* remove all the original packages from the sack */
-	length = g_strv_length (state->package_ids);
-	for (i=0; i<length; i++)
-		pk_package_sack_remove_package_by_id (sack, state->package_ids[i]);
-
-	/* remove packages from the array that will not be useful */
-	array = pk_results_get_package_array (results);
-	while (idx < array->len) {
-		item = g_ptr_array_index (array, idx);
-		package_id = pk_package_get_id (item);
-		g_object_get (item,
-			      "info", &info,
-			      NULL);
-
-		/* remove all the cleanup and finished packages */
-		if (info == PK_INFO_ENUM_CLEANUP ||
-		    info == PK_INFO_ENUM_FINISHED) {
-			egg_debug ("removing %s", package_id);
-			g_ptr_array_remove (array, item);
-			continue;
-		}
+	if (state->package_ids != NULL) {
+		length = g_strv_length (state->package_ids);
+		for (i=0; i<length; i++)
+			pk_package_sack_remove_package_by_id (sack, state->package_ids[i]);
+
+		/* remove packages from the array that will not be useful */
+		array = pk_results_get_package_array (results);
+		while (idx < array->len) {
+			item = g_ptr_array_index (array, idx);
+			package_id = pk_package_get_id (item);
+			g_object_get (item,
+				      "info", &info,
+				      NULL);
 
-		/* remove all the original packages */
-		ret = FALSE;
-		for (i=0; i<length; i++) {
-			if (g_strcmp0 (package_id, state->package_ids[i]) == 0) {
+			/* remove all the cleanup and finished packages */
+			if (info == PK_INFO_ENUM_CLEANUP ||
+			    info == PK_INFO_ENUM_FINISHED) {
 				egg_debug ("removing %s", package_id);
 				g_ptr_array_remove (array, item);
-				ret = TRUE;
-				break;
+				continue;
 			}
-		}
-		if (ret)
-			continue;
 
-		/* no removal done */
-		idx++;
+			/* remove all the original packages */
+			ret = FALSE;
+			for (i=0; i<length; i++) {
+				if (g_strcmp0 (package_id, state->package_ids[i]) == 0) {
+					egg_debug ("removing %s", package_id);
+					g_ptr_array_remove (array, item);
+					ret = TRUE;
+					break;
+				}
+			}
+			if (ret)
+				continue;
+
+			/* no removal done */
+			idx++;
+		}
 	}
 
 	/* no results from simulate */
-	if (array->len == 0) {
+	if (pk_package_sack_get_size (sack) == 0) {
 		pk_task_do_async_action (state);
 		goto out;
 	}
commit 70e6a148a0f97df124478dc205473eabbd9a58c9
Author: Richard Hughes <richard at hughsie.com>
Date:   Tue Mar 16 08:39:08 2010 +0000

    yum: ensure we send out the UntrustedPackage message when we simulate installing a file, so ensure we don't prompt the user twice

diff --git a/backends/yum/yumBackend.py b/backends/yum/yumBackend.py
index 5c58e30..e2a7928 100755
--- a/backends/yum/yumBackend.py
+++ b/backends/yum/yumBackend.py
@@ -1828,30 +1828,31 @@ class PackageKitYumBackend(PackageKitBaseBackend, PackagekitPackage):
                        'All of the specified packages have already been installed')
 
         # If only_trusted is true, it means that we will only install trusted files
-        if only_trusted:
-            # disregard the default
+        if only_trusted or simulate:
             self.yumbase.conf.gpgcheck = 1
+        else:
+            self.yumbase.conf.gpgcheck = 0
 
-            # self.yumbase.installLocal fails for unsigned packages when self.yumbase.conf.gpgcheck = 1
-            # This means we don't run runYumTransaction, and don't get the GPG failure in
-            # PackageKitYumBase(_checkSignatures) -- so we check here
-            for inst_file in inst_files:
-                try:
-                    po = YumLocalPackage(ts=self.yumbase.rpmdb.readOnlyTS(), filename=inst_file)
-                except yum.Errors.MiscError:
-                    self.error(ERROR_INVALID_PACKAGE_FILE, "%s does not appear to be a valid package." % inst_file, exit=False)
-                    return
-                except Exception, e:
-                    self.error(ERROR_INTERNAL_ERROR, _format_str(traceback.format_exc()))
-                try:
-                    self.yumbase._checkSignatures([po], None)
-                except yum.Errors.YumGPGCheckError, e:
+        # self.yumbase.installLocal fails for unsigned packages when self.yumbase.conf.gpgcheck = 1
+        # This means we don't run runYumTransaction, and don't get the GPG failure in
+        # PackageKitYumBase(_checkSignatures) -- so we check here
+        for inst_file in inst_files:
+            try:
+                po = YumLocalPackage(ts=self.yumbase.rpmdb.readOnlyTS(), filename=inst_file)
+            except yum.Errors.MiscError:
+                self.error(ERROR_INVALID_PACKAGE_FILE, "%s does not appear to be a valid package." % inst_file, exit=False)
+                return
+            except Exception, e:
+                self.error(ERROR_INTERNAL_ERROR, _format_str(traceback.format_exc()))
+            try:
+                self.yumbase._checkSignatures([po], None)
+            except yum.Errors.YumGPGCheckError, e:
+                if only_trusted:
                     self.error(ERROR_MISSING_GPG_SIGNATURE, _to_unicode(e), exit=False)
                     return
-                except Exception, e:
-                    self.error(ERROR_INTERNAL_ERROR, _format_str(traceback.format_exc()))
-        else:
-            self.yumbase.conf.gpgcheck = 0
+                self.message (MESSAGE_UNTRUSTED_PACKAGE, "The package %s is untrusted" % po.name)
+            except Exception, e:
+                self.error(ERROR_INTERNAL_ERROR, _format_str(traceback.format_exc()))
 
         # common checks copied from yum
         for inst_file in inst_files:
commit 730ae1c42628a270b0551f4e413bab91cadd80b2
Author: Richard Hughes <richard at hughsie.com>
Date:   Mon Mar 15 16:54:25 2010 +0000

    yum: ensure to catch exceptions when we fail to initialize for GetRepoList

diff --git a/backends/yum/yumBackend.py b/backends/yum/yumBackend.py
index d1c7a46..5c58e30 100755
--- a/backends/yum/yumBackend.py
+++ b/backends/yum/yumBackend.py
@@ -2496,7 +2496,11 @@ class PackageKitYumBackend(PackageKitBaseBackend, PackagekitPackage):
         '''
         Implement the get-repo-list functionality
         '''
-        self._check_init()
+        try:
+            self._check_init()
+        except PkError, e:
+            self.error(e.code, e.details, exit=False)
+            return
         self.yumbase.conf.cache = 0 # Allow new files
         self.status(STATUS_INFO)
 
commit 7e02395cc49c94ac8de21f01aba8f462d72d526a
Author: Richard Hughes <richard at hughsie.com>
Date:   Mon Mar 15 16:42:17 2010 +0000

    trivial: update the example spec file to the latest from Fedora

diff --git a/contrib/PackageKit.spec.in b/contrib/PackageKit.spec.in
index 68d3b41..b8e3182 100644
--- a/contrib/PackageKit.spec.in
+++ b/contrib/PackageKit.spec.in
@@ -159,7 +159,6 @@ Summary: GLib Libraries and headers for PackageKit
 Group: Development/Libraries
 Requires: %{name} = %{version}-%{release}
 Requires: dbus-devel >= %{dbus_version}
-Requires: pkgconfig
 Requires: sqlite-devel
 Requires: PackageKit-glib = %{version}-%{release}
 Obsoletes: PackageKit-devel < %{version}-%{release}
@@ -172,7 +171,6 @@ GLib headers and libraries for PackageKit.
 Summary: Qt Libraries and headers for PackageKit
 Group: Development/Libraries
 Requires: %{name}-qt = %{version}-%{release}
-Requires: pkgconfig
 
 %description qt-devel
 Qt headers and libraries for PackageKit.
@@ -244,25 +242,21 @@ user to restart the computer or remove and re-insert the device.
 
 %build
 %configure \
-	--disable-static \
-	--enable-yum \
+        --disable-static \
+        --enable-yum \
 %if 0%{?rhel} == 0
-	--enable-smart \
-	--enable-introspection \
+        --enable-smart \
+        --enable-introspection \
 %endif
-	--with-default-backend=yum \
-	--disable-local \
-	--disable-ruck \
-	--disable-strict \
-%if 0
-	--disable-glib \
-%endif
-	--disable-tests
+        --with-default-backend=yum \
+        --disable-local \
+        --disable-ruck \
+        --disable-strict \
+        --disable-tests
 
 make %{?_smp_mflags}
 
 %install
-rm -rf $RPM_BUILD_ROOT
 make install DESTDIR=$RPM_BUILD_ROOT
 
 rm -f $RPM_BUILD_ROOT%{_libdir}/libpackagekit*.la
commit e7c1ea0edbd3de453df64756ff71232cd1376dc5
Merge: 2bc7836... e777013...
Author: Scott Parkerson <scott.parkerson at gmail.com>
Date:   Fri Mar 12 17:06:23 2010 -0500

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

commit 2bc7836db7985e11c648261af323a1c3a6b7259c
Author: Scott Parkerson <scott.parkerson at gmail.com>
Date:   Fri Mar 12 17:05:50 2010 -0500

    conary: fix local variable called before it was set (hurrr)

diff --git a/backends/conary/conaryCallback.py b/backends/conary/conaryCallback.py
index 1b78512..d34d1a0 100644
--- a/backends/conary/conaryCallback.py
+++ b/backends/conary/conaryCallback.py
@@ -102,19 +102,19 @@ class BasePKConaryCallback(callbacks.UpdateCallback):
         oldVersion, oldFlavor = job[1]
         newVersion, newFlavor = job[2]
         if oldVersion and newVersion:
+            package_id = self.backend.get_package_id(name, newVersion, newFlavor)
             log.info("Preparing Update %d out of %d: %s" % (troveNum, troveCount, package_id))
             self.backend.status(STATUS_UPDATE)
-            package_id = self.backend.get_package_id(name, newVersion, newFlavor)
             self.backend.package(package_id, INFO_UPDATING, '')
         elif oldVersion and not newVersion:
+            package_id = self.backend.get_package_id(name, oldVersion, oldFlavor)
             log.info("Preparing Remove %d out of %d: %s" % (troveNum, troveCount, package_id))
             self.backend.status(STATUS_REMOVE)
-            package_id = self.backend.get_package_id(name, oldVersion, oldFlavor)
             self.backend.package(package_id, INFO_REMOVING, '')
         elif not oldVersion and newVersion:
+            package_id = self.backend.get_package_id(name, newVersion, newFlavor)
             log.info("Preparing Install %d out of %d: %s" % (troveNum, troveCount, package_id))
             self.backend.status(STATUS_INSTALL)
-            package_id = self.backend.get_package_id(name, newVersion, newFlavor)
             self.backend.package(package_id, INFO_INSTALLING, '')
 
     def creatingDatabaseTransaction(self, troveNum, troveCount):
commit c41579cca48a2c028b26e5a95fa0a1785861041e
Author: Scott Parkerson <scott.parkerson at gmail.com>
Date:   Fri Mar 12 17:05:11 2010 -0500

    conary: make progress really chatty

diff --git a/backends/conary/conaryProgress.py b/backends/conary/conaryProgress.py
index 17d4543..da1e5ae 100644
--- a/backends/conary/conaryProgress.py
+++ b/backends/conary/conaryProgress.py
@@ -17,6 +17,8 @@
 # Copyright (C) 2008
 #    Richard Hughes <richard at hughsie.com>
 
+from pkConaryLog import log
+
 class PackagekitProgress:
     '''
     Progress class there controls the total progress of a transaction
@@ -60,12 +62,14 @@ class PackagekitProgress:
         self.reset()
         self.steps = steps
         self.current_step = 0
+        log.info("[Progress] Setting the following steps: %s" % (str(self.steps),))
 
     def reset(self):
         self.percent = 0
         self.steps = []
         self.current_step = 0
         self.subpercent = 0
+        log.info("[Progress] Reset")
 
     def step(self):
         '''
@@ -78,6 +82,7 @@ class PackagekitProgress:
         else:
             self.percent = 100
             self.subpercent = 0
+        log.info("[Progress] Step -> %d, Percent -> %d " % (self.current_step, self.percent))
 
     def set_subpercent(self, pct):
         '''
@@ -85,6 +90,7 @@ class PackagekitProgress:
         '''
         self.subpercent = pct
         self._update_percent()
+        log.info("[Progress] Update SubPercent: Percent -> %d, SubPercent -> %d" % (self.percent, self.subpercent))
 
     def _update_percent(self):
         '''
commit 73159eb800e5840a36358d652a3fe94e1b07292a
Author: Scott Parkerson <scott.parkerson at gmail.com>
Date:   Fri Mar 12 17:04:25 2010 -0500

    Fix typo

diff --git a/backends/conary/conaryBackend.py b/backends/conary/conaryBackend.py
index 69dca86..657e837 100755
--- a/backends/conary/conaryBackend.py
+++ b/backends/conary/conaryBackend.py
@@ -280,6 +280,7 @@ class PackageKitConaryBackend(PackageKitBaseBackend):
         return updJob
 
     def _do_update(self, applyList, simulate=False):
+        updJob = None
         jobPath = self.xmlcache.checkCachedUpdateJob(applyList)
         if jobPath:
             updJob = self.client.newUpdateJob()
@@ -295,7 +296,7 @@ class PackageKitConaryBackend(PackageKitBaseBackend):
             restartDir = self.client.applyUpdateJob(updJob, test=simulate)
         except errors.InternalConaryError:
             self.error(ERROR_NO_PACKAGES_TO_UPDATE,"get-updates first and then update sytem")
-        except trove.TroveIntegrityError: 
+        except trove.TroveIntegrityError:
             self.error(ERROR_NO_PACKAGES_TO_UPDATE,"run get-updates again")
         return updJob
 
commit 747a1ed13b0ba9f33acb3c2b20c5343e31010e7b
Author: Scott Parkerson <scott.parkerson at gmail.com>
Date:   Fri Mar 12 16:11:43 2010 -0500

    conary: bring back _do_update, which got whacked accidently

diff --git a/backends/conary/conaryBackend.py b/backends/conary/conaryBackend.py
index 58f8ff8..69dca86 100755
--- a/backends/conary/conaryBackend.py
+++ b/backends/conary/conaryBackend.py
@@ -279,6 +279,26 @@ class PackageKitConaryBackend(PackageKitBaseBackend):
 
         return updJob
 
+    def _do_update(self, applyList, simulate=False):
+        jobPath = self.xmlcache.checkCachedUpdateJob(applyList)
+        if jobPath:
+            updJob = self.client.newUpdateJob()
+            try:
+                updJob.thaw(jobPath)
+            except IOError, err:
+                updJob = None
+        else:
+            updJob,suggMap = self._get_update(applyList, cache=False)
+        self.allow_cancel(False)
+        try:
+            # TODO we should really handle the restart case here
+            restartDir = self.client.applyUpdateJob(updJob, test=simulate)
+        except errors.InternalConaryError:
+            self.error(ERROR_NO_PACKAGES_TO_UPDATE,"get-updates first and then update sytem")
+        except trove.TroveIntegrityError: 
+            self.error(ERROR_NO_PACKAGES_TO_UPDATE,"run get-updates again")
+        return updJob
+
     def _get_package_update(self, name, version, flavor):
         if name.startswith('-'):
             applyList = [(name, (version, flavor), (None, None), False)]
commit a81e49b5e58418d5d9643b8f491399a90cdb3cf5
Author: Scott Parkerson <scott.parkerson at gmail.com>
Date:   Fri Mar 12 15:40:16 2010 -0500

    conary: fix details views, more or less

diff --git a/backends/conary/conaryBackend.py b/backends/conary/conaryBackend.py
index 0ca08e8..58f8ff8 100755
--- a/backends/conary/conaryBackend.py
+++ b/backends/conary/conaryBackend.py
@@ -696,30 +696,21 @@ class PackageKitConaryBackend(PackageKitBaseBackend):
         self.allow_cancel(True)
         self.percentage(None)
         self.status(STATUS_INFO)
-        package_id = package_ids[0]
-        log.info(package_id)
-        name, version,arch,summary  = pkpackage.get_package_from_id(package_id)
-        pkgDict = self.xmlcache.resolve(name)
-        #update = self._get_updated(pkg)
-        update = ""
-        obsolete = ""
-        cve_url = ""
-        if pkgDict:
-            if "url" in pkgDict:
-                vendor_url = pkgDict["url"]
-            else:
-                vendor_url = ""
-            if "longDesc" in pkgDict:
-                desc = pkgDict["longDesc"]
-            else:
-                desc = ""
-            reboot = self._get_restart(pkgDict.get("name"))
-            state = self._get_branch( pkgDict.get("label"))
-            bz_url = self._get_fits(pkgDict.get("label"), pkgDict.get("name"))
-            #
-            #def update_detail(self, package_id, updates, obsoletes, vendor_url, bugzilla_url, cve_url, restart, update_text, changelog, state, issued, updated):
-            self.update_detail(package_id, update, obsolete, vendor_url, bz_url, cve_url,
-                    reboot, desc, changelog="", state= state, issued="", updated = "")
+        for package_id in package_ids:
+            log.info(package_id)
+            name, version,arch,summary  = pkpackage.get_package_from_id(package_id)
+            pkgDict = self.xmlcache.resolve(name)
+            update = ""
+            obsolete = ""
+            cve_url = ""
+            if pkgDict:
+                vendor_url = pkgDict.get("url","")
+                desc = pkgDict.get("longDesc","")
+                reboot = self._get_restart(pkgDict.get("name"))
+                state = self._get_branch( pkgDict.get("label"))
+                bz_url = self._get_fits(pkgDict.get("label"), pkgDict.get("name"))
+                self.update_detail(package_id, update, obsolete, vendor_url, bz_url, cve_url,
+                        reboot, desc, changelog="", state= state, issued="", updated = "")
 
    # @ExceptionHandler
     def get_details(self, package_ids):
@@ -731,41 +722,24 @@ class PackageKitConaryBackend(PackageKitBaseBackend):
         self.status(STATUS_INFO)
 
         log.info("========== get_details =============")
-        log.info(package_ids[0])
-        package_id = package_ids[0]
-        #name, version, flavor, installed = self._findPackage(package_id)
-        
-        summary = package_id.split(";")
-        log.info("====== geting summary")
-        log.info(summary)
-        name,version,arch,data = pkpackage.get_package_from_id(package_id)
-        pkgDict = self.xmlcache.resolve(name)
-        
-        if name and pkgDict:
-            shortDesc = ""
-            longDesc = ""
-            url = ""
-            categories  = None
-            license = ""
-
-            if "shortDesc" in pkgDict:
-                shortDesc = pkgDict["shortDesc"] 
-            if "longDesc" in pkgDict:
-                longDesc = pkgDict["longDesc"]
-            if "url" in pkgDict:
-                url = pkgDict["url"] #+ ";%s" % pkgDict["url"].replace("http://","")
-            if "category" in pkgDict:
-                categories =  self.xmlcache.getGroup( pkgDict['category'])
-            if "licenses" in pkgDict:
-                license = self._get_license(pkgDict["licenses"])
-                log.info(license)
-            # Package size goes here, but I don't know how to find that for conary packages.
-            #
-            #LICENSE_UNKNOWN = "unknown"
-            pkg_id = package_id.split(";")
-            pkg_id[3] = pkgDict["label"]
-            package_id = ";".join(pkg_id)
-            self.details(package_id, license, categories, longDesc, url, 0)
+        for package_id in package_ids:
+            name,version,arch,data = pkpackage.get_package_from_id(package_id)
+            pkgDict = self.xmlcache.resolve(name)
+            if name and pkgDict:
+                shortDesc = ""
+                longDesc = ""
+                url = ""
+                categories  = None
+                license = ""
+
+                shortDesc = pkgDict.get("shortDesc", "")
+                longDesc = pkgDict.get("longDesc", "")
+                url = pkgDict.get("url", "")
+                categories = self.xmlcache.getGroup(pkgDict.get("category",""))
+                license = self._get_license(pkgDict.get("licenses",""))
+                size = pkgDict.get("size", 0)
+                log.info("Details: %s, %s, %s, %s, %s, %d" % (package_id, license, categories, longDesc, url, size))
+                self.details(package_id, license, categories, longDesc, url, size)
 
     def _show_package(self, name, version, flavor, status):
         '''  Show info about package'''
@@ -935,19 +909,19 @@ class PackageKitConaryBackend(PackageKitBaseBackend):
 	'''
 	Simulate an install of one or more packages.
         '''
-	return self.install_packages(package_ids, False, simulate=True)
+	return self.install_packages(False, package_ids, simulate=True)
 
     def simulate_update_packages(self, package_ids):
 	'''
 	Simulate an update of one or more packages.
         '''
-	return self.update_packages(package_ids, False, simulate=True)
+	return self.update_packages(False, package_ids, simulate=True)
 
     def simulate_remove_packages(self, package_ids):
 	'''
 	Simulate an update of one or more packages.
         '''
-	return self.remove_packages(package_ids, False, simulate=True)
+	return self.remove_packages(False, False, package_ids, simulate=True)
 
 from pkConaryLog import pdb
 
commit f4836816c20c987e20d7936998d7d9183f3c4f29
Author: Scott Parkerson <scott.parkerson at gmail.com>
Date:   Fri Mar 12 15:14:09 2010 -0500

    conary: make _get_update a bit less spaghetti-ish

diff --git a/backends/conary/conaryBackend.py b/backends/conary/conaryBackend.py
index 3201f6c..0ca08e8 100755
--- a/backends/conary/conaryBackend.py
+++ b/backends/conary/conaryBackend.py
@@ -251,40 +251,32 @@ class PackageKitConaryBackend(PackageKitBaseBackend):
 
     def _get_update(self, applyList, cache=True):
         from conary.conaryclient.update import NoNewTrovesError,DepResolutionFailure
+        self.allow_cancel(False)
         updJob = self.client.newUpdateJob()
-        try:
-            log.info("prepare updateJOb...............")
-            log.info(applyList)
-            suggMap = self.client.prepareUpdateJob(updJob, applyList)
-            log.info("end prepare updateJOB..............")
-        except NoNewTrovesError:
-            #self.error(ERROR_NO_PACKAGES_TO_UPDATE, "No new apps were found")
-            return updJob, None
-        except DepResolutionFailure as error :
-            log.info(error.getErrorMessage())
-            deps =  error.cannotResolve
-            
-            dep_package = [ str(i[0][0]).split(":")[0] for i in deps ]
-            log.info(dep_package)
-            self.error(ERROR_DEP_RESOLUTION_FAILED,  "This package depends of:  %s" % ", ".join(set(dep_package)))
-        if cache:
-            self.xmlcache.checkCachedUpdateJob(applyList)
-        log.info(jobPath)
-        if jobPath:
-            updJob = self.client.newUpdateJob()
+        jobPath = self.xmlcache.checkCachedUpdateJob(applyList)
+        if cache and jobPath:
             try:
+                log.info("Using previously cached update job at %s" % (jobPath,))
                 updJob.thaw(jobPath)
             except IOError, err:
+                log.error("Failed to read update job at %s (error=%s)" % (jobPath, str(err)))
                 updJob = None
         else:
-            updJob,suggMap = self._get_update(applyList, cache=False)
-        self.allow_cancel(False)
-        try:
-            restartDir = self.client.applyUpdateJob(updJob, test=simulate)
-        except errors.InternalConaryError:
-            self.error(ERROR_NO_PACKAGES_TO_UPDATE,"get-updates first and then update sytem")
-        except trove.TroveIntegrityError: 
-            self.error(ERROR_NO_PACKAGES_TO_UPDATE,"run get-updates again")
+            log.info("Creating a new update job")
+            try:
+                suggMap = self.client.prepareUpdateJob(updJob, applyList)
+                log.info("Successfully created a new update job")
+                if cache:
+                    self.xmlcache.cacheUpdateJob(applyList, updJob)
+            except NoNewTrovesError:
+                return updJob, None
+            except DepResolutionFailure as error :
+                log.info(error.getErrorMessage())
+                deps =  error.cannotResolve
+                dep_package = [ str(i[0][0]).split(":")[0] for i in deps ]
+                log.info(dep_package)
+                self.error(ERROR_DEP_RESOLUTION_FAILED,  "This package depends of:  %s" % ", ".join(set(dep_package)))
+
         return updJob
 
     def _get_package_update(self, name, version, flavor):
@@ -763,7 +755,7 @@ class PackageKitConaryBackend(PackageKitBaseBackend):
             if "url" in pkgDict:
                 url = pkgDict["url"] #+ ";%s" % pkgDict["url"].replace("http://","")
             if "category" in pkgDict:
-                categories =  Cache().getGroup( pkgDict['category'])
+                categories =  self.xmlcache.getGroup( pkgDict['category'])
             if "licenses" in pkgDict:
                 license = self._get_license(pkgDict["licenses"])
                 log.info(license)
@@ -859,13 +851,12 @@ class PackageKitConaryBackend(PackageKitBaseBackend):
         log.info("_get_update ....")
 
         self.status(STATUS_RUNNING)
-        updJob, suggMap = self._get_update(applyList)
+        updJob = self._get_update(applyList)
         log.info("_get_update ....end.")
 
-        jobLists = updJob.getJobs()
         log.info("getting JobLists...........")
         r = []
-        for num, job in enumerate(jobLists):
+        for num, job in enumerate(updJob.getJobs()):
             name = job[0][0]
 
             # On an erase display the old version/flavor information.
@@ -876,13 +867,12 @@ class PackageKitConaryBackend(PackageKitBaseBackend):
             flavor = job[0][2][1]
             if flavor is None:
                 flavor = job[0][1][1]
-            
+
             info = self._get_info(name)
             trove_info = ( ( name,version,flavor ), info) 
             r.append(trove_info)
-            #self._show_package(name, version, flavor, info)
-        
-        pkg_list = Cache().resolve_list([ name for (  ( name,version,flavor), info )  in r ])
+
+        pkg_list = self.xmlcache.resolve_list([ name for (  ( name,version,flavor), info )  in r ])
         log.info("generate the pkgs ")
         new_res = []
         for pkg in pkg_list:
commit af4e564c190be5993336638449a8427366078db7
Author: Scott Parkerson <scott.parkerson at gmail.com>
Date:   Fri Mar 12 15:12:46 2010 -0500

    conary: tidy things up a bit in conaryCallback

diff --git a/backends/conary/conaryCallback.py b/backends/conary/conaryCallback.py
index 4bae6c3..1b78512 100644
--- a/backends/conary/conaryCallback.py
+++ b/backends/conary/conaryCallback.py
@@ -24,7 +24,7 @@ from pkConaryLog import log
 
 MEGA = 1048576.0
 
-class UpdateSystemCallback(callbacks.UpdateCallback):
+class BasePKConaryCallback(callbacks.UpdateCallback):
     def __init__(self, backend, cfg=None):
         callbacks.UpdateCallback.__init__(self)
         log.info("==== callback ==== ")
@@ -36,214 +36,146 @@ class UpdateSystemCallback(callbacks.UpdateCallback):
         self.smallUpdate = False
         self.error = []
         self.progress = PackagekitProgress()
-        self.progress.set_steps([ 30,60 ]  )
         self.disablepercent = False
         self.dostep = True
-    #1
-    #3
+
     def requestingChangeSet(self):
-        log.info("Callback UpdateSystem........ STATUS_REQUEST changeset ")
         self.backend.status(STATUS_REQUEST)
-#        self.backend.percentage(self.progress.percent)
- #       log.info(self.progress.percent)
-    #2
+        log.info("[STATUS_REQUEST] Requesting ChangeSet")
+
     def downloadingChangeSet(self, got, need):
         self.backend.status(STATUS_DOWNLOAD)
-        log.info("Callback UpdateSystem........ STATUS_DOWNLOAD  Changeset %.2f percent %.2f/%.2f Mbytes" % ( got*100/float(need), got/MEGA,need/MEGA) )
+        log.info("[STATUS_DOWNLOAD] Downloading ChangeSet (%.2f%% %.2f out of %.2f MiB)" \
+                % ( got*100/float(need), got/MEGA,need/MEGA) )
         self.progress.set_subpercent( got*100 / float(need) )
         self.backend.percentage( self.progress.percent )
-        log.info( "%s percent" % self.progress.percent)
-        if got == need:
-            log.info("Do a step ========0")
-            self.progress.step()
+        if got >= need:
+            self.dostep = True
 
-    #4
     def resolvingDependencies(self):
-        log.info("Callback UpdateSystem........ STATUS_DEP_RESOLVE ")
-        self.backend.percentage(self.progress.percent)
         self.backend.status(STATUS_DEP_RESOLVE)
+        log.info("[STATUS_DEP_RESOLVE] Resolving Dependencies")
+        self.backend.percentage(self.progress.percent)
 
-    #5  >> request> download
     def setChangesetHunk(self, num, total):
-        log.info("callback. .......... set Changeset HUnk %s/%s" % (num, total ) )
+        log.info("Changeset Hunk %d out of %d" % (num, total) )
         if total > 0:
             p = num*100/float(total)
         else:
             p = 0
-        log.info("Do a supercent ========sub")
         self.progress.set_subpercent(p)
         self.disablepercent = True
         self.backend.percentage(self.progress.percent)
-        log.info(self.progress.percent)
         if num == total:
-            self.dostep =True
-    #6 
-    def setUpdateHunk(self, hunk, hunkCount):
-        log.info("callback. .......... set update HUnk %s/%s" % ( hunk, hunkCount))
+            self.dostep = True
+
+    def setUpdateHunk(self, num, total):
+        log.info("Update Hunk %d out of %d" % (num, total ) )
         if self.dostep:
             self.disablepercent = True
             self.dostep = False
 
-
-        if hunk < hunkCount:
-            p = hunk*100/float(hunkCount)
-            log.info("Do a supercent ========sub")
-            self.progress.set_subpercent( p )
+        if num < total:
+            p = num*100/float(total)
+            self.progress.set_subpercent(p)
         else:
             self.smallUpdate = True
-
         self.backend.percentage(self.progress.percent)
-        log.info(self.progress.percent)
 
     def setUpdateJob(self, job):
         self.currentJob = job
         self.backend.percentage(self.progress.percent)
         log.info("callback UpdateSystem. setUpdateJob")
         log.info(self.progress.percent)
-        
 
     def creatingRollback(self):
-        #self.backend.status('Creating Rollback')
-        self.backend.status(STATUS_ROLLBACK)
-        self.backend.percentage(self.progress.percent)
-        log.info("callback updateSystem. creatingRollback")
-        log.info(self.progress.percent)
-        log.info(self.progress.percent)
-
+        # Don't do anything unless we actually rollback
+        pass
 
     def preparingUpdate(self, troveNum, troveCount, add=0):
-        #self.progress.step()
-        log.info("callback updateSystem. preparingUpdate")
         if not self.currentJob or len(self.currentJob) == 0 or troveNum > troveCount:
             return
 
-
         self.backend.percentage(self.progress.percent)
-        if troveNum > 0:
-            troveNum -= 1
-        job = self.currentJob[troveNum]
+        job = self.currentJob[troveNum-1]
         name = job[0]
         oldVersion, oldFlavor = job[1]
         newVersion, newFlavor = job[2]
-        #log.info("JOB>>>>>>>> %s " % str(job) )
         if oldVersion and newVersion:
+            log.info("Preparing Update %d out of %d: %s" % (troveNum, troveCount, package_id))
             self.backend.status(STATUS_UPDATE)
             package_id = self.backend.get_package_id(name, newVersion, newFlavor)
             self.backend.package(package_id, INFO_UPDATING, '')
         elif oldVersion and not newVersion:
+            log.info("Preparing Remove %d out of %d: %s" % (troveNum, troveCount, package_id))
             self.backend.status(STATUS_REMOVE)
             package_id = self.backend.get_package_id(name, oldVersion, oldFlavor)
             self.backend.package(package_id, INFO_REMOVING, '')
         elif not oldVersion and newVersion:
+            log.info("Preparing Install %d out of %d: %s" % (troveNum, troveCount, package_id))
             self.backend.status(STATUS_INSTALL)
             package_id = self.backend.get_package_id(name, newVersion, newFlavor)
             self.backend.package(package_id, INFO_INSTALLING, '')
-        log.info(self.progress.percent)
 
     def creatingDatabaseTransaction(self, troveNum, troveCount):
+        log.info("Creating Database Transaction %d out of %d" % (troveNum, troveCount))
         self.backend.percentage(self.progress.percent)
         log.info(self.progress.percent)
-        self.backend.status(STATUS_COMMIT)
-        #self.preparingUpdate(troveNum, troveCount, add=troveCount)
-        log.info("Callback UpdateSystem........ CreateingDatabaseTransaction %.2f / %.2f " % ( troveNum, troveCount ) )
-        #self.progress.set_subpercent( got*100 / float(need) )
 
     def committingTransaction(self):
-        log.info('callback UpdateSystem......Committing Transaction')
-
+        log.info('[STATUS_COMMIT] Committing Transaction')
         self.backend.status(STATUS_COMMIT)
         self.backend.percentage(self.progress.percent)
-        log.info(self.progress.percent)
 
     def updateDone(self):
-        log.info("callback. ..........  update done")
+        log.info("Update Done")
         self.backend.percentage(self.progress.percent)
         self.currentJob = None
         log.info(self.progress.percent)
 
     def downloadingFileContents(self, got, need):
-        #self.backend.status('Downloading files for changeset')
-        log.info("Callback ........ STATUS_DOWNLOAD  FIle Contents %s " %  str( got*100/need  ))
+        log.info("[STATUS_DOWNLOAD] Downloading File Contents (%.2f%% %.2f out of %.2f MiB)" \
+                % ( got*100/float(need), got/MEGA,need/MEGA) )
         self.backend.status(STATUS_DOWNLOAD)
         #self.backend.sub_percentage(got*100/need)
 
     def requestingFileContents(self):
-        #self.backend.status('Requesting File Contents')
-        log.info("Callback ........ STATUS_REQUEST request File contents ")
+        log.info("[STATUS_REQUEST] Requesting File Contents")
         self.backend.status(STATUS_REQUEST)
 
     def removeFiles(self, filenum, total):
-        log.info("Callback ........ STATUS_REMOVE %s/%sfiles" %( filenum, total) )
+        log.info("[STATUS_REMOVE] %s out of %s file(s)" %( filenum, total) )
         self.backend.status(STATUS_REMOVE)
-        self.preparingUpdate(filenum, total, add=total)
-    
+
     def done(self):
-        #self.backend.status('Done')
-    #    self.progress.step()
-        log.info("DONEEEEEEEEEEEE")
+        log.info("Done.")
  
     def warning(self, msg, *args, **kwargs):
         e = msg %args
         log.warning(e)
-        
+
     def tagHandlerOutput(self, tag, msg, stderr = False):
-        pass
+        log.info("Tag Handler Output: [%s] %s" % (tag, msg)) 
 
     def troveScriptOutput(self, typ, msg):
-        pass
+        log.info("Trove Script Output [%s] %s" % (typ, msg)) 
 
-class GetUpdateCallback(callbacks.UpdateCallback):
-    def __init__(self, backend, cfg=None):
-        callbacks.UpdateCallback.__init__(self)
-        log.info("==== callback ==== ")
-        if cfg:
-            self.setTrustThreshold(cfg.trustThreshold)
 
-        self.backend = backend
-        self.currentJob = None
-        self.smallUpdate = False
-        self.error = []
-        self.progress = PackagekitProgress()
-        self.progress.set_steps([1,50, 100 ]  )
-    # 1 >> downloadingChangeSet
-    # 2 >> downloadingChangeSet
-    def requestingChangeSet(self):
-        log.info("Callback getUpdates ........ STATUS_REQUEST changeset ")
-        self.backend.status(STATUS_REQUEST)
-        self.backend.percentage(self.progress.percent)
-        log.info(self.progress.percent)
-        self.progress.step()
+class UpdateSystemCallback(BasePKConaryCallback):
 
-    def downloadingChangeSet(self, got, need):
-       # log.info("Callback getUpdates. Changeset %s percent of %.2f/%.2f bytes" % ( int( got*100/float(need)), got/MEGA,need/MEGA) )
-        self.backend.status(STATUS_DOWNLOAD)
-        self.progress.set_subpercent( got*100 / float(need) )
-        self.backend.percentage( self.progress.percent )
-       # log.info( "%s percent" % self.progress.percent)
-    # 3
-    def resolvingDependencies(self):
-        #self.backend.status('Resolving Dependencies')
-        self.backend.status(STATUS_DEP_RESOLVE)
-        self.progress.step()
-        log.info("Callback getUpdates........ STATUS_DEP_RESOLVE ")
-        self.backend.percentage(self.progress.percent)
-        log.info("do a step>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>")
+    def __init__(self, backend, cfg=None):
+        BasePKConaryCallback.__init__(self, backend, cfg)
+        self.progress.set_steps([ 30,60 ]  )
+
+class GetUpdateCallback(BasePKConaryCallback):
 
-        self.backend.percentage(self.progress.percent)
-        log.info(self.progress.percent)
-  
-class UpdateCallback(callbacks.UpdateCallback):
     def __init__(self, backend, cfg=None):
-        callbacks.UpdateCallback.__init__(self)
-        log.info("==== callback ==== ")
-        if cfg:
-            self.setTrustThreshold(cfg.trustThreshold)
+        BasePKConaryCallback.__init__(self, backend, cfg)
+        self.progress.set_steps([1,50, 100 ]  )
 
-        self.backend = backend
-        self.currentJob = None
-        self.smallUpdate = False
-        self.error = []
-        self.progress = PackagekitProgress()
+class UpdateCallback(BasePKConaryCallback):
+    def __init__(self, backend, cfg=None):
+        BasePKConaryCallback.__init__(self, backend, cfg)
         self.progress.set_steps([ 
             1, # requestingChangeSet 1
             50, # resolveDeps2
@@ -252,285 +184,8 @@ class UpdateCallback(callbacks.UpdateCallback):
             80,# setUpdateHUnk5
             81,# setUpdateJob6
             ]  )
-    # 1 >> download
-    # 4 >> download
-    def requestingChangeSet(self):
-        log.info("Callback ........ STATUS_REQUEST changeset ")
-        self.backend.status(STATUS_DOWNLOAD)
-        self.backend.percentage(self.progress.percent)
-        log.info(self.progress.percent)
-        self.progress.step()
-
-    def downloadingChangeSet(self, got, need):
-        log.info("Callback ........ STATUS_DOWNLOAD  Changeset %s percent %.2f/%.2f bytes" % ( got*100/float(need), got/MEGA,need/MEGA) )
-        self.progress.set_subpercent( got*100 / float(need) )
-        self.backend.percentage( self.progress.percent )
-        log.info( "%s percent" % self.progress.percent)
-
-
-
-    # 2  
-    def resolvingDependencies(self):
-        #self.backend.status('Resolving Dependencies')
-        log.info("Callback ........ STATUS_DEP_RESOLVE ")
-        self.backend.percentage(self.progress.percent)
-        self.backend.status(STATUS_DEP_RESOLVE)
-        self.progress.step()
-        self.backend.percentage(self.progress.percent)
-        log.info(self.progress.percent)
-    # 3 
-    def setChangesetHunk(self, num, total):
-        log.info("callback. .......... set Changeset HUnk %s/%s" % (num, total ) )
-        self.progress.step()
-        self.backend.percentage(self.progress.percent)
-        log.info(self.progress.percent)
-
-   # 5
-    def setUpdateHunk(self, hunk, hunkCount):
-        log.info("callback. .......... set update HUnk %s/%s" % ( hunk, hunkCount))
-        self.progress.step()
-
-        if hunk < hunkCount:
-            p = hunk / float(hunkCount) * 100.0
-            self.progress.set_subpercent(p)
-        else:
-            self.smallUpdate = True
-
-        self.backend.percentage(self.progress.percent)
-        log.info(self.progress.percent)
-    # 6
-    def setUpdateJob(self, job):
-        log.info("callback. .......... set update Job")
-        self.currentJob = job
-        self.backend.percentage(self.progress.percent)
-        log.info(self.progress.percent)
 
-    #7 >> preparing update
-    def creatingRollback(self):
-        #self.backend.status('Creating Rollback')
-        log.info("Callback ........ STATUS_ROLLBACK  ")
-        self.backend.status(STATUS_ROLLBACK)
-        self.backend.percentage(self.progress.percent)
-        log.info(self.progress.percent)
-
-
-    def preparingUpdate(self, troveNum, troveCount, add=0):
-        log.info("callback ....... preparing Update  trove %s/%s" % (troveNum, troveCount) )
-        #self.progress.step()
-        if not self.currentJob or len(self.currentJob) == 0 or troveNum > troveCount:
-            return
-
-        if troveNum > 0 and troveCount > 0:
-            sub_percent = (add + troveNum) / (2 * float(troveCount)) * 100
-            self.progress.set_subpercent(sub_percent)
-
-        self.backend.percentage(self.progress.percent)
-        if troveNum > 0:
-            troveNum -= 1
-        log.info("currentJob")
-        log.info(self.currentJob[troveNum])
-        job = self.currentJob[troveNum]
-        name = job[0]
-        oldVersion, oldFlavor = job[1]
-        newVersion, newFlavor = job[2]
-        #log.info("JOB>>>>>>>> %s " % str(job) )
-        if oldVersion and newVersion:
-            log.info("pU.. status Update")
-            self.backend.status(STATUS_UPDATE)
-            package_id = self.backend.get_package_id(name, newVersion, newFlavor)
-            self.backend.package(package_id, INFO_UPDATING, '')
-        elif oldVersion and not newVersion:
-            self.backend.status(STATUS_REMOVE)
-            log.info("pU.. status remove")
-            package_id = self.backend.get_package_id(name, oldVersion, oldFlavor)
-            self.backend.package(package_id, INFO_REMOVING, '')
-        elif not oldVersion and newVersion:
-            #self.backend.status(STATUS_INSTALL)
-            log.info("pU.. status install")
-            package_id = self.backend.get_package_id(name, newVersion, newFlavor)
-            self.backend.package(package_id, INFO_INSTALLING, '')
-        log.info(self.progress.percent)
-    #8
-    def creatingDatabaseTransaction(self, troveNum, troveCount):
-        log.info("callback. .......... creating Database Transactions")
-        self.backend.percentage(self.progress.percent)
-        log.info(self.progress.percent)
-        self.backend.status(STATUS_COMMIT)
-     #   self.preparingUpdate(troveNum, troveCount, add=troveCount)
-
-    # 9
-    def committingTransaction(self):
-        #self.backend.status('Committing Transaction')
-        log.info("Callback ........ STATUS_COMMIT  transactions ")
-
-        self.backend.status(STATUS_COMMIT)
-        self.progress.step()
-        self.backend.percentage(self.progress.percent)
-        log.info(self.progress.percent)
-
-    #10
-    def updateDone(self):
-        log.info("callback. ..........  update done")
-        self.backend.percentage(self.progress.percent)
-        self.currentJob = None
-        log.info(self.progress.percent)
-
-
-
-    def downloadingFileContents(self, got, need):
-        #self.backend.status('Downloading files for changeset')
-        log.info("Callback ........ STATUS_DOWNLOAD  FIle Contents %s " %  str( got*100/need  ))
-        self.backend.status(STATUS_DOWNLOAD)
-        #self.backend.sub_percentage(got*100/need)
-
-    def requestingFileContents(self):
-        #self.backend.status('Requesting File Contents')
-        log.info("Callback ........ STATUS_REQUEST request File contents ")
-        self.backend.status(STATUS_REQUEST)
-
-    def removeFiles(self, filenum, total):
-        log.info("Callback ........ STATUS_REMOVE %s/%sfiles" %( filenum, total) )
-        self.backend.status(STATUS_REMOVE)
-        self.preparingUpdate(filenum, total, add=total)
-    
-    def done(self):
-        #self.backend.status('Done')
-    #    self.progress.step()
-        log.info("DONEEEEEEEEEEEE")
- 
-    def warning(self, msg, *args, **kwargs):
-        e = msg %args
-	log.warning(e)
-        
-    def tagHandlerOutput(self, tag, msg, stderr = False):
-        pass
-
-    def troveScriptOutput(self, typ, msg):
-        pass
-
-    def troveScriptFailure(self, typ, errcode):
-        pass
-
-class RemoveCallback(callbacks.UpdateCallback):
+class RemoveCallback(BasePKConaryCallback):
     def __init__(self, backend, cfg=None):
-        callbacks.UpdateCallback.__init__(self)
-        log.info("==== callback ==== ")
-        if cfg:
-            self.setTrustThreshold(cfg.trustThreshold)
-
-        self.backend = backend
-        self.currentJob = None
-        self.smallUpdate = False
-        self.error = []
-        self.progress = PackagekitProgress()
+        BasePKConaryCallback.__init__(self, backend, cfg)
         self.progress.set_steps([ 2,5,7,8,90,100 ]  )
-     # 1
-    def resolvingDependencies(self):
-        #self.backend.status('Resolving Dependencies')
-        log.info("Callback ........ STATUS_DEP_RESOLVE ")
-        self.backend.percentage(self.progress.percent)
-        self.backend.status(STATUS_DEP_RESOLVE)
-        self.progress.step()
-        self.backend.percentage(self.progress.percent)
-        log.info(self.progress.percent)
-    #2
-    def setChangesetHunk(self, num, total):
-        log.info("callback. .......... set Changeset HUnk %s/%s" % (num, total ) )
-        self.progress.step()
-        self.backend.percentage(self.progress.percent)
-        log.info(self.progress.percent)
-    #3
-    def setUpdateHunk(self, hunk, hunkCount):
-        log.info("callback. .......... set update HUnk %s/%s" % ( hunk, hunkCount))
-        if hunk < hunkCount:
-            p = hunk / float(hunkCount) * 100.0
-            self.progress.set_subpercent(p)
-        else:
-            self.smallUpdate = True
-
-        self.backend.percentage(self.progress.percent)
-        log.info(self.progress.percent)
-    #4
-    def setUpdateJob(self, job):
-        log.info("callback. .......... set update Job")
-        self.currentJob = job
-        self.progress.step()
-        self.backend.percentage(self.progress.percent)
-        log.info(self.progress.percent)
-    #5
-    def creatingRollback(self):
-        #self.backend.status('Creating Rollback')
-        log.info("Callback ........ STATUS_ROLLBACK  ")
-        self.backend.status(STATUS_ROLLBACK)
-        self.progress.step()
-        #self.backend.percentage(self.progress.percent)
-        log.info(self.progress.percent)
-     #6
-    def removeFiles(self, filenum, total):
-        log.info("Callback ........ STATUS_REMOVE %s percent %s/%s files" %(filenum*100/float(total), filenum, total) )
-        self.progress.set_subpercent( filenum*100/float(total) )
-        self.backend.percentage(self.progress.percent)
-        log.info(self.progress.percent)
-        self.backend.status(STATUS_REMOVE)
-        self.preparingUpdate(filenum, total, add=total)
-
-    def preparingUpdate(self, troveNum, troveCount, add=0):
-        log.info("callback ....... preparing Update  trove %s/%s" % (troveNum, troveCount) )
-        #self.progress.step()
-        if not self.currentJob or len(self.currentJob) == 0 or troveNum > troveCount:
-            return
-
-        log.info("currentJob %s" % troveNum)
-        log.info("job %s" % self.currentJob)
-        if len(self.currentJob) > troveNum:
-            job = self.currentJob[troveNum]
-        else:
-            return
-        name = job[0]
-        oldVersion, oldFlavor = job[1]
-        newVersion, newFlavor = job[2]
-        #log.info("JOB>>>>>>>> %s " % str(job) )
-        if oldVersion and newVersion:
-            log.info("Callback ........ STATUS_UPDATE preparing Update ")
-            self.backend.status(STATUS_UPDATE)
-            package_id = self.backend.get_package_id(name, newVersion, newFlavor)
-            self.backend.package(package_id, INFO_UPDATING, '')
-        elif oldVersion and not newVersion:
-            log.info("Callback ........ STATUS_REMOVE preparing Update ")
-            self.backend.status(STATUS_REMOVE)
-            package_id = self.backend.get_package_id(name, oldVersion, oldFlavor)
-            self.backend.package(package_id, INFO_REMOVING, '')
-
-    def creatingDatabaseTransaction(self, troveNum, troveCount):
-        log.info("callback. .......... creating Database Transactions")
-        self.progress.step()
-        self.backend.percentage(self.progress.percent)
-        log.info(self.progress.percent)
-        #self.preparingUpdate(troveNum, troveCount, add=troveCount)
-    #8
-    def committingTransaction(self):
-        #self.backend.status('Committing Transaction')
-        log.info("Callback ........ STATUS_COMMIT  transactions ")
-
-        self.backend.status(STATUS_COMMIT)
-        self.progress.step()
-        self.backend.percentage(self.progress.percent)
-        log.info(self.progress.percent)
-    #9
-    def updateDone(self):
-        log.info("callback. ..........  update done")
-        self.progress.step()
-        self.backend.percentage(self.progress.percent)
-        self.currentJob = None
-        log.info(self.progress.percent)
-  
-    def done(self):
-    #    self.progress.step()
-        log.info("Some Problem ...............>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>")
-        log.info(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>")
- 
-    def warning(self, msg, *args, **kwargs):
-        e = msg %args
-        log.warning(e)
-        
- 
commit d1412ce709ba39149f698527b1985f850feebfe8
Author: Scott Parkerson <scott.parkerson at gmail.com>
Date:   Fri Mar 12 12:02:53 2010 -0500

    conary: improvements to XMLCache and generateXML
    
    1. Do not write a partial XML file upon a network error
       or when there is no repos data to write. This can happen
       if the Conary repository is down, and may cause subsequent
       parsetree errors when ElementTree tries to read an empty
       file.
    2. Ignore the NETWORK env variable (not used ATM AFAICT)
    3. Hardcode in a list of "pregenerated" labels for Foresight.
    4. Fix a case where the XML was fetched too many times.

diff --git a/backends/conary/XMLCache.py b/backends/conary/XMLCache.py
index 527d962..2b18030 100644
--- a/backends/conary/XMLCache.py
+++ b/backends/conary/XMLCache.py
@@ -7,13 +7,14 @@ import urllib as url
 from conary.lib import sha1helper
 from conary.lib import util
 
-from packagekit.backend import PackageKitBaseBackend
+from packagekit.backend import *
 from packagekit.enums import ERROR_NO_CACHE,ERROR_REPO_CONFIGURATION_ERROR, ERROR_NO_NETWORK
 
 
 from pkConaryLog import log
 from conarypk import ConaryPk
 from conaryEnums import groupMap
+import generateXML
 
 #{{{ FuNCS
 def getGroup( categorieList ):
@@ -42,7 +43,8 @@ def mapGroup(categorieList):
 class XMLRepo:
     xml_path = ""
     repository = ""
-    def __init__(self, repo, path ):
+    def __init__(self, repo, path, pk):
+        self.pk = pk
         self.xml_path = path
         self._setRepo(repo)
 
@@ -83,8 +85,7 @@ class XMLRepo:
                 self._repo =   cElementTree.parse(r).getroot()
                 return self._repo
             except:
-                Pk = PackageKitBaseBackend("")
-                Pk.error(ERROR_REPO_CONFIGURATION_ERROR," The file %s not parsed submit a issue at http://issues.foresightlinux.org" % self.repo )
+                self.pk.error(ERROR_REPO_CONFIGURATION_ERROR," The file %s not parsed submit a issue at http://issues.foresightlinux.org" % self.repo )
        
 
     def _generatePackage(self, package_node ): 
@@ -173,8 +174,20 @@ class XMLRepo:
 
 
 class XMLCache:
-    #xml_files = ["foresight.rpath.org at fl:2"]
-    xml_files = []
+
+    # Let's only get XML data from things that we support.
+    # XXX We really should replace this with the Conary
+    #     RESTful API real soon now.
+    pregenerated_XML_labels = (
+        'conary.rpath.com at rpl:2-qa',
+        'foresight.rpath.org at fl:2',
+        'foresight.rpath.org at fl:2-qa',
+        'foresight.rpath.org at fl:2-devel',
+        'foresight.rpath.org at fl:2-kernel',
+        'foresight.rpath.org at fl:2-qa-kernel',
+        'foresight.rpath.org at fl:2-devel-kernel',
+    )
+
     server = "http://packages.foresightlinux.org/cache/"
     repos = []
     dbPath = '/var/cache/conary/'
@@ -182,8 +195,9 @@ class XMLCache:
     xml_path =  dbPath + "xmlrepo/"
 
     def __init__(self):
-        con = ConaryPk()
-        labels = con.get_labels_from_config()
+        self.conarypk = ConaryPk()
+        self.labels = ( x for x in self.conarypk.get_labels_from_config() )
+        self.pk = PackageKitBaseBackend("")
 
         if not os.path.isdir(self.dbPath):
             os.makedirs(self.dbPath)
@@ -191,12 +205,11 @@ class XMLCache:
             os.mkdir(self.jobPath)
         if not os.path.isdir( self.xml_path ):
             os.makedirs(self.xml_path )
- 
-        for xml_file in labels:
-           if not os.path.exists( self.xml_path + xml_file + ".xml"  ):
-                self._fetchXML()
-        for xml_file in labels :
-            self.repos.append(XMLRepo( xml_file + ".xml", self.xml_path ))
+
+        for label in self.labels:
+           if not os.path.exists( self.xml_path + label + ".xml"  ):
+                self._fetchXML(label)
+           self.repos.append(XMLRepo( label + ".xml", self.xml_path, self.pk ))
 
     def _getJobCachePath(self, applyList):
         applyStr = '\0'.join(['%s=%s[%s]--%s[%s]%s' % (x[0], x[1][0], x[1][1], x[2][0], x[2][1], x[3]) for x in applyList])
@@ -223,7 +236,7 @@ class XMLCache:
 
     def convertTroveToDict(self, troveTupleList):
         mList = []
-        for troveTuple in troveTupleList: 
+        for troveTuple in troveTupleList:
             pkg = {}
             pkg["name"] = troveTuple[0]
             pkg["version"] = troveTuple[1].trailingRevision()
@@ -233,8 +246,11 @@ class XMLCache:
             
     def searchByGroups(self, groups):
         pass
+
     def refresh(self):
-        self._fetchXML()
+        for label in self.labels:
+            self._fetchXML(label)
+
     def resolve(self, name ):
         for repo in self.repos:
             r =  repo.resolve(name)
@@ -275,30 +291,21 @@ class XMLCache:
         #log.debug([i["name"] for i in results ] )
         return results
 
-    def _fetchXML(self ):
-        con = ConaryPk()
-        labels = con.get_labels_from_config()
-        log.info(labels)
-        Pk = PackageKitBaseBackend("")
-        for i in labels:
-            if "foresight.rpath.org" in i or "conary.rpath.com" in i:
-                label = i + '.xml'
-                filename = self.xml_path + label
-                wwwfile = self.server + label
-                if os.environ.get("NETWORK"):
-                    try:
-                        wget = url.urlopen( wwwfile )
-                    except:
-                        Pk.error(ERROR_NO_NETWORK,"%s can not open" % wwwfile)
-                else:
-                    Pk.error(ERROR_NO_CACHE,"Not exist network conection")
-                openfile = open( filename ,'w')
+    def _fetchXML(self, label):
+        log.info("Updating XMLCache for label %s" % label)
+        filename = label + '.xml'
+        filepath = self.xml_path + filename
+        if label in self.pregenerated_XML_labels:
+            wwwfile = self.server + filename
+            try:
+                wget = url.urlopen( wwwfile )
+                openfile = open(filepath,'w')
                 openfile.writelines(wget.readlines())
                 openfile.close()
-            else:
-                import generateXML
-                filename = self.xml_path + i + ".xml"
-                generateXML.init(i,filename)
+            except:
+                self.pk.error(ERROR_NO_NETWORK,"%s can not open" % wwwfile)
+        else:
+            generateXML.init(label,filepath,self.conarypk)
 
     def getGroup(self,categorieList):
         return getGroup(categorieList)
@@ -344,8 +351,8 @@ if __name__ == '__main__':
     import sys
     #print XMLCache().resolve("gimp")
     l= XMLCache().resolve_list(sys.argv[1:])
-   # print ">> details"
-   # l= XMLCache().search('Internet', 'group' )
+    #print ">> details"
+    #l= XMLCache().search('Internet', 'group' )
 
     for v,p in enumerate(l):
         print v,p["name"]
diff --git a/backends/conary/generateXML.py b/backends/conary/generateXML.py
index a512aac..1ca14d7 100644
--- a/backends/conary/generateXML.py
+++ b/backends/conary/generateXML.py
@@ -67,20 +67,22 @@ def generate_xml( troves, label):
         document.append(package)
     return document
 
-
-def init(label, fileoutput ):
-    conary = ConaryPk()
-    cli = conary.cli
-
-    cfg = conary.cfg
-    log.info(" write %s on xml" %  label)
-    pkgs = getPackagesFromLabel(cfg,cli,label)
-    troves = conary.repos.getTroves(pkgs,withFiles=False)
-    nodes = generate_xml(troves,label)
-    cElementTree.ElementTree(nodes).write(fileoutput)
-    log.info("%s repo done" % label)
-
-
+def init(label, fileoutput, conarypk=None):
+
+    if not conarypk:
+        conarypk = ConaryPk()
+
+    cli = conarypk.cli
+    cfg = conarypk.cfg
+    log.info("Attempting to retrieve repository data for %s" %  label)
+    try:
+        pkgs = getPackagesFromLabel(cfg,cli,label)
+        troves = conarypk.repos.getTroves(pkgs,withFiles=False)
+        nodes = generate_xml(troves,label)
+        cElementTree.ElementTree(nodes).write(fileoutput)
+        log.info("Successfully wrote XML data for label %s into file %s" % (label, fileoutput))
+    except:
+        log.error("Failed to gather data from the repository")
 
 if __name__ == "__main__":
     init('zodyrepo.rpath.org at rpl:devel','tmp.xml')
commit 81d82c23e1155e74aec7a3f6c74cacf8c9780667
Author: Scott Parkerson <scott.parkerson at gmail.com>
Date:   Fri Mar 12 10:46:26 2010 -0500

    conary: instantiate XMLCache only once, avoiding massive memory usage

diff --git a/backends/conary/conaryBackend.py b/backends/conary/conaryBackend.py
index 3909998..3201f6c 100755
--- a/backends/conary/conaryBackend.py
+++ b/backends/conary/conaryBackend.py
@@ -39,7 +39,7 @@ from packagekit.progress import PackagekitProgress
 from conaryCallback import UpdateCallback, GetUpdateCallback
 from conaryCallback import RemoveCallback, UpdateSystemCallback
 from conaryFilter import *
-from XMLCache import XMLCache as Cache
+from XMLCache import XMLCache
 from conaryInit import *
 
 from conary import conarycfg, conaryclient
@@ -128,6 +128,7 @@ class PackageKitConaryBackend(PackageKitBaseBackend):
         self.conary = conary
         self.callback = UpdateCallback(self, self.cfg)
         self.client.setUpdateCallback(self.callback)
+        self.xmlcache = XMLCache()
 
     def _freezeData(self, version, flavor):
         frzVersion = version.freeze()
@@ -168,8 +169,7 @@ class PackageKitConaryBackend(PackageKitBaseBackend):
     def get_package_id(self, name, versionObj, flavor):
 
         version = versionObj.trailingRevision()
-        cache = Cache()
-        pkg = cache.resolve(name)
+        pkg = self.xmlcache.resolve(name)
         #pkg["shortDesc"] = "."
         arch = self._get_arch(flavor)
         #data = versionObj.asString() + "#"
@@ -230,10 +230,9 @@ class PackageKitConaryBackend(PackageKitBaseBackend):
             log.info("where %s" % where)
             self.error(ERROR_UNKNOWN, "DORK---- search where not found")
 
-        cache = Cache()
         log.debug((searchlist, where))
         log.info("||||||||||||||||||||||||||||searching  on cache... ")
-        pkgList = cache.search(searchlist, where )
+        pkgList = self.xmlcache.search(searchlist, where )
         log.info("|||||||||||||||||||||||||||||1end searching on cache... ")
 
         if len(pkgList) > 0 :
@@ -269,12 +268,7 @@ class PackageKitConaryBackend(PackageKitBaseBackend):
             log.info(dep_package)
             self.error(ERROR_DEP_RESOLUTION_FAILED,  "This package depends of:  %s" % ", ".join(set(dep_package)))
         if cache:
-            Cache().cacheUpdateJob(applyList, updJob)
-        return updJob, suggMap
-
-    def _do_update(self, applyList, simulate=False):
-        log.info("========= _do_update ========")
-        jobPath = Cache().checkCachedUpdateJob(applyList)
+            self.xmlcache.checkCachedUpdateJob(applyList)
         log.info(jobPath)
         if jobPath:
             updJob = self.client.newUpdateJob()
@@ -368,8 +362,7 @@ class PackageKitConaryBackend(PackageKitBaseBackend):
         self.status(STATUS_INFO)
         log.info("filters: %s package:%s " % (filters, package))
 
-        cache = Cache()
-        pkg_dict = cache.resolve( package[0] )
+        pkg_dict = self.xmlcache.resolve( package[0] )
         log.info(pkg_dict)
         if pkg_dict is None:
             return None
@@ -572,8 +565,7 @@ class PackageKitConaryBackend(PackageKitBaseBackend):
         self.percentage(None)
         self.status(STATUS_REFRESH_CACHE)
         self.percentage(None)
-        cache = Cache()
-        cache.refresh()
+        self.xmlcache.refresh()
 
     def install_packages(self, only_trusted, package_ids, simulate=False):
         """
@@ -715,8 +707,7 @@ class PackageKitConaryBackend(PackageKitBaseBackend):
         package_id = package_ids[0]
         log.info(package_id)
         name, version,arch,summary  = pkpackage.get_package_from_id(package_id)
-        cache = Cache()
-        pkgDict = cache.resolve(name)
+        pkgDict = self.xmlcache.resolve(name)
         #update = self._get_updated(pkg)
         update = ""
         obsolete = ""
@@ -756,8 +747,7 @@ class PackageKitConaryBackend(PackageKitBaseBackend):
         log.info("====== geting summary")
         log.info(summary)
         name,version,arch,data = pkpackage.get_package_from_id(package_id)
-        cache = Cache()
-        pkgDict = cache.resolve(name)
+        pkgDict = self.xmlcache.resolve(name)
         
         if name and pkgDict:
             shortDesc = ""
commit 3ad0efb6d630454a4c19628e7c8c1eea363a502b
Author: Scott Parkerson <scott.parkerson at gmail.com>
Date:   Fri Mar 12 10:39:39 2010 -0500

    conary: refuse to explode on a warning callback

diff --git a/backends/conary/conaryCallback.py b/backends/conary/conaryCallback.py
index 7dc9ffc..4bae6c3 100644
--- a/backends/conary/conaryCallback.py
+++ b/backends/conary/conaryCallback.py
@@ -184,9 +184,7 @@ class UpdateSystemCallback(callbacks.UpdateCallback):
  
     def warning(self, msg, *args, **kwargs):
         e = msg %args
-        log.error("<<<<<<<<<<<<<<<<<<<<<<<<<<<<")
-        log.error(e)
-        self.backend.error(ERROR_DEP_RESOLUTION_FAILED, e, False )
+        log.warning(e)
         
     def tagHandlerOutput(self, tag, msg, stderr = False):
         pass
@@ -402,9 +400,7 @@ class UpdateCallback(callbacks.UpdateCallback):
  
     def warning(self, msg, *args, **kwargs):
         e = msg %args
-        log.error("<<<<<<<<<<<<<<<<<<<<<<<<<<<<")
-        log.error(e)
-        self.backend.error(ERROR_DEP_RESOLUTION_FAILED, e, False )
+	log.warning(e)
         
     def tagHandlerOutput(self, tag, msg, stderr = False):
         pass
@@ -535,8 +531,6 @@ class RemoveCallback(callbacks.UpdateCallback):
  
     def warning(self, msg, *args, **kwargs):
         e = msg %args
-        self.error.append(e)
-        log.error("<<<<<<<<<<<<<<<<<<<<<<<<<<<<")
-        log.error( args )
+        log.warning(e)
         
  
commit 73a645e69421cbc547bbcbb809a74a1926757f82
Author: Scott Parkerson <scott.parkerson at gmail.com>
Date:   Fri Mar 12 10:35:07 2010 -0500

    conary: refrain from using threaded mode

diff --git a/backends/conary/conarypk.py b/backends/conary/conarypk.py
index 7a8628e..f0bb12c 100644
--- a/backends/conary/conarypk.py
+++ b/backends/conary/conarypk.py
@@ -26,6 +26,9 @@ class ConaryPk:
         cfg.initializeFlavors()
         self.cfg = cfg
 
+        # Don't use threaded mode
+        self.cfg.configLine('threaded False')
+
         cli = ConaryClient(cfg)
 
         # labels enable on /etc/conary/config.d/
commit e777013a7609e7a4a24cdbe6e9d5ac70645f8d30
Author: Richard Hughes <richard at hughsie.com>
Date:   Thu Mar 11 21:27:56 2010 +0000

    yum: enable the libzif code for downloading packages
    
    Also update the version of libzif used, to fix various other buglets.

diff --git a/backends/yum/libzif/zif-completion.c b/backends/yum/libzif/zif-completion.c
index 9ee0352..f96dd8f 100644
--- a/backends/yum/libzif/zif-completion.c
+++ b/backends/yum/libzif/zif-completion.c
@@ -304,7 +304,7 @@ zif_completion_get_child (ZifCompletion *completion)
 {
 	ZifCompletion *child = NULL;
 
-	g_return_val_if_fail (ZIF_IS_COMPLETION (completion), FALSE);
+	g_return_val_if_fail (ZIF_IS_COMPLETION (completion), NULL);
 
 	/* already set child */
 	if (completion->priv->child != NULL) {
diff --git a/backends/yum/libzif/zif-config.c b/backends/yum/libzif/zif-config.c
index 763f011..54e631e 100644
--- a/backends/yum/libzif/zif-config.c
+++ b/backends/yum/libzif/zif-config.c
@@ -34,6 +34,10 @@
  * zif_config_set_filename() and any reads prior to that will fail.
  */
 
+#ifdef HAVE_CONFIG_H
+#  include <config.h>
+#endif
+
 #include <string.h>
 
 #include <glib.h>
@@ -181,6 +185,7 @@ zif_config_get_boolean (ZifConfig *config, const gchar *key, GError **error)
 
 	g_return_val_if_fail (ZIF_IS_CONFIG (config), FALSE);
 	g_return_val_if_fail (key != NULL, FALSE);
+	g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
 
 	/* get string value */
 	value = zif_config_get_string (config, key, error);
@@ -216,6 +221,7 @@ zif_config_get_uint (ZifConfig *config, const gchar *key, GError **error)
 
 	g_return_val_if_fail (ZIF_IS_CONFIG (config), G_MAXUINT);
 	g_return_val_if_fail (key != NULL, G_MAXUINT);
+	g_return_val_if_fail (error == NULL || *error == NULL, G_MAXUINT);
 
 	/* get string value */
 	value = zif_config_get_string (config, key, error);
@@ -299,7 +305,7 @@ out:
  *
  * Gets a time value from a local setting, falling back to the config file.
  *
- * Return value: the data value
+ * Return value: the data value, or 0 for an error
  *
  * Since: 0.0.1
  **/
@@ -309,8 +315,9 @@ zif_config_get_time (ZifConfig *config, const gchar *key, GError **error)
 	gchar *value;
 	guint timeval = 0;
 
-	g_return_val_if_fail (ZIF_IS_CONFIG (config), FALSE);
-	g_return_val_if_fail (key != NULL, FALSE);
+	g_return_val_if_fail (ZIF_IS_CONFIG (config), 0);
+	g_return_val_if_fail (key != NULL, 0);
+	g_return_val_if_fail (error == NULL || *error == NULL, 0);
 
 	/* get string value */
 	value = zif_config_get_string (config, key, error);
@@ -410,6 +417,7 @@ zif_config_set_filename (ZifConfig *config, const gchar *filename, GError **erro
 	g_return_val_if_fail (ZIF_IS_CONFIG (config), FALSE);
 	g_return_val_if_fail (filename != NULL, FALSE);
 	g_return_val_if_fail (!config->priv->loaded, FALSE);
+	g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
 
 	/* check file exists */
 	ret = g_file_test (filename, G_FILE_TEST_IS_REGULAR);
@@ -513,6 +521,7 @@ gboolean
 zif_config_reset_default (ZifConfig *config, GError **error)
 {
 	g_return_val_if_fail (ZIF_IS_CONFIG (config), FALSE);
+	g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
 	g_hash_table_remove_all (config->priv->hash);
 	return TRUE;
 }
@@ -538,6 +547,7 @@ zif_config_set_local (ZifConfig *config, const gchar *key, const gchar *value, G
 
 	g_return_val_if_fail (ZIF_IS_CONFIG (config), FALSE);
 	g_return_val_if_fail (key != NULL, FALSE);
+	g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
 
 	/* already exists? */
 	value_tmp = g_hash_table_lookup (config->priv->hash, key);
diff --git a/backends/yum/libzif/zif-download.c b/backends/yum/libzif/zif-download.c
index daf4d55..a389484 100644
--- a/backends/yum/libzif/zif-download.c
+++ b/backends/yum/libzif/zif-download.c
@@ -168,6 +168,7 @@ zif_download_file (ZifDownload *download, const gchar *uri, const gchar *filenam
 	g_return_val_if_fail (filename != NULL, FALSE);
 	g_return_val_if_fail (download->priv->msg == NULL, FALSE);
 	g_return_val_if_fail (download->priv->session != NULL, FALSE);
+	g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
 
 	/* save an instance of the completion object */
 	download->priv->completion = g_object_ref (completion);
@@ -246,6 +247,7 @@ zif_download_set_proxy (ZifDownload *download, const gchar *http_proxy, GError *
 	guint connection_timeout;
 
 	g_return_val_if_fail (ZIF_IS_DOWNLOAD (download), FALSE);
+	g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
 
 	/* get default value from the config file */
 	connection_timeout = zif_config_get_uint (download->priv->config, "connection_timeout", NULL);
diff --git a/backends/yum/libzif/zif-groups.c b/backends/yum/libzif/zif-groups.c
index d56ba71..e674cb9 100644
--- a/backends/yum/libzif/zif-groups.c
+++ b/backends/yum/libzif/zif-groups.c
@@ -29,6 +29,10 @@
  * set using zif_groups_set_mapping_file() before any queries are done.
  */
 
+#ifdef HAVE_CONFIG_H
+#  include <config.h>
+#endif
+
 #include <string.h>
 
 #include <glib.h>
@@ -248,6 +252,7 @@ zif_groups_get_categories (ZifGroups *groups, GError **error)
 	gboolean ret;
 
 	g_return_val_if_fail (ZIF_IS_GROUPS (groups), NULL);
+	g_return_val_if_fail (error == NULL || *error == NULL, NULL);
 
 	/* if not already loaded, load */
 	if (!groups->priv->loaded) {
@@ -289,6 +294,7 @@ zif_groups_get_group_for_cat (ZifGroups *groups, const gchar *cat, GError **erro
 
 	g_return_val_if_fail (ZIF_IS_GROUPS (groups), PK_GROUP_ENUM_UNKNOWN);
 	g_return_val_if_fail (cat != NULL, PK_GROUP_ENUM_UNKNOWN);
+	g_return_val_if_fail (error == NULL || *error == NULL, PK_GROUP_ENUM_UNKNOWN);
 
 	/* if not already loaded, load */
 	if (!groups->priv->loaded) {
diff --git a/backends/yum/libzif/zif-lock.c b/backends/yum/libzif/zif-lock.c
index 1461443..cb80eb9 100644
--- a/backends/yum/libzif/zif-lock.c
+++ b/backends/yum/libzif/zif-lock.c
@@ -191,6 +191,7 @@ zif_lock_set_locked (ZifLock *lock, guint *pid, GError **error)
 	GError *error_local = NULL;
 
 	g_return_val_if_fail (ZIF_IS_LOCK (lock), FALSE);
+	g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
 
 	/* already locked */
 	ret = zif_lock_is_locked (lock, &pid_tmp);
@@ -253,6 +254,7 @@ zif_lock_set_unlocked (ZifLock *lock, GError **error)
 	gint retval;
 
 	g_return_val_if_fail (ZIF_IS_LOCK (lock), FALSE);
+	g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
 
 	/* optimise as we hold the lock */
 	if (lock->priv->self_locked) {
diff --git a/backends/yum/libzif/zif-monitor.c b/backends/yum/libzif/zif-monitor.c
index b401228..b87867b 100644
--- a/backends/yum/libzif/zif-monitor.c
+++ b/backends/yum/libzif/zif-monitor.c
@@ -115,6 +115,7 @@ zif_monitor_add_watch (ZifMonitor *monitor, const gchar *filename, GError **erro
 
 	g_return_val_if_fail (ZIF_IS_MONITOR (monitor), FALSE);
 	g_return_val_if_fail (filename != NULL, FALSE);
+	g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
 
 	/* watch this file */
 	file = g_file_new_for_path (filename);
diff --git a/backends/yum/libzif/zif-package-local.c b/backends/yum/libzif/zif-package-local.c
index d6fd455..0dc1111 100644
--- a/backends/yum/libzif/zif-package-local.c
+++ b/backends/yum/libzif/zif-package-local.c
@@ -479,6 +479,7 @@ zif_package_local_set_from_header (ZifPackageLocal *pkg, Header header, GError *
 
 	g_return_val_if_fail (ZIF_IS_PACKAGE_LOCAL (pkg), FALSE);
 	g_return_val_if_fail (header != NULL, FALSE);
+	g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
 
 	zif_package_set_installed (ZIF_PACKAGE (pkg), TRUE);
 
@@ -534,6 +535,10 @@ zif_package_local_set_from_filename (ZifPackageLocal *pkg, const gchar *filename
 	gboolean ret = FALSE;
 	GError *error_local = NULL;
 
+	g_return_val_if_fail (ZIF_IS_PACKAGE_LOCAL (pkg), FALSE);
+	g_return_val_if_fail (filename != NULL, FALSE);
+	g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+
 	/* open the file for reading */
 	fd = Fopen(filename, "r.fdio");
 	if (fd == NULL) {
diff --git a/backends/yum/libzif/zif-package-remote.c b/backends/yum/libzif/zif-package-remote.c
index 915736e..b36322c 100644
--- a/backends/yum/libzif/zif-package-remote.c
+++ b/backends/yum/libzif/zif-package-remote.c
@@ -86,6 +86,7 @@ zif_package_remote_set_from_repo (ZifPackageRemote *pkg, guint length, gchar **t
 	g_return_val_if_fail (ZIF_IS_PACKAGE_REMOTE (pkg), FALSE);
 	g_return_val_if_fail (type != NULL, FALSE);
 	g_return_val_if_fail (data != NULL, FALSE);
+	g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
 
 	/* get the ID */
 	for (i=0; i<length; i++) {
diff --git a/backends/yum/libzif/zif-package.c b/backends/yum/libzif/zif-package.c
index 2980cf6..a82654c 100644
--- a/backends/yum/libzif/zif-package.c
+++ b/backends/yum/libzif/zif-package.c
@@ -578,6 +578,7 @@ zif_package_ensure_data (ZifPackage *package, ZifPackageEnsureType type, GError
 	ZifPackageClass *klass = ZIF_PACKAGE_GET_CLASS (package);
 
 	g_return_val_if_fail (ZIF_IS_PACKAGE (package), FALSE);
+	g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
 
 	/* no support */
 	if (klass->ensure_data == NULL) {
@@ -609,6 +610,7 @@ zif_package_get_summary (ZifPackage *package, GError **error)
 
 	g_return_val_if_fail (ZIF_IS_PACKAGE (package), NULL);
 	g_return_val_if_fail (package->priv->package_id_split != NULL, NULL);
+	g_return_val_if_fail (error == NULL || *error == NULL, NULL);
 
 	/* not exists */
 	if (package->priv->summary == NULL) {
@@ -639,6 +641,7 @@ zif_package_get_description (ZifPackage *package, GError **error)
 
 	g_return_val_if_fail (ZIF_IS_PACKAGE (package), NULL);
 	g_return_val_if_fail (package->priv->package_id_split != NULL, NULL);
+	g_return_val_if_fail (error == NULL || *error == NULL, NULL);
 
 	/* not exists */
 	if (package->priv->description == NULL) {
@@ -669,6 +672,7 @@ zif_package_get_license (ZifPackage *package, GError **error)
 
 	g_return_val_if_fail (ZIF_IS_PACKAGE (package), NULL);
 	g_return_val_if_fail (package->priv->package_id_split != NULL, NULL);
+	g_return_val_if_fail (error == NULL || *error == NULL, NULL);
 
 	/* not exists */
 	if (package->priv->license == NULL) {
@@ -699,6 +703,7 @@ zif_package_get_url (ZifPackage *package, GError **error)
 
 	g_return_val_if_fail (ZIF_IS_PACKAGE (package), NULL);
 	g_return_val_if_fail (package->priv->package_id_split != NULL, NULL);
+	g_return_val_if_fail (error == NULL || *error == NULL, NULL);
 
 	/* not exists */
 	if (package->priv->url == NULL) {
@@ -727,13 +732,7 @@ zif_package_get_filename (ZifPackage *package, GError **error)
 {
 	g_return_val_if_fail (ZIF_IS_PACKAGE (package), NULL);
 	g_return_val_if_fail (package->priv->package_id_split != NULL, NULL);
-
-	/* doesn't make much sense */
-	if (package->priv->installed) {
-		g_set_error_literal (error, ZIF_PACKAGE_ERROR, ZIF_PACKAGE_ERROR_FAILED,
-				     "cannot get remote filename for installed package");
-		return NULL;
-	}
+	g_return_val_if_fail (error == NULL || *error == NULL, NULL);
 
 	/* not exists */
 	if (package->priv->location_href == NULL) {
@@ -764,6 +763,7 @@ zif_package_get_category (ZifPackage *package, GError **error)
 
 	g_return_val_if_fail (ZIF_IS_PACKAGE (package), NULL);
 	g_return_val_if_fail (package->priv->package_id_split != NULL, NULL);
+	g_return_val_if_fail (error == NULL || *error == NULL, NULL);
 
 	/* not exists */
 	if (package->priv->category == NULL) {
@@ -792,6 +792,9 @@ zif_package_get_group (ZifPackage *package, GError **error)
 {
 	gboolean ret;
 
+	g_return_val_if_fail (ZIF_IS_PACKAGE (package), 0);
+	g_return_val_if_fail (error == NULL || *error == NULL, 0);
+
 	/* not exists */
 	if (package->priv->group == PK_GROUP_ENUM_UNKNOWN) {
 		ret = zif_package_ensure_data (package, ZIF_PACKAGE_ENSURE_TYPE_GROUP, error);
@@ -813,7 +816,7 @@ zif_package_get_group (ZifPackage *package, GError **error)
  * This is the installed size for installed packages, and the download size for
  * remote packages.
  *
- * Return value: %TRUE for success, %FALSE for failure
+ * Return value: the package size, or 0 for failure
  *
  * Since: 0.0.1
  **/
@@ -822,6 +825,9 @@ zif_package_get_size (ZifPackage *package, GError **error)
 {
 	gboolean ret;
 
+	g_return_val_if_fail (ZIF_IS_PACKAGE (package), 0);
+	g_return_val_if_fail (error == NULL || *error == NULL, 0);
+
 	if (package->priv->size == 0) {
 		ret = zif_package_ensure_data (package, ZIF_PACKAGE_ENSURE_TYPE_SIZE, error);
 		if (!ret)
@@ -851,6 +857,7 @@ zif_package_get_files (ZifPackage *package, GError **error)
 
 	g_return_val_if_fail (ZIF_IS_PACKAGE (package), NULL);
 	g_return_val_if_fail (package->priv->package_id_split != NULL, NULL);
+	g_return_val_if_fail (error == NULL || *error == NULL, NULL);
 
 	/* not exists */
 	if (package->priv->files == NULL) {
@@ -881,6 +888,7 @@ zif_package_get_requires (ZifPackage *package, GError **error)
 
 	g_return_val_if_fail (ZIF_IS_PACKAGE (package), NULL);
 	g_return_val_if_fail (package->priv->package_id_split != NULL, NULL);
+	g_return_val_if_fail (error == NULL || *error == NULL, NULL);
 
 	/* not exists */
 	if (package->priv->requires == NULL) {
@@ -911,6 +919,7 @@ zif_package_get_provides (ZifPackage *package, GError **error)
 
 	g_return_val_if_fail (ZIF_IS_PACKAGE (package), NULL);
 	g_return_val_if_fail (package->priv->package_id_split != NULL, NULL);
+	g_return_val_if_fail (error == NULL || *error == NULL, NULL);
 
 	/* not exists */
 	if (package->priv->requires == NULL) {
diff --git a/backends/yum/libzif/zif-repo-md-comps.c b/backends/yum/libzif/zif-repo-md-comps.c
index 066fb60..096176f 100644
--- a/backends/yum/libzif/zif-repo-md-comps.c
+++ b/backends/yum/libzif/zif-repo-md-comps.c
@@ -620,6 +620,7 @@ zif_repo_md_comps_get_groups_for_category (ZifRepoMdComps *md, const gchar *cate
 
 	g_return_val_if_fail (ZIF_IS_REPO_MD_COMPS (md), NULL);
 	g_return_val_if_fail (category_id != NULL, NULL);
+	g_return_val_if_fail (error == NULL || *error == NULL, NULL);
 
 	/* if not already loaded, load */
 	if (!md->priv->loaded) {
@@ -694,6 +695,7 @@ zif_repo_md_comps_get_packages_for_group (ZifRepoMdComps *md, const gchar *group
 
 	g_return_val_if_fail (ZIF_IS_REPO_MD_COMPS (md), NULL);
 	g_return_val_if_fail (group_id != NULL, NULL);
+	g_return_val_if_fail (error == NULL || *error == NULL, NULL);
 
 	/* if not already loaded, load */
 	if (!md->priv->loaded) {
diff --git a/backends/yum/libzif/zif-repo-md-filelists.c b/backends/yum/libzif/zif-repo-md-filelists.c
index 007610b..0bd808a 100644
--- a/backends/yum/libzif/zif-repo-md-filelists.c
+++ b/backends/yum/libzif/zif-repo-md-filelists.c
@@ -192,7 +192,8 @@ zif_repo_md_filelists_search_file (ZifRepoMdFilelists *md, const gchar *search,
 	gchar *dirname = NULL;
 	ZifRepoMdFilelistsData *data = NULL;
 
-	g_return_val_if_fail (ZIF_IS_REPO_MD_FILELISTS (md), FALSE);
+	g_return_val_if_fail (ZIF_IS_REPO_MD_FILELISTS (md), NULL);
+	g_return_val_if_fail (error == NULL || *error == NULL, NULL);
 
 	/* if not already loaded, load */
 	if (!md->priv->loaded) {
diff --git a/backends/yum/libzif/zif-repo-md-metalink.c b/backends/yum/libzif/zif-repo-md-metalink.c
index 7cbb8e1..743a133 100644
--- a/backends/yum/libzif/zif-repo-md-metalink.c
+++ b/backends/yum/libzif/zif-repo-md-metalink.c
@@ -282,7 +282,8 @@ zif_repo_md_metalink_get_uris (ZifRepoMdMetalink *md, guint threshold, GCancella
 	guint i;
 	ZifRepoMdMetalink *metalink = ZIF_REPO_MD_METALINK (md);
 
-	g_return_val_if_fail (ZIF_IS_REPO_MD_METALINK (md), FALSE);
+	g_return_val_if_fail (ZIF_IS_REPO_MD_METALINK (md), NULL);
+	g_return_val_if_fail (error == NULL || *error == NULL, NULL);
 
 	/* if not already loaded, load */
 	if (!metalink->priv->loaded) {
diff --git a/backends/yum/libzif/zif-repo-md-mirrorlist.c b/backends/yum/libzif/zif-repo-md-mirrorlist.c
index 34cdbf7..cd9077e 100644
--- a/backends/yum/libzif/zif-repo-md-mirrorlist.c
+++ b/backends/yum/libzif/zif-repo-md-mirrorlist.c
@@ -144,7 +144,8 @@ zif_repo_md_mirrorlist_get_uris (ZifRepoMdMirrorlist *md, GCancellable *cancella
 	guint i;
 	ZifRepoMdMirrorlist *mirrorlist = ZIF_REPO_MD_MIRRORLIST (md);
 
-	g_return_val_if_fail (ZIF_IS_REPO_MD_MIRRORLIST (md), FALSE);
+	g_return_val_if_fail (ZIF_IS_REPO_MD_MIRRORLIST (md), NULL);
+	g_return_val_if_fail (error == NULL || *error == NULL, NULL);
 
 	/* if not already loaded, load */
 	if (!mirrorlist->priv->loaded) {
diff --git a/backends/yum/libzif/zif-repo-md-primary.c b/backends/yum/libzif/zif-repo-md-primary.c
index 2dccab4..6d418e7 100644
--- a/backends/yum/libzif/zif-repo-md-primary.c
+++ b/backends/yum/libzif/zif-repo-md-primary.c
@@ -200,7 +200,8 @@ zif_repo_md_primary_resolve (ZifRepoMdPrimary *md, const gchar *search, GCancell
 	gchar *pred;
 	GPtrArray *array;
 
-	g_return_val_if_fail (ZIF_IS_REPO_MD_PRIMARY (md), FALSE);
+	g_return_val_if_fail (ZIF_IS_REPO_MD_PRIMARY (md), NULL);
+	g_return_val_if_fail (error == NULL || *error == NULL, NULL);
 
 	/* search with predicate */
 	pred = g_strdup_printf ("WHERE name = '%s'", search);
@@ -230,7 +231,8 @@ zif_repo_md_primary_search_name (ZifRepoMdPrimary *md, const gchar *search, GCan
 	gchar *pred;
 	GPtrArray *array;
 
-	g_return_val_if_fail (ZIF_IS_REPO_MD_PRIMARY (md), FALSE);
+	g_return_val_if_fail (ZIF_IS_REPO_MD_PRIMARY (md), NULL);
+	g_return_val_if_fail (error == NULL || *error == NULL, NULL);
 
 	/* search with predicate */
 	pred = g_strdup_printf ("WHERE name LIKE '%%%s%%'", search);
@@ -260,7 +262,8 @@ zif_repo_md_primary_search_details (ZifRepoMdPrimary *md, const gchar *search, G
 	gchar *pred;
 	GPtrArray *array;
 
-	g_return_val_if_fail (ZIF_IS_REPO_MD_PRIMARY (md), FALSE);
+	g_return_val_if_fail (ZIF_IS_REPO_MD_PRIMARY (md), NULL);
+	g_return_val_if_fail (error == NULL || *error == NULL, NULL);
 
 	/* search with predicate */
 	pred = g_strdup_printf ("WHERE name LIKE '%%%s%%' OR summary LIKE '%%%s%%' OR description LIKE '%%%s%%'", search, search, search);
@@ -290,7 +293,8 @@ zif_repo_md_primary_search_group (ZifRepoMdPrimary *md, const gchar *search, GCa
 	gchar *pred;
 	GPtrArray *array;
 
-	g_return_val_if_fail (ZIF_IS_REPO_MD_PRIMARY (md), FALSE);
+	g_return_val_if_fail (ZIF_IS_REPO_MD_PRIMARY (md), NULL);
+	g_return_val_if_fail (error == NULL || *error == NULL, NULL);
 
 	/* search with predicate */
 	pred = g_strdup_printf ("WHERE rpm_group = '%s'", search);
@@ -320,7 +324,8 @@ zif_repo_md_primary_search_pkgid (ZifRepoMdPrimary *md, const gchar *search, GCa
 	gchar *pred;
 	GPtrArray *array;
 
-	g_return_val_if_fail (ZIF_IS_REPO_MD_PRIMARY (md), FALSE);
+	g_return_val_if_fail (ZIF_IS_REPO_MD_PRIMARY (md), NULL);
+	g_return_val_if_fail (error == NULL || *error == NULL, NULL);
 
 	/* search with predicate */
 	pred = g_strdup_printf ("WHERE pkgid = '%s'", search);
@@ -351,7 +356,8 @@ zif_repo_md_primary_find_package (ZifRepoMdPrimary *md, const gchar *package_id,
 	GPtrArray *array;
 	gchar **split;
 
-	g_return_val_if_fail (ZIF_IS_REPO_MD_PRIMARY (md), FALSE);
+	g_return_val_if_fail (ZIF_IS_REPO_MD_PRIMARY (md), NULL);
+	g_return_val_if_fail (error == NULL || *error == NULL, NULL);
 
 	/* search with predicate, TODO: search version (epoch+release) */
 	split = pk_package_id_split (package_id);
@@ -381,7 +387,8 @@ zif_repo_md_primary_get_packages (ZifRepoMdPrimary *md, GCancellable *cancellabl
 {
 	GPtrArray *array;
 
-	g_return_val_if_fail (ZIF_IS_REPO_MD_PRIMARY (md), FALSE);
+	g_return_val_if_fail (ZIF_IS_REPO_MD_PRIMARY (md), NULL);
+	g_return_val_if_fail (error == NULL || *error == NULL, NULL);
 
 	/* search with predicate */
 	array = zif_repo_md_primary_search (md, "", cancellable, completion, error);
diff --git a/backends/yum/libzif/zif-repo-md.c b/backends/yum/libzif/zif-repo-md.c
index ba0889b..7ed680a 100644
--- a/backends/yum/libzif/zif-repo-md.c
+++ b/backends/yum/libzif/zif-repo-md.c
@@ -598,6 +598,7 @@ zif_repo_md_unload (ZifRepoMd *md, GCancellable *cancellable, ZifCompletion *com
 	ZifRepoMdClass *klass = ZIF_REPO_MD_GET_CLASS (md);
 
 	g_return_val_if_fail (ZIF_IS_REPO_MD (md), FALSE);
+	g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
 
 	/* no support */
 	if (klass->unload == NULL) {
@@ -630,6 +631,7 @@ zif_repo_md_clean (ZifRepoMd *md, GError **error)
 	GError *error_local = NULL;
 
 	g_return_val_if_fail (ZIF_IS_REPO_MD (md), FALSE);
+	g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
 
 	/* get filename */
 	filename = zif_repo_md_get_filename (md);
@@ -743,6 +745,7 @@ zif_repo_md_file_check (ZifRepoMd *md, gboolean use_uncompressed, GError **error
 
 	g_return_val_if_fail (ZIF_IS_REPO_MD (md), FALSE);
 	g_return_val_if_fail (md->priv->id != NULL, FALSE);
+	g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
 
 	/* metalink has no checksum... */
 	if (md->priv->type == ZIF_REPO_MD_TYPE_METALINK ||
diff --git a/backends/yum/libzif/zif-repos.c b/backends/yum/libzif/zif-repos.c
index 9537fa5..1ce63b2 100644
--- a/backends/yum/libzif/zif-repos.c
+++ b/backends/yum/libzif/zif-repos.c
@@ -96,6 +96,7 @@ zif_repos_set_repos_dir (ZifRepos *repos, const gchar *repos_dir, GError **error
 	g_return_val_if_fail (repos->priv->repos_dir == NULL, FALSE);
 	g_return_val_if_fail (!repos->priv->loaded, FALSE);
 	g_return_val_if_fail (repos_dir != NULL, FALSE);
+	g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
 
 	/* check directory exists */
 	ret = g_file_test (repos_dir, G_FILE_TEST_IS_DIR);
@@ -201,6 +202,7 @@ zif_repos_load (ZifRepos *repos, GCancellable *cancellable, ZifCompletion *compl
 
 	g_return_val_if_fail (ZIF_IS_REPOS (repos), FALSE);
 	g_return_val_if_fail (repos->priv->repos_dir != NULL, FALSE);
+	g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
 
 	/* already loaded */
 	if (repos->priv->loaded)
@@ -312,10 +314,11 @@ GPtrArray *
 zif_repos_get_stores (ZifRepos *repos, GCancellable *cancellable, ZifCompletion *completion, GError **error)
 {
 	GPtrArray *array = NULL;
-	GError *error_local;
+	GError *error_local = NULL;
 	gboolean ret;
 
-	g_return_val_if_fail (ZIF_IS_REPOS (repos), FALSE);
+	g_return_val_if_fail (ZIF_IS_REPOS (repos), NULL);
+	g_return_val_if_fail (error == NULL || *error == NULL, NULL);
 
 	/* if not already loaded, load */
 	if (!repos->priv->loaded) {
@@ -351,12 +354,13 @@ GPtrArray *
 zif_repos_get_stores_enabled (ZifRepos *repos, GCancellable *cancellable, ZifCompletion *completion, GError **error)
 {
 	GPtrArray *array = NULL;
-	GError *error_local;
+	GError *error_local = NULL;
 	ZifStoreRemote *store;
 	gboolean ret;
 	guint i;
 
-	g_return_val_if_fail (ZIF_IS_REPOS (repos), FALSE);
+	g_return_val_if_fail (ZIF_IS_REPOS (repos), NULL);
+	g_return_val_if_fail (error == NULL || *error == NULL, NULL);
 
 	/* if not already loaded, load */
 	if (!repos->priv->loaded) {
@@ -400,11 +404,12 @@ zif_repos_get_store (ZifRepos *repos, const gchar *id, GCancellable *cancellable
 	ZifStoreRemote *store = NULL;
 	ZifStoreRemote *store_tmp;
 	const gchar *id_tmp;
-	GError *error_local;
+	GError *error_local = NULL;
 	gboolean ret;
 
-	g_return_val_if_fail (ZIF_IS_REPOS (repos), FALSE);
-	g_return_val_if_fail (id != NULL, FALSE);
+	g_return_val_if_fail (ZIF_IS_REPOS (repos), NULL);
+	g_return_val_if_fail (id != NULL, NULL);
+	g_return_val_if_fail (error == NULL || *error == NULL, NULL);
 
 	/* if not already loaded, load */
 	if (!repos->priv->loaded) {
diff --git a/backends/yum/libzif/zif-store-array.c b/backends/yum/libzif/zif-store-array.c
index 051beb1..a6fc2ba 100644
--- a/backends/yum/libzif/zif-store-array.c
+++ b/backends/yum/libzif/zif-store-array.c
@@ -321,6 +321,8 @@ zif_store_array_find_package (GPtrArray *store_array, const gchar *package_id, G
 	ZifPackage *package = NULL;
 	ZifCompletion *completion_local = NULL;
 
+	g_return_val_if_fail (error == NULL || *error == NULL, NULL);
+
 	/* nothing to do */
 	if (store_array->len == 0) {
 		g_set_error_literal (error, ZIF_STORE_ERROR, ZIF_STORE_ERROR_ARRAY_IS_EMPTY,
@@ -380,6 +382,8 @@ zif_store_array_clean (GPtrArray *store_array,
 	GError *error_local = NULL;
 	ZifCompletion *completion_local = NULL;
 
+	g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+
 	/* nothing to do */
 	if (store_array->len == 0) {
 		egg_debug ("nothing to do");
@@ -399,6 +403,7 @@ zif_store_array_clean (GPtrArray *store_array,
 		if (!ret) {
 			/* do we need to skip this error */
 			if (error_cb != NULL && error_cb (store_array, error_local, user_data)) {
+				ret = TRUE;
 				g_clear_error (&error_local);
 				goto skip_error;
 			}
@@ -442,6 +447,8 @@ zif_store_array_refresh (GPtrArray *store_array, gboolean force,
 	GError *error_local = NULL;
 	ZifCompletion *completion_local = NULL;
 
+	g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+
 	/* nothing to do */
 	if (store_array->len == 0) {
 		egg_debug ("nothing to do");
@@ -461,6 +468,7 @@ zif_store_array_refresh (GPtrArray *store_array, gboolean force,
 		if (!ret) {
 			/* do we need to skip this error */
 			if (error_cb != NULL && error_cb (store_array, error_local, user_data)) {
+				ret = TRUE;
 				g_clear_error (&error_local);
 				goto skip_error;
 			}
@@ -498,6 +506,7 @@ zif_store_array_resolve (GPtrArray *store_array, const gchar *search,
 			 ZifStoreArrayErrorCb error_cb, gpointer user_data,
 			 GCancellable *cancellable, ZifCompletion *completion, GError **error)
 {
+	g_return_val_if_fail (error == NULL || *error == NULL, NULL);
 	return zif_store_array_repos_search (store_array, PK_ROLE_ENUM_RESOLVE, search,
 					     error_cb, user_data, cancellable, completion, error);
 }
@@ -523,6 +532,7 @@ zif_store_array_search_name (GPtrArray *store_array, const gchar *search,
 			     ZifStoreArrayErrorCb error_cb, gpointer user_data,
 			     GCancellable *cancellable, ZifCompletion *completion, GError **error)
 {
+	g_return_val_if_fail (error == NULL || *error == NULL, NULL);
 	return zif_store_array_repos_search (store_array, PK_ROLE_ENUM_SEARCH_NAME, search,
 					     error_cb, user_data, cancellable, completion, error);
 }
@@ -548,6 +558,7 @@ zif_store_array_search_details (GPtrArray *store_array, const gchar *search,
 				ZifStoreArrayErrorCb error_cb, gpointer user_data,
 				GCancellable *cancellable, ZifCompletion *completion, GError **error)
 {
+	g_return_val_if_fail (error == NULL || *error == NULL, NULL);
 	return zif_store_array_repos_search (store_array, PK_ROLE_ENUM_SEARCH_DETAILS, search,
 					     error_cb, user_data, cancellable, completion, error);
 }
@@ -573,6 +584,7 @@ zif_store_array_search_group (GPtrArray *store_array, const gchar *group_enum,
 			      ZifStoreArrayErrorCb error_cb, gpointer user_data,
 			      GCancellable *cancellable, ZifCompletion *completion, GError **error)
 {
+	g_return_val_if_fail (error == NULL || *error == NULL, NULL);
 	return zif_store_array_repos_search (store_array, PK_ROLE_ENUM_SEARCH_GROUP, group_enum,
 					     error_cb, user_data, cancellable, completion, error);
 }
@@ -605,6 +617,8 @@ zif_store_array_search_category (GPtrArray *store_array, const gchar *group_id,
 	const gchar *package_id_tmp;
 	gchar **split;
 
+	g_return_val_if_fail (error == NULL || *error == NULL, NULL);
+
 	/* get all results from all repos */
 	array = zif_store_array_repos_search (store_array, PK_ROLE_ENUM_SEARCH_CATEGORY, group_id,
 					      error_cb, user_data, cancellable, completion, error);
@@ -653,6 +667,7 @@ zif_store_array_search_file (GPtrArray *store_array, const gchar *search,
 			     ZifStoreArrayErrorCb error_cb, gpointer user_data,
 			     GCancellable *cancellable, ZifCompletion *completion, GError **error)
 {
+	g_return_val_if_fail (error == NULL || *error == NULL, NULL);
 	return zif_store_array_repos_search (store_array, PK_ROLE_ENUM_SEARCH_FILE, search,
 					     error_cb, user_data, cancellable, completion, error);
 }
@@ -677,6 +692,7 @@ zif_store_array_get_packages (GPtrArray *store_array,
 			      ZifStoreArrayErrorCb error_cb, gpointer user_data,
 			      GCancellable *cancellable, ZifCompletion *completion, GError **error)
 {
+	g_return_val_if_fail (error == NULL || *error == NULL, NULL);
 	return zif_store_array_repos_search (store_array, PK_ROLE_ENUM_GET_PACKAGES, NULL,
 					     error_cb, user_data, cancellable, completion, error);
 }
@@ -701,6 +717,7 @@ zif_store_array_get_updates (GPtrArray *store_array,
 			     ZifStoreArrayErrorCb error_cb, gpointer user_data,
 			     GCancellable *cancellable, ZifCompletion *completion, GError **error)
 {
+	g_return_val_if_fail (error == NULL || *error == NULL, NULL);
 	return zif_store_array_repos_search (store_array, PK_ROLE_ENUM_GET_UPDATES, NULL,
 					     error_cb, user_data, cancellable, completion, error);
 }
@@ -726,6 +743,7 @@ zif_store_array_what_provides (GPtrArray *store_array, const gchar *search,
 			       ZifStoreArrayErrorCb error_cb, gpointer user_data,
 			       GCancellable *cancellable, ZifCompletion *completion, GError **error)
 {
+	g_return_val_if_fail (error == NULL || *error == NULL, NULL);
 
 	/* if this is a path, then we use the file list and treat like a SearchFile */
 	if (g_str_has_prefix (search, "/")) {
@@ -765,6 +783,8 @@ zif_store_array_get_categories (GPtrArray *store_array,
 	gchar *cat_id;
 	gchar *cat_id_tmp;
 
+	g_return_val_if_fail (error == NULL || *error == NULL, NULL);
+
 	/* get all results from all repos */
 	array = zif_store_array_repos_search (store_array, PK_ROLE_ENUM_GET_CATEGORIES, NULL,
 					      error_cb, user_data, cancellable, completion, error);
diff --git a/backends/yum/libzif/zif-store-local.c b/backends/yum/libzif/zif-store-local.c
index 47db128..6b45237 100644
--- a/backends/yum/libzif/zif-store-local.c
+++ b/backends/yum/libzif/zif-store-local.c
@@ -90,6 +90,7 @@ zif_store_local_set_prefix (ZifStoreLocal *store, const gchar *prefix, GError **
 	g_return_val_if_fail (store->priv->prefix == NULL, FALSE);
 	g_return_val_if_fail (!store->priv->loaded, FALSE);
 	g_return_val_if_fail (prefix != NULL, FALSE);
+	g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
 
 	/* check file exists */
 	ret = g_file_test (prefix, G_FILE_TEST_IS_DIR);
diff --git a/backends/yum/libzif/zif-store-remote.c b/backends/yum/libzif/zif-store-remote.c
index ead84e2..f76e41a 100644
--- a/backends/yum/libzif/zif-store-remote.c
+++ b/backends/yum/libzif/zif-store-remote.c
@@ -384,6 +384,7 @@ zif_store_remote_download (ZifStoreRemote *store, const gchar *filename, const g
 	g_return_val_if_fail (store->priv->id != NULL, FALSE);
 	g_return_val_if_fail (filename != NULL, FALSE);
 	g_return_val_if_fail (directory != NULL, FALSE);
+	g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
 
 	/* if not online, then this is fatal */
 	ret = zif_config_get_boolean (store->priv->config, "network", NULL);
@@ -393,6 +394,14 @@ zif_store_remote_download (ZifStoreRemote *store, const gchar *filename, const g
 		goto out;
 	}
 
+	/* check this isn't an absolute path */
+	if (g_str_has_prefix (filename, "/")) {
+		g_set_error (error, ZIF_STORE_ERROR, ZIF_STORE_ERROR_FAILED_AS_OFFLINE,
+			     "filename %s' should not be an absolute path", filename);
+		ret = FALSE;
+		goto out;
+	}
+
 	/* setup completion */
 	if (store->priv->loaded_metadata)
 		zif_completion_set_number_steps (completion, 1);
@@ -440,7 +449,7 @@ zif_store_remote_download (ZifStoreRemote *store, const gchar *filename, const g
 
 		/* build url */
 		baseurl = g_ptr_array_index (store->priv->baseurls, i);
-		uri = g_build_filename (baseurl, "repodata", basename, NULL);
+		uri = g_build_filename (baseurl, filename, NULL);
 
 		/* try download */
 		zif_completion_reset (completion_local);
@@ -521,6 +530,7 @@ zif_store_remote_add_metalink (ZifStoreRemote *store, GCancellable *cancellable,
 	completion_local = zif_completion_get_child (completion);
 	array = zif_repo_md_metalink_get_uris (ZIF_REPO_MD_METALINK (store->priv->md_metalink), 50, cancellable, completion_local, &error_local);
 	if (array == NULL) {
+		ret = FALSE;
 		g_set_error (error, ZIF_STORE_ERROR, ZIF_STORE_ERROR_FAILED,
 			     "failed to add mirrors from metalink: %s", error_local->message);
 		g_error_free (error_local);
@@ -595,6 +605,7 @@ zif_store_remote_add_mirrorlist (ZifStoreRemote *store, GCancellable *cancellabl
 	completion_local = zif_completion_get_child (completion);
 	array = zif_repo_md_mirrorlist_get_uris (ZIF_REPO_MD_MIRRORLIST (store->priv->md_mirrorlist), cancellable, completion_local, &error_local);
 	if (array == NULL) {
+		ret = FALSE;
 		g_set_error (error, ZIF_STORE_ERROR, ZIF_STORE_ERROR_FAILED,
 			     "failed to add mirrors from mirrorlist: %s", error_local->message);
 		g_error_free (error_local);
@@ -871,8 +882,8 @@ zif_store_remote_refresh (ZifStore *store, gboolean force, GCancellable *cancell
 	/* get local completion object */
 	completion_local = zif_completion_get_child (completion);
 
-	/* download new file */
-	ret = zif_store_remote_download (remote, remote->priv->repomd_filename, remote->priv->directory, cancellable, completion_local, &error_local);
+	/* download new repomd file */
+	ret = zif_store_remote_download (remote, "repodata/repomd.xml", remote->priv->directory, cancellable, completion_local, &error_local);
 	if (!ret) {
 		g_set_error (error, ZIF_STORE_ERROR, ZIF_STORE_ERROR_FAILED,
 			     "failed to download repomd: %s", error_local->message);
@@ -905,7 +916,7 @@ zif_store_remote_refresh (ZifStore *store, gboolean force, GCancellable *cancell
 		}
 
 		/* get filename */
-		filename = zif_repo_md_get_filename (md);
+		filename = zif_repo_md_get_location (md);
 		if (filename == NULL) {
 			egg_warning ("no filename set for %s", zif_repo_md_type_to_text (i));
 			continue;
@@ -913,8 +924,12 @@ zif_store_remote_refresh (ZifStore *store, gboolean force, GCancellable *cancell
 
 		/* does current uncompressed file equal what repomd says it should be */
 		ret = zif_repo_md_file_check (md, TRUE, &error_local);
+		if (!ret) {
+			egg_warning ("failed to verify md: %s", error_local->message);
+			g_clear_error (&error_local);
+		}
 		if (ret && !force) {
-			egg_debug ("%s is okay", zif_repo_md_type_to_text (i));
+			egg_debug ("%s is okay, and we're not forcing", zif_repo_md_type_to_text (i));
 			continue;
 		}
 
@@ -933,6 +948,7 @@ zif_store_remote_refresh (ZifStore *store, gboolean force, GCancellable *cancell
 
 		/* decompress */
 		completion_local = zif_completion_get_child (completion);
+		filename = zif_repo_md_get_filename (md);
 		ret = zif_store_file_decompress (filename, cancellable, completion_local, &error_local);
 		if (!ret) {
 			g_set_error (error, ZIF_STORE_ERROR, ZIF_STORE_ERROR_FAILED,
@@ -1206,6 +1222,7 @@ zif_store_remote_set_from_file (ZifStoreRemote *store, const gchar *repo_filenam
 	g_return_val_if_fail (id != NULL, FALSE);
 	g_return_val_if_fail (store->priv->id == NULL, FALSE);
 	g_return_val_if_fail (!store->priv->loaded, FALSE);
+	g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
 
 	/* not locked */
 	ret = zif_lock_is_locked (store->priv->lock, NULL);
@@ -1276,6 +1293,7 @@ zif_store_remote_set_enabled (ZifStoreRemote *store, gboolean enabled, GError **
 
 	g_return_val_if_fail (ZIF_IS_STORE_REMOTE (store), FALSE);
 	g_return_val_if_fail (store->priv->id != NULL, FALSE);
+	g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
 
 	/* not locked */
 	ret = zif_lock_is_locked (store->priv->lock, NULL);
@@ -1344,8 +1362,8 @@ zif_store_remote_resolve (ZifStore *store, const gchar *search, GCancellable *ca
 	ZifStoreRemote *remote = ZIF_STORE_REMOTE (store);
 	ZifCompletion *completion_local;
 
-	g_return_val_if_fail (ZIF_IS_STORE_REMOTE (store), FALSE);
-	g_return_val_if_fail (remote->priv->id != NULL, FALSE);
+	g_return_val_if_fail (ZIF_IS_STORE_REMOTE (store), NULL);
+	g_return_val_if_fail (remote->priv->id != NULL, NULL);
 
 	/* not locked */
 	ret = zif_lock_is_locked (remote->priv->lock, NULL);
@@ -1397,8 +1415,8 @@ zif_store_remote_search_name (ZifStore *store, const gchar *search, GCancellable
 	ZifStoreRemote *remote = ZIF_STORE_REMOTE (store);
 	ZifCompletion *completion_local;
 
-	g_return_val_if_fail (ZIF_IS_STORE_REMOTE (store), FALSE);
-	g_return_val_if_fail (remote->priv->id != NULL, FALSE);
+	g_return_val_if_fail (ZIF_IS_STORE_REMOTE (store), NULL);
+	g_return_val_if_fail (remote->priv->id != NULL, NULL);
 
 	/* not locked */
 	ret = zif_lock_is_locked (remote->priv->lock, NULL);
@@ -1450,8 +1468,8 @@ zif_store_remote_search_details (ZifStore *store, const gchar *search, GCancella
 	ZifStoreRemote *remote = ZIF_STORE_REMOTE (store);
 	ZifCompletion *completion_local;
 
-	g_return_val_if_fail (ZIF_IS_STORE_REMOTE (store), FALSE);
-	g_return_val_if_fail (remote->priv->id != NULL, FALSE);
+	g_return_val_if_fail (ZIF_IS_STORE_REMOTE (store), NULL);
+	g_return_val_if_fail (remote->priv->id != NULL, NULL);
 
 	/* not locked */
 	ret = zif_lock_is_locked (remote->priv->lock, NULL);
@@ -1579,8 +1597,8 @@ zif_store_remote_search_category (ZifStore *store, const gchar *group_id, GCance
 	const gchar *location;
 	guint i;
 
-	g_return_val_if_fail (ZIF_IS_STORE_REMOTE (store), FALSE);
-	g_return_val_if_fail (remote->priv->id != NULL, FALSE);
+	g_return_val_if_fail (ZIF_IS_STORE_REMOTE (store), NULL);
+	g_return_val_if_fail (remote->priv->id != NULL, NULL);
 
 	/* not locked */
 	ret = zif_lock_is_locked (remote->priv->lock, NULL);
@@ -1698,8 +1716,8 @@ zif_store_remote_search_group (ZifStore *store, const gchar *search, GCancellabl
 	ZifStoreRemote *remote = ZIF_STORE_REMOTE (store);
 	ZifCompletion *completion_local;
 
-	g_return_val_if_fail (ZIF_IS_STORE_REMOTE (store), FALSE);
-	g_return_val_if_fail (remote->priv->id != NULL, FALSE);
+	g_return_val_if_fail (ZIF_IS_STORE_REMOTE (store), NULL);
+	g_return_val_if_fail (remote->priv->id != NULL, NULL);
 
 	/* not locked */
 	ret = zif_lock_is_locked (remote->priv->lock, NULL);
@@ -1752,8 +1770,8 @@ zif_store_remote_find_package (ZifStore *store, const gchar *package_id, GCancel
 	ZifStoreRemote *remote = ZIF_STORE_REMOTE (store);
 	ZifCompletion *completion_local;
 
-	g_return_val_if_fail (ZIF_IS_STORE_REMOTE (store), FALSE);
-	g_return_val_if_fail (remote->priv->id != NULL, FALSE);
+	g_return_val_if_fail (ZIF_IS_STORE_REMOTE (store), NULL);
+	g_return_val_if_fail (remote->priv->id != NULL, NULL);
 
 	/* not locked */
 	ret = zif_lock_is_locked (remote->priv->lock, NULL);
@@ -1830,8 +1848,8 @@ zif_store_remote_get_packages (ZifStore *store, GCancellable *cancellable, ZifCo
 	ZifStoreRemote *remote = ZIF_STORE_REMOTE (store);
 	ZifCompletion *completion_local;
 
-	g_return_val_if_fail (ZIF_IS_STORE_REMOTE (store), FALSE);
-	g_return_val_if_fail (remote->priv->id != NULL, FALSE);
+	g_return_val_if_fail (ZIF_IS_STORE_REMOTE (store), NULL);
+	g_return_val_if_fail (remote->priv->id != NULL, NULL);
 
 	/* not locked */
 	ret = zif_lock_is_locked (remote->priv->lock, NULL);
@@ -1892,8 +1910,8 @@ zif_store_remote_get_categories (ZifStore *store, GCancellable *cancellable, Zif
 	PkCategory *category;
 	PkCategory *category_tmp;
 
-	g_return_val_if_fail (ZIF_IS_STORE_REMOTE (store), FALSE);
-	g_return_val_if_fail (remote->priv->id != NULL, FALSE);
+	g_return_val_if_fail (ZIF_IS_STORE_REMOTE (store), NULL);
+	g_return_val_if_fail (remote->priv->id != NULL, NULL);
 
 	/* not locked */
 	ret = zif_lock_is_locked (remote->priv->lock, NULL);
@@ -2261,6 +2279,7 @@ zif_store_remote_is_devel (ZifStoreRemote *store, GCancellable *cancellable, Zif
 
 	g_return_val_if_fail (ZIF_IS_STORE_REMOTE (store), FALSE);
 	g_return_val_if_fail (store->priv->id != NULL, FALSE);
+	g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
 
 	/* not locked */
 	ret = zif_lock_is_locked (store->priv->lock, NULL);
@@ -2333,6 +2352,7 @@ zif_store_remote_get_name (ZifStoreRemote *store, GCancellable *cancellable, Zif
 
 	g_return_val_if_fail (ZIF_IS_STORE_REMOTE (store), NULL);
 	g_return_val_if_fail (store->priv->id != NULL, NULL);
+	g_return_val_if_fail (error == NULL || *error == NULL, NULL);
 
 	/* not locked */
 	ret = zif_lock_is_locked (store->priv->lock, NULL);
@@ -2377,6 +2397,7 @@ zif_store_remote_get_enabled (ZifStoreRemote *store, GCancellable *cancellable,
 
 	g_return_val_if_fail (ZIF_IS_STORE_REMOTE (store), FALSE);
 	g_return_val_if_fail (store->priv->id != NULL, FALSE);
+	g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
 
 	/* not locked */
 	ret = zif_lock_is_locked (store->priv->lock, NULL);
diff --git a/backends/yum/libzif/zif-store.c b/backends/yum/libzif/zif-store.c
index 9646833..efba57d 100644
--- a/backends/yum/libzif/zif-store.c
+++ b/backends/yum/libzif/zif-store.c
@@ -76,6 +76,7 @@ zif_store_load (ZifStore *store, GCancellable *cancellable, ZifCompletion *compl
 	ZifStoreClass *klass = ZIF_STORE_GET_CLASS (store);
 
 	g_return_val_if_fail (ZIF_IS_STORE (store), FALSE);
+	g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
 
 	/* no support */
 	if (klass->load == NULL) {
@@ -106,6 +107,7 @@ zif_store_clean (ZifStore *store, GCancellable *cancellable, ZifCompletion *comp
 	ZifStoreClass *klass = ZIF_STORE_GET_CLASS (store);
 
 	g_return_val_if_fail (ZIF_IS_STORE (store), FALSE);
+	g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
 
 	/* no support */
 	if (klass->clean == NULL) {
@@ -137,6 +139,7 @@ zif_store_refresh (ZifStore *store, gboolean force, GCancellable *cancellable, Z
 	ZifStoreClass *klass = ZIF_STORE_GET_CLASS (store);
 
 	g_return_val_if_fail (ZIF_IS_STORE (store), FALSE);
+	g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
 
 	/* no support */
 	if (klass->refresh == NULL) {
@@ -167,14 +170,15 @@ zif_store_search_name (ZifStore *store, const gchar *search, GCancellable *cance
 {
 	ZifStoreClass *klass = ZIF_STORE_GET_CLASS (store);
 
-	g_return_val_if_fail (ZIF_IS_STORE (store), FALSE);
+	g_return_val_if_fail (ZIF_IS_STORE (store), NULL);
 	g_return_val_if_fail (search != NULL, NULL);
+	g_return_val_if_fail (error == NULL || *error == NULL, NULL);
 
 	/* no support */
 	if (klass->search_name == NULL) {
 		g_set_error_literal (error, ZIF_STORE_ERROR, ZIF_STORE_ERROR_NO_SUPPORT,
 				     "operation cannot be performed on this store");
-		return FALSE;
+		return NULL;
 	}
 
 	return klass->search_name (store, search, cancellable, completion, error);
@@ -199,14 +203,15 @@ zif_store_search_category (ZifStore *store, const gchar *search, GCancellable *c
 {
 	ZifStoreClass *klass = ZIF_STORE_GET_CLASS (store);
 
-	g_return_val_if_fail (ZIF_IS_STORE (store), FALSE);
+	g_return_val_if_fail (ZIF_IS_STORE (store), NULL);
 	g_return_val_if_fail (search != NULL, NULL);
+	g_return_val_if_fail (error == NULL || *error == NULL, NULL);
 
 	/* no support */
 	if (klass->search_category == NULL) {
 		g_set_error_literal (error, ZIF_STORE_ERROR, ZIF_STORE_ERROR_NO_SUPPORT,
 				     "operation cannot be performed on this store");
-		return FALSE;
+		return NULL;
 	}
 
 	return klass->search_category (store, search, cancellable, completion, error);
@@ -231,14 +236,14 @@ zif_store_search_details (ZifStore *store, const gchar *search, GCancellable *ca
 {
 	ZifStoreClass *klass = ZIF_STORE_GET_CLASS (store);
 
-	g_return_val_if_fail (ZIF_IS_STORE (store), FALSE);
+	g_return_val_if_fail (ZIF_IS_STORE (store), NULL);
 	g_return_val_if_fail (search != NULL, NULL);
 
 	/* no support */
 	if (klass->search_details == NULL) {
 		g_set_error_literal (error, ZIF_STORE_ERROR, ZIF_STORE_ERROR_NO_SUPPORT,
 				     "operation cannot be performed on this store");
-		return FALSE;
+		return NULL;
 	}
 
 	return klass->search_details (store, search, cancellable, completion, error);
@@ -263,14 +268,15 @@ zif_store_search_group (ZifStore *store, const gchar *search, GCancellable *canc
 {
 	ZifStoreClass *klass = ZIF_STORE_GET_CLASS (store);
 
-	g_return_val_if_fail (ZIF_IS_STORE (store), FALSE);
+	g_return_val_if_fail (ZIF_IS_STORE (store), NULL);
 	g_return_val_if_fail (search != NULL, NULL);
+	g_return_val_if_fail (error == NULL || *error == NULL, NULL);
 
 	/* no support */
 	if (klass->search_group == NULL) {
 		g_set_error_literal (error, ZIF_STORE_ERROR, ZIF_STORE_ERROR_NO_SUPPORT,
 				     "operation cannot be performed on this store");
-		return FALSE;
+		return NULL;
 	}
 
 	return klass->search_group (store, search, cancellable, completion, error);
@@ -295,14 +301,15 @@ zif_store_search_file (ZifStore *store, const gchar *search, GCancellable *cance
 {
 	ZifStoreClass *klass = ZIF_STORE_GET_CLASS (store);
 
-	g_return_val_if_fail (ZIF_IS_STORE (store), FALSE);
+	g_return_val_if_fail (ZIF_IS_STORE (store), NULL);
 	g_return_val_if_fail (search != NULL, NULL);
+	g_return_val_if_fail (error == NULL || *error == NULL, NULL);
 
 	/* no support */
 	if (klass->search_file == NULL) {
 		g_set_error_literal (error, ZIF_STORE_ERROR, ZIF_STORE_ERROR_NO_SUPPORT,
 				     "operation cannot be performed on this store");
-		return FALSE;
+		return NULL;
 	}
 
 	return klass->search_file (store, search, cancellable, completion, error);
@@ -327,14 +334,15 @@ zif_store_resolve (ZifStore *store, const gchar *search, GCancellable *cancellab
 {
 	ZifStoreClass *klass = ZIF_STORE_GET_CLASS (store);
 
-	g_return_val_if_fail (ZIF_IS_STORE (store), FALSE);
+	g_return_val_if_fail (ZIF_IS_STORE (store), NULL);
 	g_return_val_if_fail (search != NULL, NULL);
+	g_return_val_if_fail (error == NULL || *error == NULL, NULL);
 
 	/* no support */
 	if (klass->resolve == NULL) {
 		g_set_error_literal (error, ZIF_STORE_ERROR, ZIF_STORE_ERROR_NO_SUPPORT,
 				     "operation cannot be performed on this store");
-		return FALSE;
+		return NULL;
 	}
 
 	return klass->resolve (store, search, cancellable, completion, error);
@@ -359,14 +367,15 @@ zif_store_what_provides (ZifStore *store, const gchar *search, GCancellable *can
 {
 	ZifStoreClass *klass = ZIF_STORE_GET_CLASS (store);
 
-	g_return_val_if_fail (ZIF_IS_STORE (store), FALSE);
+	g_return_val_if_fail (ZIF_IS_STORE (store), NULL);
 	g_return_val_if_fail (search != NULL, NULL);
+	g_return_val_if_fail (error == NULL || *error == NULL, NULL);
 
 	/* no support */
 	if (klass->search_name == NULL) {
 		g_set_error_literal (error, ZIF_STORE_ERROR, ZIF_STORE_ERROR_NO_SUPPORT,
 				     "operation cannot be performed on this store");
-		return FALSE;
+		return NULL;
 	}
 
 	return klass->what_provides (store, search, cancellable, completion, error);
@@ -390,13 +399,14 @@ zif_store_get_packages (ZifStore *store, GCancellable *cancellable, ZifCompletio
 {
 	ZifStoreClass *klass = ZIF_STORE_GET_CLASS (store);
 
-	g_return_val_if_fail (ZIF_IS_STORE (store), FALSE);
+	g_return_val_if_fail (ZIF_IS_STORE (store), NULL);
+	g_return_val_if_fail (error == NULL || *error == NULL, NULL);
 
 	/* no support */
 	if (klass->get_packages == NULL) {
 		g_set_error_literal (error, ZIF_STORE_ERROR, ZIF_STORE_ERROR_NO_SUPPORT,
 				     "operation cannot be performed on this store");
-		return FALSE;
+		return NULL;
 	}
 
 	return klass->get_packages (store, cancellable, completion, error);
@@ -420,13 +430,14 @@ zif_store_get_updates (ZifStore *store, GCancellable *cancellable, ZifCompletion
 {
 	ZifStoreClass *klass = ZIF_STORE_GET_CLASS (store);
 
-	g_return_val_if_fail (ZIF_IS_STORE (store), FALSE);
+	g_return_val_if_fail (ZIF_IS_STORE (store), NULL);
+	g_return_val_if_fail (error == NULL || *error == NULL, NULL);
 
 	/* no support */
 	if (klass->get_updates == NULL) {
 		g_set_error_literal (error, ZIF_STORE_ERROR, ZIF_STORE_ERROR_NO_SUPPORT,
 				     "operation cannot be performed on this store");
-		return FALSE;
+		return NULL;
 	}
 
 	return klass->get_updates (store, cancellable, completion, error);
@@ -451,14 +462,15 @@ zif_store_find_package (ZifStore *store, const gchar *package_id, GCancellable *
 {
 	ZifStoreClass *klass = ZIF_STORE_GET_CLASS (store);
 
-	g_return_val_if_fail (ZIF_IS_STORE (store), FALSE);
+	g_return_val_if_fail (ZIF_IS_STORE (store), NULL);
 	g_return_val_if_fail (package_id != NULL, NULL);
+	g_return_val_if_fail (error == NULL || *error == NULL, NULL);
 
 	/* no support */
 	if (klass->find_package == NULL) {
 		g_set_error_literal (error, ZIF_STORE_ERROR, ZIF_STORE_ERROR_NO_SUPPORT,
 				     "operation cannot be performed on this store");
-		return FALSE;
+		return NULL;
 	}
 
 	return klass->find_package (store, package_id, cancellable, completion, error);
@@ -482,13 +494,14 @@ zif_store_get_categories (ZifStore *store, GCancellable *cancellable, ZifComplet
 {
 	ZifStoreClass *klass = ZIF_STORE_GET_CLASS (store);
 
-	g_return_val_if_fail (ZIF_IS_STORE (store), FALSE);
+	g_return_val_if_fail (ZIF_IS_STORE (store), NULL);
+	g_return_val_if_fail (error == NULL || *error == NULL, NULL);
 
 	/* no support */
 	if (klass->get_categories == NULL) {
 		g_set_error_literal (error, ZIF_STORE_ERROR, ZIF_STORE_ERROR_NO_SUPPORT,
 				     "operation cannot be performed on this store");
-		return FALSE;
+		return NULL;
 	}
 
 	return klass->get_categories (store, cancellable, completion, error);
diff --git a/backends/yum/libzif/zif-utils.c b/backends/yum/libzif/zif-utils.c
index ed13e36..276f4bf 100644
--- a/backends/yum/libzif/zif-utils.c
+++ b/backends/yum/libzif/zif-utils.c
@@ -504,6 +504,7 @@ zif_file_untar (const gchar *filename, const gchar *directory, GError **error)
 
 	g_return_val_if_fail (filename != NULL, FALSE);
 	g_return_val_if_fail (directory != NULL, FALSE);
+	g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
 
 	/* save the PWD as we chdir to extract */
 	retcwd = getcwd (buf, PATH_MAX);
diff --git a/backends/yum/pk-backend-yum.c b/backends/yum/pk-backend-yum.c
index 77dfd95..cea97cf 100644
--- a/backends/yum/pk-backend-yum.c
+++ b/backends/yum/pk-backend-yum.c
@@ -912,6 +912,9 @@ backend_download_packages_thread (PkBackend *backend)
 	guint len;
 	gboolean ret;
 	GError *error = NULL;
+	ZifString *filename;
+	gchar *basename;
+	gchar *path;
 
 	/* get lock */
 	ret = backend_get_lock (backend);
@@ -963,17 +966,18 @@ backend_download_packages_thread (PkBackend *backend)
 	pk_backend_set_status (backend, PK_STATUS_ENUM_DOWNLOAD);
 	for (i=0; i<packages->len; i++) {
 		package = g_ptr_array_index (packages, i);
+
+		/* get filename */
+		filename = zif_package_get_filename (package, &error);
+		if (filename == NULL) {
+			pk_backend_error_code (backend, PK_ERROR_ENUM_PACKAGE_DOWNLOAD_FAILED,
+					       "failed to get filename for %s: %s", zif_package_get_id (package), error->message);
+			g_error_free (error);
+			goto out;
+		}
+
 		ret = zif_package_download (package, directory, priv->cancellable, completion_local, &error);
 		if (!ret) {
-			ZifString *filename;
-			GError *error_local = NULL;
-			filename = zif_package_get_filename (package, &error_local);
-			if (filename == NULL) {
-				pk_backend_error_code (backend, PK_ERROR_ENUM_PACKAGE_DOWNLOAD_FAILED,
-						       "failed to get filename for %s: %s", zif_package_get_id (package), error_local->message);
-				g_error_free (error_local);
-				goto out;
-			}
 			pk_backend_error_code (backend, PK_ERROR_ENUM_PACKAGE_DOWNLOAD_FAILED,
 					       "failed to download %s: %s", zif_string_get_value (filename), error->message);
 			zif_string_unref (filename);
@@ -981,6 +985,14 @@ backend_download_packages_thread (PkBackend *backend)
 			goto out;
 		}
 
+		/* send a signal for the daemon so the file is copied */
+		basename = g_path_get_basename (zif_string_get_value (filename));
+		path = g_build_filename (directory, basename, NULL);
+		pk_backend_files (backend, zif_package_get_id (package), path);
+		zif_string_unref (filename);
+		g_free (basename);
+		g_free (path);
+
 		/* this section done */
 		zif_completion_done (priv->completion);
 	}
@@ -1001,7 +1013,7 @@ static void
 backend_download_packages (PkBackend *backend, gchar **package_ids, const gchar *directory)
 {
 	/* it seems some people are not ready for the awesomeness */
-	if (TRUE || !priv->use_zif) {
+	if (!priv->use_zif) {
 		gchar *package_ids_temp;
 
 		/* send the complete list as stdin */
commit 0c2416d88a8a9e6bd73935f84c317c19709b45c1
Author: Richard Hughes <richard at hughsie.com>
Date:   Thu Mar 11 15:52:42 2010 +0000

    yum: use libzif to download packages
    
    Note: this isn't any faster than the yum version, and it's
    currently disabled due to a zif bug.

diff --git a/backends/yum/libzif/zif-package.c b/backends/yum/libzif/zif-package.c
index 9b9edab..2980cf6 100644
--- a/backends/yum/libzif/zif-package.c
+++ b/backends/yum/libzif/zif-package.c
@@ -728,6 +728,13 @@ zif_package_get_filename (ZifPackage *package, GError **error)
 	g_return_val_if_fail (ZIF_IS_PACKAGE (package), NULL);
 	g_return_val_if_fail (package->priv->package_id_split != NULL, NULL);
 
+	/* doesn't make much sense */
+	if (package->priv->installed) {
+		g_set_error_literal (error, ZIF_PACKAGE_ERROR, ZIF_PACKAGE_ERROR_FAILED,
+				     "cannot get remote filename for installed package");
+		return NULL;
+	}
+
 	/* not exists */
 	if (package->priv->location_href == NULL) {
 		g_set_error (error, ZIF_PACKAGE_ERROR, ZIF_PACKAGE_ERROR_FAILED,
diff --git a/backends/yum/pk-backend-yum.c b/backends/yum/pk-backend-yum.c
index 2ae248f..77dfd95 100644
--- a/backends/yum/pk-backend-yum.c
+++ b/backends/yum/pk-backend-yum.c
@@ -896,17 +896,121 @@ backend_cancel (PkBackend *backend)
 }
 
 /**
+ * backend_download_packages_thread:
+ */
+static gboolean
+backend_download_packages_thread (PkBackend *backend)
+{
+	gchar **package_ids = pk_backend_get_strv (backend, "package_ids");
+	const gchar *directory = pk_backend_get_string (backend, "directory");
+	GPtrArray *store_array = NULL;
+	ZifPackage *package;
+	ZifCompletion *completion_local;
+	GPtrArray *packages = NULL;
+	const gchar *id;
+	guint i;
+	guint len;
+	gboolean ret;
+	GError *error = NULL;
+
+	/* get lock */
+	ret = backend_get_lock (backend);
+	if (!ret) {
+		egg_warning ("failed to get lock");
+		goto out;
+	}
+
+	/* set the network state */
+	backend_setup_network (backend);
+
+	/* setup completion */
+	zif_completion_reset (priv->completion);
+	len = g_strv_length (package_ids);
+	zif_completion_set_number_steps (priv->completion, (len * 2) + 1);
+
+	/* find all the packages */
+	packages = g_ptr_array_new ();
+	completion_local = zif_completion_get_child (priv->completion);
+	store_array = backend_get_default_store_array_for_filter (backend, pk_bitfield_value (PK_FILTER_ENUM_NOT_INSTALLED), completion_local, &error);
+	if (store_array == NULL) {
+		pk_backend_error_code (backend, PK_ERROR_ENUM_INTERNAL_ERROR, "failed to get stores: %s", error->message);
+		g_error_free (error);
+		goto out;
+	}
+
+	/* this section done */
+	zif_completion_done (priv->completion);
+
+	pk_backend_set_status (backend, PK_STATUS_ENUM_QUERY);
+	for (i=0; package_ids[i] != NULL; i++) {
+		id = package_ids[i];
+		completion_local = zif_completion_get_child (priv->completion);
+		package = zif_store_array_find_package (store_array, id, priv->cancellable, completion_local, &error);
+		if (package == NULL) {
+			pk_backend_error_code (backend, PK_ERROR_ENUM_PACKAGE_NOT_FOUND, "failed to find %s: %s", package_ids[i], error->message);
+			g_error_free (error);
+			goto out;
+		}
+
+		/* this section done */
+		zif_completion_done (priv->completion);
+
+		g_ptr_array_add (packages, g_object_ref (package));
+		g_object_unref (package);
+	}
+
+	/* download list */
+	pk_backend_set_status (backend, PK_STATUS_ENUM_DOWNLOAD);
+	for (i=0; i<packages->len; i++) {
+		package = g_ptr_array_index (packages, i);
+		ret = zif_package_download (package, directory, priv->cancellable, completion_local, &error);
+		if (!ret) {
+			ZifString *filename;
+			GError *error_local = NULL;
+			filename = zif_package_get_filename (package, &error_local);
+			if (filename == NULL) {
+				pk_backend_error_code (backend, PK_ERROR_ENUM_PACKAGE_DOWNLOAD_FAILED,
+						       "failed to get filename for %s: %s", zif_package_get_id (package), error_local->message);
+				g_error_free (error_local);
+				goto out;
+			}
+			pk_backend_error_code (backend, PK_ERROR_ENUM_PACKAGE_DOWNLOAD_FAILED,
+					       "failed to download %s: %s", zif_string_get_value (filename), error->message);
+			zif_string_unref (filename);
+			g_error_free (error);
+			goto out;
+		}
+
+		/* this section done */
+		zif_completion_done (priv->completion);
+	}
+out:
+	backend_unlock (backend);
+	pk_backend_finished (backend);
+	if (packages != NULL)
+		g_ptr_array_unref (packages);
+	if (store_array != NULL)
+		g_ptr_array_unref (store_array);
+	return TRUE;
+}
+
+/**
  * backend_download_packages:
  */
 static void
 backend_download_packages (PkBackend *backend, gchar **package_ids, const gchar *directory)
 {
-	gchar *package_ids_temp;
+	/* it seems some people are not ready for the awesomeness */
+	if (TRUE || !priv->use_zif) {
+		gchar *package_ids_temp;
 
-	/* send the complete list as stdin */
-	package_ids_temp = pk_package_ids_to_string (package_ids);
-	pk_backend_spawn_helper (priv->spawn, "yumBackend.py", "download-packages", directory, package_ids_temp, NULL);
-	g_free (package_ids_temp);
+		/* send the complete list as stdin */
+		package_ids_temp = pk_package_ids_to_string (package_ids);
+		pk_backend_spawn_helper (priv->spawn, "yumBackend.py", "download-packages", directory, package_ids_temp, NULL);
+		g_free (package_ids_temp);
+		return;
+	}
+	pk_backend_thread_create (backend, backend_download_packages_thread);
 }
 
 /**
commit 170c5ccba2526646a93592b861e4d307ec2bfa33
Author: Richard Hughes <richard at hughsie.com>
Date:   Thu Mar 11 15:50:43 2010 +0000

    Do not show installed packages when we choose packages to download

diff --git a/client/pk-console.c b/client/pk-console.c
index b11cf67..a7240dc 100644
--- a/client/pk-console.c
+++ b/client/pk-console.c
@@ -909,7 +909,7 @@ pk_console_download_packages (gchar **packages, const gchar *directory, GError *
 	gchar **package_ids;
 	GError *error_local = NULL;
 
-	package_ids = pk_console_resolve_packages (PK_CLIENT(task), pk_bitfield_value (PK_FILTER_ENUM_NONE), packages, &error_local);
+	package_ids = pk_console_resolve_packages (PK_CLIENT(task), pk_bitfield_value (PK_FILTER_ENUM_NOT_INSTALLED), packages, &error_local);
 	if (package_ids == NULL) {
 		/* TRANSLATORS: There was an error getting the list of files for the package. The detailed error follows */
 		*error = g_error_new (1, 0, _("This tool could not find the package: %s"), error_local->message);
diff --git a/lib/packagekit-glib2/pk-console-shared.c b/lib/packagekit-glib2/pk-console-shared.c
index 76cd562..ce9c658 100644
--- a/lib/packagekit-glib2/pk-console-shared.c
+++ b/lib/packagekit-glib2/pk-console-shared.c
@@ -135,9 +135,11 @@ pk_console_get_prompt (const gchar *question, gboolean defaultyes)
 gchar *
 pk_console_resolve_package (PkClient *client, PkBitfield filter, const gchar *package_name, GError **error)
 {
+	const gchar *package_id_tmp;
 	gchar *package_id = NULL;
 	gboolean valid;
 	gchar **tmp;
+	gchar **split = NULL;
 	PkResults *results;
 	GPtrArray *array = NULL;
 	guint i;
@@ -183,13 +185,11 @@ pk_console_resolve_package (PkClient *client, PkBitfield filter, const gchar *pa
 	g_print ("%s\n", _("More than one package matches:"));
 	for (i=0; i<array->len; i++) {
 		package = g_ptr_array_index (array, i);
-		g_object_get (package,
-			      "package-id", &package_id,
-			      NULL);
-		printable = pk_package_id_to_printable (package_id);
-		g_print ("%i. %s\n", i+1, printable);
+		package_id_tmp = pk_package_get_id (package);
+		split = pk_package_id_split (package_id_tmp);
+		printable = pk_package_id_to_printable (package_id_tmp);
+		g_print ("%i. %s [%s]\n", i+1, printable, split[PK_PACKAGE_ID_DATA]);
 		g_free (printable);
-		g_free (package_id);
 	}
 
 	/* TRANSLATORS: This finds out which package in the list to use */
@@ -204,6 +204,7 @@ out:
 	if (array != NULL)
 		g_ptr_array_unref (array);
 	g_strfreev (tmp);
+	g_strfreev (split);
 	return package_id;
 }
 
commit 211ffa4e1c8884444d6e1894f48ac06bb730125c
Author: Richard Hughes <richard at hughsie.com>
Date:   Thu Mar 11 15:08:35 2010 +0000

    trivial: do not allow backends to kill the default process (-1)

diff --git a/src/pk-spawn.c b/src/pk-spawn.c
index 4d46ee3..f831435 100644
--- a/src/pk-spawn.c
+++ b/src/pk-spawn.c
@@ -311,6 +311,12 @@ pk_spawn_kill (PkSpawn *spawn)
 	g_return_val_if_fail (PK_IS_SPAWN (spawn), FALSE);
 	g_return_val_if_fail (spawn->priv->kill_id == 0, FALSE);
 
+	/* is there a process running? */
+	if (spawn->priv->child_pid == -1) {
+		egg_warning ("no child pid to kill!");
+		return FALSE;
+	}
+
 	/* check if process has already gone */
 	if (spawn->priv->finished) {
 		egg_warning ("already finished, ignoring");
commit 9e97ca0ca071cf21bc757f5ddb7680c3368391f8
Author: Richard Hughes <richard at hughsie.com>
Date:   Thu Mar 11 14:40:47 2010 +0000

    yum: when using libzif, quit the spawned backend rather than waiting for it to time out

diff --git a/backends/yum/pk-backend-yum.c b/backends/yum/pk-backend-yum.c
index 4cdf0c0..2ae248f 100644
--- a/backends/yum/pk-backend-yum.c
+++ b/backends/yum/pk-backend-yum.c
@@ -148,6 +148,9 @@ backend_get_lock (PkBackend *backend)
 	gboolean ret = FALSE;
 	GError *error = NULL;
 
+	/* quit the spawned backend rather than waiting for it to time out */
+	pk_backend_spawn_kill (priv->spawn);
+
 	for (i=0; i<YUM_BACKEND_LOCKING_RETRIES; i++) {
 
 		/* try to lock */
commit 3a07bcd8c55dd7160f3193f801d0a07929bbf36e
Author: Richard Hughes <richard at hughsie.com>
Date:   Thu Mar 11 14:40:24 2010 +0000

    yum: fix up API usage of get_applicable_notices to prevent an internal error
    
    Apparently get_applicable_notices(pkgtup) returns an array of (pkgtup, notice)
    which doesn't make a lot of sense to me.

diff --git a/backends/yum/yumBackend.py b/backends/yum/yumBackend.py
index 6998728..d1c7a46 100755
--- a/backends/yum/yumBackend.py
+++ b/backends/yum/yumBackend.py
@@ -2449,7 +2449,7 @@ class PackageKitYumBackend(PackageKitBaseBackend, PackagekitPackage):
                 notices = md.get_applicable_notices(pkg.pkgtup)
                 status = INFO_NORMAL
                 if notices:
-                    for notice in notices:
+                    for (pkgtup, notice) in notices:
                         status = self._get_status(notice)
                         if status == INFO_SECURITY:
                             break
commit 98b2b56a7e4efead8c7628062a37c992279f003f
Author: Richard Hughes <richard at hughsie.com>
Date:   Thu Mar 11 13:03:51 2010 +0000

    yum: use libzif to refresh the repos
    
    This is 2.3x faster than using yum

diff --git a/backends/yum/pk-backend-yum.c b/backends/yum/pk-backend-yum.c
index 51cfef4..4cdf0c0 100644
--- a/backends/yum/pk-backend-yum.c
+++ b/backends/yum/pk-backend-yum.c
@@ -531,7 +531,8 @@ backend_search_thread (PkBackend *backend)
 	/* do get action */
 	if (role == PK_ROLE_ENUM_GET_PACKAGES) {
 		completion_local = zif_completion_get_child (priv->completion);
-		array = zif_store_array_get_packages (store_array, (ZifStoreArrayErrorCb) backend_error_handler_cb, backend, priv->cancellable, completion_local, &error);
+		array = zif_store_array_get_packages (store_array, (ZifStoreArrayErrorCb) backend_error_handler_cb, backend,
+						      priv->cancellable, completion_local, &error);
 		if (array == NULL) {
 			pk_backend_error_code (backend, PK_ERROR_ENUM_INTERNAL_ERROR, "failed to get packages: %s", error->message);
 			g_error_free (error);
@@ -540,6 +541,11 @@ backend_search_thread (PkBackend *backend)
 	} else {
 		/* treat these all the same */
 		search = pk_backend_get_strv (backend, "search");
+		if (search == NULL) {
+			pk_backend_error_code (backend, PK_ERROR_ENUM_INTERNAL_ERROR,
+					       "failed to get 'search' for %s", pk_role_enum_to_string (role));
+			goto out;
+		}
 		array = g_ptr_array_new_with_free_func ((GDestroyNotify) g_object_unref);
 
 		completion_local = zif_completion_get_child (priv->completion);
@@ -1418,6 +1424,72 @@ backend_install_signature (PkBackend *backend, PkSigTypeEnum type,
 }
 
 /**
+ * backend_refresh_cache_thread:
+ */
+static gboolean
+backend_refresh_cache_thread (PkBackend *backend)
+{
+	GPtrArray *store_array = NULL;
+	gboolean ret;
+	GError *error = NULL;
+	ZifCompletion *completion_local;
+	gboolean force = pk_backend_get_bool (backend, "force");
+
+	/* get lock */
+	ret = backend_get_lock (backend);
+	if (!ret) {
+		egg_warning ("failed to get lock");
+		goto out;
+	}
+
+	/* set the network state */
+	backend_setup_network (backend);
+
+	/* setup completion */
+	zif_completion_reset (priv->completion);
+	zif_completion_set_number_steps (priv->completion, 2);
+
+	pk_backend_set_status (backend, PK_STATUS_ENUM_QUERY);
+	pk_backend_set_percentage (backend, 0);
+
+	/* don't nuke the metadata */
+	if (!force) {
+		egg_debug ("not supported yet");
+		goto out;
+	}
+
+	/* get a store_array of remote stores */
+	store_array = zif_store_array_new ();
+	completion_local = zif_completion_get_child (priv->completion);
+	ret = zif_store_array_add_remote_enabled (store_array, priv->cancellable, completion_local, &error);
+	if (!ret) {
+		pk_backend_error_code (backend, PK_ERROR_ENUM_INTERNAL_ERROR, "failed to add enabled stores: %s\n", error->message);
+		g_error_free (error);
+		goto out;
+	}
+
+	/* this section done */
+	zif_completion_done (priv->completion);
+
+	/* clean all the repos */
+	completion_local = zif_completion_get_child (priv->completion);
+	ret = zif_store_array_clean (store_array, (ZifStoreArrayErrorCb) backend_error_handler_cb, backend,
+				     priv->cancellable, completion_local, &error);
+	if (!ret) {
+		pk_backend_error_code (backend, PK_ERROR_ENUM_INTERNAL_ERROR, "failed to clean: %s\n", error->message);
+		g_error_free (error);
+		goto out;
+	}
+out:
+	backend_unlock (backend);
+	pk_backend_finished (backend);
+	if (store_array != NULL)
+		g_ptr_array_unref (store_array);
+
+	return TRUE;
+}
+
+/**
  * backend_refresh_cache:
  */
 static void
@@ -1430,7 +1502,12 @@ backend_refresh_cache (PkBackend *backend, gboolean force)
 		return;
 	}
 
-	pk_backend_spawn_helper (priv->spawn, "yumBackend.py", "refresh-cache", pk_backend_bool_to_string (force), NULL);
+	/* it seems some people are not ready for the awesomeness */
+	if (!priv->use_zif) {
+		pk_backend_spawn_helper (priv->spawn, "yumBackend.py", "refresh-cache", pk_backend_bool_to_string (force), NULL);
+		return;
+	}
+	pk_backend_thread_create (backend, backend_refresh_cache_thread);
 }
 
 /**
commit bbb0237b4117e5bbf824dfe62bf862c8791ac2c2
Author: Richard Hughes <richard at hughsie.com>
Date:   Thu Mar 11 13:00:36 2010 +0000

    Set the backend role in the pk_backend_(role) functions, not in PkTransaction
    
    Otherwise we do not get the role set correctly when the backend
    is being used in PkTransactionExtra which affects some threaded
    backends.

diff --git a/src/pk-backend.c b/src/pk-backend.c
index bbff2aa..c4072e4 100644
--- a/src/pk-backend.c
+++ b/src/pk-backend.c
@@ -2649,6 +2649,7 @@ void
 pk_backend_download_packages (PkBackend *backend, gchar **package_ids, const gchar *directory)
 {
 	g_return_if_fail (PK_IS_BACKEND (backend));
+	pk_backend_set_role (backend, PK_ROLE_ENUM_DOWNLOAD_PACKAGES);
 	pk_store_set_strv (backend->priv->store, "package_ids", package_ids);
 	pk_store_set_string (backend->priv->store, "directory", directory);
 	backend->priv->desc->download_packages (backend, package_ids, directory);
@@ -2661,6 +2662,7 @@ void
 pk_backend_get_categories (PkBackend *backend)
 {
 	g_return_if_fail (PK_IS_BACKEND (backend));
+	pk_backend_set_role (backend, PK_ROLE_ENUM_GET_CATEGORIES);
 	backend->priv->desc->get_categories (backend);
 }
 
@@ -2671,6 +2673,7 @@ void
 pk_backend_get_depends (PkBackend *backend, PkBitfield filters, gchar **package_ids, gboolean recursive)
 {
 	g_return_if_fail (PK_IS_BACKEND (backend));
+	pk_backend_set_role (backend, PK_ROLE_ENUM_GET_DEPENDS);
 	pk_store_set_uint (backend->priv->store, "filters", filters);
 	pk_store_set_strv (backend->priv->store, "package_ids", package_ids);
 	pk_store_set_bool (backend->priv->store, "recursive", recursive);
@@ -2684,6 +2687,7 @@ void
 pk_backend_get_details (PkBackend *backend, gchar **package_ids)
 {
 	g_return_if_fail (PK_IS_BACKEND (backend));
+	pk_backend_set_role (backend, PK_ROLE_ENUM_GET_DETAILS);
 	pk_store_set_strv (backend->priv->store, "package_ids", package_ids);
 	backend->priv->desc->get_details (backend, package_ids);
 }
@@ -2695,6 +2699,7 @@ void
 pk_backend_get_distro_upgrades (PkBackend *backend)
 {
 	g_return_if_fail (PK_IS_BACKEND (backend));
+	pk_backend_set_role (backend, PK_ROLE_ENUM_GET_DISTRO_UPGRADES);
 	backend->priv->desc->get_distro_upgrades (backend);
 }
 
@@ -2705,6 +2710,7 @@ void
 pk_backend_get_files (PkBackend *backend, gchar **package_ids)
 {
 	g_return_if_fail (PK_IS_BACKEND (backend));
+	pk_backend_set_role (backend, PK_ROLE_ENUM_GET_FILES);
 	pk_store_set_strv (backend->priv->store, "package_ids", package_ids);
 	backend->priv->desc->get_files (backend, package_ids);
 }
@@ -2716,6 +2722,7 @@ void
 pk_backend_get_requires (PkBackend *backend, PkBitfield filters, gchar **package_ids, gboolean recursive)
 {
 	g_return_if_fail (PK_IS_BACKEND (backend));
+	pk_backend_set_role (backend, PK_ROLE_ENUM_GET_REQUIRES);
 	pk_store_set_uint (backend->priv->store, "filters", filters);
 	pk_store_set_strv (backend->priv->store, "package_ids", package_ids);
 	pk_store_set_bool (backend->priv->store, "recursive", recursive);
@@ -2729,6 +2736,7 @@ void
 pk_backend_get_update_detail (PkBackend *backend, gchar **package_ids)
 {
 	g_return_if_fail (PK_IS_BACKEND (backend));
+	pk_backend_set_role (backend, PK_ROLE_ENUM_GET_UPDATE_DETAIL);
 	pk_store_set_strv (backend->priv->store, "package_ids", package_ids);
 	backend->priv->desc->get_update_detail (backend, package_ids);
 }
@@ -2740,6 +2748,7 @@ void
 pk_backend_get_updates (PkBackend *backend, PkBitfield filters)
 {
 	g_return_if_fail (PK_IS_BACKEND (backend));
+	pk_backend_set_role (backend, PK_ROLE_ENUM_GET_UPDATES);
 	pk_store_set_uint (backend->priv->store, "filters", filters);
 	backend->priv->desc->get_updates (backend, filters);
 }
@@ -2751,6 +2760,7 @@ void
 pk_backend_install_packages (PkBackend *backend, gboolean only_trusted, gchar **package_ids)
 {
 	g_return_if_fail (PK_IS_BACKEND (backend));
+	pk_backend_set_role (backend, PK_ROLE_ENUM_INSTALL_PACKAGES);
 	pk_store_set_bool (backend->priv->store, "only_trusted", only_trusted);
 	pk_store_set_strv (backend->priv->store, "package_ids", package_ids);
 	backend->priv->desc->install_packages (backend, only_trusted, package_ids);
@@ -2763,6 +2773,7 @@ void
 pk_backend_install_signature (PkBackend *backend, PkSigTypeEnum type, const gchar *key_id, const gchar *package_id)
 {
 	g_return_if_fail (PK_IS_BACKEND (backend));
+	pk_backend_set_role (backend, PK_ROLE_ENUM_INSTALL_SIGNATURE);
 	pk_store_set_string (backend->priv->store, "key_id", key_id);
 	pk_store_set_string (backend->priv->store, "package_id", package_id);
 	backend->priv->desc->install_signature (backend, type, key_id, package_id);
@@ -2775,6 +2786,7 @@ void
 pk_backend_install_files (PkBackend *backend, gboolean only_trusted, gchar **full_paths)
 {
 	g_return_if_fail (PK_IS_BACKEND (backend));
+	pk_backend_set_role (backend, PK_ROLE_ENUM_INSTALL_FILES);
 	pk_store_set_bool (backend->priv->store, "only_trusted", only_trusted);
 	pk_store_set_strv (backend->priv->store, "full_paths", full_paths);
 	backend->priv->desc->install_files (backend, only_trusted, full_paths);
@@ -2787,6 +2799,7 @@ void
 pk_backend_refresh_cache (PkBackend *backend, gboolean force)
 {
 	g_return_if_fail (PK_IS_BACKEND (backend));
+	pk_backend_set_role (backend, PK_ROLE_ENUM_REFRESH_CACHE);
 	pk_store_set_bool (backend->priv->store, "force", force);
 	backend->priv->desc->refresh_cache (backend, force);
 }
@@ -2798,6 +2811,7 @@ void
 pk_backend_remove_packages (PkBackend *backend, gchar **package_ids, gboolean allow_deps, gboolean autoremove)
 {
 	g_return_if_fail (PK_IS_BACKEND (backend));
+	pk_backend_set_role (backend, PK_ROLE_ENUM_REMOVE_PACKAGES);
 	pk_store_set_strv (backend->priv->store, "package_ids", package_ids);
 	pk_store_set_bool (backend->priv->store, "allow_deps", allow_deps);
 	pk_store_set_bool (backend->priv->store, "autoremove", autoremove);
@@ -2811,6 +2825,7 @@ void
 pk_backend_resolve (PkBackend *backend, PkBitfield filters, gchar **package_ids)
 {
 	g_return_if_fail (PK_IS_BACKEND (backend));
+	pk_backend_set_role (backend, PK_ROLE_ENUM_RESOLVE);
 	pk_store_set_uint (backend->priv->store, "filters", filters);
 	pk_store_set_strv (backend->priv->store, "package_ids", package_ids);
 	backend->priv->desc->resolve (backend, filters, package_ids);
@@ -2823,6 +2838,7 @@ void
 pk_backend_rollback (PkBackend *backend, const gchar *transaction_id)
 {
 	g_return_if_fail (PK_IS_BACKEND (backend));
+	pk_backend_set_role (backend, PK_ROLE_ENUM_ROLLBACK);
 	pk_store_set_string (backend->priv->store, "transaction_id", transaction_id);
 	backend->priv->desc->rollback (backend, transaction_id);
 }
@@ -2834,6 +2850,7 @@ void
 pk_backend_search_details (PkBackend *backend, PkBitfield filters, gchar **values)
 {
 	g_return_if_fail (PK_IS_BACKEND (backend));
+	pk_backend_set_role (backend, PK_ROLE_ENUM_SEARCH_DETAILS);
 	pk_store_set_uint (backend->priv->store, "filters", filters);
 	pk_store_set_strv (backend->priv->store, "search", values);
 	backend->priv->desc->search_details (backend, filters, values);
@@ -2846,6 +2863,7 @@ void
 pk_backend_search_files (PkBackend *backend, PkBitfield filters, gchar **values)
 {
 	g_return_if_fail (PK_IS_BACKEND (backend));
+	pk_backend_set_role (backend, PK_ROLE_ENUM_SEARCH_FILE);
 	pk_store_set_uint (backend->priv->store, "filters", filters);
 	pk_store_set_strv (backend->priv->store, "search", values);
 	backend->priv->desc->search_files (backend, filters, values);
@@ -2858,6 +2876,7 @@ void
 pk_backend_search_groups (PkBackend *backend, PkBitfield filters, gchar **values)
 {
 	g_return_if_fail (PK_IS_BACKEND (backend));
+	pk_backend_set_role (backend, PK_ROLE_ENUM_SEARCH_GROUP);
 	pk_store_set_uint (backend->priv->store, "filters", filters);
 	pk_store_set_strv (backend->priv->store, "search", values);
 	backend->priv->desc->search_groups (backend, filters, values);
@@ -2870,6 +2889,7 @@ void
 pk_backend_search_names (PkBackend *backend, PkBitfield filters, gchar **values)
 {
 	g_return_if_fail (PK_IS_BACKEND (backend));
+	pk_backend_set_role (backend, PK_ROLE_ENUM_SEARCH_NAME);
 	pk_store_set_uint (backend->priv->store, "filters", filters);
 	pk_store_set_strv (backend->priv->store, "search", values);
 	backend->priv->desc->search_names (backend, filters, values);
@@ -2882,6 +2902,7 @@ void
 pk_backend_update_packages (PkBackend *backend, gboolean only_trusted, gchar **package_ids)
 {
 	g_return_if_fail (PK_IS_BACKEND (backend));
+	pk_backend_set_role (backend, PK_ROLE_ENUM_UPDATE_PACKAGES);
 	pk_store_set_bool (backend->priv->store, "only_trusted", only_trusted);
 	pk_store_set_strv (backend->priv->store, "package_ids", package_ids);
 	backend->priv->desc->update_packages (backend, only_trusted, package_ids);
@@ -2894,6 +2915,7 @@ void
 pk_backend_update_system (PkBackend *backend, gboolean only_trusted)
 {
 	g_return_if_fail (PK_IS_BACKEND (backend));
+	pk_backend_set_role (backend, PK_ROLE_ENUM_UPDATE_SYSTEM);
 	pk_store_set_bool (backend->priv->store, "only_trusted", only_trusted);
 	backend->priv->desc->update_system (backend, only_trusted);
 }
@@ -2905,6 +2927,7 @@ void
 pk_backend_get_repo_list (PkBackend *backend, PkBitfield filters)
 {
 	g_return_if_fail (PK_IS_BACKEND (backend));
+	pk_backend_set_role (backend, PK_ROLE_ENUM_GET_REPO_LIST);
 	pk_store_set_uint (backend->priv->store, "filters", filters);
 	backend->priv->desc->get_repo_list (backend, filters);
 }
@@ -2916,6 +2939,7 @@ void
 pk_backend_repo_enable (PkBackend *backend, const gchar *repo_id, gboolean enabled)
 {
 	g_return_if_fail (PK_IS_BACKEND (backend));
+	pk_backend_set_role (backend, PK_ROLE_ENUM_REPO_ENABLE);
 	pk_store_set_string (backend->priv->store, "repo_id", repo_id);
 	pk_store_set_bool (backend->priv->store, "enabled", enabled);
 	backend->priv->desc->repo_enable (backend, repo_id, enabled);
@@ -2928,6 +2952,7 @@ void
 pk_backend_repo_set_data (PkBackend *backend, const gchar *repo_id, const gchar *parameter, const gchar *value)
 {
 	g_return_if_fail (PK_IS_BACKEND (backend));
+	pk_backend_set_role (backend, PK_ROLE_ENUM_REPO_SET_DATA);
 	pk_store_set_string (backend->priv->store, "repo_id", repo_id);
 	pk_store_set_string (backend->priv->store, "parameter", parameter);
 	pk_store_set_string (backend->priv->store, "value", value);
@@ -2941,6 +2966,7 @@ void
 pk_backend_what_provides (PkBackend *backend, PkBitfield filters, PkProvidesEnum provides, gchar **values)
 {
 	g_return_if_fail (PK_IS_BACKEND (backend));
+	pk_backend_set_role (backend, PK_ROLE_ENUM_WHAT_PROVIDES);
 	pk_store_set_uint (backend->priv->store, "filters", filters);
 	pk_store_set_uint (backend->priv->store, "provides", provides);
 	pk_store_set_strv (backend->priv->store, "search", values);
@@ -2954,6 +2980,7 @@ void
 pk_backend_get_packages (PkBackend *backend, PkBitfield filters)
 {
 	g_return_if_fail (PK_IS_BACKEND (backend));
+	pk_backend_set_role (backend, PK_ROLE_ENUM_GET_PACKAGES);
 	pk_store_set_uint (backend->priv->store, "filters", filters);
 	backend->priv->desc->get_packages (backend, filters);
 }
@@ -2965,6 +2992,7 @@ void
 pk_backend_simulate_install_files (PkBackend *backend, gchar **full_paths)
 {
 	g_return_if_fail (PK_IS_BACKEND (backend));
+	pk_backend_set_role (backend, PK_ROLE_ENUM_SIMULATE_INSTALL_FILES);
 	pk_store_set_strv (backend->priv->store, "full_paths", full_paths);
 	backend->priv->desc->simulate_install_files (backend, full_paths);
 }
@@ -2976,6 +3004,7 @@ void
 pk_backend_simulate_install_packages (PkBackend *backend, gchar **package_ids)
 {
 	g_return_if_fail (PK_IS_BACKEND (backend));
+	pk_backend_set_role (backend, PK_ROLE_ENUM_SIMULATE_INSTALL_PACKAGES);
 	pk_store_set_strv (backend->priv->store, "package_ids", package_ids);
 	backend->priv->desc->simulate_install_packages (backend, package_ids);
 }
@@ -2987,6 +3016,7 @@ void
 pk_backend_simulate_remove_packages (PkBackend *backend, gchar **package_ids, gboolean	 autoremove)
 {
 	g_return_if_fail (PK_IS_BACKEND (backend));
+	pk_backend_set_role (backend, PK_ROLE_ENUM_SIMULATE_REMOVE_PACKAGES);
 	pk_store_set_strv (backend->priv->store, "package_ids", package_ids);
 	pk_store_set_bool (backend->priv->store, "autoremove", autoremove);
 	backend->priv->desc->simulate_remove_packages (backend, package_ids, autoremove);
@@ -2999,6 +3029,7 @@ void
 pk_backend_simulate_update_packages (PkBackend *backend, gchar **package_ids)
 {
 	g_return_if_fail (PK_IS_BACKEND (backend));
+	pk_backend_set_role (backend, PK_ROLE_ENUM_SIMULATE_UPDATE_PACKAGES);
 	pk_store_set_strv (backend->priv->store, "package_ids", package_ids);
 	backend->priv->desc->simulate_update_packages (backend, package_ids);
 }
diff --git a/src/pk-transaction.c b/src/pk-transaction.c
index 0a4aafa..5b51e30 100644
--- a/src/pk-transaction.c
+++ b/src/pk-transaction.c
@@ -1657,9 +1657,6 @@ pk_transaction_set_running (PkTransaction *transaction)
 	/* might have to reset again if we used the backend */
 	pk_backend_reset (transaction->priv->backend);
 
-	/* set the role again, as resetting will have cleared the value */
-	pk_backend_set_role (priv->backend, priv->role);
-
 	/* connect up the signals */
 	transaction->priv->signal_allow_cancel =
 		g_signal_connect (transaction->priv->backend, "allow-cancel",
commit 044c9f8b9b283b823b8fb303f8604f65fed7cb98
Author: Richard Hughes <richard at hughsie.com>
Date:   Thu Mar 11 12:36:31 2010 +0000

    yum: ignore repos that are not contactable when using libzif

diff --git a/backends/yum/Makefile.am b/backends/yum/Makefile.am
index b6675d8..a645404 100644
--- a/backends/yum/Makefile.am
+++ b/backends/yum/Makefile.am
@@ -15,6 +15,7 @@ INCLUDES = \
 	$(BZLIB_CFLAGS)						\
 	$(SOUP_CFLAGS)						\
 	$(ARCHIVE_CFLAGS)					\
+	-DSYSCONFDIR=\""$(sysconfdir)"\"			\
 	-I$(top_srcdir)/backends/yum/libzif			\
 	-I$(top_builddir)/backends/yum/libzif
 
diff --git a/backends/yum/libzif/zif-store-array.c b/backends/yum/libzif/zif-store-array.c
index 583f9fc..051beb1 100644
--- a/backends/yum/libzif/zif-store-array.c
+++ b/backends/yum/libzif/zif-store-array.c
@@ -21,16 +21,13 @@
 
 /**
  * SECTION:zif-store-array
- * @short_description: A store-			g_set_error (error, ZIF_STORE_ERROR, ZIF_STORE_ERROR_FAILED,
-				     "failed to %s in %s: %s", pk_role_enum_to_text (role), zif_store_get_id (store), error_local->message);
-array is a container that holds one or more stores
+ * @short_description: A store-array is a container that holds one or more stores
  *
  * A #GPtrArray is the container where #ZifStore's are kept. Global operations can
  * be done on the array and not the indervidual stores.
  *
- * IMPORTANT: any errors that happen on the ZifStores are fatal. You will need to
- * copy this functionality in this file and issue warnings if the error policy
- * needs to be less harsh.
+ * IMPORTANT: any errors that happen on the ZifStores are fatal unless you're
+ * using ZifStoreArrayErrorCb, and it returns TRUE.
  */
 
 #ifdef HAVE_CONFIG_H
@@ -217,7 +214,9 @@ out:
  * zif_store_array_repos_search:
  **/
 static GPtrArray *
-zif_store_array_repos_search (GPtrArray *store_array, PkRoleEnum role, const gchar *search, GCancellable *cancellable, ZifCompletion *completion, GError **error)
+zif_store_array_repos_search (GPtrArray *store_array, PkRoleEnum role, const gchar *search,
+			      ZifStoreArrayErrorCb error_cb, gpointer user_data,
+			      GCancellable *cancellable, ZifCompletion *completion, GError **error)
 {
 	guint i, j;
 	GPtrArray *array = NULL;
@@ -274,6 +273,11 @@ zif_store_array_repos_search (GPtrArray *store_array, PkRoleEnum role, const gch
 			goto out;
 		}
 		if (part == NULL) {
+			/* do we need to skip this error */
+			if (error_cb != NULL && error_cb (store_array, error_local, user_data)) {
+				g_clear_error (&error_local);
+				goto skip_error;
+			}
 			g_set_error (error, ZIF_STORE_ERROR, ZIF_STORE_ERROR_FAILED,
 				     "failed to %s in %s: %s", pk_role_enum_to_text (role), zif_store_get_id (store), error_local->message);
 			g_error_free (error_local);
@@ -287,7 +291,7 @@ zif_store_array_repos_search (GPtrArray *store_array, PkRoleEnum role, const gch
 			g_ptr_array_add (array, g_object_ref (package));
 		}
 		g_ptr_array_unref (part);
-
+skip_error:
 		/* this section done */
 		zif_completion_done (completion);
 	}
@@ -353,6 +357,8 @@ out:
 /**
  * zif_store_array_clean:
  * @store_array: the #GPtrArray of #ZifStores
+ * @error_cb: a #ZifStoreArrayErrorCb which returns %FALSE if the error is fatal
+ * @user_data: the user_data to be passed to the #ZifStoreArrayErrorCb
  * @cancellable: a #GCancellable which is used to cancel tasks, or %NULL
  * @completion: a #ZifCompletion to use for progress reporting
  * @error: a #GError which is used on failure, or %NULL
@@ -364,7 +370,9 @@ out:
  * Since: 0.0.1
  **/
 gboolean
-zif_store_array_clean (GPtrArray *store_array, GCancellable *cancellable, ZifCompletion *completion, GError **error)
+zif_store_array_clean (GPtrArray *store_array,
+		       ZifStoreArrayErrorCb error_cb, gpointer user_data,
+		       GCancellable *cancellable, ZifCompletion *completion, GError **error)
 {
 	guint i;
 	ZifStore *store;
@@ -389,12 +397,17 @@ zif_store_array_clean (GPtrArray *store_array, GCancellable *cancellable, ZifCom
 		completion_local = zif_completion_get_child (completion);
 		ret = zif_store_clean (store, cancellable, completion_local, &error_local);
 		if (!ret) {
+			/* do we need to skip this error */
+			if (error_cb != NULL && error_cb (store_array, error_local, user_data)) {
+				g_clear_error (&error_local);
+				goto skip_error;
+			}
 			g_set_error (error, ZIF_STORE_ERROR, ZIF_STORE_ERROR_FAILED,
 				     "failed to clean %s: %s", zif_store_get_id (store), error_local->message);
 			g_error_free (error_local);
 			goto out;
 		}
-
+skip_error:
 		/* this section done */
 		zif_completion_done (completion);
 	}
@@ -406,6 +419,8 @@ out:
  * zif_store_array_refresh:
  * @store_array: the #GPtrArray of #ZifStores
  * @force: if the data should be re-downloaded if it's still valid
+ * @error_cb: a #ZifStoreArrayErrorCb which returns %FALSE if the error is fatal
+ * @user_data: the user_data to be passed to the #ZifStoreArrayErrorCb
  * @cancellable: a #GCancellable which is used to cancel tasks, or %NULL
  * @completion: a #ZifCompletion to use for progress reporting
  * @error: a #GError which is used on failure, or %NULL
@@ -417,7 +432,9 @@ out:
  * Since: 0.0.1
  **/
 gboolean
-zif_store_array_refresh (GPtrArray *store_array, gboolean force, GCancellable *cancellable, ZifCompletion *completion, GError **error)
+zif_store_array_refresh (GPtrArray *store_array, gboolean force,
+			 ZifStoreArrayErrorCb error_cb, gpointer user_data,
+			 GCancellable *cancellable, ZifCompletion *completion, GError **error)
 {
 	guint i;
 	ZifStore *store;
@@ -442,12 +459,17 @@ zif_store_array_refresh (GPtrArray *store_array, gboolean force, GCancellable *c
 		completion_local = zif_completion_get_child (completion);
 		ret = zif_store_refresh (store, force, cancellable, completion_local, &error_local);
 		if (!ret) {
-			/* non-fatal */
-			g_print ("failed to refresh %s: %s\n", zif_store_get_id (store), error_local->message);
-			g_clear_error (&error_local);
-			ret = TRUE;
+			/* do we need to skip this error */
+			if (error_cb != NULL && error_cb (store_array, error_local, user_data)) {
+				g_clear_error (&error_local);
+				goto skip_error;
+			}
+			g_set_error (error, ZIF_STORE_ERROR, ZIF_STORE_ERROR_FAILED,
+				     "failed to clean %s: %s", zif_store_get_id (store), error_local->message);
+			g_error_free (error_local);
+			goto out;
 		}
-
+skip_error:
 		/* this section done */
 		zif_completion_done (completion);
 	}
@@ -459,6 +481,8 @@ out:
  * zif_store_array_resolve:
  * @store_array: the #GPtrArray of #ZifStores
  * @search: the search term, e.g. "gnome-power-manager"
+ * @error_cb: a #ZifStoreArrayErrorCb which returns %FALSE if the error is fatal
+ * @user_data: the user_data to be passed to the #ZifStoreArrayErrorCb
  * @cancellable: a #GCancellable which is used to cancel tasks, or %NULL
  * @completion: a #ZifCompletion to use for progress reporting
  * @error: a #GError which is used on failure, or %NULL
@@ -470,15 +494,20 @@ out:
  * Since: 0.0.1
  **/
 GPtrArray *
-zif_store_array_resolve (GPtrArray *store_array, const gchar *search, GCancellable *cancellable, ZifCompletion *completion, GError **error)
+zif_store_array_resolve (GPtrArray *store_array, const gchar *search,
+			 ZifStoreArrayErrorCb error_cb, gpointer user_data,
+			 GCancellable *cancellable, ZifCompletion *completion, GError **error)
 {
-	return zif_store_array_repos_search (store_array, PK_ROLE_ENUM_RESOLVE, search, cancellable, completion, error);
+	return zif_store_array_repos_search (store_array, PK_ROLE_ENUM_RESOLVE, search,
+					     error_cb, user_data, cancellable, completion, error);
 }
 
 /**
  * zif_store_array_search_name:
  * @store_array: the #GPtrArray of #ZifStores
  * @search: the search term, e.g. "power"
+ * @error_cb: a #ZifStoreArrayErrorCb which returns %FALSE if the error is fatal
+ * @user_data: the user_data to be passed to the #ZifStoreArrayErrorCb
  * @cancellable: a #GCancellable which is used to cancel tasks, or %NULL
  * @completion: a #ZifCompletion to use for progress reporting
  * @error: a #GError which is used on failure, or %NULL
@@ -490,15 +519,20 @@ zif_store_array_resolve (GPtrArray *store_array, const gchar *search, GCancellab
  * Since: 0.0.1
  **/
 GPtrArray *
-zif_store_array_search_name (GPtrArray *store_array, const gchar *search, GCancellable *cancellable, ZifCompletion *completion, GError **error)
+zif_store_array_search_name (GPtrArray *store_array, const gchar *search,
+			     ZifStoreArrayErrorCb error_cb, gpointer user_data,
+			     GCancellable *cancellable, ZifCompletion *completion, GError **error)
 {
-	return zif_store_array_repos_search (store_array, PK_ROLE_ENUM_SEARCH_NAME, search, cancellable, completion, error);
+	return zif_store_array_repos_search (store_array, PK_ROLE_ENUM_SEARCH_NAME, search,
+					     error_cb, user_data, cancellable, completion, error);
 }
 
 /**
  * zif_store_array_search_details:
  * @store_array: the #GPtrArray of #ZifStores
  * @search: the search term, e.g. "trouble"
+ * @error_cb: a #ZifStoreArrayErrorCb which returns %FALSE if the error is fatal
+ * @user_data: the user_data to be passed to the #ZifStoreArrayErrorCb
  * @cancellable: a #GCancellable which is used to cancel tasks, or %NULL
  * @completion: a #ZifCompletion to use for progress reporting
  * @error: a #GError which is used on failure, or %NULL
@@ -510,15 +544,20 @@ zif_store_array_search_name (GPtrArray *store_array, const gchar *search, GCance
  * Since: 0.0.1
  **/
 GPtrArray *
-zif_store_array_search_details (GPtrArray *store_array, const gchar *search, GCancellable *cancellable, ZifCompletion *completion, GError **error)
+zif_store_array_search_details (GPtrArray *store_array, const gchar *search,
+				ZifStoreArrayErrorCb error_cb, gpointer user_data,
+				GCancellable *cancellable, ZifCompletion *completion, GError **error)
 {
-	return zif_store_array_repos_search (store_array, PK_ROLE_ENUM_SEARCH_DETAILS, search, cancellable, completion, error);
+	return zif_store_array_repos_search (store_array, PK_ROLE_ENUM_SEARCH_DETAILS, search,
+					     error_cb, user_data, cancellable, completion, error);
 }
 
 /**
  * zif_store_array_search_group:
  * @store_array: the #GPtrArray of #ZifStores
  * @group_enum: the group enumerated value, e.g. "games"
+ * @error_cb: a #ZifStoreArrayErrorCb which returns %FALSE if the error is fatal
+ * @user_data: the user_data to be passed to the #ZifStoreArrayErrorCb
  * @cancellable: a #GCancellable which is used to cancel tasks, or %NULL
  * @completion: a #ZifCompletion to use for progress reporting
  * @error: a #GError which is used on failure, or %NULL
@@ -530,15 +569,20 @@ zif_store_array_search_details (GPtrArray *store_array, const gchar *search, GCa
  * Since: 0.0.1
  **/
 GPtrArray *
-zif_store_array_search_group (GPtrArray *store_array, const gchar *group_enum, GCancellable *cancellable, ZifCompletion *completion, GError **error)
+zif_store_array_search_group (GPtrArray *store_array, const gchar *group_enum,
+			      ZifStoreArrayErrorCb error_cb, gpointer user_data,
+			      GCancellable *cancellable, ZifCompletion *completion, GError **error)
 {
-	return zif_store_array_repos_search (store_array, PK_ROLE_ENUM_SEARCH_GROUP, group_enum, cancellable, completion, error);
+	return zif_store_array_repos_search (store_array, PK_ROLE_ENUM_SEARCH_GROUP, group_enum,
+					     error_cb, user_data, cancellable, completion, error);
 }
 
 /**
  * zif_store_array_search_category:
  * @store_array: the #GPtrArray of #ZifStores
  * @group_id: the group id, e.g. "gnome-system-tools"
+ * @error_cb: a #ZifStoreArrayErrorCb which returns %FALSE if the error is fatal
+ * @user_data: the user_data to be passed to the #ZifStoreArrayErrorCb
  * @cancellable: a #GCancellable which is used to cancel tasks, or %NULL
  * @completion: a #ZifCompletion to use for progress reporting
  * @error: a #GError which is used on failure, or %NULL
@@ -550,7 +594,9 @@ zif_store_array_search_group (GPtrArray *store_array, const gchar *group_enum, G
  * Since: 0.0.1
  **/
 GPtrArray *
-zif_store_array_search_category (GPtrArray *store_array, const gchar *group_id, GCancellable *cancellable, ZifCompletion *completion, GError **error)
+zif_store_array_search_category (GPtrArray *store_array, const gchar *group_id,
+				 ZifStoreArrayErrorCb error_cb, gpointer user_data,
+				 GCancellable *cancellable, ZifCompletion *completion, GError **error)
 {
 	guint i, j;
 	GPtrArray *array;
@@ -559,9 +605,9 @@ zif_store_array_search_category (GPtrArray *store_array, const gchar *group_id,
 	const gchar *package_id_tmp;
 	gchar **split;
 
-
 	/* get all results from all repos */
-	array = zif_store_array_repos_search (store_array, PK_ROLE_ENUM_SEARCH_CATEGORY, group_id, cancellable, completion, error);
+	array = zif_store_array_repos_search (store_array, PK_ROLE_ENUM_SEARCH_CATEGORY, group_id,
+					      error_cb, user_data, cancellable, completion, error);
 	if (array == NULL)
 		goto out;
 
@@ -590,6 +636,8 @@ out:
  * zif_store_array_search_file:
  * @store_array: the #GPtrArray of #ZifStores
  * @search: the search term, e.g. "/usr/bin/gnome-power-manager"
+ * @error_cb: a #ZifStoreArrayErrorCb which returns %FALSE if the error is fatal
+ * @user_data: the user_data to be passed to the #ZifStoreArrayErrorCb
  * @cancellable: a #GCancellable which is used to cancel tasks, or %NULL
  * @completion: a #ZifCompletion to use for progress reporting
  * @error: a #GError which is used on failure, or %NULL
@@ -601,14 +649,19 @@ out:
  * Since: 0.0.1
  **/
 GPtrArray *
-zif_store_array_search_file (GPtrArray *store_array, const gchar *search, GCancellable *cancellable, ZifCompletion *completion, GError **error)
+zif_store_array_search_file (GPtrArray *store_array, const gchar *search,
+			     ZifStoreArrayErrorCb error_cb, gpointer user_data,
+			     GCancellable *cancellable, ZifCompletion *completion, GError **error)
 {
-	return zif_store_array_repos_search (store_array, PK_ROLE_ENUM_SEARCH_FILE, search, cancellable, completion, error);
+	return zif_store_array_repos_search (store_array, PK_ROLE_ENUM_SEARCH_FILE, search,
+					     error_cb, user_data, cancellable, completion, error);
 }
 
 /**
  * zif_store_array_get_packages:
  * @store_array: the #GPtrArray of #ZifStores
+ * @error_cb: a #ZifStoreArrayErrorCb which returns %FALSE if the error is fatal
+ * @user_data: the user_data to be passed to the #ZifStoreArrayErrorCb
  * @cancellable: a #GCancellable which is used to cancel tasks, or %NULL
  * @completion: a #ZifCompletion to use for progress reporting
  * @error: a #GError which is used on failure, or %NULL
@@ -620,14 +673,19 @@ zif_store_array_search_file (GPtrArray *store_array, const gchar *search, GCance
  * Since: 0.0.1
  **/
 GPtrArray *
-zif_store_array_get_packages (GPtrArray *store_array, GCancellable *cancellable, ZifCompletion *completion, GError **error)
+zif_store_array_get_packages (GPtrArray *store_array,
+			      ZifStoreArrayErrorCb error_cb, gpointer user_data,
+			      GCancellable *cancellable, ZifCompletion *completion, GError **error)
 {
-	return zif_store_array_repos_search (store_array, PK_ROLE_ENUM_GET_PACKAGES, NULL, cancellable, completion, error);
+	return zif_store_array_repos_search (store_array, PK_ROLE_ENUM_GET_PACKAGES, NULL,
+					     error_cb, user_data, cancellable, completion, error);
 }
 
 /**
  * zif_store_array_get_updates:
  * @store_array: the #GPtrArray of #ZifStores
+ * @error_cb: a #ZifStoreArrayErrorCb which returns %FALSE if the error is fatal
+ * @user_data: the user_data to be passed to the #ZifStoreArrayErrorCb
  * @cancellable: a #GCancellable which is used to cancel tasks, or %NULL
  * @completion: a #ZifCompletion to use for progress reporting
  * @error: a #GError which is used on failure, or %NULL
@@ -639,15 +697,20 @@ zif_store_array_get_packages (GPtrArray *store_array, GCancellable *cancellable,
  * Since: 0.0.1
  **/
 GPtrArray *
-zif_store_array_get_updates (GPtrArray *store_array, GCancellable *cancellable, ZifCompletion *completion, GError **error)
+zif_store_array_get_updates (GPtrArray *store_array,
+			     ZifStoreArrayErrorCb error_cb, gpointer user_data,
+			     GCancellable *cancellable, ZifCompletion *completion, GError **error)
 {
-	return zif_store_array_repos_search (store_array, PK_ROLE_ENUM_GET_UPDATES, NULL, cancellable, completion, error);
+	return zif_store_array_repos_search (store_array, PK_ROLE_ENUM_GET_UPDATES, NULL,
+					     error_cb, user_data, cancellable, completion, error);
 }
 
 /**
  * zif_store_array_what_provides:
  * @store_array: the #GPtrArray of #ZifStores
  * @search: the search term, e.g. "gstreamer(codec-mp3)"
+ * @error_cb: a #ZifStoreArrayErrorCb which returns %FALSE if the error is fatal
+ * @user_data: the user_data to be passed to the #ZifStoreArrayErrorCb
  * @cancellable: a #GCancellable which is used to cancel tasks, or %NULL
  * @completion: a #ZifCompletion to use for progress reporting
  * @error: a #GError which is used on failure, or %NULL
@@ -659,18 +722,25 @@ zif_store_array_get_updates (GPtrArray *store_array, GCancellable *cancellable,
  * Since: 0.0.1
  **/
 GPtrArray *
-zif_store_array_what_provides (GPtrArray *store_array, const gchar *search, GCancellable *cancellable, ZifCompletion *completion, GError **error)
+zif_store_array_what_provides (GPtrArray *store_array, const gchar *search,
+			       ZifStoreArrayErrorCb error_cb, gpointer user_data,
+			       GCancellable *cancellable, ZifCompletion *completion, GError **error)
 {
 
 	/* if this is a path, then we use the file list and treat like a SearchFile */
-	if (g_str_has_prefix (search, "/"))
-		return zif_store_array_repos_search (store_array, PK_ROLE_ENUM_SEARCH_FILE, search, cancellable, completion, error);
-	return zif_store_array_repos_search (store_array, PK_ROLE_ENUM_WHAT_PROVIDES, search, cancellable, completion, error);
+	if (g_str_has_prefix (search, "/")) {
+		return zif_store_array_repos_search (store_array, PK_ROLE_ENUM_SEARCH_FILE, search,
+						     error_cb, user_data, cancellable, completion, error);
+	}
+	return zif_store_array_repos_search (store_array, PK_ROLE_ENUM_WHAT_PROVIDES, search,
+					     error_cb, user_data, cancellable, completion, error);
 }
 
 /**
  * zif_store_array_get_categories:
  * @store_array: the #GPtrArray of #ZifStores
+ * @error_cb: a #ZifStoreArrayErrorCb which returns %FALSE if the error is fatal
+ * @user_data: the user_data to be passed to the #ZifStoreArrayErrorCb
  * @cancellable: a #GCancellable which is used to cancel tasks, or %NULL
  * @completion: a #ZifCompletion to use for progress reporting
  * @error: a #GError which is used on failure, or %NULL
@@ -682,7 +752,9 @@ zif_store_array_what_provides (GPtrArray *store_array, const gchar *search, GCan
  * Since: 0.0.1
  **/
 GPtrArray *
-zif_store_array_get_categories (GPtrArray *store_array, GCancellable *cancellable, ZifCompletion *completion, GError **error)
+zif_store_array_get_categories (GPtrArray *store_array,
+				ZifStoreArrayErrorCb error_cb, gpointer user_data,
+				GCancellable *cancellable, ZifCompletion *completion, GError **error)
 {
 	guint i, j;
 	GPtrArray *array;
@@ -693,9 +765,9 @@ zif_store_array_get_categories (GPtrArray *store_array, GCancellable *cancellabl
 	gchar *cat_id;
 	gchar *cat_id_tmp;
 
-
 	/* get all results from all repos */
-	array = zif_store_array_repos_search (store_array, PK_ROLE_ENUM_GET_CATEGORIES, NULL, cancellable, completion, error);
+	array = zif_store_array_repos_search (store_array, PK_ROLE_ENUM_GET_CATEGORIES, NULL,
+					      error_cb, user_data, cancellable, completion, error);
 	if (array == NULL)
 		goto out;
 
@@ -717,7 +789,6 @@ zif_store_array_get_categories (GPtrArray *store_array, GCancellable *cancellabl
 			if (g_strcmp0 (parent_id_tmp, parent_id) == 0 &&
 			    g_strcmp0 (cat_id_tmp, cat_id) == 0) {
 				/* duplicate */
-				g_object_unref (obj_tmp);
 				g_ptr_array_remove_index (array, j);
 			}
 			g_free (parent_id_tmp);
diff --git a/backends/yum/libzif/zif-store-array.h b/backends/yum/libzif/zif-store-array.h
index 61c5dfc..7391c77 100644
--- a/backends/yum/libzif/zif-store-array.h
+++ b/backends/yum/libzif/zif-store-array.h
@@ -34,6 +34,10 @@
 
 G_BEGIN_DECLS
 
+typedef gboolean (*ZifStoreArrayErrorCb)		(GPtrArray		*store_array,
+							 const GError		*error,
+							 gpointer		 user_data);
+
 GPtrArray	*zif_store_array_new			(void);
 
 /* stores */
@@ -56,54 +60,76 @@ gboolean	 zif_store_array_add_remote_enabled	(GPtrArray		*store_array,
 
 /* methods */
 gboolean	 zif_store_array_clean			(GPtrArray		*store_array,
+							 ZifStoreArrayErrorCb	 error_cb,
+							 gpointer		 user_data,
 							 GCancellable		*cancellable,
 							 ZifCompletion		*completion,
 							 GError			**error);
 gboolean	 zif_store_array_refresh		(GPtrArray		*store_array,
 							 gboolean		 force,
+							 ZifStoreArrayErrorCb	 error_cb,
+							 gpointer		 user_data,
 							 GCancellable		*cancellable,
 							 ZifCompletion		*completion,
 							 GError			**error);
 GPtrArray	*zif_store_array_resolve		(GPtrArray		*store_array,
 							 const gchar		*search,
+							 ZifStoreArrayErrorCb	 error_cb,
+							 gpointer		 user_data,
 							 GCancellable		*cancellable,
 							 ZifCompletion		*completion,
 							 GError			**error);
 GPtrArray	*zif_store_array_search_name		(GPtrArray		*store_array,
 							 const gchar		*search,
+							 ZifStoreArrayErrorCb	 error_cb,
+							 gpointer		 user_data,
 							 GCancellable		*cancellable,
 							 ZifCompletion		*completion,
 							 GError			**error);
 GPtrArray	*zif_store_array_search_details		(GPtrArray		*store_array,
 							 const gchar		*search,
+							 ZifStoreArrayErrorCb	 error_cb,
+							 gpointer		 user_data,
 							 GCancellable		*cancellable,
 							 ZifCompletion		*completion,
 							 GError			**error);
 GPtrArray	*zif_store_array_search_group		(GPtrArray		*store_array,
 							 const gchar		*group_enum,
+							 ZifStoreArrayErrorCb	 error_cb,
+							 gpointer		 user_data,
 							 GCancellable		*cancellable,
 							 ZifCompletion		*completion,
 							 GError			**error);
 GPtrArray	*zif_store_array_search_category	(GPtrArray		*store_array,
 							 const gchar		*group_id,
+							 ZifStoreArrayErrorCb	 error_cb,
+							 gpointer		 user_data,
 							 GCancellable		*cancellable,
 							 ZifCompletion		*completion,
 							 GError			**error);
 GPtrArray	*zif_store_array_search_file		(GPtrArray		*store_array,
 							 const gchar		*search,
+							 ZifStoreArrayErrorCb	 error_cb,
+							 gpointer		 user_data,
 							 GCancellable		*cancellable,
 							 ZifCompletion		*completion,
 							 GError			**error);
 GPtrArray	*zif_store_array_what_provides		(GPtrArray		*store_array,
 							 const gchar		*search,
+							 ZifStoreArrayErrorCb	 error_cb,
+							 gpointer		 user_data,
 							 GCancellable		*cancellable,
 							 ZifCompletion		*completion,
 							 GError			**error);
 GPtrArray	*zif_store_array_get_packages		(GPtrArray		*store_array,
+							 ZifStoreArrayErrorCb	 error_cb,
+							 gpointer		 user_data,
 							 GCancellable		*cancellable,
 							 ZifCompletion		*completion,
 							 GError			**error);
 GPtrArray	*zif_store_array_get_updates		(GPtrArray		*store_array,
+							 ZifStoreArrayErrorCb	 error_cb,
+							 gpointer		 user_data,
 							 GCancellable		*cancellable,
 							 ZifCompletion		*completion,
 							 GError			**error);
@@ -113,6 +139,8 @@ ZifPackage	*zif_store_array_find_package		(GPtrArray		*store_array,
 							 ZifCompletion		*completion,
 							 GError			**error);
 GPtrArray	*zif_store_array_get_categories		(GPtrArray		*store_array,
+							 ZifStoreArrayErrorCb	 error_cb,
+							 gpointer		 user_data,
 							 GCancellable		*cancellable,
 							 ZifCompletion		*completion,
 							 GError			**error);
diff --git a/backends/yum/pk-backend-yum.c b/backends/yum/pk-backend-yum.c
index baedb54..51cfef4 100644
--- a/backends/yum/pk-backend-yum.c
+++ b/backends/yum/pk-backend-yum.c
@@ -391,6 +391,17 @@ backend_emit_package_array (PkBackend *backend, GPtrArray *array)
 }
 
 /**
+ * backend_error_handler_cb:
+ */
+static gboolean
+backend_error_handler_cb (GPtrArray *store_array, const GError *error, PkBackend *backend)
+{
+	/* emit a warning, this isn't fatal */
+	pk_backend_message (backend, PK_MESSAGE_ENUM_BROKEN_MIRROR, "%s", error->message);
+	return TRUE;
+}
+
+/**
  * backend_search_thread_get_array:
  */
 static GPtrArray *
@@ -400,20 +411,33 @@ backend_search_thread_get_array (PkBackend *backend, GPtrArray *store_array, con
 	GPtrArray *array = NULL;
 
 	role = pk_backend_get_role (backend);
-	if (role == PK_ROLE_ENUM_SEARCH_NAME)
-		array = zif_store_array_search_name (store_array, search, priv->cancellable, completion, error);
-	else if (role == PK_ROLE_ENUM_SEARCH_DETAILS)
-		array = zif_store_array_search_details (store_array, search, priv->cancellable, completion, error);
-	else if (role == PK_ROLE_ENUM_SEARCH_GROUP)
-		array = zif_store_array_search_category (store_array, search, priv->cancellable, completion, error);
-	else if (role == PK_ROLE_ENUM_SEARCH_FILE)
-		array = zif_store_array_search_file (store_array, search, priv->cancellable, completion, error);
-	else if (role == PK_ROLE_ENUM_RESOLVE)
-		array = zif_store_array_resolve (store_array, search, priv->cancellable, completion, error);
-	else if (role == PK_ROLE_ENUM_WHAT_PROVIDES)
-		array = zif_store_array_what_provides (store_array, search, priv->cancellable, completion, error);
-	else
+	if (role == PK_ROLE_ENUM_SEARCH_NAME) {
+		array = zif_store_array_search_name (store_array, search,
+						     (ZifStoreArrayErrorCb) backend_error_handler_cb, backend,
+						     priv->cancellable, completion, error);
+	} else if (role == PK_ROLE_ENUM_SEARCH_DETAILS) {
+		array = zif_store_array_search_details (store_array, search,
+							(ZifStoreArrayErrorCb) backend_error_handler_cb, backend,
+							priv->cancellable, completion, error);
+	} else if (role == PK_ROLE_ENUM_SEARCH_GROUP) {
+		array = zif_store_array_search_category (store_array, search,
+							 (ZifStoreArrayErrorCb) backend_error_handler_cb, backend,
+							 priv->cancellable, completion, error);
+	} else if (role == PK_ROLE_ENUM_SEARCH_FILE) {
+		array = zif_store_array_search_file (store_array, search,
+						     (ZifStoreArrayErrorCb) backend_error_handler_cb, backend,
+						     priv->cancellable, completion, error);
+	} else if (role == PK_ROLE_ENUM_RESOLVE) {
+		array = zif_store_array_resolve (store_array, search,
+						 (ZifStoreArrayErrorCb) backend_error_handler_cb, backend,
+						 priv->cancellable, completion, error);
+	} else if (role == PK_ROLE_ENUM_WHAT_PROVIDES) {
+		array = zif_store_array_what_provides (store_array, search,
+						       (ZifStoreArrayErrorCb) backend_error_handler_cb, backend,
+						       priv->cancellable, completion, error);
+	} else {
 		g_set_error (error, 1, 0, "does not support: %s", pk_role_enum_to_string (role));
+	}
 	return array;
 }
 
@@ -507,7 +531,7 @@ backend_search_thread (PkBackend *backend)
 	/* do get action */
 	if (role == PK_ROLE_ENUM_GET_PACKAGES) {
 		completion_local = zif_completion_get_child (priv->completion);
-		array = zif_store_array_get_packages (store_array, priv->cancellable, completion_local, &error);
+		array = zif_store_array_get_packages (store_array, (ZifStoreArrayErrorCb) backend_error_handler_cb, backend, priv->cancellable, completion_local, &error);
 		if (array == NULL) {
 			pk_backend_error_code (backend, PK_ERROR_ENUM_INTERNAL_ERROR, "failed to get packages: %s", error->message);
 			g_error_free (error);
@@ -1759,137 +1783,6 @@ backend_what_provides (PkBackend *backend, PkBitfield filters, PkProvidesEnum pr
 	g_free (search);
 }
 
-#define PK_ROLE_ENUM_SEARCH_CATEGORY	(PK_ROLE_ENUM_UNKNOWN + 1)
-
-/**
- * backend_repos_search:
- **/
-static GPtrArray *
-backend_repos_search (PkBackend *backend, GPtrArray *stores, PkRoleEnum role, const gchar *search, ZifCompletion *completion, GError **error)
-{
-	guint i, j;
-	GPtrArray *array = NULL;
-	GPtrArray *part;
-	ZifStore *store;
-	ZifPackage *package;
-	GError *error_local = NULL;
-	ZifCompletion *completion_local = NULL;
-
-	/* nothing to do */
-	if (stores->len == 0) {
-		if (error != NULL)
-			*error = g_error_new (1, 0, "nothing to do as no stores");
-		goto out;
-	}
-
-	/* set number of stores */
-	zif_completion_set_number_steps (completion, stores->len);
-
-	/* do each one */
-	array = g_ptr_array_new_with_free_func ((GDestroyNotify) g_object_unref);
-	for (i=0; i<stores->len; i++) {
-		store = g_ptr_array_index (stores, i);
-
-		/* create a chain of completions */
-		completion_local = zif_completion_get_child (completion);
-
-		/* get results for this store */
-		if (role == PK_ROLE_ENUM_RESOLVE)
-			part = zif_store_resolve (store, search, priv->cancellable, completion_local, &error_local);
-		else if (role == PK_ROLE_ENUM_SEARCH_NAME)
-			part = zif_store_search_name (store, search, priv->cancellable, completion_local, &error_local);
-		else if (role == PK_ROLE_ENUM_SEARCH_DETAILS)
-			part = zif_store_search_details (store, search, priv->cancellable, completion_local, &error_local);
-		else if (role == PK_ROLE_ENUM_SEARCH_GROUP)
-			part = zif_store_search_group (store, search, priv->cancellable, completion_local, &error_local);
-		else if (role == PK_ROLE_ENUM_SEARCH_CATEGORY)
-			part = zif_store_search_category (store, search, priv->cancellable, completion_local, &error_local);
-		else if (role == PK_ROLE_ENUM_SEARCH_FILE)
-			part = zif_store_search_file (store, search, priv->cancellable, completion_local, &error_local);
-		else if (role == PK_ROLE_ENUM_GET_PACKAGES)
-			part = zif_store_get_packages (store, priv->cancellable, completion_local, &error_local);
-		else if (role == PK_ROLE_ENUM_GET_UPDATES)
-			part = zif_store_get_updates (store, priv->cancellable, completion_local, &error_local);
-		else if (role == PK_ROLE_ENUM_WHAT_PROVIDES)
-			part = zif_store_what_provides (store, search, priv->cancellable, completion_local, &error_local);
-		else if (role == PK_ROLE_ENUM_GET_CATEGORIES)
-			part = zif_store_get_categories (store, priv->cancellable, completion_local, &error_local);
-		else
-			egg_error ("internal error: %s", pk_role_enum_to_text (role));
-		if (part == NULL) {
-			/* emit a warning, this isn't fatal */
-			pk_backend_message (backend, PK_MESSAGE_ENUM_BROKEN_MIRROR, "failed to %s for repo %s: %s",
-					    pk_role_enum_to_text (role),
-					    zif_store_get_id (store),
-					    error_local->message);
-			g_clear_error (&error_local);
-			zif_completion_done (completion);
-			continue;
-		}
-
-		for (j=0; j<part->len; j++) {
-			package = g_ptr_array_index (part, j);
-			g_ptr_array_add (array, g_object_ref (package));
-		}
-		g_ptr_array_unref (part);
-
-		/* this section done */
-		zif_completion_done (completion);
-	}
-out:
-	return array;
-}
-
-/**
- * backend_get_unique_categories:
- **/
-static GPtrArray *
-backend_get_unique_categories (PkBackend *backend, GPtrArray *stores, ZifCompletion *completion, GError **error)
-{
-	guint i, j;
-	GPtrArray *array;
-	PkCategory *obj;
-	PkCategory *obj_tmp;
-	gchar *parent_id;
-	gchar *parent_id_tmp;
-	gchar *cat_id;
-	gchar *cat_id_tmp;
-
-	/* get all results from all repos */
-	array = backend_repos_search (backend, stores, PK_ROLE_ENUM_GET_CATEGORIES, NULL, completion, error);
-	if (array == NULL)
-		goto out;
-
-	/* remove duplicate parents and groups */
-	for (i=0; i<array->len; i++) {
-		obj = g_ptr_array_index (array, i);
-		g_object_get (obj,
-			      "parent-id", &parent_id,
-			      "cat-id", &cat_id,
-			      NULL);
-		for (j=0; j<array->len; j++) {
-			if (i == j)
-				continue;
-			obj_tmp = g_ptr_array_index (array, j);
-			g_object_get (obj_tmp,
-				      "parent-id", &parent_id_tmp,
-				      "cat-id", &cat_id_tmp,
-				      NULL);
-			if (g_strcmp0 (parent_id_tmp, parent_id) == 0 &&
-			    g_strcmp0 (cat_id_tmp, cat_id) == 0) {
-				egg_warning ("duplicate %s-%s", parent_id, cat_id);
-				g_ptr_array_remove_index (array, j);
-			}
-			g_free (parent_id_tmp);
-			g_free (cat_id_tmp);
-		}
-		g_free (parent_id);
-		g_free (cat_id);
-	}
-out:
-	return array;
-}
-
 /**
  * backend_get_categories_thread:
  */
@@ -1937,7 +1830,8 @@ backend_get_categories_thread (PkBackend *backend)
 
 	/* get sorted list of unique categories */
 	completion_local = zif_completion_get_child (priv->completion);
-	array = backend_get_unique_categories (backend, stores, completion_local, &error);
+	array = zif_store_array_get_categories (stores, (ZifStoreArrayErrorCb) backend_error_handler_cb, backend,
+						priv->cancellable, completion_local, &error);
 	if (array == NULL) {
 		pk_backend_error_code (backend, PK_ERROR_ENUM_GROUP_LIST_INVALID, "failed to add get categories: %s", error->message);
 		g_error_free (error);
commit 782b1c9122ac0959b063e4fb750a49bcae379fbf
Author: Richard Hughes <richard at hughsie.com>
Date:   Thu Mar 11 12:13:04 2010 +0000

    yum: add an entry UseZif into Yum.conf so admins can change the default setting

diff --git a/backends/yum/Yum.conf b/backends/yum/Yum.conf
index 8b07cba..2cfb6dd 100644
--- a/backends/yum/Yum.conf
+++ b/backends/yum/Yum.conf
@@ -13,3 +13,14 @@
 # default=rpm-warm-cache;remove-with-leaves;auto-update-debuginfo
 DisabledPlugins=rpm-warm-cache;remove-with-leaves;auto-update-debuginfo
 
+# Yum is slow, and we can use Zif to accelerate some simple transactions
+#
+# Yum is written in python, and we therefor have to execute a new process and
+# communicate with it. This is much slower than just acessing the repo files
+# and rpmdb in a C thread. Zif is a pretty new project, and is not well tested
+# at this time. It is however up to an order of magnitude faster in some
+# benchmark tests.
+#
+# default=true
+UseZif=true
+
diff --git a/backends/yum/pk-backend-yum.c b/backends/yum/pk-backend-yum.c
index 309efee..baedb54 100644
--- a/backends/yum/pk-backend-yum.c
+++ b/backends/yum/pk-backend-yum.c
@@ -30,12 +30,12 @@
 #define YUM_BACKEND_LOCKING_RETRIES		10
 #define YUM_BACKEND_LOCKING_DELAY		2 /* seconds */
 
-static gboolean use_zif = TRUE;
 
 typedef struct {
 	PkBackendSpawn	*spawn;
 	GFileMonitor	*monitor;
 	GCancellable	*cancellable;
+	gboolean	 use_zif;
 	ZifDownload	*download;
 	ZifConfig	*config;
 	ZifStoreLocal	*store_local;
@@ -582,6 +582,7 @@ backend_initialize (PkBackend *backend)
 	gboolean ret;
 	GFile *file;
 	GError *error = NULL;
+	GKeyFile *key_file = NULL;
 
 	/* create private area */
 	priv = g_new0 (PkBackendYumPrivate, 1);
@@ -603,8 +604,18 @@ backend_initialize (PkBackend *backend)
 		g_error_free (error);
 	}
 
+	/* read the config file */
+	key_file = g_key_file_new ();
+	ret = g_key_file_load_from_file (key_file, SYSCONFDIR "/PackageKit/Yum.conf", G_KEY_FILE_NONE, &error);
+	if (!ret) {
+		pk_backend_error_code (backend, PK_ERROR_ENUM_REPO_CONFIGURATION_ERROR, "failed to load Yum.conf: %s", error->message);
+		g_error_free (error);
+		goto out;
+	}
+
 	/* it seems some people are not ready for the awesomeness */
-	if (!use_zif)
+	priv->use_zif = g_key_file_get_boolean (key_file, "Backend", "UseZif", NULL);
+	if (!priv->use_zif)
 		goto out;
 
 	/* use a timer for profiling */
@@ -678,6 +689,7 @@ backend_initialize (PkBackend *backend)
 	/* profile */
 	backend_profile ("read groups");
 out:
+	g_key_file_free (key_file);
 	g_object_unref (file);
 }
 
@@ -721,7 +733,7 @@ backend_get_groups (PkBackend *backend)
 	PkBitfield groups;
 
 	/* it seems some people are not ready for the awesomeness */
-	if (!use_zif) {
+	if (!priv->use_zif) {
 		groups = pk_bitfield_from_enums (
 			PK_GROUP_ENUM_COLLECTIONS,
 			PK_GROUP_ENUM_NEWEST,
@@ -982,7 +994,7 @@ static void
 backend_get_details (PkBackend *backend, gchar **package_ids)
 {
 	/* check if we can use zif */
-	if (!use_zif) {
+	if (!priv->use_zif) {
 		gchar *package_ids_temp;
 		package_ids_temp = pk_package_ids_to_string (package_ids);
 		pk_backend_spawn_helper (priv->spawn, "yumBackend.py", "get-details", package_ids_temp, NULL);
@@ -1105,7 +1117,7 @@ static void
 backend_get_distro_upgrades (PkBackend *backend)
 {
 	/* it seems some people are not ready for the awesomeness */
-	if (!use_zif) {
+	if (!priv->use_zif) {
 		pk_backend_spawn_helper (priv->spawn, "yumBackend.py", "get-distro-upgrades", NULL);
 		return;
 	}
@@ -1231,7 +1243,7 @@ backend_get_files (PkBackend *backend, gchar **package_ids)
 
 	/* check if we can use zif */
 	ret = backend_is_all_installed (package_ids);
-	if (ret && use_zif) {
+	if (ret && priv->use_zif) {
 		pk_backend_thread_create (backend, backend_get_files_thread);
 		return;
 	}
@@ -1276,7 +1288,7 @@ static void
 backend_get_packages (PkBackend *backend, PkBitfield filters)
 {
 	/* it seems some people are not ready for the awesomeness */
-	if (!use_zif) {
+	if (!priv->use_zif) {
 		gchar *filters_text;
 		filters_text = pk_filter_bitfield_to_string (filters);
 		pk_backend_spawn_helper (priv->spawn, "yumBackend.py", "get-packages", filters_text, NULL);
@@ -1418,7 +1430,7 @@ static void
 backend_search_details (PkBackend *backend, PkBitfield filters, gchar **values)
 {
 	/* it seems some people are not ready for the awesomeness */
-	if (!use_zif) {
+	if (!priv->use_zif) {
 		gchar *filters_text;
 		gchar *search;
 		filters_text = pk_filter_bitfield_to_string (filters);
@@ -1438,7 +1450,7 @@ static void
 backend_search_files (PkBackend *backend, PkBitfield filters, gchar **values)
 {
 	/* it seems some people are not ready for the awesomeness */
-	if (!use_zif) {
+	if (!priv->use_zif) {
 		gchar *filters_text;
 		gchar *search;
 		filters_text = pk_filter_bitfield_to_string (filters);
@@ -1458,7 +1470,7 @@ static void
 backend_search_groups (PkBackend *backend, PkBitfield filters, gchar **values)
 {
 	/* it seems some people are not ready for the awesomeness */
-	if (!use_zif) {
+	if (!priv->use_zif) {
 		gchar *filters_text;
 		gchar *search;
 		filters_text = pk_filter_bitfield_to_string (filters);
@@ -1478,7 +1490,7 @@ static void
 backend_search_names (PkBackend *backend, PkBitfield filters, gchar **values)
 {
 	/* it seems some people are not ready for the awesomeness */
-	if (!use_zif) {
+	if (!priv->use_zif) {
 		gchar *filters_text;
 		gchar *search;
 		filters_text = pk_filter_bitfield_to_string (filters);
@@ -1521,7 +1533,7 @@ static void
 backend_resolve (PkBackend *backend, PkBitfield filters, gchar **packages)
 {
 	/* it seems some people are not ready for the awesomeness */
-	if (!use_zif) {
+	if (!priv->use_zif) {
 		gchar *filters_text;
 		gchar *package_ids_temp;
 		filters_text = pk_filter_bitfield_to_string (filters);
@@ -1628,7 +1640,7 @@ static void
 backend_get_repo_list (PkBackend *backend, PkBitfield filters)
 {
 	/* it seems some people are not ready for the awesomeness */
-	if (!use_zif) {
+	if (!priv->use_zif) {
 		gchar *filters_text;
 		filters_text = pk_filter_bitfield_to_string (filters);
 		pk_backend_spawn_helper (priv->spawn, "yumBackend.py", "get-repo-list", filters_text, NULL);
@@ -1709,7 +1721,7 @@ static void
 backend_repo_enable (PkBackend *backend, const gchar *repo_id, gboolean enabled)
 {
 	/* it seems some people are not ready for the awesomeness */
-	if (!use_zif) {
+	if (!priv->use_zif) {
 		if (enabled == TRUE) {
 			pk_backend_spawn_helper (priv->spawn, "yumBackend.py", "repo-enable", repo_id, "true", NULL);
 		} else {
@@ -1971,7 +1983,7 @@ static void
 backend_get_categories (PkBackend *backend)
 {
 	/* it seems some people are not ready for the awesomeness */
-	if (!use_zif) {
+	if (!priv->use_zif) {
 		pk_backend_spawn_helper (priv->spawn, "yumBackend.py", "get-categories", NULL);
 		return;
 	}
commit ab3a78ee15cf866d03ecdf79917e11cf8def092a
Author: Richard Hughes <richard at hughsie.com>
Date:   Thu Mar 11 11:23:10 2010 +0000

    yum: add a Yum.conf configuration file and add the DisabledPlugin key there

diff --git a/backends/yum/Makefile.am b/backends/yum/Makefile.am
index f500bed..b6675d8 100644
--- a/backends/yum/Makefile.am
+++ b/backends/yum/Makefile.am
@@ -87,6 +87,12 @@ libpk_backend_yum_la_LIBADD +=					\
 	$(ARCHIVE_LIBS)						\
 	$(NULL)
 
+confdir = $(PK_CONF_DIR)
+conf_DATA = Yum.conf
+
+EXTRA_DIST =							\
+	$(conf_DATA)
+
 install-data-hook:
 	chmod a+rx $(DESTDIR)$(helperdir)/*.py
 
diff --git a/backends/yum/Yum.conf b/backends/yum/Yum.conf
new file mode 100644
index 0000000..8b07cba
--- /dev/null
+++ b/backends/yum/Yum.conf
@@ -0,0 +1,15 @@
+# Only the system administrator should modify this file, ordinary users
+# should not have to change anything.
+
+[Backend]
+
+# Yum plugins which we should disabled when running with PackageKit
+#
+# Some yum plugins do not work well with PackageKit, either by trying to be too
+# clever or by adding support for things that PackageKit doesn't understand
+#
+# Seporate entries can be seporated with the ';' character.
+#
+# default=rpm-warm-cache;remove-with-leaves;auto-update-debuginfo
+DisabledPlugins=rpm-warm-cache;remove-with-leaves;auto-update-debuginfo
+
diff --git a/backends/yum/yumBackend.py b/backends/yum/yumBackend.py
index 87ed876..6998728 100755
--- a/backends/yum/yumBackend.py
+++ b/backends/yum/yumBackend.py
@@ -3033,10 +3033,19 @@ class PackageKitYumBase(yum.YumBase):
     def __init__(self, backend):
         yum.YumBase.__init__(self)
 
+        # load the config file
+        config = ConfigParser.ConfigParser()
+        try:
+            config.read('/etc/PackageKit/Yum.conf')
+            disabled_plugins = config.get('Backend', 'DisabledPlugins').split(';')
+        except Exception, e:
+            raise PkError(ERROR_REPO_CONFIGURATION_ERROR, "Failed to load Yum.conf: %s" % _to_unicode(e))
+        disabled_plugins.append('refresh-packagekit')
+
         # disable the PackageKit plugin when running under PackageKit
         try:
             pc = self.preconf
-            pc.disabled_plugins = ['refresh-packagekit', 'rpm-warm-cache', 'remove-with-leaves', 'auto-update-debuginfo']
+            pc.disabled_plugins = disabled_plugins
         except yum.Errors.ConfigError, e:
             raise PkError(ERROR_REPO_CONFIGURATION_ERROR, _to_unicode(e))
         except ValueError, e:
diff --git a/contrib/PackageKit.spec.in b/contrib/PackageKit.spec.in
index 97262dd..68d3b41 100644
--- a/contrib/PackageKit.spec.in
+++ b/contrib/PackageKit.spec.in
@@ -318,7 +318,8 @@ update-mime-database %{_datadir}/mime &> /dev/null || :
 %dir %{_sysconfdir}/bash_completion.d
 %dir %{_libdir}/packagekit-backend
 %config %{_sysconfdir}/bash_completion.d/pk-completion.bash
-%config(noreplace) %{_sysconfdir}/PackageKit/*.conf
+%config(noreplace) %{_sysconfdir}/PackageKit/PackageKit.conf
+%config(noreplace) %{_sysconfdir}/PackageKit/Vendor.conf
 %config %{_sysconfdir}/dbus-1/system.d/*
 %dir %{_datadir}/PackageKit/helpers/test_spawn
 %dir %{_datadir}/PackageKit/icons
@@ -366,6 +367,7 @@ update-mime-database %{_datadir}/mime &> /dev/null || :
 %files yum
 %defattr(-,root,root,-)
 %doc README AUTHORS NEWS COPYING
+%config(noreplace) %{_sysconfdir}/PackageKit/Yum.conf
 %{_libdir}/packagekit-backend/libpk_backend_yum.so
 %dir %{_datadir}/PackageKit/helpers/yum
 %{_datadir}/PackageKit/helpers/yum/*
@@ -421,6 +423,7 @@ update-mime-database %{_datadir}/mime &> /dev/null || :
 %doc README AUTHORS NEWS COPYING
 %{_sysconfdir}/profile.d/*
 %{_libexecdir}/pk-command-not-found
+%config(noreplace) %{_sysconfdir}/PackageKit/CommandNotFound.conf
 
 %files device-rebind
 %defattr(-,root,root,-)
commit 6a9be7be3a68d860149ada7dd80df7124c3a3660
Author: Richard Hughes <richard at hughsie.com>
Date:   Thu Mar 11 10:59:53 2010 +0000

    yum: fix searching by file when using zif

diff --git a/backends/yum/libzif/zif-completion.c b/backends/yum/libzif/zif-completion.c
index 8930492..9ee0352 100644
--- a/backends/yum/libzif/zif-completion.c
+++ b/backends/yum/libzif/zif-completion.c
@@ -49,24 +49,24 @@
  * static void
  * _do_something (ZifCompletion *completion)
  * {
- * 	ZifCompletion *completion_local;
+ *	ZifCompletion *completion_local;
  *
- * 	// setup correct number of steps
- * 	zif_completion_set_number_steps (completion, 2);
+ *	// setup correct number of steps
+ *	zif_completion_set_number_steps (completion, 2);
  *
- * 	// run a sub function
- * 	completion_local = zif_completion_get_child (completion);
- * 	_do_something_else1 (completion_local);
+ *	// run a sub function
+ *	completion_local = zif_completion_get_child (completion);
+ *	_do_something_else1 (completion_local);
  *
- * 	// this section done
- * 	zif_completion_done (completion);
+ *	// this section done
+ *	zif_completion_done (completion);
  *
- * 	// run another sub function
- * 	completion_local = zif_completion_get_child (completion);
- * 	_do_something_else2 (completion_local);
+ *	// run another sub function
+ *	completion_local = zif_completion_get_child (completion);
+ *	_do_something_else2 (completion_local);
  *
- * 	// this section done (all complete)
- * 	zif_completion_done (completion);
+ *	// this section done (all complete)
+ *	zif_completion_done (completion);
  * }
  *   </programlisting>
  * </example>
diff --git a/backends/yum/libzif/zif-package-local.c b/backends/yum/libzif/zif-package-local.c
index cf940a5..d6fd455 100644
--- a/backends/yum/libzif/zif-package-local.c
+++ b/backends/yum/libzif/zif-package-local.c
@@ -295,13 +295,13 @@ zif_package_local_ensure_data (ZifPackage *pkg, ZifPackageEnsureType type, GErro
 			fileindex = zif_get_header_uint32_index (header, RPMTAG_DIRINDEXES, basenames->len);
 			if (basenames->len != fileindex->len) {
 				ret = FALSE;
- 				g_set_error_literal (error, ZIF_PACKAGE_ERROR, ZIF_PACKAGE_ERROR_FAILED,
+				g_set_error_literal (error, ZIF_PACKAGE_ERROR, ZIF_PACKAGE_ERROR_FAILED,
 						     "internal error, basenames length is not the same as index length, possibly corrupt db?");
 				goto out;
- 			}
+			}
 			if (fileindex->len > fileindex->len) {
 				ret = FALSE;
- 				g_set_error_literal (error, ZIF_PACKAGE_ERROR, ZIF_PACKAGE_ERROR_FAILED,
+				g_set_error_literal (error, ZIF_PACKAGE_ERROR, ZIF_PACKAGE_ERROR_FAILED,
 						     "internal error, fileindex length is bigger than index length, possibly corrupt db?");
 				goto out;
 			}
@@ -535,7 +535,7 @@ zif_package_local_set_from_filename (ZifPackageLocal *pkg, const gchar *filename
 	GError *error_local = NULL;
 
 	/* open the file for reading */
-	fd = Fopen(filename, "r.fdio"); 
+	fd = Fopen(filename, "r.fdio");
 	if (fd == NULL) {
 		g_set_error (error, ZIF_PACKAGE_ERROR, ZIF_PACKAGE_ERROR_FAILED,
 			     "failed to open %s", filename);
diff --git a/backends/yum/libzif/zif-repo-md-comps.c b/backends/yum/libzif/zif-repo-md-comps.c
index 7fc94f0..066fb60 100644
--- a/backends/yum/libzif/zif-repo-md-comps.c
+++ b/backends/yum/libzif/zif-repo-md-comps.c
@@ -97,7 +97,7 @@ typedef struct {
 struct _ZifRepoMdCompsPrivate
 {
 	gboolean			 loaded;
-	GPtrArray			*array_groups;	 	/* stored as ZifRepoMdCompsGroupData */
+	GPtrArray			*array_groups;		/* stored as ZifRepoMdCompsGroupData */
 	GPtrArray			*array_categories;	/* stored as ZifRepoMdCompsCategoryData */
 	/* for parser */
 	ZifRepoMdCompsSection		 section;
diff --git a/backends/yum/libzif/zif-repo-md-filelists.c b/backends/yum/libzif/zif-repo-md-filelists.c
index 9b06362..007610b 100644
--- a/backends/yum/libzif/zif-repo-md-filelists.c
+++ b/backends/yum/libzif/zif-repo-md-filelists.c
@@ -196,7 +196,7 @@ zif_repo_md_filelists_search_file (ZifRepoMdFilelists *md, const gchar *search,
 
 	/* if not already loaded, load */
 	if (!md->priv->loaded) {
-		ret = zif_repo_md_filelists_load (ZIF_REPO_MD (md), cancellable, completion, &error_local);
+		ret = zif_repo_md_load (ZIF_REPO_MD (md), cancellable, completion, &error_local);
 		if (!ret) {
 			g_set_error (error, ZIF_REPO_MD_ERROR, ZIF_REPO_MD_ERROR_FAILED_TO_LOAD,
 				     "failed to load store file: %s", error_local->message);
diff --git a/backends/yum/libzif/zif-repo-md-primary.c b/backends/yum/libzif/zif-repo-md-primary.c
index 59020d3..2dccab4 100644
--- a/backends/yum/libzif/zif-repo-md-primary.c
+++ b/backends/yum/libzif/zif-repo-md-primary.c
@@ -292,8 +292,8 @@ zif_repo_md_primary_search_group (ZifRepoMdPrimary *md, const gchar *search, GCa
 
 	g_return_val_if_fail (ZIF_IS_REPO_MD_PRIMARY (md), FALSE);
 
-	/* FIXME: search with predicate */
-	pred = g_strdup_printf ("WHERE group = '%s'", search);
+	/* search with predicate */
+	pred = g_strdup_printf ("WHERE rpm_group = '%s'", search);
 	array = zif_repo_md_primary_search (md, pred, cancellable, completion, error);
 	g_free (pred);
 
@@ -322,7 +322,7 @@ zif_repo_md_primary_search_pkgid (ZifRepoMdPrimary *md, const gchar *search, GCa
 
 	g_return_val_if_fail (ZIF_IS_REPO_MD_PRIMARY (md), FALSE);
 
-	/* FIXME: search with predicate */
+	/* search with predicate */
 	pred = g_strdup_printf ("WHERE pkgid = '%s'", search);
 	array = zif_repo_md_primary_search (md, pred, cancellable, completion, error);
 	g_free (pred);
diff --git a/backends/yum/libzif/zif-store-array.c b/backends/yum/libzif/zif-store-array.c
index 6cdbb2f..583f9fc 100644
--- a/backends/yum/libzif/zif-store-array.c
+++ b/backends/yum/libzif/zif-store-array.c
@@ -229,7 +229,6 @@ zif_store_array_repos_search (GPtrArray *store_array, PkRoleEnum role, const gch
 
 	/* nothing to do */
 	if (store_array->len == 0) {
-		egg_warning ("nothing to do");
 		g_set_error (error, ZIF_STORE_ERROR, ZIF_STORE_ERROR_ARRAY_IS_EMPTY,
 			     "nothing to do as no stores in store_array");
 		goto out;
@@ -272,8 +271,8 @@ zif_store_array_repos_search (GPtrArray *store_array, PkRoleEnum role, const gch
 				     "internal error, no such role: %s", pk_role_enum_to_text (role));
 			g_ptr_array_unref (array);
 			array = NULL;
- 			goto out;
- 		}
+			goto out;
+		}
 		if (part == NULL) {
 			g_set_error (error, ZIF_STORE_ERROR, ZIF_STORE_ERROR_FAILED,
 				     "failed to %s in %s: %s", pk_role_enum_to_text (role), zif_store_get_id (store), error_local->message);
@@ -439,8 +438,6 @@ zif_store_array_refresh (GPtrArray *store_array, gboolean force, GCancellable *c
 	for (i=0; i<store_array->len; i++) {
 		store = g_ptr_array_index (store_array, i);
 
-		egg_warning ("refreshing %s", zif_store_get_id (store));
-
 		/* refresh this one */
 		completion_local = zif_completion_get_child (completion);
 		ret = zif_store_refresh (store, force, cancellable, completion_local, &error_local);
@@ -579,7 +576,7 @@ zif_store_array_search_category (GPtrArray *store_array, const gchar *group_id,
 			package_id_tmp = zif_package_get_id (package);
 			if (g_strcmp0 (package_id, package_id_tmp) == 0) {
 				split = pk_package_id_split (package_id);
-				egg_warning ("duplicate %s-%s", split[PK_PACKAGE_ID_NAME], split[PK_PACKAGE_ID_VERSION]);
+				/* duplicate */
 				g_ptr_array_remove_index (array, j);
 				g_strfreev (split);
 			}
@@ -719,7 +716,7 @@ zif_store_array_get_categories (GPtrArray *store_array, GCancellable *cancellabl
 				      NULL);
 			if (g_strcmp0 (parent_id_tmp, parent_id) == 0 &&
 			    g_strcmp0 (cat_id_tmp, cat_id) == 0) {
-				egg_warning ("duplicate %s-%s", parent_id, cat_id);
+				/* duplicate */
 				g_object_unref (obj_tmp);
 				g_ptr_array_remove_index (array, j);
 			}
diff --git a/backends/yum/libzif/zif-store-remote.c b/backends/yum/libzif/zif-store-remote.c
index 6e8693c..ead84e2 100644
--- a/backends/yum/libzif/zif-store-remote.c
+++ b/backends/yum/libzif/zif-store-remote.c
@@ -1551,7 +1551,7 @@ zif_store_remote_search_category_resolve (ZifStore *store, const gchar *name, GC
 		goto out;
 
 	/* we suck */
-	g_set_error (error, ZIF_STORE_ERROR, ZIF_STORE_ERROR_FAILED,
+	g_set_error (error, ZIF_STORE_ERROR, ZIF_STORE_ERROR_FAILED_TO_FIND,
 		     "failed to resolve installed package %s installed or in this repo", name);
 out:
 	if (array != NULL)
@@ -1654,10 +1654,10 @@ zif_store_remote_search_category (ZifStore *store, const gchar *group_id, GCance
 		completion_loop = zif_completion_get_child (completion_local);
 		package = zif_store_remote_search_category_resolve (store, name, cancellable, completion_loop, &error_local);
 		if (package == NULL) {
-			/* ignore when package isn't present, TODO: use GError code */
-			if (g_str_has_prefix (error_local->message, "failed to resolve")) {
-				g_error_free (error_local);
-				egg_warning ("Failed to find %s installed or in repo %s", name, remote->priv->id);
+			/* ignore when package isn't present */
+			if (error_local->code == ZIF_STORE_ERROR_FAILED_TO_FIND) {
+				g_clear_error (&error_local);
+				egg_debug ("Failed to find %s installed or in repo %s", name, remote->priv->id);
 				goto ignore_error;
 			}
 
@@ -2533,7 +2533,7 @@ zif_store_remote_init (ZifStoreRemote *store)
 	/* get cache */
 	cache_dir = zif_config_get_string (store->priv->config, "cachedir", &error);
 	if (cache_dir == NULL) {
- 		egg_warning ("failed to get cachedir: %s", error->message);
+		egg_warning ("failed to get cachedir: %s", error->message);
 		g_error_free (error);
 		goto out;
 	}
diff --git a/backends/yum/pk-backend-yum.c b/backends/yum/pk-backend-yum.c
index 0e21cb0..309efee 100644
--- a/backends/yum/pk-backend-yum.c
+++ b/backends/yum/pk-backend-yum.c
@@ -381,9 +381,9 @@ backend_emit_package_array (PkBackend *backend, GPtrArray *array)
 		package_id = zif_package_get_package_id (package);
 		summary = zif_package_get_summary (package, NULL);
 		info = installed ? PK_INFO_ENUM_INSTALLED : PK_INFO_ENUM_AVAILABLE;
-		/* hack until we have update details */
-		if (strstr (package_id, "update") != NULL)
-			info = PK_INFO_ENUM_NORMAL;
+//		/* hack until we have update details */
+//		if (strstr (package_id, "update") != NULL)
+//			info = PK_INFO_ENUM_NORMAL;
 		pk_backend_package (backend, info, package_id, zif_string_get_value (summary));
 		zif_string_unref (summary);
 	}
@@ -405,7 +405,7 @@ backend_search_thread_get_array (PkBackend *backend, GPtrArray *store_array, con
 	else if (role == PK_ROLE_ENUM_SEARCH_DETAILS)
 		array = zif_store_array_search_details (store_array, search, priv->cancellable, completion, error);
 	else if (role == PK_ROLE_ENUM_SEARCH_GROUP)
-		array = zif_store_array_search_group (store_array, search, priv->cancellable, completion, error);
+		array = zif_store_array_search_category (store_array, search, priv->cancellable, completion, error);
 	else if (role == PK_ROLE_ENUM_SEARCH_FILE)
 		array = zif_store_array_search_file (store_array, search, priv->cancellable, completion, error);
 	else if (role == PK_ROLE_ENUM_RESOLVE)
@@ -470,6 +470,7 @@ backend_search_thread (PkBackend *backend)
 	ZifCompletion *completion_loop;
 	GError *error = NULL;
 	gchar **search;
+	const gchar *search_tmp;
 	guint i;
 	filters = (PkBitfield) pk_backend_get_uint (backend, "filters");
 	role = pk_backend_get_role (backend);
@@ -524,7 +525,15 @@ backend_search_thread (PkBackend *backend)
 		for (i=0; search[i] != NULL; i++) {
 			/* make loop deeper */
 			completion_loop = zif_completion_get_child (completion_local);
-			result = backend_search_thread_get_array (backend, store_array, search[i], completion_loop, &error);
+
+			/* strip off the prefix '@' */
+			search_tmp = search[i];
+			if (g_str_has_prefix (search_tmp, "@"))
+				search_tmp = search_tmp+1;
+
+			/* get the results */
+			egg_debug ("searching for: %s", search_tmp);
+			result = backend_search_thread_get_array (backend, store_array, search_tmp, completion_loop, &error);
 			if (result == NULL) {
 				pk_backend_error_code (backend, PK_ERROR_ENUM_INTERNAL_ERROR, "failed to search: %s", error->message);
 				g_error_free (error);
@@ -1756,7 +1765,6 @@ backend_repos_search (PkBackend *backend, GPtrArray *stores, PkRoleEnum role, co
 
 	/* nothing to do */
 	if (stores->len == 0) {
-		egg_warning ("nothing to do");
 		if (error != NULL)
 			*error = g_error_new (1, 0, "nothing to do as no stores");
 		goto out;
commit 7a8901dae04527347b0804b1e45a75f0ae927b5b
Author: Richard Hughes <richard at hughsie.com>
Date:   Wed Mar 10 22:59:33 2010 +0000

    yum: use more Zif functionality when searching for packages
    
    17.1x faster than using yum when doing a Resolve() on 10 packages

diff --git a/backends/yum/libzif/zif-completion.c b/backends/yum/libzif/zif-completion.c
index 7e6f52f..8930492 100644
--- a/backends/yum/libzif/zif-completion.c
+++ b/backends/yum/libzif/zif-completion.c
@@ -136,6 +136,8 @@ zif_completion_discrete_to_percent (guint discrete, guint steps)
  * NOTE: this must be above what was previously set, or it will be rejected.
  *
  * Return value: %TRUE if the signal was propagated, %FALSE for failure
+ *
+ * Since: 0.0.1
  **/
 gboolean
 zif_completion_set_percentage (ZifCompletion *completion, guint percentage)
@@ -164,6 +166,8 @@ out:
  * Get the percentage completion.
  *
  * Return value: A percentage value, or G_MAXUINT for error
+ *
+ * Since: 0.0.1
  **/
 guint
 zif_completion_get_percentage (ZifCompletion *completion)
@@ -252,6 +256,8 @@ zif_completion_child_subpercentage_changed_cb (ZifCompletion *child, guint perce
  * Resets the #ZifCompletion object to unset
  *
  * Return value: %TRUE for success, %FALSE for failure
+ *
+ * Since: 0.0.1
  **/
 gboolean
 zif_completion_reset (ZifCompletion *completion)
@@ -290,6 +296,8 @@ zif_completion_reset (ZifCompletion *completion)
  * Yo udo not have to g_object_unref() this value.
  *
  * Return value: a new %ZifCompletion or %NULL for failure
+ *
+ * Since: 0.0.1
  **/
 ZifCompletion *
 zif_completion_get_child (ZifCompletion *completion)
@@ -329,6 +337,8 @@ zif_completion_get_child (ZifCompletion *completion)
  * function will be called in the loop.
  *
  * Return value: %TRUE for success, %FALSE for failure
+ *
+ * Since: 0.0.1
  **/
 gboolean
 zif_completion_set_number_steps (ZifCompletion *completion, guint steps)
@@ -359,6 +369,8 @@ zif_completion_set_number_steps (ZifCompletion *completion, guint steps)
  * Called when the current sub-task has finished.
  *
  * Return value: %TRUE for success, %FALSE for failure
+ *
+ * Since: 0.0.1
  **/
 gboolean
 zif_completion_done (ZifCompletion *completion)
@@ -457,6 +469,8 @@ zif_completion_init (ZifCompletion *completion)
  * zif_completion_new:
  *
  * Return value: A new #ZifCompletion class instance.
+ *
+ * Since: 0.0.1
  **/
 ZifCompletion *
 zif_completion_new (void)
diff --git a/backends/yum/libzif/zif-config.c b/backends/yum/libzif/zif-config.c
index 57a6355..763f011 100644
--- a/backends/yum/libzif/zif-config.c
+++ b/backends/yum/libzif/zif-config.c
@@ -62,6 +62,22 @@ G_DEFINE_TYPE (ZifConfig, zif_config, G_TYPE_OBJECT)
 static gpointer zif_config_object = NULL;
 
 /**
+ * zif_config_error_quark:
+ *
+ * Return value: Our personal error quark.
+ *
+ * Since: 0.0.1
+ **/
+GQuark
+zif_config_error_quark (void)
+{
+	static GQuark quark = 0;
+	if (!quark)
+		quark = g_quark_from_static_string ("zif_config_error");
+	return quark;
+}
+
+/**
  * zif_config_get_string:
  * @config: the #ZifConfig object
  * @key: the key name to retrieve, e.g. "cachedir"
@@ -70,6 +86,8 @@ static gpointer zif_config_object = NULL;
  * Gets a string value from a local setting, falling back to the config file.
  *
  * Return value: the allocated value, or %NULL
+ *
+ * Since: 0.0.1
  **/
 gchar *
 zif_config_get_string (ZifConfig *config, const gchar *key, GError **error)
@@ -84,7 +102,8 @@ zif_config_get_string (ZifConfig *config, const gchar *key, GError **error)
 
 	/* not loaded yet */
 	if (!config->priv->loaded) {
-		g_set_error_literal (error, 1, 0, "config not loaded");
+		g_set_error_literal (error, ZIF_CONFIG_ERROR, ZIF_CONFIG_ERROR_FAILED,
+				     "config not loaded");
 		goto out;
 	}
 
@@ -134,7 +153,8 @@ zif_config_get_string (ZifConfig *config, const gchar *key, GError **error)
 	}
 
 	/* nothing matched */
-	g_set_error (error, 1, 0, "failed to read %s: %s", key, error_local->message);
+	g_set_error (error, ZIF_CONFIG_ERROR, ZIF_CONFIG_ERROR_FAILED,
+		     "failed to read %s: %s", key, error_local->message);
 free_error:
 	g_error_free (error_local);
 out:
@@ -150,6 +170,8 @@ out:
  * Gets a boolean value from a local setting, falling back to the config file.
  *
  * Return value: %TRUE or %FALSE
+ *
+ * Since: 0.0.1
  **/
 gboolean
 zif_config_get_boolean (ZifConfig *config, const gchar *key, GError **error)
@@ -182,6 +204,8 @@ out:
  * Gets a unsigned integer value from a local setting, falling back to the config file.
  *
  * Return value: the data value, or %G_MAXUINT for error
+ *
+ * Since: 0.0.1
  **/
 guint
 zif_config_get_uint (ZifConfig *config, const gchar *key, GError **error)
@@ -201,7 +225,8 @@ zif_config_get_uint (ZifConfig *config, const gchar *key, GError **error)
 	/* convert to int */
 	ret = egg_strtouint (value, &retval);
 	if (!ret) {
-		g_set_error (error, 1, 0, "failed to convert '%s' to unsigned integer", value);
+		g_set_error (error, ZIF_CONFIG_ERROR, ZIF_CONFIG_ERROR_FAILED,
+			     "failed to convert '%s' to unsigned integer", value);
 		goto out;
 	}
 
@@ -275,6 +300,8 @@ out:
  * Gets a time value from a local setting, falling back to the config file.
  *
  * Return value: the data value
+ *
+ * Since: 0.0.1
  **/
 guint
 zif_config_get_time (ZifConfig *config, const gchar *key, GError **error)
@@ -298,7 +325,7 @@ out:
 }
 
 /**
- * zif_config_expand_substitutions:"
+ * zif_config_expand_substitutions:
  * @config: the #ZifConfig object
  * @text: string to scan, e.g. "http://fedora/$releasever/$basearch/moo.rpm"
  * @error: a #GError which is used on failure, or %NULL
@@ -306,6 +333,8 @@ out:
  * Replaces substitutions in text with the actual values of the running system.
  *
  * Return value: A new allocated string or %NULL for error, free with g_free()
+ *
+ * Since: 0.0.1
  **/
 gchar *
 zif_config_expand_substitutions (ZifConfig *config, const gchar *text, GError **error)
@@ -345,6 +374,8 @@ out:
  * Gets the list of architectures that packages are native on for this machine.
  *
  * Return value: A array of strings, do not free, e.g. [ "i386", "i486", "noarch" ]
+ *
+ * Since: 0.0.1
  **/
 gchar **
 zif_config_get_basearch_array (ZifConfig *config)
@@ -362,6 +393,8 @@ zif_config_get_basearch_array (ZifConfig *config)
  * Sets the filename to use as the system wide config file.
  *
  * Return value: %TRUE for success, %FALSE for failure
+ *
+ * Since: 0.0.1
  **/
 gboolean
 zif_config_set_filename (ZifConfig *config, const gchar *filename, GError **error)
@@ -381,14 +414,16 @@ zif_config_set_filename (ZifConfig *config, const gchar *filename, GError **erro
 	/* check file exists */
 	ret = g_file_test (filename, G_FILE_TEST_IS_REGULAR);
 	if (!ret) {
-		g_set_error (error, 1, 0, "config file %s does not exist", filename);
+		g_set_error (error, ZIF_CONFIG_ERROR, ZIF_CONFIG_ERROR_FAILED,
+			     "config file %s does not exist", filename);
 		goto out;
 	}
 
 	/* setup watch */
 	ret = zif_monitor_add_watch (config->priv->monitor, filename, &error_local);
 	if (!ret) {
-		g_set_error (error, 1, 0, "failed to setup watch: %s", error_local->message);
+		g_set_error (error, ZIF_CONFIG_ERROR, ZIF_CONFIG_ERROR_FAILED,
+			     "failed to setup watch: %s", error_local->message);
 		g_error_free (error_local);
 		goto out;
 	}
@@ -396,7 +431,8 @@ zif_config_set_filename (ZifConfig *config, const gchar *filename, GError **erro
 	/* load file */
 	ret = g_key_file_load_from_file (config->priv->keyfile, filename, G_KEY_FILE_NONE, &error_local);
 	if (!ret) {
-		g_set_error (error, 1, 0, "failed to load config file: %s", error_local->message);
+		g_set_error (error, ZIF_CONFIG_ERROR, ZIF_CONFIG_ERROR_FAILED,
+			     "failed to load config file: %s", error_local->message);
 		g_error_free (error_local);
 		goto out;
 	}
@@ -410,7 +446,8 @@ zif_config_set_filename (ZifConfig *config, const gchar *filename, GError **erro
 		/* get distro constants from fedora-release */
 		ret = g_file_get_contents ("/etc/fedora-release", &releasever, NULL, &error_local);
 		if (!ret) {
-			g_set_error (error, 1, 0, "failed to get distro release version: %s", error_local->message);
+			g_set_error (error, ZIF_CONFIG_ERROR, ZIF_CONFIG_ERROR_FAILED,
+				     "failed to get distro release version: %s", error_local->message);
 			g_error_free (error_local);
 			goto out;
 		}
@@ -421,7 +458,8 @@ zif_config_set_filename (ZifConfig *config, const gchar *filename, GError **erro
 		/* set local */
 		ret = zif_config_set_local (config, "releasever", releasever+15, &error_local);
 		if (!ret) {
-			g_set_error (error, 1, 0, "failed to set distro release version: %s", error_local->message);
+			g_set_error (error, ZIF_CONFIG_ERROR, ZIF_CONFIG_ERROR_FAILED,
+				     "failed to set distro release version: %s", error_local->message);
 			g_error_free (error_local);
 			goto out;
 		}
@@ -430,7 +468,8 @@ zif_config_set_filename (ZifConfig *config, const gchar *filename, GError **erro
 	/* calculate the valid basearchs */
 	basearch = zif_config_get_string (config, "basearch", &error_local);
 	if (basearch == NULL) {
-		g_set_error (error, 1, 0, "failed to get basearch: %s", error_local->message);
+		g_set_error (error, ZIF_CONFIG_ERROR, ZIF_CONFIG_ERROR_FAILED,
+			     "failed to get basearch: %s", error_local->message);
 		g_error_free (error_local);
 		ret = FALSE;
 		goto out;
@@ -467,6 +506,8 @@ out:
  * Removes any local settings previously set.
  *
  * Return value: %TRUE for success, %FALSE for failure
+ *
+ * Since: 0.0.1
  **/
 gboolean
 zif_config_reset_default (ZifConfig *config, GError **error)
@@ -486,6 +527,8 @@ zif_config_reset_default (ZifConfig *config, GError **error)
  * Sets a local value which is used in preference to the config value.
  *
  * Return value: %TRUE for success, %FALSE for failure
+ *
+ * Since: 0.0.1
  **/
 gboolean
 zif_config_set_local (ZifConfig *config, const gchar *key, const gchar *value, GError **error)
@@ -499,7 +542,8 @@ zif_config_set_local (ZifConfig *config, const gchar *key, const gchar *value, G
 	/* already exists? */
 	value_tmp = g_hash_table_lookup (config->priv->hash, key);
 	if (value_tmp != NULL) {
-		g_set_error (error, 1, 0, "already set key %s to %s, cannot overwrite with %s", key, value_tmp, value);
+		g_set_error (error, ZIF_CONFIG_ERROR, ZIF_CONFIG_ERROR_FAILED,
+			     "already set key %s to %s, cannot overwrite with %s", key, value_tmp, value);
 		ret = FALSE;
 		goto out;
 	}
@@ -568,6 +612,8 @@ zif_config_init (ZifConfig *config)
  * zif_config_new:
  *
  * Return value: A new #ZifConfig class instance.
+ *
+ * Since: 0.0.1
  **/
 ZifConfig *
 zif_config_new (void)
diff --git a/backends/yum/libzif/zif-config.h b/backends/yum/libzif/zif-config.h
index 14c45cd..8ddd340 100644
--- a/backends/yum/libzif/zif-config.h
+++ b/backends/yum/libzif/zif-config.h
@@ -36,6 +36,7 @@ G_BEGIN_DECLS
 #define ZIF_IS_CONFIG(o)	(G_TYPE_CHECK_INSTANCE_TYPE ((o), ZIF_TYPE_CONFIG))
 #define ZIF_IS_CONFIG_CLASS(k)	(G_TYPE_CHECK_CLASS_TYPE ((k), ZIF_TYPE_CONFIG))
 #define ZIF_CONFIG_GET_CLASS(o)	(G_TYPE_INSTANCE_GET_CLASS ((o), ZIF_TYPE_CONFIG, ZifConfigClass))
+#define ZIF_CONFIG_ERROR	(zif_config_error_quark ())
 
 typedef struct _ZifConfig		ZifConfig;
 typedef struct _ZifConfigPrivate	ZifConfigPrivate;
@@ -52,6 +53,12 @@ struct _ZifConfigClass
 	GObjectClass		 parent_class;
 };
 
+typedef enum {
+	ZIF_CONFIG_ERROR_FAILED,
+	ZIF_CONFIG_ERROR_LAST
+} ZifConfigError;
+
+GQuark		 zif_config_error_quark		(void);
 GType		 zif_config_get_type		(void);
 ZifConfig	*zif_config_new			(void);
 gboolean	 zif_config_set_filename	(ZifConfig	*config,
diff --git a/backends/yum/libzif/zif-depend.c b/backends/yum/libzif/zif-depend.c
index cfde807..ccb467c 100644
--- a/backends/yum/libzif/zif-depend.c
+++ b/backends/yum/libzif/zif-depend.c
@@ -32,6 +32,8 @@
 
 /**
  * zif_depend_flag_to_string:
+ *
+ * Since: 0.0.1
  **/
 const gchar *
 zif_depend_flag_to_string (ZifDependFlag flag)
@@ -49,6 +51,8 @@ zif_depend_flag_to_string (ZifDependFlag flag)
 
 /**
  * zif_depend_new:
+ *
+ * Since: 0.0.1
  **/
 ZifDepend *
 zif_depend_new (const gchar *name, ZifDependFlag flag, const gchar *version)
@@ -64,6 +68,8 @@ zif_depend_new (const gchar *name, ZifDependFlag flag, const gchar *version)
 
 /**
  * zif_depend_new_value:
+ *
+ * Since: 0.0.1
  **/
 ZifDepend *
 zif_depend_new_value (gchar *name, ZifDependFlag flag, gchar *version)
@@ -79,6 +85,8 @@ zif_depend_new_value (gchar *name, ZifDependFlag flag, gchar *version)
 
 /**
  * zif_depend_ref:
+ *
+ * Since: 0.0.1
  **/
 ZifDepend *
 zif_depend_ref (ZifDepend *depend)
@@ -90,6 +98,8 @@ zif_depend_ref (ZifDepend *depend)
 
 /**
  * zif_depend_unref:
+ *
+ * Since: 0.0.1
  **/
 ZifDepend *
 zif_depend_unref (ZifDepend *depend)
@@ -110,6 +120,8 @@ zif_depend_unref (ZifDepend *depend)
 
 /**
  * zif_depend_to_string:
+ *
+ * Since: 0.0.1
  **/
 gchar *
 zif_depend_to_string (const ZifDepend *depend)
diff --git a/backends/yum/libzif/zif-download.c b/backends/yum/libzif/zif-download.c
index aaf089d..daf4d55 100644
--- a/backends/yum/libzif/zif-download.c
+++ b/backends/yum/libzif/zif-download.c
@@ -60,6 +60,22 @@ static gpointer zif_download_object = NULL;
 G_DEFINE_TYPE (ZifDownload, zif_download, G_TYPE_OBJECT)
 
 /**
+ * zif_download_error_quark:
+ *
+ * Return value: Our personal error quark.
+ *
+ * Since: 0.0.1
+ **/
+GQuark
+zif_download_error_quark (void)
+{
+	static GQuark quark = 0;
+	if (!quark)
+		quark = g_quark_from_static_string ("zif_download_error");
+	return quark;
+}
+
+/**
  * zif_download_file_got_chunk_cb:
  **/
 static void
@@ -135,6 +151,8 @@ zif_download_cancelled_cb (GCancellable *cancellable, ZifDownload *download)
  * Downloads a file.
  *
  * Return value: %TRUE for success, %FALSE for failure
+ *
+ * Since: 0.0.1
  **/
 gboolean
 zif_download_file (ZifDownload *download, const gchar *uri, const gchar *filename, GCancellable *cancellable, ZifCompletion *completion, GError **error)
@@ -162,14 +180,16 @@ zif_download_file (ZifDownload *download, const gchar *uri, const gchar *filenam
 
 	base_uri = soup_uri_new (uri);
 	if (base_uri == NULL) {
-		g_set_error (error, 1, 0, "could not parse uri: %s", uri);
+		g_set_error (error, ZIF_DOWNLOAD_ERROR, ZIF_DOWNLOAD_ERROR_FAILED,
+			     "could not parse uri: %s", uri);
 		goto out;
 	}
 
 	/* GET package */
 	msg = soup_message_new_from_uri (SOUP_METHOD_GET, base_uri);
 	if (msg == NULL) {
-		g_set_error_literal (error, 1, 0, "could not setup message");
+		g_set_error_literal (error, ZIF_DOWNLOAD_ERROR, ZIF_DOWNLOAD_ERROR_FAILED,
+				     "could not setup message");
 		goto out;
 	}
 
@@ -188,14 +208,16 @@ zif_download_file (ZifDownload *download, const gchar *uri, const gchar *filenam
 
 	/* find length */
 	if (!SOUP_STATUS_IS_SUCCESSFUL (msg->status_code)) {
-		g_set_error (error, 1, 0, "failed to get valid response for %s: %s", uri, soup_status_get_phrase (msg->status_code));
+		g_set_error (error, ZIF_DOWNLOAD_ERROR, ZIF_DOWNLOAD_ERROR_FAILED,
+			     "failed to get valid response for %s: %s", uri, soup_status_get_phrase (msg->status_code));
 		goto out;
 	}
 
 	/* write file */
 	ret = g_file_set_contents (filename, msg->response_body->data, msg->response_body->length, &error_local);
 	if (!ret) {
-		g_set_error (error, 1, 0, "failed to write file: %s",  error_local->message);
+		g_set_error (error, ZIF_DOWNLOAD_ERROR, ZIF_DOWNLOAD_ERROR_FAILED,
+			     "failed to write file: %s",  error_local->message);
 		g_error_free (error_local);
 		goto out;
 	}
@@ -213,6 +235,8 @@ out:
 
 /**
  * zif_download_set_proxy:
+ *
+ * Since: 0.0.1
  **/
 gboolean
 zif_download_set_proxy (ZifDownload *download, const gchar *http_proxy, GError **error)
@@ -234,7 +258,8 @@ zif_download_set_proxy (ZifDownload *download, const gchar *http_proxy, GError *
 								      SOUP_SESSION_TIMEOUT, connection_timeout,
 								      NULL);
 	if (download->priv->session == NULL) {
-		g_set_error_literal (error, 1, 0, "could not setup session");
+		g_set_error_literal (error, ZIF_DOWNLOAD_ERROR, ZIF_DOWNLOAD_ERROR_FAILED,
+				     "could not setup session");
 		goto out;
 	}
 	ret = TRUE;
@@ -294,6 +319,8 @@ zif_download_init (ZifDownload *download)
  * zif_download_new:
  *
  * Return value: A new download class instance.
+ *
+ * Since: 0.0.1
  **/
 ZifDownload *
 zif_download_new (void)
@@ -314,6 +341,7 @@ zif_download_new (void)
 #include "egg-test.h"
 
 static guint _updates = 0;
+static GMainLoop *_loop = NULL;
 
 static void
 zif_download_progress_changed (ZifDownload *download, guint value, gpointer data)
@@ -326,9 +354,21 @@ zif_download_cancel_cb (GCancellable *cancellable)
 {
 	egg_debug ("sending cancel");
 	g_cancellable_cancel (cancellable);
+	g_main_loop_quit (_loop);
 	return FALSE;
 }
 
+static gpointer
+zif_download_cancel_thread_cb (GCancellable *cancellable)
+{
+	egg_debug ("thread running");
+	g_timeout_add (50, (GSourceFunc) zif_download_cancel_cb, cancellable);
+	_loop = g_main_loop_new (NULL, FALSE);
+	g_main_loop_run (_loop);
+	g_main_loop_unref (_loop);
+	return NULL;
+}
+
 void
 zif_download_test (EggTest *test)
 {
@@ -362,7 +402,8 @@ zif_download_test (EggTest *test)
 
 	/************************************************************/
 	egg_test_title (test, "download file");
-	ret = zif_download_file (download, "http://people.freedesktop.org/~hughsient/temp/Screenshot.png", "../test/downloads", cancellable, completion, &error);
+	ret = zif_download_file (download, "http://people.freedesktop.org/~hughsient/temp/Screenshot.png",
+				 "../test/downloads", cancellable, completion, &error);
 	if (ret)
 		egg_test_success (test, NULL);
 	else
@@ -376,12 +417,13 @@ zif_download_test (EggTest *test)
 		egg_test_failed (test, "got %i updates", _updates);
 
 	/* setup cancel */
-	g_timeout_add (50, (GSourceFunc) zif_download_cancel_cb, cancellable);
+	g_thread_create (zif_download_cancel_thread_cb, cancellable, FALSE, NULL);
 
 	/************************************************************/
 	egg_test_title (test, "download second file (should be cancelled)");
 	zif_completion_reset (completion);
-	ret = zif_download_file (download, "http://people.freedesktop.org/~hughsient/temp/Screenshot.png", "../test/downloads", cancellable, completion, &error);
+	ret = zif_download_file (download, "http://people.freedesktop.org/~hughsient/temp/Screenshot.png",
+				 "../test/downloads", cancellable, completion, &error);
 	if (!ret)
 		egg_test_success (test, NULL);
 	else
diff --git a/backends/yum/libzif/zif-download.h b/backends/yum/libzif/zif-download.h
index 939de98..73b91ed 100644
--- a/backends/yum/libzif/zif-download.h
+++ b/backends/yum/libzif/zif-download.h
@@ -37,6 +37,7 @@ G_BEGIN_DECLS
 #define ZIF_IS_DOWNLOAD(o)		(G_TYPE_CHECK_INSTANCE_TYPE ((o), ZIF_TYPE_DOWNLOAD))
 #define ZIF_IS_DOWNLOAD_CLASS(k)	(G_TYPE_CHECK_CLASS_TYPE ((k), ZIF_TYPE_DOWNLOAD))
 #define ZIF_DOWNLOAD_GET_CLASS(o)	(G_TYPE_INSTANCE_GET_CLASS ((o), ZIF_TYPE_DOWNLOAD, ZifDownloadClass))
+#define ZIF_DOWNLOAD_ERROR		(zif_download_error_quark ())
 
 typedef struct _ZifDownload		ZifDownload;
 typedef struct _ZifDownloadPrivate	ZifDownloadPrivate;
@@ -53,7 +54,13 @@ struct _ZifDownloadClass
 	GObjectClass	parent_class;
 };
 
+typedef enum {
+	ZIF_DOWNLOAD_ERROR_FAILED,
+	ZIF_DOWNLOAD_ERROR_LAST
+} ZifDownloadError;
+
 GType		 zif_download_get_type			(void);
+GQuark		 zif_download_error_quark		(void);
 ZifDownload	*zif_download_new			(void);
 gboolean	 zif_download_set_proxy			(ZifDownload		*download,
 							 const gchar		*http_proxy,
diff --git a/backends/yum/libzif/zif-groups.c b/backends/yum/libzif/zif-groups.c
index ad961f1..d56ba71 100644
--- a/backends/yum/libzif/zif-groups.c
+++ b/backends/yum/libzif/zif-groups.c
@@ -60,6 +60,22 @@ G_DEFINE_TYPE (ZifGroups, zif_groups, G_TYPE_OBJECT)
 static gpointer zif_groups_object = NULL;
 
 /**
+ * zif_groups_error_quark:
+ *
+ * Return value: Our personal error quark.
+ *
+ * Since: 0.0.1
+ **/
+GQuark
+zif_groups_error_quark (void)
+{
+	static GQuark quark = 0;
+	if (!quark)
+		quark = g_quark_from_static_string ("zif_groups_error");
+	return quark;
+}
+
+/**
  * zif_groups_set_mapping_file:
  * @groups: the #ZifGroups object
  * @mapping_file: mapping file from categories to groups
@@ -68,6 +84,8 @@ static gpointer zif_groups_object = NULL;
  * This sets up the file that is used to map categories to group enums.
  *
  * Return value: %TRUE for success, %FALSE for failure
+ *
+ * Since: 0.0.1
  **/
 gboolean
 zif_groups_set_mapping_file (ZifGroups *groups, const gchar *mapping_file, GError **error)
@@ -83,14 +101,16 @@ zif_groups_set_mapping_file (ZifGroups *groups, const gchar *mapping_file, GErro
 	/* check file exists */
 	ret = g_file_test (mapping_file, G_FILE_TEST_IS_REGULAR);
 	if (!ret) {
-		g_set_error (error, 1, 0, "mapping file %s does not exist", mapping_file);
+		g_set_error (error, ZIF_GROUPS_ERROR, ZIF_GROUPS_ERROR_FAILED,
+			     "mapping file %s does not exist", mapping_file);
 		goto out;
 	}
 
 	/* setup watch */
 	ret = zif_monitor_add_watch (groups->priv->monitor, mapping_file, &error_local);
 	if (!ret) {
-		g_set_error (error, 1, 0, "failed to setup watch: %s", error_local->message);
+		g_set_error (error, ZIF_GROUPS_ERROR, ZIF_GROUPS_ERROR_FAILED,
+			     "failed to setup watch: %s", error_local->message);
 		g_error_free (error_local);
 		goto out;
 	}
@@ -108,6 +128,8 @@ out:
  * Loads the mapping file from disk into memory.
  *
  * Return value: %TRUE for success, %FALSE for failure
+ *
+ * Since: 0.0.1
  **/
 gboolean
 zif_groups_load (ZifGroups *groups, GError **error)
@@ -137,7 +159,8 @@ zif_groups_load (ZifGroups *groups, GError **error)
 	/* get data */
 	ret = g_file_get_contents (groups->priv->mapping_file, &data, NULL, &error_local);
 	if (!ret) {
-		g_set_error (error, 1, 0, "failed to get groups data: %s", error_local->message);
+		g_set_error (error, ZIF_GROUPS_ERROR, ZIF_GROUPS_ERROR_FAILED,
+			     "failed to get groups data: %s", error_local->message);
 		g_error_free (error_local);
 		goto out;
 	}
@@ -180,6 +203,8 @@ out:
  * Gets the groups supported by the packaging system.
  *
  * Return value: A #PkBitfield of the groups that are supported
+ *
+ * Since: 0.0.1
  **/
 PkBitfield
 zif_groups_get_groups (ZifGroups *groups, GError **error)
@@ -193,7 +218,8 @@ zif_groups_get_groups (ZifGroups *groups, GError **error)
 	if (!groups->priv->loaded) {
 		ret = zif_groups_load (groups, &error_local);
 		if (!ret) {
-			g_set_error (error, 1, 0, "failed to load config file: %s", error_local->message);
+			g_set_error (error, ZIF_GROUPS_ERROR, ZIF_GROUPS_ERROR_FAILED,
+				     "failed to load config file: %s", error_local->message);
 			g_error_free (error_local);
 			goto out;
 		}
@@ -210,6 +236,8 @@ out:
  * Gets the categories supported by the packaging system.
  *
  * Return value: category list as an array of strings
+ *
+ * Since: 0.0.1
  **/
 GPtrArray *
 zif_groups_get_categories (ZifGroups *groups, GError **error)
@@ -225,7 +253,8 @@ zif_groups_get_categories (ZifGroups *groups, GError **error)
 	if (!groups->priv->loaded) {
 		ret = zif_groups_load (groups, &error_local);
 		if (!ret) {
-			g_set_error (error, 1, 0, "failed to load config file: %s", error_local->message);
+			g_set_error (error, ZIF_GROUPS_ERROR, ZIF_GROUPS_ERROR_FAILED,
+				     "failed to load config file: %s", error_local->message);
 			g_error_free (error_local);
 			goto out;
 		}
@@ -247,6 +276,8 @@ out:
  * Returns the group enumerated type for the category.
  *
  * Return value: the specific #PkGroupEnum or %PK_GROUP_ENUM_UNKNOWN
+ *
+ * Since: 0.0.1
  **/
 PkGroupEnum
 zif_groups_get_group_for_cat (ZifGroups *groups, const gchar *cat, GError **error)
@@ -263,7 +294,8 @@ zif_groups_get_group_for_cat (ZifGroups *groups, const gchar *cat, GError **erro
 	if (!groups->priv->loaded) {
 		ret = zif_groups_load (groups, &error_local);
 		if (!ret) {
-			g_set_error (error, 1, 0, "failed to load config file: %s", error_local->message);
+			g_set_error (error, ZIF_GROUPS_ERROR, ZIF_GROUPS_ERROR_FAILED,
+				     "failed to load config file: %s", error_local->message);
 			g_error_free (error_local);
 			goto out;
 		}
@@ -342,6 +374,8 @@ zif_groups_init (ZifGroups *groups)
  * zif_groups_new:
  *
  * Return value: A new #ZifGroups class instance.
+ *
+ * Since: 0.0.1
  **/
 ZifGroups *
 zif_groups_new (void)
diff --git a/backends/yum/libzif/zif-groups.h b/backends/yum/libzif/zif-groups.h
index 2b7778f..1d94f27 100644
--- a/backends/yum/libzif/zif-groups.h
+++ b/backends/yum/libzif/zif-groups.h
@@ -37,6 +37,7 @@ G_BEGIN_DECLS
 #define ZIF_IS_GROUPS(o)	(G_TYPE_CHECK_INSTANCE_TYPE ((o), ZIF_TYPE_GROUPS))
 #define ZIF_IS_GROUPS_CLASS(k)	(G_TYPE_CHECK_CLASS_TYPE ((k), ZIF_TYPE_GROUPS))
 #define ZIF_GROUPS_GET_CLASS(o)	(G_TYPE_INSTANCE_GET_CLASS ((o), ZIF_TYPE_GROUPS, ZifGroupsClass))
+#define ZIF_GROUPS_ERROR	(zif_groups_error_quark ())
 
 typedef struct _ZifGroups		ZifGroups;
 typedef struct _ZifGroupsPrivate	ZifGroupsPrivate;
@@ -53,7 +54,13 @@ struct _ZifGroupsClass
 	GObjectClass		 parent_class;
 };
 
+typedef enum {
+	ZIF_GROUPS_ERROR_FAILED,
+	ZIF_GROUPS_ERROR_LAST
+} ZifGroupsError;
+
 GType		 zif_groups_get_type		(void);
+GQuark		 zif_groups_error_quark		(void);
 ZifGroups	*zif_groups_new			(void);
 gboolean	 zif_groups_set_mapping_file	(ZifGroups	*groups,
 						 const gchar	*mapping_file,
diff --git a/backends/yum/libzif/zif-lock.c b/backends/yum/libzif/zif-lock.c
index d3b5eeb..1461443 100644
--- a/backends/yum/libzif/zif-lock.c
+++ b/backends/yum/libzif/zif-lock.c
@@ -59,6 +59,22 @@ static gpointer zif_lock_object = NULL;
 G_DEFINE_TYPE (ZifLock, zif_lock, G_TYPE_OBJECT)
 
 /**
+ * zif_lock_error_quark:
+ *
+ * Return value: Our personal error quark.
+ *
+ * Since: 0.0.1
+ **/
+GQuark
+zif_lock_error_quark (void)
+{
+	static GQuark quark = 0;
+	if (!quark)
+		quark = g_quark_from_static_string ("zif_lock_error");
+	return quark;
+}
+
+/**
  * zif_lock_get_pid:
  **/
 static guint
@@ -115,6 +131,8 @@ out:
  * Gets the lock state.
  *
  * Return value: %TRUE if we are already locked
+ *
+ * Since: 0.0.1
  **/
 gboolean
 zif_lock_is_locked (ZifLock *lock, guint *pid)
@@ -161,6 +179,8 @@ out:
  * Tries to lock the packaging system.
  *
  * Return value: %TRUE if we locked, else %FALSE and the error is set
+ *
+ * Since: 0.0.1
  **/
 gboolean
 zif_lock_set_locked (ZifLock *lock, guint *pid, GError **error)
@@ -175,7 +195,8 @@ zif_lock_set_locked (ZifLock *lock, guint *pid, GError **error)
 	/* already locked */
 	ret = zif_lock_is_locked (lock, &pid_tmp);
 	if (ret) {
-		g_set_error (error, 1, 0, "already locked by %i", pid_tmp);
+		g_set_error (error, ZIF_LOCK_ERROR, ZIF_LOCK_ERROR_ALREADY_LOCKED,
+			     "already locked by %i", pid_tmp);
 		if (pid != NULL)
 			*pid = pid_tmp;
 		ret = FALSE;
@@ -184,7 +205,8 @@ zif_lock_set_locked (ZifLock *lock, guint *pid, GError **error)
 
 	/* no lock file set */
 	if (lock->priv->filename == NULL) {
-		g_set_error_literal (error, 1, 0, "lock file not set");
+		g_set_error_literal (error, ZIF_LOCK_ERROR, ZIF_LOCK_ERROR_FAILED,
+				     "lock file not set");
 		ret = FALSE;
 		goto out;
 	}
@@ -194,7 +216,8 @@ zif_lock_set_locked (ZifLock *lock, guint *pid, GError **error)
 	pid_text = g_strdup_printf ("%i", pid_tmp);
 	ret = g_file_set_contents (lock->priv->filename, pid_text, -1, &error_local);
 	if (!ret) {
-		g_set_error (error, 1, 0, "failed to write: %s", error_local->message);
+		g_set_error (error, ZIF_LOCK_ERROR, ZIF_LOCK_ERROR_FAILED,
+			     "failed to write: %s", error_local->message);
 		g_error_free (error_local);
 		goto out;
 	}
@@ -218,6 +241,8 @@ out:
  * Unlocks the packaging system.
  *
  * Return value: %TRUE for success, %FALSE for failure
+ *
+ * Since: 0.0.1
  **/
 gboolean
 zif_lock_set_unlocked (ZifLock *lock, GError **error)
@@ -238,14 +263,16 @@ zif_lock_set_unlocked (ZifLock *lock, GError **error)
 	/* are we already locked */
 	ret = zif_lock_is_locked (lock, &pid);
 	if (!ret) {
-		g_set_error_literal (error, 1, 0, "not locked");
+		g_set_error_literal (error, ZIF_LOCK_ERROR, ZIF_LOCK_ERROR_NOT_LOCKED,
+				     "not locked");
 		goto out;
 	}
 
 	/* is it locked by somethine that isn't us? */
 	pid_tmp = getpid ();
 	if (pid != pid_tmp) {
-		g_set_error (error, 1, 0, "locked by %i, cannot unlock", pid_tmp);
+		g_set_error (error, ZIF_LOCK_ERROR, ZIF_LOCK_ERROR_ALREADY_LOCKED,
+			     "locked by %i, cannot unlock", pid_tmp);
 		ret = FALSE;
 		goto out;
 	}
@@ -255,7 +282,8 @@ skip_checks:
 	/* remove file */
 	retval = g_unlink (lock->priv->filename);
 	if (retval != 0) {
-		g_set_error (error, 1, 0, "cannot remove %s, cannot unlock", lock->priv->filename);
+		g_set_error (error, ZIF_LOCK_ERROR, ZIF_LOCK_ERROR_FAILED,
+			     "cannot remove %s, cannot unlock", lock->priv->filename);
 		ret = FALSE;
 		goto out;
 	}
@@ -321,6 +349,8 @@ zif_lock_init (ZifLock *lock)
  * zif_lock_new:
  *
  * Return value: A new lock class instance.
+ *
+ * Since: 0.0.1
  **/
 ZifLock *
 zif_lock_new (void)
diff --git a/backends/yum/libzif/zif-lock.h b/backends/yum/libzif/zif-lock.h
index 5e84dc9..c9627e9 100644
--- a/backends/yum/libzif/zif-lock.h
+++ b/backends/yum/libzif/zif-lock.h
@@ -37,6 +37,7 @@ G_BEGIN_DECLS
 #define ZIF_IS_LOCK(o)		(G_TYPE_CHECK_INSTANCE_TYPE ((o), ZIF_TYPE_LOCK))
 #define ZIF_IS_LOCK_CLASS(k)	(G_TYPE_CHECK_CLASS_TYPE ((k), ZIF_TYPE_LOCK))
 #define ZIF_LOCK_GET_CLASS(o)	(G_TYPE_INSTANCE_GET_CLASS ((o), ZIF_TYPE_LOCK, ZifLockClass))
+#define ZIF_LOCK_ERROR		(zif_lock_error_quark ())
 
 typedef struct _ZifLock		ZifLock;
 typedef struct _ZifLockPrivate	ZifLockPrivate;
@@ -53,7 +54,15 @@ struct _ZifLockClass
 	GObjectClass	parent_class;
 };
 
+typedef enum {
+	ZIF_LOCK_ERROR_FAILED,
+	ZIF_LOCK_ERROR_ALREADY_LOCKED,
+	ZIF_LOCK_ERROR_NOT_LOCKED,
+	ZIF_LOCK_ERROR_LAST
+} ZifLockError;
+
 GType		 zif_lock_get_type			(void);
+GQuark		 zif_lock_error_quark			(void);
 ZifLock		*zif_lock_new				(void);
 gboolean	 zif_lock_is_locked			(ZifLock		*lock,
 							 guint			*pid);
diff --git a/backends/yum/libzif/zif-monitor.c b/backends/yum/libzif/zif-monitor.c
index 33e510d..b401228 100644
--- a/backends/yum/libzif/zif-monitor.c
+++ b/backends/yum/libzif/zif-monitor.c
@@ -64,6 +64,22 @@ static guint signals [ZIF_MONITOR_SIGNAL_LAST_SIGNAL] = { 0 };
 G_DEFINE_TYPE (ZifMonitor, zif_monitor, G_TYPE_OBJECT)
 
 /**
+ * zif_monitor_error_quark:
+ *
+ * Return value: Our personal error quark.
+ *
+ * Since: 0.0.1
+ **/
+GQuark
+zif_monitor_error_quark (void)
+{
+	static GQuark quark = 0;
+	if (!quark)
+		quark = g_quark_from_static_string ("zif_monitor_error");
+	return quark;
+}
+
+/**
  * zif_monitor_file_monitor_cb:
  **/
 static void
@@ -86,6 +102,8 @@ zif_monitor_file_monitor_cb (GFileMonitor *file_monitor, GFile *file, GFile *oth
  * file is changed.
  *
  * Return value: %TRUE for success, %FALSE for failure
+ *
+ * Since: 0.0.1
  **/
 gboolean
 zif_monitor_add_watch (ZifMonitor *monitor, const gchar *filename, GError **error)
@@ -102,7 +120,8 @@ zif_monitor_add_watch (ZifMonitor *monitor, const gchar *filename, GError **erro
 	file = g_file_new_for_path (filename);
 	file_monitor = g_file_monitor (file, G_FILE_MONITOR_NONE, NULL, &error_local);
 	if (file_monitor == NULL) {
-		g_set_error (error, 1, 0, "failed to add monitor: %s", error_local->message);
+		g_set_error (error, ZIF_MONITOR_ERROR, ZIF_MONITOR_ERROR_FAILED,
+			     "failed to add monitor: %s", error_local->message);
 		g_error_free (error_local);
 		g_object_unref (file_monitor);
 		ret = FALSE;
@@ -167,6 +186,8 @@ zif_monitor_init (ZifMonitor *monitor)
  * zif_monitor_new:
  *
  * Return value: A new #ZifMonitor class instance.
+ *
+ * Since: 0.0.1
  **/
 ZifMonitor *
 zif_monitor_new (void)
diff --git a/backends/yum/libzif/zif-monitor.h b/backends/yum/libzif/zif-monitor.h
index 2724853..0e4cfac 100644
--- a/backends/yum/libzif/zif-monitor.h
+++ b/backends/yum/libzif/zif-monitor.h
@@ -36,6 +36,7 @@ G_BEGIN_DECLS
 #define ZIF_IS_MONITOR(o)		(G_TYPE_CHECK_INSTANCE_TYPE ((o), ZIF_TYPE_MONITOR))
 #define ZIF_IS_MONITOR_CLASS(k)		(G_TYPE_CHECK_CLASS_TYPE ((k), ZIF_TYPE_MONITOR))
 #define ZIF_MONITOR_GET_CLASS(o)	(G_TYPE_INSTANCE_GET_CLASS ((o), ZIF_TYPE_MONITOR, ZifMonitorClass))
+#define ZIF_MONITOR_ERROR		(zif_monitor_error_quark ())
 
 typedef struct _ZifMonitor		ZifMonitor;
 typedef struct _ZifMonitorPrivate	ZifMonitorPrivate;
@@ -52,7 +53,13 @@ struct _ZifMonitorClass
 	GObjectClass		 parent_class;
 };
 
+typedef enum {
+	ZIF_MONITOR_ERROR_FAILED,
+	ZIF_MONITOR_ERROR_LAST
+} ZifMonitorError;
+
 GType		 zif_monitor_get_type		(void);
+GQuark		 zif_monitor_error_quark	(void);
 ZifMonitor	*zif_monitor_new		(void);
 gboolean	 zif_monitor_add_watch		(ZifMonitor	*monitor,
 						 const gchar	*filename,
diff --git a/backends/yum/libzif/zif-package-local.c b/backends/yum/libzif/zif-package-local.c
index e04f8d9..cf940a5 100644
--- a/backends/yum/libzif/zif-package-local.c
+++ b/backends/yum/libzif/zif-package-local.c
@@ -277,7 +277,8 @@ zif_package_local_ensure_data (ZifPackage *pkg, ZifPackageEnsureType type, GErro
 
 	/* eigh? */
 	if (header == NULL) {
-		g_set_error (error, 1, 0, "no header for %s", zif_package_get_id (pkg));
+		g_set_error (error, ZIF_PACKAGE_ERROR, ZIF_PACKAGE_ERROR_FAILED,
+			     "no header for %s", zif_package_get_id (pkg));
 		ret = FALSE;
 		goto out;
 	}
@@ -292,10 +293,18 @@ zif_package_local_ensure_data (ZifPackage *pkg, ZifPackageEnsureType type, GErro
 			/* get the mapping */
 			dirnames = zif_get_header_string_array (header, RPMTAG_DIRNAMES);
 			fileindex = zif_get_header_uint32_index (header, RPMTAG_DIRINDEXES, basenames->len);
-			if (basenames->len != fileindex->len)
-				egg_error ("internal error, basenames length is not the same as index length, possibly corrupt db?");
-			if (fileindex->len > fileindex->len)
-				egg_error ("internal error, fileindex length is bigger than index length, possibly corrupt db?");
+			if (basenames->len != fileindex->len) {
+				ret = FALSE;
+ 				g_set_error_literal (error, ZIF_PACKAGE_ERROR, ZIF_PACKAGE_ERROR_FAILED,
+						     "internal error, basenames length is not the same as index length, possibly corrupt db?");
+				goto out;
+ 			}
+			if (fileindex->len > fileindex->len) {
+				ret = FALSE;
+ 				g_set_error_literal (error, ZIF_PACKAGE_ERROR, ZIF_PACKAGE_ERROR_FAILED,
+						     "internal error, fileindex length is bigger than index length, possibly corrupt db?");
+				goto out;
+			}
 
 			files = g_ptr_array_new_with_free_func (g_free);
 			for (i=0; i<basenames->len-2 /* why -1? I'm not sure */; i++) {
@@ -460,6 +469,8 @@ out:
  * Sets the local package from an RPM header object.
  *
  * Return value: %TRUE for success, %FALSE for failure
+ *
+ * Since: 0.0.1
  **/
 gboolean
 zif_package_local_set_from_header (ZifPackageLocal *pkg, Header header, GError **error)
@@ -510,6 +521,8 @@ zif_package_local_rpmrc_to_string (rpmRC rc)
  * Sets a local package object from a local file.
  *
  * Return value: %TRUE for success, %FALSE for failure
+ *
+ * Since: 0.0.1
  **/
 gboolean
 zif_package_local_set_from_filename (ZifPackageLocal *pkg, const gchar *filename, GError **error)
@@ -524,11 +537,13 @@ zif_package_local_set_from_filename (ZifPackageLocal *pkg, const gchar *filename
 	/* open the file for reading */
 	fd = Fopen(filename, "r.fdio"); 
 	if (fd == NULL) {
-		g_set_error (error, 1, 0, "failed to open %s", filename);
+		g_set_error (error, ZIF_PACKAGE_ERROR, ZIF_PACKAGE_ERROR_FAILED,
+			     "failed to open %s", filename);
 		goto out;
 	}
 	if (Ferror(fd)) {
-		g_set_error (error, 1, 0, "failed to open %s: %s", filename, Fstrerror(fd));
+		g_set_error (error, ZIF_PACKAGE_ERROR, ZIF_PACKAGE_ERROR_FAILED,
+			     "failed to open %s: %s", filename, Fstrerror(fd));
 		goto out;
 	}
 
@@ -541,7 +556,8 @@ zif_package_local_set_from_filename (ZifPackageLocal *pkg, const gchar *filename
 	/* read in the file */
 	rc = rpmReadPackageFile (ts, fd, filename, &hdr);
 	if (rc != RPMRC_OK) {
-		g_set_error (error, 1, 0, "failed to read %s: %s", filename, zif_package_local_rpmrc_to_string (rc));
+		g_set_error (error, ZIF_PACKAGE_ERROR, ZIF_PACKAGE_ERROR_FAILED,
+			     "failed to read %s: %s", filename, zif_package_local_rpmrc_to_string (rc));
 		goto out;
 	}
 
@@ -551,7 +567,8 @@ zif_package_local_set_from_filename (ZifPackageLocal *pkg, const gchar *filename
 	/* set from header */
 	ret = zif_package_local_set_from_header (pkg, hdr, &error_local);
 	if (!ret) {
-		g_set_error (error, 1, 0, "failed to set from header: %s", error_local->message);
+		g_set_error (error, ZIF_PACKAGE_ERROR, ZIF_PACKAGE_ERROR_FAILED,
+			     "failed to set from header: %s", error_local->message);
 		g_error_free (error_local);
 		goto out;
 	}
@@ -559,7 +576,8 @@ zif_package_local_set_from_filename (ZifPackageLocal *pkg, const gchar *filename
 	/* close the database used by the transaction */
 	rc = rpmtsCloseDB (ts);
 	if (rc != RPMRC_OK) {
-		g_set_error (error, 1, 0, "failed to close: %s", zif_package_local_rpmrc_to_string (rc));
+		g_set_error (error, ZIF_PACKAGE_ERROR, ZIF_PACKAGE_ERROR_FAILED,
+			     "failed to close: %s", zif_package_local_rpmrc_to_string (rc));
 		ret = FALSE;
 		goto out;
 	}
@@ -621,6 +639,8 @@ zif_package_local_init (ZifPackageLocal *pkg)
  * zif_package_local_new:
  *
  * Return value: A new #ZifPackageLocal class instance.
+ *
+ * Since: 0.0.1
  **/
 ZifPackageLocal *
 zif_package_local_new (void)
diff --git a/backends/yum/libzif/zif-package-remote.c b/backends/yum/libzif/zif-package-remote.c
index ae6fa67..915736e 100644
--- a/backends/yum/libzif/zif-package-remote.c
+++ b/backends/yum/libzif/zif-package-remote.c
@@ -68,6 +68,8 @@ G_DEFINE_TYPE (ZifPackageRemote, zif_package_remote, ZIF_TYPE_PACKAGE)
  * Sets details on a remote package from repo data derived from the metadata xml.
  *
  * Return value: %TRUE for success, %FALSE for failure
+ *
+ * Since: 0.0.1
  **/
 gboolean
 zif_package_remote_set_from_repo (ZifPackageRemote *pkg, guint length, gchar **type, gchar **data, const gchar *repo_id, GError **error)
@@ -180,6 +182,8 @@ zif_package_remote_init (ZifPackageRemote *pkg)
  * zif_package_remote_new:
  *
  * Return value: A new #ZifPackageRemote class instance.
+ *
+ * Since: 0.0.1
  **/
 ZifPackageRemote *
 zif_package_remote_new (void)
diff --git a/backends/yum/libzif/zif-package.c b/backends/yum/libzif/zif-package.c
index 4336e62..9b9edab 100644
--- a/backends/yum/libzif/zif-package.c
+++ b/backends/yum/libzif/zif-package.c
@@ -71,6 +71,22 @@ struct _ZifPackagePrivate
 G_DEFINE_TYPE (ZifPackage, zif_package, G_TYPE_OBJECT)
 
 /**
+ * zif_package_error_quark:
+ *
+ * Return value: Our personal error quark.
+ *
+ * Since: 0.0.1
+ **/
+GQuark
+zif_package_error_quark (void)
+{
+	static GQuark quark = 0;
+	if (!quark)
+		quark = g_quark_from_static_string ("zif_package_error");
+	return quark;
+}
+
+/**
  * zif_package_compare:
  * @a: the first package to compare
  * @b: the second package to compare
@@ -78,6 +94,8 @@ G_DEFINE_TYPE (ZifPackage, zif_package, G_TYPE_OBJECT)
  * Compares one package versions against each other.
  *
  * Return value: 1 for a>b, 0 for a==b, -1 for b>a
+ *
+ * Since: 0.0.1
  **/
 gint
 zif_package_compare (ZifPackage *a, ZifPackage *b)
@@ -119,6 +137,8 @@ out:
  * Returns the newest package from a list.
  *
  * Return value: a single %ZifPackage, or %NULL in the case of an error
+ *
+ * Since: 0.0.1
  **/
 ZifPackage *
 zif_package_array_get_newest (GPtrArray *array, GError **error)
@@ -130,7 +150,8 @@ zif_package_array_get_newest (GPtrArray *array, GError **error)
 
 	/* no results */
 	if (array->len == 0) {
-		g_set_error_literal (error, 1, 0, "nothing in array");
+		g_set_error_literal (error, ZIF_PACKAGE_ERROR, ZIF_PACKAGE_ERROR_FAILED,
+				     "nothing in array");
 		goto out;
 	}
 
@@ -162,6 +183,8 @@ out:
  * Downloads a package.
  *
  * Return value: %TRUE for success, %FALSE for failure
+ *
+ * Since: 0.0.1
  **/
 gboolean
 zif_package_download (ZifPackage *package, const gchar *directory, GCancellable *cancellable, ZifCompletion *completion, GError **error)
@@ -177,7 +200,8 @@ zif_package_download (ZifPackage *package, const gchar *directory, GCancellable
 
 	/* check we are not installed */
 	if (package->priv->installed) {
-		g_set_error_literal (error, 1, 0, "cannot download installed packages");
+		g_set_error_literal (error, ZIF_PACKAGE_ERROR, ZIF_PACKAGE_ERROR_FAILED,
+				     "cannot download installed packages");
 		goto out;
 	}
 
@@ -188,7 +212,8 @@ zif_package_download (ZifPackage *package, const gchar *directory, GCancellable
 	completion_local = zif_completion_get_child (completion);
 	repo = zif_repos_get_store (package->priv->repos, package->priv->package_id_split[PK_PACKAGE_ID_DATA], cancellable, completion_local, &error_local);
 	if (repo == NULL) {
-		g_set_error (error, 1, 0, "cannot find remote repo: %s", error_local->message);
+		g_set_error (error, ZIF_PACKAGE_ERROR, ZIF_PACKAGE_ERROR_FAILED,
+			     "cannot find remote repo: %s", error_local->message);
 		g_error_free (error_local);
 		goto out;
 	}
@@ -202,7 +227,8 @@ zif_package_download (ZifPackage *package, const gchar *directory, GCancellable
 	/* download from the repo */
 	ret = zif_store_remote_download (repo, zif_string_get_value (package->priv->location_href), directory, cancellable, completion_local, &error_local);
 	if (!ret) {
-		g_set_error (error, 1, 0, "cannot download from repo: %s", error_local->message);
+		g_set_error (error, ZIF_PACKAGE_ERROR, ZIF_PACKAGE_ERROR_FAILED,
+			     "cannot download from repo: %s", error_local->message);
 		g_error_free (error_local);
 		goto out;
 	}
@@ -220,6 +246,8 @@ out:
  * @package: the #ZifPackage object
  *
  * Prints details about a package to %STDOUT.
+ *
+ * Since: 0.0.1
  **/
 void
 zif_package_print (ZifPackage *package)
@@ -277,6 +305,8 @@ zif_package_print (ZifPackage *package)
  * Finds out if a package is a development package.
  *
  * Return value: %TRUE or %FALSE
+ *
+ * Since: 0.0.1
  **/
 gboolean
 zif_package_is_devel (ZifPackage *package)
@@ -302,6 +332,8 @@ zif_package_is_devel (ZifPackage *package)
  * Finds out if a package is a GUI package.
  *
  * Return value: %TRUE or %FALSE
+ *
+ * Since: 0.0.1
  **/
 gboolean
 zif_package_is_gui (ZifPackage *package)
@@ -336,6 +368,8 @@ out:
  * Finds out if a package is installed.
  *
  * Return value: %TRUE or %FALSE
+ *
+ * Since: 0.0.1
  **/
 gboolean
 zif_package_is_installed (ZifPackage *package)
@@ -352,6 +386,8 @@ zif_package_is_installed (ZifPackage *package)
  * Finds out if a package is the native architecture for the system.
  *
  * Return value: %TRUE or %FALSE
+ *
+ * Since: 0.0.1
  **/
 gboolean
 zif_package_is_native (ZifPackage *package)
@@ -404,6 +440,8 @@ zif_package_is_native (ZifPackage *package)
  * is empty, the package is considered non-free.
  *
  * Return value: %TRUE or %FALSE
+ *
+ * Since: 0.0.1
  **/
 gboolean
 zif_package_is_free (ZifPackage *package)
@@ -465,6 +503,8 @@ zif_package_is_free (ZifPackage *package)
  * Gets the id uniquely identifying the package in all repos.
  *
  * Return value: the PackageId representing the package.
+ *
+ * Since: 0.0.1
  **/
 const gchar *
 zif_package_get_id (ZifPackage *package)
@@ -481,6 +521,8 @@ zif_package_get_id (ZifPackage *package)
  * Gets the id (as text) uniquely identifying the package in all repos.
  *
  * Return value: The %package_id representing the package.
+ *
+ * Since: 0.0.1
  **/
 const gchar *
 zif_package_get_package_id (ZifPackage *package)
@@ -539,7 +581,8 @@ zif_package_ensure_data (ZifPackage *package, ZifPackageEnsureType type, GError
 
 	/* no support */
 	if (klass->ensure_data == NULL) {
-		g_set_error (error, 1, 0, "cannot ensure data for %s data", zif_package_ensure_type_to_string (type));
+		g_set_error (error, ZIF_PACKAGE_ERROR, ZIF_PACKAGE_ERROR_FAILED,
+			     "cannot ensure data for %s data", zif_package_ensure_type_to_string (type));
 		goto out;
 	}
 
@@ -556,6 +599,8 @@ out:
  * Gets the package summary.
  *
  * Return value: the reference counted #ZifString or %NULL, use zif_string_unref() when done
+ *
+ * Since: 0.0.1
  **/
 ZifString *
 zif_package_get_summary (ZifPackage *package, GError **error)
@@ -584,6 +629,8 @@ zif_package_get_summary (ZifPackage *package, GError **error)
  * Gets the package description.
  *
  * Return value: the reference counted #ZifString or %NULL, use zif_string_unref() when done
+ *
+ * Since: 0.0.1
  **/
 ZifString *
 zif_package_get_description (ZifPackage *package, GError **error)
@@ -612,6 +659,8 @@ zif_package_get_description (ZifPackage *package, GError **error)
  * Gets the package licence.
  *
  * Return value: the reference counted #ZifString or %NULL, use zif_string_unref() when done
+ *
+ * Since: 0.0.1
  **/
 ZifString *
 zif_package_get_license (ZifPackage *package, GError **error)
@@ -640,6 +689,8 @@ zif_package_get_license (ZifPackage *package, GError **error)
  * Gets the homepage URL for the package.
  *
  * Return value: the reference counted #ZifString or %NULL, use zif_string_unref() when done
+ *
+ * Since: 0.0.1
  **/
 ZifString *
 zif_package_get_url (ZifPackage *package, GError **error)
@@ -668,6 +719,8 @@ zif_package_get_url (ZifPackage *package, GError **error)
  * Gets the remote filename for the package, e.g. Packages/net-snmp-5.4.2-3.fc10.i386.rpm
  *
  * Return value: the reference counted #ZifString or %NULL, use zif_string_unref() when done
+ *
+ * Since: 0.0.1
  **/
 ZifString *
 zif_package_get_filename (ZifPackage *package, GError **error)
@@ -677,7 +730,8 @@ zif_package_get_filename (ZifPackage *package, GError **error)
 
 	/* not exists */
 	if (package->priv->location_href == NULL) {
-		g_set_error (error, 1, 0, "no data for %s", package->priv->package_id_split[PK_PACKAGE_ID_NAME]);
+		g_set_error (error, ZIF_PACKAGE_ERROR, ZIF_PACKAGE_ERROR_FAILED,
+			     "no data for %s", package->priv->package_id_split[PK_PACKAGE_ID_NAME]);
 		return NULL;
 	}
 
@@ -693,6 +747,8 @@ zif_package_get_filename (ZifPackage *package, GError **error)
  * Gets the category the packag is in.
  *
  * Return value: the reference counted #ZifString or %NULL, use zif_string_unref() when done
+ *
+ * Since: 0.0.1
  **/
 ZifString *
 zif_package_get_category (ZifPackage *package, GError **error)
@@ -721,6 +777,8 @@ zif_package_get_category (ZifPackage *package, GError **error)
  * Gets the package group.
  *
  * Return value: %TRUE for success, %FALSE for failure
+ *
+ * Since: 0.0.1
  **/
 PkGroupEnum
 zif_package_get_group (ZifPackage *package, GError **error)
@@ -749,6 +807,8 @@ zif_package_get_group (ZifPackage *package, GError **error)
  * remote packages.
  *
  * Return value: %TRUE for success, %FALSE for failure
+ *
+ * Since: 0.0.1
  **/
 guint64
 zif_package_get_size (ZifPackage *package, GError **error)
@@ -774,6 +834,8 @@ zif_package_get_size (ZifPackage *package, GError **error)
  * Gets the file list for the package.
  *
  * Return value: the reference counted #GPtrArray, use g_ptr_array_unref() when done
+ *
+ * Since: 0.0.1
  **/
 GPtrArray *
 zif_package_get_files (ZifPackage *package, GError **error)
@@ -802,6 +864,8 @@ zif_package_get_files (ZifPackage *package, GError **error)
  * Gets all the package requires.
  *
  * Return value: the reference counted #GPtrArray, use g_ptr_array_unref() when done
+ *
+ * Since: 0.0.1
  **/
 GPtrArray *
 zif_package_get_requires (ZifPackage *package, GError **error)
@@ -830,6 +894,8 @@ zif_package_get_requires (ZifPackage *package, GError **error)
  * Get all the package provides.
  *
  * Return value: the reference counted #GPtrArray, use g_ptr_array_unref() when done
+ *
+ * Since: 0.0.1
  **/
 GPtrArray *
 zif_package_get_provides (ZifPackage *package, GError **error)
@@ -858,6 +924,8 @@ zif_package_get_provides (ZifPackage *package, GError **error)
  * Sets the package installed status.
  *
  * Return value: %TRUE for success, %FALSE for failure
+ *
+ * Since: 0.0.1
  **/
 gboolean
 zif_package_set_installed (ZifPackage *package, gboolean installed)
@@ -875,6 +943,8 @@ zif_package_set_installed (ZifPackage *package, gboolean installed)
  * Sets the unique id for the package.
  *
  * Return value: %TRUE for success, %FALSE for failure
+ *
+ * Since: 0.0.1
  **/
 gboolean
 zif_package_set_id (ZifPackage *package, const gchar *package_id)
@@ -896,6 +966,8 @@ zif_package_set_id (ZifPackage *package, const gchar *package_id)
  * Sets the package summary.
  *
  * Return value: %TRUE for success, %FALSE for failure
+ *
+ * Since: 0.0.1
  **/
 gboolean
 zif_package_set_summary (ZifPackage *package, ZifString *summary)
@@ -916,6 +988,8 @@ zif_package_set_summary (ZifPackage *package, ZifString *summary)
  * Sets the package description.
  *
  * Return value: %TRUE for success, %FALSE for failure
+ *
+ * Since: 0.0.1
  **/
 gboolean
 zif_package_set_description (ZifPackage *package, ZifString *description)
@@ -936,6 +1010,8 @@ zif_package_set_description (ZifPackage *package, ZifString *description)
  * Sets the package license.
  *
  * Return value: %TRUE for success, %FALSE for failure
+ *
+ * Since: 0.0.1
  **/
 gboolean
 zif_package_set_license (ZifPackage *package, ZifString *license)
@@ -956,6 +1032,8 @@ zif_package_set_license (ZifPackage *package, ZifString *license)
  * Sets the project homepage URL.
  *
  * Return value: %TRUE for success, %FALSE for failure
+ *
+ * Since: 0.0.1
  **/
 gboolean
 zif_package_set_url (ZifPackage *package, ZifString *url)
@@ -976,6 +1054,8 @@ zif_package_set_url (ZifPackage *package, ZifString *url)
  * Sets the remote download location.
  *
  * Return value: %TRUE for success, %FALSE for failure
+ *
+ * Since: 0.0.1
  **/
 gboolean
 zif_package_set_location_href (ZifPackage *package, ZifString *location_href)
@@ -996,6 +1076,8 @@ zif_package_set_location_href (ZifPackage *package, ZifString *location_href)
  * Sets the package category.
  *
  * Return value: %TRUE for success, %FALSE for failure
+ *
+ * Since: 0.0.1
  **/
 gboolean
 zif_package_set_category (ZifPackage *package, ZifString *category)
@@ -1016,6 +1098,8 @@ zif_package_set_category (ZifPackage *package, ZifString *category)
  * Sets the package group.
  *
  * Return value: %TRUE for success, %FALSE for failure
+ *
+ * Since: 0.0.1
  **/
 gboolean
 zif_package_set_group (ZifPackage *package, PkGroupEnum group)
@@ -1036,6 +1120,8 @@ zif_package_set_group (ZifPackage *package, PkGroupEnum group)
  * Sets the package size in bytes.
  *
  * Return value: %TRUE for success, %FALSE for failure
+ *
+ * Since: 0.0.1
  **/
 gboolean
 zif_package_set_size (ZifPackage *package, guint64 size)
@@ -1056,6 +1142,8 @@ zif_package_set_size (ZifPackage *package, guint64 size)
  * Sets the package file list.
  *
  * Return value: %TRUE for success, %FALSE for failure
+ *
+ * Since: 0.0.1
  **/
 gboolean
 zif_package_set_files (ZifPackage *package, GPtrArray *files)
@@ -1076,6 +1164,8 @@ zif_package_set_files (ZifPackage *package, GPtrArray *files)
  * Sets the package requires.
  *
  * Return value: %TRUE for success, %FALSE for failure
+ *
+ * Since: 0.0.1
  **/
 gboolean
 zif_package_set_requires (ZifPackage *package, GPtrArray *requires)
@@ -1096,6 +1186,8 @@ zif_package_set_requires (ZifPackage *package, GPtrArray *requires)
  * Sets the package provides
  *
  * Return value: %TRUE for success, %FALSE for failure
+ *
+ * Since: 0.0.1
  **/
 gboolean
 zif_package_set_provides (ZifPackage *package, GPtrArray *provides)
@@ -1188,6 +1280,8 @@ zif_package_init (ZifPackage *package)
  * zif_package_new:
  *
  * Return value: A new #ZifPackage class instance.
+ *
+ * Since: 0.0.1
  **/
 ZifPackage *
 zif_package_new (void)
diff --git a/backends/yum/libzif/zif-package.h b/backends/yum/libzif/zif-package.h
index bbb4fea..b626e28 100644
--- a/backends/yum/libzif/zif-package.h
+++ b/backends/yum/libzif/zif-package.h
@@ -41,6 +41,7 @@ G_BEGIN_DECLS
 #define ZIF_IS_PACKAGE(o)		(G_TYPE_CHECK_INSTANCE_TYPE ((o), ZIF_TYPE_PACKAGE))
 #define ZIF_IS_PACKAGE_CLASS(k)		(G_TYPE_CHECK_CLASS_TYPE ((k), ZIF_TYPE_PACKAGE))
 #define ZIF_PACKAGE_GET_CLASS(o)	(G_TYPE_INSTANCE_GET_CLASS ((o), ZIF_TYPE_PACKAGE, ZifPackageClass))
+#define ZIF_PACKAGE_ERROR		(zif_package_error_quark ())
 
 typedef struct _ZifPackage		ZifPackage;
 typedef struct _ZifPackagePrivate	ZifPackagePrivate;
@@ -78,7 +79,13 @@ struct _ZifPackageClass
 							 GError		**error);
 };
 
+typedef enum {
+	ZIF_PACKAGE_ERROR_FAILED,
+	ZIF_PACKAGE_ERROR_LAST
+} ZifPackageError;
+
 GType			 zif_package_get_type		(void);
+GQuark			 zif_package_error_quark	(void);
 ZifPackage		*zif_package_new		(void);
 
 /* public getters */
diff --git a/backends/yum/libzif/zif-repo-md-comps.c b/backends/yum/libzif/zif-repo-md-comps.c
index b49cf57..7fc94f0 100644
--- a/backends/yum/libzif/zif-repo-md-comps.c
+++ b/backends/yum/libzif/zif-repo-md-comps.c
@@ -450,7 +450,8 @@ zif_repo_md_comps_load (ZifRepoMd *md, GCancellable *cancellable, ZifCompletion
 	/* get filename */
 	filename = zif_repo_md_get_filename_uncompressed (md);
 	if (filename == NULL) {
-		g_set_error_literal (error, 1, 0, "failed to get filename for comps");
+		g_set_error_literal (error, ZIF_REPO_MD_ERROR, ZIF_REPO_MD_ERROR_FAILED,
+				     "failed to get filename for comps");
 		goto out;
 	}
 
@@ -519,6 +520,8 @@ out:
  * Gets the available list of categories.
  *
  * Return value: %PkCategory array of categories, with parent_id set to %NULL
+ *
+ * Since: 0.0.1
  **/
 GPtrArray *
 zif_repo_md_comps_get_categories (ZifRepoMdComps *md, GCancellable *cancellable,
@@ -538,7 +541,8 @@ zif_repo_md_comps_get_categories (ZifRepoMdComps *md, GCancellable *cancellable,
 	if (!md->priv->loaded) {
 		ret = zif_repo_md_load (ZIF_REPO_MD (md), cancellable, completion, &error_local);
 		if (!ret) {
-			g_set_error (error, 1, 0, "failed to get load comps: %s", error_local->message);
+			g_set_error (error, ZIF_REPO_MD_ERROR, ZIF_REPO_MD_ERROR_FAILED_TO_LOAD,
+				     "failed to get load comps: %s", error_local->message);
 			g_error_free (error_local);
 			goto out;
 		}
@@ -597,6 +601,8 @@ zif_repo_md_comps_get_category_for_group (ZifRepoMdComps *md, const gchar *group
  * Gets the list of groups for a specific category.
  *
  * Return value: %PkCategory array of groups
+ *
+ * Since: 0.0.1
  **/
 GPtrArray *
 zif_repo_md_comps_get_groups_for_category (ZifRepoMdComps *md, const gchar *category_id,
@@ -619,7 +625,8 @@ zif_repo_md_comps_get_groups_for_category (ZifRepoMdComps *md, const gchar *cate
 	if (!md->priv->loaded) {
 		ret = zif_repo_md_load (ZIF_REPO_MD (md), cancellable, completion, &error_local);
 		if (!ret) {
-			g_set_error (error, 1, 0, "failed to get load comps: %s", error_local->message);
+			g_set_error (error, ZIF_REPO_MD_ERROR, ZIF_REPO_MD_ERROR_FAILED_TO_LOAD,
+				     "failed to get load comps: %s", error_local->message);
 			g_error_free (error_local);
 			goto out;
 		}
@@ -651,7 +658,8 @@ zif_repo_md_comps_get_groups_for_category (ZifRepoMdComps *md, const gchar *cate
 
 	/* nothing found */
 	if (array == NULL) {
-		g_set_error (error, 1, 0, "could not find category: %s", category_id);
+		g_set_error (error, ZIF_REPO_MD_ERROR, ZIF_REPO_MD_ERROR_FAILED,
+			     "could not find category: %s", category_id);
 	}
 out:
 	return array;
@@ -668,6 +676,8 @@ out:
  * Gets the package names for a group.
  *
  * Return value: gchar pointer array of package names (not %ZifPackage's)
+ *
+ * Since: 0.0.1
  **/
 GPtrArray *
 zif_repo_md_comps_get_packages_for_group (ZifRepoMdComps *md, const gchar *group_id,
@@ -689,7 +699,8 @@ zif_repo_md_comps_get_packages_for_group (ZifRepoMdComps *md, const gchar *group
 	if (!md->priv->loaded) {
 		ret = zif_repo_md_load (ZIF_REPO_MD (md), cancellable, completion, &error_local);
 		if (!ret) {
-			g_set_error (error, 1, 0, "failed to get load comps: %s", error_local->message);
+			g_set_error (error, ZIF_REPO_MD_ERROR, ZIF_REPO_MD_ERROR_FAILED_TO_LOAD,
+				     "failed to get load comps: %s", error_local->message);
 			g_error_free (error_local);
 			goto out;
 		}
@@ -713,7 +724,8 @@ zif_repo_md_comps_get_packages_for_group (ZifRepoMdComps *md, const gchar *group
 
 	/* nothing found */
 	if (array == NULL) {
-		g_set_error (error, 1, 0, "could not find group: %s", group_id);
+		g_set_error (error, ZIF_REPO_MD_ERROR, ZIF_REPO_MD_ERROR_FAILED,
+			     "could not find group: %s", group_id);
 	}
 out:
 	return array;
@@ -775,6 +787,8 @@ zif_repo_md_comps_init (ZifRepoMdComps *md)
  * zif_repo_md_comps_new:
  *
  * Return value: A new #ZifRepoMdComps class instance.
+ *
+ * Since: 0.0.1
  **/
 ZifRepoMdComps *
 zif_repo_md_comps_new (void)
diff --git a/backends/yum/libzif/zif-repo-md-filelists.c b/backends/yum/libzif/zif-repo-md-filelists.c
index 74c7f99..9b06362 100644
--- a/backends/yum/libzif/zif-repo-md-filelists.c
+++ b/backends/yum/libzif/zif-repo-md-filelists.c
@@ -92,7 +92,8 @@ zif_repo_md_filelists_load (ZifRepoMd *md, GCancellable *cancellable, ZifComplet
 	/* get filename */
 	filename = zif_repo_md_get_filename_uncompressed (md);
 	if (filename == NULL) {
-		g_set_error_literal (error, 1, 0, "failed to get filename for filelists");
+		g_set_error_literal (error, ZIF_REPO_MD_ERROR, ZIF_REPO_MD_ERROR_FAILED,
+				     "failed to get filename for filelists");
 		goto out;
 	}
 
@@ -101,7 +102,8 @@ zif_repo_md_filelists_load (ZifRepoMd *md, GCancellable *cancellable, ZifComplet
 	rc = sqlite3_open (filename, &filelists->priv->db);
 	if (rc != 0) {
 		egg_warning ("Can't open database: %s\n", sqlite3_errmsg (filelists->priv->db));
-		g_set_error (error, 1, 0, "can't open database: %s", sqlite3_errmsg (filelists->priv->db));
+		g_set_error (error, ZIF_REPO_MD_ERROR, ZIF_REPO_MD_ERROR_BAD_SQL,
+			     "can't open database: %s", sqlite3_errmsg (filelists->priv->db));
 		goto out;
 	}
 
@@ -196,7 +198,8 @@ zif_repo_md_filelists_search_file (ZifRepoMdFilelists *md, const gchar *search,
 	if (!md->priv->loaded) {
 		ret = zif_repo_md_filelists_load (ZIF_REPO_MD (md), cancellable, completion, &error_local);
 		if (!ret) {
-			g_set_error (error, 1, 0, "failed to load store file: %s", error_local->message);
+			g_set_error (error, ZIF_REPO_MD_ERROR, ZIF_REPO_MD_ERROR_FAILED_TO_LOAD,
+				     "failed to load store file: %s", error_local->message);
 			g_error_free (error_local);
 			goto out;
 		}
@@ -217,7 +220,8 @@ zif_repo_md_filelists_search_file (ZifRepoMdFilelists *md, const gchar *search,
 	rc = sqlite3_exec (md->priv->db, statement, zif_repo_md_filelists_sqlite_get_files_cb, data, &error_msg);
 	g_free (statement);
 	if (rc != SQLITE_OK) {
-		g_set_error (error, 1, 0, "SQL error (failed to get keys): %s\n", error_msg);
+		g_set_error (error, ZIF_REPO_MD_ERROR, ZIF_REPO_MD_ERROR_BAD_SQL,
+			     "SQL error (failed to get keys): %s\n", error_msg);
 		sqlite3_free (error_msg);
 		goto out;
 	}
@@ -234,14 +238,16 @@ zif_repo_md_filelists_search_file (ZifRepoMdFilelists *md, const gchar *search,
 		rc = sqlite3_exec (md->priv->db, statement, zif_repo_md_filelists_sqlite_get_id_cb, &pkgid, &error_msg);
 		g_free (statement);
 		if (rc != SQLITE_OK) {
-			g_set_error (error, 1, 0, "SQL error (failed to get packages): %s", error_msg);
+			g_set_error (error, ZIF_REPO_MD_ERROR, ZIF_REPO_MD_ERROR_BAD_SQL,
+				     "SQL error (failed to get packages): %s", error_msg);
 			sqlite3_free (error_msg);
 			goto out;
 		}
 
 		/* we failed to get any results */
 		if (pkgid == NULL) {
-			g_set_error (error, 1, 0, "failed to resolve pkgKey: %i", key);
+			g_set_error (error, ZIF_REPO_MD_ERROR, ZIF_REPO_MD_ERROR_BAD_SQL,
+				     "failed to resolve pkgKey: %i", key);
 			goto out;
 		}
 
@@ -307,6 +313,8 @@ zif_repo_md_filelists_init (ZifRepoMdFilelists *md)
  * zif_repo_md_filelists_new:
  *
  * Return value: A new #ZifRepoMdFilelists class instance.
+ *
+ * Since: 0.0.1
  **/
 ZifRepoMdFilelists *
 zif_repo_md_filelists_new (void)
diff --git a/backends/yum/libzif/zif-repo-md-metalink.c b/backends/yum/libzif/zif-repo-md-metalink.c
index 57d78a2..7cbb8e1 100644
--- a/backends/yum/libzif/zif-repo-md-metalink.c
+++ b/backends/yum/libzif/zif-repo-md-metalink.c
@@ -227,7 +227,8 @@ zif_repo_md_metalink_load (ZifRepoMd *md, GCancellable *cancellable, ZifCompleti
 	/* get filename */
 	filename = zif_repo_md_get_filename_uncompressed (md);
 	if (filename == NULL) {
-		g_set_error_literal (error, 1, 0, "failed to get filename for metalink");
+		g_set_error_literal (error, ZIF_REPO_MD_ERROR, ZIF_REPO_MD_ERROR_FAILED,
+				     "failed to get filename for metalink");
 		goto out;
 	}
 
@@ -266,6 +267,8 @@ out:
  * Finds all mirrors we should use.
  *
  * Return value: the uris to use as an array of strings
+ *
+ * Since: 0.0.1
  **/
 GPtrArray *
 zif_repo_md_metalink_get_uris (ZifRepoMdMetalink *md, guint threshold, GCancellable *cancellable, ZifCompletion *completion, GError **error)
@@ -285,7 +288,8 @@ zif_repo_md_metalink_get_uris (ZifRepoMdMetalink *md, guint threshold, GCancella
 	if (!metalink->priv->loaded) {
 		ret = zif_repo_md_load (ZIF_REPO_MD (md), cancellable, completion, &error_local);
 		if (!ret) {
-			g_set_error (error, 1, 0, "failed to get mirrors from metalink: %s", error_local->message);
+			g_set_error (error, ZIF_REPO_MD_ERROR, ZIF_REPO_MD_ERROR_FAILED_TO_LOAD,
+				     "failed to get mirrors from metalink: %s", error_local->message);
 			g_error_free (error_local);
 			goto out;
 		}
@@ -305,7 +309,8 @@ zif_repo_md_metalink_get_uris (ZifRepoMdMetalink *md, guint threshold, GCancella
 		if (data->preference >= threshold) {
 			uri = zif_config_expand_substitutions (md->priv->config, data->uri, &error_local);
 			if (uri == NULL) {
-				g_set_error (error, 1, 0, "failed to expand substitutions: %s", error_local->message);
+				g_set_error (error, ZIF_REPO_MD_ERROR, ZIF_REPO_MD_ERROR_FAILED,
+					     "failed to expand substitutions: %s", error_local->message);
 				g_error_free (error_local);
 				/* rip apart what we've done already */
 				g_ptr_array_unref (array);
@@ -379,6 +384,8 @@ zif_repo_md_metalink_init (ZifRepoMdMetalink *md)
  * zif_repo_md_metalink_new:
  *
  * Return value: A new #ZifRepoMdMetalink class instance.
+ *
+ * Since: 0.0.1
  **/
 ZifRepoMdMetalink *
 zif_repo_md_metalink_new (void)
@@ -478,7 +485,7 @@ zif_repo_md_metalink_test (EggTest *test)
 	/************************************************************/
 	egg_test_title (test, "correct value");
 	uri = g_ptr_array_index (array, 0);
-	if (g_strcmp0 (uri, "http://www.mirrorservice.org/sites/download.fedora.redhat.com/pub/fedora/linux/releases/12/Everything/i386/os/repodata/repomd.xml") == 0)
+	if (g_strcmp0 (uri, "http://www.mirrorservice.org/sites/download.fedora.redhat.com/pub/fedora/linux/releases/12/Everything/i386/os/") == 0)
 		egg_test_success (test, NULL);
 	else
 		egg_test_failed (test, "failed to get correct url '%s'", uri);
diff --git a/backends/yum/libzif/zif-repo-md-mirrorlist.c b/backends/yum/libzif/zif-repo-md-mirrorlist.c
index 4ddd2b0..34cdbf7 100644
--- a/backends/yum/libzif/zif-repo-md-mirrorlist.c
+++ b/backends/yum/libzif/zif-repo-md-mirrorlist.c
@@ -89,7 +89,8 @@ zif_repo_md_mirrorlist_load (ZifRepoMd *md, GCancellable *cancellable, ZifComple
 	/* get filename */
 	filename = zif_repo_md_get_filename_uncompressed (md);
 	if (filename == NULL) {
-		g_set_error_literal (error, 1, 0, "failed to get filename for mirrorlist");
+		g_set_error_literal (error, ZIF_REPO_MD_ERROR, ZIF_REPO_MD_ERROR_FAILED,
+				     "failed to get filename for mirrorlist");
 		goto out;
 	}
 
@@ -128,6 +129,8 @@ out:
  * Finds all mirrors we should use.
  *
  * Return value: the uris to use as an array of strings
+ *
+ * Since: 0.0.1
  **/
 GPtrArray *
 zif_repo_md_mirrorlist_get_uris (ZifRepoMdMirrorlist *md, GCancellable *cancellable, ZifCompletion *completion, GError **error)
@@ -147,7 +150,8 @@ zif_repo_md_mirrorlist_get_uris (ZifRepoMdMirrorlist *md, GCancellable *cancella
 	if (!mirrorlist->priv->loaded) {
 		ret = zif_repo_md_load (ZIF_REPO_MD (md), cancellable, completion, &error_local);
 		if (!ret) {
-			g_set_error (error, 1, 0, "failed to get uris from mirrorlist: %s", error_local->message);
+			g_set_error (error, ZIF_REPO_MD_ERROR, ZIF_REPO_MD_ERROR_FAILED_TO_LOAD,
+				     "failed to get uris from mirrorlist: %s", error_local->message);
 			g_error_free (error_local);
 			goto out;
 		}
@@ -160,7 +164,8 @@ zif_repo_md_mirrorlist_get_uris (ZifRepoMdMirrorlist *md, GCancellable *cancella
 		data = g_ptr_array_index (mirrorlist->priv->array, i);
 		uri = zif_config_expand_substitutions (md->priv->config, data, &error_local);
 		if (uri == NULL) {
-			g_set_error (error, 1, 0, "failed to expand substitutions: %s", error_local->message);
+			g_set_error (error, ZIF_REPO_MD_ERROR, ZIF_REPO_MD_ERROR_FAILED,
+				     "failed to expand substitutions: %s", error_local->message);
 			g_error_free (error_local);
 			/* rip apart what we've done already */
 			g_ptr_array_unref (array);
@@ -223,6 +228,8 @@ zif_repo_md_mirrorlist_init (ZifRepoMdMirrorlist *md)
  * zif_repo_md_mirrorlist_new:
  *
  * Return value: A new #ZifRepoMdMirrorlist class instance.
+ *
+ * Since: 0.0.1
  **/
 ZifRepoMdMirrorlist *
 zif_repo_md_mirrorlist_new (void)
diff --git a/backends/yum/libzif/zif-repo-md-primary.c b/backends/yum/libzif/zif-repo-md-primary.c
index 8d0346c..59020d3 100644
--- a/backends/yum/libzif/zif-repo-md-primary.c
+++ b/backends/yum/libzif/zif-repo-md-primary.c
@@ -93,7 +93,8 @@ zif_repo_md_primary_load (ZifRepoMd *md, GCancellable *cancellable, ZifCompletio
 	/* get filename */
 	filename = zif_repo_md_get_filename_uncompressed (md);
 	if (filename == NULL) {
-		g_set_error_literal (error, 1, 0, "failed to get filename for primary");
+		g_set_error_literal (error, ZIF_REPO_MD_ERROR, ZIF_REPO_MD_ERROR_FAILED,
+				     "failed to get filename for primary");
 		goto out;
 	}
 
@@ -102,7 +103,8 @@ zif_repo_md_primary_load (ZifRepoMd *md, GCancellable *cancellable, ZifCompletio
 	rc = sqlite3_open (filename, &primary->priv->db);
 	if (rc != 0) {
 		egg_warning ("Can't open database: %s\n", sqlite3_errmsg (primary->priv->db));
-		g_set_error (error, 1, 0, "can't open database: %s", sqlite3_errmsg (primary->priv->db));
+		g_set_error (error, ZIF_REPO_MD_ERROR, ZIF_REPO_MD_ERROR_BAD_SQL,
+			     "can't open database: %s", sqlite3_errmsg (primary->priv->db));
 		goto out;
 	}
 
@@ -147,7 +149,8 @@ zif_repo_md_primary_search (ZifRepoMdPrimary *md, const gchar *pred, GCancellabl
 	if (!md->priv->loaded) {
 		ret = zif_repo_md_load (ZIF_REPO_MD (md), cancellable, completion, &error_local);
 		if (!ret) {
-			g_set_error (error, 1, 0, "failed to load repo_md_primary file: %s", error_local->message);
+			g_set_error (error, ZIF_REPO_MD_ERROR, ZIF_REPO_MD_ERROR_FAILED_TO_LOAD,
+				     "failed to load repo_md_primary file: %s", error_local->message);
 			g_error_free (error_local);
 			goto out;
 		}
@@ -163,7 +166,8 @@ zif_repo_md_primary_search (ZifRepoMdPrimary *md, const gchar *pred, GCancellabl
 				     "rpm_license, rpm_group, size_package, location_href FROM packages %s", pred);
 	rc = sqlite3_exec (md->priv->db, statement, zif_repo_md_primary_sqlite_create_package_cb, data, &error_msg);
 	if (rc != SQLITE_OK) {
-		g_set_error (error, 1, 0, "SQL error: %s\n", error_msg);
+		g_set_error (error, ZIF_REPO_MD_ERROR, ZIF_REPO_MD_ERROR_BAD_SQL,
+			     "SQL error: %s\n", error_msg);
 		sqlite3_free (error_msg);
 		g_ptr_array_unref (data->packages);
 		goto out;
@@ -187,6 +191,8 @@ out:
  * Finds all remote packages that match the name exactly.
  *
  * Return value: an array of #ZifPackageRemote's
+ *
+ * Since: 0.0.1
  **/
 GPtrArray *
 zif_repo_md_primary_resolve (ZifRepoMdPrimary *md, const gchar *search, GCancellable *cancellable, ZifCompletion *completion, GError **error)
@@ -215,6 +221,8 @@ zif_repo_md_primary_resolve (ZifRepoMdPrimary *md, const gchar *search, GCancell
  * Finds all packages that match the name.
  *
  * Return value: an array of #ZifPackageRemote's
+ *
+ * Since: 0.0.1
  **/
 GPtrArray *
 zif_repo_md_primary_search_name (ZifRepoMdPrimary *md, const gchar *search, GCancellable *cancellable, ZifCompletion *completion, GError **error)
@@ -243,6 +251,8 @@ zif_repo_md_primary_search_name (ZifRepoMdPrimary *md, const gchar *search, GCan
  * Finds all packages that match the name or description.
  *
  * Return value: an array of #ZifPackageRemote's
+ *
+ * Since: 0.0.1
  **/
 GPtrArray *
 zif_repo_md_primary_search_details (ZifRepoMdPrimary *md, const gchar *search, GCancellable *cancellable, ZifCompletion *completion, GError **error)
@@ -271,6 +281,8 @@ zif_repo_md_primary_search_details (ZifRepoMdPrimary *md, const gchar *search, G
  * Finds all packages that match the group.
  *
  * Return value: an array of #ZifPackageRemote's
+ *
+ * Since: 0.0.1
  **/
 GPtrArray *
 zif_repo_md_primary_search_group (ZifRepoMdPrimary *md, const gchar *search, GCancellable *cancellable, ZifCompletion *completion, GError **error)
@@ -299,6 +311,8 @@ zif_repo_md_primary_search_group (ZifRepoMdPrimary *md, const gchar *search, GCa
  * Finds all packages that match the given pkgId.
  *
  * Return value: an array of #ZifPackageRemote's
+ *
+ * Since: 0.0.1
  **/
 GPtrArray *
 zif_repo_md_primary_search_pkgid (ZifRepoMdPrimary *md, const gchar *search, GCancellable *cancellable, ZifCompletion *completion, GError **error)
@@ -327,6 +341,8 @@ zif_repo_md_primary_search_pkgid (ZifRepoMdPrimary *md, const gchar *search, GCa
  * Finds all packages that match PackageId.
  *
  * Return value: an array of #ZifPackageRemote's
+ *
+ * Since: 0.0.1
  **/
 GPtrArray *
 zif_repo_md_primary_find_package (ZifRepoMdPrimary *md, const gchar *package_id, GCancellable *cancellable, ZifCompletion *completion, GError **error)
@@ -357,6 +373,8 @@ zif_repo_md_primary_find_package (ZifRepoMdPrimary *md, const gchar *package_id,
  * Returns all packages in the repo.
  *
  * Return value: an array of #ZifPackageRemote's
+ *
+ * Since: 0.0.1
  **/
 GPtrArray *
 zif_repo_md_primary_get_packages (ZifRepoMdPrimary *md, GCancellable *cancellable, ZifCompletion *completion, GError **error)
@@ -418,6 +436,8 @@ zif_repo_md_primary_init (ZifRepoMdPrimary *md)
  * zif_repo_md_primary_new:
  *
  * Return value: A new #ZifRepoMdPrimary class instance.
+ *
+ * Since: 0.0.1
  **/
 ZifRepoMdPrimary *
 zif_repo_md_primary_new (void)
diff --git a/backends/yum/libzif/zif-repo-md.c b/backends/yum/libzif/zif-repo-md.c
index cfa22ba..ba0889b 100644
--- a/backends/yum/libzif/zif-repo-md.c
+++ b/backends/yum/libzif/zif-repo-md.c
@@ -69,12 +69,30 @@ struct _ZifRepoMdPrivate
 G_DEFINE_TYPE (ZifRepoMd, zif_repo_md, G_TYPE_OBJECT)
 
 /**
+ * zif_repo_md_error_quark:
+ *
+ * Return value: Our personal error quark.
+ *
+ * Since: 0.0.1
+ **/
+GQuark
+zif_repo_md_error_quark (void)
+{
+	static GQuark quark = 0;
+	if (!quark)
+		quark = g_quark_from_static_string ("zif_repo_md_error");
+	return quark;
+}
+
+/**
  * zif_repo_md_get_id:
  * @md: the #ZifRepoMd object
  *
  * Gets the md identifier, usually the repo name.
  *
  * Return value: the repo id.
+ *
+ * Since: 0.0.1
  **/
 const gchar *
 zif_repo_md_get_id (ZifRepoMd *md)
@@ -90,6 +108,8 @@ zif_repo_md_get_id (ZifRepoMd *md)
  * Gets the compressed filename of the repo.
  *
  * Return value: the filename
+ *
+ * Since: 0.0.1
  **/
 const gchar *
 zif_repo_md_get_filename (ZifRepoMd *md)
@@ -105,6 +125,8 @@ zif_repo_md_get_filename (ZifRepoMd *md)
  * Gets the location of the repo.
  *
  * Return value: the location
+ *
+ * Since: 0.0.1
  **/
 const gchar *
 zif_repo_md_get_location (ZifRepoMd *md)
@@ -120,6 +142,8 @@ zif_repo_md_get_location (ZifRepoMd *md)
  * Gets the type of the repo.
  *
  * Return value: the type
+ *
+ * Since: 0.0.1
  **/
 ZifRepoMdType
 zif_repo_md_get_mdtype (ZifRepoMd *md)
@@ -135,6 +159,8 @@ zif_repo_md_get_mdtype (ZifRepoMd *md)
  * Gets the uncompressed filename of the repo.
  *
  * Return value: the filename
+ *
+ * Since: 0.0.1
  **/
 const gchar *
 zif_repo_md_get_filename_uncompressed (ZifRepoMd *md)
@@ -151,6 +177,8 @@ zif_repo_md_get_filename_uncompressed (ZifRepoMd *md)
  * Sets the filename of the compressed file.
  *
  * Return value: %TRUE for success, %FALSE for failure
+ *
+ * Since: 0.0.1
  **/
 gboolean
 zif_repo_md_set_filename (ZifRepoMd *md, const gchar *filename)
@@ -176,6 +204,8 @@ zif_repo_md_set_filename (ZifRepoMd *md, const gchar *filename)
  * Sets the timestamp of the compressed file.
  *
  * Return value: %TRUE for success, %FALSE for failure
+ *
+ * Since: 0.0.1
  **/
 gboolean
 zif_repo_md_set_timestamp (ZifRepoMd *md, guint timestamp)
@@ -197,6 +227,8 @@ zif_repo_md_set_timestamp (ZifRepoMd *md, guint timestamp)
  * Sets the location of the compressed file, e.g. "repodata/35d817e-primary.sqlite.bz2"
  *
  * Return value: %TRUE for success, %FALSE for failure
+ *
+ * Since: 0.0.1
  **/
 gboolean
 zif_repo_md_set_location (ZifRepoMd *md, const gchar *location)
@@ -218,6 +250,8 @@ zif_repo_md_set_location (ZifRepoMd *md, const gchar *location)
  * Sets the checksum of the compressed file.
  *
  * Return value: %TRUE for success, %FALSE for failure
+ *
+ * Since: 0.0.1
  **/
 gboolean
 zif_repo_md_set_checksum (ZifRepoMd *md, const gchar *checksum)
@@ -239,6 +273,8 @@ zif_repo_md_set_checksum (ZifRepoMd *md, const gchar *checksum)
  * Sets the checksum of the uncompressed file.
  *
  * Return value: %TRUE for success, %FALSE for failure
+ *
+ * Since: 0.0.1
  **/
 gboolean
 zif_repo_md_set_checksum_uncompressed (ZifRepoMd *md, const gchar *checksum_uncompressed)
@@ -260,6 +296,8 @@ zif_repo_md_set_checksum_uncompressed (ZifRepoMd *md, const gchar *checksum_unco
  * Sets the checksum_type of the files.
  *
  * Return value: %TRUE for success, %FALSE for failure
+ *
+ * Since: 0.0.1
  **/
 gboolean
 zif_repo_md_set_checksum_type (ZifRepoMd *md, GChecksumType checksum_type)
@@ -280,6 +318,8 @@ zif_repo_md_set_checksum_type (ZifRepoMd *md, GChecksumType checksum_type)
  * Sets the type of the metadata, e.g. ZIF_REPO_MD_TYPE_FILELISTS_DB.
  *
  * Return value: %TRUE for success, %FALSE for failure
+ *
+ * Since: 0.0.1
  **/
 gboolean
 zif_repo_md_set_mdtype (ZifRepoMd *md, ZifRepoMdType type)
@@ -325,6 +365,8 @@ out:
  * Sets the repository ID for this metadata.
  *
  * Return value: %TRUE for success, %FALSE for failure
+ *
+ * Since: 0.0.1
  **/
 gboolean
 zif_repo_md_set_id (ZifRepoMd *md, const gchar *id)
@@ -345,6 +387,8 @@ zif_repo_md_set_id (ZifRepoMd *md, const gchar *id)
  * Sets the repository ID for this metadata.
  *
  * Return value: %TRUE for success, %FALSE for failure
+ *
+ * Since: 0.0.1
  **/
 gboolean
 zif_repo_md_set_store_remote (ZifRepoMd *md, ZifStoreRemote *remote)
@@ -417,6 +461,8 @@ out:
  *           abort
  *
  * Return value: %TRUE for success, %FALSE for failure
+ *
+ * Since: 0.0.1
  **/
 gboolean
 zif_repo_md_load (ZifRepoMd *md, GCancellable *cancellable, ZifCompletion *completion, GError **error)
@@ -430,7 +476,8 @@ zif_repo_md_load (ZifRepoMd *md, GCancellable *cancellable, ZifCompletion *compl
 
 	/* no support */
 	if (klass->load == NULL) {
-		g_set_error_literal (error, 1, 0, "operation cannot be performed on this md");
+		g_set_error_literal (error, ZIF_REPO_MD_ERROR, ZIF_REPO_MD_ERROR_NO_SUPPORT,
+				     "operation cannot be performed on this md");
 		return FALSE;
 	}
 
@@ -462,8 +509,9 @@ zif_repo_md_load (ZifRepoMd *md, GCancellable *cancellable, ZifCompletion *compl
 		/* if not online, then this is fatal */
 		ret = zif_config_get_boolean (md->priv->config, "network", NULL);
 		if (!ret) {
-			g_set_error (error, 1, 0, "failed to check %s checksum for %s and offline",
-						      zif_repo_md_type_to_text (md->priv->type), md->priv->id);
+			g_set_error (error, ZIF_REPO_MD_ERROR, ZIF_REPO_MD_ERROR_FAILED_AS_OFFLINE,
+				     "failed to check %s checksum for %s and offline",
+				     zif_repo_md_type_to_text (md->priv->type), md->priv->id);
 			goto out;
 		}
 
@@ -472,14 +520,16 @@ zif_repo_md_load (ZifRepoMd *md, GCancellable *cancellable, ZifCompletion *compl
 		dirname = g_path_get_dirname (md->priv->filename);
 		ret = zif_store_remote_download (md->priv->remote, md->priv->location, dirname, cancellable, completion_local, &error_local);
 		if (!ret) {
-			g_set_error (error, 1, 0, "failed to download missing compressed file: %s", error_local->message);
+			g_set_error (error, ZIF_REPO_MD_ERROR, ZIF_REPO_MD_ERROR_FAILED_DOWNLOAD,
+				     "failed to download missing compressed file: %s", error_local->message);
 			goto out;
 		}
 
 		/* check newly downloaded compressed file */
 		ret = zif_repo_md_file_check (md, FALSE, &error_local);
 		if (!ret) {
-			g_set_error (error, 1, 0, "failed checksum on downloaded file: %s", error_local->message);
+			g_set_error (error, ZIF_REPO_MD_ERROR, ZIF_REPO_MD_ERROR_FAILED,
+				     "failed checksum on downloaded file: %s", error_local->message);
 			goto out;
 		}
 	}
@@ -499,14 +549,16 @@ zif_repo_md_load (ZifRepoMd *md, GCancellable *cancellable, ZifCompletion *compl
 		ret = zif_file_decompress (md->priv->filename, md->priv->filename_uncompressed,
 					   cancellable, completion_local, &error_local);
 		if (!ret) {
-			g_set_error (error, 1, 0, "failed to decompress: %s", error_local->message);
+			g_set_error (error, ZIF_REPO_MD_ERROR, ZIF_REPO_MD_ERROR_FAILED,
+				     "failed to decompress: %s", error_local->message);
 			goto out;
 		}
 
 		/* check newly uncompressed file */
 		ret = zif_repo_md_file_check (md, TRUE, &error_local);
 		if (!ret) {
-			g_set_error (error, 1, 0, "failed checksum on decompressed file: %s", error_local->message);
+			g_set_error (error, ZIF_REPO_MD_ERROR, ZIF_REPO_MD_ERROR_FAILED,
+				     "failed checksum on decompressed file: %s", error_local->message);
 			goto out;
 		}
 	}
@@ -537,6 +589,8 @@ out:
  * Unload the metadata store.
  *
  * Return value: %TRUE for success, %FALSE for failure
+ *
+ * Since: 0.0.1
  **/
 gboolean
 zif_repo_md_unload (ZifRepoMd *md, GCancellable *cancellable, ZifCompletion *completion, GError **error)
@@ -547,7 +601,8 @@ zif_repo_md_unload (ZifRepoMd *md, GCancellable *cancellable, ZifCompletion *com
 
 	/* no support */
 	if (klass->unload == NULL) {
-		g_set_error_literal (error, 1, 0, "operation cannot be performed on this md");
+		g_set_error_literal (error, ZIF_REPO_MD_ERROR, ZIF_REPO_MD_ERROR_NO_SUPPORT,
+				     "operation cannot be performed on this md");
 		return FALSE;
 	}
 
@@ -562,6 +617,8 @@ zif_repo_md_unload (ZifRepoMd *md, GCancellable *cancellable, ZifCompletion *com
  * Clean the metadata store.
  *
  * Return value: %TRUE for success, %FALSE for failure
+ *
+ * Since: 0.0.1
  **/
 gboolean
 zif_repo_md_clean (ZifRepoMd *md, GError **error)
@@ -577,7 +634,8 @@ zif_repo_md_clean (ZifRepoMd *md, GError **error)
 	/* get filename */
 	filename = zif_repo_md_get_filename (md);
 	if (filename == NULL) {
-		g_set_error (error, 1, 0, "failed to get filename for %s", zif_repo_md_type_to_text (md->priv->type));
+		g_set_error (error, ZIF_REPO_MD_ERROR, ZIF_REPO_MD_ERROR_FAILED,
+			     "failed to get filename for %s", zif_repo_md_type_to_text (md->priv->type));
 		ret = FALSE;
 		goto out;
 	}
@@ -589,7 +647,8 @@ zif_repo_md_clean (ZifRepoMd *md, GError **error)
 		ret = g_file_delete (file, NULL, &error_local);
 		g_object_unref (file);
 		if (!ret) {
-			g_set_error (error, 1, 0, "failed to delete metadata file %s: %s", filename, error_local->message);
+			g_set_error (error, ZIF_REPO_MD_ERROR, ZIF_REPO_MD_ERROR_FAILED,
+				     "failed to delete metadata file %s: %s", filename, error_local->message);
 			g_error_free (error_local);
 			goto out;
 		}
@@ -598,7 +657,8 @@ zif_repo_md_clean (ZifRepoMd *md, GError **error)
 	/* get filename */
 	filename = zif_repo_md_get_filename_uncompressed (md);
 	if (filename == NULL) {
-		g_set_error (error, 1, 0, "failed to get uncompressed filename for %s", zif_repo_md_type_to_text (md->priv->type));
+		g_set_error (error, ZIF_REPO_MD_ERROR, ZIF_REPO_MD_ERROR_FAILED,
+			     "failed to get uncompressed filename for %s", zif_repo_md_type_to_text (md->priv->type));
 		ret = FALSE;
 		goto out;
 	}
@@ -610,7 +670,8 @@ zif_repo_md_clean (ZifRepoMd *md, GError **error)
 		ret = g_file_delete (file, NULL, &error_local);
 		g_object_unref (file);
 		if (!ret) {
-			g_set_error (error, 1, 0, "failed to delete metadata file %s: %s", filename, error_local->message);
+			g_set_error (error, ZIF_REPO_MD_ERROR, ZIF_REPO_MD_ERROR_FAILED,
+				     "failed to delete metadata file %s: %s", filename, error_local->message);
 			g_error_free (error_local);
 			goto out;
 		}
@@ -624,6 +685,8 @@ out:
 
 /**
  * zif_repo_md_type_to_text:
+ *
+ * Since: 0.0.1
  **/
 const gchar *
 zif_repo_md_type_to_text (ZifRepoMdType type)
@@ -664,6 +727,8 @@ zif_repo_md_type_to_text (ZifRepoMdType type)
  * Check the metadata files to make sure they are valid.
  *
  * Return value: %TRUE for success, %FALSE for failure
+ *
+ * Since: 0.0.1
  **/
 gboolean
 zif_repo_md_file_check (ZifRepoMd *md, gboolean use_uncompressed, GError **error)
@@ -696,7 +761,8 @@ zif_repo_md_file_check (ZifRepoMd *md, gboolean use_uncompressed, GError **error
 	/* get contents */
 	ret = g_file_get_contents (filename, &data, &length, &error_local);
 	if (!ret) {
-		g_set_error (error, 1, 0, "failed to get contents of %s: %s", filename, error_local->message);
+		g_set_error (error, ZIF_REPO_MD_ERROR, ZIF_REPO_MD_ERROR_FAILED,
+			     "failed to get contents of %s: %s", filename, error_local->message);
 		g_error_free (error_local);
 		goto out;
 	}
@@ -709,7 +775,8 @@ zif_repo_md_file_check (ZifRepoMd *md, gboolean use_uncompressed, GError **error
 
 	/* no checksum set */
 	if (checksum_wanted == NULL) {
-		g_set_error (error, 1, 0, "checksum not set for %s", filename);
+		g_set_error (error, ZIF_REPO_MD_ERROR, ZIF_REPO_MD_ERROR_FAILED,
+			     "checksum not set for %s", filename);
 		ret = FALSE;
 		goto out;
 	}
@@ -720,7 +787,8 @@ zif_repo_md_file_check (ZifRepoMd *md, gboolean use_uncompressed, GError **error
 	/* matches? */
 	ret = (g_strcmp0 (checksum, checksum_wanted) == 0);
 	if (!ret) {
-		g_set_error (error, 1, 0, "checksum incorrect, wanted %s, got %s for %s", checksum_wanted, checksum, filename);
+		g_set_error (error, ZIF_REPO_MD_ERROR, ZIF_REPO_MD_ERROR_FAILED,
+			     "checksum incorrect, wanted %s, got %s for %s", checksum_wanted, checksum, filename);
 		goto out;
 	}
 	egg_debug ("%s checksum correct (%s)", filename, checksum_wanted);
@@ -788,6 +856,8 @@ zif_repo_md_init (ZifRepoMd *md)
  * zif_repo_md_new:
  *
  * Return value: A new #ZifRepoMd class instance.
+ *
+ * Since: 0.0.1
  **/
 ZifRepoMd *
 zif_repo_md_new (void)
diff --git a/backends/yum/libzif/zif-repo-md.h b/backends/yum/libzif/zif-repo-md.h
index 301412e..6c4baab 100644
--- a/backends/yum/libzif/zif-repo-md.h
+++ b/backends/yum/libzif/zif-repo-md.h
@@ -41,6 +41,7 @@ G_BEGIN_DECLS
 #define ZIF_IS_REPO_MD(o)		(G_TYPE_CHECK_INSTANCE_TYPE ((o), ZIF_TYPE_REPO_MD))
 #define ZIF_IS_REPO_MD_CLASS(k)		(G_TYPE_CHECK_CLASS_TYPE ((k), ZIF_TYPE_REPO_MD))
 #define ZIF_REPO_MD_GET_CLASS(o)	(G_TYPE_INSTANCE_GET_CLASS ((o), ZIF_TYPE_REPO_MD, ZifRepoMdClass))
+#define ZIF_REPO_MD_ERROR		(zif_repo_md_error_quark ())
 
 typedef struct _ZifRepoMd		ZifRepoMd;
 typedef struct _ZifRepoMdPrivate	ZifRepoMdPrivate;
@@ -83,7 +84,18 @@ typedef enum {
 	ZIF_REPO_MD_TYPE_UNKNOWN
 } ZifRepoMdType;
 
+typedef enum {
+	ZIF_REPO_MD_ERROR_FAILED,
+	ZIF_REPO_MD_ERROR_NO_SUPPORT,
+	ZIF_REPO_MD_ERROR_FAILED_TO_LOAD,
+	ZIF_REPO_MD_ERROR_FAILED_AS_OFFLINE,
+	ZIF_REPO_MD_ERROR_FAILED_DOWNLOAD,
+	ZIF_REPO_MD_ERROR_BAD_SQL,
+	ZIF_REPO_MD_ERROR_LAST
+} ZifRepoMdError;
+
 GType		 zif_repo_md_get_type			(void);
+GQuark		 zif_repo_md_error_quark			(void);
 ZifRepoMd	*zif_repo_md_new			(void);
 
 /* setters */
diff --git a/backends/yum/libzif/zif-repos.c b/backends/yum/libzif/zif-repos.c
index b74313e..9537fa5 100644
--- a/backends/yum/libzif/zif-repos.c
+++ b/backends/yum/libzif/zif-repos.c
@@ -59,6 +59,22 @@ G_DEFINE_TYPE (ZifRepos, zif_repos, G_TYPE_OBJECT)
 static gpointer zif_repos_object = NULL;
 
 /**
+ * zif_repos_error_quark:
+ *
+ * Return value: Our personal error quark.
+ *
+ * Since: 0.0.1
+ **/
+GQuark
+zif_repos_error_quark (void)
+{
+	static GQuark quark = 0;
+	if (!quark)
+		quark = g_quark_from_static_string ("zif_repos_error");
+	return quark;
+}
+
+/**
  * zif_repos_set_repos_dir:
  * @repos: the #ZifRepos object
  * @repos_dir: the directory, e.g. "/etc/yum.repos.d"
@@ -67,6 +83,8 @@ static gpointer zif_repos_object = NULL;
  * Set the repository directory.
  *
  * Return value: %TRUE for success, %FALSE for failure
+ *
+ * Since: 0.0.1
  **/
 gboolean
 zif_repos_set_repos_dir (ZifRepos *repos, const gchar *repos_dir, GError **error)
@@ -82,14 +100,16 @@ zif_repos_set_repos_dir (ZifRepos *repos, const gchar *repos_dir, GError **error
 	/* check directory exists */
 	ret = g_file_test (repos_dir, G_FILE_TEST_IS_DIR);
 	if (!ret) {
-		g_set_error (error, 1, 0, "repo directory %s does not exist", repos_dir);
+		g_set_error (error, ZIF_REPOS_ERROR, ZIF_REPOS_ERROR_FAILED,
+			     "repo directory %s does not exist", repos_dir);
 		goto out;
 	}
 
 	/* setup watch */
 	ret = zif_monitor_add_watch (repos->priv->monitor, repos_dir, &error_local);
 	if (!ret) {
-		g_set_error (error, 1, 0, "failed to setup watch: %s", error_local->message);
+		g_set_error (error, ZIF_REPOS_ERROR, ZIF_REPOS_ERROR_FAILED,
+			     "failed to setup watch: %s", error_local->message);
 		g_error_free (error_local);
 		goto out;
 	}
@@ -119,7 +139,8 @@ zif_repos_get_for_filename (ZifRepos *repos, const gchar *filename, GCancellable
 	path = g_build_filename (repos->priv->repos_dir, filename, NULL);
 	ret = g_key_file_load_from_file (file, path, G_KEY_FILE_NONE, &error_local);
 	if (!ret) {
-		g_set_error (error, 1, 0, "failed to load %s: %s", path, error_local->message);
+		g_set_error (error, ZIF_REPOS_ERROR, ZIF_REPOS_ERROR_FAILED,
+			     "failed to load %s: %s", path, error_local->message);
 		g_error_free (error_local);
 		goto out;
 	}
@@ -136,7 +157,8 @@ zif_repos_get_for_filename (ZifRepos *repos, const gchar *filename, GCancellable
 		completion_local = zif_completion_get_child (completion);
 		ret = zif_store_remote_set_from_file (store, path, repos_groups[i], cancellable, completion_local, &error_local);
 		if (!ret) {
-			g_set_error (error, 1, 0, "failed to set from %s: %s", path, error_local->message);
+			g_set_error (error, ZIF_REPOS_ERROR, ZIF_REPOS_ERROR_FAILED,
+				     "failed to set from %s: %s", path, error_local->message);
 			g_error_free (error_local);
 			break;
 		}
@@ -162,6 +184,8 @@ out:
  * Load the repository, and parse it's config file.
  *
  * Return value: %TRUE for success, %FALSE for failure
+ *
+ * Since: 0.0.1
  **/
 gboolean
 zif_repos_load (ZifRepos *repos, GCancellable *cancellable, ZifCompletion *completion, GError **error)
@@ -185,7 +209,8 @@ zif_repos_load (ZifRepos *repos, GCancellable *cancellable, ZifCompletion *compl
 	/* search repos dir */
 	dir = g_dir_open (repos->priv->repos_dir, 0, &error_local);
 	if (dir == NULL) {
-		g_set_error (error, 1, 0, "failed to list directory: %s", error_local->message);
+		g_set_error (error, ZIF_REPOS_ERROR, ZIF_REPOS_ERROR_FAILED,
+			     "failed to list directory: %s", error_local->message);
 		g_error_free (error_local);
 		ret = FALSE;
 		goto out;
@@ -211,7 +236,8 @@ zif_repos_load (ZifRepos *repos, GCancellable *cancellable, ZifCompletion *compl
 		filename = g_ptr_array_index (repofiles, i);
 		ret = zif_monitor_add_watch (repos->priv->monitor, filename, &error_local);
 		if (!ret) {
-			g_set_error (error, 1, 0, "failed to setup watch: %s", error_local->message);
+			g_set_error (error, ZIF_REPOS_ERROR, ZIF_REPOS_ERROR_FAILED,
+				     "failed to setup watch: %s", error_local->message);
 			g_error_free (error_local);
 			break;
 		}
@@ -220,7 +246,8 @@ zif_repos_load (ZifRepos *repos, GCancellable *cancellable, ZifCompletion *compl
 		completion_local = zif_completion_get_child (completion);
 		ret = zif_repos_get_for_filename (repos, filename, cancellable, completion_local, &error_local);
 		if (!ret) {
-			g_set_error (error, 1, 0, "failed to get filename %s: %s", filename, error_local->message);
+			g_set_error (error, ZIF_REPOS_ERROR, ZIF_REPOS_ERROR_FAILED,
+				     "failed to get filename %s: %s", filename, error_local->message);
 			g_error_free (error_local);
 			g_ptr_array_set_size (repos->priv->list, 0);
 			ret = FALSE;
@@ -243,7 +270,8 @@ zif_repos_load (ZifRepos *repos, GCancellable *cancellable, ZifCompletion *compl
 		completion_local = zif_completion_get_child (completion);
 		ret = zif_store_remote_get_enabled (store, cancellable, completion_local, &error_local);
 		if (error_local != NULL) {
-			g_set_error (error, 1, 0, "failed to get repo state for %s: %s", zif_store_get_id (ZIF_STORE (store)), error_local->message);
+			g_set_error (error, ZIF_REPOS_ERROR, ZIF_REPOS_ERROR_FAILED,
+				     "failed to get repo state for %s: %s", zif_store_get_id (ZIF_STORE (store)), error_local->message);
 			g_ptr_array_set_size (repos->priv->enabled, 0);
 			ret = FALSE;
 			goto out;
@@ -277,6 +305,8 @@ out:
  * Gets the enabled and disabled remote stores.
  *
  * Return value: a list of #ZifStore's
+ *
+ * Since: 0.0.1
  **/
 GPtrArray *
 zif_repos_get_stores (ZifRepos *repos, GCancellable *cancellable, ZifCompletion *completion, GError **error)
@@ -291,7 +321,8 @@ zif_repos_get_stores (ZifRepos *repos, GCancellable *cancellable, ZifCompletion
 	if (!repos->priv->loaded) {
 		ret = zif_repos_load (repos, cancellable, completion, &error_local);
 		if (!ret) {
-			g_set_error (error, 1, 0, "failed to load repos: %s", error_local->message);
+			g_set_error (error, ZIF_REPOS_ERROR, ZIF_REPOS_ERROR_FAILED,
+				     "failed to load repos: %s", error_local->message);
 			g_error_free (error_local);
 			goto out;
 		}
@@ -313,6 +344,8 @@ out:
  * Gets the enabled remote stores.
  *
  * Return value: a list of #ZifStore's
+ *
+ * Since: 0.0.1
  **/
 GPtrArray *
 zif_repos_get_stores_enabled (ZifRepos *repos, GCancellable *cancellable, ZifCompletion *completion, GError **error)
@@ -329,7 +362,8 @@ zif_repos_get_stores_enabled (ZifRepos *repos, GCancellable *cancellable, ZifCom
 	if (!repos->priv->loaded) {
 		ret = zif_repos_load (repos, cancellable, completion, &error_local);
 		if (!ret) {
-			g_set_error (error, 1, 0, "failed to load enabled repos: %s", error_local->message);
+			g_set_error (error, ZIF_REPOS_ERROR, ZIF_REPOS_ERROR_FAILED,
+				     "failed to load enabled repos: %s", error_local->message);
 			g_error_free (error_local);
 			goto out;
 		}
@@ -356,6 +390,8 @@ out:
  * Gets the store matching the ID.
  *
  * Return value: A #ZifStoreRemote object, or %NULL
+ *
+ * Since: 0.0.1
  **/
 ZifStoreRemote *
 zif_repos_get_store (ZifRepos *repos, const gchar *id, GCancellable *cancellable, ZifCompletion *completion, GError **error)
@@ -374,7 +410,8 @@ zif_repos_get_store (ZifRepos *repos, const gchar *id, GCancellable *cancellable
 	if (!repos->priv->loaded) {
 		ret = zif_repos_load (repos, cancellable, completion, &error_local);
 		if (!ret) {
-			g_set_error (error, 1, 0, "failed to load repos: %s", error_local->message);
+			g_set_error (error, ZIF_REPOS_ERROR, ZIF_REPOS_ERROR_FAILED,
+				     "failed to load repos: %s", error_local->message);
 			g_error_free (error_local);
 			goto out;
 		}
@@ -387,7 +424,8 @@ zif_repos_get_store (ZifRepos *repos, const gchar *id, GCancellable *cancellable
 		/* get the id */
 		id_tmp = zif_store_get_id (ZIF_STORE (store_tmp));
 		if (id_tmp == NULL) {
-			g_set_error_literal (error, 1, 0, "failed to get id");
+			g_set_error_literal (error, ZIF_REPOS_ERROR, ZIF_REPOS_ERROR_FAILED,
+					     "failed to get id");
 			goto out;
 		}
 
@@ -463,6 +501,8 @@ zif_repos_init (ZifRepos *repos)
  * zif_repos_new:
  *
  * Return value: A new #ZifRepos class instance.
+ *
+ * Since: 0.0.1
  **/
 ZifRepos *
 zif_repos_new (void)
diff --git a/backends/yum/libzif/zif-repos.h b/backends/yum/libzif/zif-repos.h
index f9f83f2..ee09481 100644
--- a/backends/yum/libzif/zif-repos.h
+++ b/backends/yum/libzif/zif-repos.h
@@ -37,6 +37,7 @@ G_BEGIN_DECLS
 #define ZIF_IS_REPOS(o)		(G_TYPE_CHECK_INSTANCE_TYPE ((o), ZIF_TYPE_REPOS))
 #define ZIF_IS_REPOS_CLASS(k)	(G_TYPE_CHECK_CLASS_TYPE ((k), ZIF_TYPE_REPOS))
 #define ZIF_REPOS_GET_CLASS(o)	(G_TYPE_INSTANCE_GET_CLASS ((o), ZIF_TYPE_REPOS, ZifReposClass))
+#define ZIF_REPOS_ERROR		(zif_repos_error_quark ())
 
 typedef struct _ZifRepos	ZifRepos;
 typedef struct _ZifReposPrivate	ZifReposPrivate;
@@ -53,7 +54,13 @@ struct _ZifReposClass
 	GObjectClass		 parent_class;
 };
 
+typedef enum {
+	ZIF_REPOS_ERROR_FAILED,
+	ZIF_REPOS_ERROR_LAST
+} ZifReposError;
+
 GType		 zif_repos_get_type		(void);
+GQuark		 zif_repos_error_quark			(void);
 ZifRepos	*zif_repos_new			(void);
 gboolean	 zif_repos_set_repos_dir	(ZifRepos		*repos,
 						 const gchar		*repos_dir,
diff --git a/backends/yum/libzif/zif-store-array.c b/backends/yum/libzif/zif-store-array.c
index 326aece..6cdbb2f 100644
--- a/backends/yum/libzif/zif-store-array.c
+++ b/backends/yum/libzif/zif-store-array.c
@@ -20,8 +20,10 @@
  */
 
 /**
- * SECTION:zif-store_array
- * @short_description: A store_array is a container that holds one or more stores
+ * SECTION:zif-store-array
+ * @short_description: A store-			g_set_error (error, ZIF_STORE_ERROR, ZIF_STORE_ERROR_FAILED,
+				     "failed to %s in %s: %s", pk_role_enum_to_text (role), zif_store_get_id (store), error_local->message);
+array is a container that holds one or more stores
  *
  * A #GPtrArray is the container where #ZifStore's are kept. Global operations can
  * be done on the array and not the indervidual stores.
@@ -61,6 +63,8 @@
  * Add a single #ZifStore to the #GPtrArray.
  *
  * Return value: %TRUE for success, %FALSE for failure
+ *
+ * Since: 0.0.1
  **/
 gboolean
 zif_store_array_add_store (GPtrArray *store_array, ZifStore *store)
@@ -79,6 +83,8 @@ zif_store_array_add_store (GPtrArray *store_array, ZifStore *store)
  * Add an array of #ZifStore's to the #GPtrArray.
  *
  * Return value: %TRUE for success, %FALSE for failure
+ *
+ * Since: 0.0.1
  **/
 gboolean
 zif_store_array_add_stores (GPtrArray *store_array, GPtrArray *stores)
@@ -108,6 +114,8 @@ zif_store_array_add_stores (GPtrArray *store_array, GPtrArray *stores)
  * Convenience function to add local store to the #GPtrArray.
  *
  * Return value: %TRUE for success, %FALSE for failure
+ *
+ * Since: 0.0.1
  **/
 gboolean
 zif_store_array_add_local (GPtrArray *store_array, GCancellable *cancellable, ZifCompletion *completion, GError **error)
@@ -131,6 +139,8 @@ zif_store_array_add_local (GPtrArray *store_array, GCancellable *cancellable, Zi
  * Convenience function to add remote stores to the #GPtrArray.
  *
  * Return value: %TRUE for success, %FALSE for failure
+ *
+ * Since: 0.0.1
  **/
 gboolean
 zif_store_array_add_remote (GPtrArray *store_array, GCancellable *cancellable, ZifCompletion *completion, GError **error)
@@ -144,7 +154,8 @@ zif_store_array_add_remote (GPtrArray *store_array, GCancellable *cancellable, Z
 	repos = zif_repos_new ();
 	array = zif_repos_get_stores (repos, cancellable, completion, &error_local);
 	if (array == NULL) {
-		g_set_error (error, 1, 0, "failed to get enabled stores: %s", error_local->message);
+		g_set_error (error, ZIF_STORE_ERROR, ZIF_STORE_ERROR_FAILED,
+			     "failed to get enabled stores: %s", error_local->message);
 		g_error_free (error_local);
 		ret = FALSE;
 		goto out;
@@ -170,6 +181,8 @@ out:
  * Convenience function to add enabled remote stores to the #GPtrArray.
  *
  * Return value: %TRUE for success, %FALSE for failure
+ *
+ * Since: 0.0.1
  **/
 gboolean
 zif_store_array_add_remote_enabled (GPtrArray *store_array, GCancellable *cancellable, ZifCompletion *completion, GError **error)
@@ -183,7 +196,8 @@ zif_store_array_add_remote_enabled (GPtrArray *store_array, GCancellable *cancel
 	repos = zif_repos_new ();
 	array = zif_repos_get_stores_enabled (repos, cancellable, completion, &error_local);
 	if (array == NULL) {
-		g_set_error (error, 1, 0, "failed to get enabled stores: %s", error_local->message);
+		g_set_error (error, ZIF_STORE_ERROR, ZIF_STORE_ERROR_FAILED,
+			     "failed to get enabled stores: %s", error_local->message);
 		g_error_free (error_local);
 		ret = FALSE;
 		goto out;
@@ -216,7 +230,8 @@ zif_store_array_repos_search (GPtrArray *store_array, PkRoleEnum role, const gch
 	/* nothing to do */
 	if (store_array->len == 0) {
 		egg_warning ("nothing to do");
-		g_set_error (error, 1, 0, "nothing to do as no stores in store_array");
+		g_set_error (error, ZIF_STORE_ERROR, ZIF_STORE_ERROR_ARRAY_IS_EMPTY,
+			     "nothing to do as no stores in store_array");
 		goto out;
 	}
 
@@ -252,10 +267,16 @@ zif_store_array_repos_search (GPtrArray *store_array, PkRoleEnum role, const gch
 			part = zif_store_what_provides (store, search, cancellable, completion_local, &error_local);
 		else if (role == PK_ROLE_ENUM_GET_CATEGORIES)
 			part = zif_store_get_categories (store, cancellable, completion_local, &error_local);
-		else
-			egg_error ("internal error: %s", pk_role_enum_to_text (role));
+		else {
+			g_set_error (error, ZIF_STORE_ERROR, ZIF_STORE_ERROR_FAILED,
+				     "internal error, no such role: %s", pk_role_enum_to_text (role));
+			g_ptr_array_unref (array);
+			array = NULL;
+ 			goto out;
+ 		}
 		if (part == NULL) {
-			g_set_error (error, 1, 0, "failed to %s in %s: %s", pk_role_enum_to_text (role), zif_store_get_id (store), error_local->message);
+			g_set_error (error, ZIF_STORE_ERROR, ZIF_STORE_ERROR_FAILED,
+				     "failed to %s in %s: %s", pk_role_enum_to_text (role), zif_store_get_id (store), error_local->message);
 			g_error_free (error_local);
 			g_ptr_array_unref (array);
 			array = NULL;
@@ -286,6 +307,8 @@ out:
  * Find a single package in the #GPtrArray.
  *
  * Return value: A single #ZifPackage or %NULL
+ *
+ * Since: 0.0.1
  **/
 ZifPackage *
 zif_store_array_find_package (GPtrArray *store_array, const gchar *package_id, GCancellable *cancellable, ZifCompletion *completion, GError **error)
@@ -297,7 +320,8 @@ zif_store_array_find_package (GPtrArray *store_array, const gchar *package_id, G
 
 	/* nothing to do */
 	if (store_array->len == 0) {
-		g_set_error_literal (error, 1, 0, "package cannot be found as the store array is empty");
+		g_set_error_literal (error, ZIF_STORE_ERROR, ZIF_STORE_ERROR_ARRAY_IS_EMPTY,
+				     "package cannot be found as the store array is empty");
 		goto out;
 	}
 
@@ -319,7 +343,8 @@ zif_store_array_find_package (GPtrArray *store_array, const gchar *package_id, G
 
 	/* nothing to do */
 	if (package == NULL) {
-		g_set_error_literal (error, 1, 0, "package cannot be found");
+		g_set_error_literal (error, ZIF_STORE_ERROR, ZIF_STORE_ERROR_FAILED,
+				     "package cannot be found");
 		goto out;
 	}
 out:
@@ -336,6 +361,8 @@ out:
  * Cleans the #ZifStoreRemote objects by deleting cache.
  *
  * Return value: %TRUE for success, %FALSE for failure
+ *
+ * Since: 0.0.1
  **/
 gboolean
 zif_store_array_clean (GPtrArray *store_array, GCancellable *cancellable, ZifCompletion *completion, GError **error)
@@ -363,7 +390,8 @@ zif_store_array_clean (GPtrArray *store_array, GCancellable *cancellable, ZifCom
 		completion_local = zif_completion_get_child (completion);
 		ret = zif_store_clean (store, cancellable, completion_local, &error_local);
 		if (!ret) {
-			g_set_error (error, 1, 0, "failed to clean %s: %s", zif_store_get_id (store), error_local->message);
+			g_set_error (error, ZIF_STORE_ERROR, ZIF_STORE_ERROR_FAILED,
+				     "failed to clean %s: %s", zif_store_get_id (store), error_local->message);
 			g_error_free (error_local);
 			goto out;
 		}
@@ -386,6 +414,8 @@ out:
  * Refreshs the #ZifStoreRemote objects by downloading new data
  *
  * Return value: %TRUE for success, %FALSE for failure
+ *
+ * Since: 0.0.1
  **/
 gboolean
 zif_store_array_refresh (GPtrArray *store_array, gboolean force, GCancellable *cancellable, ZifCompletion *completion, GError **error)
@@ -439,6 +469,8 @@ out:
  * Finds packages matching the package name exactly.
  *
  * Return value: an array of #ZifPackage's
+ *
+ * Since: 0.0.1
  **/
 GPtrArray *
 zif_store_array_resolve (GPtrArray *store_array, const gchar *search, GCancellable *cancellable, ZifCompletion *completion, GError **error)
@@ -457,6 +489,8 @@ zif_store_array_resolve (GPtrArray *store_array, const gchar *search, GCancellab
  * Find packages that match the package name in some part.
  *
  * Return value: an array of #ZifPackage's
+ *
+ * Since: 0.0.1
  **/
 GPtrArray *
 zif_store_array_search_name (GPtrArray *store_array, const gchar *search, GCancellable *cancellable, ZifCompletion *completion, GError **error)
@@ -475,6 +509,8 @@ zif_store_array_search_name (GPtrArray *store_array, const gchar *search, GCance
  * Find packages that match some detail about the package.
  *
  * Return value: an array of #ZifPackage's
+ *
+ * Since: 0.0.1
  **/
 GPtrArray *
 zif_store_array_search_details (GPtrArray *store_array, const gchar *search, GCancellable *cancellable, ZifCompletion *completion, GError **error)
@@ -493,6 +529,8 @@ zif_store_array_search_details (GPtrArray *store_array, const gchar *search, GCa
  * Find packages that belong in a specific group.
  *
  * Return value: an array of #ZifPackage's
+ *
+ * Since: 0.0.1
  **/
 GPtrArray *
 zif_store_array_search_group (GPtrArray *store_array, const gchar *group_enum, GCancellable *cancellable, ZifCompletion *completion, GError **error)
@@ -511,6 +549,8 @@ zif_store_array_search_group (GPtrArray *store_array, const gchar *group_enum, G
  * Find packages that belong in a specific category.
  *
  * Return value: an array of #ZifPackage's
+ *
+ * Since: 0.0.1
  **/
 GPtrArray *
 zif_store_array_search_category (GPtrArray *store_array, const gchar *group_id, GCancellable *cancellable, ZifCompletion *completion, GError **error)
@@ -560,6 +600,8 @@ out:
  * Find packages that provide the specified file.
  *
  * Return value: an array of #ZifPackage's
+ *
+ * Since: 0.0.1
  **/
 GPtrArray *
 zif_store_array_search_file (GPtrArray *store_array, const gchar *search, GCancellable *cancellable, ZifCompletion *completion, GError **error)
@@ -577,6 +619,8 @@ zif_store_array_search_file (GPtrArray *store_array, const gchar *search, GCance
  * Return all packages in the #GPtrArray's.
  *
  * Return value: an array of #ZifPackage's
+ *
+ * Since: 0.0.1
  **/
 GPtrArray *
 zif_store_array_get_packages (GPtrArray *store_array, GCancellable *cancellable, ZifCompletion *completion, GError **error)
@@ -594,6 +638,8 @@ zif_store_array_get_packages (GPtrArray *store_array, GCancellable *cancellable,
  * Return a list of packages that are updatable.
  *
  * Return value: an array of #ZifPackage's
+ *
+ * Since: 0.0.1
  **/
 GPtrArray *
 zif_store_array_get_updates (GPtrArray *store_array, GCancellable *cancellable, ZifCompletion *completion, GError **error)
@@ -612,6 +658,8 @@ zif_store_array_get_updates (GPtrArray *store_array, GCancellable *cancellable,
  * Find packages that provide a specific string.
  *
  * Return value: an array of #ZifPackage's
+ *
+ * Since: 0.0.1
  **/
 GPtrArray *
 zif_store_array_what_provides (GPtrArray *store_array, const gchar *search, GCancellable *cancellable, ZifCompletion *completion, GError **error)
@@ -633,6 +681,8 @@ zif_store_array_what_provides (GPtrArray *store_array, const gchar *search, GCan
  * Return a list of custom categories from all repos.
  *
  * Return value: an array of #PkCategory's
+ *
+ * Since: 0.0.1
  **/
 GPtrArray *
 zif_store_array_get_categories (GPtrArray *store_array, GCancellable *cancellable, ZifCompletion *completion, GError **error)
@@ -687,6 +737,8 @@ out:
  * zif_store_array_new:
  *
  * Return value: A new #GPtrArray class instance.
+ *
+ * Since: 0.0.1
  **/
 GPtrArray *
 zif_store_array_new (void)
diff --git a/backends/yum/libzif/zif-store-local.c b/backends/yum/libzif/zif-store-local.c
index c4f6aba..47db128 100644
--- a/backends/yum/libzif/zif-store-local.c
+++ b/backends/yum/libzif/zif-store-local.c
@@ -76,6 +76,8 @@ static gpointer zif_store_local_object = NULL;
  * Sets the prefix to use for the install root.
  *
  * Return value: %TRUE for success, %FALSE for failure
+ *
+ * Since: 0.0.1
  **/
 gboolean
 zif_store_local_set_prefix (ZifStoreLocal *store, const gchar *prefix, GError **error)
@@ -92,7 +94,8 @@ zif_store_local_set_prefix (ZifStoreLocal *store, const gchar *prefix, GError **
 	/* check file exists */
 	ret = g_file_test (prefix, G_FILE_TEST_IS_DIR);
 	if (!ret) {
-		g_set_error (error, 1, 0, "prefix %s does not exist", prefix);
+		g_set_error (error, ZIF_STORE_ERROR, ZIF_STORE_ERROR_FAILED,
+			     "prefix %s does not exist", prefix);
 		goto out;
 	}
 
@@ -100,7 +103,8 @@ zif_store_local_set_prefix (ZifStoreLocal *store, const gchar *prefix, GError **
 	filename = g_build_filename (prefix, "var", "lib", "rpm", "Packages", NULL);
 	ret = zif_monitor_add_watch (store->priv->monitor, filename, &error_local);
 	if (!ret) {
-		g_set_error (error, 1, 0, "failed to setup watch: %s", error_local->message);
+		g_set_error (error, ZIF_STORE_ERROR, ZIF_STORE_ERROR_FAILED,
+			     "failed to setup watch: %s", error_local->message);
 		g_error_free (error_local);
 		goto out;
 	}
@@ -133,8 +137,8 @@ zif_store_local_load (ZifStore *store, GCancellable *cancellable, ZifCompletion
 	/* not locked */
 	ret = zif_lock_is_locked (local->priv->lock, NULL);
 	if (!ret) {
-		egg_warning ("not locked");
-		g_set_error_literal (error, 1, 0, "not locked");
+		g_set_error_literal (error, ZIF_STORE_ERROR, ZIF_STORE_ERROR_NOT_LOCKED,
+				     "not locked");
 		goto out;
 	}
 
@@ -147,7 +151,8 @@ zif_store_local_load (ZifStore *store, GCancellable *cancellable, ZifCompletion
 
 	retval = rpmdbOpen (local->priv->prefix, &db, O_RDONLY, 0777);
 	if (retval != 0) {
-		g_set_error_literal (error, 1, 0, "failed to open rpmdb");
+		g_set_error_literal (error, ZIF_STORE_ERROR, ZIF_STORE_ERROR_FAILED,
+				     "failed to open rpmdb");
 		ret = FALSE;
 		goto out;
 	}
@@ -166,7 +171,8 @@ zif_store_local_load (ZifStore *store, GCancellable *cancellable, ZifCompletion
 		package = zif_package_local_new ();
 		ret = zif_package_local_set_from_header (package, header, &error_local);
 		if (!ret) {
-			g_set_error (error, 1, 0, "failed to set from header: %s", error_local->message);
+			g_set_error (error, ZIF_STORE_ERROR, ZIF_STORE_ERROR_FAILED,
+				     "failed to set from header: %s", error_local->message);
 			g_error_free (error_local);
 			g_object_unref (package);
 			break;
@@ -208,8 +214,8 @@ zif_store_local_search_name (ZifStore *store, const gchar *search, GCancellable
 	/* not locked */
 	ret = zif_lock_is_locked (local->priv->lock, NULL);
 	if (!ret) {
-		egg_warning ("not locked");
-		g_set_error_literal (error, 1, 0, "not locked");
+		g_set_error_literal (error, ZIF_STORE_ERROR, ZIF_STORE_ERROR_NOT_LOCKED,
+				     "not locked");
 		goto out;
 	}
 
@@ -224,7 +230,8 @@ zif_store_local_search_name (ZifStore *store, const gchar *search, GCancellable
 		completion_local = zif_completion_get_child (completion);
 		ret = zif_store_local_load (store, cancellable, completion_local, &error_local);
 		if (!ret) {
-			g_set_error (error, 1, 0, "failed to load package store: %s", error_local->message);
+			g_set_error (error, ZIF_STORE_ERROR, ZIF_STORE_ERROR_FAILED,
+				     "failed to load package store: %s", error_local->message);
 			g_error_free (error_local);
 			goto out;
 		}
@@ -235,8 +242,8 @@ zif_store_local_search_name (ZifStore *store, const gchar *search, GCancellable
 
 	/* check we have packages */
 	if (local->priv->packages->len == 0) {
-		egg_warning ("no packages in sack, so nothing to do!");
-		g_set_error_literal (error, 1, 0, "no packages in local sack");
+		g_set_error_literal (error, ZIF_STORE_ERROR, ZIF_STORE_ERROR_FAILED,
+				     "no packages in local sack");
 		goto out;
 	}
 
@@ -286,8 +293,7 @@ zif_store_local_search_category (ZifStore *store, const gchar *search, GCancella
 	/* not locked */
 	ret = zif_lock_is_locked (local->priv->lock, NULL);
 	if (!ret) {
-		egg_warning ("not locked");
-		g_set_error_literal (error, 1, 0, "not locked");
+		g_set_error_literal (error, ZIF_STORE_ERROR, ZIF_STORE_ERROR_NOT_LOCKED, "not locked");
 		goto out;
 	}
 
@@ -302,7 +308,8 @@ zif_store_local_search_category (ZifStore *store, const gchar *search, GCancella
 		completion_local = zif_completion_get_child (completion);
 		ret = zif_store_local_load (store, cancellable, completion_local, &error_local);
 		if (!ret) {
-			g_set_error (error, 1, 0, "failed to load package store: %s", error_local->message);
+			g_set_error (error, ZIF_STORE_ERROR, ZIF_STORE_ERROR_FAILED,
+				     "failed to load package store: %s", error_local->message);
 			g_error_free (error_local);
 			goto out;
 		}
@@ -314,7 +321,8 @@ zif_store_local_search_category (ZifStore *store, const gchar *search, GCancella
 	/* check we have packages */
 	if (local->priv->packages->len == 0) {
 		egg_warning ("no packages in sack, so nothing to do!");
-		g_set_error_literal (error, 1, 0, "no packages in local sack");
+		g_set_error_literal (error, ZIF_STORE_ERROR, ZIF_STORE_ERROR_ARRAY_IS_EMPTY,
+				     "no packages in local sack");
 		goto out;
 	}
 
@@ -365,8 +373,7 @@ zif_store_local_search_details (ZifStore *store, const gchar *search, GCancellab
 	/* not locked */
 	ret = zif_lock_is_locked (local->priv->lock, NULL);
 	if (!ret) {
-		egg_warning ("not locked");
-		g_set_error_literal (error, 1, 0, "not locked");
+		g_set_error_literal (error, ZIF_STORE_ERROR, ZIF_STORE_ERROR_NOT_LOCKED, "not locked");
 		goto out;
 	}
 
@@ -381,7 +388,8 @@ zif_store_local_search_details (ZifStore *store, const gchar *search, GCancellab
 		completion_local = zif_completion_get_child (completion);
 		ret = zif_store_local_load (store, cancellable, completion_local, &error_local);
 		if (!ret) {
-			g_set_error (error, 1, 0, "failed to load package store: %s", error_local->message);
+			g_set_error (error, ZIF_STORE_ERROR, ZIF_STORE_ERROR_FAILED,
+				     "failed to load package store: %s", error_local->message);
 			g_error_free (error_local);
 			goto out;
 		}
@@ -393,7 +401,8 @@ zif_store_local_search_details (ZifStore *store, const gchar *search, GCancellab
 	/* check we have packages */
 	if (local->priv->packages->len == 0) {
 		egg_warning ("no packages in sack, so nothing to do!");
-		g_set_error_literal (error, 1, 0, "no packages in local sack");
+		g_set_error_literal (error, ZIF_STORE_ERROR, ZIF_STORE_ERROR_ARRAY_IS_EMPTY,
+				     "no packages in local sack");
 		goto out;
 	}
 
@@ -447,8 +456,7 @@ zif_store_local_search_group (ZifStore *store, const gchar *search, GCancellable
 	/* not locked */
 	ret = zif_lock_is_locked (local->priv->lock, NULL);
 	if (!ret) {
-		egg_warning ("not locked");
-		g_set_error_literal (error, 1, 0, "not locked");
+		g_set_error_literal (error, ZIF_STORE_ERROR, ZIF_STORE_ERROR_NOT_LOCKED, "not locked");
 		goto out;
 	}
 
@@ -463,7 +471,8 @@ zif_store_local_search_group (ZifStore *store, const gchar *search, GCancellable
 		completion_local = zif_completion_get_child (completion);
 		ret = zif_store_local_load (store, cancellable, completion_local, &error_local);
 		if (!ret) {
-			g_set_error (error, 1, 0, "failed to load package store: %s", error_local->message);
+			g_set_error (error, ZIF_STORE_ERROR, ZIF_STORE_ERROR_FAILED,
+				     "failed to load package store: %s", error_local->message);
 			g_error_free (error_local);
 			goto out;
 		}
@@ -475,7 +484,8 @@ zif_store_local_search_group (ZifStore *store, const gchar *search, GCancellable
 	/* check we have packages */
 	if (local->priv->packages->len == 0) {
 		egg_warning ("no packages in sack, so nothing to do!");
-		g_set_error_literal (error, 1, 0, "no packages in local sack");
+		g_set_error_literal (error, ZIF_STORE_ERROR, ZIF_STORE_ERROR_ARRAY_IS_EMPTY,
+				     "no packages in local sack");
 		goto out;
 	}
 
@@ -524,8 +534,7 @@ zif_store_local_search_file (ZifStore *store, const gchar *search, GCancellable
 	/* not locked */
 	ret = zif_lock_is_locked (local->priv->lock, NULL);
 	if (!ret) {
-		egg_warning ("not locked");
-		g_set_error_literal (error, 1, 0, "not locked");
+		g_set_error_literal (error, ZIF_STORE_ERROR, ZIF_STORE_ERROR_NOT_LOCKED, "not locked");
 		goto out;
 	}
 
@@ -540,7 +549,8 @@ zif_store_local_search_file (ZifStore *store, const gchar *search, GCancellable
 		completion_local = zif_completion_get_child (completion);
 		ret = zif_store_local_load (store, cancellable, completion_local, &error_local);
 		if (!ret) {
-			g_set_error (error, 1, 0, "failed to load package store: %s", error_local->message);
+			g_set_error (error, ZIF_STORE_ERROR, ZIF_STORE_ERROR_FAILED,
+				     "failed to load package store: %s", error_local->message);
 			g_error_free (error_local);
 			goto out;
 		}
@@ -552,7 +562,8 @@ zif_store_local_search_file (ZifStore *store, const gchar *search, GCancellable
 	/* check we have packages */
 	if (local->priv->packages->len == 0) {
 		egg_warning ("no packages in sack, so nothing to do!");
-		g_set_error_literal (error, 1, 0, "no packages in local sack");
+		g_set_error_literal (error, ZIF_STORE_ERROR, ZIF_STORE_ERROR_ARRAY_IS_EMPTY,
+				     "no packages in local sack");
 		goto out;
 	}
 
@@ -566,7 +577,8 @@ zif_store_local_search_file (ZifStore *store, const gchar *search, GCancellable
 		package = g_ptr_array_index (local->priv->packages, i);
 		files = zif_package_get_files (package, &error_local);
 		if (files == NULL) {
-			g_set_error (error, 1, 0, "failed to get file lists: %s", error_local->message);
+			g_set_error (error, ZIF_STORE_ERROR, ZIF_STORE_ERROR_FAILED,
+				     "failed to get file lists: %s", error_local->message);
 			g_error_free (error_local);
 			g_ptr_array_unref (array);
 			array = NULL;
@@ -609,8 +621,7 @@ zif_store_local_resolve (ZifStore *store, const gchar *search, GCancellable *can
 	/* not locked */
 	ret = zif_lock_is_locked (local->priv->lock, NULL);
 	if (!ret) {
-		egg_warning ("not locked");
-		g_set_error_literal (error, 1, 0, "not locked");
+		g_set_error_literal (error, ZIF_STORE_ERROR, ZIF_STORE_ERROR_NOT_LOCKED, "not locked");
 		goto out;
 	}
 
@@ -625,7 +636,8 @@ zif_store_local_resolve (ZifStore *store, const gchar *search, GCancellable *can
 		completion_local = zif_completion_get_child (completion);
 		ret = zif_store_local_load (store, cancellable, completion_local, &error_local);
 		if (!ret) {
-			g_set_error (error, 1, 0, "failed to load package store: %s", error_local->message);
+			g_set_error (error, ZIF_STORE_ERROR, ZIF_STORE_ERROR_FAILED,
+				     "failed to load package store: %s", error_local->message);
 			g_error_free (error_local);
 			goto out;
 		}
@@ -637,7 +649,8 @@ zif_store_local_resolve (ZifStore *store, const gchar *search, GCancellable *can
 	/* check we have packages */
 	if (local->priv->packages->len == 0) {
 		egg_warning ("no packages in sack, so nothing to do!");
-		g_set_error_literal (error, 1, 0, "no packages in local sack");
+		g_set_error_literal (error, ZIF_STORE_ERROR, ZIF_STORE_ERROR_ARRAY_IS_EMPTY,
+				     "no packages in local sack");
 		goto out;
 	}
 
@@ -689,8 +702,7 @@ zif_store_local_what_provides (ZifStore *store, const gchar *search, GCancellabl
 	/* not locked */
 	ret = zif_lock_is_locked (local->priv->lock, NULL);
 	if (!ret) {
-		egg_warning ("not locked");
-		g_set_error_literal (error, 1, 0, "not locked");
+		g_set_error_literal (error, ZIF_STORE_ERROR, ZIF_STORE_ERROR_NOT_LOCKED, "not locked");
 		goto out;
 	}
 
@@ -705,7 +717,8 @@ zif_store_local_what_provides (ZifStore *store, const gchar *search, GCancellabl
 		completion_local = zif_completion_get_child (completion);
 		ret = zif_store_local_load (store, cancellable, completion_local, &error_local);
 		if (!ret) {
-			g_set_error (error, 1, 0, "failed to load package store: %s", error_local->message);
+			g_set_error (error, ZIF_STORE_ERROR, ZIF_STORE_ERROR_FAILED,
+				     "failed to load package store: %s", error_local->message);
 			g_error_free (error_local);
 			goto out;
 		}
@@ -717,7 +730,8 @@ zif_store_local_what_provides (ZifStore *store, const gchar *search, GCancellabl
 	/* check we have packages */
 	if (local->priv->packages->len == 0) {
 		egg_warning ("no packages in sack, so nothing to do!");
-		g_set_error_literal (error, 1, 0, "no packages in local sack");
+		g_set_error_literal (error, ZIF_STORE_ERROR, ZIF_STORE_ERROR_ARRAY_IS_EMPTY,
+				     "no packages in local sack");
 		goto out;
 	}
 
@@ -768,8 +782,7 @@ zif_store_local_get_packages (ZifStore *store, GCancellable *cancellable, ZifCom
 	/* not locked */
 	ret = zif_lock_is_locked (local->priv->lock, NULL);
 	if (!ret) {
-		egg_warning ("not locked");
-		g_set_error_literal (error, 1, 0, "not locked");
+		g_set_error_literal (error, ZIF_STORE_ERROR, ZIF_STORE_ERROR_NOT_LOCKED, "not locked");
 		goto out;
 	}
 
@@ -784,7 +797,8 @@ zif_store_local_get_packages (ZifStore *store, GCancellable *cancellable, ZifCom
 		completion_local = zif_completion_get_child (completion);
 		ret = zif_store_local_load (store, cancellable, completion_local, &error_local);
 		if (!ret) {
-			g_set_error (error, 1, 0, "failed to load package store: %s", error_local->message);
+			g_set_error (error, ZIF_STORE_ERROR, ZIF_STORE_ERROR_FAILED,
+				     "failed to load package store: %s", error_local->message);
 			g_error_free (error_local);
 			goto out;
 		}
@@ -796,7 +810,8 @@ zif_store_local_get_packages (ZifStore *store, GCancellable *cancellable, ZifCom
 	/* check we have packages */
 	if (local->priv->packages->len == 0) {
 		egg_warning ("no packages in sack, so nothing to do!");
-		g_set_error_literal (error, 1, 0, "no packages in local sack");
+		g_set_error_literal (error, ZIF_STORE_ERROR, ZIF_STORE_ERROR_ARRAY_IS_EMPTY,
+				     "no packages in local sack");
 		goto out;
 	}
 
@@ -843,8 +858,7 @@ zif_store_local_find_package (ZifStore *store, const gchar *package_id, GCancell
 	/* not locked */
 	ret = zif_lock_is_locked (local->priv->lock, NULL);
 	if (!ret) {
-		egg_warning ("not locked");
-		g_set_error_literal (error, 1, 0, "not locked");
+		g_set_error_literal (error, ZIF_STORE_ERROR, ZIF_STORE_ERROR_NOT_LOCKED, "not locked");
 		goto out;
 	}
 
@@ -859,7 +873,8 @@ zif_store_local_find_package (ZifStore *store, const gchar *package_id, GCancell
 		completion_local = zif_completion_get_child (completion);
 		ret = zif_store_local_load (store, cancellable, completion_local, &error_local);
 		if (!ret) {
-			g_set_error (error, 1, 0, "failed to load package store: %s", error_local->message);
+			g_set_error (error, ZIF_STORE_ERROR, ZIF_STORE_ERROR_FAILED,
+				     "failed to load package store: %s", error_local->message);
 			g_error_free (error_local);
 			goto out;
 		}
@@ -871,7 +886,8 @@ zif_store_local_find_package (ZifStore *store, const gchar *package_id, GCancell
 	/* check we have packages */
 	if (local->priv->packages->len == 0) {
 		egg_warning ("no packages in sack, so nothing to do!");
-		g_set_error_literal (error, 1, 0, "no packages in local sack");
+		g_set_error_literal (error, ZIF_STORE_ERROR, ZIF_STORE_ERROR_ARRAY_IS_EMPTY,
+				     "no packages in local sack");
 		goto out;
 	}
 
@@ -898,13 +914,15 @@ zif_store_local_find_package (ZifStore *store, const gchar *package_id, GCancell
 
 	/* nothing */
 	if (array->len == 0) {
-		g_set_error_literal (error, 1, 0, "failed to find package");
+		g_set_error_literal (error, ZIF_STORE_ERROR, ZIF_STORE_ERROR_FAILED_TO_FIND,
+				     "failed to find package");
 		goto out;
 	}
 
 	/* more than one match */
 	if (array->len > 1) {
-		g_set_error_literal (error, 1, 0, "more than one match");
+		g_set_error_literal (error, ZIF_STORE_ERROR, ZIF_STORE_ERROR_MULTIPLE_MATCHES,
+				     "more than one match");
 		goto out;
 	}
 
@@ -1029,6 +1047,8 @@ zif_store_local_init (ZifStoreLocal *store)
  * zif_store_local_new:
  *
  * Return value: A new #ZifStoreLocal class instance.
+ *
+ * Since: 0.0.1
  **/
 ZifStoreLocal *
 zif_store_local_new (void)
diff --git a/backends/yum/libzif/zif-store-remote.c b/backends/yum/libzif/zif-store-remote.c
index af9468e..6e8693c 100644
--- a/backends/yum/libzif/zif-store-remote.c
+++ b/backends/yum/libzif/zif-store-remote.c
@@ -191,7 +191,8 @@ zif_store_remote_parser_start_element (GMarkupParseContext *context, const gchar
 						g_string_set_size (string, string->len - 2);
 
 						/* return error */
-						g_set_error (error, 1, 0, "%s", string->str);
+						g_set_error (error, ZIF_STORE_ERROR, ZIF_STORE_ERROR_FAILED,
+							     "%s", string->str);
 						g_string_free (string, TRUE);
 					}
 				}
@@ -310,7 +311,8 @@ zif_store_remote_download_try (ZifStoreRemote *store, const gchar *uri, const gc
 	egg_debug ("trying to download %s and save to %s", uri, filename);
 	ret = zif_download_file (download, uri, filename, cancellable, completion, &error_local);
 	if (!ret) {
-		g_set_error (error, 1, 0, "failed to download %s from %s: %s", filename, uri, error_local->message);
+		g_set_error (error, ZIF_STORE_ERROR, ZIF_STORE_ERROR_FAILED,
+			     "failed to download %s from %s: %s", filename, uri, error_local->message);
 		g_error_free (error_local);
 		goto out;
 	}
@@ -318,21 +320,24 @@ zif_store_remote_download_try (ZifStoreRemote *store, const gchar *uri, const gc
 	/* try to read it */
 	ret = g_file_get_contents (filename, &contents, &length, &error_local);
 	if (!ret) {
-		g_set_error (error, 1, 0, "failed to download %s from %s: %s (unable to read file)", filename, uri, error_local->message);
+		g_set_error (error, ZIF_STORE_ERROR, ZIF_STORE_ERROR_FAILED,
+			     "failed to download %s from %s: %s (unable to read file)", filename, uri, error_local->message);
 		g_error_free (error_local);
 		goto out;
 	}
 
 	/* check we have some data */
 	if (length == 0) {
-		g_set_error (error, 1, 0, "failed to download %s from %s: no data", filename, uri);
+		g_set_error (error, ZIF_STORE_ERROR, ZIF_STORE_ERROR_FAILED,
+			     "failed to download %s from %s: no data", filename, uri);
 		ret = FALSE;
 		goto out;
 	}
 
 	/* check this really isn't a fancy 404 page */
 	if (g_str_has_prefix (contents, "<html>")) {
-		g_set_error (error, 1, 0, "failed to download %s from %s: invalid file", filename, uri);
+		g_set_error (error, ZIF_STORE_ERROR, ZIF_STORE_ERROR_FAILED,
+			     "failed to download %s from %s: invalid file", filename, uri);
 		ret = FALSE;
 		goto out;
 	}
@@ -357,6 +362,8 @@ out:
  * then the downloaded file will "/var/cache/zif/hal-0.0.1.rpm"
  *
  * Return value: %TRUE for success, %FALSE for failure
+ *
+ * Since: 0.0.1
  **/
 gboolean
 zif_store_remote_download (ZifStoreRemote *store, const gchar *filename, const gchar *directory,
@@ -381,7 +388,8 @@ zif_store_remote_download (ZifStoreRemote *store, const gchar *filename, const g
 	/* if not online, then this is fatal */
 	ret = zif_config_get_boolean (store->priv->config, "network", NULL);
 	if (!ret) {
-		g_set_error (error, 1, 0, "failed to download %s as offline", filename);
+		g_set_error (error, ZIF_STORE_ERROR, ZIF_STORE_ERROR_FAILED_AS_OFFLINE,
+			     "failed to download %s as offline", filename);
 		goto out;
 	}
 
@@ -396,7 +404,8 @@ zif_store_remote_download (ZifStoreRemote *store, const gchar *filename, const g
 		completion_local = zif_completion_get_child (completion);
 		ret = zif_store_remote_load_metadata (store, cancellable, completion_local, &error_local);
 		if (!ret) {
-			g_set_error (error, 1, 0, "failed to load metadata: %s", error_local->message);
+			g_set_error (error, ZIF_STORE_ERROR, ZIF_STORE_ERROR_FAILED,
+				     "failed to load metadata: %s", error_local->message);
 			g_error_free (error_local);
 			goto out;
 		}
@@ -407,7 +416,8 @@ zif_store_remote_download (ZifStoreRemote *store, const gchar *filename, const g
 
 	/* we need at least one baseurl */
 	if (store->priv->baseurls->len == 0) {
-		g_set_error (error, 1, 0, "no baseurls for %s", store->priv->id);
+		g_set_error (error, ZIF_STORE_ERROR, ZIF_STORE_ERROR_FAILED,
+			     "no baseurls for %s", store->priv->id);
 		ret = FALSE;
 		goto out;
 	}
@@ -453,7 +463,8 @@ zif_store_remote_download (ZifStoreRemote *store, const gchar *filename, const g
 
 	/* nothing */
 	if (!ret) {
-		g_set_error (error, 1, 0, "failed to download %s from any sources", filename);
+		g_set_error (error, ZIF_STORE_ERROR, ZIF_STORE_ERROR_FAILED,
+			     "failed to download %s from any sources", filename);
 		goto out;
 	}
 out:
@@ -481,8 +492,8 @@ zif_store_remote_add_metalink (ZifStoreRemote *store, GCancellable *cancellable,
 	/* if we're loading the metadata with an empty cache, the file won't yet exist. So download it */
 	filename = zif_repo_md_get_filename_uncompressed (store->priv->md_metalink);
 	if (filename == NULL) {
-		egg_error ("Moo: %s", zif_repo_md_get_filename (store->priv->md_metalink));
-		g_set_error (error, 1, 0, "metalink filename not set for %s", store->priv->id);
+		g_set_error (error, ZIF_STORE_ERROR, ZIF_STORE_ERROR_FAILED,
+			     "metalink filename not set for %s", store->priv->id);
 		goto out;
 	}
 
@@ -497,7 +508,8 @@ zif_store_remote_add_metalink (ZifStoreRemote *store, GCancellable *cancellable,
 		download = zif_download_new ();
 		ret = zif_download_file (download, store->priv->metalink, filename, cancellable, completion_local, &error_local);
 		if (!ret) {
-			g_set_error (error, 1, 0, "failed to download %s from %s: %s", filename, store->priv->metalink, error_local->message);
+			g_set_error (error, ZIF_STORE_ERROR, ZIF_STORE_ERROR_FAILED,
+				     "failed to download %s from %s: %s", filename, store->priv->metalink, error_local->message);
 			g_error_free (error_local);
 			goto out;
 		}
@@ -509,7 +521,8 @@ zif_store_remote_add_metalink (ZifStoreRemote *store, GCancellable *cancellable,
 	completion_local = zif_completion_get_child (completion);
 	array = zif_repo_md_metalink_get_uris (ZIF_REPO_MD_METALINK (store->priv->md_metalink), 50, cancellable, completion_local, &error_local);
 	if (array == NULL) {
-		g_set_error (error, 1, 0, "failed to add mirrors from metalink: %s", error_local->message);
+		g_set_error (error, ZIF_STORE_ERROR, ZIF_STORE_ERROR_FAILED,
+			     "failed to add mirrors from metalink: %s", error_local->message);
 		g_error_free (error_local);
 		goto out;
 	}
@@ -517,7 +530,8 @@ zif_store_remote_add_metalink (ZifStoreRemote *store, GCancellable *cancellable,
 	/* nothing here? */
 	if (array->len == 0) {
 		ret = FALSE;
-		g_set_error (error, 1, 0, "failed to get any mirrors from metalink: %s", filename);
+		g_set_error (error, ZIF_STORE_ERROR, ZIF_STORE_ERROR_FAILED,
+			     "failed to get any mirrors from metalink: %s", filename);
 		goto out;
 	}
 
@@ -552,7 +566,8 @@ zif_store_remote_add_mirrorlist (ZifStoreRemote *store, GCancellable *cancellabl
 	/* if we're loading the metadata with an empty cache, the file won't yet exist. So download it */
 	filename = zif_repo_md_get_filename_uncompressed (store->priv->md_mirrorlist);
 	if (filename == NULL) {
-		g_set_error (error, 1, 0, "mirrorlist filename not set for %s", store->priv->id);
+		g_set_error (error, ZIF_STORE_ERROR, ZIF_STORE_ERROR_FAILED,
+			     "mirrorlist filename not set for %s", store->priv->id);
 		goto out;
 	}
 
@@ -567,7 +582,8 @@ zif_store_remote_add_mirrorlist (ZifStoreRemote *store, GCancellable *cancellabl
 		download = zif_download_new ();
 		ret = zif_download_file (download, store->priv->mirrorlist, filename, cancellable, completion_local, &error_local);
 		if (!ret) {
-			g_set_error (error, 1, 0, "failed to download %s from %s: %s", filename, store->priv->mirrorlist, error_local->message);
+			g_set_error (error, ZIF_STORE_ERROR, ZIF_STORE_ERROR_FAILED,
+				     "failed to download %s from %s: %s", filename, store->priv->mirrorlist, error_local->message);
 			g_error_free (error_local);
 			goto out;
 		}
@@ -579,7 +595,8 @@ zif_store_remote_add_mirrorlist (ZifStoreRemote *store, GCancellable *cancellabl
 	completion_local = zif_completion_get_child (completion);
 	array = zif_repo_md_mirrorlist_get_uris (ZIF_REPO_MD_MIRRORLIST (store->priv->md_mirrorlist), cancellable, completion_local, &error_local);
 	if (array == NULL) {
-		g_set_error (error, 1, 0, "failed to add mirrors from mirrorlist: %s", error_local->message);
+		g_set_error (error, ZIF_STORE_ERROR, ZIF_STORE_ERROR_FAILED,
+			     "failed to add mirrors from mirrorlist: %s", error_local->message);
 		g_error_free (error_local);
 		goto out;
 	}
@@ -587,7 +604,8 @@ zif_store_remote_add_mirrorlist (ZifStoreRemote *store, GCancellable *cancellabl
 	/* nothing here? */
 	if (array->len == 0) {
 		ret = FALSE;
-		g_set_error (error, 1, 0, "failed to get any mirrors from mirrorlist: %s", filename);
+		g_set_error (error, ZIF_STORE_ERROR, ZIF_STORE_ERROR_FAILED,
+			     "failed to get any mirrors from mirrorlist: %s", filename);
 		goto out;
 	}
 
@@ -645,7 +663,8 @@ zif_store_remote_load_metadata (ZifStoreRemote *store, GCancellable *cancellable
 	/* not locked */
 	ret = zif_lock_is_locked (store->priv->lock, NULL);
 	if (!ret) {
-		g_set_error_literal (error, 1, 0, "not locked");
+		g_set_error_literal (error, ZIF_STORE_ERROR, ZIF_STORE_ERROR_NOT_LOCKED,
+				     "not locked");
 		goto out;
 	}
 
@@ -661,7 +680,8 @@ zif_store_remote_load_metadata (ZifStoreRemote *store, GCancellable *cancellable
 		completion_local = zif_completion_get_child (completion);
 		ret = zif_store_remote_add_mirrorlist (store, cancellable, completion_local, &error_local);
 		if (!ret) {
-			g_set_error (error, 1, 0, "failed to add mirrorlist: %s", error_local->message);
+			g_set_error (error, ZIF_STORE_ERROR, ZIF_STORE_ERROR_FAILED,
+				     "failed to add mirrorlist: %s", error_local->message);
 			g_error_free (error_local);
 			goto out;
 		}
@@ -675,7 +695,8 @@ zif_store_remote_load_metadata (ZifStoreRemote *store, GCancellable *cancellable
 		completion_local = zif_completion_get_child (completion);
 		ret = zif_store_remote_add_metalink (store, cancellable, completion_local, &error_local);
 		if (!ret) {
-			g_set_error (error, 1, 0, "failed to add metalink: %s", error_local->message);
+			g_set_error (error, ZIF_STORE_ERROR, ZIF_STORE_ERROR_FAILED,
+				     "failed to add metalink: %s", error_local->message);
 			g_error_free (error_local);
 			goto out;
 		}
@@ -683,7 +704,8 @@ zif_store_remote_load_metadata (ZifStoreRemote *store, GCancellable *cancellable
 
 	/* check we got something */
 	if (store->priv->baseurls->len == 0) {
-		g_set_error (error, 1, 0, "no baseurls for %s, so can't download anything! [meta:%s, mirror:%s]",
+		g_set_error (error, ZIF_STORE_ERROR, ZIF_STORE_ERROR_ARRAY_IS_EMPTY,
+			     "no baseurls for %s, so can't download anything! [meta:%s, mirror:%s]",
 			     store->priv->id, store->priv->metalink, store->priv->mirrorlist);
 		ret = FALSE;
 		goto out;
@@ -698,7 +720,8 @@ zif_store_remote_load_metadata (ZifStoreRemote *store, GCancellable *cancellable
 		/* if not online, then this is fatal */
 		ret = zif_config_get_boolean (store->priv->config, "network", NULL);
 		if (!ret) {
-			g_set_error (error, 1, 0, "failed to download repomd as offline");
+			g_set_error (error, ZIF_STORE_ERROR, ZIF_STORE_ERROR_FAILED_AS_OFFLINE,
+				     "failed to download repomd as offline");
 			goto out;
 		}
 
@@ -708,7 +731,8 @@ zif_store_remote_load_metadata (ZifStoreRemote *store, GCancellable *cancellable
 		ret = zif_store_remote_download (store, store->priv->repomd_filename, store->priv->directory, cancellable, completion_local, &error_local);
 		store->priv->loaded_metadata = FALSE;
 		if (!ret) {
-			g_set_error (error, 1, 0, "failed to download missing repomd: %s", error_local->message);
+			g_set_error (error, ZIF_STORE_ERROR, ZIF_STORE_ERROR_FAILED,
+				     "failed to download missing repomd: %s", error_local->message);
 			g_error_free (error_local);
 			goto out;
 		}
@@ -752,7 +776,8 @@ zif_store_remote_load_metadata (ZifStoreRemote *store, GCancellable *cancellable
 		if (location == NULL) {
 			/* messed up repo file, this is fatal */
 			if (i == ZIF_REPO_MD_TYPE_PRIMARY_DB) {
-				g_set_error (error, 1, 0, "failed to get primary metadata location for %s", store->priv->id);
+				g_set_error (error, ZIF_STORE_ERROR, ZIF_STORE_ERROR_FAILED,
+					     "failed to get primary metadata location for %s", store->priv->id);
 				ret = FALSE;
 				goto out;
 			}
@@ -827,7 +852,8 @@ zif_store_remote_refresh (ZifStore *store, gboolean force, GCancellable *cancell
 	/* if not online, then this is fatal */
 	ret = zif_config_get_boolean (remote->priv->config, "network", NULL);
 	if (!ret) {
-		g_set_error_literal (error, 1, 0, "failed to refresh as offline");
+		g_set_error_literal (error, ZIF_STORE_ERROR, ZIF_STORE_ERROR_FAILED_AS_OFFLINE,
+				     "failed to refresh as offline");
 		goto out;
 	}
 
@@ -837,7 +863,8 @@ zif_store_remote_refresh (ZifStore *store, gboolean force, GCancellable *cancell
 	/* not locked */
 	ret = zif_lock_is_locked (remote->priv->lock, NULL);
 	if (!ret) {
-		g_set_error_literal (error, 1, 0, "not locked");
+		g_set_error_literal (error, ZIF_STORE_ERROR, ZIF_STORE_ERROR_NOT_LOCKED,
+				     "not locked");
 		goto out;
 	}
 
@@ -847,7 +874,8 @@ zif_store_remote_refresh (ZifStore *store, gboolean force, GCancellable *cancell
 	/* download new file */
 	ret = zif_store_remote_download (remote, remote->priv->repomd_filename, remote->priv->directory, cancellable, completion_local, &error_local);
 	if (!ret) {
-		g_set_error (error, 1, 0, "failed to download repomd: %s", error_local->message);
+		g_set_error (error, ZIF_STORE_ERROR, ZIF_STORE_ERROR_FAILED,
+			     "failed to download repomd: %s", error_local->message);
 		g_error_free (error_local);
 		goto out;
 	}
@@ -859,7 +887,8 @@ zif_store_remote_refresh (ZifStore *store, gboolean force, GCancellable *cancell
 	completion_local = zif_completion_get_child (completion);
 	ret = zif_store_remote_load_metadata (remote, cancellable, completion_local, &error_local);
 	if (!ret) {
-		g_set_error (error, 1, 0, "failed to load updated metadata: %s", error_local->message);
+		g_set_error (error, ZIF_STORE_ERROR, ZIF_STORE_ERROR_FAILED,
+			     "failed to load updated metadata: %s", error_local->message);
 		g_error_free (error_local);
 		goto out;
 	}
@@ -893,7 +922,8 @@ zif_store_remote_refresh (ZifStore *store, gboolean force, GCancellable *cancell
 		completion_local = zif_completion_get_child (completion);
 		ret = zif_store_remote_download (remote, filename, remote->priv->directory, cancellable, completion_local, &error_local);
 		if (!ret) {
-			g_set_error (error, 1, 0, "failed to refresh %s (%s): %s", zif_repo_md_type_to_text (i), filename, error_local->message);
+			g_set_error (error, ZIF_STORE_ERROR, ZIF_STORE_ERROR_FAILED,
+				     "failed to refresh %s (%s): %s", zif_repo_md_type_to_text (i), filename, error_local->message);
 			g_error_free (error_local);
 			goto out;
 		}
@@ -905,7 +935,8 @@ zif_store_remote_refresh (ZifStore *store, gboolean force, GCancellable *cancell
 		completion_local = zif_completion_get_child (completion);
 		ret = zif_store_file_decompress (filename, cancellable, completion_local, &error_local);
 		if (!ret) {
-			g_set_error (error, 1, 0, "failed to decompress %s for %s: %s",
+			g_set_error (error, ZIF_STORE_ERROR, ZIF_STORE_ERROR_FAILED,
+				     "failed to decompress %s for %s: %s",
 				     filename, zif_repo_md_type_to_text (i), error_local->message);
 			g_error_free (error_local);
 			goto out;
@@ -944,7 +975,8 @@ zif_store_remote_load (ZifStore *store, GCancellable *cancellable, ZifCompletion
 	/* not locked */
 	ret = zif_lock_is_locked (remote->priv->lock, NULL);
 	if (!ret) {
-		g_set_error_literal (error, 1, 0, "not locked");
+		g_set_error_literal (error, ZIF_STORE_ERROR, ZIF_STORE_ERROR_NOT_LOCKED,
+				     "not locked");
 		goto out;
 	}
 
@@ -958,7 +990,8 @@ zif_store_remote_load (ZifStore *store, GCancellable *cancellable, ZifCompletion
 	file = g_key_file_new ();
 	ret = g_key_file_load_from_file (file, remote->priv->repo_filename, G_KEY_FILE_NONE, &error_local);
 	if (!ret) {
-		g_set_error (error, 1, 0, "failed to load %s: %s", remote->priv->repo_filename, error_local->message);
+		g_set_error (error, ZIF_STORE_ERROR, ZIF_STORE_ERROR_FAILED,
+			     "failed to load %s: %s", remote->priv->repo_filename, error_local->message);
 		g_error_free (error_local);
 		goto out;
 	}
@@ -969,7 +1002,8 @@ zif_store_remote_load (ZifStore *store, GCancellable *cancellable, ZifCompletion
 	/* name */
 	remote->priv->name = g_key_file_get_string (file, remote->priv->id, "name", &error_local);
 	if (error_local != NULL) {
-		g_set_error (error, 1, 0, "failed to get name: %s", error_local->message);
+		g_set_error (error, ZIF_STORE_ERROR, ZIF_STORE_ERROR_FAILED,
+			     "failed to get name: %s", error_local->message);
 		g_error_free (error_local);
 		ret = FALSE;
 		goto out;
@@ -978,7 +1012,8 @@ zif_store_remote_load (ZifStore *store, GCancellable *cancellable, ZifCompletion
 	/* enabled */
 	enabled = g_key_file_get_string (file, remote->priv->id, "enabled", &error_local);
 	if (enabled == NULL) {
-		g_set_error (error, 1, 0, "failed to get enabled: %s", error_local->message);
+		g_set_error (error, ZIF_STORE_ERROR, ZIF_STORE_ERROR_FAILED,
+			     "failed to get enabled: %s", error_local->message);
 		g_error_free (error_local);
 		ret = FALSE;
 		goto out;
@@ -1033,7 +1068,8 @@ zif_store_remote_load (ZifStore *store, GCancellable *cancellable, ZifCompletion
 
 	/* we need either a base url or mirror list for an enabled store */
 	if (remote->priv->enabled && remote->priv->baseurls->len == 0 && remote->priv->metalink == NULL && remote->priv->mirrorlist == NULL) {
-		g_set_error_literal (error, 1, 0, "baseurl, metalink or mirrorlist required");
+		g_set_error_literal (error, ZIF_STORE_ERROR, ZIF_STORE_ERROR_FAILED,
+				     "baseurl, metalink or mirrorlist required");
 		ret = FALSE;
 		goto out;
 	}
@@ -1072,7 +1108,8 @@ zif_store_remote_clean (ZifStore *store, GCancellable *cancellable, ZifCompletio
 	/* not locked */
 	ret = zif_lock_is_locked (remote->priv->lock, NULL);
 	if (!ret) {
-		g_set_error_literal (error, 1, 0, "not locked");
+		g_set_error_literal (error, ZIF_STORE_ERROR, ZIF_STORE_ERROR_NOT_LOCKED,
+				     "not locked");
 		goto out;
 	}
 
@@ -1117,7 +1154,8 @@ zif_store_remote_clean (ZifStore *store, GCancellable *cancellable, ZifCompletio
 		/* clean md */
 		ret = zif_repo_md_clean (md, &error_local);
 		if (!ret) {
-			g_set_error (error, 1, 0, "failed to clean %s: %s", zif_repo_md_type_to_text (i), error_local->message);
+			g_set_error (error, ZIF_STORE_ERROR, ZIF_STORE_ERROR_FAILED,
+				     "failed to clean %s: %s", zif_repo_md_type_to_text (i), error_local->message);
 			g_error_free (error_local);
 			goto out;
 		}
@@ -1133,7 +1171,8 @@ skip:
 		ret = g_file_delete (file, NULL, &error_local);
 		g_object_unref (file);
 		if (!ret) {
-			g_set_error (error, 1, 0, "failed to delete metadata file %s: %s",
+			g_set_error (error, ZIF_STORE_ERROR, ZIF_STORE_ERROR_FAILED,
+				     "failed to delete metadata file %s: %s",
 				     remote->priv->repomd_filename, error_local->message);
 			g_error_free (error_local);
 			goto out;
@@ -1150,6 +1189,8 @@ out:
  * zif_store_remote_set_from_file:
  * @cancellable: a #GCancellable which is used to cancel tasks, or %NULL
  * @completion: a #ZifCompletion to use for progress reporting
+ *
+ * Since: 0.0.1
  **/
 gboolean
 zif_store_remote_set_from_file (ZifStoreRemote *store, const gchar *repo_filename, const gchar *id,
@@ -1169,7 +1210,8 @@ zif_store_remote_set_from_file (ZifStoreRemote *store, const gchar *repo_filenam
 	/* not locked */
 	ret = zif_lock_is_locked (store->priv->lock, NULL);
 	if (!ret) {
-		g_set_error_literal (error, 1, 0, "not locked");
+		g_set_error_literal (error, ZIF_STORE_ERROR, ZIF_STORE_ERROR_NOT_LOCKED,
+				     "not locked");
 		goto out;
 	}
 
@@ -1193,7 +1235,8 @@ zif_store_remote_set_from_file (ZifStoreRemote *store, const gchar *repo_filenam
 	/* setup watch */
 	ret = zif_monitor_add_watch (store->priv->monitor, repo_filename, &error_local);
 	if (!ret) {
-		g_set_error (error, 1, 0, "failed to setup watch: %s", error_local->message);
+		g_set_error (error, ZIF_STORE_ERROR, ZIF_STORE_ERROR_FAILED,
+			     "failed to setup watch: %s", error_local->message);
 		g_error_free (error_local);
 		goto out;
 	}
@@ -1201,7 +1244,8 @@ zif_store_remote_set_from_file (ZifStoreRemote *store, const gchar *repo_filenam
 	/* get data */
 	ret = zif_store_remote_load (ZIF_STORE (store), cancellable, completion, &error_local);
 	if (!ret) {
-		g_set_error (error, 1, 0, "failed to load %s: %s", id, error_local->message);
+		g_set_error (error, ZIF_STORE_ERROR, ZIF_STORE_ERROR_FAILED,
+			     "failed to load %s: %s", id, error_local->message);
 		g_error_free (error_local);
 		goto out;
 	}
@@ -1219,6 +1263,8 @@ out:
  * Enable or disable a remote repository.
  *
  * Return value: %TRUE for success, %FALSE for failure
+ *
+ * Since: 0.0.1
  **/
 gboolean
 zif_store_remote_set_enabled (ZifStoreRemote *store, gboolean enabled, GError **error)
@@ -1234,7 +1280,8 @@ zif_store_remote_set_enabled (ZifStoreRemote *store, gboolean enabled, GError **
 	/* not locked */
 	ret = zif_lock_is_locked (store->priv->lock, NULL);
 	if (!ret) {
-		g_set_error_literal (error, 1, 0, "not locked");
+		g_set_error_literal (error, ZIF_STORE_ERROR, ZIF_STORE_ERROR_NOT_LOCKED,
+				     "not locked");
 		goto out;
 	}
 
@@ -1242,7 +1289,8 @@ zif_store_remote_set_enabled (ZifStoreRemote *store, gboolean enabled, GError **
 	file = g_key_file_new ();
 	ret = g_key_file_load_from_file (file, store->priv->repo_filename, G_KEY_FILE_KEEP_COMMENTS, &error_local);
 	if (!ret) {
-		g_set_error (error, 1, 0, "failed to load store file: %s", error_local->message);
+		g_set_error (error, ZIF_STORE_ERROR, ZIF_STORE_ERROR_FAILED,
+			     "failed to load store file: %s", error_local->message);
 		g_error_free (error_local);
 		goto out;
 	}
@@ -1255,7 +1303,8 @@ zif_store_remote_set_enabled (ZifStoreRemote *store, gboolean enabled, GError **
 	data = g_key_file_to_data (file, NULL, NULL);
 	ret = g_file_set_contents (store->priv->repo_filename, data, -1, &error_local);
 	if (!ret) {
-		g_set_error (error, 1, 0, "failed to save: %s", error_local->message);
+		g_set_error (error, ZIF_STORE_ERROR, ZIF_STORE_ERROR_FAILED,
+			     "failed to save: %s", error_local->message);
 		g_error_free (error_local);
 		goto out;
 	}
@@ -1301,7 +1350,8 @@ zif_store_remote_resolve (ZifStore *store, const gchar *search, GCancellable *ca
 	/* not locked */
 	ret = zif_lock_is_locked (remote->priv->lock, NULL);
 	if (!ret) {
-		g_set_error_literal (error, 1, 0, "not locked");
+		g_set_error_literal (error, ZIF_STORE_ERROR, ZIF_STORE_ERROR_NOT_LOCKED,
+				     "not locked");
 		goto out;
 	}
 
@@ -1316,7 +1366,8 @@ zif_store_remote_resolve (ZifStore *store, const gchar *search, GCancellable *ca
 		completion_local = zif_completion_get_child (completion);
 		ret = zif_store_remote_load_metadata (remote, cancellable, completion_local, &error_local);
 		if (!ret) {
-			g_set_error (error, 1, 0, "failed to load metadata for %s: %s", remote->priv->id, error_local->message);
+			g_set_error (error, ZIF_STORE_ERROR, ZIF_STORE_ERROR_FAILED,
+				     "failed to load metadata for %s: %s", remote->priv->id, error_local->message);
 			g_error_free (error_local);
 			goto out;
 		}
@@ -1352,7 +1403,8 @@ zif_store_remote_search_name (ZifStore *store, const gchar *search, GCancellable
 	/* not locked */
 	ret = zif_lock_is_locked (remote->priv->lock, NULL);
 	if (!ret) {
-		g_set_error_literal (error, 1, 0, "not locked");
+		g_set_error_literal (error, ZIF_STORE_ERROR, ZIF_STORE_ERROR_NOT_LOCKED,
+				     "not locked");
 		goto out;
 	}
 
@@ -1367,7 +1419,8 @@ zif_store_remote_search_name (ZifStore *store, const gchar *search, GCancellable
 		completion_local = zif_completion_get_child (completion);
 		ret = zif_store_remote_load_metadata (remote, cancellable, completion_local, &error_local);
 		if (!ret) {
-			g_set_error (error, 1, 0, "failed to load xml: %s", error_local->message);
+			g_set_error (error, ZIF_STORE_ERROR, ZIF_STORE_ERROR_FAILED,
+				     "failed to load xml: %s", error_local->message);
 			g_error_free (error_local);
 			goto out;
 		}
@@ -1403,7 +1456,8 @@ zif_store_remote_search_details (ZifStore *store, const gchar *search, GCancella
 	/* not locked */
 	ret = zif_lock_is_locked (remote->priv->lock, NULL);
 	if (!ret) {
-		g_set_error_literal (error, 1, 0, "not locked");
+		g_set_error_literal (error, ZIF_STORE_ERROR, ZIF_STORE_ERROR_NOT_LOCKED,
+				     "not locked");
 		goto out;
 	}
 
@@ -1418,7 +1472,8 @@ zif_store_remote_search_details (ZifStore *store, const gchar *search, GCancella
 		completion_local = zif_completion_get_child (completion);
 		ret = zif_store_remote_load_metadata (remote, cancellable, completion_local, &error_local);
 		if (!ret) {
-			g_set_error (error, 1, 0, "failed to load xml: %s", error_local->message);
+			g_set_error (error, ZIF_STORE_ERROR, ZIF_STORE_ERROR_FAILED,
+				     "failed to load xml: %s", error_local->message);
 			g_error_free (error_local);
 			goto out;
 		}
@@ -1457,7 +1512,8 @@ zif_store_remote_search_category_resolve (ZifStore *store, const gchar *name, GC
 	completion_local = zif_completion_get_child (completion);
 	array = zif_store_resolve (ZIF_STORE (store_local), name, cancellable, completion_local, &error_local);
 	if (array == NULL) {
-		g_set_error (error, 1, 0, "failed to resolve installed package %s: %s", name, error_local->message);
+		g_set_error (error, ZIF_STORE_ERROR, ZIF_STORE_ERROR_FAILED,
+			     "failed to resolve installed package %s: %s", name, error_local->message);
 		g_error_free (error_local);
 		goto out;
 	}
@@ -1480,7 +1536,8 @@ zif_store_remote_search_category_resolve (ZifStore *store, const gchar *name, GC
 	completion_local = zif_completion_get_child (completion);
 	array = zif_store_resolve (ZIF_STORE (store), name, cancellable, completion_local, &error_local);
 	if (array == NULL) {
-		g_set_error (error, 1, 0, "failed to resolve installed package %s: %s", name, error_local->message);
+		g_set_error (error, ZIF_STORE_ERROR, ZIF_STORE_ERROR_FAILED,
+			     "failed to resolve installed package %s: %s", name, error_local->message);
 		g_error_free (error_local);
 		goto out;
 	}
@@ -1494,7 +1551,8 @@ zif_store_remote_search_category_resolve (ZifStore *store, const gchar *name, GC
 		goto out;
 
 	/* we suck */
-	g_set_error (error, 1, 0, "failed to resolve installed package %s installed or in this repo", name);
+	g_set_error (error, ZIF_STORE_ERROR, ZIF_STORE_ERROR_FAILED,
+		     "failed to resolve installed package %s installed or in this repo", name);
 out:
 	if (array != NULL)
 		g_ptr_array_unref (array);
@@ -1527,7 +1585,8 @@ zif_store_remote_search_category (ZifStore *store, const gchar *group_id, GCance
 	/* not locked */
 	ret = zif_lock_is_locked (remote->priv->lock, NULL);
 	if (!ret) {
-		g_set_error_literal (error, 1, 0, "not locked");
+		g_set_error_literal (error, ZIF_STORE_ERROR, ZIF_STORE_ERROR_NOT_LOCKED,
+				     "not locked");
 		goto out;
 	}
 
@@ -1542,7 +1601,8 @@ zif_store_remote_search_category (ZifStore *store, const gchar *group_id, GCance
 		completion_local = zif_completion_get_child (completion);
 		ret = zif_store_remote_load_metadata (remote, cancellable, completion_local, &error_local);
 		if (!ret) {
-			g_set_error (error, 1, 0, "failed to load xml: %s", error_local->message);
+			g_set_error (error, ZIF_STORE_ERROR, ZIF_STORE_ERROR_FAILED,
+				     "failed to load xml: %s", error_local->message);
 			g_error_free (error_local);
 			goto out;
 		}
@@ -1570,7 +1630,8 @@ zif_store_remote_search_category (ZifStore *store, const gchar *group_id, GCance
 			g_error_free (error_local);
 			goto out;
 		}
-		g_set_error (error, 1, 0, "failed to get packages for group %s: %s", group_id, error_local->message);
+		g_set_error (error, ZIF_STORE_ERROR, ZIF_STORE_ERROR_FAILED,
+			     "failed to get packages for group %s: %s", group_id, error_local->message);
 		g_error_free (error_local);
 		goto out;
 	}
@@ -1600,7 +1661,8 @@ zif_store_remote_search_category (ZifStore *store, const gchar *group_id, GCance
 				goto ignore_error;
 			}
 
-			g_set_error (error, 1, 0, "failed to get resolve %s for %s: %s", name, group_id, error_local->message);
+			g_set_error (error, ZIF_STORE_ERROR, ZIF_STORE_ERROR_FAILED,
+				     "failed to get resolve %s for %s: %s", name, group_id, error_local->message);
 			g_error_free (error_local);
 
 			/* undo all our hard work */
@@ -1642,7 +1704,8 @@ zif_store_remote_search_group (ZifStore *store, const gchar *search, GCancellabl
 	/* not locked */
 	ret = zif_lock_is_locked (remote->priv->lock, NULL);
 	if (!ret) {
-		g_set_error_literal (error, 1, 0, "not locked");
+		g_set_error_literal (error, ZIF_STORE_ERROR, ZIF_STORE_ERROR_NOT_LOCKED,
+				     "not locked");
 		goto out;
 	}
 
@@ -1657,7 +1720,8 @@ zif_store_remote_search_group (ZifStore *store, const gchar *search, GCancellabl
 		completion_local = zif_completion_get_child (completion);
 		ret = zif_store_remote_load_metadata (remote, cancellable, completion_local, &error_local);
 		if (!ret) {
-			g_set_error (error, 1, 0, "failed to load xml: %s", error_local->message);
+			g_set_error (error, ZIF_STORE_ERROR, ZIF_STORE_ERROR_FAILED,
+				     "failed to load xml: %s", error_local->message);
 			g_error_free (error_local);
 			goto out;
 		}
@@ -1694,7 +1758,8 @@ zif_store_remote_find_package (ZifStore *store, const gchar *package_id, GCancel
 	/* not locked */
 	ret = zif_lock_is_locked (remote->priv->lock, NULL);
 	if (!ret) {
-		g_set_error_literal (error, 1, 0, "not locked");
+		g_set_error_literal (error, ZIF_STORE_ERROR, ZIF_STORE_ERROR_NOT_LOCKED,
+				     "not locked");
 		goto out;
 	}
 
@@ -1709,7 +1774,8 @@ zif_store_remote_find_package (ZifStore *store, const gchar *package_id, GCancel
 		completion_local = zif_completion_get_child (completion);
 		ret = zif_store_remote_load_metadata (remote, cancellable, completion_local, &error_local);
 		if (!ret) {
-			g_set_error (error, 1, 0, "failed to load xml: %s", error_local->message);
+			g_set_error (error, ZIF_STORE_ERROR, ZIF_STORE_ERROR_FAILED,
+				     "failed to load xml: %s", error_local->message);
 			g_error_free (error_local);
 			goto out;
 		}
@@ -1722,7 +1788,8 @@ zif_store_remote_find_package (ZifStore *store, const gchar *package_id, GCancel
 	completion_local = zif_completion_get_child (completion);
 	array = zif_repo_md_primary_find_package (ZIF_REPO_MD_PRIMARY (remote->priv->md_primary), package_id, cancellable, completion_local, &error_local);
 	if (array == NULL) {
-		g_set_error (error, 1, 0, "failed to search: %s", error_local->message);
+		g_set_error (error, ZIF_STORE_ERROR, ZIF_STORE_ERROR_FAILED,
+			     "failed to search: %s", error_local->message);
 		g_error_free (error_local);
 		goto out;
 	}
@@ -1732,13 +1799,15 @@ zif_store_remote_find_package (ZifStore *store, const gchar *package_id, GCancel
 
 	/* nothing */
 	if (array->len == 0) {
-		g_set_error_literal (error, 1, 0, "failed to find package");
+		g_set_error_literal (error, ZIF_STORE_ERROR, ZIF_STORE_ERROR_FAILED_TO_FIND,
+				     "failed to find package");
 		goto out;
 	}
 
 	/* more than one match */
 	if (array->len > 1) {
-		g_set_error_literal (error, 1, 0, "more than one match");
+		g_set_error_literal (error, ZIF_STORE_ERROR, ZIF_STORE_ERROR_MULTIPLE_MATCHES,
+				     "more than one match");
 		goto out;
 	}
 
@@ -1767,7 +1836,8 @@ zif_store_remote_get_packages (ZifStore *store, GCancellable *cancellable, ZifCo
 	/* not locked */
 	ret = zif_lock_is_locked (remote->priv->lock, NULL);
 	if (!ret) {
-		g_set_error_literal (error, 1, 0, "not locked");
+		g_set_error_literal (error, ZIF_STORE_ERROR, ZIF_STORE_ERROR_NOT_LOCKED,
+				     "not locked");
 		goto out;
 	}
 
@@ -1782,7 +1852,8 @@ zif_store_remote_get_packages (ZifStore *store, GCancellable *cancellable, ZifCo
 		completion_local = zif_completion_get_child (completion);
 		ret = zif_store_remote_load_metadata (remote, cancellable, completion_local, &error_local);
 		if (!ret) {
-			g_set_error (error, 1, 0, "failed to load xml: %s", error_local->message);
+			g_set_error (error, ZIF_STORE_ERROR, ZIF_STORE_ERROR_FAILED,
+				     "failed to load xml: %s", error_local->message);
 			g_error_free (error_local);
 			goto out;
 		}
@@ -1827,7 +1898,8 @@ zif_store_remote_get_categories (ZifStore *store, GCancellable *cancellable, Zif
 	/* not locked */
 	ret = zif_lock_is_locked (remote->priv->lock, NULL);
 	if (!ret) {
-		g_set_error_literal (error, 1, 0, "not locked");
+		g_set_error_literal (error, ZIF_STORE_ERROR, ZIF_STORE_ERROR_NOT_LOCKED,
+				     "not locked");
 		goto out;
 	}
 
@@ -1842,7 +1914,8 @@ zif_store_remote_get_categories (ZifStore *store, GCancellable *cancellable, Zif
 		completion_local = zif_completion_get_child (completion);
 		ret = zif_store_remote_load_metadata (remote, cancellable, completion_local, &error_local);
 		if (!ret) {
-			g_set_error (error, 1, 0, "failed to load xml: %s", error_local->message);
+			g_set_error (error, ZIF_STORE_ERROR, ZIF_STORE_ERROR_FAILED,
+				     "failed to load xml: %s", error_local->message);
 			g_error_free (error_local);
 			goto out;
 		}
@@ -1863,7 +1936,8 @@ zif_store_remote_get_categories (ZifStore *store, GCancellable *cancellable, Zif
 	completion_local = zif_completion_get_child (completion);
 	array_cats = zif_repo_md_comps_get_categories (ZIF_REPO_MD_COMPS (remote->priv->md_comps), cancellable, completion_local, &error_local);
 	if (array_cats == NULL) {
-		g_set_error (error, 1, 0, "failed to get categories: %s", error_local->message);
+		g_set_error (error, ZIF_STORE_ERROR, ZIF_STORE_ERROR_FAILED,
+			     "failed to get categories: %s", error_local->message);
 		g_error_free (error_local);
 		goto out;
 	}
@@ -1891,7 +1965,8 @@ zif_store_remote_get_categories (ZifStore *store, GCancellable *cancellable, Zif
 		array_groups = zif_repo_md_comps_get_groups_for_category (ZIF_REPO_MD_COMPS (remote->priv->md_comps),
 									  pk_category_get_id (category), cancellable, completion_loop, &error_local);
 		if (array_groups == NULL) {
-			g_set_error (error, 1, 0, "failed to get groups for %s: %s", pk_category_get_id (category), error_local->message);
+			g_set_error (error, ZIF_STORE_ERROR, ZIF_STORE_ERROR_FAILED,
+				     "failed to get groups for %s: %s", pk_category_get_id (category), error_local->message);
 			g_error_free (error_local);
 
 			/* undo the work we've already done */
@@ -1952,7 +2027,8 @@ zif_store_remote_get_updates (ZifStore *store, GCancellable *cancellable, ZifCom
 	/* not locked */
 	ret = zif_lock_is_locked (remote->priv->lock, NULL);
 	if (!ret) {
-		g_set_error_literal (error, 1, 0, "not locked");
+		g_set_error_literal (error, ZIF_STORE_ERROR, ZIF_STORE_ERROR_NOT_LOCKED,
+				     "not locked");
 		goto out;
 	}
 
@@ -1967,7 +2043,8 @@ zif_store_remote_get_updates (ZifStore *store, GCancellable *cancellable, ZifCom
 		completion_local = zif_completion_get_child (completion);
 		ret = zif_store_remote_load_metadata (remote, cancellable, completion_local, &error_local);
 		if (!ret) {
-			g_set_error (error, 1, 0, "failed to load xml: %s", error_local->message);
+			g_set_error (error, ZIF_STORE_ERROR, ZIF_STORE_ERROR_FAILED,
+				     "failed to load xml: %s", error_local->message);
 			g_error_free (error_local);
 			goto out;
 		}
@@ -1981,7 +2058,8 @@ zif_store_remote_get_updates (ZifStore *store, GCancellable *cancellable, ZifCom
 	completion_local = zif_completion_get_child (completion);
 	packages = zif_store_get_packages (store_local, cancellable, completion_local, &error_local);
 	if (packages == NULL) {
-		g_set_error (error, 1, 0, "failed to get local store: %s", error_local->message);
+		g_set_error (error, ZIF_STORE_ERROR, ZIF_STORE_ERROR_FAILED,
+			     "failed to get local store: %s", error_local->message);
 		g_error_free (error_local);
 		goto out;
 	}
@@ -2049,7 +2127,8 @@ zif_store_remote_what_provides (ZifStore *store, const gchar *search, GCancellab
 	/* not locked */
 	ret = zif_lock_is_locked (remote->priv->lock, NULL);
 	if (!ret) {
-		g_set_error_literal (error, 1, 0, "not locked");
+		g_set_error_literal (error, ZIF_STORE_ERROR, ZIF_STORE_ERROR_NOT_LOCKED,
+				     "not locked");
 		goto out;
 	}
 
@@ -2057,7 +2136,8 @@ zif_store_remote_what_provides (ZifStore *store, const gchar *search, GCancellab
 	if (!remote->priv->loaded_metadata) {
 		ret = zif_store_remote_load_metadata (remote, cancellable, completion, &error_local);
 		if (!ret) {
-			g_set_error (error, 1, 0, "failed to load xml: %s", error_local->message);
+			g_set_error (error, ZIF_STORE_ERROR, ZIF_STORE_ERROR_FAILED,
+				     "failed to load xml: %s", error_local->message);
 			g_error_free (error_local);
 			goto out;
 		}
@@ -2087,7 +2167,8 @@ zif_store_remote_search_file (ZifStore *store, const gchar *search, GCancellable
 	/* not locked */
 	ret = zif_lock_is_locked (remote->priv->lock, NULL);
 	if (!ret) {
-		g_set_error_literal (error, 1, 0, "not locked");
+		g_set_error_literal (error, ZIF_STORE_ERROR, ZIF_STORE_ERROR_NOT_LOCKED,
+				     "not locked");
 		goto out;
 	}
 
@@ -2102,7 +2183,8 @@ zif_store_remote_search_file (ZifStore *store, const gchar *search, GCancellable
 		completion_local = zif_completion_get_child (completion);
 		ret = zif_store_remote_load_metadata (remote, cancellable, completion_local, &error_local);
 		if (!ret) {
-			g_set_error (error, 1, 0, "failed to load xml: %s", error_local->message);
+			g_set_error (error, ZIF_STORE_ERROR, ZIF_STORE_ERROR_FAILED,
+				     "failed to load xml: %s", error_local->message);
 			g_error_free (error_local);
 			goto out;
 		}
@@ -2115,7 +2197,8 @@ zif_store_remote_search_file (ZifStore *store, const gchar *search, GCancellable
 	completion_local = zif_completion_get_child (completion);
 	pkgids = zif_repo_md_filelists_search_file (ZIF_REPO_MD_FILELISTS (remote->priv->md_filelists), search, cancellable, completion_local, &error_local);
 	if (pkgids == NULL) {
-		g_set_error (error, 1, 0, "failed to load get list of pkgids: %s", error_local->message);
+		g_set_error (error, ZIF_STORE_ERROR, ZIF_STORE_ERROR_FAILED,
+			     "failed to load get list of pkgids: %s", error_local->message);
 		g_error_free (error_local);
 		goto out;
 	}
@@ -2132,7 +2215,8 @@ zif_store_remote_search_file (ZifStore *store, const gchar *search, GCancellable
 		completion_local = zif_completion_get_child (completion);
 		tmp = zif_repo_md_primary_search_pkgid (ZIF_REPO_MD_PRIMARY (remote->priv->md_primary), pkgid, cancellable, completion_local, &error_local);
 		if (tmp == NULL) {
-			g_set_error (error, 1, 0, "failed to resolve pkgId to package: %s", error_local->message);
+			g_set_error (error, ZIF_STORE_ERROR, ZIF_STORE_ERROR_FAILED_TO_FIND,
+				     "failed to resolve pkgId to package: %s", error_local->message);
 			g_error_free (error_local);
 			/* free what we've collected already */
 			g_ptr_array_unref (array);
@@ -2166,6 +2250,8 @@ out:
  * Finds out if the repository is a development repository.
  *
  * Return value: %TRUE or %FALSE
+ *
+ * Since: 0.0.1
  **/
 gboolean
 zif_store_remote_is_devel (ZifStoreRemote *store, GCancellable *cancellable, ZifCompletion *completion, GError **error)
@@ -2179,7 +2265,8 @@ zif_store_remote_is_devel (ZifStoreRemote *store, GCancellable *cancellable, Zif
 	/* not locked */
 	ret = zif_lock_is_locked (store->priv->lock, NULL);
 	if (!ret) {
-		g_set_error_literal (error, 1, 0, "not locked");
+		g_set_error_literal (error, ZIF_STORE_ERROR, ZIF_STORE_ERROR_NOT_LOCKED,
+				     "not locked");
 		goto out;
 	}
 
@@ -2187,7 +2274,8 @@ zif_store_remote_is_devel (ZifStoreRemote *store, GCancellable *cancellable, Zif
 	if (!store->priv->loaded) {
 		ret = zif_store_remote_load (ZIF_STORE (store), cancellable, completion, &error_local);
 		if (!ret) {
-			g_set_error (error, 1, 0, "failed to load store file: %s", error_local->message);
+			g_set_error (error, ZIF_STORE_ERROR, ZIF_STORE_ERROR_FAILED,
+				     "failed to load store file: %s", error_local->message);
 			g_error_free (error_local);
 			goto out;
 		}
@@ -2234,6 +2322,8 @@ zif_store_remote_get_id (ZifStore *store)
  * Get the name of this repository.
  *
  * Return value: The repository name, e.g. "Fedora"
+ *
+ * Since: 0.0.1
  **/
 const gchar *
 zif_store_remote_get_name (ZifStoreRemote *store, GCancellable *cancellable, ZifCompletion *completion, GError **error)
@@ -2247,7 +2337,8 @@ zif_store_remote_get_name (ZifStoreRemote *store, GCancellable *cancellable, Zif
 	/* not locked */
 	ret = zif_lock_is_locked (store->priv->lock, NULL);
 	if (!ret) {
-		g_set_error_literal (error, 1, 0, "not locked");
+		g_set_error_literal (error, ZIF_STORE_ERROR, ZIF_STORE_ERROR_NOT_LOCKED,
+				     "not locked");
 		goto out;
 	}
 
@@ -2255,7 +2346,8 @@ zif_store_remote_get_name (ZifStoreRemote *store, GCancellable *cancellable, Zif
 	if (!store->priv->loaded) {
 		ret = zif_store_remote_load (ZIF_STORE (store), cancellable, completion, &error_local);
 		if (!ret) {
-			g_set_error (error, 1, 0, "failed to load store file: %s", error_local->message);
+			g_set_error (error, ZIF_STORE_ERROR, ZIF_STORE_ERROR_FAILED,
+				     "failed to load store file: %s", error_local->message);
 			g_error_free (error_local);
 			goto out;
 		}
@@ -2274,6 +2366,8 @@ out:
  * Find out if this repository is enabled or not.
  *
  * Return value: %TRUE or %FALSE
+ *
+ * Since: 0.0.1
  **/
 gboolean
 zif_store_remote_get_enabled (ZifStoreRemote *store, GCancellable *cancellable, ZifCompletion *completion, GError **error)
@@ -2287,7 +2381,8 @@ zif_store_remote_get_enabled (ZifStoreRemote *store, GCancellable *cancellable,
 	/* not locked */
 	ret = zif_lock_is_locked (store->priv->lock, NULL);
 	if (!ret) {
-		g_set_error_literal (error, 1, 0, "not locked");
+		g_set_error_literal (error, ZIF_STORE_ERROR, ZIF_STORE_ERROR_NOT_LOCKED,
+				     "not locked");
 		goto out;
 	}
 
@@ -2295,7 +2390,8 @@ zif_store_remote_get_enabled (ZifStoreRemote *store, GCancellable *cancellable,
 	if (!store->priv->loaded) {
 		ret = zif_store_remote_load (ZIF_STORE (store), cancellable, completion, &error_local);
 		if (!ret) {
-			g_set_error (error, 1, 0, "failed to load store file: %s", error_local->message);
+			g_set_error (error, ZIF_STORE_ERROR, ZIF_STORE_ERROR_FAILED,
+				     "failed to load store file: %s", error_local->message);
 			g_error_free (error_local);
 			goto out;
 		}
@@ -2437,7 +2533,7 @@ zif_store_remote_init (ZifStoreRemote *store)
 	/* get cache */
 	cache_dir = zif_config_get_string (store->priv->config, "cachedir", &error);
 	if (cache_dir == NULL) {
-		egg_error ("failed to get cachedir: %s", error->message);
+ 		egg_warning ("failed to get cachedir: %s", error->message);
 		g_error_free (error);
 		goto out;
 	}
@@ -2445,7 +2541,7 @@ zif_store_remote_init (ZifStoreRemote *store)
 	/* expand */
 	store->priv->cache_dir = zif_config_expand_substitutions (store->priv->config, cache_dir, &error);
 	if (store->priv->cache_dir == NULL) {
-		egg_error ("failed to get expand substitutions: %s", error->message);
+		egg_warning ("failed to get expand substitutions: %s", error->message);
 		g_error_free (error);
 		goto out;
 	}
@@ -2470,6 +2566,8 @@ out:
  * zif_store_remote_new:
  *
  * Return value: A new #ZifStoreRemote class instance.
+ *
+ * Since: 0.0.1
  **/
 ZifStoreRemote *
 zif_store_remote_new (void)
diff --git a/backends/yum/libzif/zif-store.c b/backends/yum/libzif/zif-store.c
index dfd5b7f..9646833 100644
--- a/backends/yum/libzif/zif-store.c
+++ b/backends/yum/libzif/zif-store.c
@@ -42,6 +42,22 @@
 G_DEFINE_TYPE (ZifStore, zif_store, G_TYPE_OBJECT)
 
 /**
+ * zif_store_error_quark:
+ *
+ * Return value: Our personal error quark.
+ *
+ * Since: 0.0.1
+ **/
+GQuark
+zif_store_error_quark (void)
+{
+	static GQuark quark = 0;
+	if (!quark)
+		quark = g_quark_from_static_string ("zif_store_error");
+	return quark;
+}
+
+/**
  * zif_store_load:
  * @store: the #ZifStore object
  * @cancellable: a #GCancellable which is used to cancel tasks, or %NULL
@@ -51,6 +67,8 @@ G_DEFINE_TYPE (ZifStore, zif_store, G_TYPE_OBJECT)
  * Loads the #ZifStore object.
  *
  * Return value: %TRUE for success, %FALSE for failure
+ *
+ * Since: 0.0.1
  **/
 gboolean
 zif_store_load (ZifStore *store, GCancellable *cancellable, ZifCompletion *completion, GError **error)
@@ -61,7 +79,8 @@ zif_store_load (ZifStore *store, GCancellable *cancellable, ZifCompletion *compl
 
 	/* no support */
 	if (klass->load == NULL) {
-		g_set_error_literal (error, 1, 0, "operation cannot be performed on this store");
+		g_set_error_literal (error, ZIF_STORE_ERROR, ZIF_STORE_ERROR_NO_SUPPORT,
+				     "operation cannot be performed on this store");
 		return FALSE;
 	}
 
@@ -78,6 +97,8 @@ zif_store_load (ZifStore *store, GCancellable *cancellable, ZifCompletion *compl
  * Cleans the #ZifStore objects by deleting cache.
  *
  * Return value: %TRUE for success, %FALSE for failure
+ *
+ * Since: 0.0.1
  **/
 gboolean
 zif_store_clean (ZifStore *store, GCancellable *cancellable, ZifCompletion *completion, GError **error)
@@ -88,7 +109,8 @@ zif_store_clean (ZifStore *store, GCancellable *cancellable, ZifCompletion *comp
 
 	/* no support */
 	if (klass->clean == NULL) {
-		g_set_error_literal (error, 1, 0, "operation cannot be performed on this store");
+		g_set_error_literal (error, ZIF_STORE_ERROR, ZIF_STORE_ERROR_NO_SUPPORT,
+				     "operation cannot be performed on this store");
 		return FALSE;
 	}
 
@@ -106,6 +128,8 @@ zif_store_clean (ZifStore *store, GCancellable *cancellable, ZifCompletion *comp
  * refresh the #ZifStore objects by downloading new data if required.
  *
  * Return value: %TRUE for success, %FALSE for failure
+ *
+ * Since: 0.0.1
  **/
 gboolean
 zif_store_refresh (ZifStore *store, gboolean force, GCancellable *cancellable, ZifCompletion *completion, GError **error)
@@ -116,7 +140,8 @@ zif_store_refresh (ZifStore *store, gboolean force, GCancellable *cancellable, Z
 
 	/* no support */
 	if (klass->refresh == NULL) {
-		g_set_error_literal (error, 1, 0, "operation cannot be performed on this store");
+		g_set_error_literal (error, ZIF_STORE_ERROR, ZIF_STORE_ERROR_NO_SUPPORT,
+				     "operation cannot be performed on this store");
 		return FALSE;
 	}
 
@@ -134,6 +159,8 @@ zif_store_refresh (ZifStore *store, gboolean force, GCancellable *cancellable, Z
  * Find packages that match the package name in some part.
  *
  * Return value: an array of #ZifPackage's
+ *
+ * Since: 0.0.1
  **/
 GPtrArray *
 zif_store_search_name (ZifStore *store, const gchar *search, GCancellable *cancellable, ZifCompletion *completion, GError **error)
@@ -145,7 +172,8 @@ zif_store_search_name (ZifStore *store, const gchar *search, GCancellable *cance
 
 	/* no support */
 	if (klass->search_name == NULL) {
-		g_set_error_literal (error, 1, 0, "operation cannot be performed on this store");
+		g_set_error_literal (error, ZIF_STORE_ERROR, ZIF_STORE_ERROR_NO_SUPPORT,
+				     "operation cannot be performed on this store");
 		return FALSE;
 	}
 
@@ -163,6 +191,8 @@ zif_store_search_name (ZifStore *store, const gchar *search, GCancellable *cance
  * Return packages in a specific category.
  *
  * Return value: an array of #ZifPackage's
+ *
+ * Since: 0.0.1
  **/
 GPtrArray *
 zif_store_search_category (ZifStore *store, const gchar *search, GCancellable *cancellable, ZifCompletion *completion, GError **error)
@@ -174,7 +204,8 @@ zif_store_search_category (ZifStore *store, const gchar *search, GCancellable *c
 
 	/* no support */
 	if (klass->search_category == NULL) {
-		g_set_error_literal (error, 1, 0, "operation cannot be performed on this store");
+		g_set_error_literal (error, ZIF_STORE_ERROR, ZIF_STORE_ERROR_NO_SUPPORT,
+				     "operation cannot be performed on this store");
 		return FALSE;
 	}
 
@@ -192,6 +223,8 @@ zif_store_search_category (ZifStore *store, const gchar *search, GCancellable *c
  * Find packages that match some detail about the package.
  *
  * Return value: an array of #ZifPackage's
+ *
+ * Since: 0.0.1
  **/
 GPtrArray *
 zif_store_search_details (ZifStore *store, const gchar *search, GCancellable *cancellable, ZifCompletion *completion, GError **error)
@@ -203,7 +236,8 @@ zif_store_search_details (ZifStore *store, const gchar *search, GCancellable *ca
 
 	/* no support */
 	if (klass->search_details == NULL) {
-		g_set_error_literal (error, 1, 0, "operation cannot be performed on this store");
+		g_set_error_literal (error, ZIF_STORE_ERROR, ZIF_STORE_ERROR_NO_SUPPORT,
+				     "operation cannot be performed on this store");
 		return FALSE;
 	}
 
@@ -221,6 +255,8 @@ zif_store_search_details (ZifStore *store, const gchar *search, GCancellable *ca
  * Find packages that belong in a specific group.
  *
  * Return value: an array of #ZifPackage's
+ *
+ * Since: 0.0.1
  **/
 GPtrArray *
 zif_store_search_group (ZifStore *store, const gchar *search, GCancellable *cancellable, ZifCompletion *completion, GError **error)
@@ -232,7 +268,8 @@ zif_store_search_group (ZifStore *store, const gchar *search, GCancellable *canc
 
 	/* no support */
 	if (klass->search_group == NULL) {
-		g_set_error_literal (error, 1, 0, "operation cannot be performed on this store");
+		g_set_error_literal (error, ZIF_STORE_ERROR, ZIF_STORE_ERROR_NO_SUPPORT,
+				     "operation cannot be performed on this store");
 		return FALSE;
 	}
 
@@ -250,6 +287,8 @@ zif_store_search_group (ZifStore *store, const gchar *search, GCancellable *canc
  * Find packages that provide the specified file.
  *
  * Return value: an array of #ZifPackage's
+ *
+ * Since: 0.0.1
  **/
 GPtrArray *
 zif_store_search_file (ZifStore *store, const gchar *search, GCancellable *cancellable, ZifCompletion *completion, GError **error)
@@ -261,7 +300,8 @@ zif_store_search_file (ZifStore *store, const gchar *search, GCancellable *cance
 
 	/* no support */
 	if (klass->search_file == NULL) {
-		g_set_error_literal (error, 1, 0, "operation cannot be performed on this store");
+		g_set_error_literal (error, ZIF_STORE_ERROR, ZIF_STORE_ERROR_NO_SUPPORT,
+				     "operation cannot be performed on this store");
 		return FALSE;
 	}
 
@@ -279,6 +319,8 @@ zif_store_search_file (ZifStore *store, const gchar *search, GCancellable *cance
  * Finds packages matching the package name exactly.
  *
  * Return value: an array of #ZifPackage's
+ *
+ * Since: 0.0.1
  **/
 GPtrArray *
 zif_store_resolve (ZifStore *store, const gchar *search, GCancellable *cancellable, ZifCompletion *completion, GError **error)
@@ -290,7 +332,8 @@ zif_store_resolve (ZifStore *store, const gchar *search, GCancellable *cancellab
 
 	/* no support */
 	if (klass->resolve == NULL) {
-		g_set_error_literal (error, 1, 0, "operation cannot be performed on this store");
+		g_set_error_literal (error, ZIF_STORE_ERROR, ZIF_STORE_ERROR_NO_SUPPORT,
+				     "operation cannot be performed on this store");
 		return FALSE;
 	}
 
@@ -308,6 +351,8 @@ zif_store_resolve (ZifStore *store, const gchar *search, GCancellable *cancellab
  * Find packages that provide a specific string.
  *
  * Return value: an array of #ZifPackage's
+ *
+ * Since: 0.0.1
  **/
 GPtrArray *
 zif_store_what_provides (ZifStore *store, const gchar *search, GCancellable *cancellable, ZifCompletion *completion, GError **error)
@@ -319,7 +364,8 @@ zif_store_what_provides (ZifStore *store, const gchar *search, GCancellable *can
 
 	/* no support */
 	if (klass->search_name == NULL) {
-		g_set_error_literal (error, 1, 0, "operation cannot be performed on this store");
+		g_set_error_literal (error, ZIF_STORE_ERROR, ZIF_STORE_ERROR_NO_SUPPORT,
+				     "operation cannot be performed on this store");
 		return FALSE;
 	}
 
@@ -336,6 +382,8 @@ zif_store_what_provides (ZifStore *store, const gchar *search, GCancellable *can
  * Return all packages in the #ZifSack's.
  *
  * Return value: an array of #ZifPackage's
+ *
+ * Since: 0.0.1
  **/
 GPtrArray *
 zif_store_get_packages (ZifStore *store, GCancellable *cancellable, ZifCompletion *completion, GError **error)
@@ -346,7 +394,8 @@ zif_store_get_packages (ZifStore *store, GCancellable *cancellable, ZifCompletio
 
 	/* no support */
 	if (klass->get_packages == NULL) {
-		g_set_error_literal (error, 1, 0, "operation cannot be performed on this store");
+		g_set_error_literal (error, ZIF_STORE_ERROR, ZIF_STORE_ERROR_NO_SUPPORT,
+				     "operation cannot be performed on this store");
 		return FALSE;
 	}
 
@@ -363,6 +412,8 @@ zif_store_get_packages (ZifStore *store, GCancellable *cancellable, ZifCompletio
  * Return a list of packages that are updatable.
  *
  * Return value: an array of #ZifPackage's
+ *
+ * Since: 0.0.1
  **/
 GPtrArray *
 zif_store_get_updates (ZifStore *store, GCancellable *cancellable, ZifCompletion *completion, GError **error)
@@ -373,7 +424,8 @@ zif_store_get_updates (ZifStore *store, GCancellable *cancellable, ZifCompletion
 
 	/* no support */
 	if (klass->get_updates == NULL) {
-		g_set_error_literal (error, 1, 0, "operation cannot be performed on this store");
+		g_set_error_literal (error, ZIF_STORE_ERROR, ZIF_STORE_ERROR_NO_SUPPORT,
+				     "operation cannot be performed on this store");
 		return FALSE;
 	}
 
@@ -391,6 +443,8 @@ zif_store_get_updates (ZifStore *store, GCancellable *cancellable, ZifCompletion
  * Find a single package in the #ZifSack.
  *
  * Return value: A single #ZifPackage or %NULL
+ *
+ * Since: 0.0.1
  **/
 ZifPackage *
 zif_store_find_package (ZifStore *store, const gchar *package_id, GCancellable *cancellable, ZifCompletion *completion, GError **error)
@@ -402,7 +456,8 @@ zif_store_find_package (ZifStore *store, const gchar *package_id, GCancellable *
 
 	/* no support */
 	if (klass->find_package == NULL) {
-		g_set_error_literal (error, 1, 0, "operation cannot be performed on this store");
+		g_set_error_literal (error, ZIF_STORE_ERROR, ZIF_STORE_ERROR_NO_SUPPORT,
+				     "operation cannot be performed on this store");
 		return FALSE;
 	}
 
@@ -419,6 +474,8 @@ zif_store_find_package (ZifStore *store, const gchar *package_id, GCancellable *
  * Return a list of custom categories.
  *
  * Return value: an array of #PkCategory's
+ *
+ * Since: 0.0.1
  **/
 GPtrArray *
 zif_store_get_categories (ZifStore *store, GCancellable *cancellable, ZifCompletion *completion, GError **error)
@@ -429,7 +486,8 @@ zif_store_get_categories (ZifStore *store, GCancellable *cancellable, ZifComplet
 
 	/* no support */
 	if (klass->get_categories == NULL) {
-		g_set_error_literal (error, 1, 0, "operation cannot be performed on this store");
+		g_set_error_literal (error, ZIF_STORE_ERROR, ZIF_STORE_ERROR_NO_SUPPORT,
+				     "operation cannot be performed on this store");
 		return FALSE;
 	}
 
@@ -443,6 +501,8 @@ zif_store_get_categories (ZifStore *store, GCancellable *cancellable, ZifComplet
  * Gets the id for the object.
  *
  * Return value: A text ID, or %NULL
+ *
+ * Since: 0.0.1
  **/
 const gchar *
 zif_store_get_id (ZifStore *store)
@@ -463,6 +523,8 @@ zif_store_get_id (ZifStore *store)
  * @store: the #ZifStore object
  *
  * Prints all the objects in the store.
+ *
+ * Since: 0.0.1
  **/
 void
 zif_store_print (ZifStore *store)
@@ -512,6 +574,8 @@ zif_store_init (ZifStore *store)
  * zif_store_new:
  *
  * Return value: A new #ZifStore class instance.
+ *
+ * Since: 0.0.1
  **/
 ZifStore *
 zif_store_new (void)
diff --git a/backends/yum/libzif/zif-store.h b/backends/yum/libzif/zif-store.h
index c4aa869..83b1a25 100644
--- a/backends/yum/libzif/zif-store.h
+++ b/backends/yum/libzif/zif-store.h
@@ -41,6 +41,7 @@ G_BEGIN_DECLS
 #define ZIF_IS_STORE(o)		(G_TYPE_CHECK_INSTANCE_TYPE ((o), ZIF_TYPE_STORE))
 #define ZIF_IS_STORE_CLASS(k)	(G_TYPE_CHECK_CLASS_TYPE ((k), ZIF_TYPE_STORE))
 #define ZIF_STORE_GET_CLASS(o)	(G_TYPE_INSTANCE_GET_CLASS ((o), ZIF_TYPE_STORE, ZifStoreClass))
+#define ZIF_STORE_ERROR		(zif_store_error_quark ())
 
 typedef struct _ZifStore	ZifStore;
 typedef struct _ZifStorePrivate	ZifStorePrivate;
@@ -125,7 +126,20 @@ struct _ZifStoreClass
 	void		 (*print)		(ZifStore		*store);
 };
 
+
+typedef enum {
+	ZIF_STORE_ERROR_FAILED,
+	ZIF_STORE_ERROR_FAILED_AS_OFFLINE,
+	ZIF_STORE_ERROR_FAILED_TO_FIND,
+	ZIF_STORE_ERROR_ARRAY_IS_EMPTY,
+	ZIF_STORE_ERROR_NO_SUPPORT,
+	ZIF_STORE_ERROR_NOT_LOCKED,
+	ZIF_STORE_ERROR_MULTIPLE_MATCHES,
+	ZIF_STORE_ERROR_LAST
+} ZifStoreError;
+
 GType		 zif_store_get_type		(void);
+GQuark		 zif_store_error_quark		(void);
 ZifStore	*zif_store_new			(void);
 gboolean	 zif_store_load			(ZifStore		*store,
 						 GCancellable		*cancellable,
diff --git a/backends/yum/libzif/zif-string.c b/backends/yum/libzif/zif-string.c
index 9d429b6..149e48a 100644
--- a/backends/yum/libzif/zif-string.c
+++ b/backends/yum/libzif/zif-string.c
@@ -51,6 +51,8 @@ struct ZifString {
  * Creates a new referenced counted string
  *
  * Return value: New allocated object
+ *
+ * Since: 0.0.1
  **/
 ZifString *
 zif_string_new (const gchar *value)
@@ -70,6 +72,8 @@ zif_string_new (const gchar *value)
  * Do not free this string as it is now owned by the #ZifString.
  *
  * Return value: New allocated object
+ *
+ * Since: 0.0.1
  **/
 ZifString *
 zif_string_new_value (gchar *value)
@@ -89,6 +93,8 @@ zif_string_new_value (gchar *value)
  * This value is only valid while the #ZifString's reference count > 1.
  *
  * Return value: string value
+ *
+ * Since: 0.0.1
  **/
 const gchar *
 zif_string_get_value (ZifString *string)
@@ -104,6 +110,8 @@ zif_string_get_value (ZifString *string)
  * Increases the reference count on the object.
  *
  * Return value: the #ZifString object
+ *
+ * Since: 0.0.1
  **/
 ZifString *
 zif_string_ref (ZifString *string)
@@ -121,6 +129,8 @@ zif_string_ref (ZifString *string)
  * it calls to zero.
  *
  * Return value: the #ZifString object
+ *
+ * Since: 0.0.1
  **/
 ZifString *
 zif_string_unref (ZifString *string)
diff --git a/backends/yum/libzif/zif-utils.c b/backends/yum/libzif/zif-utils.c
index 9630cfc..ed13e36 100644
--- a/backends/yum/libzif/zif-utils.c
+++ b/backends/yum/libzif/zif-utils.c
@@ -48,11 +48,29 @@
 #define ZIF_CRASH_DEBUG
 
 /**
+ * zif_utils_error_quark:
+ *
+ * Return value: Our personal error quark.
+ *
+ * Since: 0.0.1
+ **/
+GQuark
+zif_utils_error_quark (void)
+{
+	static GQuark quark = 0;
+	if (!quark)
+		quark = g_quark_from_static_string ("zif_utils_error");
+	return quark;
+}
+
+/**
  * zif_init:
  *
  * This must be called before any of the zif_* functions are called.
  *
  * Return value: %TRUE if we initialised correctly
+ *
+ * Since: 0.0.1
  **/
 gboolean
 zif_init (void)
@@ -72,6 +90,8 @@ zif_init (void)
  * zif_debug_crash:
  *
  * Does a null dereference, useful for debugging.
+ *
+ * Since: 0.0.1
  **/
 void
 zif_debug_crash (void)
@@ -89,6 +109,8 @@ zif_debug_crash (void)
  * Convert a text boolean into it's enumerated boolean state
  *
  * Return value: %TRUE for positive, %FALSE for negative
+ *
+ * Since: 0.0.1
  **/
 gboolean
 zif_boolean_from_text (const gchar *text)
@@ -106,6 +128,8 @@ zif_boolean_from_text (const gchar *text)
  * @array: The string array to print
  *
  * Print an array of strings to %STDOUT.
+ *
+ * Since: 0.0.1
  **/
 void
 zif_list_print_array (GPtrArray *array)
@@ -131,6 +155,8 @@ zif_list_print_array (GPtrArray *array)
  * Formats a PackageId structure from a NEVRA.
  *
  * Return value: The PackageId value, or %NULL if invalid
+ *
+ * Since: 0.0.1
  **/
 gchar *
 zif_package_id_from_nevra (const gchar *name, const gchar *epoch, const gchar *version, const gchar *release, const gchar *arch, const gchar *data)
@@ -195,6 +221,8 @@ zif_package_convert_evr (gchar *evr, const gchar **epoch, const gchar **version,
  * Compare two [epoch:]version[-release] strings
  *
  * Return value: 1 for a>b, 0 for a==b, -1 for b>a
+ *
+ * Since: 0.0.1
  **/
 gint
 zif_compare_evr (const gchar *a, const gchar *b)
@@ -269,14 +297,16 @@ zif_file_decompress_zlib (const gchar *in, const gchar *out, GCancellable *cance
 	/* open file for reading */
 	f_in = gzopen (in, "rb");
 	if (f_in == NULL) {
-		g_set_error (error, 1, 0, "cannot open %s for reading", in);
+		g_set_error (error, ZIF_UTILS_ERROR, ZIF_UTILS_ERROR_FAILED_TO_READ,
+			     "cannot open %s for reading", in);
 		goto out;
 	}
 
 	/* open file for writing */
 	f_out = fopen (out, "w");
 	if (f_out == NULL) {
-		g_set_error (error, 1, 0, "cannot open %s for writing", out);
+		g_set_error (error, ZIF_UTILS_ERROR, ZIF_UTILS_ERROR_FAILED_TO_WRITE,
+			     "cannot open %s for writing", out);
 		goto out;
 	}
 
@@ -289,21 +319,23 @@ zif_file_decompress_zlib (const gchar *in, const gchar *out, GCancellable *cance
 
 		/* error */
 		if (size < 0) {
-			g_set_error_literal (error, 1, 0, "failed read");
+			g_set_error_literal (error, ZIF_UTILS_ERROR, ZIF_UTILS_ERROR_FAILED_TO_READ,
+					     "failed read");
 			goto out;
 		}
 
 		/* write data */
 		written = fwrite (buf, 1, size, f_out);
 		if (written != size) {
-			g_set_error (error, 1, 0, "only wrote %i/%i bytes", written, size);
+			g_set_error (error, ZIF_UTILS_ERROR, ZIF_UTILS_ERROR_FAILED_TO_WRITE,
+				     "only wrote %i/%i bytes", written, size);
 			goto out;
 		}
 
 		/* is cancelled */
 		ret = !g_cancellable_is_cancelled (cancellable);
 		if (!ret) {
-			g_set_error_literal (error, 1, 0, "cancelled");
+			g_set_error_literal (error, ZIF_UTILS_ERROR, ZIF_UTILS_ERROR_CANCELLED, "cancelled");
 			goto out;
 		}
 	}
@@ -339,21 +371,24 @@ zif_file_decompress_bz2 (const gchar *in, const gchar *out, GCancellable *cancel
 	/* open file for reading */
 	f_in = fopen (in, "r");
 	if (f_in == NULL) {
-		g_set_error (error, 1, 0, "cannot open %s for reading", in);
+		g_set_error (error, ZIF_UTILS_ERROR, ZIF_UTILS_ERROR_FAILED_TO_READ,
+			     "cannot open %s for reading", in);
 		goto out;
 	}
 
 	/* open file for writing */
 	f_out = fopen (out, "w");
 	if (f_out == NULL) {
-		g_set_error (error, 1, 0, "cannot open %s for writing", out);
+		g_set_error (error, ZIF_UTILS_ERROR, ZIF_UTILS_ERROR_FAILED_TO_WRITE,
+			     "cannot open %s for writing", out);
 		goto out;
 	}
 
 	/* read in file */
 	b = BZ2_bzReadOpen (&bzerror, f_in, 0, 0, NULL, 0);
 	if (bzerror != BZ_OK) {
-		g_set_error (error, 1, 0, "cannot open %s for bz2 reading", in);
+		g_set_error (error, ZIF_UTILS_ERROR, ZIF_UTILS_ERROR_FAILED_TO_READ,
+			     "cannot open %s for bz2 reading", in);
 		goto out;
 	}
 
@@ -362,28 +397,32 @@ zif_file_decompress_bz2 (const gchar *in, const gchar *out, GCancellable *cancel
 		/* read data */
 		size = BZ2_bzRead (&bzerror, b, buf, ZIF_BUFFER_SIZE);
 		if (bzerror != BZ_OK && bzerror != BZ_STREAM_END) {
-			g_set_error_literal (error, 1, 0, "failed to decompress");
+			g_set_error_literal (error, ZIF_UTILS_ERROR, ZIF_UTILS_ERROR_FAILED,
+					     "failed to decompress");
 			goto out;
 		}
 
 		/* write data */
 		written = fwrite (buf, 1, size, f_out);
 		if (written != size) {
-			g_set_error (error, 1, 0, "only wrote %i/%i bytes", written, size);
+			g_set_error (error, ZIF_UTILS_ERROR, ZIF_UTILS_ERROR_FAILED_TO_WRITE,
+				     "only wrote %i/%i bytes", written, size);
 			goto out;
 		}
 
 		/* is cancelled */
 		ret = !g_cancellable_is_cancelled (cancellable);
 		if (!ret) {
-			g_set_error_literal (error, 1, 0, "cancelled");
+			g_set_error_literal (error, ZIF_UTILS_ERROR, ZIF_UTILS_ERROR_CANCELLED,
+					     "cancelled");
 			goto out;
 		}
 	}
 
 	/* failed to read */
 	if (bzerror != BZ_STREAM_END) {
-		g_set_error (error, 1, 0, "did not decompress file: %s", in);
+		g_set_error (error, ZIF_UTILS_ERROR, ZIF_UTILS_ERROR_FAILED,
+			     "did not decompress file: %s", in);
 		goto out;
 	}
 
@@ -410,6 +449,8 @@ out:
  * Decompress files into a directory
  *
  * Return value: %TRUE if the file was decompressed
+ *
+ * Since: 0.0.1
  **/
 gboolean
 zif_file_decompress (const gchar *in, const gchar *out, GCancellable *cancellable, ZifCompletion *completion, GError **error)
@@ -432,7 +473,8 @@ zif_file_decompress (const gchar *in, const gchar *out, GCancellable *cancellabl
 	}
 
 	/* no support */
-	g_set_error (error, 1, 0, "no support to decompress file: %s", in);
+	g_set_error (error, ZIF_UTILS_ERROR, ZIF_UTILS_ERROR_FAILED,
+		     "no support to decompress file: %s", in);
 out:
 	return ret;
 }
@@ -446,6 +488,8 @@ out:
  * Untar files into a directory
  *
  * Return value: %TRUE if the file was decompressed
+ *
+ * Since: 0.0.1
  **/
 gboolean
 zif_file_untar (const gchar *filename, const gchar *directory, GError **error)
@@ -464,7 +508,8 @@ zif_file_untar (const gchar *filename, const gchar *directory, GError **error)
 	/* save the PWD as we chdir to extract */
 	retcwd = getcwd (buf, PATH_MAX);
 	if (retcwd == NULL) {
-		g_set_error_literal (error, 1, 0, "failed to get cwd");
+		g_set_error_literal (error, ZIF_UTILS_ERROR, ZIF_UTILS_ERROR_FAILED,
+				     "failed to get cwd");
 		goto out;
 	}
 
@@ -476,14 +521,16 @@ zif_file_untar (const gchar *filename, const gchar *directory, GError **error)
 	/* open the tar file */
 	r = archive_read_open_file (arch, filename, ZIF_BUFFER_SIZE);
 	if (r) {
-		g_set_error (error, 1, 0, "cannot open: %s", archive_error_string (arch));
+		g_set_error (error, ZIF_UTILS_ERROR, ZIF_UTILS_ERROR_FAILED_TO_READ,
+			     "cannot open: %s", archive_error_string (arch));
 		goto out;
 	}
 
 	/* switch to our destination directory */
 	retval = chdir (directory);
 	if (retval != 0) {
-		g_set_error (error, 1, 0, "failed chdir to %s", directory);
+		g_set_error (error, ZIF_UTILS_ERROR, ZIF_UTILS_ERROR_FAILED,
+			     "failed chdir to %s", directory);
 		goto out;
 	}
 
@@ -493,12 +540,14 @@ zif_file_untar (const gchar *filename, const gchar *directory, GError **error)
 		if (r == ARCHIVE_EOF)
 			break;
 		if (r != ARCHIVE_OK) {
-			g_set_error (error, 1, 0, "cannot read header: %s", archive_error_string (arch));
+			g_set_error (error, ZIF_UTILS_ERROR, ZIF_UTILS_ERROR_FAILED,
+				     "cannot read header: %s", archive_error_string (arch));
 			goto out;
 		}
 		r = archive_read_extract (arch, entry, 0);
 		if (r != ARCHIVE_OK) {
-			g_set_error (error, 1, 0, "cannot extract: %s", archive_error_string (arch));
+			g_set_error (error, ZIF_UTILS_ERROR, ZIF_UTILS_ERROR_FAILED,
+				     "cannot extract: %s", archive_error_string (arch));
 			goto out;
 		}
 	}
@@ -527,6 +576,8 @@ out:
  * Finds the uncompressed filename.
  *
  * Return value: the uncompressed file name, e.g. /lib/dave.tar, use g_free() to free.
+ *
+ * Since: 0.0.1
  **/
 gchar *
 zif_file_get_uncompressed_name (const gchar *filename)
@@ -555,6 +606,8 @@ zif_file_get_uncompressed_name (const gchar *filename)
  * Finds out if the filename is compressed
  *
  * Return value: %TRUE if the file needs decompression
+ *
+ * Since: 0.0.1
  **/
 gboolean
 zif_file_is_compressed_name (const gchar *filename)
diff --git a/backends/yum/libzif/zif-utils.h b/backends/yum/libzif/zif-utils.h
index b33c73a..3bb474a 100644
--- a/backends/yum/libzif/zif-utils.h
+++ b/backends/yum/libzif/zif-utils.h
@@ -34,8 +34,19 @@
 
 G_BEGIN_DECLS
 
+#define ZIF_UTILS_ERROR	(zif_utils_error_quark ())
+
+typedef enum {
+	ZIF_UTILS_ERROR_FAILED,
+	ZIF_UTILS_ERROR_FAILED_TO_READ,
+	ZIF_UTILS_ERROR_FAILED_TO_WRITE,
+	ZIF_UTILS_ERROR_CANCELLED,
+	ZIF_UTILS_ERROR_LAST
+} ZifUtilsError;
+
 gboolean	 zif_init			(void);
 void		 zif_debug_crash		(void);
+GQuark		 zif_utils_error_quark		(void);
 void		 zif_list_print_array		(GPtrArray	*array);
 gchar		*zif_package_id_from_nevra	(const gchar	*name,
 						 const gchar	*epoch,
diff --git a/backends/yum/pk-backend-yum.c b/backends/yum/pk-backend-yum.c
index 7a6e7a8..0e21cb0 100644
--- a/backends/yum/pk-backend-yum.c
+++ b/backends/yum/pk-backend-yum.c
@@ -209,6 +209,360 @@ backend_unlock (PkBackend *backend)
 	return ret;
 }
 
+
+/**
+ * backend_add_package_array:
+ **/
+static gboolean
+backend_add_package_array (GPtrArray *array, GPtrArray *add)
+{
+	guint i;
+	ZifPackage *package;
+
+	for (i=0;i<add->len;i++) {
+		package = g_ptr_array_index (add, i);
+		g_ptr_array_add (array, g_object_ref (package));
+	}
+	return TRUE;
+}
+
+/**
+ * backend_filter_package_array_newest:
+ *
+ * This function needs to scale well, and be fast to process 50,000 packages in
+ * less than one second. If it looks overcomplicated, it's because it needs to
+ * be O(n) not O(n*n).
+ **/
+static gboolean
+backend_filter_package_array_newest (GPtrArray *array)
+{
+	gchar **split;
+	const gchar *package_id;
+	gboolean installed;
+	gchar *key;
+	GHashTable *hash;
+	gint retval;
+	guint i;
+	ZifPackage *found;
+	ZifPackage *package;
+
+	/* as an indexed hash table for speed */
+	hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref);
+
+	for (i=0; i<array->len; i++) {
+
+		/* get the current package */
+		package = g_ptr_array_index (array, i);
+		package_id = zif_package_get_id (package);
+		installed = zif_package_is_installed (package);
+
+		/* generate enough data to be specific */
+		split = pk_package_id_split (package_id);
+		key = g_strdup_printf ("%s-%s-%i", split[PK_PACKAGE_ID_NAME], split[PK_PACKAGE_ID_ARCH], installed);
+		g_strfreev (split);
+
+		/* we've not already come across this package */
+		found = g_hash_table_lookup (hash, key);
+		if (found == NULL) {
+			g_hash_table_insert (hash, key, g_object_ref (package));
+			continue;
+		}
+
+		/* compare one package vs the other package */
+		retval = zif_package_compare (package, found);
+
+		/* the package is older than the one we have stored */
+		if (retval <= 0) {
+			g_free (key);
+			g_object_unref (package);
+			g_ptr_array_remove (array, package);
+			continue;
+		}
+
+		/* the package is newer than what we have stored, delete the old store, and add this one */
+		g_hash_table_remove (hash, found);
+		g_hash_table_insert (hash, key, g_object_ref (package));
+	}
+
+	g_hash_table_unref (hash);
+	return TRUE;
+}
+
+/**
+ * backend_filter_package_array:
+ **/
+static GPtrArray *
+backend_filter_package_array (GPtrArray *array, PkBitfield filters)
+{
+	guint i;
+	ZifPackage *package;
+	GPtrArray *result = NULL;
+
+	result = g_ptr_array_new_with_free_func ((GDestroyNotify) g_object_unref);
+
+	/* pre-result */
+	for (i=0;i<array->len;i++) {
+		package = g_ptr_array_index (array, i);
+
+		/* installed */
+		if (pk_bitfield_contain (filters, PK_FILTER_ENUM_INSTALLED)) {
+			if (!zif_package_is_installed (package))
+				continue;
+		} else if (pk_bitfield_contain (filters, PK_FILTER_ENUM_NOT_INSTALLED)) {
+			if (zif_package_is_installed (package))
+				continue;
+		}
+
+		/* development */
+		if (pk_bitfield_contain (filters, PK_FILTER_ENUM_DEVELOPMENT)) {
+			if (!zif_package_is_devel (package))
+				continue;
+		} else if (pk_bitfield_contain (filters, PK_FILTER_ENUM_NOT_DEVELOPMENT)) {
+			if (zif_package_is_devel (package))
+				continue;
+		}
+
+		/* gui */
+		if (pk_bitfield_contain (filters, PK_FILTER_ENUM_GUI)) {
+			if (!zif_package_is_gui (package))
+				continue;
+		} else if (pk_bitfield_contain (filters, PK_FILTER_ENUM_NOT_GUI)) {
+			if (zif_package_is_gui (package))
+				continue;
+		}
+
+		/* free */
+		if (pk_bitfield_contain (filters, PK_FILTER_ENUM_FREE)) {
+			if (!zif_package_is_free (package))
+				continue;
+		} else if (pk_bitfield_contain (filters, PK_FILTER_ENUM_NOT_FREE)) {
+			if (zif_package_is_free (package))
+				continue;
+		}
+
+		/* arch */
+		if (pk_bitfield_contain (filters, PK_FILTER_ENUM_ARCH)) {
+			if (!zif_package_is_native (package))
+				continue;
+		} else if (pk_bitfield_contain (filters, PK_FILTER_ENUM_NOT_ARCH)) {
+			if (zif_package_is_native (package))
+				continue;
+		}
+
+		/* add to array so we can post process */
+		g_ptr_array_add (result, g_object_ref (package));
+	}
+
+	/* do newest filtering */
+	if (pk_bitfield_contain (filters, PK_FILTER_ENUM_NEWEST))
+		backend_filter_package_array_newest (result);
+
+	return result;
+}
+
+/**
+ * backend_emit_package_array:
+ **/
+static gboolean
+backend_emit_package_array (PkBackend *backend, GPtrArray *array)
+{
+	guint i;
+	gboolean installed;
+	PkInfoEnum info;
+	const gchar *package_id;
+	ZifString *summary;
+	ZifPackage *package;
+
+	g_return_val_if_fail (array != NULL, FALSE);
+
+	for (i=0; i<array->len; i++) {
+		package = g_ptr_array_index (array, i);
+		installed = zif_package_is_installed (package);
+		package_id = zif_package_get_package_id (package);
+		summary = zif_package_get_summary (package, NULL);
+		info = installed ? PK_INFO_ENUM_INSTALLED : PK_INFO_ENUM_AVAILABLE;
+		/* hack until we have update details */
+		if (strstr (package_id, "update") != NULL)
+			info = PK_INFO_ENUM_NORMAL;
+		pk_backend_package (backend, info, package_id, zif_string_get_value (summary));
+		zif_string_unref (summary);
+	}
+	return TRUE;
+}
+
+/**
+ * backend_search_thread_get_array:
+ */
+static GPtrArray *
+backend_search_thread_get_array (PkBackend *backend, GPtrArray *store_array, const gchar *search, ZifCompletion *completion, GError **error)
+{
+	PkRoleEnum role;
+	GPtrArray *array = NULL;
+
+	role = pk_backend_get_role (backend);
+	if (role == PK_ROLE_ENUM_SEARCH_NAME)
+		array = zif_store_array_search_name (store_array, search, priv->cancellable, completion, error);
+	else if (role == PK_ROLE_ENUM_SEARCH_DETAILS)
+		array = zif_store_array_search_details (store_array, search, priv->cancellable, completion, error);
+	else if (role == PK_ROLE_ENUM_SEARCH_GROUP)
+		array = zif_store_array_search_group (store_array, search, priv->cancellable, completion, error);
+	else if (role == PK_ROLE_ENUM_SEARCH_FILE)
+		array = zif_store_array_search_file (store_array, search, priv->cancellable, completion, error);
+	else if (role == PK_ROLE_ENUM_RESOLVE)
+		array = zif_store_array_resolve (store_array, search, priv->cancellable, completion, error);
+	else if (role == PK_ROLE_ENUM_WHAT_PROVIDES)
+		array = zif_store_array_what_provides (store_array, search, priv->cancellable, completion, error);
+	else
+		g_set_error (error, 1, 0, "does not support: %s", pk_role_enum_to_string (role));
+	return array;
+}
+
+/**
+ * backend_get_default_store_array_for_filter:
+ */
+static GPtrArray *
+backend_get_default_store_array_for_filter (PkBackend *backend, PkBitfield filters, ZifCompletion *completion, GError **error)
+{
+	GPtrArray *store_array;
+	ZifStore *store;
+	GPtrArray *array;
+	GError *error_local = NULL;
+
+	store_array = zif_store_array_new ();
+
+	/* add local packages to the store_array */
+	if (!pk_bitfield_contain (filters, PK_FILTER_ENUM_NOT_INSTALLED)) {
+		store = ZIF_STORE (zif_store_local_new ());
+		zif_store_array_add_store (store_array, store);
+		g_object_unref (store);
+	}
+
+	/* add remote packages to the store_array */
+	if (!pk_bitfield_contain (filters, PK_FILTER_ENUM_INSTALLED)) {
+		array = zif_repos_get_stores_enabled (priv->repos, priv->cancellable, completion, &error_local);
+		if (array == NULL) {
+			g_set_error (error, 1, 0, "failed to get enabled stores: %s", error_local->message);
+			g_error_free (error_local);
+			g_ptr_array_unref (store_array);
+			store_array = NULL;
+			goto out;
+		}
+		zif_store_array_add_stores (store_array, array);
+		g_ptr_array_unref (array);
+	}
+out:
+	return store_array;
+}
+
+/**
+ * backend_search_thread:
+ */
+static gboolean
+backend_search_thread (PkBackend *backend)
+{
+	gboolean ret;
+	GPtrArray *store_array = NULL;
+	GPtrArray *array = NULL;
+	GPtrArray *result;
+	PkBitfield filters;
+	PkRoleEnum role;
+	ZifCompletion *completion_local;
+	ZifCompletion *completion_loop;
+	GError *error = NULL;
+	gchar **search;
+	guint i;
+	filters = (PkBitfield) pk_backend_get_uint (backend, "filters");
+	role = pk_backend_get_role (backend);
+
+	/* get lock */
+	ret = backend_get_lock (backend);
+	if (!ret) {
+		egg_warning ("failed to get lock");
+		goto out;
+	}
+
+	/* set the network state */
+	backend_setup_network (backend);
+
+	pk_backend_set_status (backend, PK_STATUS_ENUM_QUERY);
+	pk_backend_set_percentage (backend, 0);
+
+	/* setup completion */
+	zif_completion_reset (priv->completion);
+	zif_completion_set_number_steps (priv->completion, 3);
+
+	/* get default store_array */
+	completion_local = zif_completion_get_child (priv->completion);
+	store_array = backend_get_default_store_array_for_filter (backend, filters, completion_local, &error);
+	if (store_array == NULL) {
+		pk_backend_error_code (backend, PK_ERROR_ENUM_INTERNAL_ERROR, "failed to get stores: %s", error->message);
+		g_error_free (error);
+		goto out;
+	}
+
+	/* this section done */
+	zif_completion_done (priv->completion);
+
+	/* do get action */
+	if (role == PK_ROLE_ENUM_GET_PACKAGES) {
+		completion_local = zif_completion_get_child (priv->completion);
+		array = zif_store_array_get_packages (store_array, priv->cancellable, completion_local, &error);
+		if (array == NULL) {
+			pk_backend_error_code (backend, PK_ERROR_ENUM_INTERNAL_ERROR, "failed to get packages: %s", error->message);
+			g_error_free (error);
+			goto out;
+		}
+	} else {
+		/* treat these all the same */
+		search = pk_backend_get_strv (backend, "search");
+		array = g_ptr_array_new_with_free_func ((GDestroyNotify) g_object_unref);
+
+		completion_local = zif_completion_get_child (priv->completion);
+		zif_completion_set_number_steps (completion_local, g_strv_length (search));
+
+		/* do OR search */
+		for (i=0; search[i] != NULL; i++) {
+			/* make loop deeper */
+			completion_loop = zif_completion_get_child (completion_local);
+			result = backend_search_thread_get_array (backend, store_array, search[i], completion_loop, &error);
+			if (result == NULL) {
+				pk_backend_error_code (backend, PK_ERROR_ENUM_INTERNAL_ERROR, "failed to search: %s", error->message);
+				g_error_free (error);
+				goto out;
+			}
+
+			/* this section done */
+			zif_completion_done (completion_local);
+
+			backend_add_package_array (array, result);
+			g_ptr_array_unref (result);
+		}
+	}
+
+	/* this section done */
+	zif_completion_done (priv->completion);
+
+	/* filter */
+	result = backend_filter_package_array (array, filters);
+
+	/* this section done */
+	zif_completion_done (priv->completion);
+
+	/* done */
+	pk_backend_set_percentage (backend, 100);
+
+	/* emit */
+	backend_emit_package_array (backend, result);
+out:
+	if (store_array != NULL)
+		g_ptr_array_unref (store_array);
+	if (array != NULL)
+		g_ptr_array_unref (array);
+	backend_unlock (backend);
+	pk_backend_finished (backend);
+	return TRUE;
+}
+
 /**
  * backend_initialize:
  * This should only be run once per backend load, i.e. not every transaction
@@ -516,7 +870,6 @@ backend_get_depends (PkBackend *backend, PkBitfield filters, gchar **package_ids
 	g_free (package_ids_temp);
 }
 
-
 /**
  * backend_get_details_thread:
  */
@@ -537,6 +890,7 @@ backend_get_details_thread (PkBackend *backend)
 	ZifString *url;
 	PkGroupEnum group;
 	guint64 size;
+	PkBitfield filters = PK_FILTER_ENUM_UNKNOWN;
 
 	/* get lock */
 	ret = backend_get_lock (backend);
@@ -556,14 +910,14 @@ backend_get_details_thread (PkBackend *backend)
 
 	/* find all the packages */
 	completion_local = zif_completion_get_child (priv->completion);
-//	store_array = backend_get_default_store_array_for_filter (backend, PK_FILTER_ENUM_UNKNOWN, completion_local);
-{
-	ZifStore *store;
-	store = ZIF_STORE (zif_store_local_new ());
-	store_array = zif_store_array_new ();
-	zif_store_array_add_store (store_array, store);
-	g_object_unref (store);
-}
+	if (backend_is_all_installed (package_ids))
+		pk_bitfield_add (filters, PK_FILTER_ENUM_INSTALLED);
+	store_array = backend_get_default_store_array_for_filter (backend, filters, completion_local, &error);
+	if (store_array == NULL) {
+		pk_backend_error_code (backend, PK_ERROR_ENUM_INTERNAL_ERROR, "failed to get stores: %s", error->message);
+		g_error_free (error);
+		goto out;
+	}
 
 	/* this section done */
 	zif_completion_done (priv->completion);
@@ -618,19 +972,15 @@ out:
 static void
 backend_get_details (PkBackend *backend, gchar **package_ids)
 {
-	gchar *package_ids_temp;
-	gboolean ret;
-
 	/* check if we can use zif */
-	ret = backend_is_all_installed (package_ids);
-	if (ret && use_zif) {
-		pk_backend_thread_create (backend, backend_get_details_thread);
+	if (!use_zif) {
+		gchar *package_ids_temp;
+		package_ids_temp = pk_package_ids_to_string (package_ids);
+		pk_backend_spawn_helper (priv->spawn, "yumBackend.py", "get-details", package_ids_temp, NULL);
+		g_free (package_ids_temp);
 		return;
 	}
-
-	package_ids_temp = pk_package_ids_to_string (package_ids);
-	pk_backend_spawn_helper (priv->spawn, "yumBackend.py", "get-details", package_ids_temp, NULL);
-	g_free (package_ids_temp);
+	pk_backend_thread_create (backend, backend_get_details_thread);
 }
 
 /**
@@ -772,6 +1122,7 @@ backend_get_files_thread (PkBackend *backend)
 	GError *error = NULL;
 	const gchar *file;
 	GString *files_str;
+	PkBitfield filters = PK_FILTER_ENUM_UNKNOWN;
 
 	/* reset */
 	backend_profile (NULL);
@@ -797,14 +1148,14 @@ backend_get_files_thread (PkBackend *backend)
 
 	/* find all the packages */
 	completion_local = zif_completion_get_child (priv->completion);
-//	store_array = backend_get_default_store_array_for_filter (backend, PK_FILTER_ENUM_UNKNOWN, completion_local);
-{
-	ZifStore *store;
-	store = ZIF_STORE (zif_store_local_new ());
-	store_array = zif_store_array_new ();
-	zif_store_array_add_store (store_array, store);
-	g_object_unref (store);
-}
+	if (backend_is_all_installed (package_ids))
+		pk_bitfield_add (filters, PK_FILTER_ENUM_INSTALLED);
+	store_array = backend_get_default_store_array_for_filter (backend, filters, completion_local, &error);
+	if (store_array == NULL) {
+		pk_backend_error_code (backend, PK_ERROR_ENUM_INTERNAL_ERROR, "failed to get stores: %s", error->message);
+		g_error_free (error);
+		goto out;
+	}
 
 	/* profile */
 	backend_profile ("add local");
@@ -915,10 +1266,15 @@ backend_get_updates (PkBackend *backend, PkBitfield filters)
 static void
 backend_get_packages (PkBackend *backend, PkBitfield filters)
 {
-	gchar *filters_text;
-	filters_text = pk_filter_bitfield_to_string (filters);
-	pk_backend_spawn_helper (priv->spawn, "yumBackend.py", "get-packages", filters_text, NULL);
-	g_free (filters_text);
+	/* it seems some people are not ready for the awesomeness */
+	if (!use_zif) {
+		gchar *filters_text;
+		filters_text = pk_filter_bitfield_to_string (filters);
+		pk_backend_spawn_helper (priv->spawn, "yumBackend.py", "get-packages", filters_text, NULL);
+		g_free (filters_text);
+		return;
+	}
+	pk_backend_thread_create (backend, backend_search_thread);
 }
 
 /**
@@ -1052,13 +1408,18 @@ backend_remove_packages (PkBackend *backend, gchar **package_ids, gboolean allow
 static void
 backend_search_details (PkBackend *backend, PkBitfield filters, gchar **values)
 {
-	gchar *filters_text;
-	gchar *search;
-	filters_text = pk_filter_bitfield_to_string (filters);
-	search = g_strjoinv ("&", values);
-	pk_backend_spawn_helper (priv->spawn, "yumBackend.py", "search-details", filters_text, search, NULL);
-	g_free (filters_text);
-	g_free (search);
+	/* it seems some people are not ready for the awesomeness */
+	if (!use_zif) {
+		gchar *filters_text;
+		gchar *search;
+		filters_text = pk_filter_bitfield_to_string (filters);
+		search = g_strjoinv ("&", values);
+		pk_backend_spawn_helper (priv->spawn, "yumBackend.py", "search-details", filters_text, search, NULL);
+		g_free (filters_text);
+		g_free (search);
+		return;
+	}
+	pk_backend_thread_create (backend, backend_search_thread);
 }
 
 /**
@@ -1067,13 +1428,18 @@ backend_search_details (PkBackend *backend, PkBitfield filters, gchar **values)
 static void
 backend_search_files (PkBackend *backend, PkBitfield filters, gchar **values)
 {
-	gchar *filters_text;
-	gchar *search;
-	filters_text = pk_filter_bitfield_to_string (filters);
-	search = g_strjoinv ("&", values);
-	pk_backend_spawn_helper (priv->spawn, "yumBackend.py", "search-file", filters_text, search, NULL);
-	g_free (filters_text);
-	g_free (search);
+	/* it seems some people are not ready for the awesomeness */
+	if (!use_zif) {
+		gchar *filters_text;
+		gchar *search;
+		filters_text = pk_filter_bitfield_to_string (filters);
+		search = g_strjoinv ("&", values);
+		pk_backend_spawn_helper (priv->spawn, "yumBackend.py", "search-file", filters_text, search, NULL);
+		g_free (filters_text);
+		g_free (search);
+		return;
+	}
+	pk_backend_thread_create (backend, backend_search_thread);
 }
 
 /**
@@ -1082,13 +1448,18 @@ backend_search_files (PkBackend *backend, PkBitfield filters, gchar **values)
 static void
 backend_search_groups (PkBackend *backend, PkBitfield filters, gchar **values)
 {
-	gchar *filters_text;
-	gchar *search;
-	filters_text = pk_filter_bitfield_to_string (filters);
-	search = g_strjoinv ("&", values);
-	pk_backend_spawn_helper (priv->spawn, "yumBackend.py", "search-group", filters_text, search, NULL);
-	g_free (filters_text);
-	g_free (search);
+	/* it seems some people are not ready for the awesomeness */
+	if (!use_zif) {
+		gchar *filters_text;
+		gchar *search;
+		filters_text = pk_filter_bitfield_to_string (filters);
+		search = g_strjoinv ("&", values);
+		pk_backend_spawn_helper (priv->spawn, "yumBackend.py", "search-group", filters_text, search, NULL);
+		g_free (filters_text);
+		g_free (search);
+		return;
+	}
+	pk_backend_thread_create (backend, backend_search_thread);
 }
 
 /**
@@ -1097,13 +1468,18 @@ backend_search_groups (PkBackend *backend, PkBitfield filters, gchar **values)
 static void
 backend_search_names (PkBackend *backend, PkBitfield filters, gchar **values)
 {
-	gchar *filters_text;
-	gchar *search;
-	filters_text = pk_filter_bitfield_to_string (filters);
-	search = g_strjoinv ("&", values);
-	pk_backend_spawn_helper (priv->spawn, "yumBackend.py", "search-name", filters_text, search, NULL);
-	g_free (filters_text);
-	g_free (search);
+	/* it seems some people are not ready for the awesomeness */
+	if (!use_zif) {
+		gchar *filters_text;
+		gchar *search;
+		filters_text = pk_filter_bitfield_to_string (filters);
+		search = g_strjoinv ("&", values);
+		pk_backend_spawn_helper (priv->spawn, "yumBackend.py", "search-name", filters_text, search, NULL);
+		g_free (filters_text);
+		g_free (search);
+		return;
+	}
+	pk_backend_thread_create (backend, backend_search_thread);
 }
 
 /**
@@ -1133,15 +1509,21 @@ backend_update_system (PkBackend *backend, gboolean only_trusted)
  * pk_backend_resolve:
  */
 static void
-backend_resolve (PkBackend *backend, PkBitfield filters, gchar **package_ids)
+backend_resolve (PkBackend *backend, PkBitfield filters, gchar **packages)
 {
-	gchar *filters_text;
-	gchar *package_ids_temp;
-	filters_text = pk_filter_bitfield_to_string (filters);
-	package_ids_temp = pk_package_ids_to_string (package_ids);
-	pk_backend_spawn_helper (priv->spawn, "yumBackend.py", "resolve", filters_text, package_ids_temp, NULL);
-	g_free (filters_text);
-	g_free (package_ids_temp);
+	/* it seems some people are not ready for the awesomeness */
+	if (!use_zif) {
+		gchar *filters_text;
+		gchar *package_ids_temp;
+		filters_text = pk_filter_bitfield_to_string (filters);
+		package_ids_temp = pk_package_ids_to_string (packages);
+		pk_backend_spawn_helper (priv->spawn, "yumBackend.py", "resolve", filters_text, package_ids_temp, NULL);
+		g_free (filters_text);
+		g_free (package_ids_temp);
+		return;
+	}
+	pk_backend_set_strv (backend, "search", packages);
+	pk_backend_thread_create (backend, backend_search_thread);
 }
 
 /**
@@ -1476,7 +1858,6 @@ backend_get_unique_categories (PkBackend *backend, GPtrArray *stores, ZifComplet
 			if (g_strcmp0 (parent_id_tmp, parent_id) == 0 &&
 			    g_strcmp0 (cat_id_tmp, cat_id) == 0) {
 				egg_warning ("duplicate %s-%s", parent_id, cat_id);
-				g_object_unref (obj_tmp);
 				g_ptr_array_remove_index (array, j);
 			}
 			g_free (parent_id_tmp);
commit a048884d3e8f4aebf0f657aa9af45f9b9426c5a4
Author: shnurapet <shnurapet at fedoraproject.org>
Date:   Wed Mar 10 21:48:06 2010 +0000

    Sending translation for Russian

diff --git a/po/ru.po b/po/ru.po
index 51ed2a3..886372f 100644
--- a/po/ru.po
+++ b/po/ru.po
@@ -8,6 +8,7 @@
 # Ivan Ignatyev <ivan.ignatyev at auditory.ru>, 2008, 2009.
 # Alexey Kostyuk <unitoff at gmail.com>, 2009.
 # Yulia <ypoyarko at redhat.com>, 2009.
+# Misha Shnurapet <zayzayats at yandex.ru>, 2010.
 msgid ""
 msgstr ""
 "Project-Id-Version: ru\n"
commit a6b9a20490739414b42c68dc49b8b177425a1f73
Author: shnurapet <shnurapet at fedoraproject.org>
Date:   Wed Mar 10 21:14:40 2010 +0000

    Sending translation for Russian

diff --git a/po/ru.po b/po/ru.po
index 8006bc4..51ed2a3 100644
--- a/po/ru.po
+++ b/po/ru.po
@@ -12,21 +12,22 @@ msgid ""
 msgstr ""
 "Project-Id-Version: ru\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2009-12-09 02:27+0000\n"
-"PO-Revision-Date: 2009-12-09 17:12+1100\n"
-"Last-Translator: Yulia <ypoyarko at redhat.com>\n"
+"POT-Creation-Date: 2010-03-10 17:38+0000\n"
+"PO-Revision-Date: 2010-03-11 05:01+0800\n"
+"Last-Translator: Misha Shnurapet <zayzayats at yandex.ru>\n"
 "Language-Team: Russian\n"
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
 "X-Generator: KBabel 1.11.4\n"
-"Plural-Forms:  nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n"
+"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n"
 
 #. TRANSLATORS: this is an atomic transaction
 #. TRANSLATORS: the role is the point of the transaction, e.g. update-system
-#: ../client/pk-console.c:175 ../client/pk-console.c:597
+#: ../client/pk-console.c:175
+#: ../client/pk-console.c:597
 msgid "Transaction"
-msgstr "Транзакция"
+msgstr "Операция"
 
 #. TRANSLATORS: this is the time the transaction was started in system timezone
 #: ../client/pk-console.c:177
@@ -48,7 +49,8 @@ msgstr "Ложь"
 
 #. TRANSLATORS: this is the transactions role, e.g. "update-system"
 #. TRANSLATORS: the trasaction role, e.g. update-system
-#: ../client/pk-console.c:181 ../src/pk-polkit-action-lookup.c:332
+#: ../client/pk-console.c:181
+#: ../src/pk-polkit-action-lookup.c:332
 msgid "Role"
 msgstr "Роль"
 
@@ -63,7 +65,8 @@ msgstr "(секунды)"
 
 #. TRANSLATORS: this is The command line used to do the action
 #. TRANSLATORS: the command line of the thing that wants the authentication
-#: ../client/pk-console.c:190 ../src/pk-polkit-action-lookup.c:346
+#: ../client/pk-console.c:190
+#: ../src/pk-polkit-action-lookup.c:346
 msgid "Command line"
 msgstr "Командная строка"
 
@@ -98,11 +101,12 @@ msgstr "Дистрибутив"
 #. TRANSLATORS: this is type of update, stable or testing
 #: ../client/pk-console.c:250
 msgid "Type"
-msgstr "Тип"
+msgstr "Вид"
 
 #. TRANSLATORS: this is any summary text describing the upgrade
 #. TRANSLATORS: this is the summary of the group
-#: ../client/pk-console.c:252 ../client/pk-console.c:291
+#: ../client/pk-console.c:252
+#: ../client/pk-console.c:291
 msgid "Summary"
 msgstr "Суммарно"
 
@@ -129,19 +133,20 @@ msgstr "Имя"
 #. TRANSLATORS: this is preferred icon for the group
 #: ../client/pk-console.c:294
 msgid "Icon"
-msgstr "Иконка"
+msgstr "Значок"
 
 #. TRANSLATORS: this is a header for the package that can be updated
 #: ../client/pk-console.c:340
 msgid "Details about the update:"
-msgstr "Подробная информация об обновлении:"
+msgstr "Подробности об обновлении:"
 
 #. TRANSLATORS: details about the update, package name and version
 #. TRANSLATORS: the package that is being processed
 #. TRANSLATORS: the package that is not signed by a known key
 #. TRANSLATORS: the package name that was trying to be installed
 #. TRANSLATORS: title, the names of the packages that the method is processing
-#: ../client/pk-console.c:346 ../client/pk-console.c:616
+#: ../client/pk-console.c:346
+#: ../client/pk-console.c:616
 #: ../lib/packagekit-glib2/pk-task-text.c:126
 #: ../lib/packagekit-glib2/pk-task-text.c:208
 #: ../src/pk-polkit-action-lookup.c:357
@@ -163,7 +168,8 @@ msgstr "Устаревшие"
 
 #. TRANSLATORS: details about the update, the vendor URLs
 #. TRANSLATORS: the vendor (e.g. vmware) that is providing the EULA
-#: ../client/pk-console.c:357 ../lib/packagekit-glib2/pk-task-text.c:211
+#: ../client/pk-console.c:357
+#: ../lib/packagekit-glib2/pk-task-text.c:211
 msgid "Vendor"
 msgstr "Поставщик"
 
@@ -185,7 +191,7 @@ msgstr "Перезапуск"
 #. TRANSLATORS: details about the update, any description of the update
 #: ../client/pk-console.c:373
 msgid "Update text"
-msgstr "Подробности обновления"
+msgstr "Описание"
 
 #. TRANSLATORS: details about the update, the changelog for the package
 #: ../client/pk-console.c:377
@@ -195,7 +201,7 @@ msgstr "Изменения"
 #. TRANSLATORS: details about the update, the ongoing state of the update
 #: ../client/pk-console.c:381
 msgid "State"
-msgstr "Статус"
+msgstr "Состояние"
 
 #. TRANSLATORS: details about the update, date the update was issued
 #: ../client/pk-console.c:385
@@ -204,7 +210,8 @@ msgstr "Выпущено"
 
 #. TRANSLATORS: details about the update, date the update was updated
 #. TRANSLATORS: The action of the package, in past tense
-#: ../client/pk-console.c:389 ../lib/packagekit-glib2/pk-console-shared.c:510
+#: ../client/pk-console.c:389
+#: ../lib/packagekit-glib2/pk-console-shared.c:510
 msgid "Updated"
 msgstr "Обновлено"
 
@@ -231,12 +238,12 @@ msgstr "Необходим перезапуск сеанса:"
 #. TRANSLATORS: a package requires the system to be restarted due to a security update
 #: ../client/pk-console.c:466
 msgid "System restart (security) required by:"
-msgstr "Запрос перезапуска системы (безопасность):"
+msgstr "Необходим перезапуск системы (безопасность) для:"
 
 #. TRANSLATORS: a package requires the session to be restarted due to a security update
 #: ../client/pk-console.c:469
 msgid "Session restart (security) required:"
-msgstr "Запрос перезапуска сессии (безопасность):"
+msgstr "Необходим перезапуск сеанса (безопасность):"
 
 #. TRANSLATORS: a package requires the application to be restarted
 #: ../client/pk-console.c:472
@@ -271,367 +278,377 @@ msgstr "Проценты"
 #. TRANSLATORS: the status of the transaction (e.g. downloading)
 #: ../client/pk-console.c:650
 msgid "Status"
-msgstr "Статус"
+msgstr "Состояние"
 
 #. TRANSLATORS: the results from the transaction
-#: ../client/pk-console.c:678
+#: ../client/pk-console.c:679
 msgid "Results:"
 msgstr "Результаты:"
 
+# «Фатальная» — это смертельная или роковая? :)
 #. TRANSLATORS: we failed to get any results, which is pretty fatal in my book
-#: ../client/pk-console.c:685
+#: ../client/pk-console.c:686
 msgid "Fatal error"
-msgstr "Фатальная ошибка"
+msgstr "Серьезная ошибка"
 
 #. TRANSLATORS: the transaction failed in a way we could not expect
-#: ../client/pk-console.c:694
+#: ../client/pk-console.c:695
 #: ../contrib/command-not-found/pk-command-not-found.c:432
 #: ../contrib/command-not-found/pk-command-not-found.c:603
 msgid "The transaction failed"
-msgstr "Сбой операции"
+msgstr "Действие не удалось"
 
 #. TRANSLATORS: print a message when there are no updates
-#: ../client/pk-console.c:721
+#: ../client/pk-console.c:726
 msgid "There are no updates available at this time."
-msgstr "На данный момент нет обновлений."
+msgstr "В данный момент обновления отсутствуют."
+
+#: ../client/pk-console.c:749
+msgid "There are no upgrades available at this time."
+msgstr "В данный момент обновления отсутствуют."
 
 #. TRANSLATORS: a package needs to restart their system
-#: ../client/pk-console.c:808
+#: ../client/pk-console.c:816
 msgid "Please restart the computer to complete the update."
 msgstr "Перезагрузите компьютер, чтобы завершить обновление."
 
 #. TRANSLATORS: a package needs to restart the session
-#: ../client/pk-console.c:811
+#: ../client/pk-console.c:819
 msgid "Please logout and login to complete the update."
-msgstr "Пожалуйста, выйдите из системы и войдите вновь, чтобы завершить обновление."
+msgstr "Пожалуйста, перезайдите в систему, чтобы завершить обновление."
 
 #. TRANSLATORS: a package needs to restart their system (due to security)
-#: ../client/pk-console.c:814
-msgid ""
-"Please restart the computer to complete the update as important security "
-"updates have been installed."
-msgstr ""
-"Пожалуйста, перезагрузите компьютер, чтобы завершить установку обновления "
-"безопасности."
+#: ../client/pk-console.c:822
+msgid "Please restart the computer to complete the update as important security updates have been installed."
+msgstr "Пожалуйста, перезагрузите компьютер, чтобы завершить установку обновления безопасности."
 
 #. TRANSLATORS: a package needs to restart the session (due to security)
-#: ../client/pk-console.c:817
-msgid ""
-"Please logout and login to complete the update as important security updates "
-"have been installed."
-msgstr ""
-"Пожалуйста, выйдите из системы и войдите вновь, чтобы завершить установку "
-"обновления безопасности."
+#: ../client/pk-console.c:825
+msgid "Please logout and login to complete the update as important security updates have been installed."
+msgstr "Пожалуйста, перезайдите в систему, чтобы завершить установку обновления безопасности."
+
+#. TRANSLATORS: The user used 'pkcon install dave.rpm' rather than 'pkcon install-local dave.rpm'
+#: ../client/pk-console.c:851
+#, c-format
+msgid "Extected package name, actually got file. Try using 'pkcon install-local %s' instead."
+msgstr "Вместо названия пакета получено имя файла. Используйте 'pkcon install-local %s'."
 
 #. TRANSLATORS: There was an error getting the list of files for the package. The detailed error follows
-#: ../client/pk-console.c:840
+#: ../client/pk-console.c:859
 #, c-format
 msgid "This tool could not find any available package: %s"
-msgstr "Этот инструмент не нашёл доступный пакет: %s"
+msgstr "Не найдено доступного пакета: %s"
 
 #. TRANSLATORS: There was an error getting the list of files for the package. The detailed error follows
-#: ../client/pk-console.c:868
+#: ../client/pk-console.c:887
 #, c-format
 msgid "This tool could not find the installed package: %s"
-msgstr "Этот инструмент не нашёл установленный пакет: %s"
+msgstr "Не найдено установленного пакета: %s"
 
 #. TRANSLATORS: There was an error getting the list of files for the package. The detailed error follows
-#: ../client/pk-console.c:896 ../client/pk-console.c:924
+#: ../client/pk-console.c:915
+#: ../client/pk-console.c:943
 #, c-format
 msgid "This tool could not find the package: %s"
-msgstr "Этот инструмент не нашёл пакет: %s"
+msgstr "Невозможно найти пакет: %s"
 
 #. TRANSLATORS: There was an error getting the list of files for the package. The detailed error follows
 #. TRANSLATORS: There was an error getting the dependencies for the package. The detailed error follows
 #. TRANSLATORS: There was an error getting the details about the package. The detailed error follows
 #. TRANSLATORS: The package name was not found in any software sources. The detailed error follows
-#: ../client/pk-console.c:952 ../client/pk-console.c:980
-#: ../client/pk-console.c:1008 ../client/pk-console.c:1036
-#: ../client/pk-console.c:1064
+#: ../client/pk-console.c:971
+#: ../client/pk-console.c:999
+#: ../client/pk-console.c:1027
+#: ../client/pk-console.c:1055
+#: ../client/pk-console.c:1083
 #, c-format
 msgid "This tool could not find all the packages: %s"
-msgstr "Этот инструмент не нашёл все пакеты: %s"
+msgstr "Невозможно найти все пакеты: %s"
 
 #. TRANSLATORS: This is when the daemon crashed, and we are up shit creek without a paddle
-#: ../client/pk-console.c:1093
+#: ../client/pk-console.c:1112
 msgid "The daemon crashed mid-transaction!"
-msgstr "Демон сломался в середине транзакции!"
+msgstr "Служба рухнула в ходе выполнения!"
 
 #. TRANSLATORS: This is the header to the --help menu
-#: ../client/pk-console.c:1127
+#: ../client/pk-console.c:1146
 msgid "PackageKit Console Interface"
-msgstr "Интерфейс консоли PackageKit"
+msgstr "Консольный интерфейс PackageKit"
 
 #. these are commands we can use with pkcon
-#: ../client/pk-console.c:1129
+#: ../client/pk-console.c:1148
 msgid "Subcommands:"
 msgstr "Подкоманды:"
 
 #. TRANSLATORS: we keep a database updated with the time that an action was last executed
-#: ../client/pk-console.c:1208
+#: ../client/pk-console.c:1227
 msgid "Failed to get the time since this action was last completed"
-msgstr "Не удалось получить время, с тех пор как это действие было в последний раз завершено"
+msgstr "Неизвестно, как давно было совершено это действие"
 
 #. TRANSLATORS: command line argument, just show the version string
-#: ../client/pk-console.c:1244 ../client/pk-monitor.c:280
+#: ../client/pk-console.c:1263
+#: ../client/pk-monitor.c:306
 msgid "Show the program version and exit"
 msgstr "Показать версию программы и выйти"
 
 #. TRANSLATORS: command line argument, use a filter to narrow down results
-#: ../client/pk-console.c:1247
+#: ../client/pk-console.c:1266
 msgid "Set the filter, e.g. installed"
-msgstr "Определить фильтр, к примеру, установленные программы"
+msgstr "Задать фильтр, к примеру, на установленные"
 
 #. TRANSLATORS: command line argument, work asynchronously
-#: ../client/pk-console.c:1250
+#: ../client/pk-console.c:1269
 msgid "Exit without waiting for actions to complete"
 msgstr "Выйти, не ожидая завершения задач"
 
 #. command line argument, do we ask questions
-#: ../client/pk-console.c:1253
+#: ../client/pk-console.c:1272
 #: ../contrib/debuginfo-install/pk-debuginfo-install.c:527
 msgid "Install the packages without asking for confirmation"
-msgstr "Установить пакеты без запроса подтверждения"
+msgstr "Установить пакеты, не спрашивая подтверждения"
 
 #. TRANSLATORS: command line argument, this command is not a priority
-#: ../client/pk-console.c:1256
+#: ../client/pk-console.c:1275
 msgid "Run the command using idle network bandwidth and also using less power"
-msgstr "Выполнить команду, используя свободные ресурсы полосы пропускания и минимум энергии"
+msgstr "Выполнить команду, используя свободную часть канала, и при меньшей энергии"
 
 #. TRANSLATORS: command line argument, just output without fancy formatting
-#: ../client/pk-console.c:1259
+#: ../client/pk-console.c:1278
 msgid "Print to screen a machine readable output, rather than using animated widgets"
 msgstr "Вывести на экран в простом формате без анимации элементов"
 
 #. TRANSLATORS: we failed to contact the daemon
-#: ../client/pk-console.c:1281
+#: ../client/pk-console.c:1300
 msgid "Failed to contact PackageKit"
 msgstr "Не удалось соединиться с PackageKit"
 
 #. TRANSLATORS: The user specified an incorrect filter
-#: ../client/pk-console.c:1339
+#: ../client/pk-console.c:1358
 msgid "The filter specified was invalid"
 msgstr "Указанный фильтр не верен"
 
 #. TRANSLATORS: a search type can be name, details, file, etc
-#: ../client/pk-console.c:1358
+#: ../client/pk-console.c:1377
 msgid "A search type is required, e.g. name"
-msgstr "Необходимо ввести поисковый запрос, например имя пакета"
+msgstr "Укажите вид поиска, например, по имени"
 
 #. TRANSLATORS: the user needs to provide a search term
-#: ../client/pk-console.c:1365 ../client/pk-console.c:1377
-#: ../client/pk-console.c:1389 ../client/pk-console.c:1401
+#: ../client/pk-console.c:1384
+#: ../client/pk-console.c:1396
+#: ../client/pk-console.c:1408
+#: ../client/pk-console.c:1420
 msgid "A search term is required"
-msgstr "Необходим поисковый термин"
+msgstr "Необходимо поисковое слово"
 
 #. TRANSLATORS: the search type was provided, but invalid
-#: ../client/pk-console.c:1411
+#: ../client/pk-console.c:1430
 msgid "Invalid search type"
-msgstr "Неверный тип поиска"
+msgstr "Неверный вид поиска"
 
 #. TRANSLATORS: the user did not specify what they wanted to install
-#: ../client/pk-console.c:1417
+#: ../client/pk-console.c:1436
 msgid "A package name to install is required"
-msgstr "Запрос названия пакета для установки"
+msgstr "Необходимо название устанавливаемого пакета"
 
 #. TRANSLATORS: the user did not specify what they wanted to install
-#: ../client/pk-console.c:1426
+#: ../client/pk-console.c:1445
 msgid "A filename to install is required"
-msgstr "Запрос имени файла для установки"
+msgstr "Необходимо имя устанавливаемого файла"
 
 #. TRANSLATORS: geeky error, 99.9999% of users won't see this
-#: ../client/pk-console.c:1438
+#: ../client/pk-console.c:1457
 msgid "A type, key_id and package_id are required"
 msgstr "Требуется указать тип, key_id или package_id"
 
 #. TRANSLATORS: the user did not specify what they wanted to remove
-#: ../client/pk-console.c:1449
+#: ../client/pk-console.c:1468
 msgid "A package name to remove is required"
-msgstr "Для удаления необходимо указать имя пакета"
+msgstr "Необходимо название удаляемого пакета"
 
 #. TRANSLATORS: the user did not specify anything about what to download or where
-#: ../client/pk-console.c:1458
+#: ../client/pk-console.c:1477
 msgid "A destination directory and the package names to download are required"
-msgstr "Запрос директории назначения и имени пакетов для загрузки"
+msgstr "Необходимо указать названия пакетов и папку назначения"
 
 #. TRANSLATORS: the directory does not exist, so we can't continue
-#: ../client/pk-console.c:1465
+#: ../client/pk-console.c:1484
 msgid "Directory not found"
 msgstr "Каталог не найден"
 
 #. TRANSLATORS: geeky error, 99.9999% of users won't see this
-#: ../client/pk-console.c:1474
+#: ../client/pk-console.c:1493
 msgid "A licence identifier (eula-id) is required"
 msgstr "Необходим идентификатор лицензии (eula-id)"
 
 #. TRANSLATORS: geeky error, 99.9999% of users won't see this
-#: ../client/pk-console.c:1485
+#: ../client/pk-console.c:1504
 msgid "A transaction identifier (tid) is required"
-msgstr "Необходим идентификатор транзакции (tid)"
+msgstr "Необходим номер операции (tid)"
 
 #. TRANSLATORS: The user did not specify a package name
-#: ../client/pk-console.c:1506
+#: ../client/pk-console.c:1525
 msgid "A package name to resolve is required"
-msgstr "Для сопоставления необходимо имя пакета"
+msgstr "Необходимо название пакета для сопоставления"
 
 #. TRANSLATORS: The user did not specify a repository (software source) name
-#: ../client/pk-console.c:1517 ../client/pk-console.c:1528
+#: ../client/pk-console.c:1536
+#: ../client/pk-console.c:1547
 msgid "A repository name is required"
-msgstr "Необходимо имя репозитория"
+msgstr "Необходимо название репозитория"
 
 #. TRANSLATORS: The user didn't provide any data
-#: ../client/pk-console.c:1539
+#: ../client/pk-console.c:1558
 msgid "A repo name, parameter and value are required"
 msgstr "Необходимо указать имя, параметр и значение репозитория"
 
 #. TRANSLATORS: The user didn't specify what action to use
-#: ../client/pk-console.c:1556
+#: ../client/pk-console.c:1575
 msgid "An action, e.g. 'update-system' is required"
-msgstr "Необходимо указать действие, например 'update-system'"
+msgstr "Необходимо действие, например 'update-system'"
 
 #. TRANSLATORS: The user specified an invalid action
-#: ../client/pk-console.c:1563
+#: ../client/pk-console.c:1582
 msgid "A correct role is required"
-msgstr "Необходимо выбрать роль"
+msgstr "Необходимо указать роль"
 
 #. TRANSLATORS: The user did not provide a package name
 #. TRANSLATORS: This is when the user fails to supply the package name
-#: ../client/pk-console.c:1573 ../client/pk-console.c:1588
-#: ../client/pk-console.c:1597 ../client/pk-console.c:1617
-#: ../client/pk-console.c:1626 ../client/pk-generate-pack.c:298
+#: ../client/pk-console.c:1592
+#: ../client/pk-console.c:1607
+#: ../client/pk-console.c:1616
+#: ../client/pk-console.c:1636
+#: ../client/pk-console.c:1645
+#: ../client/pk-generate-pack.c:316
 msgid "A package name is required"
-msgstr "Необходимо указать имя пакета"
+msgstr "Необходимо название пакета"
 
 #. TRANSLATORS: each package "provides" certain things, e.g. mime(gstreamer-decoder-mp3), the user didn't specify it
-#: ../client/pk-console.c:1606
+#: ../client/pk-console.c:1625
 msgid "A package provide string is required"
-msgstr "Необходим пакет предоставляемый строкой"
+msgstr "Необходима строка, указывающая на пакет"
 
 #. TRANSLATORS: The user tried to use an unsupported option on the command line
-#: ../client/pk-console.c:1686
+#: ../client/pk-console.c:1705
 #, c-format
 msgid "Option '%s' is not supported"
 msgstr "Опция '%s' не поддерживается"
 
 #. TRANSLATORS: Generic failure of what they asked to do
-#: ../client/pk-console.c:1696
+#: ../client/pk-console.c:1715
 msgid "Command failed"
-msgstr "Ошибка команды"
+msgstr "Действие не удалось"
 
 #. TRANSLATORS: we can exclude certain packages (glibc) when we know they'll exist on the target
-#: ../client/pk-generate-pack.c:237
+#: ../client/pk-generate-pack.c:255
 msgid "Set the file name of dependencies to be excluded"
 msgstr "Укажите имена файлов зависимостей, которые требуется исключить"
 
 #. TRANSLATORS: the output location
-#: ../client/pk-generate-pack.c:240
+#: ../client/pk-generate-pack.c:258
 msgid "The output file or directory (the current directory is used if ommitted)"
-msgstr "Выходной файл или каталог (используется текущий каталог, если не указан иной)"
+msgstr "Выходной файл или каталог (используется текущий, если не указан иной)"
 
 #. TRANSLATORS: put a list of packages in the pack
-#: ../client/pk-generate-pack.c:243
+#: ../client/pk-generate-pack.c:261
 msgid "The package to be put into the service pack"
-msgstr "Пакет, который необходимо поместить в пакет обновления"
+msgstr "Пакет для пометки частью сервисного обновления"
 
 #. TRANSLATORS: put all pending updates in the pack
-#: ../client/pk-generate-pack.c:246
+#: ../client/pk-generate-pack.c:264
 msgid "Put all updates available in the service pack"
-msgstr "Поместить все доступные обновления в пакет обновлений"
+msgstr "Отнести все доступные обновления с сервисным"
 
 #. TRANSLATORS: This is when the user fails to supply the correct arguments
-#: ../client/pk-generate-pack.c:282
+#: ../client/pk-generate-pack.c:300
 msgid "Neither --package or --updates option selected."
-msgstr "Ни опции --package или --updates указано."
+msgstr "Не выбран параметр --package или --updates"
 
 #. TRANSLATORS: This is when the user fails to supply just one argument
-#: ../client/pk-generate-pack.c:290
+#: ../client/pk-generate-pack.c:308
 msgid "Both options selected."
-msgstr "Оба варианта выбрано."
+msgstr "Выбраны оба параметра."
 
 #. TRANSLATORS: This is when the user fails to supply the output
-#: ../client/pk-generate-pack.c:306
+#: ../client/pk-generate-pack.c:324
 msgid "A output directory or file name is required"
-msgstr "Необходимо указать конечный каталог или имя файла"
+msgstr "Требуется выходной каталог или имя файла"
 
 #. TRANSLATORS: This is when the dameon is not-installed/broken and fails to startup
-#: ../client/pk-generate-pack.c:324
+#: ../client/pk-generate-pack.c:342
 msgid "The dameon failed to startup"
-msgstr "Сбой запуска демона"
+msgstr "Служба не запущена"
 
 #. TRANSLATORS: This is when the backend doesn't have the capability to get-depends
 #. TRANSLATORS: This is when the backend doesn't have the capability to download
-#: ../client/pk-generate-pack.c:335 ../client/pk-generate-pack.c:341
+#: ../client/pk-generate-pack.c:353
+#: ../client/pk-generate-pack.c:359
 msgid "The package manager cannot perform this type of operation."
-msgstr "Менеджер пакетов не может выполнить такого рода операции."
+msgstr "Менеджер пакетов не может выполнить подобное действие."
 
 #. TRANSLATORS: This is when the distro didn't include libarchive support into PK
-#: ../client/pk-generate-pack.c:348
-msgid ""
-"Service packs cannot be created as PackageKit was not built with libarchive "
-"support."
-msgstr ""
-"Сервис-пак не может быть создан, потому что PackageKit собран без поддержки "
-"libarchive"
+#: ../client/pk-generate-pack.c:366
+msgid "Service packs cannot be created as PackageKit was not built with libarchive support."
+msgstr "Сервисное обновление не создано, потому что PackageKit собран без поддержки libarchive."
 
 #. TRANSLATORS: the user specified an absolute path, but didn't get the extension correct
-#: ../client/pk-generate-pack.c:359
+#: ../client/pk-generate-pack.c:377
 msgid "If specifying a file, the service pack name must end with"
-msgstr "Если указан файл, то имя пакета обновления должно существовать"
+msgstr "При указании файла название обновления должно оканчиваться на"
 
 #. TRANSLATORS: This is when file already exists
-#: ../client/pk-generate-pack.c:375
+#: ../client/pk-generate-pack.c:393
 msgid "A pack with the same name already exists, do you want to overwrite it?"
-msgstr "Пакет с таким именем уже существует, Вы желаете переписать его?"
+msgstr "Пакет с таким названием уже существует, желаете переписать его?"
 
 #. TRANSLATORS: This is when the pack was not overwritten
-#: ../client/pk-generate-pack.c:378
+#: ../client/pk-generate-pack.c:396
 msgid "The pack was not overwritten."
 msgstr "Пакет не был перезаписан."
 
 #. TRANSLATORS: This is when the temporary directory cannot be created, the directory name follows
-#: ../client/pk-generate-pack.c:391
+#: ../client/pk-generate-pack.c:409
 msgid "Failed to create directory:"
-msgstr "Не удалось создать каталог."
+msgstr "Не удалось создать каталог:"
 
 #. TRANSLATORS: This is when the list of packages from the remote computer cannot be opened
-#: ../client/pk-generate-pack.c:403
+#: ../client/pk-generate-pack.c:421
 msgid "Failed to open package list."
 msgstr "Не удалось открыть список пакетов."
 
 #. TRANSLATORS: The package name is being matched up to available packages
-#: ../client/pk-generate-pack.c:412
+#: ../client/pk-generate-pack.c:430
 msgid "Finding package name."
-msgstr "Поиск пакета по имени."
+msgstr "Поиск пакета по названию."
 
 #. TRANSLATORS: This is when the package cannot be found in any software source. The detailed error follows
-#: ../client/pk-generate-pack.c:416
+#: ../client/pk-generate-pack.c:434
 #, c-format
 msgid "Failed to find package '%s': %s"
 msgstr "Не удалось найти пакет '%s': %s"
 
 #. TRANSLATORS: This is telling the user we are in the process of making the pack
-#: ../client/pk-generate-pack.c:424
+#: ../client/pk-generate-pack.c:442
 msgid "Creating service pack..."
-msgstr "Создание пакета обновления..."
+msgstr "Подготовка служебного обновления..."
 
 #. TRANSLATORS: we succeeded in making the file
-#: ../client/pk-generate-pack.c:439
+#: ../client/pk-generate-pack.c:457
 #, c-format
 msgid "Service pack created '%s'"
-msgstr "Пакет обновления создан '%s'"
+msgstr "Служебное обновление готово '%s'"
 
 #. TRANSLATORS: we failed to make te file
-#: ../client/pk-generate-pack.c:444
+#: ../client/pk-generate-pack.c:462
 #, c-format
 msgid "Failed to create '%s': %s"
 msgstr "Не удалось создать '%s': %s"
 
-#: ../client/pk-monitor.c:210
+#: ../client/pk-monitor.c:236
 msgid "Failed to get daemon state"
-msgstr "Не удалось получить состояние демона"
+msgstr "Не удалось получить состояние службы"
 
 #. TRANSLATORS: this is a program that monitors PackageKit
-#: ../client/pk-monitor.c:296
+#: ../client/pk-monitor.c:322
 msgid "PackageKit Monitor"
 msgstr "Монитор PackageKit"
 
@@ -692,7 +709,7 @@ msgstr "Установка..."
 #. TRANSLATORS: downloading repo data so we can search
 #: ../contrib/command-not-found/pk-command-not-found.c:365
 msgid "Downloading details about the software sources."
-msgstr "Загрузка подробностей об источнике программ."
+msgstr "Загрузка подробностей об источниках программ."
 
 #. TRANSLATORS: downloading file lists so we can search
 #: ../contrib/command-not-found/pk-command-not-found.c:369
@@ -727,7 +744,7 @@ msgstr "Не удалось установить пакеты"
 #. TRANSLATORS: tool that gets called when the command is not found
 #: ../contrib/command-not-found/pk-command-not-found.c:670
 msgid "PackageKit Command Not Found"
-msgstr "PackageKit Команда не найдена"
+msgstr "Команда PackageKit не найдена"
 
 #. TRANSLATORS: the prefix of all the output telling the user why it's not executing
 #: ../contrib/command-not-found/pk-command-not-found.c:699
@@ -770,7 +787,7 @@ msgstr "Установить пакет '%s' предоставляющий ко
 #. TRANSLATORS: Show the user a list of packages that provide this command
 #: ../contrib/command-not-found/pk-command-not-found.c:793
 msgid "Packages providing this file are:"
-msgstr "Пакеты предоставляемые этим файлом:"
+msgstr "Пакеты, содержащие этот файл:"
 
 #. TRANSLATORS: Show the user a list of packages that they can install to provide this command
 #: ../contrib/command-not-found/pk-command-not-found.c:803
@@ -781,7 +798,7 @@ msgstr "Подходящие пакеты:"
 #. TRANSLATORS: ask the user to choose a file to install
 #: ../contrib/command-not-found/pk-command-not-found.c:812
 msgid "Please choose a package to install"
-msgstr "Пожалуйста, выберете пакет для установки:"
+msgstr "Пожалуйста, выберите пакет для установки:"
 
 #. TRANSLATORS: we are starting to install the packages
 #: ../contrib/debuginfo-install/pk-debuginfo-install.c:197
@@ -876,13 +893,13 @@ msgstr "Включение отладочного источника."
 #: ../contrib/debuginfo-install/pk-debuginfo-install.c:695
 #, c-format
 msgid "Enabled %i debugging sources."
-msgstr "Включен %i отладочных источника"
+msgstr "Включено %i отладочных источников."
 
 #. TRANSLATORS: we're now finding packages that match in all the repos
 #: ../contrib/debuginfo-install/pk-debuginfo-install.c:702
 #, c-format
 msgid "Finding debugging packages"
-msgstr "Поиск обновления пакета"
+msgstr "Поиск отладочных пакетов"
 
 #. TRANSLATORS: we couldn't find the package name, non-fatal
 #: ../contrib/debuginfo-install/pk-debuginfo-install.c:714
@@ -977,92 +994,92 @@ msgid "Disabled %i debugging sources."
 msgstr "Отключено %i отладочных источников."
 
 #. TRANSLATORS: couldn't open device to write
-#: ../contrib/device-rebind/pk-device-rebind.c:61
+#: ../contrib/device-rebind/pk-device-rebind.c:62
 msgid "Failed to open file"
 msgstr "Ошибка открытия файла"
 
 #. TRANSLATORS: could not write to the device
-#: ../contrib/device-rebind/pk-device-rebind.c:70
+#: ../contrib/device-rebind/pk-device-rebind.c:71
 msgid "Failed to write to the file"
 msgstr "Ошибка записи в  файл"
 
 #. TRANSLATORS: we failed to release the current driver
-#: ../contrib/device-rebind/pk-device-rebind.c:110
-#: ../contrib/device-rebind/pk-device-rebind.c:147
+#: ../contrib/device-rebind/pk-device-rebind.c:111
+#: ../contrib/device-rebind/pk-device-rebind.c:148
 msgid "Failed to write to device"
 msgstr "Не удалось сохранить на диск"
 
 #. TRANSLATORS: the device could not be found in sysfs
-#: ../contrib/device-rebind/pk-device-rebind.c:175
+#: ../contrib/device-rebind/pk-device-rebind.c:176
 msgid "Device could not be found"
 msgstr "Устройство не найдено"
 
 #. TRANSLATORS: we failed to release the current driver
-#: ../contrib/device-rebind/pk-device-rebind.c:202
+#: ../contrib/device-rebind/pk-device-rebind.c:203
 msgid "Failed to unregister driver"
 msgstr "Не удалось отменить регистрацию драйвера"
 
 #. TRANSLATORS: we failed to bind the old driver
-#: ../contrib/device-rebind/pk-device-rebind.c:211
+#: ../contrib/device-rebind/pk-device-rebind.c:212
 msgid "Failed to register driver"
 msgstr "Не удалось зарегистрировать драйвер"
 
 #. TRANSLATORS: user did not specify a device sysfs path that exists
-#: ../contrib/device-rebind/pk-device-rebind.c:260
+#: ../contrib/device-rebind/pk-device-rebind.c:261
 msgid "Device path not found"
 msgstr "Путь устройства не найден"
 
 #. TRANSLATORS: user did not specify a valid device sysfs path
-#: ../contrib/device-rebind/pk-device-rebind.c:268
+#: ../contrib/device-rebind/pk-device-rebind.c:269
 msgid "Incorrect device path specified"
 msgstr "Указан неверный путь к устройству"
 
-#: ../contrib/device-rebind/pk-device-rebind.c:293
+#: ../contrib/device-rebind/pk-device-rebind.c:294
 msgid "Show extra debugging information"
 msgstr "Показать дополнительную отладочную информацию"
 
 #. command line argument, simulate what would be done, but don't actually do it
-#: ../contrib/device-rebind/pk-device-rebind.c:296
+#: ../contrib/device-rebind/pk-device-rebind.c:297
 msgid "Don't actually touch the hardware, only simulate what would be done"
 msgstr "Не проводить операцию, только симулировать её."
 
 #. TRANSLATORS: command line option: a list of files to install
-#: ../contrib/device-rebind/pk-device-rebind.c:299
+#: ../contrib/device-rebind/pk-device-rebind.c:300
 msgid "Device paths"
 msgstr "Путь к устройству"
 
 #. TRANSLATORS: tool that gets called when the device needs reloading after installing firmware
-#: ../contrib/device-rebind/pk-device-rebind.c:314
+#: ../contrib/device-rebind/pk-device-rebind.c:315
 msgid "PackageKit Device Reloader"
 msgstr "PackageKit перезагружает устройство"
 
 #. TRANSLATORS: user did not specify a valid device sysfs path
-#: ../contrib/device-rebind/pk-device-rebind.c:322
+#: ../contrib/device-rebind/pk-device-rebind.c:323
 msgid "You need to specify at least one valid device path"
 msgstr "Вам необходимо указать хотя бы один действительный путь до устройства"
 
 #. TRANSLATORS: user did not specify a valid device sysfs path
-#: ../contrib/device-rebind/pk-device-rebind.c:332
+#: ../contrib/device-rebind/pk-device-rebind.c:333
 msgid "This script can only be used by the root user"
 msgstr "Этот скрипт может быть использован только пользователем root"
 
 #. TRANSLATORS: we're going to verify the path first
-#: ../contrib/device-rebind/pk-device-rebind.c:341
+#: ../contrib/device-rebind/pk-device-rebind.c:342
 msgid "Verifying device path"
 msgstr "Проверка пути к устройству"
 
 #. TRANSLATORS: user did not specify a device sysfs path that exists
-#: ../contrib/device-rebind/pk-device-rebind.c:346
+#: ../contrib/device-rebind/pk-device-rebind.c:347
 msgid "Failed to verify device path"
 msgstr "Ошибка проверки пути к устройству"
 
 #. TRANSLATORS: we're going to try
-#: ../contrib/device-rebind/pk-device-rebind.c:360
+#: ../contrib/device-rebind/pk-device-rebind.c:361
 msgid "Attempting to rebind device"
 msgstr "Попытка перемонтировать устройство."
 
 #. TRANSLATORS: we failed to release the current driver
-#: ../contrib/device-rebind/pk-device-rebind.c:365
+#: ../contrib/device-rebind/pk-device-rebind.c:366
 msgid "Failed to rebind device"
 msgstr "Не удалось перемонтировать устройство"
 
@@ -1091,7 +1108,7 @@ msgstr "Найдено несколько подходящих пакетов"
 #. TRANSLATORS: This finds out which package in the list to use
 #: ../lib/packagekit-glib2/pk-console-shared.c:196
 msgid "Please choose the correct package: "
-msgstr "Пожалуйста, выберете корректный пакет:"
+msgstr "Пожалуйста, выберите корректный пакет:"
 
 #. TRANSLATORS: This is when the transaction status is not known
 #: ../lib/packagekit-glib2/pk-console-shared.c:250
@@ -1111,7 +1128,7 @@ msgstr "Ожидание в очереди"
 #. TRANSLATORS: transaction state, just started
 #: ../lib/packagekit-glib2/pk-console-shared.c:262
 msgid "Running"
-msgstr "Запуск"
+msgstr "Выполнение"
 
 #. TRANSLATORS: transaction state, is querying data
 #: ../lib/packagekit-glib2/pk-console-shared.c:266
@@ -1143,7 +1160,7 @@ msgstr "Обновление списка пакетов"
 #. TRANSLATORS: transaction state, installing updates
 #: ../lib/packagekit-glib2/pk-console-shared.c:290
 msgid "Installing updates"
-msgstr "установка обновлений"
+msgstr "Установка обновлений"
 
 #. TRANSLATORS: transaction state, removing old packages, and cleaning config files
 #: ../lib/packagekit-glib2/pk-console-shared.c:294
@@ -1163,19 +1180,19 @@ msgstr "Разрешение зависимостей"
 #. TRANSLATORS: transaction state, checking if we have all the security keys for the operation
 #: ../lib/packagekit-glib2/pk-console-shared.c:306
 msgid "Checking signatures"
-msgstr "Проверка сигнатур"
+msgstr "Проверка подписи"
 
 #. TRANSLATORS: transaction state, when we return to a previous system state
 #. TRANSLATORS: The role of the transaction, in present tense
 #: ../lib/packagekit-glib2/pk-console-shared.c:310
 #: ../lib/packagekit-glib2/pk-console-shared.c:616
 msgid "Rolling back"
-msgstr "Откат обратно"
+msgstr "Отмена действий"
 
 #. TRANSLATORS: transaction state, when we're doing a test transaction
 #: ../lib/packagekit-glib2/pk-console-shared.c:314
 msgid "Testing changes"
-msgstr "Тестирование изменений"
+msgstr "Проверка изменений"
 
 #. TRANSLATORS: transaction state, when we're writing to the system package database
 #: ../lib/packagekit-glib2/pk-console-shared.c:318
@@ -1190,7 +1207,7 @@ msgstr "Запрос данных"
 #. TRANSLATORS: transaction state, all done!
 #: ../lib/packagekit-glib2/pk-console-shared.c:326
 msgid "Finished"
-msgstr "Завершение"
+msgstr "Завершено"
 
 #. TRANSLATORS: transaction state, in the process of cancelling
 #: ../lib/packagekit-glib2/pk-console-shared.c:330
@@ -1230,12 +1247,12 @@ msgstr "Загрузка информации об обновлении"
 #. TRANSLATORS: transaction state, repackaging delta files
 #: ../lib/packagekit-glib2/pk-console-shared.c:358
 msgid "Repackaging files"
-msgstr "Выполняется повторная сборка файлов"
+msgstr "Повторная сборка файлов"
 
 #. TRANSLATORS: transaction state, loading databases
 #: ../lib/packagekit-glib2/pk-console-shared.c:362
 msgid "Loading cache"
-msgstr "Выполняется загрузка в кэш"
+msgstr "Загрузка в память"
 
 #. TRANSLATORS: transaction state, scanning for running processes
 #: ../lib/packagekit-glib2/pk-console-shared.c:366
@@ -1245,17 +1262,17 @@ msgstr "Сканирование приложений"
 #. TRANSLATORS: transaction state, generating a list of packages installed on the system
 #: ../lib/packagekit-glib2/pk-console-shared.c:370
 msgid "Generating package lists"
-msgstr "создание списка пакетов"
+msgstr "Создание списка пакетов"
 
 #. TRANSLATORS: transaction state, when we're waiting for the native tools to exit
 #: ../lib/packagekit-glib2/pk-console-shared.c:374
 msgid "Waiting for package manager lock"
-msgstr "Пакетный менеджер заблокирован, ожидание"
+msgstr "Ожидание блокировки менеджера пакетов"
 
 #. TRANSLATORS: transaction state, waiting for user to type in a password
 #: ../lib/packagekit-glib2/pk-console-shared.c:378
 msgid "Waiting for authentication"
-msgstr "Ожидание аутентификации"
+msgstr "Ожидание авторизации"
 
 #. TRANSLATORS: transaction state, we are updating the list of processes
 #: ../lib/packagekit-glib2/pk-console-shared.c:382
@@ -1265,12 +1282,12 @@ msgstr "Обновление запущенных приложений"
 #. TRANSLATORS: transaction state, we are checking executable files currently in use
 #: ../lib/packagekit-glib2/pk-console-shared.c:386
 msgid "Checking applications in use"
-msgstr "Проверка используемых приложений"
+msgstr "Поиск занятых приложений"
 
 #. TRANSLATORS: transaction state, we are checking for libraries currently in use
 #: ../lib/packagekit-glib2/pk-console-shared.c:390
 msgid "Checking libraries in use"
-msgstr "Проверка используемых библиотек"
+msgstr "Поиск занятых библиотек"
 
 #. TRANSLATORS: transaction state, we are copying package files before or after the transaction
 #: ../lib/packagekit-glib2/pk-console-shared.c:394
@@ -1280,17 +1297,17 @@ msgstr "Копирование файлов"
 #. TRANSLATORS: The type of update
 #: ../lib/packagekit-glib2/pk-console-shared.c:412
 msgid "Trivial"
-msgstr "Простой"
+msgstr "Незначительное"
 
 #. TRANSLATORS: The type of update
 #: ../lib/packagekit-glib2/pk-console-shared.c:416
 msgid "Normal"
-msgstr "Нормальный"
+msgstr "Обычное"
 
 #. TRANSLATORS: The type of update
 #: ../lib/packagekit-glib2/pk-console-shared.c:420
 msgid "Important"
-msgstr "Важный"
+msgstr "Важное"
 
 #. TRANSLATORS: The type of update
 #: ../lib/packagekit-glib2/pk-console-shared.c:424
@@ -1300,7 +1317,7 @@ msgstr "Безопасность"
 #. TRANSLATORS: The type of update
 #: ../lib/packagekit-glib2/pk-console-shared.c:428
 msgid "Bug fix "
-msgstr "Исправление ошибок"
+msgstr "Устранение ошибок"
 
 #. TRANSLATORS: The type of update
 #: ../lib/packagekit-glib2/pk-console-shared.c:432
@@ -1396,12 +1413,12 @@ msgstr "Неизвестный тип"
 #. TRANSLATORS: The role of the transaction, in present tense
 #: ../lib/packagekit-glib2/pk-console-shared.c:552
 msgid "Getting dependencies"
-msgstr "Загрузка зависимостей"
+msgstr "Получение зависимостей"
 
 #. TRANSLATORS: The role of the transaction, in present tense
 #: ../lib/packagekit-glib2/pk-console-shared.c:556
 msgid "Getting update details"
-msgstr "Получение подробностей обновления"
+msgstr "Получение подробностей об обновлении"
 
 #. TRANSLATORS: The role of the transaction, in present tense
 #: ../lib/packagekit-glib2/pk-console-shared.c:560
@@ -1411,7 +1428,7 @@ msgstr "Получение подробностей"
 #. TRANSLATORS: The role of the transaction, in present tense
 #: ../lib/packagekit-glib2/pk-console-shared.c:564
 msgid "Getting requires"
-msgstr "Получение запроса"
+msgstr "Выявление требований"
 
 #. TRANSLATORS: The role of the transaction, in present tense
 #: ../lib/packagekit-glib2/pk-console-shared.c:568
@@ -1421,22 +1438,22 @@ msgstr "Получение обновлений"
 #. TRANSLATORS: The role of the transaction, in present tense
 #: ../lib/packagekit-glib2/pk-console-shared.c:572
 msgid "Searching by details"
-msgstr "Поиск по подробностям"
+msgstr "Поиск по особенностям"
 
 #. TRANSLATORS: The role of the transaction, in present tense
 #: ../lib/packagekit-glib2/pk-console-shared.c:576
 msgid "Searching by file"
-msgstr "Поиск по файлу"
+msgstr "Поиск по имени файла"
 
 #. TRANSLATORS: The role of the transaction, in present tense
 #: ../lib/packagekit-glib2/pk-console-shared.c:580
 msgid "Searching groups"
-msgstr "Поиск группы"
+msgstr "Поиск по группам"
 
 #. TRANSLATORS: The role of the transaction, in present tense
 #: ../lib/packagekit-glib2/pk-console-shared.c:584
 msgid "Searching by name"
-msgstr "Поиск по имени"
+msgstr "Поиск по названию"
 
 #. TRANSLATORS: The role of the transaction, in present tense
 #: ../lib/packagekit-glib2/pk-console-shared.c:596
@@ -1476,12 +1493,12 @@ msgstr "Включение репозитория"
 #. TRANSLATORS: The role of the transaction, in present tense
 #: ../lib/packagekit-glib2/pk-console-shared.c:628
 msgid "Setting data"
-msgstr "Настройки данных"
+msgstr "Настройка данных"
 
 #. TRANSLATORS: The role of the transaction, in present tense
 #: ../lib/packagekit-glib2/pk-console-shared.c:632
 msgid "Resolving"
-msgstr "Разрешение"
+msgstr "Сопоставление"
 
 #. TRANSLATORS: The role of the transaction, in present tense
 #: ../lib/packagekit-glib2/pk-console-shared.c:636
@@ -1542,22 +1559,22 @@ msgstr "Симуляция обновления"
 #. TRANSLATORS: ask the user if they are comfortable installing insecure packages
 #: ../lib/packagekit-glib2/pk-task-text.c:69
 msgid "Do you want to allow installing of unsigned software?"
-msgstr "Разрешить установку программ без подписи?"
+msgstr "Желаете разрешить установку неподписанных пакетов?"
 
 #. TRANSLATORS: tell the user we've not done anything
 #: ../lib/packagekit-glib2/pk-task-text.c:74
 msgid "The unsigned software will not be installed."
-msgstr "Неподписанное программное обеспечение не будет установлено."
+msgstr "Пакеты без подписи установлены не будут."
 
 #. TRANSLATORS: the package repository is signed by a key that is not recognised
 #: ../lib/packagekit-glib2/pk-task-text.c:123
 msgid "Software source signature required"
-msgstr "Запрос подписи источника программ"
+msgstr "Необходима подпись источника"
 
 #. TRANSLATORS: the package repository name
 #: ../lib/packagekit-glib2/pk-task-text.c:129
 msgid "Software source name"
-msgstr "Имя источника программ"
+msgstr "Название источника"
 
 #. TRANSLATORS: the key URL
 #: ../lib/packagekit-glib2/pk-task-text.c:132
@@ -1577,12 +1594,12 @@ msgstr "Идентификатор ключа"
 #. TRANSLATORS: the key fingerprint, again, yet more hex
 #: ../lib/packagekit-glib2/pk-task-text.c:141
 msgid "Key fingerprint"
-msgstr "Ключ отпечатка пальца"
+msgstr "Метка ключа"
 
 #. TRANSLATORS: the timestamp (a bit like a machine readable time)
 #: ../lib/packagekit-glib2/pk-task-text.c:144
 msgid "Key Timestamp"
-msgstr "Ключ Timestamp"
+msgstr "Время создания ключа"
 
 #. TRANSLATORS: ask the user if they want to import
 #: ../lib/packagekit-glib2/pk-task-text.c:157
@@ -1592,12 +1609,12 @@ msgstr "Вы принимаете эту подпись?"
 #. TRANSLATORS: tell the user we've not done anything
 #: ../lib/packagekit-glib2/pk-task-text.c:162
 msgid "The signature was not accepted."
-msgstr "Эта подпись не может быть принята."
+msgstr "Подпись не принята."
 
 #. TRANSLATORS: this is another name for a software licence that has to be read before installing
 #: ../lib/packagekit-glib2/pk-task-text.c:205
 msgid "End user licence agreement required"
-msgstr "Необходимо лицензионное соглашение с конечным пользователем."
+msgstr "Необходимо принять пользовательское соглашение"
 
 #. TRANSLATORS: the EULA text itself (long and boring)
 #: ../lib/packagekit-glib2/pk-task-text.c:214
@@ -1607,7 +1624,7 @@ msgstr "Соглашение"
 #. TRANSLATORS: ask the user if they've read and accepted the EULA
 #: ../lib/packagekit-glib2/pk-task-text.c:223
 msgid "Do you accept this agreement?"
-msgstr "Вы принимаете это соглашение?"
+msgstr "Принимаете это соглашение?"
 
 #. TRANSLATORS: tell the user we've not done anything
 #: ../lib/packagekit-glib2/pk-task-text.c:228
@@ -1617,7 +1634,7 @@ msgstr "Соглашение не принято."
 #. TRANSLATORS: the user needs to change media inserted into the computer
 #: ../lib/packagekit-glib2/pk-task-text.c:267
 msgid "Media change required"
-msgstr "Запрос смены носителя"
+msgstr "Требуется сменить носитель"
 
 #. TRANSLATORS: the type, e.g. DVD, CD, etc
 #: ../lib/packagekit-glib2/pk-task-text.c:270
@@ -1637,12 +1654,12 @@ msgstr "Текст"
 #. TRANSLATORS: ask the user to insert the media
 #: ../lib/packagekit-glib2/pk-task-text.c:282
 msgid "Please insert the correct media"
-msgstr "Пожалуйста, вставьте корректный носитель"
+msgstr "Пожалуйста, вставьте верный носитель"
 
 #. TRANSLATORS: tell the user we've not done anything as they are lazy
 #: ../lib/packagekit-glib2/pk-task-text.c:287
 msgid "The correct media was not inserted."
-msgstr "Корректный носитель не установлен."
+msgstr "Верный носитель не вставлен."
 
 #. TRANSLATORS: When processing, we might have to remove other dependencies
 #: ../lib/packagekit-glib2/pk-task-text.c:302
@@ -1667,12 +1684,12 @@ msgstr "Следующие пакеты должны быть переустан
 #. TRANSLATORS: When processing, we might have to downgrade other dependencies
 #: ../lib/packagekit-glib2/pk-task-text.c:322
 msgid "The following packages have to be downgraded:"
-msgstr "Следующие пакеты должны быть пониженны:"
+msgstr "Следующие пакеты следует откатить:"
 
 #. TRANSLATORS: ask the user if the proposed changes are okay
 #: ../lib/packagekit-glib2/pk-task-text.c:382
 msgid "Proceed with changes?"
-msgstr "Продолжить с изменениями"
+msgstr "Обработать изменения?"
 
 #. TRANSLATORS: tell the user we didn't do anything
 #: ../lib/packagekit-glib2/pk-task-text.c:387
@@ -1691,59 +1708,51 @@ msgstr "Примите EULA"
 
 #: ../policy/org.freedesktop.packagekit.policy.in.h:8
 msgid "Authentication is required to accept a EULA"
-msgstr "Для принятия EULA необходима аутентификация"
+msgstr "Для принятия EULA необходимо авторизоваться"
 
 #: ../policy/org.freedesktop.packagekit.policy.in.h:9
 msgid "Authentication is required to cancel a task that was not started by yourself"
-msgstr "Требуется аутентификация для отмены задачи, которая не была запущена Вами"
+msgstr "Требуются права на отмену задачи, запущенной не Вами"
 
 #: ../policy/org.freedesktop.packagekit.policy.in.h:10
 msgid "Authentication is required to change software source parameters"
-msgstr "Для изменения параметров исходного кода необходима аутентификация"
+msgstr "Для настройки источников программ необходимо авторизоваться"
 
 #: ../policy/org.freedesktop.packagekit.policy.in.h:11
-msgid ""
-"Authentication is required to consider a key used for signing packages as "
-"trusted"
-msgstr ""
-"Требуется аутентификация для рассмотрения ключа, используемого для "
-"подписания пакетов, как доверенного"
+msgid "Authentication is required to consider a key used for signing packages as trusted"
+msgstr "Чтобы пометить ключ для подписи пакетов как доверенный, нужно авторизоваться"
 
 #: ../policy/org.freedesktop.packagekit.policy.in.h:12
 msgid "Authentication is required to install a signed package"
-msgstr "Требуется аутентификация для установки подписанных пакетов"
+msgstr "Требуются права на установку подписанных пакетов"
 
 #: ../policy/org.freedesktop.packagekit.policy.in.h:13
 msgid "Authentication is required to install an untrusted package"
-msgstr "Для установки ненадежных пакетов необходима аутентификация"
+msgstr "Перед установкой ненадежных пакетов необходимо авторизоваться"
 
 #: ../policy/org.freedesktop.packagekit.policy.in.h:14
 msgid "Authentication is required to refresh the system sources"
-msgstr "Требуется аутентификация для обновления списка пакетов"
+msgstr "Чтобы обновить список пакетов, необходимо авторизоваться"
 
 #: ../policy/org.freedesktop.packagekit.policy.in.h:15
 msgid "Authentication is required to reload the device with a new driver"
-msgstr "Требуется аутентификация для перезагрузки устройства с новым драйвером"
+msgstr "Требуется разрешение на перезагрузку устройства с новым драйвером"
 
 #: ../policy/org.freedesktop.packagekit.policy.in.h:16
 msgid "Authentication is required to remove packages"
-msgstr "Для удаления пакетов необходима аутентификация"
+msgstr "Перед удалением пакетов нужно авторизоваться"
 
 #: ../policy/org.freedesktop.packagekit.policy.in.h:17
 msgid "Authentication is required to rollback a transaction"
-msgstr "Для отката транзакции необходима аутентификация"
+msgstr "Для отмены действия необходимо разрешение"
 
 #: ../policy/org.freedesktop.packagekit.policy.in.h:18
-msgid ""
-"Authentication is required to set the network proxy used for downloading "
-"packages"
-msgstr ""
-"Требуется аутентификация для настройки параметров прокси, используемого для "
-"загрузки пакетов"
+msgid "Authentication is required to set the network proxy used for downloading packages"
+msgstr "Настройка прокси-сервера для загрузки пакетов требует авторизации"
 
 #: ../policy/org.freedesktop.packagekit.policy.in.h:19
 msgid "Authentication is required to update packages"
-msgstr "Для обновления пакетов необходима аутентификация"
+msgstr "Для обновления пакетов нужно авторизоваться"
 
 #. SECURITY:
 #. - Normal users are allowed to cancel their own task without
@@ -1761,7 +1770,7 @@ msgstr "Остановить внешнюю задачу"
 #.
 #: ../policy/org.freedesktop.packagekit.policy.in.h:31
 msgid "Change software source parameters"
-msgstr "Изменить параметры исходного кода"
+msgstr "Настроить источники программ"
 
 #. SECURITY:
 #. - Normal users do not need authentication to install signed packages
@@ -1781,7 +1790,7 @@ msgstr "Установить подписанный пакет"
 #.
 #: ../policy/org.freedesktop.packagekit.policy.in.h:45
 msgid "Install untrusted local file"
-msgstr "Установить ненадежный локальный файл"
+msgstr "Установить недоверяемый локальный файл"
 
 #. SECURITY:
 #. - Normal users do not require admin authentication to refresh the
@@ -1822,7 +1831,7 @@ msgstr "Удалить пакет"
 #.
 #: ../policy/org.freedesktop.packagekit.policy.in.h:74
 msgid "Rollback to a previous transaction"
-msgstr "Откатиться к предыдущей транзакции"
+msgstr "Откатиться до предыдущего действия"
 
 #. SECURITY:
 #. - Normal users do not require admin authentication to set the proxy
@@ -1830,7 +1839,7 @@ msgstr "Откатиться к предыдущей транзакции"
 #.
 #: ../policy/org.freedesktop.packagekit.policy.in.h:79
 msgid "Set network proxy"
-msgstr "Установить настройки прокси сервера"
+msgstr "Задать прокси-сервер"
 
 #. SECURITY:
 #. - Normal users require admin authentication to add signing keys.
@@ -1840,7 +1849,7 @@ msgstr "Установить настройки прокси сервера"
 #.
 #: ../policy/org.freedesktop.packagekit.policy.in.h:86
 msgid "Trust a key used for signing packages"
-msgstr "Для подписания пакетов используется доверенный ключ"
+msgstr "Доверять ключу в подписях пакетов"
 
 #. SECURITY:
 #. - Normal users do not require admin authentication to update the
@@ -1856,12 +1865,12 @@ msgstr "Обновить пакеты"
 #. TRANSLATORS: failed due to DBus security
 #: ../src/pk-main.c:87
 msgid "Startup failed due to security policies on this machine."
-msgstr "Запуск не удался из-за политики безопасности на этом компьютере"
+msgstr "Запуск не удался по правилам безопасности на этом компьютере."
 
 #. TRANSLATORS: only two ways this can fail...
 #: ../src/pk-main.c:89
 msgid "This can happen for two reasons:"
-msgstr "Это может случится по двум причинам:"
+msgstr "Это может случиться по двум причинам:"
 
 #. TRANSLATORS: only allowed to be owned by root
 #: ../src/pk-main.c:91
@@ -1870,10 +1879,8 @@ msgstr "Нужный пользователь не запускает испол
 
 #. TRANSLATORS: or we are installed in a prefix
 #: ../src/pk-main.c:93
-msgid ""
-"The org.freedesktop.PackageKit.conf file is not installed in the system "
-"directory:"
-msgstr "Файл org.freedesktop.PackageKit.conf не установлен в системной директории:"
+msgid "The org.freedesktop.PackageKit.conf file is not installed in the system directory:"
+msgstr "Файл org.freedesktop.PackageKit.conf отсутствует в системном каталоге:"
 
 #. TRANSLATORS: a backend is the system package tool, e.g. yum, apt
 #: ../src/pk-main.c:199
@@ -1883,12 +1890,12 @@ msgstr "Использовать внутренний интерфейс пак
 #. TRANSLATORS: if we should run in the background
 #: ../src/pk-main.c:202
 msgid "Daemonize and detach from the terminal"
-msgstr "Запустить в качестве демона и отсоединить от терминала"
+msgstr "Сделать службой и открепить от терминала"
 
 #. TRANSLATORS: if we should not monitor how long we are inactive for
 #: ../src/pk-main.c:205
 msgid "Disable the idle timer"
-msgstr "Отключить таймер неактивности"
+msgstr "Отключить таймер бездействия"
 
 #. TRANSLATORS: show version
 #: ../src/pk-main.c:208
@@ -1898,7 +1905,7 @@ msgstr "Показать версию и выйти"
 #. TRANSLATORS: exit after we've started up, used for user profiling
 #: ../src/pk-main.c:211
 msgid "Exit after a small delay"
-msgstr "Выйти после небольшой задержки"
+msgstr "Выйти после недолгой задержки"
 
 #. TRANSLATORS: exit straight away, used for automatic profiling
 #: ../src/pk-main.c:214
@@ -1908,7 +1915,7 @@ msgstr "Выйти после загрузки движка"
 #. TRANSLATORS: describing the service that is running
 #: ../src/pk-main.c:229
 msgid "PackageKit service"
-msgstr "Сервис PackageKit"
+msgstr "Служба PackageKit"
 
 #. TRANSLATORS: fatal error, dbus is not running
 #: ../src/pk-main.c:266
@@ -1922,30 +1929,29 @@ msgstr "Ошибка при попытке запуска:"
 
 #: ../src/pk-polkit-action-lookup.c:150
 msgid "To install debugging packages, extra sources need to be enabled"
-msgstr ""
-"Для установки пакета с обновлениями должны быть включены дополнительные "
-"источники."
+msgstr "Чтобы установить отладочные пакеты, включите дополнительные источники"
 
 #. TRANSLATORS: is not GPG signed
-#: ../src/pk-polkit-action-lookup.c:171 ../src/pk-polkit-action-lookup.c:190
+#: ../src/pk-polkit-action-lookup.c:171
+#: ../src/pk-polkit-action-lookup.c:190
 msgid "The software is not from a trusted source."
-msgstr "Программа получена не из доверенного источника."
+msgstr "Программа получена из недоверяемого источника."
 
 #: ../src/pk-polkit-action-lookup.c:176
 msgid "Do not update this package unless you are sure it is safe to do so."
-msgstr "Не обновляйте этот пакет если вы не уверены в последствиях обновления."
+msgstr "Не обновляйте этот пакет, если не уверены в том, что это безопасно."
 
 #: ../src/pk-polkit-action-lookup.c:177
 msgid "Do not update these packages unless you are sure it is safe to do so."
-msgstr "Не обновляйте эти пакеты если вы не уверены в последствиях обновления."
+msgstr "Не обновляйте эти пакеты, если не уверены в том, что это безопасно."
 
 #: ../src/pk-polkit-action-lookup.c:195
 msgid "Do not install this package unless you are sure it is safe to do so."
-msgstr "Не устанавливайте этот пакет если вы не уверены в последствиях установки."
+msgstr "Не устанавливайте этот пакет, если не уверены в том, что он безопаснен."
 
 #: ../src/pk-polkit-action-lookup.c:196
 msgid "Do not install these packages unless you are sure it is safe to do so."
-msgstr "Не устанавливайте эти пакеты если вы не уверены в последствиях установки."
+msgstr "Не устанавливайте эти пакеты, если не уверены в том, что они безопасны."
 
 #. TRANSLATORS: too many packages to list each one
 #: ../src/pk-polkit-action-lookup.c:273
@@ -1975,7 +1981,7 @@ msgstr "Отладка выбранных функций"
 #. TRANSLATORS: save to a log
 #: ../src/egg-debug.c:465
 msgid "Log debugging data to a file"
-msgstr "Сохранить отладочную информацию в журнал"
+msgstr "Записать отладочную информацию в журнал"
 
 #: ../src/egg-debug.c:469
 msgid "Debugging Options"
commit 0c0c5d2401570a3ac2b83980f81ad0ebb6d5bd61
Author: kristho <kristho at fedoraproject.org>
Date:   Wed Mar 10 21:09:30 2010 +0000

    Sending translation for Danish

diff --git a/po/da.po b/po/da.po
index 7a33319..da38724 100644
--- a/po/da.po
+++ b/po/da.po
@@ -7,8 +7,8 @@ msgid ""
 msgstr ""
 "Project-Id-Version: packagekit\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2010-02-15 15:21+0000\n"
-"PO-Revision-Date: 2010-02-24 23:36+0100\n"
+"POT-Creation-Date: 2010-03-10 20:48+0000\n"
+"PO-Revision-Date: 2010-03-10 22:08+0100\n"
 "Last-Translator: Kris Thomsen <lakristho at gmail.com>\n"
 "Language-Team: Danish <dansk at dansk-gruppen.dk>\n"
 "MIME-Version: 1.0\n"
@@ -288,18 +288,22 @@ msgstr "Overførslen kunne ikke gennemføres"
 msgid "There are no updates available at this time."
 msgstr "Der er ingen tilgængelige opdateringer i øjeblikket."
 
+#: ../client/pk-console.c:749
+msgid "There are no upgrades available at this time."
+msgstr "Der er ingen tilgængelige opgraderinger i øjeblikket."
+
 #. TRANSLATORS: a package needs to restart their system
-#: ../client/pk-console.c:814
+#: ../client/pk-console.c:816
 msgid "Please restart the computer to complete the update."
 msgstr "Genstart venligst computeren for at fuldføre opdateringen."
 
 #. TRANSLATORS: a package needs to restart the session
-#: ../client/pk-console.c:817
+#: ../client/pk-console.c:819
 msgid "Please logout and login to complete the update."
 msgstr "Log venligst ud og ind igen for at fuldføre opdateringen."
 
 #. TRANSLATORS: a package needs to restart their system (due to security)
-#: ../client/pk-console.c:820
+#: ../client/pk-console.c:822
 msgid ""
 "Please restart the computer to complete the update as important security "
 "updates have been installed."
@@ -308,7 +312,7 @@ msgstr ""
 "sikkerhedsopdateringer er blevet installeret."
 
 #. TRANSLATORS: a package needs to restart the session (due to security)
-#: ../client/pk-console.c:823
+#: ../client/pk-console.c:825
 msgid ""
 "Please logout and login to complete the update as important security updates "
 "have been installed."
@@ -317,29 +321,29 @@ msgstr ""
 "sikkerhedsopdateringer er blevet installeret."
 
 #. TRANSLATORS: The user used 'pkcon install dave.rpm' rather than 'pkcon install-local dave.rpm'
-#: ../client/pk-console.c:849
+#: ../client/pk-console.c:851
 #, c-format
 msgid ""
 "Extected package name, actually got file. Try using 'pkcon install-local %s' "
 "instead."
 msgstr ""
-"Forventet pakkenavn fik faktisk fil. Prøv at bruge \"pkcon install-local %s\" "
-"istedet."
+"Forventet pakkenavn fik faktisk fil. Prøv at bruge \"pkcon install-local %s"
+"\" istedet."
 
 #. TRANSLATORS: There was an error getting the list of files for the package. The detailed error follows
-#: ../client/pk-console.c:857
+#: ../client/pk-console.c:859
 #, c-format
 msgid "This tool could not find any available package: %s"
 msgstr "Dette værktøj kunne ikke finde nogen tilgængelig pakke: %s"
 
 #. TRANSLATORS: There was an error getting the list of files for the package. The detailed error follows
-#: ../client/pk-console.c:885
+#: ../client/pk-console.c:887
 #, c-format
 msgid "This tool could not find the installed package: %s"
 msgstr "Dette værktøj kunne ikke finde den installerede pakke: %s"
 
 #. TRANSLATORS: There was an error getting the list of files for the package. The detailed error follows
-#: ../client/pk-console.c:913 ../client/pk-console.c:941
+#: ../client/pk-console.c:915 ../client/pk-console.c:943
 #, c-format
 msgid "This tool could not find the package: %s"
 msgstr "Dette værktøj kunne ikke finde pakken: %s"
@@ -348,178 +352,181 @@ msgstr "Dette værktøj kunne ikke finde pakken: %s"
 #. TRANSLATORS: There was an error getting the dependencies for the package. The detailed error follows
 #. TRANSLATORS: There was an error getting the details about the package. The detailed error follows
 #. TRANSLATORS: The package name was not found in any software sources. The detailed error follows
-#: ../client/pk-console.c:969 ../client/pk-console.c:997
-#: ../client/pk-console.c:1025 ../client/pk-console.c:1053
-#: ../client/pk-console.c:1081
+#: ../client/pk-console.c:971 ../client/pk-console.c:999
+#: ../client/pk-console.c:1027 ../client/pk-console.c:1055
+#: ../client/pk-console.c:1083
 #, c-format
 msgid "This tool could not find all the packages: %s"
 msgstr "Dette værktøj kunne ikke finde alle pakkerne: %s"
 
 #. TRANSLATORS: This is when the daemon crashed, and we are up shit creek without a paddle
-#: ../client/pk-console.c:1110
+#: ../client/pk-console.c:1112
 msgid "The daemon crashed mid-transaction!"
 msgstr "Dæmonen brød sammen under overførslen!"
 
 #. TRANSLATORS: This is the header to the --help menu
-#: ../client/pk-console.c:1144
+#: ../client/pk-console.c:1146
 msgid "PackageKit Console Interface"
 msgstr "PackageKit konsolgrænseflade"
 
 #. these are commands we can use with pkcon
-#: ../client/pk-console.c:1146
+#: ../client/pk-console.c:1148
 msgid "Subcommands:"
 msgstr "Underkommandoer:"
 
 #. TRANSLATORS: we keep a database updated with the time that an action was last executed
-#: ../client/pk-console.c:1225
+#: ../client/pk-console.c:1227
 msgid "Failed to get the time since this action was last completed"
 msgstr "Kunne ikke hente tid siden denne handling sidst blev gennemført"
 
 #. TRANSLATORS: command line argument, just show the version string
-#: ../client/pk-console.c:1261 ../client/pk-monitor.c:306
+#: ../client/pk-console.c:1263 ../client/pk-monitor.c:306
 msgid "Show the program version and exit"
 msgstr "Vis programversionen og afslut"
 
 #. TRANSLATORS: command line argument, use a filter to narrow down results
-#: ../client/pk-console.c:1264
+#: ../client/pk-console.c:1266
 msgid "Set the filter, e.g. installed"
 msgstr "Sæt filteret, f.eks. installeret"
 
 #. TRANSLATORS: command line argument, work asynchronously
-#: ../client/pk-console.c:1267
+#: ../client/pk-console.c:1269
 msgid "Exit without waiting for actions to complete"
 msgstr "Afslut uden at vente på at handlingerne færdiggøres"
 
 #. command line argument, do we ask questions
-#: ../client/pk-console.c:1270
+#: ../client/pk-console.c:1272
 #: ../contrib/debuginfo-install/pk-debuginfo-install.c:527
 msgid "Install the packages without asking for confirmation"
 msgstr "Installér pakkerne uden at spørge efter bekræftelse"
 
 #. TRANSLATORS: command line argument, this command is not a priority
-#: ../client/pk-console.c:1273
+#: ../client/pk-console.c:1275
 msgid "Run the command using idle network bandwidth and also using less power"
-msgstr "Kør kommandoen ved at bruge lav netværksbåndbredde, hvilket bruger mindre strøm"
+msgstr ""
+"Kør kommandoen ved at bruge lav netværksbåndbredde, hvilket bruger mindre "
+"strøm"
 
 #. TRANSLATORS: command line argument, just output without fancy formatting
-#: ../client/pk-console.c:1276
+#: ../client/pk-console.c:1278
 msgid ""
 "Print to screen a machine readable output, rather than using animated widgets"
 msgstr ""
-"Udskriv for at vise maskinlæsbart output, istedet for at bruge animerede widgets"
+"Udskriv for at vise maskinlæsbart output, istedet for at bruge animerede "
+"widgets"
 
 #. TRANSLATORS: we failed to contact the daemon
-#: ../client/pk-console.c:1298
+#: ../client/pk-console.c:1300
 msgid "Failed to contact PackageKit"
 msgstr "Kunne ikke kontakte PackageKit"
 
 #. TRANSLATORS: The user specified an incorrect filter
-#: ../client/pk-console.c:1356
+#: ../client/pk-console.c:1358
 msgid "The filter specified was invalid"
 msgstr "Filteret det blev angivet er ugyldigt"
 
 #. TRANSLATORS: a search type can be name, details, file, etc
-#: ../client/pk-console.c:1375
+#: ../client/pk-console.c:1377
 msgid "A search type is required, e.g. name"
 msgstr "En søgetype kræves, f.eks. navn"
 
 #. TRANSLATORS: the user needs to provide a search term
-#: ../client/pk-console.c:1382 ../client/pk-console.c:1394
-#: ../client/pk-console.c:1406 ../client/pk-console.c:1418
+#: ../client/pk-console.c:1384 ../client/pk-console.c:1396
+#: ../client/pk-console.c:1408 ../client/pk-console.c:1420
 msgid "A search term is required"
 msgstr "En søgeterm kræves"
 
 #. TRANSLATORS: the search type was provided, but invalid
-#: ../client/pk-console.c:1428
+#: ../client/pk-console.c:1430
 msgid "Invalid search type"
 msgstr "Ugyldig søgetype"
 
 #. TRANSLATORS: the user did not specify what they wanted to install
-#: ../client/pk-console.c:1434
+#: ../client/pk-console.c:1436
 msgid "A package name to install is required"
 msgstr "Et pakkenavn til installation er påkrævet"
 
 #. TRANSLATORS: the user did not specify what they wanted to install
-#: ../client/pk-console.c:1443
+#: ../client/pk-console.c:1445
 msgid "A filename to install is required"
 msgstr "Et filnavn til installation er påkrævet"
 
 #. TRANSLATORS: geeky error, 99.9999% of users won't see this
-#: ../client/pk-console.c:1455
+#: ../client/pk-console.c:1457
 msgid "A type, key_id and package_id are required"
 msgstr "En type, nøgle_id og pakke_id kræves"
 
 #. TRANSLATORS: the user did not specify what they wanted to remove
-#: ../client/pk-console.c:1466
+#: ../client/pk-console.c:1468
 msgid "A package name to remove is required"
 msgstr "Et pakkenavn til fjernelse kræves"
 
 #. TRANSLATORS: the user did not specify anything about what to download or where
-#: ../client/pk-console.c:1475
+#: ../client/pk-console.c:1477
 msgid "A destination directory and the package names to download are required"
 msgstr "En destinationsmappe og pakkenavnene kræves for at blive hentet"
 
 #. TRANSLATORS: the directory does not exist, so we can't continue
-#: ../client/pk-console.c:1482
+#: ../client/pk-console.c:1484
 msgid "Directory not found"
 msgstr "Mappe ikke fundet"
 
 #. TRANSLATORS: geeky error, 99.9999% of users won't see this
-#: ../client/pk-console.c:1491
+#: ../client/pk-console.c:1493
 msgid "A licence identifier (eula-id) is required"
 msgstr "En licensgenkender (eula-id) kræves"
 
 #. TRANSLATORS: geeky error, 99.9999% of users won't see this
-#: ../client/pk-console.c:1502
+#: ../client/pk-console.c:1504
 msgid "A transaction identifier (tid) is required"
 msgstr "En overførselsgenkender (tid) kræves"
 
 #. TRANSLATORS: The user did not specify a package name
-#: ../client/pk-console.c:1523
+#: ../client/pk-console.c:1525
 msgid "A package name to resolve is required"
 msgstr "Et pakkenavn til at løse kræves"
 
 #. TRANSLATORS: The user did not specify a repository (software source) name
-#: ../client/pk-console.c:1534 ../client/pk-console.c:1545
+#: ../client/pk-console.c:1536 ../client/pk-console.c:1547
 msgid "A repository name is required"
 msgstr "Et pakkearkivnavn kræves"
 
 #. TRANSLATORS: The user didn't provide any data
-#: ../client/pk-console.c:1556
+#: ../client/pk-console.c:1558
 msgid "A repo name, parameter and value are required"
 msgstr "Et pakkearkivnavn, parameter og værdi kræves"
 
 #. TRANSLATORS: The user didn't specify what action to use
-#: ../client/pk-console.c:1573
+#: ../client/pk-console.c:1575
 msgid "An action, e.g. 'update-system' is required"
 msgstr "En handling, f.eks. \"update-system\" kræves"
 
 #. TRANSLATORS: The user specified an invalid action
-#: ../client/pk-console.c:1580
+#: ../client/pk-console.c:1582
 msgid "A correct role is required"
 msgstr "En korrekt rolle kræves"
 
 #. TRANSLATORS: The user did not provide a package name
 #. TRANSLATORS: This is when the user fails to supply the package name
-#: ../client/pk-console.c:1590 ../client/pk-console.c:1605
-#: ../client/pk-console.c:1614 ../client/pk-console.c:1634
-#: ../client/pk-console.c:1643 ../client/pk-generate-pack.c:316
+#: ../client/pk-console.c:1592 ../client/pk-console.c:1607
+#: ../client/pk-console.c:1616 ../client/pk-console.c:1636
+#: ../client/pk-console.c:1645 ../client/pk-generate-pack.c:316
 msgid "A package name is required"
 msgstr "Et pakkenavn kræves"
 
 #. TRANSLATORS: each package "provides" certain things, e.g. mime(gstreamer-decoder-mp3), the user didn't specify it
-#: ../client/pk-console.c:1623
+#: ../client/pk-console.c:1625
 msgid "A package provide string is required"
 msgstr "En pakke udbydningsstreng kræves"
 
 #. TRANSLATORS: The user tried to use an unsupported option on the command line
-#: ../client/pk-console.c:1703
+#: ../client/pk-console.c:1705
 #, c-format
 msgid "Option '%s' is not supported"
 msgstr "Indstilling \"%s\" er ikke understøttet"
 
 #. TRANSLATORS: Generic failure of what they asked to do
-#: ../client/pk-console.c:1713
+#: ../client/pk-console.c:1715
 msgid "Command failed"
 msgstr "Kommando fejlede"
 
@@ -1948,7 +1955,8 @@ msgstr "Opdatér ikke denne pakke medmindre du er sikker på, at det er sikkert.
 
 #: ../src/pk-polkit-action-lookup.c:177
 msgid "Do not update these packages unless you are sure it is safe to do so."
-msgstr "Opdatér ikke disse pakker medmindre du er sikker på, at det er sikkert."
+msgstr ""
+"Opdatér ikke disse pakker medmindre du er sikker på, at det er sikkert."
 
 #: ../src/pk-polkit-action-lookup.c:195
 msgid "Do not install this package unless you are sure it is safe to do so."
commit 134fe6080cf89aa7f326506ec05a2eb3f37e3247
Author: yurchor <yurchor at fedoraproject.org>
Date:   Wed Mar 10 18:20:07 2010 +0000

    Sending translation for Ukrainian

diff --git a/po/uk.po b/po/uk.po
index bad95ac..5bbb994 100644
--- a/po/uk.po
+++ b/po/uk.po
@@ -7,8 +7,8 @@ msgid ""
 msgstr ""
 "Project-Id-Version: packagekit.master\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2010-03-02 09:15+0000\n"
-"PO-Revision-Date: 2010-03-02 14:32+0200\n"
+"POT-Creation-Date: 2010-03-10 17:38+0000\n"
+"PO-Revision-Date: 2010-03-10 20:19+0200\n"
 "Last-Translator: Yuri Chornoivan <yurchor at ukr.net>\n"
 "Language-Team: Ukrainian <translation at linux.org.ua>\n"
 "MIME-Version: 1.0\n"
@@ -291,18 +291,22 @@ msgstr "Спроба виконання операції зазнала невд
 msgid "There are no updates available at this time."
 msgstr "На поточний момент оновлень не виявлено."
 
+#: ../client/pk-console.c:749
+msgid "There are no upgrades available at this time."
+msgstr "На поточний момент оновлень не виявлено."
+
 #. TRANSLATORS: a package needs to restart their system
-#: ../client/pk-console.c:814
+#: ../client/pk-console.c:816
 msgid "Please restart the computer to complete the update."
 msgstr "Щоб завершити оновлення, перезавантажте систему."
 
 #. TRANSLATORS: a package needs to restart the session
-#: ../client/pk-console.c:817
+#: ../client/pk-console.c:819
 msgid "Please logout and login to complete the update."
 msgstr "Щоб завершити оновлення, вийдіть з облікового запису і увійдіть знову."
 
 #. TRANSLATORS: a package needs to restart their system (due to security)
-#: ../client/pk-console.c:820
+#: ../client/pk-console.c:822
 msgid ""
 "Please restart the computer to complete the update as important security "
 "updates have been installed."
@@ -310,7 +314,7 @@ msgstr ""
 "перезавантажте систему, щоб завершити встановлення важливих оновлень безпеки."
 
 #. TRANSLATORS: a package needs to restart the session (due to security)
-#: ../client/pk-console.c:823
+#: ../client/pk-console.c:825
 msgid ""
 "Please logout and login to complete the update as important security updates "
 "have been installed."
@@ -319,7 +323,7 @@ msgstr ""
 "запису і увійдіть до нього знову."
 
 #. TRANSLATORS: The user used 'pkcon install dave.rpm' rather than 'pkcon install-local dave.rpm'
-#: ../client/pk-console.c:849
+#: ../client/pk-console.c:851
 #, c-format
 msgid ""
 "Extected package name, actually got file. Try using 'pkcon install-local %s' "
@@ -329,19 +333,19 @@ msgstr ""
 "командою «pkcon install-local %s»."
 
 #. TRANSLATORS: There was an error getting the list of files for the package. The detailed error follows
-#: ../client/pk-console.c:857
+#: ../client/pk-console.c:859
 #, c-format
 msgid "This tool could not find any available package: %s"
 msgstr "Програмі не вдалося знайти жодного доступного пакунка: %s"
 
 #. TRANSLATORS: There was an error getting the list of files for the package. The detailed error follows
-#: ../client/pk-console.c:885
+#: ../client/pk-console.c:887
 #, c-format
 msgid "This tool could not find the installed package: %s"
 msgstr "Програмі не вдалося знайти встановлений пакунок: %s"
 
 #. TRANSLATORS: There was an error getting the list of files for the package. The detailed error follows
-#: ../client/pk-console.c:913 ../client/pk-console.c:941
+#: ../client/pk-console.c:915 ../client/pk-console.c:943
 #, c-format
 msgid "This tool could not find the package: %s"
 msgstr "Програмі не вдалося знайти пакунок: %s"
@@ -350,63 +354,63 @@ msgstr "Програмі не вдалося знайти пакунок: %s"
 #. TRANSLATORS: There was an error getting the dependencies for the package. The detailed error follows
 #. TRANSLATORS: There was an error getting the details about the package. The detailed error follows
 #. TRANSLATORS: The package name was not found in any software sources. The detailed error follows
-#: ../client/pk-console.c:969 ../client/pk-console.c:997
-#: ../client/pk-console.c:1025 ../client/pk-console.c:1053
-#: ../client/pk-console.c:1081
+#: ../client/pk-console.c:971 ../client/pk-console.c:999
+#: ../client/pk-console.c:1027 ../client/pk-console.c:1055
+#: ../client/pk-console.c:1083
 #, c-format
 msgid "This tool could not find all the packages: %s"
 msgstr "Програмі не вдалося знайти всі пакунки: %s"
 
 #. TRANSLATORS: This is when the daemon crashed, and we are up shit creek without a paddle
-#: ../client/pk-console.c:1110
+#: ../client/pk-console.c:1112
 msgid "The daemon crashed mid-transaction!"
 msgstr "Аварійне завершення фонової служби під час операції!"
 
 #. TRANSLATORS: This is the header to the --help menu
-#: ../client/pk-console.c:1144
+#: ../client/pk-console.c:1146
 msgid "PackageKit Console Interface"
 msgstr "Консольний інтерфейс PackageKit"
 
 #. these are commands we can use with pkcon
-#: ../client/pk-console.c:1146
+#: ../client/pk-console.c:1148
 msgid "Subcommands:"
 msgstr "Підкоманди:"
 
 #. TRANSLATORS: we keep a database updated with the time that an action was last executed
-#: ../client/pk-console.c:1225
+#: ../client/pk-console.c:1227
 msgid "Failed to get the time since this action was last completed"
 msgstr "Не вдалося визначити час, коли цю дію було виконано востаннє"
 
 #. TRANSLATORS: command line argument, just show the version string
-#: ../client/pk-console.c:1261 ../client/pk-monitor.c:306
+#: ../client/pk-console.c:1263 ../client/pk-monitor.c:306
 msgid "Show the program version and exit"
 msgstr "Показати версію програми і завершити роботу"
 
 #. TRANSLATORS: command line argument, use a filter to narrow down results
-#: ../client/pk-console.c:1264
+#: ../client/pk-console.c:1266
 msgid "Set the filter, e.g. installed"
 msgstr "Встановити фільтр, наприклад, встановлені"
 
 #. TRANSLATORS: command line argument, work asynchronously
-#: ../client/pk-console.c:1267
+#: ../client/pk-console.c:1269
 msgid "Exit without waiting for actions to complete"
 msgstr "Завершити роботу, не чекаючи на завершення дії"
 
 #. command line argument, do we ask questions
-#: ../client/pk-console.c:1270
+#: ../client/pk-console.c:1272
 #: ../contrib/debuginfo-install/pk-debuginfo-install.c:527
 msgid "Install the packages without asking for confirmation"
 msgstr "Встановити пакунки без запиту щодо підтвердження"
 
 #. TRANSLATORS: command line argument, this command is not a priority
-#: ../client/pk-console.c:1273
+#: ../client/pk-console.c:1275
 msgid "Run the command using idle network bandwidth and also using less power"
 msgstr ""
 "Виконати команду з мінімальним використанням мережевого каналу і меншою "
 "витратою ресурсів системи"
 
 #. TRANSLATORS: command line argument, just output without fancy formatting
-#: ../client/pk-console.c:1276
+#: ../client/pk-console.c:1278
 msgid ""
 "Print to screen a machine readable output, rather than using animated widgets"
 msgstr ""
@@ -414,118 +418,118 @@ msgstr ""
 "анімованих віджетів"
 
 #. TRANSLATORS: we failed to contact the daemon
-#: ../client/pk-console.c:1298
+#: ../client/pk-console.c:1300
 msgid "Failed to contact PackageKit"
 msgstr "Не вдалося зв’язатися з PackageKit"
 
 #. TRANSLATORS: The user specified an incorrect filter
-#: ../client/pk-console.c:1356
+#: ../client/pk-console.c:1358
 msgid "The filter specified was invalid"
 msgstr "Вказано некоректний фільтр"
 
 #. TRANSLATORS: a search type can be name, details, file, etc
-#: ../client/pk-console.c:1375
+#: ../client/pk-console.c:1377
 msgid "A search type is required, e.g. name"
 msgstr "Тип пошуку, якщо такий потрібен, наприклад, назва"
 
 #. TRANSLATORS: the user needs to provide a search term
-#: ../client/pk-console.c:1382 ../client/pk-console.c:1394
-#: ../client/pk-console.c:1406 ../client/pk-console.c:1418
+#: ../client/pk-console.c:1384 ../client/pk-console.c:1396
+#: ../client/pk-console.c:1408 ../client/pk-console.c:1420
 msgid "A search term is required"
 msgstr "Потрібен ключ пошуку"
 
 #. TRANSLATORS: the search type was provided, but invalid
-#: ../client/pk-console.c:1428
+#: ../client/pk-console.c:1430
 msgid "Invalid search type"
 msgstr "Некоректний тип пошуку"
 
 #. TRANSLATORS: the user did not specify what they wanted to install
-#: ../client/pk-console.c:1434
+#: ../client/pk-console.c:1436
 msgid "A package name to install is required"
 msgstr "Слід вказати назву пакунка, який слід встановити"
 
 #. TRANSLATORS: the user did not specify what they wanted to install
-#: ../client/pk-console.c:1443
+#: ../client/pk-console.c:1445
 msgid "A filename to install is required"
 msgstr "Слід вказати назву файла, який слід встановити"
 
 #. TRANSLATORS: geeky error, 99.9999% of users won't see this
-#: ../client/pk-console.c:1455
+#: ../client/pk-console.c:1457
 msgid "A type, key_id and package_id are required"
 msgstr "Слід вказати тип, ідентифікатор ключа і ідентифікатор пакунка"
 
 #. TRANSLATORS: the user did not specify what they wanted to remove
-#: ../client/pk-console.c:1466
+#: ../client/pk-console.c:1468
 msgid "A package name to remove is required"
 msgstr "Слід вказати назву пакунка, який потрібно вилучити"
 
 #. TRANSLATORS: the user did not specify anything about what to download or where
-#: ../client/pk-console.c:1475
+#: ../client/pk-console.c:1477
 msgid "A destination directory and the package names to download are required"
 msgstr ""
 "Слід вказати каталог призначення і назви пакунків, які потрібно звантажити"
 
 #. TRANSLATORS: the directory does not exist, so we can't continue
-#: ../client/pk-console.c:1482
+#: ../client/pk-console.c:1484
 msgid "Directory not found"
 msgstr "Каталог не знайдено"
 
 #. TRANSLATORS: geeky error, 99.9999% of users won't see this
-#: ../client/pk-console.c:1491
+#: ../client/pk-console.c:1493
 msgid "A licence identifier (eula-id) is required"
 msgstr "Слід вказати ідентифікатор ліцензії (eula-id)"
 
 #. TRANSLATORS: geeky error, 99.9999% of users won't see this
-#: ../client/pk-console.c:1502
+#: ../client/pk-console.c:1504
 msgid "A transaction identifier (tid) is required"
 msgstr "Слід вказати ідентифікатор операції (tid)"
 
 #. TRANSLATORS: The user did not specify a package name
-#: ../client/pk-console.c:1523
+#: ../client/pk-console.c:1525
 msgid "A package name to resolve is required"
 msgstr "Слід вказати назву пакунка для розв’язання конфлікту"
 
 #. TRANSLATORS: The user did not specify a repository (software source) name
-#: ../client/pk-console.c:1534 ../client/pk-console.c:1545
+#: ../client/pk-console.c:1536 ../client/pk-console.c:1547
 msgid "A repository name is required"
 msgstr "Слід вказати назву сховища"
 
 #. TRANSLATORS: The user didn't provide any data
-#: ../client/pk-console.c:1556
+#: ../client/pk-console.c:1558
 msgid "A repo name, parameter and value are required"
 msgstr "Слід вказати назву сховища, параметр і значення"
 
 #. TRANSLATORS: The user didn't specify what action to use
-#: ../client/pk-console.c:1573
+#: ../client/pk-console.c:1575
 msgid "An action, e.g. 'update-system' is required"
 msgstr "Слід вказати дію, наприклад «update-system»"
 
 #. TRANSLATORS: The user specified an invalid action
-#: ../client/pk-console.c:1580
+#: ../client/pk-console.c:1582
 msgid "A correct role is required"
 msgstr "Слід вказати належну роль"
 
 #. TRANSLATORS: The user did not provide a package name
 #. TRANSLATORS: This is when the user fails to supply the package name
-#: ../client/pk-console.c:1590 ../client/pk-console.c:1605
-#: ../client/pk-console.c:1614 ../client/pk-console.c:1634
-#: ../client/pk-console.c:1643 ../client/pk-generate-pack.c:316
+#: ../client/pk-console.c:1592 ../client/pk-console.c:1607
+#: ../client/pk-console.c:1616 ../client/pk-console.c:1636
+#: ../client/pk-console.c:1645 ../client/pk-generate-pack.c:316
 msgid "A package name is required"
 msgstr "Слід вказати назву пакунка"
 
 #. TRANSLATORS: each package "provides" certain things, e.g. mime(gstreamer-decoder-mp3), the user didn't specify it
-#: ../client/pk-console.c:1623
+#: ../client/pk-console.c:1625
 msgid "A package provide string is required"
 msgstr "Слід вказати рядок вмісту"
 
 #. TRANSLATORS: The user tried to use an unsupported option on the command line
-#: ../client/pk-console.c:1703
+#: ../client/pk-console.c:1705
 #, c-format
 msgid "Option '%s' is not supported"
 msgstr "Підтримки параметра «%s» не передбачено"
 
 #. TRANSLATORS: Generic failure of what they asked to do
-#: ../client/pk-console.c:1713
+#: ../client/pk-console.c:1715
 msgid "Command failed"
 msgstr "Спроба виконання команди зазнала невдачі"
 
commit c9a86d89d052fe6bbca75e03cfc2c9be5c39dad9
Author: Richard Hughes <richard at hughsie.com>
Date:   Wed Mar 10 16:56:47 2010 +0000

    yum: trivial: bring back the old yum support in place if we ever want to test zif

diff --git a/backends/yum/libzif/zif-store-array.c b/backends/yum/libzif/zif-store-array.c
index 387d2d1..326aece 100644
--- a/backends/yum/libzif/zif-store-array.c
+++ b/backends/yum/libzif/zif-store-array.c
@@ -295,10 +295,9 @@ zif_store_array_find_package (GPtrArray *store_array, const gchar *package_id, G
 	ZifPackage *package = NULL;
 	ZifCompletion *completion_local = NULL;
 
-
 	/* nothing to do */
 	if (store_array->len == 0) {
-		egg_debug ("nothing to do");
+		g_set_error_literal (error, 1, 0, "package cannot be found as the store array is empty");
 		goto out;
 	}
 
@@ -317,6 +316,12 @@ zif_store_array_find_package (GPtrArray *store_array, const gchar *package_id, G
 		/* this section done */
 		zif_completion_done (completion);
 	}
+
+	/* nothing to do */
+	if (package == NULL) {
+		g_set_error_literal (error, 1, 0, "package cannot be found");
+		goto out;
+	}
 out:
 	return package;
 }
diff --git a/backends/yum/pk-backend-yum.c b/backends/yum/pk-backend-yum.c
index c4b06d4..7a6e7a8 100644
--- a/backends/yum/pk-backend-yum.c
+++ b/backends/yum/pk-backend-yum.c
@@ -30,6 +30,8 @@
 #define YUM_BACKEND_LOCKING_RETRIES		10
 #define YUM_BACKEND_LOCKING_DELAY		2 /* seconds */
 
+static gboolean use_zif = TRUE;
+
 typedef struct {
 	PkBackendSpawn	*spawn;
 	GFileMonitor	*monitor;
@@ -238,6 +240,10 @@ backend_initialize (PkBackend *backend)
 		g_error_free (error);
 	}
 
+	/* it seems some people are not ready for the awesomeness */
+	if (!use_zif)
+		goto out;
+
 	/* use a timer for profiling */
 	priv->timer = g_timer_new ();
 
@@ -351,6 +357,35 @@ backend_get_groups (PkBackend *backend)
 	GError *error = NULL;
 	PkBitfield groups;
 
+	/* it seems some people are not ready for the awesomeness */
+	if (!use_zif) {
+		groups = pk_bitfield_from_enums (
+			PK_GROUP_ENUM_COLLECTIONS,
+			PK_GROUP_ENUM_NEWEST,
+			PK_GROUP_ENUM_ADMIN_TOOLS,
+			PK_GROUP_ENUM_DESKTOP_GNOME,
+			PK_GROUP_ENUM_DESKTOP_KDE,
+			PK_GROUP_ENUM_DESKTOP_XFCE,
+			PK_GROUP_ENUM_DESKTOP_OTHER,
+			PK_GROUP_ENUM_EDUCATION,
+			PK_GROUP_ENUM_FONTS,
+			PK_GROUP_ENUM_GAMES,
+			PK_GROUP_ENUM_GRAPHICS,
+			PK_GROUP_ENUM_INTERNET,
+			PK_GROUP_ENUM_LEGACY,
+			PK_GROUP_ENUM_LOCALIZATION,
+			PK_GROUP_ENUM_MULTIMEDIA,
+			PK_GROUP_ENUM_OFFICE,
+			PK_GROUP_ENUM_OTHER,
+			PK_GROUP_ENUM_PROGRAMMING,
+			PK_GROUP_ENUM_PUBLISHING,
+			PK_GROUP_ENUM_SERVERS,
+			PK_GROUP_ENUM_SYSTEM,
+			PK_GROUP_ENUM_VIRTUALIZATION,
+			-1);
+		goto out;
+	}
+
 	/* get the dynamic group list */
 	groups = zif_groups_get_groups (priv->groups, &error);
 	if (groups == 0) {
@@ -588,7 +623,7 @@ backend_get_details (PkBackend *backend, gchar **package_ids)
 
 	/* check if we can use zif */
 	ret = backend_is_all_installed (package_ids);
-	if (ret) {
+	if (ret && use_zif) {
 		pk_backend_thread_create (backend, backend_get_details_thread);
 		return;
 	}
@@ -710,6 +745,12 @@ out:
 static void
 backend_get_distro_upgrades (PkBackend *backend)
 {
+	/* it seems some people are not ready for the awesomeness */
+	if (!use_zif) {
+		pk_backend_spawn_helper (priv->spawn, "yumBackend.py", "get-distro-upgrades", NULL);
+		return;
+	}
+
 	pk_backend_thread_create (backend, backend_get_distro_upgrades_thread);
 }
 
@@ -830,7 +871,7 @@ backend_get_files (PkBackend *backend, gchar **package_ids)
 
 	/* check if we can use zif */
 	ret = backend_is_all_installed (package_ids);
-	if (ret) {
+	if (ret && use_zif) {
 		pk_backend_thread_create (backend, backend_get_files_thread);
 		return;
 	}
@@ -1195,6 +1236,15 @@ out:
 static void
 backend_get_repo_list (PkBackend *backend, PkBitfield filters)
 {
+	/* it seems some people are not ready for the awesomeness */
+	if (!use_zif) {
+		gchar *filters_text;
+		filters_text = pk_filter_bitfield_to_string (filters);
+		pk_backend_spawn_helper (priv->spawn, "yumBackend.py", "get-repo-list", filters_text, NULL);
+		g_free (filters_text);
+		return;
+	}
+
 	pk_backend_thread_create (backend, backend_get_repo_list_thread);
 }
 
@@ -1267,6 +1317,15 @@ out:
 static void
 backend_repo_enable (PkBackend *backend, const gchar *repo_id, gboolean enabled)
 {
+	/* it seems some people are not ready for the awesomeness */
+	if (!use_zif) {
+		if (enabled == TRUE) {
+			pk_backend_spawn_helper (priv->spawn, "yumBackend.py", "repo-enable", repo_id, "true", NULL);
+		} else {
+			pk_backend_spawn_helper (priv->spawn, "yumBackend.py", "repo-enable", repo_id, "false", NULL);
+		}
+		return;
+	}
 	pk_backend_thread_create (backend, backend_repo_enable_thread);
 }
 
@@ -1522,6 +1581,11 @@ out:
 static void
 backend_get_categories (PkBackend *backend)
 {
+	/* it seems some people are not ready for the awesomeness */
+	if (!use_zif) {
+		pk_backend_spawn_helper (priv->spawn, "yumBackend.py", "get-categories", NULL);
+		return;
+	}
 	pk_backend_thread_create (backend, backend_get_categories_thread);
 }
 
diff --git a/backends/yum/yumBackend.py b/backends/yum/yumBackend.py
index e0c1c68..87ed876 100755
--- a/backends/yum/yumBackend.py
+++ b/backends/yum/yumBackend.py
@@ -790,6 +790,72 @@ class PackageKitYumBackend(PackageKitBaseBackend, PackagekitPackage):
                     package_list = pkgfilter.post_process()
                     self._show_package_list(package_list)
 
+    def get_categories(self):
+        '''
+        Implement the get-categories functionality
+        '''
+        self.status(STATUS_QUERY)
+        self.allow_cancel(True)
+        cats = []
+        try:
+            cats = self.yumbase.comps.categories
+        except yum.Errors.RepoError, e:
+            self.error(ERROR_NO_CACHE, "failed to get comps list: %s" %_to_unicode(e), exit=False)
+        except Exception, e:
+            self.error(ERROR_INTERNAL_ERROR, _format_str(traceback.format_exc()))
+        else:
+            if len(cats) == 0:
+                self.error(ERROR_GROUP_LIST_INVALID, "no comps categories", exit=False)
+                return
+            for cat in cats:
+                cat_id = cat.categoryid
+                # yum >= 3.2.10
+                # name = cat.nameByLang(self.lang)
+                # summary = cat.descriptionByLang(self.lang)
+                name = cat.name
+                summary = cat.description
+                fn = "/usr/share/pixmaps/comps/%s.png" % cat_id
+                if os.access(fn, os.R_OK):
+                    icon = cat_id
+                else:
+                    icon = "image-missing"
+                self.category("", cat_id, name, summary, icon)
+                self._get_groups(cat_id)
+
+    def _get_groups(self, cat_id):
+        '''
+        Implement the get-collections functionality
+        '''
+        self.status(STATUS_QUERY)
+        self.allow_cancel(True)
+        if cat_id:
+            cats = [cat_id]
+        else:
+            cats =  [cat.categoryid for cat in self.yumbase.comps.categories]
+        for cat in cats:
+            grps = []
+            for grp_id in self.comps.get_groups(cat):
+                try:
+                    grp = self.yumbase.comps.return_group(grp_id)
+                except Exception, e:
+                    self.error(ERROR_INTERNAL_ERROR, _format_str(traceback.format_exc()))
+                if grp:
+                    grps.append(grp)
+            for grp in sorted(grps):
+                grp_id = grp.groupid
+                cat_id_name = "@%s" % (grp_id)
+                name = grp.nameByLang(self.lang)
+                summary = grp.descriptionByLang(self.lang)
+                icon = "image-missing"
+                fn = "/usr/share/pixmaps/comps/%s.png" % grp_id
+                if os.access(fn, os.R_OK):
+                    icon = grp_id
+                else:
+                    fn = "/usr/share/pixmaps/comps/%s.png" % cat_id
+                    if os.access(fn, os.R_OK):
+                        icon = cat_id
+                self.category(cat, cat_id_name, name, summary, icon)
+
     def download_packages(self, directory, package_ids):
         '''
         Implement the download-packages functionality
@@ -2253,6 +2319,56 @@ class PackageKitYumBackend(PackageKitBaseBackend, PackagekitPackage):
         package_id = self._pkg_to_id(pkg)
         self.package(package_id, status, pkg.summary)
 
+    def get_distro_upgrades(self):
+        '''
+        Implement the get-distro-upgrades functionality
+        '''
+        try:
+            self._check_init()
+        except PkError, e:
+            self.error(e.code, e.details, exit=False)
+            return
+        self.yumbase.conf.cache = 0 # Allow new files
+        self.allow_cancel(True)
+        self.percentage(None)
+        self.status(STATUS_QUERY)
+
+        # if we're RHEL, then we don't have preupgrade
+        if not os.path.exists('/usr/share/preupgrade/releases.list'):
+            return
+
+        # parse the releases file
+        config = ConfigParser.ConfigParser()
+        config.read('/usr/share/preupgrade/releases.list')
+
+        # find the newest release
+        newest = None
+        last_version = 0
+        for section in config.sections():
+            # we only care about stable versions
+            if config.has_option(section, 'stable') and config.getboolean(section, 'stable'):
+                version = config.getfloat(section, 'version')
+                if (version > last_version):
+                    newest = section
+                    last_version = version
+
+        # got no valid data
+        if not newest:
+            self.error(ERROR_FAILED_CONFIG_PARSING, "could not get latest distro data")
+
+        # are we already on the latest version
+        try:
+            present_version = float(self.yumbase.conf.yumvar['releasever'])
+        except Exception, e:
+            self.error(ERROR_INTERNAL_ERROR, _format_str(traceback.format_exc()))
+        if (present_version >= last_version):
+            return
+
+        # if we have an upgrade candidate then pass back data to daemon
+        tok = newest.split(" ")
+        name = "%s-%s" % (tok[0].lower(), tok[1])
+        self.distro_upgrade(DISTRO_UPGRADE_STABLE, name, newest)
+
     def _get_status(self, notice):
         ut = notice['type']
         if ut == 'security':
@@ -2342,6 +2458,58 @@ class PackageKitYumBackend(PackageKitBaseBackend, PackagekitPackage):
         package_list = pkgfilter.post_process()
         self._show_package_list(package_list)
 
+    def repo_enable(self, repoid, enable):
+        '''
+        Implement the repo-enable functionality
+        '''
+        try:
+            self._check_init()
+        except PkError, e:
+            self.error(e.code, e.details, exit=False)
+            return
+        self.yumbase.conf.cache = 0 # Allow new files
+        self.status(STATUS_INFO)
+        try:
+            repo = self.yumbase.repos.getRepo(repoid)
+            if not enable:
+                if repo.isEnabled():
+                    repo.disablePersistent()
+            else:
+                if not repo.isEnabled():
+                    repo.enablePersistent()
+                    if repoid.find ("rawhide") != -1:
+                        warning = "These packages are untested and still under development." \
+                                  "This repository is used for development of new releases.\n\n" \
+                                  "This repository can see significant daily turnover and major " \
+                                  "functionality changes which cause unexpected problems with " \
+                                  "other development packages.\n" \
+                                  "Please use these packages if you want to work with the " \
+                                  "Fedora developers by testing these new development packages.\n\n" \
+                                  "If this is not correct, please disable the %s software source." % repoid
+                        self.message(MESSAGE_REPO_FOR_DEVELOPERS_ONLY, warning.replace("\n", ";"))
+        except yum.Errors.RepoError, e:
+            self.error(ERROR_REPO_NOT_FOUND, _to_unicode(e))
+        except Exception, e:
+            self.error(ERROR_INTERNAL_ERROR, _format_str(traceback.format_exc()))
+
+    def get_repo_list(self, filters):
+        '''
+        Implement the get-repo-list functionality
+        '''
+        self._check_init()
+        self.yumbase.conf.cache = 0 # Allow new files
+        self.status(STATUS_INFO)
+
+        try:
+            repos = self.yumbase.repos.repos.values()
+        except Exception, e:
+            self.error(ERROR_INTERNAL_ERROR, _format_str(traceback.format_exc()))
+            return
+        for repo in repos:
+            if filters != FILTER_NOT_DEVELOPMENT or not _is_development_repo(repo.id):
+                enabled = repo.isEnabled()
+                self.repo_detail(repo.id, repo.name, enabled)
+
     def _get_obsoleted(self, name):
         try:
             # make sure yum doesn't explode in some internal fit of rage
commit 6c35820b8bc0430a667b05e176846a0c9b49fea6
Author: Richard Hughes <richard at hughsie.com>
Date:   Wed Mar 10 16:54:44 2010 +0000

    trivial: add pk_backend_thread_finished() for use on threads that want to return the signal in the main thread
    
    This is useful for debugging some threading issues. You don't want to use this function.

diff --git a/src/pk-backend.c b/src/pk-backend.c
index cc04a0f..bbff2aa 100644
--- a/src/pk-backend.c
+++ b/src/pk-backend.c
@@ -2056,6 +2056,25 @@ pk_backend_finished (PkBackend *backend)
 }
 
 /**
+ * pk_backend_thread_finished_cb:
+ **/
+static gboolean
+pk_backend_thread_finished_cb (PkBackend *backend)
+{
+	pk_backend_finished (backend);
+	return FALSE;
+}
+
+/**
+ * pk_backend_thread_finished:
+ **/
+void
+pk_backend_thread_finished (PkBackend *backend)
+{
+	g_idle_add ((GSourceFunc) pk_backend_thread_finished_cb, backend);
+}
+
+/**
  * pk_backend_bool_to_string:
  */
 const gchar *
diff --git a/src/pk-backend.h b/src/pk-backend.h
index 700699d..923b36f 100644
--- a/src/pk-backend.h
+++ b/src/pk-backend.h
@@ -198,6 +198,8 @@ gboolean	 pk_backend_not_implemented_yet		(PkBackend	*backend,
 typedef gboolean (*PkBackendThreadFunc)			(PkBackend	*backend);
 gboolean	 pk_backend_thread_create		(PkBackend	*backend,
 							 PkBackendThreadFunc func);
+void		 pk_backend_thread_finished		(PkBackend	*backend);
+
 gboolean	 pk_backend_is_online			(PkBackend	*backend);
 gboolean	 pk_backend_use_background		(PkBackend	*backend);
 
commit 70767734679fd19584f1803aa23f9db23a304f20
Author: Richard Hughes <richard at hughsie.com>
Date:   Wed Mar 10 16:49:39 2010 +0000

    Do not crash libdbus when libnm-glib uses it's own context
    
    libnm_glib.c is trying to do something which isn't really supported with dbus-glib
    which is using a non-default context. This crashes packagekitd when using a threaded
    backend every 1 in 300ish times.
    
    Bug found by Colin Walters <cwalters at gnome.org>, many thanks

diff --git a/configure.ac b/configure.ac
index 3fab046..d91d68c 100644
--- a/configure.ac
+++ b/configure.ac
@@ -148,7 +148,7 @@ GLIB_REQUIRED=2.22.0
 GIO_REQUIRED=2.16.1
 DBUS_REQUIRED=1.1.1
 DBUS_GLIB_REQUIRED=0.74
-LIBNM_GLIB_REQUIRED=0.6.4
+NETWORK_MANAGER_REQUIRED=0.6.4
 POLKIT_GOBJECT_REQUIRED=0.92
 QTCORE_REQUIRED=4.4.0
 QTDBUS_REQUIRED=4.4.0
@@ -286,11 +286,7 @@ dnl ---------------------------------------------------------------------------
 AC_ARG_ENABLE(networkmanager, AS_HELP_STRING([--disable-networkmanager],[Disable NetworkManager support]),
 		enable_networkmanager=$enableval)
 if test x$enable_networkmanager != xno; then
-	PKG_CHECK_MODULES(LIBNM, libnm-glib >= $LIBNM_GLIB_REQUIRED, PK_BUILD_NETWORKMANAGER="yes", PK_BUILD_NETWORKMANAGER="no")
-	# look for the old name for the library too
-	if test "x$PK_BUILD_NETWORKMANAGER" = "xno"; then
-		PKG_CHECK_MODULES(LIBNM, libnm_glib >= $LIBNM_GLIB_REQUIRED, PK_BUILD_NETWORKMANAGER="yes", PK_BUILD_NETWORKMANAGER="no")
-	fi
+	PKG_CHECK_MODULES(NETWORK_MANAGER, NetworkManager >= $NETWORK_MANAGER_REQUIRED, PK_BUILD_NETWORKMANAGER="yes", PK_BUILD_NETWORKMANAGER="no")
 	if test "x$PK_BUILD_NETWORKMANAGER" = "xyes"; then
 		networking_apis="${networking_apis},NetworkManager"
 		AC_DEFINE(PK_BUILD_NETWORKMANAGER, 1, [define if NetworkManager is installed])
@@ -304,8 +300,8 @@ else
 fi
 
 AM_CONDITIONAL(PK_BUILD_NETWORKMANAGER, test x$PK_BUILD_NETWORKMANAGER = xyes)
-AC_SUBST(LIBNM_CFLAGS)
-AC_SUBST(LIBNM_LIBS)
+AC_SUBST(NETWORK_MANAGER_CFLAGS)
+AC_SUBST(NETWORK_MANAGER_LIBS)
 
 dnl ---------------------------------------------------------------------------
 dnl - ConnMan (default enabled)
diff --git a/contrib/PackageKit.spec.in b/contrib/PackageKit.spec.in
index 1a3b4df..97262dd 100644
--- a/contrib/PackageKit.spec.in
+++ b/contrib/PackageKit.spec.in
@@ -37,7 +37,7 @@ BuildRequires: pam-devel
 BuildRequires: libX11-devel
 BuildRequires: xmlto
 BuildRequires: sqlite-devel
-BuildRequires: NetworkManager-glib-devel >= %{libnm_glib_version}
+BuildRequires: NetworkManager-devel >= %{libnm_glib_version}
 BuildRequires: polkit-devel >= %{polkit_version}
 BuildRequires: libtool
 BuildRequires: docbook-utils
diff --git a/src/Makefile.am b/src/Makefile.am
index 80d5caf..250b0e2 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -14,7 +14,7 @@ INCLUDES =						\
 	$(SQLITE_CFLAGS)				\
 	$(POLKIT_CFLAGS)				\
 	$(PYTHON_CFLAGS)				\
-	$(LIBNM_CFLAGS)					\
+	$(NETWORK_MANAGER_CFLAGS)			\
 	$(CONNMAN_CFLAGS)				\
 	-DPACKAGE_LOCALE_DIR=\"$(localedir)\"		\
 	-DBINDIR=\"$(bindir)\"				\
@@ -124,7 +124,7 @@ packagekitd_SOURCES =					\
 packagekitd_LDADD =					\
 	$(GLIB_LIBS)					\
 	$(GMODULE_LIBS)					\
-	$(LIBNM_LIBS)					\
+	$(NETWORK_MANAGER_LIBS)				\
 	$(CONNMAN_LIBS)					\
 	$(DBUS_LIBS)					\
 	$(SQLITE_LIBS)					\
@@ -219,7 +219,7 @@ pk_self_test_LDADD =					\
 	$(GMODULE_LIBS)					\
 	$(DBUS_LIBS)					\
 	$(SQLITE_LIBS)					\
-	$(LIBNM_LIBS)					\
+	$(NETWORK_MANAGER_LIBS)				\
 	$(CONNMAN_LIBS)					\
 	$(PK_GLIB2_LIBS)				\
 	$(POLKIT_LIBS)					\
diff --git a/src/pk-network-stack-nm.c b/src/pk-network-stack-nm.c
index e2530af..28aeafc 100644
--- a/src/pk-network-stack-nm.c
+++ b/src/pk-network-stack-nm.c
@@ -25,7 +25,6 @@
 #include <glib-object.h>
 #include <dbus/dbus-glib.h>
 #include <NetworkManager.h>
-#include <libnm_glib.h>
 
 #include "egg-debug.h"
 #include "egg-dbus-monitor.h"
@@ -38,10 +37,9 @@ struct PkNetworkStackNmPrivate
 {
 	EggDbusMonitor		*dbus_monitor;
 	PkConf			*conf;
-	libnm_glib_ctx		*ctx;
-	guint			 callback_id;
 	DBusGConnection		*bus;
 	gboolean		 is_enabled;
+	DBusGProxy		*proxy_changed;
 };
 
 G_DEFINE_TYPE (PkNetworkStackNm, pk_network_stack_nm, PK_TYPE_NETWORK_STACK)
@@ -253,13 +251,12 @@ pk_network_stack_nm_get_state (PkNetworkStack *nstack)
 }
 
 /**
- * pk_network_stack_nm_nm_changed_cb:
- **/
+ * pk_network_stack_nm_status_changed_cb:
+ */
 static void
-pk_network_stack_nm_nm_changed_cb (libnm_glib_ctx *libnm_ctx, gpointer data)
+pk_network_stack_nm_status_changed_cb (DBusGProxy *proxy, guint status, PkNetworkStackNm *nstack_nm)
 {
 	PkNetworkEnum state;
-	PkNetworkStackNm *nstack_nm = (PkNetworkStackNm *) data;
 
 	g_return_if_fail (PK_IS_NETWORK_STACK_NM (nstack_nm));
 
@@ -293,7 +290,6 @@ static void
 pk_network_stack_nm_init (PkNetworkStackNm *nstack_nm)
 {
 	GError *error = NULL;
-	GMainContext *context;
 	gboolean service_alive;
 
 	nstack_nm->priv = PK_NETWORK_STACK_NM_GET_PRIVATE (nstack_nm);
@@ -302,14 +298,6 @@ pk_network_stack_nm_init (PkNetworkStackNm *nstack_nm)
 	/* do we use this code? */
 	nstack_nm->priv->is_enabled = pk_conf_get_bool (nstack_nm->priv->conf, "UseNetworkManager");
 
-	/* register with callback */
-	context = g_main_context_default ();
-	nstack_nm->priv->ctx = libnm_glib_init ();
-	nstack_nm->priv->callback_id =
-		libnm_glib_register_callback (nstack_nm->priv->ctx,
-					      pk_network_stack_nm_nm_changed_cb,
-					      nstack_nm, context);
-
 	/* get system connection */
 	nstack_nm->priv->bus = dbus_g_bus_get (DBUS_BUS_SYSTEM, &error);
 	if (nstack_nm->priv->bus == NULL) {
@@ -322,6 +310,15 @@ pk_network_stack_nm_init (PkNetworkStackNm *nstack_nm)
 	egg_dbus_monitor_assign (nstack_nm->priv->dbus_monitor, EGG_DBUS_MONITOR_SYSTEM, "org.freedesktop.NetworkManager");
 	service_alive = egg_dbus_monitor_is_connected (nstack_nm->priv->dbus_monitor);
 
+	/* connect to changed as libnm-glib is teh suck and causes multithreading issues with dbus-glib */
+	nstack_nm->priv->proxy_changed = dbus_g_proxy_new_for_name (nstack_nm->priv->bus,
+								    "org.freedesktop.NetworkManager",
+								    "/org/freedesktop/NetworkManager",
+								    "org.freedesktop.NetworkManager");
+	dbus_g_proxy_add_signal (nstack_nm->priv->proxy_changed, "StateChanged", G_TYPE_UINT, G_TYPE_INVALID);
+	dbus_g_proxy_connect_signal (nstack_nm->priv->proxy_changed, "StateChanged",
+				     G_CALLBACK (pk_network_stack_nm_status_changed_cb), nstack_nm, NULL);
+
 	/* NetworkManager isn't up, so we can't use it */
 	if (nstack_nm->priv->is_enabled && !service_alive) {
 		egg_warning ("UseNetworkManager true, but org.freedesktop.NetworkManager not up");
@@ -343,14 +340,11 @@ pk_network_stack_nm_finalize (GObject *object)
 	nstack_nm = PK_NETWORK_STACK_NM (object);
 	g_return_if_fail (nstack_nm->priv != NULL);
 
+	dbus_g_proxy_disconnect_signal (nstack_nm->priv->proxy_changed, "StateChanged",
+					G_CALLBACK (pk_network_stack_nm_status_changed_cb), nstack_nm);
+	g_object_unref (nstack_nm->priv->proxy_changed);
 	g_object_unref (nstack_nm->priv->conf);
 	g_object_unref (nstack_nm->priv->dbus_monitor);
-	libnm_glib_unregister_callback (nstack_nm->priv->ctx, nstack_nm->priv->callback_id);
-	libnm_glib_shutdown (nstack_nm->priv->ctx);
-
-	/* be paranoid */
-	nstack_nm->priv->ctx = NULL;
-	nstack_nm->priv->callback_id = 0;
 
 	G_OBJECT_CLASS (pk_network_stack_nm_parent_class)->finalize (object);
 }
commit a8536977ea35232df89efa3e33245e5edc467b84
Author: Richard Hughes <richard at hughsie.com>
Date:   Wed Mar 10 16:38:06 2010 +0000

    trivial: make the test-succed backend more useful for debugging races

diff --git a/backends/test/pk-backend-test-succeed.c b/backends/test/pk-backend-test-succeed.c
index 8e8d004..52c4f3f 100644
--- a/backends/test/pk-backend-test-succeed.c
+++ b/backends/test/pk-backend-test-succeed.c
@@ -277,7 +277,7 @@ static void
 backend_search_name (PkBackend *backend, PkBitfield filters, gchar **values)
 {
 	pk_backend_set_percentage (backend, PK_BACKEND_PERCENTAGE_INVALID);
-	g_timeout_add (200000, backend_search_name_timeout, backend);
+	g_timeout_add (200, backend_search_name_timeout, backend);
 }
 
 /**
commit ad6c0e521ff9c4789ef33a9ac8f4d806ab966753
Author: Richard Hughes <richard at hughsie.com>
Date:   Wed Mar 10 13:11:13 2010 +0000

    Add a configure option UseThreadsInBackend so we can more easily debug packagekitd

diff --git a/etc/PackageKit.conf.in b/etc/PackageKit.conf.in
index 5a43da5..054c659 100644
--- a/etc/PackageKit.conf.in
+++ b/etc/PackageKit.conf.in
@@ -267,3 +267,15 @@ UseIdleBandwidth=true
 # default=/usr/lib/*/firefox
 NoUpdateProcessList=/usr/lib/*/firefox
 
+# If the backend should use threads to avoid blocking the daemon for other users
+#
+# The daemon, packagekitd, is shared by multiple users. Users are allowed to
+# create and send transactions when other transactions are being processed.
+# To do this, the backend action is created in a thread, but some libraries
+# notably libdbus and dbus-glib, are less threadsafe then they probably should
+# be.
+#
+# Only developers need to change this value, normally for debugging purposes.
+#
+# default=true
+UseThreadsInBackend=true
diff --git a/src/pk-backend.c b/src/pk-backend.c
index 409e4a4..cc04a0f 100644
--- a/src/pk-backend.c
+++ b/src/pk-backend.c
@@ -90,6 +90,7 @@ struct _PkBackendPrivate
 	gboolean		 set_signature;
 	gboolean		 simultaneous;
 	gboolean		 use_time;
+	gboolean		 use_threads;
 	gchar			*transaction_id;
 	gchar			*locale;
 	gchar			*name;
@@ -2137,6 +2138,8 @@ pk_backend_use_background (PkBackend *backend)
 gboolean
 pk_backend_thread_create (PkBackend *backend, PkBackendThreadFunc func)
 {
+	gboolean ret = TRUE;
+
 	g_return_val_if_fail (PK_IS_BACKEND (backend), FALSE);
 	g_return_val_if_fail (func != NULL, FALSE);
 
@@ -2144,12 +2147,24 @@ pk_backend_thread_create (PkBackend *backend, PkBackendThreadFunc func)
 		egg_warning ("already has thread");
 		return FALSE;
 	}
+
+	/* DBus-Glib isn't threadsafe */
+	if (!backend->priv->use_threads) {
+		egg_warning ("not using threads, so daemon will block");
+		ret = func (backend);
+		goto out;
+	}
+
+	/* create a thread */
+	egg_warning ("using threads, so daemon may crash");
 	backend->priv->thread = g_thread_create ((GThreadFunc) func, backend, FALSE, NULL);
 	if (backend->priv->thread == NULL) {
 		egg_warning ("failed to create thread");
-		return FALSE;
+		ret = FALSE;
+		goto out;
 	}
-	return TRUE;
+out:
+	return ret;
 }
 
 /**
@@ -2988,6 +3003,7 @@ pk_backend_init (PkBackend *backend)
 	backend->priv->file_changed_data = NULL;
 	backend->priv->last_package = NULL;
 	backend->priv->locked = FALSE;
+	backend->priv->use_threads = FALSE;
 	backend->priv->signal_finished = 0;
 	backend->priv->speed = 0;
 	backend->priv->signal_error_timeout = 0;
@@ -3009,6 +3025,7 @@ pk_backend_init (PkBackend *backend)
 	/* do we use time estimation? */
 	conf = pk_conf_new ();
 	backend->priv->use_time = pk_conf_get_bool (conf, "UseRemainingTimeEstimation");
+	backend->priv->use_threads = pk_conf_get_bool (conf, "UseThreadsInBackend");
 	g_object_unref (conf);
 
 	pk_backend_reset (backend);
commit 4c8c78f895d88a7c08d919ff9474ae9cfcea6d92
Author: Richard Hughes <richard at hughsie.com>
Date:   Wed Mar 10 13:10:41 2010 +0000

    trivial: make gdb.sh generally more useful

diff --git a/src/gdb.sh b/src/gdb.sh
index 8992589..e6100a6 100755
--- a/src/gdb.sh
+++ b/src/gdb.sh
@@ -1,4 +1,25 @@
+#!/bin/sh
+# Copyright (C) 2008 Richard Hughes <richard at hughsie.com>
+#
+# Licensed under the GNU General Public License Version 2
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+
+if [ "$USER" != "root" ]; then
+    echo "You are not running this script as root. Use sudo."
+    exit 1
+fi
+
+if [ "$1x" = "x" ]; then
+    echo "NO BACKEND SPECIFIED, using dummy"
+    BACKEND=dummy
+else
+    BACKEND=$1
+fi
+
 export G_DEBUG=fatal_criticals
 sudo touch /etc/PackageKit/PackageKit.conf
-sudo G_DEBUG=fatal_criticals gdb --args .libs/lt-packagekitd --verbose --backend=dummy --disable-timer
+sudo G_DEBUG=fatal_criticals gdb --args .libs/lt-packagekitd --verbose --backend=$BACKEND --disable-timer
 
commit 4484f491f41ac0269cc8d4cc8a56d3e5a6e279f8
Author: Richard Hughes <richard at hughsie.com>
Date:   Wed Mar 10 11:31:28 2010 +0000

    yum: for installed packages, use Zif to get the package details
    
    This is 2.1x faster than using yum

diff --git a/backends/yum/libzif/zif-package-local.c b/backends/yum/libzif/zif-package-local.c
index 5d57cde..e04f8d9 100644
--- a/backends/yum/libzif/zif-package-local.c
+++ b/backends/yum/libzif/zif-package-local.c
@@ -359,10 +359,17 @@ zif_package_local_ensure_data (ZifPackage *pkg, ZifPackageEnsureType type, GErro
 		if (size != 0)
 			zif_package_set_size (pkg, size);
 
-	} else if (type == ZIF_PACKAGE_ENSURE_TYPE_GROUP) {
-		/* category && group */
+	} else if (type == ZIF_PACKAGE_ENSURE_TYPE_CATEGORY) {
+		/* category */
 		tmp = zif_get_header_string (header, RPMTAG_GROUP);
 		zif_package_set_category (pkg, tmp);
+		zif_string_unref (tmp);
+
+	} else if (type == ZIF_PACKAGE_ENSURE_TYPE_GROUP) {
+		/* group */
+		tmp = zif_package_get_category (pkg, error);
+		if (tmp == NULL)
+			goto out;
 		group = zif_groups_get_group_for_cat (ZIF_PACKAGE_LOCAL (pkg)->priv->groups, zif_string_get_value (tmp), NULL);
 		if (group != PK_GROUP_ENUM_UNKNOWN)
 			zif_package_set_group (pkg, group);
diff --git a/backends/yum/libzif/zif-package.c b/backends/yum/libzif/zif-package.c
index 9fa874c..4336e62 100644
--- a/backends/yum/libzif/zif-package.c
+++ b/backends/yum/libzif/zif-package.c
@@ -704,7 +704,7 @@ zif_package_get_category (ZifPackage *package, GError **error)
 
 	/* not exists */
 	if (package->priv->category == NULL) {
-		ret = zif_package_ensure_data (package, ZIF_PACKAGE_ENSURE_TYPE_GROUP, error);
+		ret = zif_package_ensure_data (package, ZIF_PACKAGE_ENSURE_TYPE_CATEGORY, error);
 		if (!ret)
 			return NULL;
 	}
@@ -729,7 +729,7 @@ zif_package_get_group (ZifPackage *package, GError **error)
 
 	/* not exists */
 	if (package->priv->group == PK_GROUP_ENUM_UNKNOWN) {
-		ret = zif_package_ensure_data (package, ZIF_PACKAGE_ENSURE_TYPE_FILES, error);
+		ret = zif_package_ensure_data (package, ZIF_PACKAGE_ENSURE_TYPE_GROUP, error);
 		if (!ret)
 			return PK_GROUP_ENUM_UNKNOWN;
 	}
diff --git a/backends/yum/libzif/zif-package.h b/backends/yum/libzif/zif-package.h
index d66c5b9..bbb4fea 100644
--- a/backends/yum/libzif/zif-package.h
+++ b/backends/yum/libzif/zif-package.h
@@ -54,6 +54,7 @@ typedef enum {
 	ZIF_PACKAGE_ENSURE_TYPE_URL,
 	ZIF_PACKAGE_ENSURE_TYPE_SIZE,
 	ZIF_PACKAGE_ENSURE_TYPE_GROUP,
+	ZIF_PACKAGE_ENSURE_TYPE_CATEGORY,
 	ZIF_PACKAGE_ENSURE_TYPE_REQUIRES,
 	ZIF_PACKAGE_ENSURE_TYPE_PROVIDES,
 	ZIF_PACKAGE_ENSURE_TYPE_CONFLICTS,
diff --git a/backends/yum/pk-backend-yum.c b/backends/yum/pk-backend-yum.c
index 0bd4217..c4b06d4 100644
--- a/backends/yum/pk-backend-yum.c
+++ b/backends/yum/pk-backend-yum.c
@@ -171,6 +171,25 @@ backend_get_lock (PkBackend *backend)
 }
 
 /**
+ * backend_is_all_installed:
+ */
+static gboolean
+backend_is_all_installed (gchar **package_ids)
+{
+	guint i;
+	gboolean ret = TRUE;
+
+	/* check if we can use zif */
+	for (i=0; package_ids[i] != NULL; i++) {
+		if (!g_str_has_suffix (package_ids[i], ";installed")) {
+			ret = FALSE;
+			break;
+		}
+	}
+	return ret;
+}
+
+/**
  * backend_unlock:
  */
 static gboolean
@@ -462,6 +481,102 @@ backend_get_depends (PkBackend *backend, PkBitfield filters, gchar **package_ids
 	g_free (package_ids_temp);
 }
 
+
+/**
+ * backend_get_details_thread:
+ */
+static gboolean
+backend_get_details_thread (PkBackend *backend)
+{
+	gboolean ret;
+	gchar **package_ids = pk_backend_get_strv (backend, "package_ids");
+	GPtrArray *store_array = NULL;
+	ZifPackage *package;
+	ZifCompletion *completion_local;
+	const gchar *id;
+	guint i;
+	guint len;
+	GError *error = NULL;
+	ZifString *license;
+	ZifString *description;
+	ZifString *url;
+	PkGroupEnum group;
+	guint64 size;
+
+	/* get lock */
+	ret = backend_get_lock (backend);
+	if (!ret) {
+		egg_warning ("failed to get lock");
+		goto out;
+	}
+
+	/* set the network state */
+	backend_setup_network (backend);
+
+	len = g_strv_length (package_ids);
+
+	/* setup completion */
+	zif_completion_reset (priv->completion);
+	zif_completion_set_number_steps (priv->completion, len + 1);
+
+	/* find all the packages */
+	completion_local = zif_completion_get_child (priv->completion);
+//	store_array = backend_get_default_store_array_for_filter (backend, PK_FILTER_ENUM_UNKNOWN, completion_local);
+{
+	ZifStore *store;
+	store = ZIF_STORE (zif_store_local_new ());
+	store_array = zif_store_array_new ();
+	zif_store_array_add_store (store_array, store);
+	g_object_unref (store);
+}
+
+	/* this section done */
+	zif_completion_done (priv->completion);
+
+	pk_backend_set_status (backend, PK_STATUS_ENUM_QUERY);
+	for (i=0; package_ids[i] != NULL; i++) {
+		id = package_ids[i];
+		completion_local = zif_completion_get_child (priv->completion);
+		package = zif_store_array_find_package (store_array, id, priv->cancellable, completion_local, &error);
+		if (package == NULL) {
+			pk_backend_error_code (backend, PK_ERROR_ENUM_PACKAGE_NOT_FOUND, "failed to find %s: %s", package_ids[i], error->message);
+			g_error_free (error);
+			goto out;
+		}
+
+		/* get data */
+		license = zif_package_get_license (package, NULL);
+		group = zif_package_get_group (package, NULL);
+		description = zif_package_get_description (package, NULL);
+		url = zif_package_get_url (package, NULL);
+		size = zif_package_get_size (package, NULL);
+
+		/* emit */
+		pk_backend_details (backend,
+				    package_ids[i],
+				    zif_string_get_value (license),
+				    group,
+				    zif_string_get_value (description),
+				    zif_string_get_value (url),
+				    (gulong) size);
+
+		/* this section done */
+		zif_completion_done (priv->completion);
+
+		/* free */
+		zif_string_unref (license);
+		zif_string_unref (description);
+		zif_string_unref (url);
+		g_object_unref (package);
+	}
+out:
+	backend_unlock (backend);
+	pk_backend_finished (backend);
+	if (store_array != NULL)
+		g_ptr_array_unref (store_array);
+	return TRUE;
+}
+
 /**
  * backend_get_details:
  */
@@ -469,6 +584,15 @@ static void
 backend_get_details (PkBackend *backend, gchar **package_ids)
 {
 	gchar *package_ids_temp;
+	gboolean ret;
+
+	/* check if we can use zif */
+	ret = backend_is_all_installed (package_ids);
+	if (ret) {
+		pk_backend_thread_create (backend, backend_get_details_thread);
+		return;
+	}
+
 	package_ids_temp = pk_package_ids_to_string (package_ids);
 	pk_backend_spawn_helper (priv->spawn, "yumBackend.py", "get-details", package_ids_temp, NULL);
 	g_free (package_ids_temp);
@@ -696,25 +820,6 @@ out:
 }
 
 /**
- * backend_is_all_installed:
- */
-static gboolean
-backend_is_all_installed (gchar **package_ids)
-{
-	guint i;
-	gboolean ret = TRUE;
-
-	/* check if we can use zif */
-	for (i=0; package_ids[i] != NULL; i++) {
-		if (!g_str_has_suffix (package_ids[i], ";installed")) {
-			ret = FALSE;
-			break;
-		}
-	}
-	return ret;
-}
-
-/**
  * backend_get_files:
  */
 static void
commit bcbb8b4264f19a601d48347f3a6341054308ce01
Author: Richard Hughes <richard at hughsie.com>
Date:   Wed Mar 10 10:42:03 2010 +0000

    yum: ensure we inform Zif of the network state so it can download repodata if required

diff --git a/backends/yum/pk-backend-yum.c b/backends/yum/pk-backend-yum.c
index 0588c10..0bd4217 100644
--- a/backends/yum/pk-backend-yum.c
+++ b/backends/yum/pk-backend-yum.c
@@ -110,6 +110,32 @@ out:
 }
 
 /**
+ * backend_setup_network:
+ */
+static void
+backend_setup_network (PkBackend *backend)
+{
+	gboolean ret;
+	gchar *http_proxy = NULL;
+
+	/* get network state */
+	ret = pk_backend_is_online (backend);
+	if (!ret) {
+		zif_config_set_local (priv->config, "network", "false", NULL);
+		goto out;
+	}
+
+	/* tell ZifConfig it's okay to contact the network */
+	zif_config_set_local (priv->config, "network", "true", NULL);
+
+	/* set the proxy */
+	http_proxy = pk_backend_get_proxy_http (backend);
+	zif_download_set_proxy (priv->download, http_proxy, NULL);
+out:
+	g_free (http_proxy);
+}
+
+/**
  * backend_get_lock:
  */
 static gboolean
@@ -592,6 +618,9 @@ backend_get_files_thread (PkBackend *backend)
 		goto out;
 	}
 
+	/* set the network state */
+	backend_setup_network (backend);
+
 	/* profile */
 	backend_profile ("get lock");
 
@@ -667,25 +696,36 @@ out:
 }
 
 /**
- * backend_get_files:
+ * backend_is_all_installed:
  */
-static void
-backend_get_files (PkBackend *backend, gchar **package_ids)
+static gboolean
+backend_is_all_installed (gchar **package_ids)
 {
-	gchar *package_ids_temp;
 	guint i;
-	gboolean is_all_installed = TRUE;
+	gboolean ret = TRUE;
 
 	/* check if we can use zif */
 	for (i=0; package_ids[i] != NULL; i++) {
 		if (!g_str_has_suffix (package_ids[i], ";installed")) {
-			is_all_installed = FALSE;
+			ret = FALSE;
 			break;
 		}
 	}
+	return ret;
+}
 
-	/* yippee, we can use zif */
-	if (is_all_installed) {
+/**
+ * backend_get_files:
+ */
+static void
+backend_get_files (PkBackend *backend, gchar **package_ids)
+{
+	gchar *package_ids_temp;
+	gboolean ret;
+
+	/* check if we can use zif */
+	ret = backend_is_all_installed (package_ids);
+	if (ret) {
 		pk_backend_thread_create (backend, backend_get_files_thread);
 		return;
 	}
@@ -983,6 +1023,9 @@ backend_get_repo_list_thread (PkBackend *backend)
 		goto out;
 	}
 
+	/* set the network state */
+	backend_setup_network (backend);
+
 	pk_backend_set_status (backend, PK_STATUS_ENUM_QUERY);
 	pk_backend_set_percentage (backend, 0);
 
@@ -1070,6 +1113,9 @@ backend_repo_enable_thread (PkBackend *backend)
 		goto out;
 	}
 
+	/* set the network state */
+	backend_setup_network (backend);
+
 	pk_backend_set_status (backend, PK_STATUS_ENUM_QUERY);
 	pk_backend_set_percentage (backend, 0);
 
@@ -1302,6 +1348,9 @@ backend_get_categories_thread (PkBackend *backend)
 		goto out;
 	}
 
+	/* set the network state */
+	backend_setup_network (backend);
+
 	/* setup completion */
 	zif_completion_reset (priv->completion);
 	zif_completion_set_number_steps (priv->completion, 3);
commit a31e89c927cc55a71f234747d2874b2a2f2c66eb
Author: Richard Hughes <richard at hughsie.com>
Date:   Wed Mar 10 10:22:42 2010 +0000

    yum: for installed files, use Zif to get the file list
    
    This is 2.3x faster than using yum as we're only using the rpmdb, not loading the repos

diff --git a/backends/yum/Makefile.am b/backends/yum/Makefile.am
index 242040f..f500bed 100644
--- a/backends/yum/Makefile.am
+++ b/backends/yum/Makefile.am
@@ -63,8 +63,8 @@ libpk_backend_yum_la_SOURCES += 				\
 	libzif/zif-repo-md-mirrorlist.h				\
 	libzif/zif-repo-md-comps.c				\
 	libzif/zif-repo-md-comps.h				\
-	libzif/zif-sack.c					\
-	libzif/zif-sack.h					\
+	libzif/zif-store-array.c				\
+	libzif/zif-store-array.h				\
 	libzif/zif-repos.c					\
 	libzif/zif-repos.h					\
 	libzif/zif-utils.c					\
diff --git a/backends/yum/libzif/zif-package.c b/backends/yum/libzif/zif-package.c
index 947dec7..9fa874c 100644
--- a/backends/yum/libzif/zif-package.c
+++ b/backends/yum/libzif/zif-package.c
@@ -491,20 +491,61 @@ zif_package_get_package_id (ZifPackage *package)
 }
 
 /**
+ * zif_package_ensure_type_to_string:
+ * @type: the #ZifPackageEnsureType enumerated value
+ *
+ * Gets the string representation of a #ZifPackageEnsureType
+ *
+ * Return value: The #ZifPackageEnsureType represented as a string
+ **/
+static const gchar *
+zif_package_ensure_type_to_string (ZifPackageEnsureType type)
+{
+	if (type == ZIF_PACKAGE_ENSURE_TYPE_FILES)
+		return "files";
+	if (type == ZIF_PACKAGE_ENSURE_TYPE_SUMMARY)
+		return "summary";
+	if (type == ZIF_PACKAGE_ENSURE_TYPE_LICENCE)
+		return "licence";
+	if (type == ZIF_PACKAGE_ENSURE_TYPE_DESCRIPTION)
+		return "description";
+	if (type == ZIF_PACKAGE_ENSURE_TYPE_URL)
+		return "url";
+	if (type == ZIF_PACKAGE_ENSURE_TYPE_SIZE)
+		return "size";
+	if (type == ZIF_PACKAGE_ENSURE_TYPE_GROUP)
+		return "group";
+	if (type == ZIF_PACKAGE_ENSURE_TYPE_REQUIRES)
+		return "requires";
+	if (type == ZIF_PACKAGE_ENSURE_TYPE_PROVIDES)
+		return "provides";
+	if (type == ZIF_PACKAGE_ENSURE_TYPE_CONFLICTS)
+		return "conflicts";
+	if (type == ZIF_PACKAGE_ENSURE_TYPE_OBSOLETES)
+		return "obsoletes";
+	return "unknown";
+}
+
+/**
  * zif_package_ensure_data:
  **/
 static gboolean
 zif_package_ensure_data (ZifPackage *package, ZifPackageEnsureType type, GError **error)
 {
+	gboolean ret = FALSE;
 	ZifPackageClass *klass = ZIF_PACKAGE_GET_CLASS (package);
 
 	g_return_val_if_fail (ZIF_IS_PACKAGE (package), FALSE);
 
 	/* no support */
-	if (klass->ensure_data == NULL)
-		return TRUE;
+	if (klass->ensure_data == NULL) {
+		g_set_error (error, 1, 0, "cannot ensure data for %s data", zif_package_ensure_type_to_string (type));
+		goto out;
+	}
 
-	return klass->ensure_data (package, type, error);
+	ret = klass->ensure_data (package, type, error);
+out:
+	return ret;
 }
 
 /**
diff --git a/backends/yum/libzif/zif-repo-md-metalink.c b/backends/yum/libzif/zif-repo-md-metalink.c
index a3704d0..57d78a2 100644
--- a/backends/yum/libzif/zif-repo-md-metalink.c
+++ b/backends/yum/libzif/zif-repo-md-metalink.c
@@ -33,6 +33,7 @@
 
 #include <stdlib.h>
 #include <glib.h>
+#include <string.h>
 
 #include "zif-repo-md.h"
 #include "zif-repo-md-metalink.h"
@@ -153,6 +154,8 @@ zif_repo_md_metalink_parser_text (GMarkupParseContext *context, const gchar *tex
 
 {
 	ZifRepoMdMetalink *metalink = user_data;
+	gchar *uri = NULL;
+	guint len;
 
 	if (metalink->priv->section != ZIF_REPO_MD_METALINK_PARSER_SECTION_URL)
 		goto out;
@@ -168,8 +171,20 @@ zif_repo_md_metalink_parser_text (GMarkupParseContext *context, const gchar *tex
 		egg_warning ("previously set uri to '%s', cannot overwrite with '%s'", metalink->priv->temp->uri, text);
 		goto out;
 	}
-	metalink->priv->temp->uri = g_strdup (text);
+
+	/* copy */
+	uri = g_strdup (text);
+
+	/* do we need to trim the junk from the end */
+	if (g_str_has_suffix (uri, "/repodata/repomd.xml")) {
+		len = strlen (uri);
+		uri[len-19] = '\0';
+	}
+
+	/* save */
+	metalink->priv->temp->uri = g_strdup (uri);
 out:
+	g_free (uri);
 	return;
 }
 
diff --git a/backends/yum/libzif/zif-repo-md.c b/backends/yum/libzif/zif-repo-md.c
index 8288f4d..cfa22ba 100644
--- a/backends/yum/libzif/zif-repo-md.c
+++ b/backends/yum/libzif/zif-repo-md.c
@@ -423,6 +423,7 @@ zif_repo_md_load (ZifRepoMd *md, GCancellable *cancellable, ZifCompletion *compl
 {
 	gboolean ret;
 	gboolean uncompressed_check;
+	gchar *dirname = NULL;
 	GError *error_local = NULL;
 	ZifRepoMdClass *klass = ZIF_REPO_MD_GET_CLASS (md);
 	ZifCompletion *completion_local;
@@ -466,8 +467,10 @@ zif_repo_md_load (ZifRepoMd *md, GCancellable *cancellable, ZifCompletion *compl
 			goto out;
 		}
 
-		/* TODO: download file */
-		//ret = download (&error_local)
+		/* download file */
+		completion_local = zif_completion_get_child (completion);
+		dirname = g_path_get_dirname (md->priv->filename);
+		ret = zif_store_remote_download (md->priv->remote, md->priv->location, dirname, cancellable, completion_local, &error_local);
 		if (!ret) {
 			g_set_error (error, 1, 0, "failed to download missing compressed file: %s", error_local->message);
 			goto out;
@@ -520,6 +523,7 @@ skip_compressed_check:
 	/* this section done */
 	zif_completion_done (completion);
 out:
+	g_free (dirname);
 	return ret;
 }
 
diff --git a/backends/yum/libzif/zif-sack.c b/backends/yum/libzif/zif-sack.c
deleted file mode 100644
index 1df6f1e..0000000
--- a/backends/yum/libzif/zif-sack.c
+++ /dev/null
@@ -1,775 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
- *
- * Copyright (C) 2008 Richard Hughes <richard at hughsie.com>
- *
- * Licensed under the GNU General Public License Version 2
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-/**
- * SECTION:zif-sack
- * @short_description: A sack is a container that holds one or more stores
- *
- * A #ZifSack is a container that #ZifStore's are kept. Global operations can
- * be done on the sack and not the indervidual stores.
- */
-
-#ifdef HAVE_CONFIG_H
-#  include <config.h>
-#endif
-
-#include <glib.h>
-#include <packagekit-glib2/packagekit.h>
-
-#include "zif-config.h"
-#include "zif-completion.h"
-#include "zif-store.h"
-#include "zif-store-local.h"
-#include "zif-sack.h"
-#include "zif-package.h"
-#include "zif-utils.h"
-#include "zif-repos.h"
-
-#include "egg-debug.h"
-#include "egg-string.h"
-
-#define ZIF_SACK_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), ZIF_TYPE_SACK, ZifSackPrivate))
-
-struct _ZifSackPrivate
-{
-	GPtrArray		*array;
-};
-
-/* in PackageKit we split categories from groups using a special @ prefix (bodge) */
-#define PK_ROLE_ENUM_SEARCH_CATEGORY	PK_ROLE_ENUM_UNKNOWN + 1
-
-G_DEFINE_TYPE (ZifSack, zif_sack, G_TYPE_OBJECT)
-
-/**
- * zif_sack_add_store:
- * @sack: the #ZifSack object
- * @store: the #ZifStore to add
- *
- * Add a single #ZifStore to the #ZifSack.
- *
- * Return value: %TRUE for success, %FALSE for failure
- **/
-gboolean
-zif_sack_add_store (ZifSack *sack, ZifStore *store)
-{
-	g_return_val_if_fail (ZIF_IS_SACK (sack), FALSE);
-	g_return_val_if_fail (store != NULL, FALSE);
-
-	g_ptr_array_add (sack->priv->array, g_object_ref (store));
-	return TRUE;
-}
-
-/**
- * zif_sack_add_stores:
- * @sack: the #ZifSack object
- * @stores: the array of #ZifStore's to add
- *
- * Add an array of #ZifStore's to the #ZifSack.
- *
- * Return value: %TRUE for success, %FALSE for failure
- **/
-gboolean
-zif_sack_add_stores (ZifSack *sack, GPtrArray *stores)
-{
-	guint i;
-	ZifStore *store;
-	gboolean ret = FALSE;
-
-	g_return_val_if_fail (ZIF_IS_SACK (sack), FALSE);
-	g_return_val_if_fail (stores != NULL, FALSE);
-
-	for (i=0; i<stores->len; i++) {
-		store = g_ptr_array_index (stores, i);
-		ret = zif_sack_add_store (sack, store);
-		if (!ret)
-			break;
-	}
-	return ret;
-}
-
-/**
- * zif_sack_add_local:
- * @sack: the #ZifSack object
- * @cancellable: a #GCancellable which is used to cancel tasks, or %NULL
- * @completion: a #ZifCompletion to use for progress reporting
- * @error: a #GError which is used on failure, or %NULL
- *
- * Convenience function to add local store to the #ZifSack.
- *
- * Return value: %TRUE for success, %FALSE for failure
- **/
-gboolean
-zif_sack_add_local (ZifSack *sack, GCancellable *cancellable, ZifCompletion *completion, GError **error)
-{
-	ZifStoreLocal *store;
-
-	g_return_val_if_fail (ZIF_IS_SACK (sack), FALSE);
-
-	store = zif_store_local_new ();
-	zif_sack_add_store (sack, ZIF_STORE (store));
-	g_object_unref (store);
-
-	return TRUE;
-}
-
-/**
- * zif_sack_add_remote:
- * @sack: the #ZifSack object
- * @cancellable: a #GCancellable which is used to cancel tasks, or %NULL
- * @completion: a #ZifCompletion to use for progress reporting
- * @error: a #GError which is used on failure, or %NULL
- *
- * Convenience function to add remote stores to the #ZifSack.
- *
- * Return value: %TRUE for success, %FALSE for failure
- **/
-gboolean
-zif_sack_add_remote (ZifSack *sack, GCancellable *cancellable, ZifCompletion *completion, GError **error)
-{
-	GPtrArray *array;
-	ZifRepos *repos;
-	GError *error_local = NULL;
-	gboolean ret = TRUE;
-
-	g_return_val_if_fail (ZIF_IS_SACK (sack), FALSE);
-
-	/* get stores */
-	repos = zif_repos_new ();
-	array = zif_repos_get_stores (repos, cancellable, completion, &error_local);
-	if (array == NULL) {
-		g_set_error (error, 1, 0, "failed to get enabled stores: %s", error_local->message);
-		g_error_free (error_local);
-		ret = FALSE;
-		goto out;
-	}
-
-	/* add */
-	zif_sack_add_stores (ZIF_SACK (sack), array);
-
-	/* free */
-	g_ptr_array_unref (array);
-out:
-	g_object_unref (repos);
-	return ret;
-}
-
-/**
- * zif_sack_add_remote_enabled:
- * @sack: the #ZifSack object
- * @cancellable: a #GCancellable which is used to cancel tasks, or %NULL
- * @completion: a #ZifCompletion to use for progress reporting
- * @error: a #GError which is used on failure, or %NULL
- *
- * Convenience function to add enabled remote stores to the #ZifSack.
- *
- * Return value: %TRUE for success, %FALSE for failure
- **/
-gboolean
-zif_sack_add_remote_enabled (ZifSack *sack, GCancellable *cancellable, ZifCompletion *completion, GError **error)
-{
-	GPtrArray *array;
-	ZifRepos *repos;
-	GError *error_local = NULL;
-	gboolean ret = TRUE;
-
-	g_return_val_if_fail (ZIF_IS_SACK (sack), FALSE);
-
-	/* get stores */
-	repos = zif_repos_new ();
-	array = zif_repos_get_stores_enabled (repos, cancellable, completion, &error_local);
-	if (array == NULL) {
-		g_set_error (error, 1, 0, "failed to get enabled stores: %s", error_local->message);
-		g_error_free (error_local);
-		ret = FALSE;
-		goto out;
-	}
-
-	/* add */
-	zif_sack_add_stores (ZIF_SACK (sack), array);
-
-	/* free */
-	g_ptr_array_unref (array);
-out:
-	g_object_unref (repos);
-	return ret;
-}
-
-/**
- * zif_sack_repos_search:
- **/
-static GPtrArray *
-zif_sack_repos_search (ZifSack *sack, PkRoleEnum role, const gchar *search, GCancellable *cancellable, ZifCompletion *completion, GError **error)
-{
-	guint i, j;
-	GPtrArray *array = NULL;
-	GPtrArray *stores;
-	GPtrArray *part;
-	ZifStore *store;
-	ZifPackage *package;
-	GError *error_local = NULL;
-	ZifCompletion *completion_local = NULL;
-
-	/* find results in each store */
-	stores = sack->priv->array;
-
-	/* nothing to do */
-	if (stores->len == 0) {
-		egg_warning ("nothing to do");
-		g_set_error (error, 1, 0, "nothing to do as no stores in sack");
-		goto out;
-	}
-
-	/* set number of stores */
-	zif_completion_set_number_steps (completion, stores->len);
-
-	/* do each one */
-	array = g_ptr_array_new_with_free_func ((GDestroyNotify) g_object_unref);
-	for (i=0; i<stores->len; i++) {
-		store = g_ptr_array_index (stores, i);
-
-		/* create a chain of completions */
-		completion_local = zif_completion_get_child (completion);
-
-		/* get results for this store */
-		if (role == PK_ROLE_ENUM_RESOLVE)
-			part = zif_store_resolve (store, search, cancellable, completion_local, &error_local);
-		else if (role == PK_ROLE_ENUM_SEARCH_NAME)
-			part = zif_store_search_name (store, search, cancellable, completion_local, &error_local);
-		else if (role == PK_ROLE_ENUM_SEARCH_DETAILS)
-			part = zif_store_search_details (store, search, cancellable, completion_local, &error_local);
-		else if (role == PK_ROLE_ENUM_SEARCH_GROUP)
-			part = zif_store_search_group (store, search, cancellable, completion_local, &error_local);
-		else if (role == PK_ROLE_ENUM_SEARCH_CATEGORY)
-			part = zif_store_search_category (store, search, cancellable, completion_local, &error_local);
-		else if (role == PK_ROLE_ENUM_SEARCH_FILE)
-			part = zif_store_search_file (store, search, cancellable, completion_local, &error_local);
-		else if (role == PK_ROLE_ENUM_GET_PACKAGES)
-			part = zif_store_get_packages (store, cancellable, completion_local, &error_local);
-		else if (role == PK_ROLE_ENUM_GET_UPDATES)
-			part = zif_store_get_updates (store, cancellable, completion_local, &error_local);
-		else if (role == PK_ROLE_ENUM_WHAT_PROVIDES)
-			part = zif_store_what_provides (store, search, cancellable, completion_local, &error_local);
-		else if (role == PK_ROLE_ENUM_GET_CATEGORIES)
-			part = zif_store_get_categories (store, cancellable, completion_local, &error_local);
-		else
-			egg_error ("internal error: %s", pk_role_enum_to_text (role));
-		if (part == NULL) {
-			g_set_error (error, 1, 0, "failed to %s in %s: %s", pk_role_enum_to_text (role), zif_store_get_id (store), error_local->message);
-			g_error_free (error_local);
-			g_ptr_array_unref (array);
-			array = NULL;
-			goto out;
-		}
-
-		for (j=0; j<part->len; j++) {
-			package = g_ptr_array_index (part, j);
-			g_ptr_array_add (array, g_object_ref (package));
-		}
-		g_ptr_array_unref (part);
-
-		/* this section done */
-		zif_completion_done (completion);
-	}
-out:
-	return array;
-}
-
-/**
- * zif_sack_find_package:
- * @sack: the #ZifSack object
- * @package_id: the PackageId which defines the package
- * @cancellable: a #GCancellable which is used to cancel tasks, or %NULL
- * @completion: a #ZifCompletion to use for progress reporting
- * @error: a #GError which is used on failure, or %NULL
- *
- * Find a single package in the #ZifSack.
- *
- * Return value: A single #ZifPackage or %NULL
- **/
-ZifPackage *
-zif_sack_find_package (ZifSack *sack, const gchar *package_id, GCancellable *cancellable, ZifCompletion *completion, GError **error)
-{
-	guint i;
-	GPtrArray *stores;
-	ZifStore *store;
-	ZifPackage *package = NULL;
-	ZifCompletion *completion_local = NULL;
-
-	g_return_val_if_fail (ZIF_IS_SACK (sack), NULL);
-
-	/* find results in each store */
-	stores = sack->priv->array;
-
-	/* nothing to do */
-	if (stores->len == 0) {
-		egg_debug ("nothing to do");
-		goto out;
-	}
-
-	/* create a chain of completions */
-	zif_completion_set_number_steps (completion, stores->len);
-
-	/* do each one */
-	for (i=0; i<stores->len; i++) {
-		store = g_ptr_array_index (stores, i);
-
-		completion_local = zif_completion_get_child (completion);
-		package = zif_store_find_package (store, package_id, cancellable, completion_local, NULL);
-		if (package != NULL)
-			break;
-
-		/* this section done */
-		zif_completion_done (completion);
-	}
-out:
-	return package;
-}
-
-/**
- * zif_sack_clean:
- * @sack: the #ZifSack object
- * @cancellable: a #GCancellable which is used to cancel tasks, or %NULL
- * @completion: a #ZifCompletion to use for progress reporting
- * @error: a #GError which is used on failure, or %NULL
- *
- * Cleans the #ZifStoreRemote objects by deleting cache.
- *
- * Return value: %TRUE for success, %FALSE for failure
- **/
-gboolean
-zif_sack_clean (ZifSack *sack, GCancellable *cancellable, ZifCompletion *completion, GError **error)
-{
-	guint i;
-	GPtrArray *stores;
-	ZifStore *store;
-	gboolean ret = TRUE;
-	GError *error_local = NULL;
-	ZifCompletion *completion_local = NULL;
-
-	g_return_val_if_fail (ZIF_IS_SACK (sack), FALSE);
-
-	/* clean each store */
-	stores = sack->priv->array;
-
-	/* nothing to do */
-	if (stores->len == 0) {
-		egg_debug ("nothing to do");
-		goto out;
-	}
-
-	/* set number of stores */
-	zif_completion_set_number_steps (completion, stores->len);
-
-	/* do each one */
-	for (i=0; i<stores->len; i++) {
-		store = g_ptr_array_index (stores, i);
-
-		/* clean this one */
-		completion_local = zif_completion_get_child (completion);
-		ret = zif_store_clean (store, cancellable, completion_local, &error_local);
-		if (!ret) {
-			g_set_error (error, 1, 0, "failed to clean %s: %s", zif_store_get_id (store), error_local->message);
-			g_error_free (error_local);
-			goto out;
-		}
-
-		/* this section done */
-		zif_completion_done (completion);
-	}
-out:
-	return ret;
-}
-
-/**
- * zif_sack_refresh:
- * @sack: the #ZifSack object
- * @force: if the data should be re-downloaded if it's still valid
- * @cancellable: a #GCancellable which is used to cancel tasks, or %NULL
- * @completion: a #ZifCompletion to use for progress reporting
- * @error: a #GError which is used on failure, or %NULL
- *
- * Refreshs the #ZifStoreRemote objects by downloading new data
- *
- * Return value: %TRUE for success, %FALSE for failure
- **/
-gboolean
-zif_sack_refresh (ZifSack *sack, gboolean force, GCancellable *cancellable, ZifCompletion *completion, GError **error)
-{
-	guint i;
-	GPtrArray *stores;
-	ZifStore *store;
-	gboolean ret = TRUE;
-	GError *error_local = NULL;
-	ZifCompletion *completion_local = NULL;
-
-	g_return_val_if_fail (ZIF_IS_SACK (sack), FALSE);
-
-	/* refresh each store */
-	stores = sack->priv->array;
-
-	/* nothing to do */
-	if (stores->len == 0) {
-		egg_debug ("nothing to do");
-		goto out;
-	}
-
-	/* create a chain of completions */
-	zif_completion_set_number_steps (completion, stores->len);
-
-	/* do each one */
-	for (i=0; i<stores->len; i++) {
-		store = g_ptr_array_index (stores, i);
-
-		egg_warning ("refreshing %s", zif_store_get_id (store));
-
-		/* refresh this one */
-		completion_local = zif_completion_get_child (completion);
-		ret = zif_store_refresh (store, force, cancellable, completion_local, &error_local);
-		if (!ret) {
-			/* non-fatal */
-			g_print ("failed to refresh %s: %s\n", zif_store_get_id (store), error_local->message);
-			g_clear_error (&error_local);
-			ret = TRUE;
-		}
-
-		/* this section done */
-		zif_completion_done (completion);
-	}
-out:
-	return ret;
-}
-
-/**
- * zif_sack_resolve:
- * @sack: the #ZifSack object
- * @search: the search term, e.g. "gnome-power-manager"
- * @cancellable: a #GCancellable which is used to cancel tasks, or %NULL
- * @completion: a #ZifCompletion to use for progress reporting
- * @error: a #GError which is used on failure, or %NULL
- *
- * Finds packages matching the package name exactly.
- *
- * Return value: an array of #ZifPackage's
- **/
-GPtrArray *
-zif_sack_resolve (ZifSack *sack, const gchar *search, GCancellable *cancellable, ZifCompletion *completion, GError **error)
-{
-	g_return_val_if_fail (ZIF_IS_SACK (sack), NULL);
-	return zif_sack_repos_search (sack, PK_ROLE_ENUM_RESOLVE, search, cancellable, completion, error);
-}
-
-/**
- * zif_sack_search_name:
- * @sack: the #ZifSack object
- * @search: the search term, e.g. "power"
- * @cancellable: a #GCancellable which is used to cancel tasks, or %NULL
- * @completion: a #ZifCompletion to use for progress reporting
- * @error: a #GError which is used on failure, or %NULL
- *
- * Find packages that match the package name in some part.
- *
- * Return value: an array of #ZifPackage's
- **/
-GPtrArray *
-zif_sack_search_name (ZifSack *sack, const gchar *search, GCancellable *cancellable, ZifCompletion *completion, GError **error)
-{
-	g_return_val_if_fail (ZIF_IS_SACK (sack), NULL);
-	return zif_sack_repos_search (sack, PK_ROLE_ENUM_SEARCH_NAME, search, cancellable, completion, error);
-}
-
-/**
- * zif_sack_search_details:
- * @sack: the #ZifSack object
- * @search: the search term, e.g. "trouble"
- * @cancellable: a #GCancellable which is used to cancel tasks, or %NULL
- * @completion: a #ZifCompletion to use for progress reporting
- * @error: a #GError which is used on failure, or %NULL
- *
- * Find packages that match some detail about the package.
- *
- * Return value: an array of #ZifPackage's
- **/
-GPtrArray *
-zif_sack_search_details (ZifSack *sack, const gchar *search, GCancellable *cancellable, ZifCompletion *completion, GError **error)
-{
-	g_return_val_if_fail (ZIF_IS_SACK (sack), NULL);
-	return zif_sack_repos_search (sack, PK_ROLE_ENUM_SEARCH_DETAILS, search, cancellable, completion, error);
-}
-
-/**
- * zif_sack_search_group:
- * @sack: the #ZifSack object
- * @group_enum: the group enumerated value, e.g. "games"
- * @cancellable: a #GCancellable which is used to cancel tasks, or %NULL
- * @completion: a #ZifCompletion to use for progress reporting
- * @error: a #GError which is used on failure, or %NULL
- *
- * Find packages that belong in a specific group.
- *
- * Return value: an array of #ZifPackage's
- **/
-GPtrArray *
-zif_sack_search_group (ZifSack *sack, const gchar *group_enum, GCancellable *cancellable, ZifCompletion *completion, GError **error)
-{
-	g_return_val_if_fail (ZIF_IS_SACK (sack), NULL);
-	return zif_sack_repos_search (sack, PK_ROLE_ENUM_SEARCH_GROUP, group_enum, cancellable, completion, error);
-}
-
-/**
- * zif_sack_search_category:
- * @sack: the #ZifSack object
- * @group_id: the group id, e.g. "gnome-system-tools"
- * @cancellable: a #GCancellable which is used to cancel tasks, or %NULL
- * @completion: a #ZifCompletion to use for progress reporting
- * @error: a #GError which is used on failure, or %NULL
- *
- * Find packages that belong in a specific category.
- *
- * Return value: an array of #ZifPackage's
- **/
-GPtrArray *
-zif_sack_search_category (ZifSack *sack, const gchar *group_id, GCancellable *cancellable, ZifCompletion *completion, GError **error)
-{
-	guint i, j;
-	GPtrArray *array;
-	ZifPackage *package;
-	const gchar *package_id;
-	const gchar *package_id_tmp;
-	gchar **split;
-
-	g_return_val_if_fail (ZIF_IS_SACK (sack), NULL);
-
-	/* get all results from all repos */
-	array = zif_sack_repos_search (sack, PK_ROLE_ENUM_SEARCH_CATEGORY, group_id, cancellable, completion, error);
-	if (array == NULL)
-		goto out;
-
-	/* remove duplicate package_ids */
-	for (i=0; i<array->len; i++) {
-		package = g_ptr_array_index (array, i);
-		package_id = zif_package_get_id (package);
-		for (j=0; j<array->len; j++) {
-			if (i == j)
-				continue;
-			package = g_ptr_array_index (array, j);
-			package_id_tmp = zif_package_get_id (package);
-			if (g_strcmp0 (package_id, package_id_tmp) == 0) {
-				split = pk_package_id_split (package_id);
-				egg_warning ("duplicate %s-%s", split[PK_PACKAGE_ID_NAME], split[PK_PACKAGE_ID_VERSION]);
-				g_ptr_array_remove_index (array, j);
-				g_strfreev (split);
-			}
-		}
-	}
-out:
-	return array;
-}
-
-/**
- * zif_sack_search_file:
- * @sack: the #ZifSack object
- * @search: the search term, e.g. "/usr/bin/gnome-power-manager"
- * @cancellable: a #GCancellable which is used to cancel tasks, or %NULL
- * @completion: a #ZifCompletion to use for progress reporting
- * @error: a #GError which is used on failure, or %NULL
- *
- * Find packages that provide the specified file.
- *
- * Return value: an array of #ZifPackage's
- **/
-GPtrArray *
-zif_sack_search_file (ZifSack *sack, const gchar *search, GCancellable *cancellable, ZifCompletion *completion, GError **error)
-{
-	g_return_val_if_fail (ZIF_IS_SACK (sack), NULL);
-	return zif_sack_repos_search (sack, PK_ROLE_ENUM_SEARCH_FILE, search, cancellable, completion, error);
-}
-
-/**
- * zif_sack_get_packages:
- * @sack: the #ZifSack object
- * @cancellable: a #GCancellable which is used to cancel tasks, or %NULL
- * @completion: a #ZifCompletion to use for progress reporting
- * @error: a #GError which is used on failure, or %NULL
- *
- * Return all packages in the #ZifSack's.
- *
- * Return value: an array of #ZifPackage's
- **/
-GPtrArray *
-zif_sack_get_packages (ZifSack *sack, GCancellable *cancellable, ZifCompletion *completion, GError **error)
-{
-	g_return_val_if_fail (ZIF_IS_SACK (sack), NULL);
-	return zif_sack_repos_search (sack, PK_ROLE_ENUM_GET_PACKAGES, NULL, cancellable, completion, error);
-}
-
-/**
- * zif_sack_get_updates:
- * @sack: the #ZifSack object
- * @cancellable: a #GCancellable which is used to cancel tasks, or %NULL
- * @completion: a #ZifCompletion to use for progress reporting
- * @error: a #GError which is used on failure, or %NULL
- *
- * Return a list of packages that are updatable.
- *
- * Return value: an array of #ZifPackage's
- **/
-GPtrArray *
-zif_sack_get_updates (ZifSack *sack, GCancellable *cancellable, ZifCompletion *completion, GError **error)
-{
-	g_return_val_if_fail (ZIF_IS_SACK (sack), NULL);
-	return zif_sack_repos_search (sack, PK_ROLE_ENUM_GET_UPDATES, NULL, cancellable, completion, error);
-}
-
-/**
- * zif_sack_what_provides:
- * @sack: the #ZifSack object
- * @search: the search term, e.g. "gstreamer(codec-mp3)"
- * @cancellable: a #GCancellable which is used to cancel tasks, or %NULL
- * @completion: a #ZifCompletion to use for progress reporting
- * @error: a #GError which is used on failure, or %NULL
- *
- * Find packages that provide a specific string.
- *
- * Return value: an array of #ZifPackage's
- **/
-GPtrArray *
-zif_sack_what_provides (ZifSack *sack, const gchar *search, GCancellable *cancellable, ZifCompletion *completion, GError **error)
-{
-	g_return_val_if_fail (ZIF_IS_SACK (sack), NULL);
-
-	/* if this is a path, then we use the file list and treat like a SearchFile */
-	if (g_str_has_prefix (search, "/"))
-		return zif_sack_repos_search (sack, PK_ROLE_ENUM_SEARCH_FILE, search, cancellable, completion, error);
-	return zif_sack_repos_search (sack, PK_ROLE_ENUM_WHAT_PROVIDES, search, cancellable, completion, error);
-}
-
-/**
- * zif_sack_get_categories:
- * @sack: the #ZifSack object
- * @cancellable: a #GCancellable which is used to cancel tasks, or %NULL
- * @completion: a #ZifCompletion to use for progress reporting
- * @error: a #GError which is used on failure, or %NULL
- *
- * Return a list of custom categories from all repos.
- *
- * Return value: an array of #PkCategory's
- **/
-GPtrArray *
-zif_sack_get_categories (ZifSack *sack, GCancellable *cancellable, ZifCompletion *completion, GError **error)
-{
-	guint i, j;
-	GPtrArray *array;
-	PkCategory *obj;
-	PkCategory *obj_tmp;
-	gchar *parent_id;
-	gchar *parent_id_tmp;
-	gchar *cat_id;
-	gchar *cat_id_tmp;
-
-	g_return_val_if_fail (ZIF_IS_SACK (sack), NULL);
-
-	/* get all results from all repos */
-	array = zif_sack_repos_search (sack, PK_ROLE_ENUM_GET_CATEGORIES, NULL, cancellable, completion, error);
-	if (array == NULL)
-		goto out;
-
-	/* remove duplicate parents and groups */
-	for (i=0; i<array->len; i++) {
-		obj = g_ptr_array_index (array, i);
-		g_object_get (obj,
-			      "parent-id", &parent_id,
-			      "cat-id", &cat_id,
-			      NULL);
-		for (j=0; j<array->len; j++) {
-			if (i == j)
-				continue;
-			obj_tmp = g_ptr_array_index (array, j);
-			g_object_get (obj_tmp,
-				      "parent-id", &parent_id_tmp,
-				      "cat-id", &cat_id_tmp,
-				      NULL);
-			if (g_strcmp0 (parent_id_tmp, parent_id) == 0 &&
-			    g_strcmp0 (cat_id_tmp, cat_id) == 0) {
-				egg_warning ("duplicate %s-%s", parent_id, cat_id);
-				g_object_unref (obj_tmp);
-				g_ptr_array_remove_index (array, j);
-			}
-			g_free (parent_id_tmp);
-			g_free (cat_id_tmp);
-		}
-		g_free (parent_id);
-		g_free (cat_id);
-	}
-out:
-	return array;
-}
-
-/**
- * zif_sack_finalize:
- **/
-static void
-zif_sack_finalize (GObject *object)
-{
-	ZifSack *sack;
-
-	g_return_if_fail (object != NULL);
-	g_return_if_fail (ZIF_IS_SACK (object));
-	sack = ZIF_SACK (object);
-
-	g_ptr_array_unref (sack->priv->array);
-
-	G_OBJECT_CLASS (zif_sack_parent_class)->finalize (object);
-}
-
-/**
- * zif_sack_class_init:
- **/
-static void
-zif_sack_class_init (ZifSackClass *klass)
-{
-	GObjectClass *object_class = G_OBJECT_CLASS (klass);
-	object_class->finalize = zif_sack_finalize;
-	g_type_class_add_private (klass, sizeof (ZifSackPrivate));
-}
-
-/**
- * zif_sack_init:
- **/
-static void
-zif_sack_init (ZifSack *sack)
-{
-	sack->priv = ZIF_SACK_GET_PRIVATE (sack);
-	sack->priv->array = g_ptr_array_new_with_free_func ((GDestroyNotify) g_object_unref);
-}
-
-/**
- * zif_sack_new:
- *
- * Return value: A new #ZifSack class instance.
- **/
-ZifSack *
-zif_sack_new (void)
-{
-	ZifSack *sack;
-	sack = g_object_new (ZIF_TYPE_SACK, NULL);
-	return ZIF_SACK (sack);
-}
-
diff --git a/backends/yum/libzif/zif-sack.h b/backends/yum/libzif/zif-sack.h
deleted file mode 100644
index ee588d5..0000000
--- a/backends/yum/libzif/zif-sack.h
+++ /dev/null
@@ -1,146 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
- *
- * Copyright (C) 2008 Richard Hughes <richard at hughsie.com>
- *
- * Licensed under the GNU General Public License Version 2
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#if !defined (__ZIF_H_INSIDE__) && !defined (ZIF_COMPILATION)
-#error "Only <zif.h> can be included directly."
-#endif
-
-#ifndef __ZIF_SACK_H
-#define __ZIF_SACK_H
-
-#include <glib-object.h>
-
-#include "zif-store.h"
-#include "zif-package.h"
-#include "zif-completion.h"
-
-G_BEGIN_DECLS
-
-#define ZIF_TYPE_SACK		(zif_sack_get_type ())
-#define ZIF_SACK(o)		(G_TYPE_CHECK_INSTANCE_CAST ((o), ZIF_TYPE_SACK, ZifSack))
-#define ZIF_SACK_CLASS(k)	(G_TYPE_CHECK_CLASS_CAST((k), ZIF_TYPE_SACK, ZifSackClass))
-#define ZIF_IS_SACK(o)		(G_TYPE_CHECK_INSTANCE_TYPE ((o), ZIF_TYPE_SACK))
-#define ZIF_IS_SACK_CLASS(k)	(G_TYPE_CHECK_CLASS_TYPE ((k), ZIF_TYPE_SACK))
-#define ZIF_SACK_GET_CLASS(o)	(G_TYPE_INSTANCE_GET_CLASS ((o), ZIF_TYPE_SACK, ZifSackClass))
-
-typedef struct _ZifSack		ZifSack;
-typedef struct _ZifSackPrivate	ZifSackPrivate;
-typedef struct _ZifSackClass	ZifSackClass;
-
-struct _ZifSack
-{
-	GObject			 parent;
-	ZifSackPrivate		*priv;
-};
-
-struct _ZifSackClass
-{
-	GObjectClass		 parent_class;
-};
-
-GType		 zif_sack_get_type		(void);
-ZifSack		*zif_sack_new			(void);
-
-/* stores */
-gboolean	 zif_sack_add_store		(ZifSack		*sack,
-						 ZifStore		*store);
-gboolean	 zif_sack_add_stores		(ZifSack		*sack,
-						 GPtrArray		*stores);
-gboolean	 zif_sack_add_local		(ZifSack		*sack,
-						 GCancellable		*cancellable,
-						 ZifCompletion		*completion,
-						 GError			**error);
-gboolean	 zif_sack_add_remote		(ZifSack		*sack,
-						 GCancellable		*cancellable,
-						 ZifCompletion		*completion,
-						 GError			**error);
-gboolean	 zif_sack_add_remote_enabled	(ZifSack		*sack,
-						 GCancellable		*cancellable,
-						 ZifCompletion		*completion,
-						 GError			**error);
-
-/* methods */
-gboolean	 zif_sack_clean			(ZifSack		*sack,
-						 GCancellable		*cancellable,
-						 ZifCompletion		*completion,
-						 GError			**error);
-gboolean	 zif_sack_refresh		(ZifSack		*sack,
-						 gboolean		 force,
-						 GCancellable		*cancellable,
-						 ZifCompletion		*completion,
-						 GError			**error);
-GPtrArray	*zif_sack_resolve		(ZifSack		*sack,
-						 const gchar		*search,
-						 GCancellable		*cancellable,
-						 ZifCompletion		*completion,
-						 GError			**error);
-GPtrArray	*zif_sack_search_name		(ZifSack		*sack,
-						 const gchar		*search,
-						 GCancellable		*cancellable,
-						 ZifCompletion		*completion,
-						 GError			**error);
-GPtrArray	*zif_sack_search_details	(ZifSack		*sack,
-						 const gchar		*search,
-						 GCancellable		*cancellable,
-						 ZifCompletion		*completion,
-						 GError			**error);
-GPtrArray	*zif_sack_search_group		(ZifSack		*sack,
-						 const gchar		*group_enum,
-						 GCancellable		*cancellable,
-						 ZifCompletion		*completion,
-						 GError			**error);
-GPtrArray	*zif_sack_search_category	(ZifSack		*sack,
-						 const gchar		*group_id,
-						 GCancellable		*cancellable,
-						 ZifCompletion		*completion,
-						 GError			**error);
-GPtrArray	*zif_sack_search_file		(ZifSack		*sack,
-						 const gchar		*search,
-						 GCancellable		*cancellable,
-						 ZifCompletion		*completion,
-						 GError			**error);
-GPtrArray	*zif_sack_what_provides		(ZifSack		*sack,
-						 const gchar		*search,
-						 GCancellable		*cancellable,
-						 ZifCompletion		*completion,
-						 GError			**error);
-GPtrArray	*zif_sack_get_packages		(ZifSack		*sack,
-						 GCancellable		*cancellable,
-						 ZifCompletion		*completion,
-						 GError			**error);
-GPtrArray	*zif_sack_get_updates		(ZifSack		*sack,
-						 GCancellable		*cancellable,
-						 ZifCompletion		*completion,
-						 GError			**error);
-ZifPackage	*zif_sack_find_package		(ZifSack		*sack,
-						 const gchar		*package_id,
-						 GCancellable		*cancellable,
-						 ZifCompletion		*completion,
-						 GError			**error);
-GPtrArray	*zif_sack_get_categories	(ZifSack		*sack,
-						 GCancellable		*cancellable,
-						 ZifCompletion		*completion,
-						 GError			**error);
-
-G_END_DECLS
-
-#endif /* __ZIF_SACK_H */
-
diff --git a/backends/yum/libzif/zif-store-array.c b/backends/yum/libzif/zif-store-array.c
new file mode 100644
index 0000000..387d2d1
--- /dev/null
+++ b/backends/yum/libzif/zif-store-array.c
@@ -0,0 +1,693 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2008 Richard Hughes <richard at hughsie.com>
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+/**
+ * SECTION:zif-store_array
+ * @short_description: A store_array is a container that holds one or more stores
+ *
+ * A #GPtrArray is the container where #ZifStore's are kept. Global operations can
+ * be done on the array and not the indervidual stores.
+ *
+ * IMPORTANT: any errors that happen on the ZifStores are fatal. You will need to
+ * copy this functionality in this file and issue warnings if the error policy
+ * needs to be less harsh.
+ */
+
+#ifdef HAVE_CONFIG_H
+#  include <config.h>
+#endif
+
+#include <glib.h>
+#include <packagekit-glib2/packagekit.h>
+
+#include "zif-config.h"
+#include "zif-completion.h"
+#include "zif-store.h"
+#include "zif-store-local.h"
+#include "zif-store-array.h"
+#include "zif-package.h"
+#include "zif-utils.h"
+#include "zif-repos.h"
+
+#include "egg-debug.h"
+#include "egg-string.h"
+
+/* in PackageKit we split categories from groups using a special @ prefix (bodge) */
+#define PK_ROLE_ENUM_SEARCH_CATEGORY	(PK_ROLE_ENUM_UNKNOWN + 1)
+
+/**
+ * zif_store_array_add_store:
+ * @store_array: the #GPtrArray of #ZifStores
+ * @store: the #ZifStore to add
+ *
+ * Add a single #ZifStore to the #GPtrArray.
+ *
+ * Return value: %TRUE for success, %FALSE for failure
+ **/
+gboolean
+zif_store_array_add_store (GPtrArray *store_array, ZifStore *store)
+{
+	g_return_val_if_fail (store != NULL, FALSE);
+
+	g_ptr_array_add (store_array, g_object_ref (store));
+	return TRUE;
+}
+
+/**
+ * zif_store_array_add_stores:
+ * @store_array: the #GPtrArray of #ZifStores
+ * @stores: the array of #ZifStore's to add
+ *
+ * Add an array of #ZifStore's to the #GPtrArray.
+ *
+ * Return value: %TRUE for success, %FALSE for failure
+ **/
+gboolean
+zif_store_array_add_stores (GPtrArray *store_array, GPtrArray *stores)
+{
+	guint i;
+	ZifStore *store;
+	gboolean ret = FALSE;
+
+	g_return_val_if_fail (stores != NULL, FALSE);
+
+	for (i=0; i<stores->len; i++) {
+		store = g_ptr_array_index (stores, i);
+		ret = zif_store_array_add_store (store_array, store);
+		if (!ret)
+			break;
+	}
+	return ret;
+}
+
+/**
+ * zif_store_array_add_local:
+ * @store_array: the #GPtrArray of #ZifStores
+ * @cancellable: a #GCancellable which is used to cancel tasks, or %NULL
+ * @completion: a #ZifCompletion to use for progress reporting
+ * @error: a #GError which is used on failure, or %NULL
+ *
+ * Convenience function to add local store to the #GPtrArray.
+ *
+ * Return value: %TRUE for success, %FALSE for failure
+ **/
+gboolean
+zif_store_array_add_local (GPtrArray *store_array, GCancellable *cancellable, ZifCompletion *completion, GError **error)
+{
+	ZifStoreLocal *store;
+
+	store = zif_store_local_new ();
+	zif_store_array_add_store (store_array, ZIF_STORE (store));
+	g_object_unref (store);
+
+	return TRUE;
+}
+
+/**
+ * zif_store_array_add_remote:
+ * @store_array: the #GPtrArray of #ZifStores
+ * @cancellable: a #GCancellable which is used to cancel tasks, or %NULL
+ * @completion: a #ZifCompletion to use for progress reporting
+ * @error: a #GError which is used on failure, or %NULL
+ *
+ * Convenience function to add remote stores to the #GPtrArray.
+ *
+ * Return value: %TRUE for success, %FALSE for failure
+ **/
+gboolean
+zif_store_array_add_remote (GPtrArray *store_array, GCancellable *cancellable, ZifCompletion *completion, GError **error)
+{
+	GPtrArray *array;
+	ZifRepos *repos;
+	GError *error_local = NULL;
+	gboolean ret = TRUE;
+
+	/* get stores */
+	repos = zif_repos_new ();
+	array = zif_repos_get_stores (repos, cancellable, completion, &error_local);
+	if (array == NULL) {
+		g_set_error (error, 1, 0, "failed to get enabled stores: %s", error_local->message);
+		g_error_free (error_local);
+		ret = FALSE;
+		goto out;
+	}
+
+	/* add */
+	zif_store_array_add_stores (store_array, array);
+
+	/* free */
+	g_ptr_array_unref (array);
+out:
+	g_object_unref (repos);
+	return ret;
+}
+
+/**
+ * zif_store_array_add_remote_enabled:
+ * @store_array: the #GPtrArray of #ZifStores
+ * @cancellable: a #GCancellable which is used to cancel tasks, or %NULL
+ * @completion: a #ZifCompletion to use for progress reporting
+ * @error: a #GError which is used on failure, or %NULL
+ *
+ * Convenience function to add enabled remote stores to the #GPtrArray.
+ *
+ * Return value: %TRUE for success, %FALSE for failure
+ **/
+gboolean
+zif_store_array_add_remote_enabled (GPtrArray *store_array, GCancellable *cancellable, ZifCompletion *completion, GError **error)
+{
+	GPtrArray *array;
+	ZifRepos *repos;
+	GError *error_local = NULL;
+	gboolean ret = TRUE;
+
+	/* get stores */
+	repos = zif_repos_new ();
+	array = zif_repos_get_stores_enabled (repos, cancellable, completion, &error_local);
+	if (array == NULL) {
+		g_set_error (error, 1, 0, "failed to get enabled stores: %s", error_local->message);
+		g_error_free (error_local);
+		ret = FALSE;
+		goto out;
+	}
+
+	/* add */
+	zif_store_array_add_stores (store_array, array);
+
+	/* free */
+	g_ptr_array_unref (array);
+out:
+	g_object_unref (repos);
+	return ret;
+}
+
+/**
+ * zif_store_array_repos_search:
+ **/
+static GPtrArray *
+zif_store_array_repos_search (GPtrArray *store_array, PkRoleEnum role, const gchar *search, GCancellable *cancellable, ZifCompletion *completion, GError **error)
+{
+	guint i, j;
+	GPtrArray *array = NULL;
+	GPtrArray *part;
+	ZifStore *store;
+	ZifPackage *package;
+	GError *error_local = NULL;
+	ZifCompletion *completion_local = NULL;
+
+	/* nothing to do */
+	if (store_array->len == 0) {
+		egg_warning ("nothing to do");
+		g_set_error (error, 1, 0, "nothing to do as no stores in store_array");
+		goto out;
+	}
+
+	/* set number of stores */
+	zif_completion_set_number_steps (completion, store_array->len);
+
+	/* do each one */
+	array = g_ptr_array_new_with_free_func ((GDestroyNotify) g_object_unref);
+	for (i=0; i<store_array->len; i++) {
+		store = g_ptr_array_index (store_array, i);
+
+		/* create a chain of completions */
+		completion_local = zif_completion_get_child (completion);
+
+		/* get results for this store */
+		if (role == PK_ROLE_ENUM_RESOLVE)
+			part = zif_store_resolve (store, search, cancellable, completion_local, &error_local);
+		else if (role == PK_ROLE_ENUM_SEARCH_NAME)
+			part = zif_store_search_name (store, search, cancellable, completion_local, &error_local);
+		else if (role == PK_ROLE_ENUM_SEARCH_DETAILS)
+			part = zif_store_search_details (store, search, cancellable, completion_local, &error_local);
+		else if (role == PK_ROLE_ENUM_SEARCH_GROUP)
+			part = zif_store_search_group (store, search, cancellable, completion_local, &error_local);
+		else if (role == PK_ROLE_ENUM_SEARCH_CATEGORY)
+			part = zif_store_search_category (store, search, cancellable, completion_local, &error_local);
+		else if (role == PK_ROLE_ENUM_SEARCH_FILE)
+			part = zif_store_search_file (store, search, cancellable, completion_local, &error_local);
+		else if (role == PK_ROLE_ENUM_GET_PACKAGES)
+			part = zif_store_get_packages (store, cancellable, completion_local, &error_local);
+		else if (role == PK_ROLE_ENUM_GET_UPDATES)
+			part = zif_store_get_updates (store, cancellable, completion_local, &error_local);
+		else if (role == PK_ROLE_ENUM_WHAT_PROVIDES)
+			part = zif_store_what_provides (store, search, cancellable, completion_local, &error_local);
+		else if (role == PK_ROLE_ENUM_GET_CATEGORIES)
+			part = zif_store_get_categories (store, cancellable, completion_local, &error_local);
+		else
+			egg_error ("internal error: %s", pk_role_enum_to_text (role));
+		if (part == NULL) {
+			g_set_error (error, 1, 0, "failed to %s in %s: %s", pk_role_enum_to_text (role), zif_store_get_id (store), error_local->message);
+			g_error_free (error_local);
+			g_ptr_array_unref (array);
+			array = NULL;
+			goto out;
+		}
+
+		for (j=0; j<part->len; j++) {
+			package = g_ptr_array_index (part, j);
+			g_ptr_array_add (array, g_object_ref (package));
+		}
+		g_ptr_array_unref (part);
+
+		/* this section done */
+		zif_completion_done (completion);
+	}
+out:
+	return array;
+}
+
+/**
+ * zif_store_array_find_package:
+ * @store_array: the #GPtrArray of #ZifStores
+ * @package_id: the PackageId which defines the package
+ * @cancellable: a #GCancellable which is used to cancel tasks, or %NULL
+ * @completion: a #ZifCompletion to use for progress reporting
+ * @error: a #GError which is used on failure, or %NULL
+ *
+ * Find a single package in the #GPtrArray.
+ *
+ * Return value: A single #ZifPackage or %NULL
+ **/
+ZifPackage *
+zif_store_array_find_package (GPtrArray *store_array, const gchar *package_id, GCancellable *cancellable, ZifCompletion *completion, GError **error)
+{
+	guint i;
+	ZifStore *store;
+	ZifPackage *package = NULL;
+	ZifCompletion *completion_local = NULL;
+
+
+	/* nothing to do */
+	if (store_array->len == 0) {
+		egg_debug ("nothing to do");
+		goto out;
+	}
+
+	/* create a chain of completions */
+	zif_completion_set_number_steps (completion, store_array->len);
+
+	/* do each one */
+	for (i=0; i<store_array->len; i++) {
+		store = g_ptr_array_index (store_array, i);
+
+		completion_local = zif_completion_get_child (completion);
+		package = zif_store_find_package (store, package_id, cancellable, completion_local, NULL);
+		if (package != NULL)
+			break;
+
+		/* this section done */
+		zif_completion_done (completion);
+	}
+out:
+	return package;
+}
+
+/**
+ * zif_store_array_clean:
+ * @store_array: the #GPtrArray of #ZifStores
+ * @cancellable: a #GCancellable which is used to cancel tasks, or %NULL
+ * @completion: a #ZifCompletion to use for progress reporting
+ * @error: a #GError which is used on failure, or %NULL
+ *
+ * Cleans the #ZifStoreRemote objects by deleting cache.
+ *
+ * Return value: %TRUE for success, %FALSE for failure
+ **/
+gboolean
+zif_store_array_clean (GPtrArray *store_array, GCancellable *cancellable, ZifCompletion *completion, GError **error)
+{
+	guint i;
+	ZifStore *store;
+	gboolean ret = TRUE;
+	GError *error_local = NULL;
+	ZifCompletion *completion_local = NULL;
+
+	/* nothing to do */
+	if (store_array->len == 0) {
+		egg_debug ("nothing to do");
+		goto out;
+	}
+
+	/* set number of stores */
+	zif_completion_set_number_steps (completion, store_array->len);
+
+	/* do each one */
+	for (i=0; i<store_array->len; i++) {
+		store = g_ptr_array_index (store_array, i);
+
+		/* clean this one */
+		completion_local = zif_completion_get_child (completion);
+		ret = zif_store_clean (store, cancellable, completion_local, &error_local);
+		if (!ret) {
+			g_set_error (error, 1, 0, "failed to clean %s: %s", zif_store_get_id (store), error_local->message);
+			g_error_free (error_local);
+			goto out;
+		}
+
+		/* this section done */
+		zif_completion_done (completion);
+	}
+out:
+	return ret;
+}
+
+/**
+ * zif_store_array_refresh:
+ * @store_array: the #GPtrArray of #ZifStores
+ * @force: if the data should be re-downloaded if it's still valid
+ * @cancellable: a #GCancellable which is used to cancel tasks, or %NULL
+ * @completion: a #ZifCompletion to use for progress reporting
+ * @error: a #GError which is used on failure, or %NULL
+ *
+ * Refreshs the #ZifStoreRemote objects by downloading new data
+ *
+ * Return value: %TRUE for success, %FALSE for failure
+ **/
+gboolean
+zif_store_array_refresh (GPtrArray *store_array, gboolean force, GCancellable *cancellable, ZifCompletion *completion, GError **error)
+{
+	guint i;
+	ZifStore *store;
+	gboolean ret = TRUE;
+	GError *error_local = NULL;
+	ZifCompletion *completion_local = NULL;
+
+	/* nothing to do */
+	if (store_array->len == 0) {
+		egg_debug ("nothing to do");
+		goto out;
+	}
+
+	/* create a chain of completions */
+	zif_completion_set_number_steps (completion, store_array->len);
+
+	/* do each one */
+	for (i=0; i<store_array->len; i++) {
+		store = g_ptr_array_index (store_array, i);
+
+		egg_warning ("refreshing %s", zif_store_get_id (store));
+
+		/* refresh this one */
+		completion_local = zif_completion_get_child (completion);
+		ret = zif_store_refresh (store, force, cancellable, completion_local, &error_local);
+		if (!ret) {
+			/* non-fatal */
+			g_print ("failed to refresh %s: %s\n", zif_store_get_id (store), error_local->message);
+			g_clear_error (&error_local);
+			ret = TRUE;
+		}
+
+		/* this section done */
+		zif_completion_done (completion);
+	}
+out:
+	return ret;
+}
+
+/**
+ * zif_store_array_resolve:
+ * @store_array: the #GPtrArray of #ZifStores
+ * @search: the search term, e.g. "gnome-power-manager"
+ * @cancellable: a #GCancellable which is used to cancel tasks, or %NULL
+ * @completion: a #ZifCompletion to use for progress reporting
+ * @error: a #GError which is used on failure, or %NULL
+ *
+ * Finds packages matching the package name exactly.
+ *
+ * Return value: an array of #ZifPackage's
+ **/
+GPtrArray *
+zif_store_array_resolve (GPtrArray *store_array, const gchar *search, GCancellable *cancellable, ZifCompletion *completion, GError **error)
+{
+	return zif_store_array_repos_search (store_array, PK_ROLE_ENUM_RESOLVE, search, cancellable, completion, error);
+}
+
+/**
+ * zif_store_array_search_name:
+ * @store_array: the #GPtrArray of #ZifStores
+ * @search: the search term, e.g. "power"
+ * @cancellable: a #GCancellable which is used to cancel tasks, or %NULL
+ * @completion: a #ZifCompletion to use for progress reporting
+ * @error: a #GError which is used on failure, or %NULL
+ *
+ * Find packages that match the package name in some part.
+ *
+ * Return value: an array of #ZifPackage's
+ **/
+GPtrArray *
+zif_store_array_search_name (GPtrArray *store_array, const gchar *search, GCancellable *cancellable, ZifCompletion *completion, GError **error)
+{
+	return zif_store_array_repos_search (store_array, PK_ROLE_ENUM_SEARCH_NAME, search, cancellable, completion, error);
+}
+
+/**
+ * zif_store_array_search_details:
+ * @store_array: the #GPtrArray of #ZifStores
+ * @search: the search term, e.g. "trouble"
+ * @cancellable: a #GCancellable which is used to cancel tasks, or %NULL
+ * @completion: a #ZifCompletion to use for progress reporting
+ * @error: a #GError which is used on failure, or %NULL
+ *
+ * Find packages that match some detail about the package.
+ *
+ * Return value: an array of #ZifPackage's
+ **/
+GPtrArray *
+zif_store_array_search_details (GPtrArray *store_array, const gchar *search, GCancellable *cancellable, ZifCompletion *completion, GError **error)
+{
+	return zif_store_array_repos_search (store_array, PK_ROLE_ENUM_SEARCH_DETAILS, search, cancellable, completion, error);
+}
+
+/**
+ * zif_store_array_search_group:
+ * @store_array: the #GPtrArray of #ZifStores
+ * @group_enum: the group enumerated value, e.g. "games"
+ * @cancellable: a #GCancellable which is used to cancel tasks, or %NULL
+ * @completion: a #ZifCompletion to use for progress reporting
+ * @error: a #GError which is used on failure, or %NULL
+ *
+ * Find packages that belong in a specific group.
+ *
+ * Return value: an array of #ZifPackage's
+ **/
+GPtrArray *
+zif_store_array_search_group (GPtrArray *store_array, const gchar *group_enum, GCancellable *cancellable, ZifCompletion *completion, GError **error)
+{
+	return zif_store_array_repos_search (store_array, PK_ROLE_ENUM_SEARCH_GROUP, group_enum, cancellable, completion, error);
+}
+
+/**
+ * zif_store_array_search_category:
+ * @store_array: the #GPtrArray of #ZifStores
+ * @group_id: the group id, e.g. "gnome-system-tools"
+ * @cancellable: a #GCancellable which is used to cancel tasks, or %NULL
+ * @completion: a #ZifCompletion to use for progress reporting
+ * @error: a #GError which is used on failure, or %NULL
+ *
+ * Find packages that belong in a specific category.
+ *
+ * Return value: an array of #ZifPackage's
+ **/
+GPtrArray *
+zif_store_array_search_category (GPtrArray *store_array, const gchar *group_id, GCancellable *cancellable, ZifCompletion *completion, GError **error)
+{
+	guint i, j;
+	GPtrArray *array;
+	ZifPackage *package;
+	const gchar *package_id;
+	const gchar *package_id_tmp;
+	gchar **split;
+
+
+	/* get all results from all repos */
+	array = zif_store_array_repos_search (store_array, PK_ROLE_ENUM_SEARCH_CATEGORY, group_id, cancellable, completion, error);
+	if (array == NULL)
+		goto out;
+
+	/* remove duplicate package_ids */
+	for (i=0; i<array->len; i++) {
+		package = g_ptr_array_index (array, i);
+		package_id = zif_package_get_id (package);
+		for (j=0; j<array->len; j++) {
+			if (i == j)
+				continue;
+			package = g_ptr_array_index (array, j);
+			package_id_tmp = zif_package_get_id (package);
+			if (g_strcmp0 (package_id, package_id_tmp) == 0) {
+				split = pk_package_id_split (package_id);
+				egg_warning ("duplicate %s-%s", split[PK_PACKAGE_ID_NAME], split[PK_PACKAGE_ID_VERSION]);
+				g_ptr_array_remove_index (array, j);
+				g_strfreev (split);
+			}
+		}
+	}
+out:
+	return array;
+}
+
+/**
+ * zif_store_array_search_file:
+ * @store_array: the #GPtrArray of #ZifStores
+ * @search: the search term, e.g. "/usr/bin/gnome-power-manager"
+ * @cancellable: a #GCancellable which is used to cancel tasks, or %NULL
+ * @completion: a #ZifCompletion to use for progress reporting
+ * @error: a #GError which is used on failure, or %NULL
+ *
+ * Find packages that provide the specified file.
+ *
+ * Return value: an array of #ZifPackage's
+ **/
+GPtrArray *
+zif_store_array_search_file (GPtrArray *store_array, const gchar *search, GCancellable *cancellable, ZifCompletion *completion, GError **error)
+{
+	return zif_store_array_repos_search (store_array, PK_ROLE_ENUM_SEARCH_FILE, search, cancellable, completion, error);
+}
+
+/**
+ * zif_store_array_get_packages:
+ * @store_array: the #GPtrArray of #ZifStores
+ * @cancellable: a #GCancellable which is used to cancel tasks, or %NULL
+ * @completion: a #ZifCompletion to use for progress reporting
+ * @error: a #GError which is used on failure, or %NULL
+ *
+ * Return all packages in the #GPtrArray's.
+ *
+ * Return value: an array of #ZifPackage's
+ **/
+GPtrArray *
+zif_store_array_get_packages (GPtrArray *store_array, GCancellable *cancellable, ZifCompletion *completion, GError **error)
+{
+	return zif_store_array_repos_search (store_array, PK_ROLE_ENUM_GET_PACKAGES, NULL, cancellable, completion, error);
+}
+
+/**
+ * zif_store_array_get_updates:
+ * @store_array: the #GPtrArray of #ZifStores
+ * @cancellable: a #GCancellable which is used to cancel tasks, or %NULL
+ * @completion: a #ZifCompletion to use for progress reporting
+ * @error: a #GError which is used on failure, or %NULL
+ *
+ * Return a list of packages that are updatable.
+ *
+ * Return value: an array of #ZifPackage's
+ **/
+GPtrArray *
+zif_store_array_get_updates (GPtrArray *store_array, GCancellable *cancellable, ZifCompletion *completion, GError **error)
+{
+	return zif_store_array_repos_search (store_array, PK_ROLE_ENUM_GET_UPDATES, NULL, cancellable, completion, error);
+}
+
+/**
+ * zif_store_array_what_provides:
+ * @store_array: the #GPtrArray of #ZifStores
+ * @search: the search term, e.g. "gstreamer(codec-mp3)"
+ * @cancellable: a #GCancellable which is used to cancel tasks, or %NULL
+ * @completion: a #ZifCompletion to use for progress reporting
+ * @error: a #GError which is used on failure, or %NULL
+ *
+ * Find packages that provide a specific string.
+ *
+ * Return value: an array of #ZifPackage's
+ **/
+GPtrArray *
+zif_store_array_what_provides (GPtrArray *store_array, const gchar *search, GCancellable *cancellable, ZifCompletion *completion, GError **error)
+{
+
+	/* if this is a path, then we use the file list and treat like a SearchFile */
+	if (g_str_has_prefix (search, "/"))
+		return zif_store_array_repos_search (store_array, PK_ROLE_ENUM_SEARCH_FILE, search, cancellable, completion, error);
+	return zif_store_array_repos_search (store_array, PK_ROLE_ENUM_WHAT_PROVIDES, search, cancellable, completion, error);
+}
+
+/**
+ * zif_store_array_get_categories:
+ * @store_array: the #GPtrArray of #ZifStores
+ * @cancellable: a #GCancellable which is used to cancel tasks, or %NULL
+ * @completion: a #ZifCompletion to use for progress reporting
+ * @error: a #GError which is used on failure, or %NULL
+ *
+ * Return a list of custom categories from all repos.
+ *
+ * Return value: an array of #PkCategory's
+ **/
+GPtrArray *
+zif_store_array_get_categories (GPtrArray *store_array, GCancellable *cancellable, ZifCompletion *completion, GError **error)
+{
+	guint i, j;
+	GPtrArray *array;
+	PkCategory *obj;
+	PkCategory *obj_tmp;
+	gchar *parent_id;
+	gchar *parent_id_tmp;
+	gchar *cat_id;
+	gchar *cat_id_tmp;
+
+
+	/* get all results from all repos */
+	array = zif_store_array_repos_search (store_array, PK_ROLE_ENUM_GET_CATEGORIES, NULL, cancellable, completion, error);
+	if (array == NULL)
+		goto out;
+
+	/* remove duplicate parents and groups */
+	for (i=0; i<array->len; i++) {
+		obj = g_ptr_array_index (array, i);
+		g_object_get (obj,
+			      "parent-id", &parent_id,
+			      "cat-id", &cat_id,
+			      NULL);
+		for (j=0; j<array->len; j++) {
+			if (i == j)
+				continue;
+			obj_tmp = g_ptr_array_index (array, j);
+			g_object_get (obj_tmp,
+				      "parent-id", &parent_id_tmp,
+				      "cat-id", &cat_id_tmp,
+				      NULL);
+			if (g_strcmp0 (parent_id_tmp, parent_id) == 0 &&
+			    g_strcmp0 (cat_id_tmp, cat_id) == 0) {
+				egg_warning ("duplicate %s-%s", parent_id, cat_id);
+				g_object_unref (obj_tmp);
+				g_ptr_array_remove_index (array, j);
+			}
+			g_free (parent_id_tmp);
+			g_free (cat_id_tmp);
+		}
+		g_free (parent_id);
+		g_free (cat_id);
+	}
+out:
+	return array;
+}
+
+/**
+ * zif_store_array_new:
+ *
+ * Return value: A new #GPtrArray class instance.
+ **/
+GPtrArray *
+zif_store_array_new (void)
+{
+	GPtrArray *store_array;
+	store_array = g_ptr_array_new_with_free_func ((GDestroyNotify) g_object_unref);
+	return store_array;
+}
+
diff --git a/backends/yum/libzif/zif-store-array.h b/backends/yum/libzif/zif-store-array.h
new file mode 100644
index 0000000..61c5dfc
--- /dev/null
+++ b/backends/yum/libzif/zif-store-array.h
@@ -0,0 +1,123 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2008-2010 Richard Hughes <richard at hughsie.com>
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#if !defined (__ZIF_H_INSIDE__) && !defined (ZIF_COMPILATION)
+#error "Only <zif.h> can be included directly."
+#endif
+
+#ifndef __ZIF_STORE_ARRAY_H
+#define __ZIF_STORE_ARRAY_H
+
+#include <glib.h>
+
+#include "zif-store.h"
+#include "zif-package.h"
+#include "zif-completion.h"
+
+G_BEGIN_DECLS
+
+GPtrArray	*zif_store_array_new			(void);
+
+/* stores */
+gboolean	 zif_store_array_add_store		(GPtrArray		*store_array,
+							 ZifStore		*store);
+gboolean	 zif_store_array_add_stores		(GPtrArray		*store_array,
+							 GPtrArray		*stores);
+gboolean	 zif_store_array_add_local		(GPtrArray		*store_array,
+							 GCancellable		*cancellable,
+							 ZifCompletion		*completion,
+							 GError			**error);
+gboolean	 zif_store_array_add_remote		(GPtrArray		*store_array,
+							 GCancellable		*cancellable,
+							 ZifCompletion		*completion,
+							 GError			**error);
+gboolean	 zif_store_array_add_remote_enabled	(GPtrArray		*store_array,
+							 GCancellable		*cancellable,
+							 ZifCompletion		*completion,
+							 GError			**error);
+
+/* methods */
+gboolean	 zif_store_array_clean			(GPtrArray		*store_array,
+							 GCancellable		*cancellable,
+							 ZifCompletion		*completion,
+							 GError			**error);
+gboolean	 zif_store_array_refresh		(GPtrArray		*store_array,
+							 gboolean		 force,
+							 GCancellable		*cancellable,
+							 ZifCompletion		*completion,
+							 GError			**error);
+GPtrArray	*zif_store_array_resolve		(GPtrArray		*store_array,
+							 const gchar		*search,
+							 GCancellable		*cancellable,
+							 ZifCompletion		*completion,
+							 GError			**error);
+GPtrArray	*zif_store_array_search_name		(GPtrArray		*store_array,
+							 const gchar		*search,
+							 GCancellable		*cancellable,
+							 ZifCompletion		*completion,
+							 GError			**error);
+GPtrArray	*zif_store_array_search_details		(GPtrArray		*store_array,
+							 const gchar		*search,
+							 GCancellable		*cancellable,
+							 ZifCompletion		*completion,
+							 GError			**error);
+GPtrArray	*zif_store_array_search_group		(GPtrArray		*store_array,
+							 const gchar		*group_enum,
+							 GCancellable		*cancellable,
+							 ZifCompletion		*completion,
+							 GError			**error);
+GPtrArray	*zif_store_array_search_category	(GPtrArray		*store_array,
+							 const gchar		*group_id,
+							 GCancellable		*cancellable,
+							 ZifCompletion		*completion,
+							 GError			**error);
+GPtrArray	*zif_store_array_search_file		(GPtrArray		*store_array,
+							 const gchar		*search,
+							 GCancellable		*cancellable,
+							 ZifCompletion		*completion,
+							 GError			**error);
+GPtrArray	*zif_store_array_what_provides		(GPtrArray		*store_array,
+							 const gchar		*search,
+							 GCancellable		*cancellable,
+							 ZifCompletion		*completion,
+							 GError			**error);
+GPtrArray	*zif_store_array_get_packages		(GPtrArray		*store_array,
+							 GCancellable		*cancellable,
+							 ZifCompletion		*completion,
+							 GError			**error);
+GPtrArray	*zif_store_array_get_updates		(GPtrArray		*store_array,
+							 GCancellable		*cancellable,
+							 ZifCompletion		*completion,
+							 GError			**error);
+ZifPackage	*zif_store_array_find_package		(GPtrArray		*store_array,
+							 const gchar		*package_id,
+							 GCancellable		*cancellable,
+							 ZifCompletion		*completion,
+							 GError			**error);
+GPtrArray	*zif_store_array_get_categories		(GPtrArray		*store_array,
+							 GCancellable		*cancellable,
+							 ZifCompletion		*completion,
+							 GError			**error);
+
+G_END_DECLS
+
+#endif /* __ZIF_STORE_ARRAY_H */
+
diff --git a/backends/yum/libzif/zif-store-local.c b/backends/yum/libzif/zif-store-local.c
index 4c3a5b2..c4f6aba 100644
--- a/backends/yum/libzif/zif-store-local.c
+++ b/backends/yum/libzif/zif-store-local.c
@@ -832,6 +832,7 @@ zif_store_local_find_package (ZifStore *store, const gchar *package_id, GCancell
 	ZifPackage *package_tmp = NULL;
 	GError *error_local = NULL;
 	gboolean ret;
+	guint jump;
 	const gchar *package_id_tmp;
 	ZifCompletion *completion_local = NULL;
 	ZifStoreLocal *local = ZIF_STORE_LOCAL (store);
@@ -876,18 +877,23 @@ zif_store_local_find_package (ZifStore *store, const gchar *package_id, GCancell
 
 	/* setup completion with the correct number of steps */
 	completion_local = zif_completion_get_child (completion);
-	zif_completion_set_number_steps (completion_local, local->priv->packages->len);
+
+	/* we only do a few jumps as there could be thousands of packages, and
+	 * this makes up an inner loop of possibly deep notifications */
+	jump = local->priv->packages->len / 10;
+	zif_completion_set_number_steps (completion_local, jump);
 
 	/* iterate list */
 	array = g_ptr_array_new_with_free_func ((GDestroyNotify) g_object_unref);
 	for (i=0;i<local->priv->packages->len;i++) {
 		package_tmp = g_ptr_array_index (local->priv->packages, i);
-		package_id_tmp = zif_package_get_id (package);
+		package_id_tmp = zif_package_get_id (package_tmp);
 		if (g_strcmp0 (package_id_tmp, package_id) == 0)
 			g_ptr_array_add (array, g_object_ref (package_tmp));
 
 		/* this section done */
-		zif_completion_done (completion_local);
+		if (i % jump == 0)
+			zif_completion_done (completion_local);
 	}
 
 	/* nothing */
diff --git a/backends/yum/libzif/zif-store-remote.c b/backends/yum/libzif/zif-store-remote.c
index 265d456..af9468e 100644
--- a/backends/yum/libzif/zif-store-remote.c
+++ b/backends/yum/libzif/zif-store-remote.c
@@ -307,7 +307,7 @@ zif_store_remote_download_try (ZifStoreRemote *store, const gchar *uri, const gc
 
 	/* download object */
 	download = zif_download_new ();
-	egg_debug ("trying to download %s", uri);
+	egg_debug ("trying to download %s and save to %s", uri, filename);
 	ret = zif_download_file (download, uri, filename, cancellable, completion, &error_local);
 	if (!ret) {
 		g_set_error (error, 1, 0, "failed to download %s from %s: %s", filename, uri, error_local->message);
@@ -453,7 +453,7 @@ zif_store_remote_download (ZifStoreRemote *store, const gchar *filename, const g
 
 	/* nothing */
 	if (!ret) {
-		g_set_error_literal (error, 1, 0, "failed to download from any sources");
+		g_set_error (error, 1, 0, "failed to download %s from any sources", filename);
 		goto out;
 	}
 out:
@@ -474,7 +474,7 @@ zif_store_remote_add_metalink (ZifStoreRemote *store, GCancellable *cancellable,
 	GError *error_local = NULL;
 	const gchar *uri_tmp;
 	const gchar *filename;
-	gboolean ret;
+	gboolean ret = FALSE;
 	ZifCompletion *completion_local;
 	ZifDownload *download = NULL;
 
@@ -514,18 +514,24 @@ zif_store_remote_add_metalink (ZifStoreRemote *store, GCancellable *cancellable,
 		goto out;
 	}
 
+	/* nothing here? */
+	if (array->len == 0) {
+		ret = FALSE;
+		g_set_error (error, 1, 0, "failed to get any mirrors from metalink: %s", filename);
+		goto out;
+	}
+
 	zif_completion_done (completion);
 
 	/* add array */
 	for (i=0; i<array->len; i++) {
 		uri_tmp = g_ptr_array_index (array, i);
-		egg_warning ("uri_tmp=%s", uri_tmp);
 		g_ptr_array_add (store->priv->baseurls, g_strdup (uri_tmp));
 	}
 out:
 	if (array != NULL)
 		g_ptr_array_unref (array);
-	return (array != NULL);
+	return ret;
 }
 
 /**
@@ -537,7 +543,6 @@ zif_store_remote_add_mirrorlist (ZifStoreRemote *store, GCancellable *cancellabl
 	guint i;
 	GPtrArray *array = NULL;
 	GError *error_local = NULL;
-	gchar *uri = NULL;
 	const gchar *uri_tmp;
 	const gchar *filename;
 	gboolean ret = FALSE;
@@ -560,8 +565,7 @@ zif_store_remote_add_mirrorlist (ZifStoreRemote *store, GCancellable *cancellabl
 
 		/* download object directly, as we don't have the repo setup yet */
 		download = zif_download_new ();
-		uri = g_build_filename (store->priv->mirrorlist, filename, NULL);
-		ret = zif_download_file (download, uri, filename, cancellable, completion_local, &error_local);
+		ret = zif_download_file (download, store->priv->mirrorlist, filename, cancellable, completion_local, &error_local);
 		if (!ret) {
 			g_set_error (error, 1, 0, "failed to download %s from %s: %s", filename, store->priv->mirrorlist, error_local->message);
 			g_error_free (error_local);
@@ -580,6 +584,13 @@ zif_store_remote_add_mirrorlist (ZifStoreRemote *store, GCancellable *cancellabl
 		goto out;
 	}
 
+	/* nothing here? */
+	if (array->len == 0) {
+		ret = FALSE;
+		g_set_error (error, 1, 0, "failed to get any mirrors from mirrorlist: %s", filename);
+		goto out;
+	}
+
 	zif_completion_done (completion);
 
 	/* add array */
@@ -588,12 +599,11 @@ zif_store_remote_add_mirrorlist (ZifStoreRemote *store, GCancellable *cancellabl
 		g_ptr_array_add (store->priv->baseurls, g_strdup (uri_tmp));
 	}
 out:
-	g_free (uri);
 	if (download != NULL)
 		g_object_unref (download);
 	if (array != NULL)
 		g_ptr_array_unref (array);
-	return (array != NULL);
+	return ret;
 
 }
 
@@ -635,7 +645,6 @@ zif_store_remote_load_metadata (ZifStoreRemote *store, GCancellable *cancellable
 	/* not locked */
 	ret = zif_lock_is_locked (store->priv->lock, NULL);
 	if (!ret) {
-		egg_warning ("not locked");
 		g_set_error_literal (error, 1, 0, "not locked");
 		goto out;
 	}
@@ -828,7 +837,6 @@ zif_store_remote_refresh (ZifStore *store, gboolean force, GCancellable *cancell
 	/* not locked */
 	ret = zif_lock_is_locked (remote->priv->lock, NULL);
 	if (!ret) {
-		egg_warning ("not locked");
 		g_set_error_literal (error, 1, 0, "not locked");
 		goto out;
 	}
@@ -936,7 +944,6 @@ zif_store_remote_load (ZifStore *store, GCancellable *cancellable, ZifCompletion
 	/* not locked */
 	ret = zif_lock_is_locked (remote->priv->lock, NULL);
 	if (!ret) {
-		egg_warning ("not locked");
 		g_set_error_literal (error, 1, 0, "not locked");
 		goto out;
 	}
@@ -1065,7 +1072,6 @@ zif_store_remote_clean (ZifStore *store, GCancellable *cancellable, ZifCompletio
 	/* not locked */
 	ret = zif_lock_is_locked (remote->priv->lock, NULL);
 	if (!ret) {
-		egg_warning ("not locked");
 		g_set_error_literal (error, 1, 0, "not locked");
 		goto out;
 	}
@@ -1163,7 +1169,6 @@ zif_store_remote_set_from_file (ZifStoreRemote *store, const gchar *repo_filenam
 	/* not locked */
 	ret = zif_lock_is_locked (store->priv->lock, NULL);
 	if (!ret) {
-		egg_warning ("not locked");
 		g_set_error_literal (error, 1, 0, "not locked");
 		goto out;
 	}
@@ -1229,7 +1234,6 @@ zif_store_remote_set_enabled (ZifStoreRemote *store, gboolean enabled, GError **
 	/* not locked */
 	ret = zif_lock_is_locked (store->priv->lock, NULL);
 	if (!ret) {
-		egg_warning ("not locked");
 		g_set_error_literal (error, 1, 0, "not locked");
 		goto out;
 	}
@@ -1297,7 +1301,6 @@ zif_store_remote_resolve (ZifStore *store, const gchar *search, GCancellable *ca
 	/* not locked */
 	ret = zif_lock_is_locked (remote->priv->lock, NULL);
 	if (!ret) {
-		egg_warning ("not locked");
 		g_set_error_literal (error, 1, 0, "not locked");
 		goto out;
 	}
@@ -1349,7 +1352,6 @@ zif_store_remote_search_name (ZifStore *store, const gchar *search, GCancellable
 	/* not locked */
 	ret = zif_lock_is_locked (remote->priv->lock, NULL);
 	if (!ret) {
-		egg_warning ("not locked");
 		g_set_error_literal (error, 1, 0, "not locked");
 		goto out;
 	}
@@ -1401,7 +1403,6 @@ zif_store_remote_search_details (ZifStore *store, const gchar *search, GCancella
 	/* not locked */
 	ret = zif_lock_is_locked (remote->priv->lock, NULL);
 	if (!ret) {
-		egg_warning ("not locked");
 		g_set_error_literal (error, 1, 0, "not locked");
 		goto out;
 	}
@@ -1526,7 +1527,6 @@ zif_store_remote_search_category (ZifStore *store, const gchar *group_id, GCance
 	/* not locked */
 	ret = zif_lock_is_locked (remote->priv->lock, NULL);
 	if (!ret) {
-		egg_warning ("not locked");
 		g_set_error_literal (error, 1, 0, "not locked");
 		goto out;
 	}
@@ -1642,7 +1642,6 @@ zif_store_remote_search_group (ZifStore *store, const gchar *search, GCancellabl
 	/* not locked */
 	ret = zif_lock_is_locked (remote->priv->lock, NULL);
 	if (!ret) {
-		egg_warning ("not locked");
 		g_set_error_literal (error, 1, 0, "not locked");
 		goto out;
 	}
@@ -1695,7 +1694,6 @@ zif_store_remote_find_package (ZifStore *store, const gchar *package_id, GCancel
 	/* not locked */
 	ret = zif_lock_is_locked (remote->priv->lock, NULL);
 	if (!ret) {
-		egg_warning ("not locked");
 		g_set_error_literal (error, 1, 0, "not locked");
 		goto out;
 	}
@@ -1769,7 +1767,6 @@ zif_store_remote_get_packages (ZifStore *store, GCancellable *cancellable, ZifCo
 	/* not locked */
 	ret = zif_lock_is_locked (remote->priv->lock, NULL);
 	if (!ret) {
-		egg_warning ("not locked");
 		g_set_error_literal (error, 1, 0, "not locked");
 		goto out;
 	}
@@ -1830,7 +1827,6 @@ zif_store_remote_get_categories (ZifStore *store, GCancellable *cancellable, Zif
 	/* not locked */
 	ret = zif_lock_is_locked (remote->priv->lock, NULL);
 	if (!ret) {
-		egg_warning ("not locked");
 		g_set_error_literal (error, 1, 0, "not locked");
 		goto out;
 	}
@@ -1956,7 +1952,6 @@ zif_store_remote_get_updates (ZifStore *store, GCancellable *cancellable, ZifCom
 	/* not locked */
 	ret = zif_lock_is_locked (remote->priv->lock, NULL);
 	if (!ret) {
-		egg_warning ("not locked");
 		g_set_error_literal (error, 1, 0, "not locked");
 		goto out;
 	}
@@ -2054,7 +2049,6 @@ zif_store_remote_what_provides (ZifStore *store, const gchar *search, GCancellab
 	/* not locked */
 	ret = zif_lock_is_locked (remote->priv->lock, NULL);
 	if (!ret) {
-		egg_warning ("not locked");
 		g_set_error_literal (error, 1, 0, "not locked");
 		goto out;
 	}
@@ -2093,7 +2087,6 @@ zif_store_remote_search_file (ZifStore *store, const gchar *search, GCancellable
 	/* not locked */
 	ret = zif_lock_is_locked (remote->priv->lock, NULL);
 	if (!ret) {
-		egg_warning ("not locked");
 		g_set_error_literal (error, 1, 0, "not locked");
 		goto out;
 	}
@@ -2186,7 +2179,6 @@ zif_store_remote_is_devel (ZifStoreRemote *store, GCancellable *cancellable, Zif
 	/* not locked */
 	ret = zif_lock_is_locked (store->priv->lock, NULL);
 	if (!ret) {
-		egg_warning ("not locked");
 		g_set_error_literal (error, 1, 0, "not locked");
 		goto out;
 	}
@@ -2255,7 +2247,6 @@ zif_store_remote_get_name (ZifStoreRemote *store, GCancellable *cancellable, Zif
 	/* not locked */
 	ret = zif_lock_is_locked (store->priv->lock, NULL);
 	if (!ret) {
-		egg_warning ("not locked");
 		g_set_error_literal (error, 1, 0, "not locked");
 		goto out;
 	}
@@ -2296,7 +2287,6 @@ zif_store_remote_get_enabled (ZifStoreRemote *store, GCancellable *cancellable,
 	/* not locked */
 	ret = zif_lock_is_locked (store->priv->lock, NULL);
 	if (!ret) {
-		egg_warning ("not locked");
 		g_set_error_literal (error, 1, 0, "not locked");
 		goto out;
 	}
diff --git a/backends/yum/libzif/zif.h b/backends/yum/libzif/zif.h
index d21c0aa..aebba71 100644
--- a/backends/yum/libzif/zif.h
+++ b/backends/yum/libzif/zif.h
@@ -29,12 +29,12 @@
 #include <zif-string.h>
 #include <zif-depend.h>
 #include <zif-package.h>
+#include <zif-store-array.h>
 #include <zif-package-local.h>
 #include <zif-package-remote.h>
 #include <zif-store-local.h>
 #include <zif-store-remote.h>
 #include <zif-repos.h>
-#include <zif-sack.h>
 #include <zif-utils.h>
 #include <zif-groups.h>
 #include <zif-download.h>
diff --git a/backends/yum/pk-backend-yum.c b/backends/yum/pk-backend-yum.c
index dfedd4b..0588c10 100644
--- a/backends/yum/pk-backend-yum.c
+++ b/backends/yum/pk-backend-yum.c
@@ -41,6 +41,7 @@ typedef struct {
 	ZifGroups	*groups;
 	ZifCompletion	*completion;
 	ZifLock		*lock;
+	GTimer		*timer;
 } PkBackendYumPrivate;
 
 static PkBackendYumPrivate *priv;
@@ -92,6 +93,23 @@ backend_completion_subpercentage_changed_cb (ZifCompletion *completion, guint su
 }
 
 /**
+ * backend_profile:
+ */
+static void
+backend_profile (const gchar *title)
+{
+	gdouble elapsed;
+
+	/* just reset?  */
+	if (title == NULL)
+		goto out;
+	elapsed = g_timer_elapsed (priv->timer, NULL);
+	g_print ("PROFILE: %ims\t%s\n", (guint) (elapsed * 1000.0f), title);
+out:
+	g_timer_reset (priv->timer);
+}
+
+/**
  * backend_get_lock:
  */
 static gboolean
@@ -175,9 +193,15 @@ backend_initialize (PkBackend *backend)
 		g_error_free (error);
 	}
 
+	/* use a timer for profiling */
+	priv->timer = g_timer_new ();
+
 	/* init rpm */
 	zif_init ();
 
+	/* profile */
+	backend_profile ("zif init");
+
 	/* TODO: hook up errors */
 	priv->cancellable = g_cancellable_new ();
 
@@ -195,6 +219,9 @@ backend_initialize (PkBackend *backend)
 		goto out;
 	}
 
+	/* profile */
+	backend_profile ("read config_file");
+
 	/* ZifDownload */
 	priv->download = zif_download_new ();
 
@@ -210,6 +237,9 @@ backend_initialize (PkBackend *backend)
 		goto out;
 	}
 
+	/* profile */
+	backend_profile ("read local store");
+
 	/* ZifRepos */
 	priv->repos = zif_repos_new ();
 	ret = zif_repos_set_repos_dir (priv->repos, "/etc/yum.repos.d", &error);
@@ -219,6 +249,9 @@ backend_initialize (PkBackend *backend)
 		goto out;
 	}
 
+	/* profile */
+	backend_profile ("read repos");
+
 	/* ZifGroups */
 	priv->groups = zif_groups_new ();
 	ret = zif_groups_set_mapping_file (priv->groups, "/usr/share/PackageKit/helpers/yum/yum-comps-groups.conf", &error);
@@ -227,6 +260,9 @@ backend_initialize (PkBackend *backend)
 		g_error_free (error);
 		goto out;
 	}
+
+	/* profile */
+	backend_profile ("read groups");
 out:
 	g_object_unref (file);
 }
@@ -256,6 +292,8 @@ backend_destroy (PkBackend *backend)
 		g_object_unref (priv->store_local);
 	if (priv->lock != NULL)
 		g_object_unref (priv->lock);
+	if (priv->timer != NULL)
+		g_timer_destroy (priv->timer);
 	g_free (priv);
 }
 
@@ -526,12 +564,133 @@ backend_get_distro_upgrades (PkBackend *backend)
 }
 
 /**
+ * backend_get_files_thread:
+ */
+static gboolean
+backend_get_files_thread (PkBackend *backend)
+{
+	gboolean ret;
+	gchar **package_ids = pk_backend_get_strv (backend, "package_ids");
+	GPtrArray *store_array = NULL;
+	ZifPackage *package;
+	GPtrArray *files;
+	ZifCompletion *completion_local;
+	const gchar *id;
+	guint i, j;
+	guint len;
+	GError *error = NULL;
+	const gchar *file;
+	GString *files_str;
+
+	/* reset */
+	backend_profile (NULL);
+
+	/* get lock */
+	ret = backend_get_lock (backend);
+	if (!ret) {
+		egg_warning ("failed to get lock");
+		goto out;
+	}
+
+	/* profile */
+	backend_profile ("get lock");
+
+	len = g_strv_length (package_ids);
+
+	/* setup completion */
+	zif_completion_reset (priv->completion);
+	zif_completion_set_number_steps (priv->completion, len + 1);
+
+	/* find all the packages */
+	completion_local = zif_completion_get_child (priv->completion);
+//	store_array = backend_get_default_store_array_for_filter (backend, PK_FILTER_ENUM_UNKNOWN, completion_local);
+{
+	ZifStore *store;
+	store = ZIF_STORE (zif_store_local_new ());
+	store_array = zif_store_array_new ();
+	zif_store_array_add_store (store_array, store);
+	g_object_unref (store);
+}
+
+	/* profile */
+	backend_profile ("add local");
+
+	/* this section done */
+	zif_completion_done (priv->completion);
+
+	pk_backend_set_status (backend, PK_STATUS_ENUM_QUERY);
+	for (i=0; package_ids[i] != NULL; i++) {
+		id = package_ids[i];
+		completion_local = zif_completion_get_child (priv->completion);
+		package = zif_store_array_find_package (store_array, id, priv->cancellable, completion_local, &error);
+		if (package == NULL) {
+			pk_backend_error_code (backend, PK_ERROR_ENUM_PACKAGE_NOT_FOUND, "failed to find %s: %s", package_ids[i], error->message);
+			g_error_free (error);
+			goto out;
+		}
+
+		/* profile */
+		backend_profile ("find package");
+
+		files = zif_package_get_files (package, &error);
+		if (files == NULL) {
+			pk_backend_error_code (backend, PK_ERROR_ENUM_INTERNAL_ERROR, "no files for %s: %s", package_ids[i], error->message);
+			g_error_free (error);
+			goto out;
+		}
+
+		/* profile */
+		backend_profile ("get files");
+
+		files_str = g_string_new ("");
+		for (j=0; j<files->len; j++) {
+			file = g_ptr_array_index (files, j);
+			g_string_append_printf (files_str, "%s\n", file);
+		}
+		pk_backend_files (backend, package_ids[i], files_str->str);
+
+		/* profile */
+		backend_profile ("emit files");
+
+		/* this section done */
+		zif_completion_done (priv->completion);
+
+		g_string_free (files_str, TRUE);
+		g_object_unref (package);
+	}
+out:
+	backend_unlock (backend);
+	pk_backend_finished (backend);
+	if (store_array != NULL)
+		g_ptr_array_unref (store_array);
+	return TRUE;
+}
+
+/**
  * backend_get_files:
  */
 static void
 backend_get_files (PkBackend *backend, gchar **package_ids)
 {
 	gchar *package_ids_temp;
+	guint i;
+	gboolean is_all_installed = TRUE;
+
+	/* check if we can use zif */
+	for (i=0; package_ids[i] != NULL; i++) {
+		if (!g_str_has_suffix (package_ids[i], ";installed")) {
+			is_all_installed = FALSE;
+			break;
+		}
+	}
+
+	/* yippee, we can use zif */
+	if (is_all_installed) {
+		pk_backend_thread_create (backend, backend_get_files_thread);
+		return;
+	}
+
+	/* fall back to spawning */
 	package_ids_temp = pk_package_ids_to_string (package_ids);
 	pk_backend_spawn_helper (priv->spawn,  "yumBackend.py", "get-files", package_ids_temp, NULL);
 	g_free (package_ids_temp);
commit 42383763e1566f3476ff0d38b43f19cccba9b055
Author: raven <raven at fedoraproject.org>
Date:   Wed Mar 10 10:16:07 2010 +0000

    Sending translation for Polish

diff --git a/po/pl.po b/po/pl.po
index e59b02f..740e7d7 100644
--- a/po/pl.po
+++ b/po/pl.po
@@ -5,8 +5,8 @@ msgid ""
 msgstr ""
 "Project-Id-Version: pl\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2010-01-14 21:45+0000\n"
-"PO-Revision-Date: 2010-01-14 22:50+0100\n"
+"POT-Creation-Date: 2010-03-10 09:00+0000\n"
+"PO-Revision-Date: 2010-03-10 11:15+0100\n"
 "Last-Translator: Piotr DrÄ…g <piotrdrag at gmail.com>\n"
 "Language-Team: Polish <trans-pl at lists.fedoraproject.org>\n"
 "MIME-Version: 1.0\n"
@@ -267,39 +267,43 @@ msgid "Status"
 msgstr "Stan"
 
 #. TRANSLATORS: the results from the transaction
-#: ../client/pk-console.c:678
+#: ../client/pk-console.c:679
 msgid "Results:"
 msgstr "Wyniki:"
 
 #. TRANSLATORS: we failed to get any results, which is pretty fatal in my book
-#: ../client/pk-console.c:685
+#: ../client/pk-console.c:686
 msgid "Fatal error"
 msgstr "Krytyczny błąd"
 
 #. TRANSLATORS: the transaction failed in a way we could not expect
-#: ../client/pk-console.c:694
+#: ../client/pk-console.c:695
 #: ../contrib/command-not-found/pk-command-not-found.c:432
 #: ../contrib/command-not-found/pk-command-not-found.c:603
 msgid "The transaction failed"
 msgstr "Transakcja nie powiodła się"
 
 #. TRANSLATORS: print a message when there are no updates
-#: ../client/pk-console.c:721
+#: ../client/pk-console.c:726
 msgid "There are no updates available at this time."
 msgstr "Brak dostępnych aktualizacji w tej chwili."
 
+#: ../client/pk-console.c:749
+msgid "There are no upgrades available at this time."
+msgstr "Brak dostępnych aktualizacji w tej chwili."
+
 #. TRANSLATORS: a package needs to restart their system
-#: ../client/pk-console.c:808
+#: ../client/pk-console.c:816
 msgid "Please restart the computer to complete the update."
 msgstr "Proszę uruchomić ponownie komputer, aby zakończyć aktualizację."
 
 #. TRANSLATORS: a package needs to restart the session
-#: ../client/pk-console.c:811
+#: ../client/pk-console.c:819
 msgid "Please logout and login to complete the update."
 msgstr "Proszę wylogować się i zalogować, aby zakończyć aktualizację."
 
 #. TRANSLATORS: a package needs to restart their system (due to security)
-#: ../client/pk-console.c:814
+#: ../client/pk-console.c:822
 msgid ""
 "Please restart the computer to complete the update as important security "
 "updates have been installed."
@@ -308,7 +312,7 @@ msgstr ""
 "zainstalowano aktualizacje bezpieczeństwa."
 
 #. TRANSLATORS: a package needs to restart the session (due to security)
-#: ../client/pk-console.c:817
+#: ../client/pk-console.c:825
 msgid ""
 "Please logout and login to complete the update as important security updates "
 "have been installed."
@@ -317,7 +321,7 @@ msgstr ""
 "zainstalowano aktualizacje bezpieczeństwa."
 
 #. TRANSLATORS: The user used 'pkcon install dave.rpm' rather than 'pkcon install-local dave.rpm'
-#: ../client/pk-console.c:843
+#: ../client/pk-console.c:851
 #, c-format
 msgid ""
 "Extected package name, actually got file. Try using 'pkcon install-local %s' "
@@ -327,19 +331,19 @@ msgstr ""
 "wykonać polecenie \"pkcon install-local %s\"."
 
 #. TRANSLATORS: There was an error getting the list of files for the package. The detailed error follows
-#: ../client/pk-console.c:851
+#: ../client/pk-console.c:859
 #, c-format
 msgid "This tool could not find any available package: %s"
 msgstr "Te narzędzie nie może odnaleźć dostępnych pakietów: %s"
 
 #. TRANSLATORS: There was an error getting the list of files for the package. The detailed error follows
-#: ../client/pk-console.c:879
+#: ../client/pk-console.c:887
 #, c-format
 msgid "This tool could not find the installed package: %s"
 msgstr "Te narzędzie nie może odnaleźć zainstalowanego pakietu: %s"
 
 #. TRANSLATORS: There was an error getting the list of files for the package. The detailed error follows
-#: ../client/pk-console.c:907 ../client/pk-console.c:935
+#: ../client/pk-console.c:915 ../client/pk-console.c:943
 #, c-format
 msgid "This tool could not find the package: %s"
 msgstr "Te narzędzie nie może odnaleźć pakietu: %s"
@@ -348,64 +352,64 @@ msgstr "Te narzędzie nie może odnaleźć pakietu: %s"
 #. TRANSLATORS: There was an error getting the dependencies for the package. The detailed error follows
 #. TRANSLATORS: There was an error getting the details about the package. The detailed error follows
 #. TRANSLATORS: The package name was not found in any software sources. The detailed error follows
-#: ../client/pk-console.c:963 ../client/pk-console.c:991
-#: ../client/pk-console.c:1019 ../client/pk-console.c:1047
-#: ../client/pk-console.c:1075
+#: ../client/pk-console.c:971 ../client/pk-console.c:999
+#: ../client/pk-console.c:1027 ../client/pk-console.c:1055
+#: ../client/pk-console.c:1083
 #, c-format
 msgid "This tool could not find all the packages: %s"
 msgstr "Te narzędzie nie może odnaleźć wszystkich pakietów: %s"
 
 #. TRANSLATORS: This is when the daemon crashed, and we are up shit creek without a paddle
-#: ../client/pk-console.c:1104
+#: ../client/pk-console.c:1112
 msgid "The daemon crashed mid-transaction!"
 msgstr "Demon zawiesił się w połowie transakcji!"
 
 #. TRANSLATORS: This is the header to the --help menu
-#: ../client/pk-console.c:1138
+#: ../client/pk-console.c:1146
 msgid "PackageKit Console Interface"
 msgstr "Interfejs konsoli PackageKit"
 
 #. these are commands we can use with pkcon
-#: ../client/pk-console.c:1140
+#: ../client/pk-console.c:1148
 msgid "Subcommands:"
 msgstr "Podpolecenia:"
 
 #. TRANSLATORS: we keep a database updated with the time that an action was last executed
-#: ../client/pk-console.c:1219
+#: ../client/pk-console.c:1227
 msgid "Failed to get the time since this action was last completed"
 msgstr ""
 "Uzyskanie czasu od ostatniego zakończenia tego działania nie powiodło się"
 
 #. TRANSLATORS: command line argument, just show the version string
-#: ../client/pk-console.c:1255 ../client/pk-monitor.c:280
+#: ../client/pk-console.c:1263 ../client/pk-monitor.c:306
 msgid "Show the program version and exit"
 msgstr "Wyświetla wersję programu i wyłącza"
 
 #. TRANSLATORS: command line argument, use a filter to narrow down results
-#: ../client/pk-console.c:1258
+#: ../client/pk-console.c:1266
 msgid "Set the filter, e.g. installed"
 msgstr "Ustawia filtr, np. zainstalowane"
 
 #. TRANSLATORS: command line argument, work asynchronously
-#: ../client/pk-console.c:1261
+#: ../client/pk-console.c:1269
 msgid "Exit without waiting for actions to complete"
 msgstr "Wyłącza bez oczekiwania na zakończenie działań"
 
 #. command line argument, do we ask questions
-#: ../client/pk-console.c:1264
+#: ../client/pk-console.c:1272
 #: ../contrib/debuginfo-install/pk-debuginfo-install.c:527
 msgid "Install the packages without asking for confirmation"
 msgstr "Instaluje pakiety bez prośby o potwierdzenie"
 
 #. TRANSLATORS: command line argument, this command is not a priority
-#: ../client/pk-console.c:1267
+#: ../client/pk-console.c:1275
 msgid "Run the command using idle network bandwidth and also using less power"
 msgstr ""
 "Wykonuje polecenie używając bezczynnego połączenia sieciowego, a także "
 "zużywając mniej energii"
 
 #. TRANSLATORS: command line argument, just output without fancy formatting
-#: ../client/pk-console.c:1270
+#: ../client/pk-console.c:1278
 msgid ""
 "Print to screen a machine readable output, rather than using animated widgets"
 msgstr ""
@@ -413,117 +417,117 @@ msgstr ""
 "widgetów"
 
 #. TRANSLATORS: we failed to contact the daemon
-#: ../client/pk-console.c:1292
+#: ../client/pk-console.c:1300
 msgid "Failed to contact PackageKit"
 msgstr "Skontaktowanie się z usługą PackageKit nie powiodło się"
 
 #. TRANSLATORS: The user specified an incorrect filter
-#: ../client/pk-console.c:1350
+#: ../client/pk-console.c:1358
 msgid "The filter specified was invalid"
 msgstr "Podany filtr jest nieprawidłowy"
 
 #. TRANSLATORS: a search type can be name, details, file, etc
-#: ../client/pk-console.c:1369
+#: ../client/pk-console.c:1377
 msgid "A search type is required, e.g. name"
 msgstr "Wymagany jest typ wyszukiwania, np. nazwa"
 
 #. TRANSLATORS: the user needs to provide a search term
-#: ../client/pk-console.c:1376 ../client/pk-console.c:1388
-#: ../client/pk-console.c:1400 ../client/pk-console.c:1412
+#: ../client/pk-console.c:1384 ../client/pk-console.c:1396
+#: ../client/pk-console.c:1408 ../client/pk-console.c:1420
 msgid "A search term is required"
 msgstr "Wymagany jest wyszukiwany termin"
 
 #. TRANSLATORS: the search type was provided, but invalid
-#: ../client/pk-console.c:1422
+#: ../client/pk-console.c:1430
 msgid "Invalid search type"
 msgstr "Nieprawidłowy typ wyszukiwania"
 
 #. TRANSLATORS: the user did not specify what they wanted to install
-#: ../client/pk-console.c:1428
+#: ../client/pk-console.c:1436
 msgid "A package name to install is required"
 msgstr "Wymagana jest nazwa pakietu do zainstalowania"
 
 #. TRANSLATORS: the user did not specify what they wanted to install
-#: ../client/pk-console.c:1437
+#: ../client/pk-console.c:1445
 msgid "A filename to install is required"
 msgstr "Wymagana jest nazwa pliku do zainstalowania"
 
 #. TRANSLATORS: geeky error, 99.9999% of users won't see this
-#: ../client/pk-console.c:1449
+#: ../client/pk-console.c:1457
 msgid "A type, key_id and package_id are required"
 msgstr "Wymagany jest typ, key_id i package_id"
 
 #. TRANSLATORS: the user did not specify what they wanted to remove
-#: ../client/pk-console.c:1460
+#: ../client/pk-console.c:1468
 msgid "A package name to remove is required"
 msgstr "Wymagana jest nazwa pakietu do usunięcia"
 
 #. TRANSLATORS: the user did not specify anything about what to download or where
-#: ../client/pk-console.c:1469
+#: ../client/pk-console.c:1477
 msgid "A destination directory and the package names to download are required"
 msgstr "Wymagany jest katalog docelowy i nazwy pakietów do pobrania"
 
 #. TRANSLATORS: the directory does not exist, so we can't continue
-#: ../client/pk-console.c:1476
+#: ../client/pk-console.c:1484
 msgid "Directory not found"
 msgstr "Nie odnaleziono katalogu"
 
 #. TRANSLATORS: geeky error, 99.9999% of users won't see this
-#: ../client/pk-console.c:1485
+#: ../client/pk-console.c:1493
 msgid "A licence identifier (eula-id) is required"
 msgstr "Wymagany jest identyfikator licencji (eula-id)"
 
 #. TRANSLATORS: geeky error, 99.9999% of users won't see this
-#: ../client/pk-console.c:1496
+#: ../client/pk-console.c:1504
 msgid "A transaction identifier (tid) is required"
 msgstr "Wymagany jest identyfikator transakcji (tid)"
 
 #. TRANSLATORS: The user did not specify a package name
-#: ../client/pk-console.c:1517
+#: ../client/pk-console.c:1525
 msgid "A package name to resolve is required"
 msgstr "Wymagana jest nazwa pakietu do rozwiÄ…zania"
 
 #. TRANSLATORS: The user did not specify a repository (software source) name
-#: ../client/pk-console.c:1528 ../client/pk-console.c:1539
+#: ../client/pk-console.c:1536 ../client/pk-console.c:1547
 msgid "A repository name is required"
 msgstr "Wymagana jest nazwa repozytorium"
 
 #. TRANSLATORS: The user didn't provide any data
-#: ../client/pk-console.c:1550
+#: ../client/pk-console.c:1558
 msgid "A repo name, parameter and value are required"
 msgstr "Wymagana jest nazwa, parametr i wartość repozytorium"
 
 #. TRANSLATORS: The user didn't specify what action to use
-#: ../client/pk-console.c:1567
+#: ../client/pk-console.c:1575
 msgid "An action, e.g. 'update-system' is required"
 msgstr "Wymagane jest działanie, np. \"update-system\""
 
 #. TRANSLATORS: The user specified an invalid action
-#: ../client/pk-console.c:1574
+#: ../client/pk-console.c:1582
 msgid "A correct role is required"
 msgstr "Wymagana jest bieżąca rola"
 
 #. TRANSLATORS: The user did not provide a package name
 #. TRANSLATORS: This is when the user fails to supply the package name
-#: ../client/pk-console.c:1584 ../client/pk-console.c:1599
-#: ../client/pk-console.c:1608 ../client/pk-console.c:1628
-#: ../client/pk-console.c:1637 ../client/pk-generate-pack.c:316
+#: ../client/pk-console.c:1592 ../client/pk-console.c:1607
+#: ../client/pk-console.c:1616 ../client/pk-console.c:1636
+#: ../client/pk-console.c:1645 ../client/pk-generate-pack.c:316
 msgid "A package name is required"
 msgstr "Wymagana jest nazwa pakietu"
 
 #. TRANSLATORS: each package "provides" certain things, e.g. mime(gstreamer-decoder-mp3), the user didn't specify it
-#: ../client/pk-console.c:1617
+#: ../client/pk-console.c:1625
 msgid "A package provide string is required"
 msgstr "Wymagany jest łańcuch dostarczania pakietu"
 
 #. TRANSLATORS: The user tried to use an unsupported option on the command line
-#: ../client/pk-console.c:1697
+#: ../client/pk-console.c:1705
 #, c-format
 msgid "Option '%s' is not supported"
 msgstr "Opcja \"%s\" nie jest obsługiwana"
 
 #. TRANSLATORS: Generic failure of what they asked to do
-#: ../client/pk-console.c:1707
+#: ../client/pk-console.c:1715
 msgid "Command failed"
 msgstr "Polecenie nie powiodło się"
 
@@ -638,12 +642,12 @@ msgstr "Utworzono pakiet serwisowy \"%s\""
 msgid "Failed to create '%s': %s"
 msgstr "Utworzenie \"%s\" nie powiodło się: %s"
 
-#: ../client/pk-monitor.c:210
+#: ../client/pk-monitor.c:236
 msgid "Failed to get daemon state"
 msgstr "Uzyskanie stanu demona nie powiodło się"
 
 #. TRANSLATORS: this is a program that monitors PackageKit
-#: ../client/pk-monitor.c:296
+#: ../client/pk-monitor.c:322
 msgid "PackageKit Monitor"
 msgstr "Monitor PackageKit"
 
commit 9b0eab18ac4c62210d4b382086d908500579bfa6
Author: warrink <warrink at fedoraproject.org>
Date:   Wed Mar 10 09:32:16 2010 +0000

    Sending translation for Dutch

diff --git a/po/nl.po b/po/nl.po
index b8679f5..59e4859 100644
--- a/po/nl.po
+++ b/po/nl.po
@@ -6,8 +6,8 @@ msgid ""
 msgstr ""
 "Project-Id-Version: packagekit.master\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2010-01-21 09:59+0000\n"
-"PO-Revision-Date: 2010-01-21 15:50+0100\n"
+"POT-Creation-Date: 2010-03-10 09:24+0000\n"
+"PO-Revision-Date: 2010-03-10 10:31+0100\n"
 "Last-Translator: Richard van der Luit <nippur at fedoraproject.org>\n"
 "Language-Team: Dutch <nl at li.org>\n"
 "MIME-Version: 1.0\n"
@@ -268,39 +268,43 @@ msgid "Status"
 msgstr "Status"
 
 #. TRANSLATORS: the results from the transaction
-#: ../client/pk-console.c:678
+#: ../client/pk-console.c:679
 msgid "Results:"
 msgstr "Resultaten:"
 
 #. TRANSLATORS: we failed to get any results, which is pretty fatal in my book
-#: ../client/pk-console.c:685
+#: ../client/pk-console.c:686
 msgid "Fatal error"
 msgstr "Fatale fout"
 
 #. TRANSLATORS: the transaction failed in a way we could not expect
-#: ../client/pk-console.c:694
+#: ../client/pk-console.c:695
 #: ../contrib/command-not-found/pk-command-not-found.c:432
 #: ../contrib/command-not-found/pk-command-not-found.c:603
 msgid "The transaction failed"
 msgstr "De transactie faalde"
 
 #. TRANSLATORS: print a message when there are no updates
-#: ../client/pk-console.c:721
+#: ../client/pk-console.c:726
 msgid "There are no updates available at this time."
 msgstr "Er zijn op dit moment geen vernieuwingen beschikbaar."
 
+#: ../client/pk-console.c:749
+msgid "There are no upgrades available at this time."
+msgstr "Er zijn op dit moment geen upgrades beschikbaar."
+
 #. TRANSLATORS: a package needs to restart their system
-#: ../client/pk-console.c:808
+#: ../client/pk-console.c:816
 msgid "Please restart the computer to complete the update."
 msgstr "Herstart a.u.b de computer om de verneuwing af te maken."
 
 #. TRANSLATORS: a package needs to restart the session
-#: ../client/pk-console.c:811
+#: ../client/pk-console.c:819
 msgid "Please logout and login to complete the update."
 msgstr "Log a.u.b uit en weer in om de vernieuwing af te maken."
 
 #. TRANSLATORS: a package needs to restart their system (due to security)
-#: ../client/pk-console.c:814
+#: ../client/pk-console.c:822
 msgid ""
 "Please restart the computer to complete the update as important security "
 "updates have been installed."
@@ -309,14 +313,14 @@ msgstr ""
 "beveiligings vernieuwingen geïnstaleerd zijn."
 
 #. TRANSLATORS: a package needs to restart the session (due to security)
-#: ../client/pk-console.c:817
+#: ../client/pk-console.c:825
 msgid ""
 "Please logout and login to complete the update as important security updates "
 "have been installed."
 msgstr "Log a.u.b. uit en weer in om de verniewing af te maken."
 
 #. TRANSLATORS: The user used 'pkcon install dave.rpm' rather than 'pkcon install-local dave.rpm'
-#: ../client/pk-console.c:843
+#: ../client/pk-console.c:851
 #, c-format
 msgid ""
 "Extected package name, actually got file. Try using 'pkcon install-local %s' "
@@ -326,19 +330,19 @@ msgstr ""
 "'pkcon install-local %s' te gebruiken."
 
 #. TRANSLATORS: There was an error getting the list of files for the package. The detailed error follows
-#: ../client/pk-console.c:851
+#: ../client/pk-console.c:859
 #, c-format
 msgid "This tool could not find any available package: %s"
 msgstr "Dit programma kon geen enkel beschikbaar pakket %s vinden."
 
 #. TRANSLATORS: There was an error getting the list of files for the package. The detailed error follows
-#: ../client/pk-console.c:879
+#: ../client/pk-console.c:887
 #, c-format
 msgid "This tool could not find the installed package: %s"
 msgstr "Dit programma kon het geïinstallerde pakket %s niet vinden."
 
 #. TRANSLATORS: There was an error getting the list of files for the package. The detailed error follows
-#: ../client/pk-console.c:907 ../client/pk-console.c:935
+#: ../client/pk-console.c:915 ../client/pk-console.c:943
 #, c-format
 msgid "This tool could not find the package: %s"
 msgstr "Dit programma kon het pakket %s niet vinden."
@@ -347,64 +351,64 @@ msgstr "Dit programma kon het pakket %s niet vinden."
 #. TRANSLATORS: There was an error getting the dependencies for the package. The detailed error follows
 #. TRANSLATORS: There was an error getting the details about the package. The detailed error follows
 #. TRANSLATORS: The package name was not found in any software sources. The detailed error follows
-#: ../client/pk-console.c:963 ../client/pk-console.c:991
-#: ../client/pk-console.c:1019 ../client/pk-console.c:1047
-#: ../client/pk-console.c:1075
+#: ../client/pk-console.c:971 ../client/pk-console.c:999
+#: ../client/pk-console.c:1027 ../client/pk-console.c:1055
+#: ../client/pk-console.c:1083
 #, c-format
 msgid "This tool could not find all the packages: %s"
 msgstr "Dit programma kon niet alle pakketten vinden: %s"
 
 #. TRANSLATORS: This is when the daemon crashed, and we are up shit creek without a paddle
-#: ../client/pk-console.c:1104
+#: ../client/pk-console.c:1112
 msgid "The daemon crashed mid-transaction!"
 msgstr "De service is midden in de transactie gecrashed!"
 
 #. TRANSLATORS: This is the header to the --help menu
-#: ../client/pk-console.c:1138
+#: ../client/pk-console.c:1146
 msgid "PackageKit Console Interface"
 msgstr "PackageKit console-interface"
 
 #. these are commands we can use with pkcon
-#: ../client/pk-console.c:1140
+#: ../client/pk-console.c:1148
 msgid "Subcommands:"
 msgstr "Subopdrachten:"
 
 #. TRANSLATORS: we keep a database updated with the time that an action was last executed
-#: ../client/pk-console.c:1219
+#: ../client/pk-console.c:1227
 msgid "Failed to get the time since this action was last completed"
 msgstr ""
 "Verkrijgen van de tijd tussen laatste actie en deze actie is niet gelukt"
 
 #. TRANSLATORS: command line argument, just show the version string
-#: ../client/pk-console.c:1255 ../client/pk-monitor.c:280
+#: ../client/pk-console.c:1263 ../client/pk-monitor.c:306
 msgid "Show the program version and exit"
 msgstr "Programmaversie tonen en sluiten"
 
 #. TRANSLATORS: command line argument, use a filter to narrow down results
-#: ../client/pk-console.c:1258
+#: ../client/pk-console.c:1266
 msgid "Set the filter, e.g. installed"
 msgstr "Filter instellen, bijvoorbeeld geïnstalleerd"
 
 #. TRANSLATORS: command line argument, work asynchronously
-#: ../client/pk-console.c:1261
+#: ../client/pk-console.c:1269
 msgid "Exit without waiting for actions to complete"
 msgstr "Afsluiten zonder te wachten tot de transacties zijn afgerond"
 
 #. command line argument, do we ask questions
-#: ../client/pk-console.c:1264
+#: ../client/pk-console.c:1272
 #: ../contrib/debuginfo-install/pk-debuginfo-install.c:527
 msgid "Install the packages without asking for confirmation"
 msgstr "Installeer het pakket zonder goedkeuring te vragen"
 
 #. TRANSLATORS: command line argument, this command is not a priority
-#: ../client/pk-console.c:1267
+#: ../client/pk-console.c:1275
 msgid "Run the command using idle network bandwidth and also using less power"
 msgstr ""
 "Voer het commando uit met gebruik van onbenutte netwerk bandbreedte en ook "
 "om minder vermogen te gebruiken"
 
 #. TRANSLATORS: command line argument, just output without fancy formatting
-#: ../client/pk-console.c:1270
+#: ../client/pk-console.c:1278
 msgid ""
 "Print to screen a machine readable output, rather than using animated widgets"
 msgstr ""
@@ -412,117 +416,117 @@ msgstr ""
 "widgets te gebruiken"
 
 #. TRANSLATORS: we failed to contact the daemon
-#: ../client/pk-console.c:1292
+#: ../client/pk-console.c:1300
 msgid "Failed to contact PackageKit"
 msgstr "Contact met PackageKit krijgen mislukte."
 
 #. TRANSLATORS: The user specified an incorrect filter
-#: ../client/pk-console.c:1350
+#: ../client/pk-console.c:1358
 msgid "The filter specified was invalid"
 msgstr "De opgegeven filter was ongeldig"
 
 #. TRANSLATORS: a search type can be name, details, file, etc
-#: ../client/pk-console.c:1369
+#: ../client/pk-console.c:1377
 msgid "A search type is required, e.g. name"
 msgstr "Een zoektype is verplicht, b.v. naam"
 
 #. TRANSLATORS: the user needs to provide a search term
-#: ../client/pk-console.c:1376 ../client/pk-console.c:1388
-#: ../client/pk-console.c:1400 ../client/pk-console.c:1412
+#: ../client/pk-console.c:1384 ../client/pk-console.c:1396
+#: ../client/pk-console.c:1408 ../client/pk-console.c:1420
 msgid "A search term is required"
 msgstr "Een zoekterm is vereist"
 
 #. TRANSLATORS: the search type was provided, but invalid
-#: ../client/pk-console.c:1422
+#: ../client/pk-console.c:1430
 msgid "Invalid search type"
 msgstr "Ongeldig zoektype"
 
 #. TRANSLATORS: the user did not specify what they wanted to install
-#: ../client/pk-console.c:1428
+#: ../client/pk-console.c:1436
 msgid "A package name to install is required"
 msgstr "Een pakketnaam om te installeren is vereist"
 
 #. TRANSLATORS: the user did not specify what they wanted to install
-#: ../client/pk-console.c:1437
+#: ../client/pk-console.c:1445
 msgid "A filename to install is required"
 msgstr "Een bestandsnaam om te installeren is vereist"
 
 #. TRANSLATORS: geeky error, 99.9999% of users won't see this
-#: ../client/pk-console.c:1449
+#: ../client/pk-console.c:1457
 msgid "A type, key_id and package_id are required"
 msgstr "Er moet een type worden opgegeven, key_id of package_id"
 
 #. TRANSLATORS: the user did not specify what they wanted to remove
-#: ../client/pk-console.c:1460
+#: ../client/pk-console.c:1468
 msgid "A package name to remove is required"
 msgstr "Een te verwijderen pakketnaam is vereist"
 
 #. TRANSLATORS: the user did not specify anything about what to download or where
-#: ../client/pk-console.c:1469
+#: ../client/pk-console.c:1477
 msgid "A destination directory and the package names to download are required"
 msgstr "Een doelmap en dan de namen van te downloaden pakketten zijn vereist"
 
 #. TRANSLATORS: the directory does not exist, so we can't continue
-#: ../client/pk-console.c:1476
+#: ../client/pk-console.c:1484
 msgid "Directory not found"
 msgstr "Map niet gevonden"
 
 #. TRANSLATORS: geeky error, 99.9999% of users won't see this
-#: ../client/pk-console.c:1485
+#: ../client/pk-console.c:1493
 msgid "A licence identifier (eula-id) is required"
 msgstr "Een licentie indentificatie (eula-id) is vereis"
 
 #. TRANSLATORS: geeky error, 99.9999% of users won't see this
-#: ../client/pk-console.c:1496
+#: ../client/pk-console.c:1504
 msgid "A transaction identifier (tid) is required"
 msgstr "Een transactie indentificatie (tid) is vereist"
 
 #. TRANSLATORS: The user did not specify a package name
-#: ../client/pk-console.c:1517
+#: ../client/pk-console.c:1525
 msgid "A package name to resolve is required"
 msgstr "Een pakketnaam om te gebruiken is vereist"
 
 #. TRANSLATORS: The user did not specify a repository (software source) name
-#: ../client/pk-console.c:1528 ../client/pk-console.c:1539
+#: ../client/pk-console.c:1536 ../client/pk-console.c:1547
 msgid "A repository name is required"
 msgstr "Een naam van een repository is vereist"
 
 #. TRANSLATORS: The user didn't provide any data
-#: ../client/pk-console.c:1550
+#: ../client/pk-console.c:1558
 msgid "A repo name, parameter and value are required"
 msgstr "Een repo naam, parameter en waarde zijn vereist"
 
 #. TRANSLATORS: The user didn't specify what action to use
-#: ../client/pk-console.c:1567
+#: ../client/pk-console.c:1575
 msgid "An action, e.g. 'update-system' is required"
 msgstr "Een actie, b.v. 'update-system' is vereist"
 
 #. TRANSLATORS: The user specified an invalid action
-#: ../client/pk-console.c:1574
+#: ../client/pk-console.c:1582
 msgid "A correct role is required"
 msgstr "Een correcte rol is vereist"
 
 #. TRANSLATORS: The user did not provide a package name
 #. TRANSLATORS: This is when the user fails to supply the package name
-#: ../client/pk-console.c:1584 ../client/pk-console.c:1599
-#: ../client/pk-console.c:1608 ../client/pk-console.c:1628
-#: ../client/pk-console.c:1637 ../client/pk-generate-pack.c:316
+#: ../client/pk-console.c:1592 ../client/pk-console.c:1607
+#: ../client/pk-console.c:1616 ../client/pk-console.c:1636
+#: ../client/pk-console.c:1645 ../client/pk-generate-pack.c:316
 msgid "A package name is required"
 msgstr "Een pakketnaam is vereist"
 
 #. TRANSLATORS: each package "provides" certain things, e.g. mime(gstreamer-decoder-mp3), the user didn't specify it
-#: ../client/pk-console.c:1617
+#: ../client/pk-console.c:1625
 msgid "A package provide string is required"
 msgstr "Een pakket geleverde string is vereist"
 
 #. TRANSLATORS: The user tried to use an unsupported option on the command line
-#: ../client/pk-console.c:1697
+#: ../client/pk-console.c:1705
 #, c-format
 msgid "Option '%s' is not supported"
 msgstr "Optie '%s' wordt niet ondersteund"
 
 #. TRANSLATORS: Generic failure of what they asked to do
-#: ../client/pk-console.c:1707
+#: ../client/pk-console.c:1715
 msgid "Command failed"
 msgstr "Opdracht mislukt"
 
@@ -639,12 +643,12 @@ msgstr "Servicepack aangemaakt '%s'"
 msgid "Failed to create '%s': %s"
 msgstr "'%s' aanmaken niet gelukt: %s"
 
-#: ../client/pk-monitor.c:210
+#: ../client/pk-monitor.c:236
 msgid "Failed to get daemon state"
 msgstr "Daemon toestand verkrijgen mislukte."
 
 #. TRANSLATORS: this is a program that monitors PackageKit
-#: ../client/pk-monitor.c:296
+#: ../client/pk-monitor.c:322
 msgid "PackageKit Monitor"
 msgstr "PackageKit-monitor"
 
commit c83d07435008ec286c88bf14cd0c8deea9965543
Author: Richard Hughes <richard at hughsie.com>
Date:   Tue Mar 9 17:18:04 2010 +0000

    yum: trivial: update to the latest upstream version of libzif

diff --git a/backends/yum/libzif/zif-config.c b/backends/yum/libzif/zif-config.c
index a8dd1cd..57a6355 100644
--- a/backends/yum/libzif/zif-config.c
+++ b/backends/yum/libzif/zif-config.c
@@ -84,8 +84,7 @@ zif_config_get_string (ZifConfig *config, const gchar *key, GError **error)
 
 	/* not loaded yet */
 	if (!config->priv->loaded) {
-		if (error != NULL)
-			*error = g_error_new (1, 0, "config not loaded");
+		g_set_error_literal (error, 1, 0, "config not loaded");
 		goto out;
 	}
 
@@ -135,8 +134,7 @@ zif_config_get_string (ZifConfig *config, const gchar *key, GError **error)
 	}
 
 	/* nothing matched */
-	if (error != NULL)
-		*error = g_error_new (1, 0, "failed to read %s: %s", key, error_local->message);
+	g_set_error (error, 1, 0, "failed to read %s: %s", key, error_local->message);
 free_error:
 	g_error_free (error_local);
 out:
@@ -203,8 +201,7 @@ zif_config_get_uint (ZifConfig *config, const gchar *key, GError **error)
 	/* convert to int */
 	ret = egg_strtouint (value, &retval);
 	if (!ret) {
-		if (error != NULL)
-			*error = g_error_new (1, 0, "failed to convert '%s' to unsigned integer", value);
+		g_set_error (error, 1, 0, "failed to convert '%s' to unsigned integer", value);
 		goto out;
 	}
 
@@ -384,16 +381,14 @@ zif_config_set_filename (ZifConfig *config, const gchar *filename, GError **erro
 	/* check file exists */
 	ret = g_file_test (filename, G_FILE_TEST_IS_REGULAR);
 	if (!ret) {
-		if (error != NULL)
-			*error = g_error_new (1, 0, "config file %s does not exist", filename);
+		g_set_error (error, 1, 0, "config file %s does not exist", filename);
 		goto out;
 	}
 
 	/* setup watch */
 	ret = zif_monitor_add_watch (config->priv->monitor, filename, &error_local);
 	if (!ret) {
-		if (error != NULL)
-			*error = g_error_new (1, 0, "failed to setup watch: %s", error_local->message);
+		g_set_error (error, 1, 0, "failed to setup watch: %s", error_local->message);
 		g_error_free (error_local);
 		goto out;
 	}
@@ -401,8 +396,7 @@ zif_config_set_filename (ZifConfig *config, const gchar *filename, GError **erro
 	/* load file */
 	ret = g_key_file_load_from_file (config->priv->keyfile, filename, G_KEY_FILE_NONE, &error_local);
 	if (!ret) {
-		if (error != NULL)
-			*error = g_error_new (1, 0, "failed to load config file: %s", error_local->message);
+		g_set_error (error, 1, 0, "failed to load config file: %s", error_local->message);
 		g_error_free (error_local);
 		goto out;
 	}
@@ -416,8 +410,7 @@ zif_config_set_filename (ZifConfig *config, const gchar *filename, GError **erro
 		/* get distro constants from fedora-release */
 		ret = g_file_get_contents ("/etc/fedora-release", &releasever, NULL, &error_local);
 		if (!ret) {
-			if (error != NULL)
-				*error = g_error_new (1, 0, "failed to get distro release version: %s", error_local->message);
+			g_set_error (error, 1, 0, "failed to get distro release version: %s", error_local->message);
 			g_error_free (error_local);
 			goto out;
 		}
@@ -428,8 +421,7 @@ zif_config_set_filename (ZifConfig *config, const gchar *filename, GError **erro
 		/* set local */
 		ret = zif_config_set_local (config, "releasever", releasever+15, &error_local);
 		if (!ret) {
-			if (error != NULL)
-				*error = g_error_new (1, 0, "failed to set distro release version: %s", error_local->message);
+			g_set_error (error, 1, 0, "failed to set distro release version: %s", error_local->message);
 			g_error_free (error_local);
 			goto out;
 		}
@@ -438,8 +430,7 @@ zif_config_set_filename (ZifConfig *config, const gchar *filename, GError **erro
 	/* calculate the valid basearchs */
 	basearch = zif_config_get_string (config, "basearch", &error_local);
 	if (basearch == NULL) {
-		if (error != NULL)
-			*error = g_error_new (1, 0, "failed to get basearch: %s", error_local->message);
+		g_set_error (error, 1, 0, "failed to get basearch: %s", error_local->message);
 		g_error_free (error_local);
 		ret = FALSE;
 		goto out;
@@ -508,8 +499,7 @@ zif_config_set_local (ZifConfig *config, const gchar *key, const gchar *value, G
 	/* already exists? */
 	value_tmp = g_hash_table_lookup (config->priv->hash, key);
 	if (value_tmp != NULL) {
-		if (error != NULL)
-			*error = g_error_new (1, 0, "already set key %s to %s, cannot overwrite with %s", key, value_tmp, value);
+		g_set_error (error, 1, 0, "already set key %s to %s, cannot overwrite with %s", key, value_tmp, value);
 		ret = FALSE;
 		goto out;
 	}
diff --git a/backends/yum/libzif/zif-download.c b/backends/yum/libzif/zif-download.c
index 5572bcd..aaf089d 100644
--- a/backends/yum/libzif/zif-download.c
+++ b/backends/yum/libzif/zif-download.c
@@ -105,26 +105,22 @@ zif_download_file_finished_cb (SoupMessage *msg, ZifDownload *download)
 }
 
 /**
- * zif_download_cancel:
+ * zif_download_cancelled_cb:
  **/
-gboolean
-zif_download_cancel (ZifDownload *download, GError **error)
+static void
+zif_download_cancelled_cb (GCancellable *cancellable, ZifDownload *download)
 {
-	gboolean ret = FALSE;
-
-	g_return_val_if_fail (ZIF_IS_DOWNLOAD (download), FALSE);
+	g_return_if_fail (ZIF_IS_DOWNLOAD (download));
 
+	/* check we have a download */
 	if (download->priv->msg == NULL) {
-		if (error != NULL)
-			*error = g_error_new (1, 0, "no download in progress");
-		goto out;
+		egg_debug ("nothing to cancel");
+		return;
 	}
 
 	/* cancel */
+	egg_warning ("cancelling download");
 	soup_session_cancel_message (download->priv->session, download->priv->msg, SOUP_STATUS_CANCELLED);
-	ret = TRUE;
-out:
-	return ret;
 }
 
 /**
@@ -147,6 +143,7 @@ zif_download_file (ZifDownload *download, const gchar *uri, const gchar *filenam
 	SoupURI *base_uri;
 	SoupMessage *msg = NULL;
 	GError *error_local = NULL;
+	gulong cancellable_id = 0;
 
 	g_return_val_if_fail (ZIF_IS_DOWNLOAD (download), FALSE);
 	g_return_val_if_fail (uri != NULL, FALSE);
@@ -157,18 +154,22 @@ zif_download_file (ZifDownload *download, const gchar *uri, const gchar *filenam
 	/* save an instance of the completion object */
 	download->priv->completion = g_object_ref (completion);
 
+	/* set up cancel */
+	if (cancellable != NULL) {
+		g_cancellable_reset (cancellable);
+		cancellable_id = g_cancellable_connect (cancellable, G_CALLBACK (zif_download_cancelled_cb), download, NULL);
+	}
+
 	base_uri = soup_uri_new (uri);
 	if (base_uri == NULL) {
-		if (error != NULL)
-			*error = g_error_new (1, 0, "could not parse uri: %s", uri);
+		g_set_error (error, 1, 0, "could not parse uri: %s", uri);
 		goto out;
 	}
 
 	/* GET package */
 	msg = soup_message_new_from_uri (SOUP_METHOD_GET, base_uri);
 	if (msg == NULL) {
-		if (error != NULL)
-			*error = g_error_new (1, 0, "could not setup message");
+		g_set_error_literal (error, 1, 0, "could not setup message");
 		goto out;
 	}
 
@@ -187,20 +188,20 @@ zif_download_file (ZifDownload *download, const gchar *uri, const gchar *filenam
 
 	/* find length */
 	if (!SOUP_STATUS_IS_SUCCESSFUL (msg->status_code)) {
-		if (error != NULL)
-			*error = g_error_new (1, 0, "failed to get valid response for %s: %s", uri, soup_status_get_phrase (msg->status_code));
+		g_set_error (error, 1, 0, "failed to get valid response for %s: %s", uri, soup_status_get_phrase (msg->status_code));
 		goto out;
 	}
 
 	/* write file */
 	ret = g_file_set_contents (filename, msg->response_body->data, msg->response_body->length, &error_local);
 	if (!ret) {
-		if (error != NULL)
-			*error = g_error_new (1, 0, "failed to write file: %s",  error_local->message);
+		g_set_error (error, 1, 0, "failed to write file: %s",  error_local->message);
 		g_error_free (error_local);
 		goto out;
 	}
 out:
+	if (cancellable_id != 0)
+		g_cancellable_disconnect (cancellable, cancellable_id);
 	g_object_unref (download->priv->completion);
 	download->priv->completion = NULL;
 	if (base_uri != NULL)
@@ -233,8 +234,7 @@ zif_download_set_proxy (ZifDownload *download, const gchar *http_proxy, GError *
 								      SOUP_SESSION_TIMEOUT, connection_timeout,
 								      NULL);
 	if (download->priv->session == NULL) {
-		if (error != NULL)
-			*error = g_error_new (1, 0, "could not setup session");
+		g_set_error_literal (error, 1, 0, "could not setup session");
 		goto out;
 	}
 	ret = TRUE;
@@ -322,13 +322,10 @@ zif_download_progress_changed (ZifDownload *download, guint value, gpointer data
 }
 
 static gboolean
-zif_download_cancel_cb (ZifDownload *download)
+zif_download_cancel_cb (GCancellable *cancellable)
 {
-	gboolean ret;
-	GError *error = NULL;
-	ret = zif_download_cancel (download, &error);
-	if (!ret)
-		egg_error ("failed to cancel '%s'", error->message);
+	egg_debug ("sending cancel");
+	g_cancellable_cancel (cancellable);
 	return FALSE;
 }
 
@@ -337,6 +334,7 @@ zif_download_test (EggTest *test)
 {
 	ZifDownload *download;
 	ZifCompletion *completion;
+	GCancellable *cancellable;
 	gboolean ret;
 	GError *error = NULL;
 
@@ -346,6 +344,7 @@ zif_download_test (EggTest *test)
 	/************************************************************/
 	egg_test_title (test, "get download");
 	download = zif_download_new ();
+	cancellable = g_cancellable_new ();
 	egg_test_assert (test, download != NULL);
 
 	completion = zif_completion_new ();
@@ -358,12 +357,12 @@ zif_download_test (EggTest *test)
 
 	/************************************************************/
 	egg_test_title (test, "cancel not yet started download");
-	ret = zif_download_cancel (download, NULL);
-	egg_test_assert (test, !ret);
+	g_cancellable_cancel (cancellable);
+	egg_test_assert (test, TRUE);
 
 	/************************************************************/
 	egg_test_title (test, "download file");
-	ret = zif_download_file (download, "http://people.freedesktop.org/~hughsient/temp/Screenshot.png", "../test/downloads", NULL, completion, &error);
+	ret = zif_download_file (download, "http://people.freedesktop.org/~hughsient/temp/Screenshot.png", "../test/downloads", cancellable, completion, &error);
 	if (ret)
 		egg_test_success (test, NULL);
 	else
@@ -377,19 +376,20 @@ zif_download_test (EggTest *test)
 		egg_test_failed (test, "got %i updates", _updates);
 
 	/* setup cancel */
-	g_timeout_add (50, (GSourceFunc) zif_download_cancel_cb, download);
+	g_timeout_add (50, (GSourceFunc) zif_download_cancel_cb, cancellable);
 
 	/************************************************************/
 	egg_test_title (test, "download second file (should be cancelled)");
 	zif_completion_reset (completion);
-	ret = zif_download_file (download, "http://people.freedesktop.org/~hughsient/temp/Screenshot.png", "../test/downloads", NULL, completion, &error);
+	ret = zif_download_file (download, "http://people.freedesktop.org/~hughsient/temp/Screenshot.png", "../test/downloads", cancellable, completion, &error);
 	if (!ret)
 		egg_test_success (test, NULL);
 	else
-		egg_test_failed (test, "failed to load '%s'", error->message);
+		egg_test_failed (test, "failed to be cancelled");
 
 	g_object_unref (download);
 	g_object_unref (completion);
+	g_object_unref (cancellable);
 
 	egg_test_end (test);
 }
diff --git a/backends/yum/libzif/zif-download.h b/backends/yum/libzif/zif-download.h
index 191496c..939de98 100644
--- a/backends/yum/libzif/zif-download.h
+++ b/backends/yum/libzif/zif-download.h
@@ -64,8 +64,6 @@ gboolean	 zif_download_file			(ZifDownload		*download,
 							 GCancellable		*cancellable,
 							 ZifCompletion		*completion,
 							 GError			**error);
-gboolean	 zif_download_cancel			(ZifDownload		*download,
-							 GError			**error);
 
 G_END_DECLS
 
diff --git a/backends/yum/libzif/zif-groups.c b/backends/yum/libzif/zif-groups.c
index c0f444b..ad961f1 100644
--- a/backends/yum/libzif/zif-groups.c
+++ b/backends/yum/libzif/zif-groups.c
@@ -83,16 +83,14 @@ zif_groups_set_mapping_file (ZifGroups *groups, const gchar *mapping_file, GErro
 	/* check file exists */
 	ret = g_file_test (mapping_file, G_FILE_TEST_IS_REGULAR);
 	if (!ret) {
-		if (error != NULL)
-			*error = g_error_new (1, 0, "mapping file %s does not exist", mapping_file);
+		g_set_error (error, 1, 0, "mapping file %s does not exist", mapping_file);
 		goto out;
 	}
 
 	/* setup watch */
 	ret = zif_monitor_add_watch (groups->priv->monitor, mapping_file, &error_local);
 	if (!ret) {
-		if (error != NULL)
-			*error = g_error_new (1, 0, "failed to setup watch: %s", error_local->message);
+		g_set_error (error, 1, 0, "failed to setup watch: %s", error_local->message);
 		g_error_free (error_local);
 		goto out;
 	}
@@ -139,8 +137,7 @@ zif_groups_load (ZifGroups *groups, GError **error)
 	/* get data */
 	ret = g_file_get_contents (groups->priv->mapping_file, &data, NULL, &error_local);
 	if (!ret) {
-		if (error != NULL)
-			*error = g_error_new (1, 0, "failed to get groups data: %s", error_local->message);
+		g_set_error (error, 1, 0, "failed to get groups data: %s", error_local->message);
 		g_error_free (error_local);
 		goto out;
 	}
@@ -196,8 +193,7 @@ zif_groups_get_groups (ZifGroups *groups, GError **error)
 	if (!groups->priv->loaded) {
 		ret = zif_groups_load (groups, &error_local);
 		if (!ret) {
-			if (error != NULL)
-				*error = g_error_new (1, 0, "failed to load config file: %s", error_local->message);
+			g_set_error (error, 1, 0, "failed to load config file: %s", error_local->message);
 			g_error_free (error_local);
 			goto out;
 		}
@@ -229,8 +225,7 @@ zif_groups_get_categories (ZifGroups *groups, GError **error)
 	if (!groups->priv->loaded) {
 		ret = zif_groups_load (groups, &error_local);
 		if (!ret) {
-			if (error != NULL)
-				*error = g_error_new (1, 0, "failed to load config file: %s", error_local->message);
+			g_set_error (error, 1, 0, "failed to load config file: %s", error_local->message);
 			g_error_free (error_local);
 			goto out;
 		}
@@ -268,8 +263,7 @@ zif_groups_get_group_for_cat (ZifGroups *groups, const gchar *cat, GError **erro
 	if (!groups->priv->loaded) {
 		ret = zif_groups_load (groups, &error_local);
 		if (!ret) {
-			if (error != NULL)
-				*error = g_error_new (1, 0, "failed to load config file: %s", error_local->message);
+			g_set_error (error, 1, 0, "failed to load config file: %s", error_local->message);
 			g_error_free (error_local);
 			goto out;
 		}
diff --git a/backends/yum/libzif/zif-lock.c b/backends/yum/libzif/zif-lock.c
index afc3949..d3b5eeb 100644
--- a/backends/yum/libzif/zif-lock.c
+++ b/backends/yum/libzif/zif-lock.c
@@ -175,8 +175,7 @@ zif_lock_set_locked (ZifLock *lock, guint *pid, GError **error)
 	/* already locked */
 	ret = zif_lock_is_locked (lock, &pid_tmp);
 	if (ret) {
-		if (error != NULL)
-			*error = g_error_new (1, 0, "already locked by %i", pid_tmp);
+		g_set_error (error, 1, 0, "already locked by %i", pid_tmp);
 		if (pid != NULL)
 			*pid = pid_tmp;
 		ret = FALSE;
@@ -185,8 +184,7 @@ zif_lock_set_locked (ZifLock *lock, guint *pid, GError **error)
 
 	/* no lock file set */
 	if (lock->priv->filename == NULL) {
-		if (error != NULL)
-			*error = g_error_new (1, 0, "lock file not set");
+		g_set_error_literal (error, 1, 0, "lock file not set");
 		ret = FALSE;
 		goto out;
 	}
@@ -196,8 +194,7 @@ zif_lock_set_locked (ZifLock *lock, guint *pid, GError **error)
 	pid_text = g_strdup_printf ("%i", pid_tmp);
 	ret = g_file_set_contents (lock->priv->filename, pid_text, -1, &error_local);
 	if (!ret) {
-		if (error != NULL)
-			*error = g_error_new (1, 0, "failed to write: %s", error_local->message);
+		g_set_error (error, 1, 0, "failed to write: %s", error_local->message);
 		g_error_free (error_local);
 		goto out;
 	}
@@ -241,16 +238,14 @@ zif_lock_set_unlocked (ZifLock *lock, GError **error)
 	/* are we already locked */
 	ret = zif_lock_is_locked (lock, &pid);
 	if (!ret) {
-		if (error != NULL)
-			*error = g_error_new (1, 0, "not locked");
+		g_set_error_literal (error, 1, 0, "not locked");
 		goto out;
 	}
 
 	/* is it locked by somethine that isn't us? */
 	pid_tmp = getpid ();
 	if (pid != pid_tmp) {
-		if (error != NULL)
-			*error = g_error_new (1, 0, "locked by %i, cannot unlock", pid_tmp);
+		g_set_error (error, 1, 0, "locked by %i, cannot unlock", pid_tmp);
 		ret = FALSE;
 		goto out;
 	}
@@ -260,8 +255,7 @@ skip_checks:
 	/* remove file */
 	retval = g_unlink (lock->priv->filename);
 	if (retval != 0) {
-		if (error != NULL)
-			*error = g_error_new (1, 0, "cannot remove %s, cannot unlock", lock->priv->filename);
+		g_set_error (error, 1, 0, "cannot remove %s, cannot unlock", lock->priv->filename);
 		ret = FALSE;
 		goto out;
 	}
diff --git a/backends/yum/libzif/zif-monitor.c b/backends/yum/libzif/zif-monitor.c
index 3d34c75..33e510d 100644
--- a/backends/yum/libzif/zif-monitor.c
+++ b/backends/yum/libzif/zif-monitor.c
@@ -102,8 +102,7 @@ zif_monitor_add_watch (ZifMonitor *monitor, const gchar *filename, GError **erro
 	file = g_file_new_for_path (filename);
 	file_monitor = g_file_monitor (file, G_FILE_MONITOR_NONE, NULL, &error_local);
 	if (file_monitor == NULL) {
-		if (error != NULL)
-			*error = g_error_new (1, 0, "failed to add monitor: %s", error_local->message);
+		g_set_error (error, 1, 0, "failed to add monitor: %s", error_local->message);
 		g_error_free (error_local);
 		g_object_unref (file_monitor);
 		ret = FALSE;
diff --git a/backends/yum/libzif/zif-package-local.c b/backends/yum/libzif/zif-package-local.c
index 273cab1..5d57cde 100644
--- a/backends/yum/libzif/zif-package-local.c
+++ b/backends/yum/libzif/zif-package-local.c
@@ -517,13 +517,11 @@ zif_package_local_set_from_filename (ZifPackageLocal *pkg, const gchar *filename
 	/* open the file for reading */
 	fd = Fopen(filename, "r.fdio"); 
 	if (fd == NULL) {
-		if (error != NULL)
-			*error = g_error_new (1, 0, "failed to open %s", filename);
+		g_set_error (error, 1, 0, "failed to open %s", filename);
 		goto out;
 	}
 	if (Ferror(fd)) {
-		if (error != NULL)
-			*error = g_error_new (1, 0, "failed to open %s: %s", filename, Fstrerror(fd));
+		g_set_error (error, 1, 0, "failed to open %s: %s", filename, Fstrerror(fd));
 		goto out;
 	}
 
@@ -536,8 +534,7 @@ zif_package_local_set_from_filename (ZifPackageLocal *pkg, const gchar *filename
 	/* read in the file */
 	rc = rpmReadPackageFile (ts, fd, filename, &hdr);
 	if (rc != RPMRC_OK) {
-		if (error != NULL)
-			*error = g_error_new (1, 0, "failed to read %s: %s", filename, zif_package_local_rpmrc_to_string (rc));
+		g_set_error (error, 1, 0, "failed to read %s: %s", filename, zif_package_local_rpmrc_to_string (rc));
 		goto out;
 	}
 
@@ -547,8 +544,7 @@ zif_package_local_set_from_filename (ZifPackageLocal *pkg, const gchar *filename
 	/* set from header */
 	ret = zif_package_local_set_from_header (pkg, hdr, &error_local);
 	if (!ret) {
-		if (error != NULL)
-			*error = g_error_new (1, 0, "failed to set from header: %s", error_local->message);
+		g_set_error (error, 1, 0, "failed to set from header: %s", error_local->message);
 		g_error_free (error_local);
 		goto out;
 	}
@@ -556,8 +552,7 @@ zif_package_local_set_from_filename (ZifPackageLocal *pkg, const gchar *filename
 	/* close the database used by the transaction */
 	rc = rpmtsCloseDB (ts);
 	if (rc != RPMRC_OK) {
-		if (error != NULL)
-			*error = g_error_new (1, 0, "failed to close: %s", zif_package_local_rpmrc_to_string (rc));
+		g_set_error (error, 1, 0, "failed to close: %s", zif_package_local_rpmrc_to_string (rc));
 		ret = FALSE;
 		goto out;
 	}
diff --git a/backends/yum/libzif/zif-package.c b/backends/yum/libzif/zif-package.c
index c36ee3e..947dec7 100644
--- a/backends/yum/libzif/zif-package.c
+++ b/backends/yum/libzif/zif-package.c
@@ -130,8 +130,7 @@ zif_package_array_get_newest (GPtrArray *array, GError **error)
 
 	/* no results */
 	if (array->len == 0) {
-		if (error != NULL)
-			*error = g_error_new (1, 0, "nothing in array");
+		g_set_error_literal (error, 1, 0, "nothing in array");
 		goto out;
 	}
 
@@ -178,8 +177,7 @@ zif_package_download (ZifPackage *package, const gchar *directory, GCancellable
 
 	/* check we are not installed */
 	if (package->priv->installed) {
-		if (error != NULL)
-			*error = g_error_new (1, 0, "cannot download installed packages");
+		g_set_error_literal (error, 1, 0, "cannot download installed packages");
 		goto out;
 	}
 
@@ -190,8 +188,7 @@ zif_package_download (ZifPackage *package, const gchar *directory, GCancellable
 	completion_local = zif_completion_get_child (completion);
 	repo = zif_repos_get_store (package->priv->repos, package->priv->package_id_split[PK_PACKAGE_ID_DATA], cancellable, completion_local, &error_local);
 	if (repo == NULL) {
-		if (error != NULL)
-			*error = g_error_new (1, 0, "cannot find remote repo: %s", error_local->message);
+		g_set_error (error, 1, 0, "cannot find remote repo: %s", error_local->message);
 		g_error_free (error_local);
 		goto out;
 	}
@@ -205,8 +202,7 @@ zif_package_download (ZifPackage *package, const gchar *directory, GCancellable
 	/* download from the repo */
 	ret = zif_store_remote_download (repo, zif_string_get_value (package->priv->location_href), directory, cancellable, completion_local, &error_local);
 	if (!ret) {
-		if (error != NULL)
-			*error = g_error_new (1, 0, "cannot download from repo: %s", error_local->message);
+		g_set_error (error, 1, 0, "cannot download from repo: %s", error_local->message);
 		g_error_free (error_local);
 		goto out;
 	}
@@ -640,8 +636,7 @@ zif_package_get_filename (ZifPackage *package, GError **error)
 
 	/* not exists */
 	if (package->priv->location_href == NULL) {
-		if (error != NULL)
-			*error = g_error_new (1, 0, "no data for %s", package->priv->package_id_split[PK_PACKAGE_ID_NAME]);
+		g_set_error (error, 1, 0, "no data for %s", package->priv->package_id_split[PK_PACKAGE_ID_NAME]);
 		return NULL;
 	}
 
diff --git a/backends/yum/libzif/zif-repo-md-comps.c b/backends/yum/libzif/zif-repo-md-comps.c
index cac2ba6..b49cf57 100644
--- a/backends/yum/libzif/zif-repo-md-comps.c
+++ b/backends/yum/libzif/zif-repo-md-comps.c
@@ -450,8 +450,7 @@ zif_repo_md_comps_load (ZifRepoMd *md, GCancellable *cancellable, ZifCompletion
 	/* get filename */
 	filename = zif_repo_md_get_filename_uncompressed (md);
 	if (filename == NULL) {
-		if (error != NULL)
-			*error = g_error_new (1, 0, "failed to get filename for comps");
+		g_set_error_literal (error, 1, 0, "failed to get filename for comps");
 		goto out;
 	}
 
@@ -539,8 +538,7 @@ zif_repo_md_comps_get_categories (ZifRepoMdComps *md, GCancellable *cancellable,
 	if (!md->priv->loaded) {
 		ret = zif_repo_md_load (ZIF_REPO_MD (md), cancellable, completion, &error_local);
 		if (!ret) {
-			if (error != NULL)
-				*error = g_error_new (1, 0, "failed to get load comps: %s", error_local->message);
+			g_set_error (error, 1, 0, "failed to get load comps: %s", error_local->message);
 			g_error_free (error_local);
 			goto out;
 		}
@@ -621,8 +619,7 @@ zif_repo_md_comps_get_groups_for_category (ZifRepoMdComps *md, const gchar *cate
 	if (!md->priv->loaded) {
 		ret = zif_repo_md_load (ZIF_REPO_MD (md), cancellable, completion, &error_local);
 		if (!ret) {
-			if (error != NULL)
-				*error = g_error_new (1, 0, "failed to get load comps: %s", error_local->message);
+			g_set_error (error, 1, 0, "failed to get load comps: %s", error_local->message);
 			g_error_free (error_local);
 			goto out;
 		}
@@ -654,8 +651,7 @@ zif_repo_md_comps_get_groups_for_category (ZifRepoMdComps *md, const gchar *cate
 
 	/* nothing found */
 	if (array == NULL) {
-		if (error != NULL)
-			*error = g_error_new (1, 0, "could not find category: %s", category_id);
+		g_set_error (error, 1, 0, "could not find category: %s", category_id);
 	}
 out:
 	return array;
@@ -693,8 +689,7 @@ zif_repo_md_comps_get_packages_for_group (ZifRepoMdComps *md, const gchar *group
 	if (!md->priv->loaded) {
 		ret = zif_repo_md_load (ZIF_REPO_MD (md), cancellable, completion, &error_local);
 		if (!ret) {
-			if (error != NULL)
-				*error = g_error_new (1, 0, "failed to get load comps: %s", error_local->message);
+			g_set_error (error, 1, 0, "failed to get load comps: %s", error_local->message);
 			g_error_free (error_local);
 			goto out;
 		}
@@ -718,8 +713,7 @@ zif_repo_md_comps_get_packages_for_group (ZifRepoMdComps *md, const gchar *group
 
 	/* nothing found */
 	if (array == NULL) {
-		if (error != NULL)
-			*error = g_error_new (1, 0, "could not find group: %s", group_id);
+		g_set_error (error, 1, 0, "could not find group: %s", group_id);
 	}
 out:
 	return array;
diff --git a/backends/yum/libzif/zif-repo-md-filelists.c b/backends/yum/libzif/zif-repo-md-filelists.c
index d9202be..74c7f99 100644
--- a/backends/yum/libzif/zif-repo-md-filelists.c
+++ b/backends/yum/libzif/zif-repo-md-filelists.c
@@ -92,8 +92,7 @@ zif_repo_md_filelists_load (ZifRepoMd *md, GCancellable *cancellable, ZifComplet
 	/* get filename */
 	filename = zif_repo_md_get_filename_uncompressed (md);
 	if (filename == NULL) {
-		if (error != NULL)
-			*error = g_error_new (1, 0, "failed to get filename for filelists");
+		g_set_error_literal (error, 1, 0, "failed to get filename for filelists");
 		goto out;
 	}
 
@@ -102,8 +101,7 @@ zif_repo_md_filelists_load (ZifRepoMd *md, GCancellable *cancellable, ZifComplet
 	rc = sqlite3_open (filename, &filelists->priv->db);
 	if (rc != 0) {
 		egg_warning ("Can't open database: %s\n", sqlite3_errmsg (filelists->priv->db));
-		if (error != NULL)
-			*error = g_error_new (1, 0, "can't open database: %s", sqlite3_errmsg (filelists->priv->db));
+		g_set_error (error, 1, 0, "can't open database: %s", sqlite3_errmsg (filelists->priv->db));
 		goto out;
 	}
 
@@ -198,8 +196,7 @@ zif_repo_md_filelists_search_file (ZifRepoMdFilelists *md, const gchar *search,
 	if (!md->priv->loaded) {
 		ret = zif_repo_md_filelists_load (ZIF_REPO_MD (md), cancellable, completion, &error_local);
 		if (!ret) {
-			if (error != NULL)
-				*error = g_error_new (1, 0, "failed to load store file: %s", error_local->message);
+			g_set_error (error, 1, 0, "failed to load store file: %s", error_local->message);
 			g_error_free (error_local);
 			goto out;
 		}
@@ -220,8 +217,7 @@ zif_repo_md_filelists_search_file (ZifRepoMdFilelists *md, const gchar *search,
 	rc = sqlite3_exec (md->priv->db, statement, zif_repo_md_filelists_sqlite_get_files_cb, data, &error_msg);
 	g_free (statement);
 	if (rc != SQLITE_OK) {
-		if (error != NULL)
-			*error = g_error_new (1, 0, "SQL error (failed to get keys): %s\n", error_msg);
+		g_set_error (error, 1, 0, "SQL error (failed to get keys): %s\n", error_msg);
 		sqlite3_free (error_msg);
 		goto out;
 	}
@@ -238,16 +234,14 @@ zif_repo_md_filelists_search_file (ZifRepoMdFilelists *md, const gchar *search,
 		rc = sqlite3_exec (md->priv->db, statement, zif_repo_md_filelists_sqlite_get_id_cb, &pkgid, &error_msg);
 		g_free (statement);
 		if (rc != SQLITE_OK) {
-			if (error != NULL)
-				*error = g_error_new (1, 0, "SQL error (failed to get packages): %s", error_msg);
+			g_set_error (error, 1, 0, "SQL error (failed to get packages): %s", error_msg);
 			sqlite3_free (error_msg);
 			goto out;
 		}
 
 		/* we failed to get any results */
 		if (pkgid == NULL) {
-			if (error != NULL)
-				*error = g_error_new (1, 0, "failed to resolve pkgKey: %i", key);
+			g_set_error (error, 1, 0, "failed to resolve pkgKey: %i", key);
 			goto out;
 		}
 
diff --git a/backends/yum/libzif/zif-repo-md-metalink.c b/backends/yum/libzif/zif-repo-md-metalink.c
index 8f07a2e..a3704d0 100644
--- a/backends/yum/libzif/zif-repo-md-metalink.c
+++ b/backends/yum/libzif/zif-repo-md-metalink.c
@@ -212,8 +212,7 @@ zif_repo_md_metalink_load (ZifRepoMd *md, GCancellable *cancellable, ZifCompleti
 	/* get filename */
 	filename = zif_repo_md_get_filename_uncompressed (md);
 	if (filename == NULL) {
-		if (error != NULL)
-			*error = g_error_new (1, 0, "failed to get filename for metalink");
+		g_set_error_literal (error, 1, 0, "failed to get filename for metalink");
 		goto out;
 	}
 
@@ -271,8 +270,7 @@ zif_repo_md_metalink_get_uris (ZifRepoMdMetalink *md, guint threshold, GCancella
 	if (!metalink->priv->loaded) {
 		ret = zif_repo_md_load (ZIF_REPO_MD (md), cancellable, completion, &error_local);
 		if (!ret) {
-			if (error != NULL)
-				*error = g_error_new (1, 0, "failed to get mirrors from metalink: %s", error_local->message);
+			g_set_error (error, 1, 0, "failed to get mirrors from metalink: %s", error_local->message);
 			g_error_free (error_local);
 			goto out;
 		}
@@ -292,8 +290,7 @@ zif_repo_md_metalink_get_uris (ZifRepoMdMetalink *md, guint threshold, GCancella
 		if (data->preference >= threshold) {
 			uri = zif_config_expand_substitutions (md->priv->config, data->uri, &error_local);
 			if (uri == NULL) {
-				if (error != NULL)
-					*error = g_error_new (1, 0, "failed to expand substitutions: %s", error_local->message);
+				g_set_error (error, 1, 0, "failed to expand substitutions: %s", error_local->message);
 				g_error_free (error_local);
 				/* rip apart what we've done already */
 				g_ptr_array_unref (array);
diff --git a/backends/yum/libzif/zif-repo-md-mirrorlist.c b/backends/yum/libzif/zif-repo-md-mirrorlist.c
index 80384ec..4ddd2b0 100644
--- a/backends/yum/libzif/zif-repo-md-mirrorlist.c
+++ b/backends/yum/libzif/zif-repo-md-mirrorlist.c
@@ -89,8 +89,7 @@ zif_repo_md_mirrorlist_load (ZifRepoMd *md, GCancellable *cancellable, ZifComple
 	/* get filename */
 	filename = zif_repo_md_get_filename_uncompressed (md);
 	if (filename == NULL) {
-		if (error != NULL)
-			*error = g_error_new (1, 0, "failed to get filename for mirrorlist");
+		g_set_error_literal (error, 1, 0, "failed to get filename for mirrorlist");
 		goto out;
 	}
 
@@ -148,8 +147,7 @@ zif_repo_md_mirrorlist_get_uris (ZifRepoMdMirrorlist *md, GCancellable *cancella
 	if (!mirrorlist->priv->loaded) {
 		ret = zif_repo_md_load (ZIF_REPO_MD (md), cancellable, completion, &error_local);
 		if (!ret) {
-			if (error != NULL)
-				*error = g_error_new (1, 0, "failed to get uris from mirrorlist: %s", error_local->message);
+			g_set_error (error, 1, 0, "failed to get uris from mirrorlist: %s", error_local->message);
 			g_error_free (error_local);
 			goto out;
 		}
@@ -162,8 +160,7 @@ zif_repo_md_mirrorlist_get_uris (ZifRepoMdMirrorlist *md, GCancellable *cancella
 		data = g_ptr_array_index (mirrorlist->priv->array, i);
 		uri = zif_config_expand_substitutions (md->priv->config, data, &error_local);
 		if (uri == NULL) {
-			if (error != NULL)
-				*error = g_error_new (1, 0, "failed to expand substitutions: %s", error_local->message);
+			g_set_error (error, 1, 0, "failed to expand substitutions: %s", error_local->message);
 			g_error_free (error_local);
 			/* rip apart what we've done already */
 			g_ptr_array_unref (array);
diff --git a/backends/yum/libzif/zif-repo-md-primary.c b/backends/yum/libzif/zif-repo-md-primary.c
index 3bcf3cf..8d0346c 100644
--- a/backends/yum/libzif/zif-repo-md-primary.c
+++ b/backends/yum/libzif/zif-repo-md-primary.c
@@ -93,8 +93,7 @@ zif_repo_md_primary_load (ZifRepoMd *md, GCancellable *cancellable, ZifCompletio
 	/* get filename */
 	filename = zif_repo_md_get_filename_uncompressed (md);
 	if (filename == NULL) {
-		if (error != NULL)
-			*error = g_error_new (1, 0, "failed to get filename for primary");
+		g_set_error_literal (error, 1, 0, "failed to get filename for primary");
 		goto out;
 	}
 
@@ -103,8 +102,7 @@ zif_repo_md_primary_load (ZifRepoMd *md, GCancellable *cancellable, ZifCompletio
 	rc = sqlite3_open (filename, &primary->priv->db);
 	if (rc != 0) {
 		egg_warning ("Can't open database: %s\n", sqlite3_errmsg (primary->priv->db));
-		if (error != NULL)
-			*error = g_error_new (1, 0, "can't open database: %s", sqlite3_errmsg (primary->priv->db));
+		g_set_error (error, 1, 0, "can't open database: %s", sqlite3_errmsg (primary->priv->db));
 		goto out;
 	}
 
@@ -149,8 +147,7 @@ zif_repo_md_primary_search (ZifRepoMdPrimary *md, const gchar *pred, GCancellabl
 	if (!md->priv->loaded) {
 		ret = zif_repo_md_load (ZIF_REPO_MD (md), cancellable, completion, &error_local);
 		if (!ret) {
-			if (error != NULL)
-				*error = g_error_new (1, 0, "failed to load repo_md_primary file: %s", error_local->message);
+			g_set_error (error, 1, 0, "failed to load repo_md_primary file: %s", error_local->message);
 			g_error_free (error_local);
 			goto out;
 		}
@@ -166,8 +163,7 @@ zif_repo_md_primary_search (ZifRepoMdPrimary *md, const gchar *pred, GCancellabl
 				     "rpm_license, rpm_group, size_package, location_href FROM packages %s", pred);
 	rc = sqlite3_exec (md->priv->db, statement, zif_repo_md_primary_sqlite_create_package_cb, data, &error_msg);
 	if (rc != SQLITE_OK) {
-		if (error != NULL)
-			*error = g_error_new (1, 0, "SQL error: %s\n", error_msg);
+		g_set_error (error, 1, 0, "SQL error: %s\n", error_msg);
 		sqlite3_free (error_msg);
 		g_ptr_array_unref (data->packages);
 		goto out;
diff --git a/backends/yum/libzif/zif-repo-md.c b/backends/yum/libzif/zif-repo-md.c
index 58c3045..8288f4d 100644
--- a/backends/yum/libzif/zif-repo-md.c
+++ b/backends/yum/libzif/zif-repo-md.c
@@ -429,8 +429,7 @@ zif_repo_md_load (ZifRepoMd *md, GCancellable *cancellable, ZifCompletion *compl
 
 	/* no support */
 	if (klass->load == NULL) {
-		if (error != NULL)
-			*error = g_error_new (1, 0, "operation cannot be performed on this md");
+		g_set_error_literal (error, 1, 0, "operation cannot be performed on this md");
 		return FALSE;
 	}
 
@@ -462,8 +461,7 @@ zif_repo_md_load (ZifRepoMd *md, GCancellable *cancellable, ZifCompletion *compl
 		/* if not online, then this is fatal */
 		ret = zif_config_get_boolean (md->priv->config, "network", NULL);
 		if (!ret) {
-			if (error != NULL)
-				*error = g_error_new (1, 0, "failed to check %s checksum for %s and offline",
+			g_set_error (error, 1, 0, "failed to check %s checksum for %s and offline",
 						      zif_repo_md_type_to_text (md->priv->type), md->priv->id);
 			goto out;
 		}
@@ -471,16 +469,14 @@ zif_repo_md_load (ZifRepoMd *md, GCancellable *cancellable, ZifCompletion *compl
 		/* TODO: download file */
 		//ret = download (&error_local)
 		if (!ret) {
-			if (error != NULL)
-				*error = g_error_new (1, 0, "failed to download missing compressed file: %s", error_local->message);
+			g_set_error (error, 1, 0, "failed to download missing compressed file: %s", error_local->message);
 			goto out;
 		}
 
 		/* check newly downloaded compressed file */
 		ret = zif_repo_md_file_check (md, FALSE, &error_local);
 		if (!ret) {
-			if (error != NULL)
-				*error = g_error_new (1, 0, "failed checksum on downloaded file: %s", error_local->message);
+			g_set_error (error, 1, 0, "failed checksum on downloaded file: %s", error_local->message);
 			goto out;
 		}
 	}
@@ -500,16 +496,14 @@ zif_repo_md_load (ZifRepoMd *md, GCancellable *cancellable, ZifCompletion *compl
 		ret = zif_file_decompress (md->priv->filename, md->priv->filename_uncompressed,
 					   cancellable, completion_local, &error_local);
 		if (!ret) {
-			if (error != NULL)
-				*error = g_error_new (1, 0, "failed to decompress: %s", error_local->message);
+			g_set_error (error, 1, 0, "failed to decompress: %s", error_local->message);
 			goto out;
 		}
 
 		/* check newly uncompressed file */
 		ret = zif_repo_md_file_check (md, TRUE, &error_local);
 		if (!ret) {
-			if (error != NULL)
-				*error = g_error_new (1, 0, "failed checksum on decompressed file: %s", error_local->message);
+			g_set_error (error, 1, 0, "failed checksum on decompressed file: %s", error_local->message);
 			goto out;
 		}
 	}
@@ -549,8 +543,7 @@ zif_repo_md_unload (ZifRepoMd *md, GCancellable *cancellable, ZifCompletion *com
 
 	/* no support */
 	if (klass->unload == NULL) {
-		if (error != NULL)
-			*error = g_error_new (1, 0, "operation cannot be performed on this md");
+		g_set_error_literal (error, 1, 0, "operation cannot be performed on this md");
 		return FALSE;
 	}
 
@@ -580,8 +573,7 @@ zif_repo_md_clean (ZifRepoMd *md, GError **error)
 	/* get filename */
 	filename = zif_repo_md_get_filename (md);
 	if (filename == NULL) {
-		if (error != NULL)
-			*error = g_error_new (1, 0, "failed to get filename for %s", zif_repo_md_type_to_text (md->priv->type));
+		g_set_error (error, 1, 0, "failed to get filename for %s", zif_repo_md_type_to_text (md->priv->type));
 		ret = FALSE;
 		goto out;
 	}
@@ -593,8 +585,7 @@ zif_repo_md_clean (ZifRepoMd *md, GError **error)
 		ret = g_file_delete (file, NULL, &error_local);
 		g_object_unref (file);
 		if (!ret) {
-			if (error != NULL)
-				*error = g_error_new (1, 0, "failed to delete metadata file %s: %s", filename, error_local->message);
+			g_set_error (error, 1, 0, "failed to delete metadata file %s: %s", filename, error_local->message);
 			g_error_free (error_local);
 			goto out;
 		}
@@ -603,8 +594,7 @@ zif_repo_md_clean (ZifRepoMd *md, GError **error)
 	/* get filename */
 	filename = zif_repo_md_get_filename_uncompressed (md);
 	if (filename == NULL) {
-		if (error != NULL)
-			*error = g_error_new (1, 0, "failed to get uncompressed filename for %s", zif_repo_md_type_to_text (md->priv->type));
+		g_set_error (error, 1, 0, "failed to get uncompressed filename for %s", zif_repo_md_type_to_text (md->priv->type));
 		ret = FALSE;
 		goto out;
 	}
@@ -616,8 +606,7 @@ zif_repo_md_clean (ZifRepoMd *md, GError **error)
 		ret = g_file_delete (file, NULL, &error_local);
 		g_object_unref (file);
 		if (!ret) {
-			if (error != NULL)
-				*error = g_error_new (1, 0, "failed to delete metadata file %s: %s", filename, error_local->message);
+			g_set_error (error, 1, 0, "failed to delete metadata file %s: %s", filename, error_local->message);
 			g_error_free (error_local);
 			goto out;
 		}
@@ -703,8 +692,7 @@ zif_repo_md_file_check (ZifRepoMd *md, gboolean use_uncompressed, GError **error
 	/* get contents */
 	ret = g_file_get_contents (filename, &data, &length, &error_local);
 	if (!ret) {
-		if (error != NULL)
-			*error = g_error_new (1, 0, "failed to get contents of %s: %s", filename, error_local->message);
+		g_set_error (error, 1, 0, "failed to get contents of %s: %s", filename, error_local->message);
 		g_error_free (error_local);
 		goto out;
 	}
@@ -717,8 +705,7 @@ zif_repo_md_file_check (ZifRepoMd *md, gboolean use_uncompressed, GError **error
 
 	/* no checksum set */
 	if (checksum_wanted == NULL) {
-		if (error != NULL)
-			*error = g_error_new (1, 0, "checksum not set for %s", filename);
+		g_set_error (error, 1, 0, "checksum not set for %s", filename);
 		ret = FALSE;
 		goto out;
 	}
@@ -729,8 +716,7 @@ zif_repo_md_file_check (ZifRepoMd *md, gboolean use_uncompressed, GError **error
 	/* matches? */
 	ret = (g_strcmp0 (checksum, checksum_wanted) == 0);
 	if (!ret) {
-		if (error != NULL)
-			*error = g_error_new (1, 0, "checksum incorrect, wanted %s, got %s for %s", checksum_wanted, checksum, filename);
+		g_set_error (error, 1, 0, "checksum incorrect, wanted %s, got %s for %s", checksum_wanted, checksum, filename);
 		goto out;
 	}
 	egg_debug ("%s checksum correct (%s)", filename, checksum_wanted);
diff --git a/backends/yum/libzif/zif-repos.c b/backends/yum/libzif/zif-repos.c
index dfc5605..b74313e 100644
--- a/backends/yum/libzif/zif-repos.c
+++ b/backends/yum/libzif/zif-repos.c
@@ -82,16 +82,14 @@ zif_repos_set_repos_dir (ZifRepos *repos, const gchar *repos_dir, GError **error
 	/* check directory exists */
 	ret = g_file_test (repos_dir, G_FILE_TEST_IS_DIR);
 	if (!ret) {
-		if (error != NULL)
-			*error = g_error_new (1, 0, "repo directory %s does not exist", repos_dir);
+		g_set_error (error, 1, 0, "repo directory %s does not exist", repos_dir);
 		goto out;
 	}
 
 	/* setup watch */
 	ret = zif_monitor_add_watch (repos->priv->monitor, repos_dir, &error_local);
 	if (!ret) {
-		if (error != NULL)
-			*error = g_error_new (1, 0, "failed to setup watch: %s", error_local->message);
+		g_set_error (error, 1, 0, "failed to setup watch: %s", error_local->message);
 		g_error_free (error_local);
 		goto out;
 	}
@@ -121,8 +119,7 @@ zif_repos_get_for_filename (ZifRepos *repos, const gchar *filename, GCancellable
 	path = g_build_filename (repos->priv->repos_dir, filename, NULL);
 	ret = g_key_file_load_from_file (file, path, G_KEY_FILE_NONE, &error_local);
 	if (!ret) {
-		if (error != NULL)
-			*error = g_error_new (1, 0, "failed to load %s: %s", path, error_local->message);
+		g_set_error (error, 1, 0, "failed to load %s: %s", path, error_local->message);
 		g_error_free (error_local);
 		goto out;
 	}
@@ -139,8 +136,7 @@ zif_repos_get_for_filename (ZifRepos *repos, const gchar *filename, GCancellable
 		completion_local = zif_completion_get_child (completion);
 		ret = zif_store_remote_set_from_file (store, path, repos_groups[i], cancellable, completion_local, &error_local);
 		if (!ret) {
-			if (error != NULL)
-				*error = g_error_new (1, 0, "failed to set from %s: %s", path, error_local->message);
+			g_set_error (error, 1, 0, "failed to set from %s: %s", path, error_local->message);
 			g_error_free (error_local);
 			break;
 		}
@@ -189,8 +185,7 @@ zif_repos_load (ZifRepos *repos, GCancellable *cancellable, ZifCompletion *compl
 	/* search repos dir */
 	dir = g_dir_open (repos->priv->repos_dir, 0, &error_local);
 	if (dir == NULL) {
-		if (error != NULL)
-			*error = g_error_new (1, 0, "failed to list directory: %s", error_local->message);
+		g_set_error (error, 1, 0, "failed to list directory: %s", error_local->message);
 		g_error_free (error_local);
 		ret = FALSE;
 		goto out;
@@ -216,8 +211,7 @@ zif_repos_load (ZifRepos *repos, GCancellable *cancellable, ZifCompletion *compl
 		filename = g_ptr_array_index (repofiles, i);
 		ret = zif_monitor_add_watch (repos->priv->monitor, filename, &error_local);
 		if (!ret) {
-			if (error != NULL)
-				*error = g_error_new (1, 0, "failed to setup watch: %s", error_local->message);
+			g_set_error (error, 1, 0, "failed to setup watch: %s", error_local->message);
 			g_error_free (error_local);
 			break;
 		}
@@ -226,8 +220,7 @@ zif_repos_load (ZifRepos *repos, GCancellable *cancellable, ZifCompletion *compl
 		completion_local = zif_completion_get_child (completion);
 		ret = zif_repos_get_for_filename (repos, filename, cancellable, completion_local, &error_local);
 		if (!ret) {
-			if (error != NULL)
-				*error = g_error_new (1, 0, "failed to get filename %s: %s", filename, error_local->message);
+			g_set_error (error, 1, 0, "failed to get filename %s: %s", filename, error_local->message);
 			g_error_free (error_local);
 			g_ptr_array_set_size (repos->priv->list, 0);
 			ret = FALSE;
@@ -250,8 +243,7 @@ zif_repos_load (ZifRepos *repos, GCancellable *cancellable, ZifCompletion *compl
 		completion_local = zif_completion_get_child (completion);
 		ret = zif_store_remote_get_enabled (store, cancellable, completion_local, &error_local);
 		if (error_local != NULL) {
-			if (error != NULL)
-				*error = g_error_new (1, 0, "failed to get repo state for %s: %s", zif_store_get_id (ZIF_STORE (store)), error_local->message);
+			g_set_error (error, 1, 0, "failed to get repo state for %s: %s", zif_store_get_id (ZIF_STORE (store)), error_local->message);
 			g_ptr_array_set_size (repos->priv->enabled, 0);
 			ret = FALSE;
 			goto out;
@@ -299,8 +291,7 @@ zif_repos_get_stores (ZifRepos *repos, GCancellable *cancellable, ZifCompletion
 	if (!repos->priv->loaded) {
 		ret = zif_repos_load (repos, cancellable, completion, &error_local);
 		if (!ret) {
-			if (error != NULL)
-				*error = g_error_new (1, 0, "failed to load repos: %s", error_local->message);
+			g_set_error (error, 1, 0, "failed to load repos: %s", error_local->message);
 			g_error_free (error_local);
 			goto out;
 		}
@@ -338,8 +329,7 @@ zif_repos_get_stores_enabled (ZifRepos *repos, GCancellable *cancellable, ZifCom
 	if (!repos->priv->loaded) {
 		ret = zif_repos_load (repos, cancellable, completion, &error_local);
 		if (!ret) {
-			if (error != NULL)
-				*error = g_error_new (1, 0, "failed to load enabled repos: %s", error_local->message);
+			g_set_error (error, 1, 0, "failed to load enabled repos: %s", error_local->message);
 			g_error_free (error_local);
 			goto out;
 		}
@@ -384,8 +374,7 @@ zif_repos_get_store (ZifRepos *repos, const gchar *id, GCancellable *cancellable
 	if (!repos->priv->loaded) {
 		ret = zif_repos_load (repos, cancellable, completion, &error_local);
 		if (!ret) {
-			if (error != NULL)
-				*error = g_error_new (1, 0, "failed to load repos: %s", error_local->message);
+			g_set_error (error, 1, 0, "failed to load repos: %s", error_local->message);
 			g_error_free (error_local);
 			goto out;
 		}
@@ -398,8 +387,7 @@ zif_repos_get_store (ZifRepos *repos, const gchar *id, GCancellable *cancellable
 		/* get the id */
 		id_tmp = zif_store_get_id (ZIF_STORE (store_tmp));
 		if (id_tmp == NULL) {
-			if (error != NULL)
-				*error = g_error_new (1, 0, "failed to get id");
+			g_set_error_literal (error, 1, 0, "failed to get id");
 			goto out;
 		}
 
diff --git a/backends/yum/libzif/zif-sack.c b/backends/yum/libzif/zif-sack.c
index 53a5c23..1df6f1e 100644
--- a/backends/yum/libzif/zif-sack.c
+++ b/backends/yum/libzif/zif-sack.c
@@ -155,8 +155,7 @@ zif_sack_add_remote (ZifSack *sack, GCancellable *cancellable, ZifCompletion *co
 	repos = zif_repos_new ();
 	array = zif_repos_get_stores (repos, cancellable, completion, &error_local);
 	if (array == NULL) {
-		if (error != NULL)
-			*error = g_error_new (1, 0, "failed to get enabled stores: %s", error_local->message);
+		g_set_error (error, 1, 0, "failed to get enabled stores: %s", error_local->message);
 		g_error_free (error_local);
 		ret = FALSE;
 		goto out;
@@ -197,8 +196,7 @@ zif_sack_add_remote_enabled (ZifSack *sack, GCancellable *cancellable, ZifComple
 	repos = zif_repos_new ();
 	array = zif_repos_get_stores_enabled (repos, cancellable, completion, &error_local);
 	if (array == NULL) {
-		if (error != NULL)
-			*error = g_error_new (1, 0, "failed to get enabled stores: %s", error_local->message);
+		g_set_error (error, 1, 0, "failed to get enabled stores: %s", error_local->message);
 		g_error_free (error_local);
 		ret = FALSE;
 		goto out;
@@ -235,8 +233,7 @@ zif_sack_repos_search (ZifSack *sack, PkRoleEnum role, const gchar *search, GCan
 	/* nothing to do */
 	if (stores->len == 0) {
 		egg_warning ("nothing to do");
-		if (error != NULL)
-			*error = g_error_new (1, 0, "nothing to do as no stores in sack");
+		g_set_error (error, 1, 0, "nothing to do as no stores in sack");
 		goto out;
 	}
 
@@ -275,8 +272,7 @@ zif_sack_repos_search (ZifSack *sack, PkRoleEnum role, const gchar *search, GCan
 		else
 			egg_error ("internal error: %s", pk_role_enum_to_text (role));
 		if (part == NULL) {
-			if (error != NULL)
-				*error = g_error_new (1, 0, "failed to %s in %s: %s", pk_role_enum_to_text (role), zif_store_get_id (store), error_local->message);
+			g_set_error (error, 1, 0, "failed to %s in %s: %s", pk_role_enum_to_text (role), zif_store_get_id (store), error_local->message);
 			g_error_free (error_local);
 			g_ptr_array_unref (array);
 			array = NULL;
@@ -390,8 +386,7 @@ zif_sack_clean (ZifSack *sack, GCancellable *cancellable, ZifCompletion *complet
 		completion_local = zif_completion_get_child (completion);
 		ret = zif_store_clean (store, cancellable, completion_local, &error_local);
 		if (!ret) {
-			if (error != NULL)
-				*error = g_error_new (1, 0, "failed to clean %s: %s", zif_store_get_id (store), error_local->message);
+			g_set_error (error, 1, 0, "failed to clean %s: %s", zif_store_get_id (store), error_local->message);
 			g_error_free (error_local);
 			goto out;
 		}
@@ -449,10 +444,6 @@ zif_sack_refresh (ZifSack *sack, gboolean force, GCancellable *cancellable, ZifC
 		completion_local = zif_completion_get_child (completion);
 		ret = zif_store_refresh (store, force, cancellable, completion_local, &error_local);
 		if (!ret) {
-			//if (error != NULL)
-			//	*error = g_error_new (1, 0, "failed to refresh %s: %s", zif_store_get_id (store), error_local->message);
-			//g_error_free (error_local);
-			//goto out;
 			/* non-fatal */
 			g_print ("failed to refresh %s: %s\n", zif_store_get_id (store), error_local->message);
 			g_clear_error (&error_local);
diff --git a/backends/yum/libzif/zif-store-local.c b/backends/yum/libzif/zif-store-local.c
index f9f7f51..4c3a5b2 100644
--- a/backends/yum/libzif/zif-store-local.c
+++ b/backends/yum/libzif/zif-store-local.c
@@ -92,8 +92,7 @@ zif_store_local_set_prefix (ZifStoreLocal *store, const gchar *prefix, GError **
 	/* check file exists */
 	ret = g_file_test (prefix, G_FILE_TEST_IS_DIR);
 	if (!ret) {
-		if (error != NULL)
-			*error = g_error_new (1, 0, "prefix %s does not exist", prefix);
+		g_set_error (error, 1, 0, "prefix %s does not exist", prefix);
 		goto out;
 	}
 
@@ -101,8 +100,7 @@ zif_store_local_set_prefix (ZifStoreLocal *store, const gchar *prefix, GError **
 	filename = g_build_filename (prefix, "var", "lib", "rpm", "Packages", NULL);
 	ret = zif_monitor_add_watch (store->priv->monitor, filename, &error_local);
 	if (!ret) {
-		if (error != NULL)
-			*error = g_error_new (1, 0, "failed to setup watch: %s", error_local->message);
+		g_set_error (error, 1, 0, "failed to setup watch: %s", error_local->message);
 		g_error_free (error_local);
 		goto out;
 	}
@@ -136,8 +134,7 @@ zif_store_local_load (ZifStore *store, GCancellable *cancellable, ZifCompletion
 	ret = zif_lock_is_locked (local->priv->lock, NULL);
 	if (!ret) {
 		egg_warning ("not locked");
-		if (error != NULL)
-			*error = g_error_new (1, 0, "not locked");
+		g_set_error_literal (error, 1, 0, "not locked");
 		goto out;
 	}
 
@@ -150,8 +147,7 @@ zif_store_local_load (ZifStore *store, GCancellable *cancellable, ZifCompletion
 
 	retval = rpmdbOpen (local->priv->prefix, &db, O_RDONLY, 0777);
 	if (retval != 0) {
-		if (error != NULL)
-			*error = g_error_new (1, 0, "failed to open rpmdb");
+		g_set_error_literal (error, 1, 0, "failed to open rpmdb");
 		ret = FALSE;
 		goto out;
 	}
@@ -170,8 +166,7 @@ zif_store_local_load (ZifStore *store, GCancellable *cancellable, ZifCompletion
 		package = zif_package_local_new ();
 		ret = zif_package_local_set_from_header (package, header, &error_local);
 		if (!ret) {
-			if (error != NULL)
-				*error = g_error_new (1, 0, "failed to set from header: %s", error_local->message);
+			g_set_error (error, 1, 0, "failed to set from header: %s", error_local->message);
 			g_error_free (error_local);
 			g_object_unref (package);
 			break;
@@ -214,8 +209,7 @@ zif_store_local_search_name (ZifStore *store, const gchar *search, GCancellable
 	ret = zif_lock_is_locked (local->priv->lock, NULL);
 	if (!ret) {
 		egg_warning ("not locked");
-		if (error != NULL)
-			*error = g_error_new (1, 0, "not locked");
+		g_set_error_literal (error, 1, 0, "not locked");
 		goto out;
 	}
 
@@ -230,8 +224,7 @@ zif_store_local_search_name (ZifStore *store, const gchar *search, GCancellable
 		completion_local = zif_completion_get_child (completion);
 		ret = zif_store_local_load (store, cancellable, completion_local, &error_local);
 		if (!ret) {
-			if (error != NULL)
-				*error = g_error_new (1, 0, "failed to load package store: %s", error_local->message);
+			g_set_error (error, 1, 0, "failed to load package store: %s", error_local->message);
 			g_error_free (error_local);
 			goto out;
 		}
@@ -243,8 +236,7 @@ zif_store_local_search_name (ZifStore *store, const gchar *search, GCancellable
 	/* check we have packages */
 	if (local->priv->packages->len == 0) {
 		egg_warning ("no packages in sack, so nothing to do!");
-		if (error != NULL)
-			*error = g_error_new (1, 0, "no packages in local sack");
+		g_set_error_literal (error, 1, 0, "no packages in local sack");
 		goto out;
 	}
 
@@ -295,8 +287,7 @@ zif_store_local_search_category (ZifStore *store, const gchar *search, GCancella
 	ret = zif_lock_is_locked (local->priv->lock, NULL);
 	if (!ret) {
 		egg_warning ("not locked");
-		if (error != NULL)
-			*error = g_error_new (1, 0, "not locked");
+		g_set_error_literal (error, 1, 0, "not locked");
 		goto out;
 	}
 
@@ -311,8 +302,7 @@ zif_store_local_search_category (ZifStore *store, const gchar *search, GCancella
 		completion_local = zif_completion_get_child (completion);
 		ret = zif_store_local_load (store, cancellable, completion_local, &error_local);
 		if (!ret) {
-			if (error != NULL)
-				*error = g_error_new (1, 0, "failed to load package store: %s", error_local->message);
+			g_set_error (error, 1, 0, "failed to load package store: %s", error_local->message);
 			g_error_free (error_local);
 			goto out;
 		}
@@ -324,8 +314,7 @@ zif_store_local_search_category (ZifStore *store, const gchar *search, GCancella
 	/* check we have packages */
 	if (local->priv->packages->len == 0) {
 		egg_warning ("no packages in sack, so nothing to do!");
-		if (error != NULL)
-			*error = g_error_new (1, 0, "no packages in local sack");
+		g_set_error_literal (error, 1, 0, "no packages in local sack");
 		goto out;
 	}
 
@@ -377,8 +366,7 @@ zif_store_local_search_details (ZifStore *store, const gchar *search, GCancellab
 	ret = zif_lock_is_locked (local->priv->lock, NULL);
 	if (!ret) {
 		egg_warning ("not locked");
-		if (error != NULL)
-			*error = g_error_new (1, 0, "not locked");
+		g_set_error_literal (error, 1, 0, "not locked");
 		goto out;
 	}
 
@@ -393,8 +381,7 @@ zif_store_local_search_details (ZifStore *store, const gchar *search, GCancellab
 		completion_local = zif_completion_get_child (completion);
 		ret = zif_store_local_load (store, cancellable, completion_local, &error_local);
 		if (!ret) {
-			if (error != NULL)
-				*error = g_error_new (1, 0, "failed to load package store: %s", error_local->message);
+			g_set_error (error, 1, 0, "failed to load package store: %s", error_local->message);
 			g_error_free (error_local);
 			goto out;
 		}
@@ -406,8 +393,7 @@ zif_store_local_search_details (ZifStore *store, const gchar *search, GCancellab
 	/* check we have packages */
 	if (local->priv->packages->len == 0) {
 		egg_warning ("no packages in sack, so nothing to do!");
-		if (error != NULL)
-			*error = g_error_new (1, 0, "no packages in local sack");
+		g_set_error_literal (error, 1, 0, "no packages in local sack");
 		goto out;
 	}
 
@@ -462,8 +448,7 @@ zif_store_local_search_group (ZifStore *store, const gchar *search, GCancellable
 	ret = zif_lock_is_locked (local->priv->lock, NULL);
 	if (!ret) {
 		egg_warning ("not locked");
-		if (error != NULL)
-			*error = g_error_new (1, 0, "not locked");
+		g_set_error_literal (error, 1, 0, "not locked");
 		goto out;
 	}
 
@@ -478,8 +463,7 @@ zif_store_local_search_group (ZifStore *store, const gchar *search, GCancellable
 		completion_local = zif_completion_get_child (completion);
 		ret = zif_store_local_load (store, cancellable, completion_local, &error_local);
 		if (!ret) {
-			if (error != NULL)
-				*error = g_error_new (1, 0, "failed to load package store: %s", error_local->message);
+			g_set_error (error, 1, 0, "failed to load package store: %s", error_local->message);
 			g_error_free (error_local);
 			goto out;
 		}
@@ -491,8 +475,7 @@ zif_store_local_search_group (ZifStore *store, const gchar *search, GCancellable
 	/* check we have packages */
 	if (local->priv->packages->len == 0) {
 		egg_warning ("no packages in sack, so nothing to do!");
-		if (error != NULL)
-			*error = g_error_new (1, 0, "no packages in local sack");
+		g_set_error_literal (error, 1, 0, "no packages in local sack");
 		goto out;
 	}
 
@@ -542,8 +525,7 @@ zif_store_local_search_file (ZifStore *store, const gchar *search, GCancellable
 	ret = zif_lock_is_locked (local->priv->lock, NULL);
 	if (!ret) {
 		egg_warning ("not locked");
-		if (error != NULL)
-			*error = g_error_new (1, 0, "not locked");
+		g_set_error_literal (error, 1, 0, "not locked");
 		goto out;
 	}
 
@@ -558,8 +540,7 @@ zif_store_local_search_file (ZifStore *store, const gchar *search, GCancellable
 		completion_local = zif_completion_get_child (completion);
 		ret = zif_store_local_load (store, cancellable, completion_local, &error_local);
 		if (!ret) {
-			if (error != NULL)
-				*error = g_error_new (1, 0, "failed to load package store: %s", error_local->message);
+			g_set_error (error, 1, 0, "failed to load package store: %s", error_local->message);
 			g_error_free (error_local);
 			goto out;
 		}
@@ -571,8 +552,7 @@ zif_store_local_search_file (ZifStore *store, const gchar *search, GCancellable
 	/* check we have packages */
 	if (local->priv->packages->len == 0) {
 		egg_warning ("no packages in sack, so nothing to do!");
-		if (error != NULL)
-			*error = g_error_new (1, 0, "no packages in local sack");
+		g_set_error_literal (error, 1, 0, "no packages in local sack");
 		goto out;
 	}
 
@@ -586,8 +566,7 @@ zif_store_local_search_file (ZifStore *store, const gchar *search, GCancellable
 		package = g_ptr_array_index (local->priv->packages, i);
 		files = zif_package_get_files (package, &error_local);
 		if (files == NULL) {
-			if (error != NULL)
-				*error = g_error_new (1, 0, "failed to get file lists: %s", error_local->message);
+			g_set_error (error, 1, 0, "failed to get file lists: %s", error_local->message);
 			g_error_free (error_local);
 			g_ptr_array_unref (array);
 			array = NULL;
@@ -631,8 +610,7 @@ zif_store_local_resolve (ZifStore *store, const gchar *search, GCancellable *can
 	ret = zif_lock_is_locked (local->priv->lock, NULL);
 	if (!ret) {
 		egg_warning ("not locked");
-		if (error != NULL)
-			*error = g_error_new (1, 0, "not locked");
+		g_set_error_literal (error, 1, 0, "not locked");
 		goto out;
 	}
 
@@ -647,8 +625,7 @@ zif_store_local_resolve (ZifStore *store, const gchar *search, GCancellable *can
 		completion_local = zif_completion_get_child (completion);
 		ret = zif_store_local_load (store, cancellable, completion_local, &error_local);
 		if (!ret) {
-			if (error != NULL)
-				*error = g_error_new (1, 0, "failed to load package store: %s", error_local->message);
+			g_set_error (error, 1, 0, "failed to load package store: %s", error_local->message);
 			g_error_free (error_local);
 			goto out;
 		}
@@ -660,8 +637,7 @@ zif_store_local_resolve (ZifStore *store, const gchar *search, GCancellable *can
 	/* check we have packages */
 	if (local->priv->packages->len == 0) {
 		egg_warning ("no packages in sack, so nothing to do!");
-		if (error != NULL)
-			*error = g_error_new (1, 0, "no packages in local sack");
+		g_set_error_literal (error, 1, 0, "no packages in local sack");
 		goto out;
 	}
 
@@ -714,8 +690,7 @@ zif_store_local_what_provides (ZifStore *store, const gchar *search, GCancellabl
 	ret = zif_lock_is_locked (local->priv->lock, NULL);
 	if (!ret) {
 		egg_warning ("not locked");
-		if (error != NULL)
-			*error = g_error_new (1, 0, "not locked");
+		g_set_error_literal (error, 1, 0, "not locked");
 		goto out;
 	}
 
@@ -730,8 +705,7 @@ zif_store_local_what_provides (ZifStore *store, const gchar *search, GCancellabl
 		completion_local = zif_completion_get_child (completion);
 		ret = zif_store_local_load (store, cancellable, completion_local, &error_local);
 		if (!ret) {
-			if (error != NULL)
-				*error = g_error_new (1, 0, "failed to load package store: %s", error_local->message);
+			g_set_error (error, 1, 0, "failed to load package store: %s", error_local->message);
 			g_error_free (error_local);
 			goto out;
 		}
@@ -743,8 +717,7 @@ zif_store_local_what_provides (ZifStore *store, const gchar *search, GCancellabl
 	/* check we have packages */
 	if (local->priv->packages->len == 0) {
 		egg_warning ("no packages in sack, so nothing to do!");
-		if (error != NULL)
-			*error = g_error_new (1, 0, "no packages in local sack");
+		g_set_error_literal (error, 1, 0, "no packages in local sack");
 		goto out;
 	}
 
@@ -796,8 +769,7 @@ zif_store_local_get_packages (ZifStore *store, GCancellable *cancellable, ZifCom
 	ret = zif_lock_is_locked (local->priv->lock, NULL);
 	if (!ret) {
 		egg_warning ("not locked");
-		if (error != NULL)
-			*error = g_error_new (1, 0, "not locked");
+		g_set_error_literal (error, 1, 0, "not locked");
 		goto out;
 	}
 
@@ -812,8 +784,7 @@ zif_store_local_get_packages (ZifStore *store, GCancellable *cancellable, ZifCom
 		completion_local = zif_completion_get_child (completion);
 		ret = zif_store_local_load (store, cancellable, completion_local, &error_local);
 		if (!ret) {
-			if (error != NULL)
-				*error = g_error_new (1, 0, "failed to load package store: %s", error_local->message);
+			g_set_error (error, 1, 0, "failed to load package store: %s", error_local->message);
 			g_error_free (error_local);
 			goto out;
 		}
@@ -825,8 +796,7 @@ zif_store_local_get_packages (ZifStore *store, GCancellable *cancellable, ZifCom
 	/* check we have packages */
 	if (local->priv->packages->len == 0) {
 		egg_warning ("no packages in sack, so nothing to do!");
-		if (error != NULL)
-			*error = g_error_new (1, 0, "no packages in local sack");
+		g_set_error_literal (error, 1, 0, "no packages in local sack");
 		goto out;
 	}
 
@@ -873,8 +843,7 @@ zif_store_local_find_package (ZifStore *store, const gchar *package_id, GCancell
 	ret = zif_lock_is_locked (local->priv->lock, NULL);
 	if (!ret) {
 		egg_warning ("not locked");
-		if (error != NULL)
-			*error = g_error_new (1, 0, "not locked");
+		g_set_error_literal (error, 1, 0, "not locked");
 		goto out;
 	}
 
@@ -889,8 +858,7 @@ zif_store_local_find_package (ZifStore *store, const gchar *package_id, GCancell
 		completion_local = zif_completion_get_child (completion);
 		ret = zif_store_local_load (store, cancellable, completion_local, &error_local);
 		if (!ret) {
-			if (error != NULL)
-				*error = g_error_new (1, 0, "failed to load package store: %s", error_local->message);
+			g_set_error (error, 1, 0, "failed to load package store: %s", error_local->message);
 			g_error_free (error_local);
 			goto out;
 		}
@@ -902,8 +870,7 @@ zif_store_local_find_package (ZifStore *store, const gchar *package_id, GCancell
 	/* check we have packages */
 	if (local->priv->packages->len == 0) {
 		egg_warning ("no packages in sack, so nothing to do!");
-		if (error != NULL)
-			*error = g_error_new (1, 0, "no packages in local sack");
+		g_set_error_literal (error, 1, 0, "no packages in local sack");
 		goto out;
 	}
 
@@ -925,15 +892,13 @@ zif_store_local_find_package (ZifStore *store, const gchar *package_id, GCancell
 
 	/* nothing */
 	if (array->len == 0) {
-		if (error != NULL)
-			*error = g_error_new (1, 0, "failed to find package");
+		g_set_error_literal (error, 1, 0, "failed to find package");
 		goto out;
 	}
 
 	/* more than one match */
 	if (array->len > 1) {
-		if (error != NULL)
-			*error = g_error_new (1, 0, "more than one match");
+		g_set_error_literal (error, 1, 0, "more than one match");
 		goto out;
 	}
 
diff --git a/backends/yum/libzif/zif-store-remote.c b/backends/yum/libzif/zif-store-remote.c
index 1278cb5..265d456 100644
--- a/backends/yum/libzif/zif-store-remote.c
+++ b/backends/yum/libzif/zif-store-remote.c
@@ -191,7 +191,7 @@ zif_store_remote_parser_start_element (GMarkupParseContext *context, const gchar
 						g_string_set_size (string, string->len - 2);
 
 						/* return error */
-						*error = g_error_new (1, 0, "%s", string->str);
+						g_set_error (error, 1, 0, "%s", string->str);
 						g_string_free (string, TRUE);
 					}
 				}
@@ -302,18 +302,43 @@ zif_store_remote_download_try (ZifStoreRemote *store, const gchar *uri, const gc
 	gboolean ret = FALSE;
 	GError *error_local = NULL;
 	ZifDownload *download = NULL;
+	gchar *contents = NULL;
+	gsize length;
 
 	/* download object */
 	download = zif_download_new ();
 	egg_debug ("trying to download %s", uri);
 	ret = zif_download_file (download, uri, filename, cancellable, completion, &error_local);
 	if (!ret) {
-		if (error != NULL)
-			*error = g_error_new (1, 0, "failed to download %s from %s: %s", filename, uri, error_local->message);
+		g_set_error (error, 1, 0, "failed to download %s from %s: %s", filename, uri, error_local->message);
+		g_error_free (error_local);
+		goto out;
+	}
+
+	/* try to read it */
+	ret = g_file_get_contents (filename, &contents, &length, &error_local);
+	if (!ret) {
+		g_set_error (error, 1, 0, "failed to download %s from %s: %s (unable to read file)", filename, uri, error_local->message);
 		g_error_free (error_local);
 		goto out;
 	}
+
+	/* check we have some data */
+	if (length == 0) {
+		g_set_error (error, 1, 0, "failed to download %s from %s: no data", filename, uri);
+		ret = FALSE;
+		goto out;
+	}
+
+	/* check this really isn't a fancy 404 page */
+	if (g_str_has_prefix (contents, "<html>")) {
+		g_set_error (error, 1, 0, "failed to download %s from %s: invalid file", filename, uri);
+		ret = FALSE;
+		goto out;
+	}
+
 out:
+	g_free (contents);
 	g_object_unref (download);
 	return ret;
 }
@@ -356,8 +381,7 @@ zif_store_remote_download (ZifStoreRemote *store, const gchar *filename, const g
 	/* if not online, then this is fatal */
 	ret = zif_config_get_boolean (store->priv->config, "network", NULL);
 	if (!ret) {
-		if (error != NULL)
-			*error = g_error_new (1, 0, "failed to download %s as offline", filename);
+		g_set_error (error, 1, 0, "failed to download %s as offline", filename);
 		goto out;
 	}
 
@@ -372,8 +396,7 @@ zif_store_remote_download (ZifStoreRemote *store, const gchar *filename, const g
 		completion_local = zif_completion_get_child (completion);
 		ret = zif_store_remote_load_metadata (store, cancellable, completion_local, &error_local);
 		if (!ret) {
-			if (error != NULL)
-				*error = g_error_new (1, 0, "failed to load metadata: %s", error_local->message);
+			g_set_error (error, 1, 0, "failed to load metadata: %s", error_local->message);
 			g_error_free (error_local);
 			goto out;
 		}
@@ -384,8 +407,8 @@ zif_store_remote_download (ZifStoreRemote *store, const gchar *filename, const g
 
 	/* we need at least one baseurl */
 	if (store->priv->baseurls->len == 0) {
-		if (error != NULL)
-			*error = g_error_new (1, 0, "no baseurls for %s", store->priv->id);
+		g_set_error (error, 1, 0, "no baseurls for %s", store->priv->id);
+		ret = FALSE;
 		goto out;
 	}
 
@@ -402,6 +425,7 @@ zif_store_remote_download (ZifStoreRemote *store, const gchar *filename, const g
 
 	/* try to use all uris */
 	len = store->priv->baseurls->len;
+	completion_local = zif_completion_get_child (completion);
 	for (i=0; i<len; i++) {
 
 		/* build url */
@@ -409,8 +433,12 @@ zif_store_remote_download (ZifStoreRemote *store, const gchar *filename, const g
 		uri = g_build_filename (baseurl, "repodata", basename, NULL);
 
 		/* try download */
-		completion_local = zif_completion_get_child (completion);
+		zif_completion_reset (completion_local);
 		ret = zif_store_remote_download_try (store, uri, filename_local, cancellable, completion_local, &error_local);
+		if (!ret) {
+			egg_debug ("failed to download (non-fatal): %s", error_local->message);
+			g_clear_error (&error_local);
+		}
 
 		/* free */
 		g_free (uri);
@@ -418,11 +446,6 @@ zif_store_remote_download (ZifStoreRemote *store, const gchar *filename, const g
 		/* succeeded, otherwise retry with new mirrors */
 		if (ret)
 			break;
-
-		/* free error */
-		zif_completion_reset (completion_local);
-		egg_debug ("failed to download (non-fatal): %s", error_local->message);
-		g_error_free (error_local);
 	}
 
 	/* this section done */
@@ -430,8 +453,7 @@ zif_store_remote_download (ZifStoreRemote *store, const gchar *filename, const g
 
 	/* nothing */
 	if (!ret) {
-		if (error != NULL)
-			*error = g_error_new (1, 0, "failed to download from any sources");
+		g_set_error_literal (error, 1, 0, "failed to download from any sources");
 		goto out;
 	}
 out:
@@ -448,45 +470,61 @@ static gboolean
 zif_store_remote_add_metalink (ZifStoreRemote *store, GCancellable *cancellable, ZifCompletion *completion, GError **error)
 {
 	guint i;
-	GPtrArray *array;
+	GPtrArray *array = NULL;
 	GError *error_local = NULL;
-	const gchar *uri;
+	const gchar *uri_tmp;
 	const gchar *filename;
 	gboolean ret;
 	ZifCompletion *completion_local;
+	ZifDownload *download = NULL;
 
 	/* if we're loading the metadata with an empty cache, the file won't yet exist. So download it */
 	filename = zif_repo_md_get_filename_uncompressed (store->priv->md_metalink);
+	if (filename == NULL) {
+		egg_error ("Moo: %s", zif_repo_md_get_filename (store->priv->md_metalink));
+		g_set_error (error, 1, 0, "metalink filename not set for %s", store->priv->id);
+		goto out;
+	}
+
+	zif_completion_set_number_steps (completion, 2);
+
+	/* find if the file already exists */
 	ret = g_file_test (filename, G_FILE_TEST_EXISTS);
 	if (!ret) {
 		completion_local = zif_completion_get_child (completion);
-		ret = zif_store_remote_download (store, store->priv->mirrorlist, store->priv->directory, cancellable, completion_local, &error_local);
+
+		/* download object directly, as we don't have the repo setup yet */
+		download = zif_download_new ();
+		ret = zif_download_file (download, store->priv->metalink, filename, cancellable, completion_local, &error_local);
 		if (!ret) {
-			if (error != NULL)
-				*error = g_error_new (1, 0, "failed to download missing mirrorlist: %s", error_local->message);
+			g_set_error (error, 1, 0, "failed to download %s from %s: %s", filename, store->priv->metalink, error_local->message);
 			g_error_free (error_local);
 			goto out;
 		}
 	}
 
+	zif_completion_done (completion);
+
 	/* get mirrors */
-	array = zif_repo_md_metalink_get_uris (ZIF_REPO_MD_METALINK (store->priv->md_metalink), 50, cancellable, completion, &error_local);
+	completion_local = zif_completion_get_child (completion);
+	array = zif_repo_md_metalink_get_uris (ZIF_REPO_MD_METALINK (store->priv->md_metalink), 50, cancellable, completion_local, &error_local);
 	if (array == NULL) {
-		if (error != NULL)
-			*error = g_error_new (1, 0, "failed to add mirrors: %s", error_local->message);
+		g_set_error (error, 1, 0, "failed to add mirrors from metalink: %s", error_local->message);
 		g_error_free (error_local);
 		goto out;
 	}
 
+	zif_completion_done (completion);
+
 	/* add array */
 	for (i=0; i<array->len; i++) {
-		uri = g_ptr_array_index (array, i);
-		g_ptr_array_add (store->priv->baseurls, g_strdup (uri));
+		uri_tmp = g_ptr_array_index (array, i);
+		egg_warning ("uri_tmp=%s", uri_tmp);
+		g_ptr_array_add (store->priv->baseurls, g_strdup (uri_tmp));
 	}
-
-	/* free */
-	g_ptr_array_unref (array);
 out:
+	if (array != NULL)
+		g_ptr_array_unref (array);
 	return (array != NULL);
 }
 
@@ -497,45 +535,64 @@ static gboolean
 zif_store_remote_add_mirrorlist (ZifStoreRemote *store, GCancellable *cancellable, ZifCompletion *completion, GError **error)
 {
 	guint i;
-	GPtrArray *array;
+	GPtrArray *array = NULL;
 	GError *error_local = NULL;
-	const gchar *uri;
+	gchar *uri = NULL;
+	const gchar *uri_tmp;
 	const gchar *filename;
-	gboolean ret;
+	gboolean ret = FALSE;
 	ZifCompletion *completion_local;
+	ZifDownload *download = NULL;
 
 	/* if we're loading the metadata with an empty cache, the file won't yet exist. So download it */
 	filename = zif_repo_md_get_filename_uncompressed (store->priv->md_mirrorlist);
+	if (filename == NULL) {
+		g_set_error (error, 1, 0, "mirrorlist filename not set for %s", store->priv->id);
+		goto out;
+	}
+
+	zif_completion_set_number_steps (completion, 2);
+
+	/* find if the file already exists */
 	ret = g_file_test (filename, G_FILE_TEST_EXISTS);
 	if (!ret) {
 		completion_local = zif_completion_get_child (completion);
-		ret = zif_store_remote_download (store, store->priv->mirrorlist, store->priv->directory, cancellable, completion_local, &error_local);
+
+		/* download object directly, as we don't have the repo setup yet */
+		download = zif_download_new ();
+		uri = g_build_filename (store->priv->mirrorlist, filename, NULL);
+		ret = zif_download_file (download, uri, filename, cancellable, completion_local, &error_local);
 		if (!ret) {
-			if (error != NULL)
-				*error = g_error_new (1, 0, "failed to download missing mirrorlist: %s", error_local->message);
+			g_set_error (error, 1, 0, "failed to download %s from %s: %s", filename, store->priv->mirrorlist, error_local->message);
 			g_error_free (error_local);
 			goto out;
 		}
 	}
 
+	zif_completion_done (completion);
+
 	/* get mirrors */
-	array = zif_repo_md_mirrorlist_get_uris (ZIF_REPO_MD_MIRRORLIST (store->priv->md_mirrorlist), cancellable, completion, &error_local);
+	completion_local = zif_completion_get_child (completion);
+	array = zif_repo_md_mirrorlist_get_uris (ZIF_REPO_MD_MIRRORLIST (store->priv->md_mirrorlist), cancellable, completion_local, &error_local);
 	if (array == NULL) {
-		if (error != NULL)
-			*error = g_error_new (1, 0, "failed to add mirrors: %s", error_local->message);
+		g_set_error (error, 1, 0, "failed to add mirrors from mirrorlist: %s", error_local->message);
 		g_error_free (error_local);
 		goto out;
 	}
 
+	zif_completion_done (completion);
+
 	/* add array */
 	for (i=0; i<array->len; i++) {
-		uri = g_ptr_array_index (array, i);
-		g_ptr_array_add (store->priv->baseurls, g_strdup (uri));
+		uri_tmp = g_ptr_array_index (array, i);
+		g_ptr_array_add (store->priv->baseurls, g_strdup (uri_tmp));
 	}
-
-	/* free */
-	g_ptr_array_unref (array);
 out:
+	g_free (uri);
+	if (download != NULL)
+		g_object_unref (download);
+	if (array != NULL)
+		g_ptr_array_unref (array);
 	return (array != NULL);
 
 }
@@ -579,8 +636,7 @@ zif_store_remote_load_metadata (ZifStoreRemote *store, GCancellable *cancellable
 	ret = zif_lock_is_locked (store->priv->lock, NULL);
 	if (!ret) {
 		egg_warning ("not locked");
-		if (error != NULL)
-			*error = g_error_new (1, 0, "not locked");
+		g_set_error_literal (error, 1, 0, "not locked");
 		goto out;
 	}
 
@@ -589,7 +645,43 @@ zif_store_remote_load_metadata (ZifStoreRemote *store, GCancellable *cancellable
 		goto out;
 
 	/* setup completion */
-	zif_completion_set_number_steps (completion, 3);
+	zif_completion_set_number_steps (completion, 4);
+
+	/* extract details from mirrorlist */
+	if (store->priv->mirrorlist != NULL) {
+		completion_local = zif_completion_get_child (completion);
+		ret = zif_store_remote_add_mirrorlist (store, cancellable, completion_local, &error_local);
+		if (!ret) {
+			g_set_error (error, 1, 0, "failed to add mirrorlist: %s", error_local->message);
+			g_error_free (error_local);
+			goto out;
+		}
+	}
+
+	/* this section done */
+	zif_completion_done (completion);
+
+	/* extract details from metalink */
+	if (store->priv->metalink != NULL) {
+		completion_local = zif_completion_get_child (completion);
+		ret = zif_store_remote_add_metalink (store, cancellable, completion_local, &error_local);
+		if (!ret) {
+			g_set_error (error, 1, 0, "failed to add metalink: %s", error_local->message);
+			g_error_free (error_local);
+			goto out;
+		}
+	}
+
+	/* check we got something */
+	if (store->priv->baseurls->len == 0) {
+		g_set_error (error, 1, 0, "no baseurls for %s, so can't download anything! [meta:%s, mirror:%s]",
+			     store->priv->id, store->priv->metalink, store->priv->mirrorlist);
+		ret = FALSE;
+		goto out;
+	}
+
+	/* this section done */
+	zif_completion_done (completion);
 
 	/* repomd file does not exist */
 	ret = g_file_test (store->priv->repomd_filename, G_FILE_TEST_EXISTS);
@@ -597,8 +689,7 @@ zif_store_remote_load_metadata (ZifStoreRemote *store, GCancellable *cancellable
 		/* if not online, then this is fatal */
 		ret = zif_config_get_boolean (store->priv->config, "network", NULL);
 		if (!ret) {
-			if (error != NULL)
-				*error = g_error_new (1, 0, "failed to download repomd as offline");
+			g_set_error (error, 1, 0, "failed to download repomd as offline");
 			goto out;
 		}
 
@@ -608,13 +699,15 @@ zif_store_remote_load_metadata (ZifStoreRemote *store, GCancellable *cancellable
 		ret = zif_store_remote_download (store, store->priv->repomd_filename, store->priv->directory, cancellable, completion_local, &error_local);
 		store->priv->loaded_metadata = FALSE;
 		if (!ret) {
-			if (error != NULL)
-				*error = g_error_new (1, 0, "failed to download missing repomd: %s", error_local->message);
+			g_set_error (error, 1, 0, "failed to download missing repomd: %s", error_local->message);
 			g_error_free (error_local);
 			goto out;
 		}
 	}
 
+	/* this section done */
+	zif_completion_done (completion);
+
 	/* get repo contents */
 	ret = g_file_get_contents (store->priv->repomd_filename, &contents, &size, error);
 	if (!ret)
@@ -633,79 +726,39 @@ zif_store_remote_load_metadata (ZifStoreRemote *store, GCancellable *cancellable
 		md = zif_store_remote_get_md_from_type (store, i);
 		if (md == NULL) {
 			/* TODO: until we've created ZifRepoMdComps and ZifRepoMdOther we'll get warnings here */
-			egg_warning ("failed to get local store for %s with %s", zif_repo_md_type_to_text (i), store->priv->id);
+			egg_debug ("failed to get local store for %s with %s", zif_repo_md_type_to_text (i), store->priv->id);
 			continue;
 		}
 
 		/* no metalink? */
-		if (i == ZIF_REPO_MD_TYPE_METALINK &&
-		    store->priv->metalink == NULL)
+		if (i == ZIF_REPO_MD_TYPE_METALINK)
 			continue;
 
 		/* no mirrorlist? */
-		if (i == ZIF_REPO_MD_TYPE_MIRRORLIST &&
-		    store->priv->mirrorlist == NULL)
+		if (i == ZIF_REPO_MD_TYPE_MIRRORLIST)
 			continue;
 
-		/* set parent reference */
-		zif_repo_md_set_store_remote (md, store);
-
-		/* set MD type */
-		zif_repo_md_set_mdtype (md, i);
-
 		/* location not set */
 		location = zif_repo_md_get_location (md);
 		if (location == NULL) {
 			/* messed up repo file, this is fatal */
 			if (i == ZIF_REPO_MD_TYPE_PRIMARY_DB) {
-				if (error != NULL)
-					*error = g_error_new (1, 0, "failed to get primary metadata location for %s", store->priv->id);
+				g_set_error (error, 1, 0, "failed to get primary metadata location for %s", store->priv->id);
 				ret = FALSE;
 				goto out;
 			}
-			egg_warning ("no location set for %s with %s", zif_repo_md_type_to_text (i), store->priv->id);
+			egg_debug ("no location set for %s with %s", zif_repo_md_type_to_text (i), store->priv->id);
 			continue;
 		}
 
 		/* set MD id and filename */
 		basename = g_path_get_basename (location);
 		filename = g_build_filename (store->priv->directory, basename, NULL);
-		zif_repo_md_set_id (md, store->priv->id);
 		zif_repo_md_set_filename (md, filename);
 		g_free (basename);
 		g_free (filename);
 	}
 
-	/* this section done */
-	zif_completion_done (completion);
-
-	/* extract details from mirrorlist */
-	if (store->priv->mirrorlist != NULL) {
-		completion_local = zif_completion_get_child (completion);
-		ret = zif_store_remote_add_mirrorlist (store, cancellable, completion_local, &error_local);
-		if (!ret) {
-			if (error != NULL)
-				*error = g_error_new (1, 0, "failed to add mirrorlist: %s", error_local->message);
-			g_error_free (error_local);
-			goto out;
-		}
-	}
-
-	/* this section done */
-	zif_completion_done (completion);
-
-	/* extract details from metalink */
-	if (store->priv->metalink != NULL) {
-		completion_local = zif_completion_get_child (completion);
-		ret = zif_store_remote_add_metalink (store, cancellable, completion_local, &error_local);
-		if (!ret) {
-			if (error != NULL)
-				*error = g_error_new (1, 0, "failed to add metalink: %s", error_local->message);
-			g_error_free (error_local);
-			goto out;
-		}
-	}
-
 	/* all okay */
 	store->priv->loaded_metadata = TRUE;
 
@@ -765,8 +818,7 @@ zif_store_remote_refresh (ZifStore *store, gboolean force, GCancellable *cancell
 	/* if not online, then this is fatal */
 	ret = zif_config_get_boolean (remote->priv->config, "network", NULL);
 	if (!ret) {
-		if (error != NULL)
-			*error = g_error_new (1, 0, "failed to refresh as offline");
+		g_set_error_literal (error, 1, 0, "failed to refresh as offline");
 		goto out;
 	}
 
@@ -777,8 +829,7 @@ zif_store_remote_refresh (ZifStore *store, gboolean force, GCancellable *cancell
 	ret = zif_lock_is_locked (remote->priv->lock, NULL);
 	if (!ret) {
 		egg_warning ("not locked");
-		if (error != NULL)
-			*error = g_error_new (1, 0, "not locked");
+		g_set_error_literal (error, 1, 0, "not locked");
 		goto out;
 	}
 
@@ -788,8 +839,7 @@ zif_store_remote_refresh (ZifStore *store, gboolean force, GCancellable *cancell
 	/* download new file */
 	ret = zif_store_remote_download (remote, remote->priv->repomd_filename, remote->priv->directory, cancellable, completion_local, &error_local);
 	if (!ret) {
-		if (error != NULL)
-			*error = g_error_new (1, 0, "failed to download repomd: %s", error_local->message);
+		g_set_error (error, 1, 0, "failed to download repomd: %s", error_local->message);
 		g_error_free (error_local);
 		goto out;
 	}
@@ -801,8 +851,7 @@ zif_store_remote_refresh (ZifStore *store, gboolean force, GCancellable *cancell
 	completion_local = zif_completion_get_child (completion);
 	ret = zif_store_remote_load_metadata (remote, cancellable, completion_local, &error_local);
 	if (!ret) {
-		if (error != NULL)
-			*error = g_error_new (1, 0, "failed to load updated metadata: %s", error_local->message);
+		g_set_error (error, 1, 0, "failed to load updated metadata: %s", error_local->message);
 		g_error_free (error_local);
 		goto out;
 	}
@@ -836,8 +885,7 @@ zif_store_remote_refresh (ZifStore *store, gboolean force, GCancellable *cancell
 		completion_local = zif_completion_get_child (completion);
 		ret = zif_store_remote_download (remote, filename, remote->priv->directory, cancellable, completion_local, &error_local);
 		if (!ret) {
-			if (error != NULL)
-				*error = g_error_new (1, 0, "failed to refresh %s (%s): %s", zif_repo_md_type_to_text (i), filename, error_local->message);
+			g_set_error (error, 1, 0, "failed to refresh %s (%s): %s", zif_repo_md_type_to_text (i), filename, error_local->message);
 			g_error_free (error_local);
 			goto out;
 		}
@@ -849,9 +897,8 @@ zif_store_remote_refresh (ZifStore *store, gboolean force, GCancellable *cancell
 		completion_local = zif_completion_get_child (completion);
 		ret = zif_store_file_decompress (filename, cancellable, completion_local, &error_local);
 		if (!ret) {
-			if (error != NULL)
-				*error = g_error_new (1, 0, "failed to decompress %s for %s: %s",
-						      filename, zif_repo_md_type_to_text (i), error_local->message);
+			g_set_error (error, 1, 0, "failed to decompress %s for %s: %s",
+				     filename, zif_repo_md_type_to_text (i), error_local->message);
 			g_error_free (error_local);
 			goto out;
 		}
@@ -866,6 +913,9 @@ out:
 
 /**
  * zif_store_remote_load:
+ *
+ * This function has to be fast, so don't download anything or load any
+ * databases until zif_store_remote_load_metadata().
  **/
 static gboolean
 zif_store_remote_load (ZifStore *store, GCancellable *cancellable, ZifCompletion *completion, GError **error)
@@ -875,6 +925,8 @@ zif_store_remote_load (ZifStore *store, GCancellable *cancellable, ZifCompletion
 	gchar *enabled = NULL;
 	GError *error_local = NULL;
 	gchar *temp;
+	gchar *filename;
+//	ZifCompletion *completion_local;
 	ZifStoreRemote *remote = ZIF_STORE_REMOTE (store);
 
 	g_return_val_if_fail (ZIF_IS_STORE_REMOTE (store), FALSE);
@@ -885,8 +937,7 @@ zif_store_remote_load (ZifStore *store, GCancellable *cancellable, ZifCompletion
 	ret = zif_lock_is_locked (remote->priv->lock, NULL);
 	if (!ret) {
 		egg_warning ("not locked");
-		if (error != NULL)
-			*error = g_error_new (1, 0, "not locked");
+		g_set_error_literal (error, 1, 0, "not locked");
 		goto out;
 	}
 
@@ -900,8 +951,7 @@ zif_store_remote_load (ZifStore *store, GCancellable *cancellable, ZifCompletion
 	file = g_key_file_new ();
 	ret = g_key_file_load_from_file (file, remote->priv->repo_filename, G_KEY_FILE_NONE, &error_local);
 	if (!ret) {
-		if (error != NULL)
-			*error = g_error_new (1, 0, "failed to load %s: %s", remote->priv->repo_filename, error_local->message);
+		g_set_error (error, 1, 0, "failed to load %s: %s", remote->priv->repo_filename, error_local->message);
 		g_error_free (error_local);
 		goto out;
 	}
@@ -912,8 +962,7 @@ zif_store_remote_load (ZifStore *store, GCancellable *cancellable, ZifCompletion
 	/* name */
 	remote->priv->name = g_key_file_get_string (file, remote->priv->id, "name", &error_local);
 	if (error_local != NULL) {
-		if (error != NULL)
-			*error = g_error_new (1, 0, "failed to get name: %s", error_local->message);
+		g_set_error (error, 1, 0, "failed to get name: %s", error_local->message);
 		g_error_free (error_local);
 		ret = FALSE;
 		goto out;
@@ -922,8 +971,7 @@ zif_store_remote_load (ZifStore *store, GCancellable *cancellable, ZifCompletion
 	/* enabled */
 	enabled = g_key_file_get_string (file, remote->priv->id, "enabled", &error_local);
 	if (enabled == NULL) {
-		if (error != NULL)
-			*error = g_error_new (1, 0, "failed to get enabled: %s", error_local->message);
+		g_set_error (error, 1, 0, "failed to get enabled: %s", error_local->message);
 		g_error_free (error_local);
 		ret = FALSE;
 		goto out;
@@ -962,10 +1010,23 @@ zif_store_remote_load (ZifStore *store, GCancellable *cancellable, ZifCompletion
 		remote->priv->mirrorlist = NULL;
 	}
 
+	/* we have to set this here in case we are using the metalink to download repodata.xml */
+	if (remote->priv->metalink != NULL) {
+		filename = g_build_filename (remote->priv->directory, "metalink.xml", NULL);
+		zif_repo_md_set_filename (remote->priv->md_metalink, filename);
+		g_free (filename);
+	}
+
+	/* we have to set this here in case we are using the mirrorlist to download repodata.xml */
+	if (remote->priv->mirrorlist != NULL) {
+		filename = g_build_filename (remote->priv->directory, "mirrorlist.txt", NULL);
+		zif_repo_md_set_filename (remote->priv->md_mirrorlist, filename);
+		g_free (filename);
+	}
+
 	/* we need either a base url or mirror list for an enabled store */
 	if (remote->priv->enabled && remote->priv->baseurls->len == 0 && remote->priv->metalink == NULL && remote->priv->mirrorlist == NULL) {
-		if (error != NULL)
-			*error = g_error_new (1, 0, "baseurl, metalink or mirrorlist required");
+		g_set_error_literal (error, 1, 0, "baseurl, metalink or mirrorlist required");
 		ret = FALSE;
 		goto out;
 	}
@@ -1005,8 +1066,7 @@ zif_store_remote_clean (ZifStore *store, GCancellable *cancellable, ZifCompletio
 	ret = zif_lock_is_locked (remote->priv->lock, NULL);
 	if (!ret) {
 		egg_warning ("not locked");
-		if (error != NULL)
-			*error = g_error_new (1, 0, "not locked");
+		g_set_error_literal (error, 1, 0, "not locked");
 		goto out;
 	}
 
@@ -1021,8 +1081,6 @@ zif_store_remote_clean (ZifStore *store, GCancellable *cancellable, ZifCompletio
 		completion_local = zif_completion_get_child (completion);
 		ret = zif_store_remote_load_metadata (remote, cancellable, completion_local, &error_local);
 		if (!ret) {
-//			if (error != NULL)
-//				*error = g_error_new (1, 0, "failed to load xml: %s", error_local->message);
 			/* ignore this error */
 			g_print ("failed to load xml: %s\n", error_local->message);
 			g_error_free (error_local);
@@ -1039,22 +1097,21 @@ zif_store_remote_clean (ZifStore *store, GCancellable *cancellable, ZifCompletio
 		md = zif_store_remote_get_md_from_type (remote, i);
 		if (md == NULL) {
 			/* TODO: until we've created ZifRepoMdComps and ZifRepoMdOther we'll get warnings here */
-			egg_warning ("failed to get local store for %s with %s", zif_repo_md_type_to_text (i), remote->priv->id);
+			egg_debug ("failed to get local store for %s with %s", zif_repo_md_type_to_text (i), remote->priv->id);
 			goto skip;
 		}
 
 		/* location not set */
 		location = zif_repo_md_get_location (md);
 		if (location == NULL) {
-			egg_warning ("no location set for %s with %s", zif_repo_md_type_to_text (i), remote->priv->id);
+			egg_debug ("no location set for %s with %s", zif_repo_md_type_to_text (i), remote->priv->id);
 			goto skip;
 		}
 
 		/* clean md */
 		ret = zif_repo_md_clean (md, &error_local);
 		if (!ret) {
-			if (error != NULL)
-				*error = g_error_new (1, 0, "failed to clean %s: %s", zif_repo_md_type_to_text (i), error_local->message);
+			g_set_error (error, 1, 0, "failed to clean %s: %s", zif_repo_md_type_to_text (i), error_local->message);
 			g_error_free (error_local);
 			goto out;
 		}
@@ -1070,9 +1127,8 @@ skip:
 		ret = g_file_delete (file, NULL, &error_local);
 		g_object_unref (file);
 		if (!ret) {
-			if (error != NULL)
-				*error = g_error_new (1, 0, "failed to delete metadata file %s: %s",
-						      remote->priv->repomd_filename, error_local->message);
+			g_set_error (error, 1, 0, "failed to delete metadata file %s: %s",
+				     remote->priv->repomd_filename, error_local->message);
 			g_error_free (error_local);
 			goto out;
 		}
@@ -1093,8 +1149,10 @@ gboolean
 zif_store_remote_set_from_file (ZifStoreRemote *store, const gchar *repo_filename, const gchar *id,
 				GCancellable *cancellable, ZifCompletion *completion, GError **error)
 {
-	GError *error_local = NULL;
 	gboolean ret = TRUE;
+	guint i;
+	GError *error_local = NULL;
+	ZifRepoMd *md;
 
 	g_return_val_if_fail (ZIF_IS_STORE_REMOTE (store), FALSE);
 	g_return_val_if_fail (repo_filename != NULL, FALSE);
@@ -1106,8 +1164,7 @@ zif_store_remote_set_from_file (ZifStoreRemote *store, const gchar *repo_filenam
 	ret = zif_lock_is_locked (store->priv->lock, NULL);
 	if (!ret) {
 		egg_warning ("not locked");
-		if (error != NULL)
-			*error = g_error_new (1, 0, "not locked");
+		g_set_error_literal (error, 1, 0, "not locked");
 		goto out;
 	}
 
@@ -1120,11 +1177,18 @@ zif_store_remote_set_from_file (ZifStoreRemote *store, const gchar *repo_filenam
 	/* repomd location */
 	store->priv->repomd_filename = g_build_filename (store->priv->cache_dir, store->priv->id, "repomd.xml", NULL);
 
+	/* set MD id for each repo type */
+	for (i=0; i<ZIF_REPO_MD_TYPE_UNKNOWN; i++) {
+		md = zif_store_remote_get_md_from_type (store, i);
+		if (md == NULL)
+			continue;
+		zif_repo_md_set_id (md, store->priv->id);
+	}
+
 	/* setup watch */
 	ret = zif_monitor_add_watch (store->priv->monitor, repo_filename, &error_local);
 	if (!ret) {
-		if (error != NULL)
-			*error = g_error_new (1, 0, "failed to setup watch: %s", error_local->message);
+		g_set_error (error, 1, 0, "failed to setup watch: %s", error_local->message);
 		g_error_free (error_local);
 		goto out;
 	}
@@ -1132,8 +1196,7 @@ zif_store_remote_set_from_file (ZifStoreRemote *store, const gchar *repo_filenam
 	/* get data */
 	ret = zif_store_remote_load (ZIF_STORE (store), cancellable, completion, &error_local);
 	if (!ret) {
-		if (error != NULL)
-			*error = g_error_new (1, 0, "failed to load %s: %s", id, error_local->message);
+		g_set_error (error, 1, 0, "failed to load %s: %s", id, error_local->message);
 		g_error_free (error_local);
 		goto out;
 	}
@@ -1167,8 +1230,7 @@ zif_store_remote_set_enabled (ZifStoreRemote *store, gboolean enabled, GError **
 	ret = zif_lock_is_locked (store->priv->lock, NULL);
 	if (!ret) {
 		egg_warning ("not locked");
-		if (error != NULL)
-			*error = g_error_new (1, 0, "not locked");
+		g_set_error_literal (error, 1, 0, "not locked");
 		goto out;
 	}
 
@@ -1176,8 +1238,7 @@ zif_store_remote_set_enabled (ZifStoreRemote *store, gboolean enabled, GError **
 	file = g_key_file_new ();
 	ret = g_key_file_load_from_file (file, store->priv->repo_filename, G_KEY_FILE_KEEP_COMMENTS, &error_local);
 	if (!ret) {
-		if (error != NULL)
-			*error = g_error_new (1, 0, "failed to load store file: %s", error_local->message);
+		g_set_error (error, 1, 0, "failed to load store file: %s", error_local->message);
 		g_error_free (error_local);
 		goto out;
 	}
@@ -1190,8 +1251,7 @@ zif_store_remote_set_enabled (ZifStoreRemote *store, gboolean enabled, GError **
 	data = g_key_file_to_data (file, NULL, NULL);
 	ret = g_file_set_contents (store->priv->repo_filename, data, -1, &error_local);
 	if (!ret) {
-		if (error != NULL)
-			*error = g_error_new (1, 0, "failed to save: %s", error_local->message);
+		g_set_error (error, 1, 0, "failed to save: %s", error_local->message);
 		g_error_free (error_local);
 		goto out;
 	}
@@ -1238,8 +1298,7 @@ zif_store_remote_resolve (ZifStore *store, const gchar *search, GCancellable *ca
 	ret = zif_lock_is_locked (remote->priv->lock, NULL);
 	if (!ret) {
 		egg_warning ("not locked");
-		if (error != NULL)
-			*error = g_error_new (1, 0, "not locked");
+		g_set_error_literal (error, 1, 0, "not locked");
 		goto out;
 	}
 
@@ -1254,8 +1313,7 @@ zif_store_remote_resolve (ZifStore *store, const gchar *search, GCancellable *ca
 		completion_local = zif_completion_get_child (completion);
 		ret = zif_store_remote_load_metadata (remote, cancellable, completion_local, &error_local);
 		if (!ret) {
-			if (error != NULL)
-				*error = g_error_new (1, 0, "failed to load xml: %s", error_local->message);
+			g_set_error (error, 1, 0, "failed to load metadata for %s: %s", remote->priv->id, error_local->message);
 			g_error_free (error_local);
 			goto out;
 		}
@@ -1292,8 +1350,7 @@ zif_store_remote_search_name (ZifStore *store, const gchar *search, GCancellable
 	ret = zif_lock_is_locked (remote->priv->lock, NULL);
 	if (!ret) {
 		egg_warning ("not locked");
-		if (error != NULL)
-			*error = g_error_new (1, 0, "not locked");
+		g_set_error_literal (error, 1, 0, "not locked");
 		goto out;
 	}
 
@@ -1308,8 +1365,7 @@ zif_store_remote_search_name (ZifStore *store, const gchar *search, GCancellable
 		completion_local = zif_completion_get_child (completion);
 		ret = zif_store_remote_load_metadata (remote, cancellable, completion_local, &error_local);
 		if (!ret) {
-			if (error != NULL)
-				*error = g_error_new (1, 0, "failed to load xml: %s", error_local->message);
+			g_set_error (error, 1, 0, "failed to load xml: %s", error_local->message);
 			g_error_free (error_local);
 			goto out;
 		}
@@ -1346,8 +1402,7 @@ zif_store_remote_search_details (ZifStore *store, const gchar *search, GCancella
 	ret = zif_lock_is_locked (remote->priv->lock, NULL);
 	if (!ret) {
 		egg_warning ("not locked");
-		if (error != NULL)
-			*error = g_error_new (1, 0, "not locked");
+		g_set_error_literal (error, 1, 0, "not locked");
 		goto out;
 	}
 
@@ -1362,8 +1417,7 @@ zif_store_remote_search_details (ZifStore *store, const gchar *search, GCancella
 		completion_local = zif_completion_get_child (completion);
 		ret = zif_store_remote_load_metadata (remote, cancellable, completion_local, &error_local);
 		if (!ret) {
-			if (error != NULL)
-				*error = g_error_new (1, 0, "failed to load xml: %s", error_local->message);
+			g_set_error (error, 1, 0, "failed to load xml: %s", error_local->message);
 			g_error_free (error_local);
 			goto out;
 		}
@@ -1402,8 +1456,7 @@ zif_store_remote_search_category_resolve (ZifStore *store, const gchar *name, GC
 	completion_local = zif_completion_get_child (completion);
 	array = zif_store_resolve (ZIF_STORE (store_local), name, cancellable, completion_local, &error_local);
 	if (array == NULL) {
-		if (error != NULL)
-			*error = g_error_new (1, 0, "failed to resolve installed package %s: %s", name, error_local->message);
+		g_set_error (error, 1, 0, "failed to resolve installed package %s: %s", name, error_local->message);
 		g_error_free (error_local);
 		goto out;
 	}
@@ -1426,8 +1479,7 @@ zif_store_remote_search_category_resolve (ZifStore *store, const gchar *name, GC
 	completion_local = zif_completion_get_child (completion);
 	array = zif_store_resolve (ZIF_STORE (store), name, cancellable, completion_local, &error_local);
 	if (array == NULL) {
-		if (error != NULL)
-			*error = g_error_new (1, 0, "failed to resolve installed package %s: %s", name, error_local->message);
+		g_set_error (error, 1, 0, "failed to resolve installed package %s: %s", name, error_local->message);
 		g_error_free (error_local);
 		goto out;
 	}
@@ -1441,8 +1493,7 @@ zif_store_remote_search_category_resolve (ZifStore *store, const gchar *name, GC
 		goto out;
 
 	/* we suck */
-	if (error != NULL)
-		*error = g_error_new (1, 0, "failed to resolve installed package %s installed or in this repo", name);
+	g_set_error (error, 1, 0, "failed to resolve installed package %s installed or in this repo", name);
 out:
 	if (array != NULL)
 		g_ptr_array_unref (array);
@@ -1476,8 +1527,7 @@ zif_store_remote_search_category (ZifStore *store, const gchar *group_id, GCance
 	ret = zif_lock_is_locked (remote->priv->lock, NULL);
 	if (!ret) {
 		egg_warning ("not locked");
-		if (error != NULL)
-			*error = g_error_new (1, 0, "not locked");
+		g_set_error_literal (error, 1, 0, "not locked");
 		goto out;
 	}
 
@@ -1492,8 +1542,7 @@ zif_store_remote_search_category (ZifStore *store, const gchar *group_id, GCance
 		completion_local = zif_completion_get_child (completion);
 		ret = zif_store_remote_load_metadata (remote, cancellable, completion_local, &error_local);
 		if (!ret) {
-			if (error != NULL)
-				*error = g_error_new (1, 0, "failed to load xml: %s", error_local->message);
+			g_set_error (error, 1, 0, "failed to load xml: %s", error_local->message);
 			g_error_free (error_local);
 			goto out;
 		}
@@ -1521,8 +1570,7 @@ zif_store_remote_search_category (ZifStore *store, const gchar *group_id, GCance
 			g_error_free (error_local);
 			goto out;
 		}
-		if (error != NULL)
-			*error = g_error_new (1, 0, "failed to get packages for group %s: %s", group_id, error_local->message);
+		g_set_error (error, 1, 0, "failed to get packages for group %s: %s", group_id, error_local->message);
 		g_error_free (error_local);
 		goto out;
 	}
@@ -1552,8 +1600,7 @@ zif_store_remote_search_category (ZifStore *store, const gchar *group_id, GCance
 				goto ignore_error;
 			}
 
-			if (error != NULL)
-				*error = g_error_new (1, 0, "failed to get resolve %s for %s: %s", name, group_id, error_local->message);
+			g_set_error (error, 1, 0, "failed to get resolve %s for %s: %s", name, group_id, error_local->message);
 			g_error_free (error_local);
 
 			/* undo all our hard work */
@@ -1596,8 +1643,7 @@ zif_store_remote_search_group (ZifStore *store, const gchar *search, GCancellabl
 	ret = zif_lock_is_locked (remote->priv->lock, NULL);
 	if (!ret) {
 		egg_warning ("not locked");
-		if (error != NULL)
-			*error = g_error_new (1, 0, "not locked");
+		g_set_error_literal (error, 1, 0, "not locked");
 		goto out;
 	}
 
@@ -1612,8 +1658,7 @@ zif_store_remote_search_group (ZifStore *store, const gchar *search, GCancellabl
 		completion_local = zif_completion_get_child (completion);
 		ret = zif_store_remote_load_metadata (remote, cancellable, completion_local, &error_local);
 		if (!ret) {
-			if (error != NULL)
-				*error = g_error_new (1, 0, "failed to load xml: %s", error_local->message);
+			g_set_error (error, 1, 0, "failed to load xml: %s", error_local->message);
 			g_error_free (error_local);
 			goto out;
 		}
@@ -1651,8 +1696,7 @@ zif_store_remote_find_package (ZifStore *store, const gchar *package_id, GCancel
 	ret = zif_lock_is_locked (remote->priv->lock, NULL);
 	if (!ret) {
 		egg_warning ("not locked");
-		if (error != NULL)
-			*error = g_error_new (1, 0, "not locked");
+		g_set_error_literal (error, 1, 0, "not locked");
 		goto out;
 	}
 
@@ -1667,8 +1711,7 @@ zif_store_remote_find_package (ZifStore *store, const gchar *package_id, GCancel
 		completion_local = zif_completion_get_child (completion);
 		ret = zif_store_remote_load_metadata (remote, cancellable, completion_local, &error_local);
 		if (!ret) {
-			if (error != NULL)
-				*error = g_error_new (1, 0, "failed to load xml: %s", error_local->message);
+			g_set_error (error, 1, 0, "failed to load xml: %s", error_local->message);
 			g_error_free (error_local);
 			goto out;
 		}
@@ -1681,8 +1724,7 @@ zif_store_remote_find_package (ZifStore *store, const gchar *package_id, GCancel
 	completion_local = zif_completion_get_child (completion);
 	array = zif_repo_md_primary_find_package (ZIF_REPO_MD_PRIMARY (remote->priv->md_primary), package_id, cancellable, completion_local, &error_local);
 	if (array == NULL) {
-		if (error != NULL)
-			*error = g_error_new (1, 0, "failed to search: %s", error_local->message);
+		g_set_error (error, 1, 0, "failed to search: %s", error_local->message);
 		g_error_free (error_local);
 		goto out;
 	}
@@ -1692,15 +1734,13 @@ zif_store_remote_find_package (ZifStore *store, const gchar *package_id, GCancel
 
 	/* nothing */
 	if (array->len == 0) {
-		if (error != NULL)
-			*error = g_error_new (1, 0, "failed to find package");
+		g_set_error_literal (error, 1, 0, "failed to find package");
 		goto out;
 	}
 
 	/* more than one match */
 	if (array->len > 1) {
-		if (error != NULL)
-			*error = g_error_new (1, 0, "more than one match");
+		g_set_error_literal (error, 1, 0, "more than one match");
 		goto out;
 	}
 
@@ -1730,8 +1770,7 @@ zif_store_remote_get_packages (ZifStore *store, GCancellable *cancellable, ZifCo
 	ret = zif_lock_is_locked (remote->priv->lock, NULL);
 	if (!ret) {
 		egg_warning ("not locked");
-		if (error != NULL)
-			*error = g_error_new (1, 0, "not locked");
+		g_set_error_literal (error, 1, 0, "not locked");
 		goto out;
 	}
 
@@ -1746,8 +1785,7 @@ zif_store_remote_get_packages (ZifStore *store, GCancellable *cancellable, ZifCo
 		completion_local = zif_completion_get_child (completion);
 		ret = zif_store_remote_load_metadata (remote, cancellable, completion_local, &error_local);
 		if (!ret) {
-			if (error != NULL)
-				*error = g_error_new (1, 0, "failed to load xml: %s", error_local->message);
+			g_set_error (error, 1, 0, "failed to load xml: %s", error_local->message);
 			g_error_free (error_local);
 			goto out;
 		}
@@ -1793,8 +1831,7 @@ zif_store_remote_get_categories (ZifStore *store, GCancellable *cancellable, Zif
 	ret = zif_lock_is_locked (remote->priv->lock, NULL);
 	if (!ret) {
 		egg_warning ("not locked");
-		if (error != NULL)
-			*error = g_error_new (1, 0, "not locked");
+		g_set_error_literal (error, 1, 0, "not locked");
 		goto out;
 	}
 
@@ -1809,8 +1846,7 @@ zif_store_remote_get_categories (ZifStore *store, GCancellable *cancellable, Zif
 		completion_local = zif_completion_get_child (completion);
 		ret = zif_store_remote_load_metadata (remote, cancellable, completion_local, &error_local);
 		if (!ret) {
-			if (error != NULL)
-				*error = g_error_new (1, 0, "failed to load xml: %s", error_local->message);
+			g_set_error (error, 1, 0, "failed to load xml: %s", error_local->message);
 			g_error_free (error_local);
 			goto out;
 		}
@@ -1831,8 +1867,7 @@ zif_store_remote_get_categories (ZifStore *store, GCancellable *cancellable, Zif
 	completion_local = zif_completion_get_child (completion);
 	array_cats = zif_repo_md_comps_get_categories (ZIF_REPO_MD_COMPS (remote->priv->md_comps), cancellable, completion_local, &error_local);
 	if (array_cats == NULL) {
-		if (error != NULL)
-			*error = g_error_new (1, 0, "failed to get categories: %s", error_local->message);
+		g_set_error (error, 1, 0, "failed to get categories: %s", error_local->message);
 		g_error_free (error_local);
 		goto out;
 	}
@@ -1860,8 +1895,7 @@ zif_store_remote_get_categories (ZifStore *store, GCancellable *cancellable, Zif
 		array_groups = zif_repo_md_comps_get_groups_for_category (ZIF_REPO_MD_COMPS (remote->priv->md_comps),
 									  pk_category_get_id (category), cancellable, completion_loop, &error_local);
 		if (array_groups == NULL) {
-			if (error != NULL)
-				*error = g_error_new (1, 0, "failed to get groups for %s: %s", pk_category_get_id (category), error_local->message);
+			g_set_error (error, 1, 0, "failed to get groups for %s: %s", pk_category_get_id (category), error_local->message);
 			g_error_free (error_local);
 
 			/* undo the work we've already done */
@@ -1923,8 +1957,7 @@ zif_store_remote_get_updates (ZifStore *store, GCancellable *cancellable, ZifCom
 	ret = zif_lock_is_locked (remote->priv->lock, NULL);
 	if (!ret) {
 		egg_warning ("not locked");
-		if (error != NULL)
-			*error = g_error_new (1, 0, "not locked");
+		g_set_error_literal (error, 1, 0, "not locked");
 		goto out;
 	}
 
@@ -1939,8 +1972,7 @@ zif_store_remote_get_updates (ZifStore *store, GCancellable *cancellable, ZifCom
 		completion_local = zif_completion_get_child (completion);
 		ret = zif_store_remote_load_metadata (remote, cancellable, completion_local, &error_local);
 		if (!ret) {
-			if (error != NULL)
-				*error = g_error_new (1, 0, "failed to load xml: %s", error_local->message);
+			g_set_error (error, 1, 0, "failed to load xml: %s", error_local->message);
 			g_error_free (error_local);
 			goto out;
 		}
@@ -1954,8 +1986,7 @@ zif_store_remote_get_updates (ZifStore *store, GCancellable *cancellable, ZifCom
 	completion_local = zif_completion_get_child (completion);
 	packages = zif_store_get_packages (store_local, cancellable, completion_local, &error_local);
 	if (packages == NULL) {
-		if (error != NULL)
-			*error = g_error_new (1, 0, "failed to get local store: %s", error_local->message);
+		g_set_error (error, 1, 0, "failed to get local store: %s", error_local->message);
 		g_error_free (error_local);
 		goto out;
 	}
@@ -2024,8 +2055,7 @@ zif_store_remote_what_provides (ZifStore *store, const gchar *search, GCancellab
 	ret = zif_lock_is_locked (remote->priv->lock, NULL);
 	if (!ret) {
 		egg_warning ("not locked");
-		if (error != NULL)
-			*error = g_error_new (1, 0, "not locked");
+		g_set_error_literal (error, 1, 0, "not locked");
 		goto out;
 	}
 
@@ -2033,8 +2063,7 @@ zif_store_remote_what_provides (ZifStore *store, const gchar *search, GCancellab
 	if (!remote->priv->loaded_metadata) {
 		ret = zif_store_remote_load_metadata (remote, cancellable, completion, &error_local);
 		if (!ret) {
-			if (error != NULL)
-				*error = g_error_new (1, 0, "failed to load xml: %s", error_local->message);
+			g_set_error (error, 1, 0, "failed to load xml: %s", error_local->message);
 			g_error_free (error_local);
 			goto out;
 		}
@@ -2065,8 +2094,7 @@ zif_store_remote_search_file (ZifStore *store, const gchar *search, GCancellable
 	ret = zif_lock_is_locked (remote->priv->lock, NULL);
 	if (!ret) {
 		egg_warning ("not locked");
-		if (error != NULL)
-			*error = g_error_new (1, 0, "not locked");
+		g_set_error_literal (error, 1, 0, "not locked");
 		goto out;
 	}
 
@@ -2081,8 +2109,7 @@ zif_store_remote_search_file (ZifStore *store, const gchar *search, GCancellable
 		completion_local = zif_completion_get_child (completion);
 		ret = zif_store_remote_load_metadata (remote, cancellable, completion_local, &error_local);
 		if (!ret) {
-			if (error != NULL)
-				*error = g_error_new (1, 0, "failed to load xml: %s", error_local->message);
+			g_set_error (error, 1, 0, "failed to load xml: %s", error_local->message);
 			g_error_free (error_local);
 			goto out;
 		}
@@ -2095,8 +2122,7 @@ zif_store_remote_search_file (ZifStore *store, const gchar *search, GCancellable
 	completion_local = zif_completion_get_child (completion);
 	pkgids = zif_repo_md_filelists_search_file (ZIF_REPO_MD_FILELISTS (remote->priv->md_filelists), search, cancellable, completion_local, &error_local);
 	if (pkgids == NULL) {
-		if (error != NULL)
-			*error = g_error_new (1, 0, "failed to load get list of pkgids: %s", error_local->message);
+		g_set_error (error, 1, 0, "failed to load get list of pkgids: %s", error_local->message);
 		g_error_free (error_local);
 		goto out;
 	}
@@ -2113,8 +2139,7 @@ zif_store_remote_search_file (ZifStore *store, const gchar *search, GCancellable
 		completion_local = zif_completion_get_child (completion);
 		tmp = zif_repo_md_primary_search_pkgid (ZIF_REPO_MD_PRIMARY (remote->priv->md_primary), pkgid, cancellable, completion_local, &error_local);
 		if (tmp == NULL) {
-			if (error != NULL)
-				*error = g_error_new (1, 0, "failed to resolve pkgId to package: %s", error_local->message);
+			g_set_error (error, 1, 0, "failed to resolve pkgId to package: %s", error_local->message);
 			g_error_free (error_local);
 			/* free what we've collected already */
 			g_ptr_array_unref (array);
@@ -2162,8 +2187,7 @@ zif_store_remote_is_devel (ZifStoreRemote *store, GCancellable *cancellable, Zif
 	ret = zif_lock_is_locked (store->priv->lock, NULL);
 	if (!ret) {
 		egg_warning ("not locked");
-		if (error != NULL)
-			*error = g_error_new (1, 0, "not locked");
+		g_set_error_literal (error, 1, 0, "not locked");
 		goto out;
 	}
 
@@ -2171,8 +2195,7 @@ zif_store_remote_is_devel (ZifStoreRemote *store, GCancellable *cancellable, Zif
 	if (!store->priv->loaded) {
 		ret = zif_store_remote_load (ZIF_STORE (store), cancellable, completion, &error_local);
 		if (!ret) {
-			if (error != NULL)
-				*error = g_error_new (1, 0, "failed to load store file: %s", error_local->message);
+			g_set_error (error, 1, 0, "failed to load store file: %s", error_local->message);
 			g_error_free (error_local);
 			goto out;
 		}
@@ -2233,8 +2256,7 @@ zif_store_remote_get_name (ZifStoreRemote *store, GCancellable *cancellable, Zif
 	ret = zif_lock_is_locked (store->priv->lock, NULL);
 	if (!ret) {
 		egg_warning ("not locked");
-		if (error != NULL)
-			*error = g_error_new (1, 0, "not locked");
+		g_set_error_literal (error, 1, 0, "not locked");
 		goto out;
 	}
 
@@ -2242,8 +2264,7 @@ zif_store_remote_get_name (ZifStoreRemote *store, GCancellable *cancellable, Zif
 	if (!store->priv->loaded) {
 		ret = zif_store_remote_load (ZIF_STORE (store), cancellable, completion, &error_local);
 		if (!ret) {
-			if (error != NULL)
-				*error = g_error_new (1, 0, "failed to load store file: %s", error_local->message);
+			g_set_error (error, 1, 0, "failed to load store file: %s", error_local->message);
 			g_error_free (error_local);
 			goto out;
 		}
@@ -2276,8 +2297,7 @@ zif_store_remote_get_enabled (ZifStoreRemote *store, GCancellable *cancellable,
 	ret = zif_lock_is_locked (store->priv->lock, NULL);
 	if (!ret) {
 		egg_warning ("not locked");
-		if (error != NULL)
-			*error = g_error_new (1, 0, "not locked");
+		g_set_error_literal (error, 1, 0, "not locked");
 		goto out;
 	}
 
@@ -2285,8 +2305,7 @@ zif_store_remote_get_enabled (ZifStoreRemote *store, GCancellable *cancellable,
 	if (!store->priv->loaded) {
 		ret = zif_store_remote_load (ZIF_STORE (store), cancellable, completion, &error_local);
 		if (!ret) {
-			if (error != NULL)
-				*error = g_error_new (1, 0, "failed to load store file: %s", error_local->message);
+			g_set_error (error, 1, 0, "failed to load store file: %s", error_local->message);
 			g_error_free (error_local);
 			goto out;
 		}
@@ -2396,8 +2415,10 @@ zif_store_remote_class_init (ZifStoreRemoteClass *klass)
 static void
 zif_store_remote_init (ZifStoreRemote *store)
 {
-	GError *error = NULL;
 	gchar *cache_dir = NULL;
+	guint i;
+	GError *error = NULL;
+	ZifRepoMd *md;
 
 	store->priv = ZIF_STORE_REMOTE_GET_PRIVATE (store);
 	store->priv->loaded = FALSE;
@@ -2438,6 +2459,19 @@ zif_store_remote_init (ZifStoreRemote *store)
 		g_error_free (error);
 		goto out;
 	}
+
+	/* set MD type on each repo */
+	for (i=0; i<ZIF_REPO_MD_TYPE_UNKNOWN; i++) {
+		md = zif_store_remote_get_md_from_type (store, i);
+		if (md == NULL)
+			continue;
+
+		/* set parent reference */
+		zif_repo_md_set_store_remote (md, store);
+
+		/* set MD type */
+		zif_repo_md_set_mdtype (md, i);
+	}
 out:
 	g_free (cache_dir);
 }
diff --git a/backends/yum/libzif/zif-store.c b/backends/yum/libzif/zif-store.c
index 152fd37..dfd5b7f 100644
--- a/backends/yum/libzif/zif-store.c
+++ b/backends/yum/libzif/zif-store.c
@@ -61,8 +61,7 @@ zif_store_load (ZifStore *store, GCancellable *cancellable, ZifCompletion *compl
 
 	/* no support */
 	if (klass->load == NULL) {
-		if (error != NULL)
-			*error = g_error_new (1, 0, "operation cannot be performed on this store");
+		g_set_error_literal (error, 1, 0, "operation cannot be performed on this store");
 		return FALSE;
 	}
 
@@ -89,8 +88,7 @@ zif_store_clean (ZifStore *store, GCancellable *cancellable, ZifCompletion *comp
 
 	/* no support */
 	if (klass->clean == NULL) {
-		if (error != NULL)
-			*error = g_error_new (1, 0, "operation cannot be performed on this store");
+		g_set_error_literal (error, 1, 0, "operation cannot be performed on this store");
 		return FALSE;
 	}
 
@@ -118,8 +116,7 @@ zif_store_refresh (ZifStore *store, gboolean force, GCancellable *cancellable, Z
 
 	/* no support */
 	if (klass->refresh == NULL) {
-		if (error != NULL)
-			*error = g_error_new (1, 0, "operation cannot be performed on this store");
+		g_set_error_literal (error, 1, 0, "operation cannot be performed on this store");
 		return FALSE;
 	}
 
@@ -148,8 +145,7 @@ zif_store_search_name (ZifStore *store, const gchar *search, GCancellable *cance
 
 	/* no support */
 	if (klass->search_name == NULL) {
-		if (error != NULL)
-			*error = g_error_new (1, 0, "operation cannot be performed on this store");
+		g_set_error_literal (error, 1, 0, "operation cannot be performed on this store");
 		return FALSE;
 	}
 
@@ -178,8 +174,7 @@ zif_store_search_category (ZifStore *store, const gchar *search, GCancellable *c
 
 	/* no support */
 	if (klass->search_category == NULL) {
-		if (error != NULL)
-			*error = g_error_new (1, 0, "operation cannot be performed on this store");
+		g_set_error_literal (error, 1, 0, "operation cannot be performed on this store");
 		return FALSE;
 	}
 
@@ -208,8 +203,7 @@ zif_store_search_details (ZifStore *store, const gchar *search, GCancellable *ca
 
 	/* no support */
 	if (klass->search_details == NULL) {
-		if (error != NULL)
-			*error = g_error_new (1, 0, "operation cannot be performed on this store");
+		g_set_error_literal (error, 1, 0, "operation cannot be performed on this store");
 		return FALSE;
 	}
 
@@ -238,8 +232,7 @@ zif_store_search_group (ZifStore *store, const gchar *search, GCancellable *canc
 
 	/* no support */
 	if (klass->search_group == NULL) {
-		if (error != NULL)
-			*error = g_error_new (1, 0, "operation cannot be performed on this store");
+		g_set_error_literal (error, 1, 0, "operation cannot be performed on this store");
 		return FALSE;
 	}
 
@@ -268,8 +261,7 @@ zif_store_search_file (ZifStore *store, const gchar *search, GCancellable *cance
 
 	/* no support */
 	if (klass->search_file == NULL) {
-		if (error != NULL)
-			*error = g_error_new (1, 0, "operation cannot be performed on this store");
+		g_set_error_literal (error, 1, 0, "operation cannot be performed on this store");
 		return FALSE;
 	}
 
@@ -298,8 +290,7 @@ zif_store_resolve (ZifStore *store, const gchar *search, GCancellable *cancellab
 
 	/* no support */
 	if (klass->resolve == NULL) {
-		if (error != NULL)
-			*error = g_error_new (1, 0, "operation cannot be performed on this store");
+		g_set_error_literal (error, 1, 0, "operation cannot be performed on this store");
 		return FALSE;
 	}
 
@@ -328,8 +319,7 @@ zif_store_what_provides (ZifStore *store, const gchar *search, GCancellable *can
 
 	/* no support */
 	if (klass->search_name == NULL) {
-		if (error != NULL)
-			*error = g_error_new (1, 0, "operation cannot be performed on this store");
+		g_set_error_literal (error, 1, 0, "operation cannot be performed on this store");
 		return FALSE;
 	}
 
@@ -356,8 +346,7 @@ zif_store_get_packages (ZifStore *store, GCancellable *cancellable, ZifCompletio
 
 	/* no support */
 	if (klass->get_packages == NULL) {
-		if (error != NULL)
-			*error = g_error_new (1, 0, "operation cannot be performed on this store");
+		g_set_error_literal (error, 1, 0, "operation cannot be performed on this store");
 		return FALSE;
 	}
 
@@ -384,8 +373,7 @@ zif_store_get_updates (ZifStore *store, GCancellable *cancellable, ZifCompletion
 
 	/* no support */
 	if (klass->get_updates == NULL) {
-		if (error != NULL)
-			*error = g_error_new (1, 0, "operation cannot be performed on this store");
+		g_set_error_literal (error, 1, 0, "operation cannot be performed on this store");
 		return FALSE;
 	}
 
@@ -414,8 +402,7 @@ zif_store_find_package (ZifStore *store, const gchar *package_id, GCancellable *
 
 	/* no support */
 	if (klass->find_package == NULL) {
-		if (error != NULL)
-			*error = g_error_new (1, 0, "operation cannot be performed on this store");
+		g_set_error_literal (error, 1, 0, "operation cannot be performed on this store");
 		return FALSE;
 	}
 
@@ -442,8 +429,7 @@ zif_store_get_categories (ZifStore *store, GCancellable *cancellable, ZifComplet
 
 	/* no support */
 	if (klass->get_categories == NULL) {
-		if (error != NULL)
-			*error = g_error_new (1, 0, "operation cannot be performed on this store");
+		g_set_error_literal (error, 1, 0, "operation cannot be performed on this store");
 		return FALSE;
 	}
 
diff --git a/backends/yum/libzif/zif-utils.c b/backends/yum/libzif/zif-utils.c
index de2eaa7..9630cfc 100644
--- a/backends/yum/libzif/zif-utils.c
+++ b/backends/yum/libzif/zif-utils.c
@@ -269,16 +269,14 @@ zif_file_decompress_zlib (const gchar *in, const gchar *out, GCancellable *cance
 	/* open file for reading */
 	f_in = gzopen (in, "rb");
 	if (f_in == NULL) {
-		if (error != NULL)
-			*error = g_error_new (1, 0, "cannot open %s for reading", in);
+		g_set_error (error, 1, 0, "cannot open %s for reading", in);
 		goto out;
 	}
 
 	/* open file for writing */
 	f_out = fopen (out, "w");
 	if (f_out == NULL) {
-		if (error != NULL)
-			*error = g_error_new (1, 0, "cannot open %s for writing", out);
+		g_set_error (error, 1, 0, "cannot open %s for writing", out);
 		goto out;
 	}
 
@@ -291,24 +289,21 @@ zif_file_decompress_zlib (const gchar *in, const gchar *out, GCancellable *cance
 
 		/* error */
 		if (size < 0) {
-			if (error != NULL)
-				*error = g_error_new (1, 0, "failed read");
+			g_set_error_literal (error, 1, 0, "failed read");
 			goto out;
 		}
 
 		/* write data */
 		written = fwrite (buf, 1, size, f_out);
 		if (written != size) {
-			if (error != NULL)
-				*error = g_error_new (1, 0, "only wrote %i/%i bytes", written, size);
+			g_set_error (error, 1, 0, "only wrote %i/%i bytes", written, size);
 			goto out;
 		}
 
 		/* is cancelled */
 		ret = !g_cancellable_is_cancelled (cancellable);
 		if (!ret) {
-			if (error != NULL)
-				*error = g_error_new (1, 0, "cancelled");
+			g_set_error_literal (error, 1, 0, "cancelled");
 			goto out;
 		}
 	}
@@ -344,24 +339,21 @@ zif_file_decompress_bz2 (const gchar *in, const gchar *out, GCancellable *cancel
 	/* open file for reading */
 	f_in = fopen (in, "r");
 	if (f_in == NULL) {
-		if (error != NULL)
-			*error = g_error_new (1, 0, "cannot open %s for reading", in);
+		g_set_error (error, 1, 0, "cannot open %s for reading", in);
 		goto out;
 	}
 
 	/* open file for writing */
 	f_out = fopen (out, "w");
 	if (f_out == NULL) {
-		if (error != NULL)
-			*error = g_error_new (1, 0, "cannot open %s for writing", out);
+		g_set_error (error, 1, 0, "cannot open %s for writing", out);
 		goto out;
 	}
 
 	/* read in file */
 	b = BZ2_bzReadOpen (&bzerror, f_in, 0, 0, NULL, 0);
 	if (bzerror != BZ_OK) {
-		if (error != NULL)
-			*error = g_error_new (1, 0, "cannot open %s for bz2 reading", in);
+		g_set_error (error, 1, 0, "cannot open %s for bz2 reading", in);
 		goto out;
 	}
 
@@ -370,32 +362,28 @@ zif_file_decompress_bz2 (const gchar *in, const gchar *out, GCancellable *cancel
 		/* read data */
 		size = BZ2_bzRead (&bzerror, b, buf, ZIF_BUFFER_SIZE);
 		if (bzerror != BZ_OK && bzerror != BZ_STREAM_END) {
-			if (error != NULL)
-				*error = g_error_new (1, 0, "failed to decompress");
+			g_set_error_literal (error, 1, 0, "failed to decompress");
 			goto out;
 		}
 
 		/* write data */
 		written = fwrite (buf, 1, size, f_out);
 		if (written != size) {
-			if (error != NULL)
-				*error = g_error_new (1, 0, "only wrote %i/%i bytes", written, size);
+			g_set_error (error, 1, 0, "only wrote %i/%i bytes", written, size);
 			goto out;
 		}
 
 		/* is cancelled */
 		ret = !g_cancellable_is_cancelled (cancellable);
 		if (!ret) {
-			if (error != NULL)
-				*error = g_error_new (1, 0, "cancelled");
+			g_set_error_literal (error, 1, 0, "cancelled");
 			goto out;
 		}
 	}
 
 	/* failed to read */
 	if (bzerror != BZ_STREAM_END) {
-		if (error != NULL)
-			*error = g_error_new (1, 0, "did not decompress file: %s", in);
+		g_set_error (error, 1, 0, "did not decompress file: %s", in);
 		goto out;
 	}
 
@@ -444,8 +432,7 @@ zif_file_decompress (const gchar *in, const gchar *out, GCancellable *cancellabl
 	}
 
 	/* no support */
-	if (error != NULL)
-		*error = g_error_new (1, 0, "no support to decompress file: %s", in);
+	g_set_error (error, 1, 0, "no support to decompress file: %s", in);
 out:
 	return ret;
 }
@@ -477,7 +464,7 @@ zif_file_untar (const gchar *filename, const gchar *directory, GError **error)
 	/* save the PWD as we chdir to extract */
 	retcwd = getcwd (buf, PATH_MAX);
 	if (retcwd == NULL) {
-		*error = g_error_new (1, 0, "failed to get cwd");
+		g_set_error_literal (error, 1, 0, "failed to get cwd");
 		goto out;
 	}
 
@@ -489,14 +476,14 @@ zif_file_untar (const gchar *filename, const gchar *directory, GError **error)
 	/* open the tar file */
 	r = archive_read_open_file (arch, filename, ZIF_BUFFER_SIZE);
 	if (r) {
-		*error = g_error_new (1, 0, "cannot open: %s", archive_error_string (arch));
+		g_set_error (error, 1, 0, "cannot open: %s", archive_error_string (arch));
 		goto out;
 	}
 
 	/* switch to our destination directory */
 	retval = chdir (directory);
 	if (retval != 0) {
-		*error = g_error_new (1, 0, "failed chdir to %s", directory);
+		g_set_error (error, 1, 0, "failed chdir to %s", directory);
 		goto out;
 	}
 
@@ -506,12 +493,12 @@ zif_file_untar (const gchar *filename, const gchar *directory, GError **error)
 		if (r == ARCHIVE_EOF)
 			break;
 		if (r != ARCHIVE_OK) {
-			*error = g_error_new (1, 0, "cannot read header: %s", archive_error_string (arch));
+			g_set_error (error, 1, 0, "cannot read header: %s", archive_error_string (arch));
 			goto out;
 		}
 		r = archive_read_extract (arch, entry, 0);
 		if (r != ARCHIVE_OK) {
-			*error = g_error_new (1, 0, "cannot extract: %s", archive_error_string (arch));
+			g_set_error (error, 1, 0, "cannot extract: %s", archive_error_string (arch));
 			goto out;
 		}
 	}
commit 7724e79be8767b35da5965a5202fc7f9e7d51baf
Author: Richard Hughes <richard at hughsie.com>
Date:   Tue Mar 9 16:15:28 2010 +0000

    yum: ensure we trigger the GCancellable when we're doing a transaction cancel

diff --git a/backends/yum/pk-backend-yum.c b/backends/yum/pk-backend-yum.c
index 52c599f..dfedd4b 100644
--- a/backends/yum/pk-backend-yum.c
+++ b/backends/yum/pk-backend-yum.c
@@ -362,6 +362,9 @@ backend_get_mime_types (PkBackend *backend)
 static void
 backend_cancel (PkBackend *backend)
 {
+	/* try to cancel the thread first */
+	g_cancellable_cancel (priv->cancellable);
+
 	/* this feels bad... */
 	pk_backend_spawn_kill (priv->spawn);
 }
commit fe50bfd14367131e8193b8a67e1acf3622721e6a
Author: Richard Hughes <richard at hughsie.com>
Date:   Tue Mar 9 15:32:00 2010 +0000

    yum: Fix up the LXDE and Moblin groups. Fixes rh#571775

diff --git a/backends/yum/yum-comps-groups.conf b/backends/yum/yum-comps-groups.conf
index 248c388..e068702 100644
--- a/backends/yum/yum-comps-groups.conf
+++ b/backends/yum/yum-comps-groups.conf
@@ -3,7 +3,7 @@ admin-tools=base-system;system-tools,base-system;admin-tools,rpmfusion_free;hard
 desktop-gnome=rpmfusion_free;gnome-desktop,desktops;gnome-desktop
 desktop-kde=desktops;kde-desktop,rpmfusion_free;kde-desktop
 desktop-xfce=desktops;xfce-desktop
-desktop-other=desktops;window-managers,desktops;sugar-desktop,desktops;lxde-desktop;moblin-desktop
+desktop-other=desktops;window-managers,desktops;sugar-desktop,desktops;lxde-desktop,desktops;moblin-desktop
 education=apps;education,development;electronic-lab
 fonts=base-system;fonts,base-system;legacy-fonts
 games=apps;games,rpmfusion_free;games,rpmfusion_nonfree;games
commit 72c0d548a9ac828e28a3702a23134d412a7903f4
Author: Richard Hughes <richard at hughsie.com>
Date:   Tue Mar 9 11:23:46 2010 +0000

    yum: Use Zif for getting the category lists
    
    This ensures we don't do network IO just for reading a few XML files.
    10x speedup compared to forking yum.

diff --git a/backends/yum/libzif/zif-repo-md-comps.c b/backends/yum/libzif/zif-repo-md-comps.c
index bed4d8a..cac2ba6 100644
--- a/backends/yum/libzif/zif-repo-md-comps.c
+++ b/backends/yum/libzif/zif-repo-md-comps.c
@@ -480,6 +480,37 @@ out:
 }
 
 /**
+ * zif_repo_md_comps_category_set_icon:
+ *
+ * Check the icon exists, otherwise fallback to the parent ID, and then
+ * something sane.
+ **/
+static void
+zif_repo_md_comps_category_set_icon (PkCategory *category)
+{
+	const gchar *icon;
+	GString *filename = g_string_new ("");
+
+	/* try the proper group icon */
+	icon = pk_category_get_id (category);
+	g_string_printf (filename, "/usr/share/pixmaps/comps/%s.png", icon);
+	if (g_file_test (filename->str, G_FILE_TEST_EXISTS))
+		goto out;
+
+	/* fall back to parent icon */
+	icon = pk_category_get_parent_id (category);
+	g_string_printf (filename, "/usr/share/pixmaps/comps/%s.png", icon);
+	if (g_file_test (filename->str, G_FILE_TEST_EXISTS))
+		goto out;
+
+	/* fall back to the missing icon */
+	icon = "image-missing";
+out:
+	pk_category_set_icon (category, icon);
+	g_string_free (filename, TRUE);
+}
+
+/**
  * zif_repo_md_comps_get_categories:
  * @md: the #ZifRepoMdComps object
  * @cancellable: the %GCancellable, or %NULL
@@ -488,7 +519,7 @@ out:
  *
  * Gets the available list of categories.
  *
- * Return value: %PkCategory array of categories
+ * Return value: %PkCategory array of categories, with parent_id set to %NULL
  **/
 GPtrArray *
 zif_repo_md_comps_get_categories (ZifRepoMdComps *md, GCancellable *cancellable,
@@ -524,6 +555,7 @@ zif_repo_md_comps_get_categories (ZifRepoMdComps *md, GCancellable *cancellable,
 		pk_category_set_id (category, data->id);
 		pk_category_set_name (category, data->name);
 		pk_category_set_summary (category, data->description);
+		zif_repo_md_comps_category_set_icon (category);
 		g_ptr_array_add (array, category);
 	}
 out:
@@ -608,8 +640,13 @@ zif_repo_md_comps_get_groups_for_category (ZifRepoMdComps *md, const gchar *cate
 				id = g_ptr_array_index (data->grouplist, j);
 				/* find group matching group_id */
 				category = zif_repo_md_comps_get_category_for_group (md, id);
-				if (category != NULL)
-					g_ptr_array_add (array, category);
+				if (category == NULL)
+					continue;
+
+				/* add */
+				pk_category_set_parent_id (category, category_id);
+				zif_repo_md_comps_category_set_icon (category);
+				g_ptr_array_add (array, category);
 			}
 			break;
 		}
diff --git a/backends/yum/libzif/zif-sack.c b/backends/yum/libzif/zif-sack.c
index 090bb7d..53a5c23 100644
--- a/backends/yum/libzif/zif-sack.c
+++ b/backends/yum/libzif/zif-sack.c
@@ -721,8 +721,8 @@ zif_sack_get_categories (ZifSack *sack, GCancellable *cancellable, ZifCompletion
 				g_object_unref (obj_tmp);
 				g_ptr_array_remove_index (array, j);
 			}
-			g_free (parent_id);
-			g_free (cat_id);
+			g_free (parent_id_tmp);
+			g_free (cat_id_tmp);
 		}
 		g_free (parent_id);
 		g_free (cat_id);
diff --git a/backends/yum/libzif/zif-store-remote.c b/backends/yum/libzif/zif-store-remote.c
index e10f7d0..1278cb5 100644
--- a/backends/yum/libzif/zif-store-remote.c
+++ b/backends/yum/libzif/zif-store-remote.c
@@ -1879,13 +1879,7 @@ zif_store_remote_get_categories (ZifStore *store, GCancellable *cancellable, Zif
 			/* second, add the groups belonging to this parent */
 			for (j=0; j<array_groups->len; j++) {
 				group = g_ptr_array_index (array_groups, j);
-				category_tmp = pk_category_new ();
-				g_object_set (category_tmp,
-					      "parent-id", pk_category_get_id (category),
-					      "cat-id", pk_category_get_id (group),
-					      "name", pk_category_get_name (group),
-					      "summary", pk_category_get_summary (group),
-					      NULL);
+				category_tmp = g_object_ref (group);
 				g_ptr_array_add (array, category_tmp);
 			}
 		}
diff --git a/backends/yum/pk-backend-yum.c b/backends/yum/pk-backend-yum.c
index 7fe957b..52c599f 100644
--- a/backends/yum/pk-backend-yum.c
+++ b/backends/yum/pk-backend-yum.c
@@ -822,6 +822,7 @@ backend_get_repo_list_thread (PkBackend *backend)
 	}
 
 	pk_backend_set_status (backend, PK_STATUS_ENUM_QUERY);
+	pk_backend_set_percentage (backend, 0);
 
 	/* setup completion */
 	zif_completion_reset (priv->completion);
@@ -908,6 +909,7 @@ backend_repo_enable_thread (PkBackend *backend)
 	}
 
 	pk_backend_set_status (backend, PK_STATUS_ENUM_QUERY);
+	pk_backend_set_percentage (backend, 0);
 
 	/* find the right repo */
 	repo = zif_repos_get_store (priv->repos, repo_id, priv->cancellable, priv->completion, &error);
@@ -982,13 +984,229 @@ backend_what_provides (PkBackend *backend, PkBitfield filters, PkProvidesEnum pr
 	g_free (search);
 }
 
+#define PK_ROLE_ENUM_SEARCH_CATEGORY	(PK_ROLE_ENUM_UNKNOWN + 1)
+
+/**
+ * backend_repos_search:
+ **/
+static GPtrArray *
+backend_repos_search (PkBackend *backend, GPtrArray *stores, PkRoleEnum role, const gchar *search, ZifCompletion *completion, GError **error)
+{
+	guint i, j;
+	GPtrArray *array = NULL;
+	GPtrArray *part;
+	ZifStore *store;
+	ZifPackage *package;
+	GError *error_local = NULL;
+	ZifCompletion *completion_local = NULL;
+
+	/* nothing to do */
+	if (stores->len == 0) {
+		egg_warning ("nothing to do");
+		if (error != NULL)
+			*error = g_error_new (1, 0, "nothing to do as no stores");
+		goto out;
+	}
+
+	/* set number of stores */
+	zif_completion_set_number_steps (completion, stores->len);
+
+	/* do each one */
+	array = g_ptr_array_new_with_free_func ((GDestroyNotify) g_object_unref);
+	for (i=0; i<stores->len; i++) {
+		store = g_ptr_array_index (stores, i);
+
+		/* create a chain of completions */
+		completion_local = zif_completion_get_child (completion);
+
+		/* get results for this store */
+		if (role == PK_ROLE_ENUM_RESOLVE)
+			part = zif_store_resolve (store, search, priv->cancellable, completion_local, &error_local);
+		else if (role == PK_ROLE_ENUM_SEARCH_NAME)
+			part = zif_store_search_name (store, search, priv->cancellable, completion_local, &error_local);
+		else if (role == PK_ROLE_ENUM_SEARCH_DETAILS)
+			part = zif_store_search_details (store, search, priv->cancellable, completion_local, &error_local);
+		else if (role == PK_ROLE_ENUM_SEARCH_GROUP)
+			part = zif_store_search_group (store, search, priv->cancellable, completion_local, &error_local);
+		else if (role == PK_ROLE_ENUM_SEARCH_CATEGORY)
+			part = zif_store_search_category (store, search, priv->cancellable, completion_local, &error_local);
+		else if (role == PK_ROLE_ENUM_SEARCH_FILE)
+			part = zif_store_search_file (store, search, priv->cancellable, completion_local, &error_local);
+		else if (role == PK_ROLE_ENUM_GET_PACKAGES)
+			part = zif_store_get_packages (store, priv->cancellable, completion_local, &error_local);
+		else if (role == PK_ROLE_ENUM_GET_UPDATES)
+			part = zif_store_get_updates (store, priv->cancellable, completion_local, &error_local);
+		else if (role == PK_ROLE_ENUM_WHAT_PROVIDES)
+			part = zif_store_what_provides (store, search, priv->cancellable, completion_local, &error_local);
+		else if (role == PK_ROLE_ENUM_GET_CATEGORIES)
+			part = zif_store_get_categories (store, priv->cancellable, completion_local, &error_local);
+		else
+			egg_error ("internal error: %s", pk_role_enum_to_text (role));
+		if (part == NULL) {
+			/* emit a warning, this isn't fatal */
+			pk_backend_message (backend, PK_MESSAGE_ENUM_BROKEN_MIRROR, "failed to %s for repo %s: %s",
+					    pk_role_enum_to_text (role),
+					    zif_store_get_id (store),
+					    error_local->message);
+			g_clear_error (&error_local);
+			zif_completion_done (completion);
+			continue;
+		}
+
+		for (j=0; j<part->len; j++) {
+			package = g_ptr_array_index (part, j);
+			g_ptr_array_add (array, g_object_ref (package));
+		}
+		g_ptr_array_unref (part);
+
+		/* this section done */
+		zif_completion_done (completion);
+	}
+out:
+	return array;
+}
+
+/**
+ * backend_get_unique_categories:
+ **/
+static GPtrArray *
+backend_get_unique_categories (PkBackend *backend, GPtrArray *stores, ZifCompletion *completion, GError **error)
+{
+	guint i, j;
+	GPtrArray *array;
+	PkCategory *obj;
+	PkCategory *obj_tmp;
+	gchar *parent_id;
+	gchar *parent_id_tmp;
+	gchar *cat_id;
+	gchar *cat_id_tmp;
+
+	/* get all results from all repos */
+	array = backend_repos_search (backend, stores, PK_ROLE_ENUM_GET_CATEGORIES, NULL, completion, error);
+	if (array == NULL)
+		goto out;
+
+	/* remove duplicate parents and groups */
+	for (i=0; i<array->len; i++) {
+		obj = g_ptr_array_index (array, i);
+		g_object_get (obj,
+			      "parent-id", &parent_id,
+			      "cat-id", &cat_id,
+			      NULL);
+		for (j=0; j<array->len; j++) {
+			if (i == j)
+				continue;
+			obj_tmp = g_ptr_array_index (array, j);
+			g_object_get (obj_tmp,
+				      "parent-id", &parent_id_tmp,
+				      "cat-id", &cat_id_tmp,
+				      NULL);
+			if (g_strcmp0 (parent_id_tmp, parent_id) == 0 &&
+			    g_strcmp0 (cat_id_tmp, cat_id) == 0) {
+				egg_warning ("duplicate %s-%s", parent_id, cat_id);
+				g_object_unref (obj_tmp);
+				g_ptr_array_remove_index (array, j);
+			}
+			g_free (parent_id_tmp);
+			g_free (cat_id_tmp);
+		}
+		g_free (parent_id);
+		g_free (cat_id);
+	}
+out:
+	return array;
+}
+
+/**
+ * backend_get_categories_thread:
+ */
+static gboolean
+backend_get_categories_thread (PkBackend *backend)
+{
+	gboolean ret;
+	guint i;
+	GPtrArray *array = NULL;
+	GPtrArray *stores = NULL;
+	PkCategory *cat;
+	gchar *cat_id;
+
+	ZifCompletion *completion_local;
+	GError *error = NULL;
+
+	/* get lock */
+	ret = backend_get_lock (backend);
+	if (!ret) {
+		egg_warning ("failed to get lock");
+		goto out;
+	}
+
+	/* setup completion */
+	zif_completion_reset (priv->completion);
+	zif_completion_set_number_steps (priv->completion, 3);
+
+	pk_backend_set_status (backend, PK_STATUS_ENUM_QUERY);
+	pk_backend_set_percentage (backend, 0);
+
+	/* get enabled repos */
+	completion_local = zif_completion_get_child (priv->completion);
+	stores = zif_repos_get_stores_enabled (priv->repos, priv->cancellable, completion_local, &error);
+	if (stores == NULL) {
+		pk_backend_error_code (backend, PK_ERROR_ENUM_REPO_CONFIGURATION_ERROR, "failed to add remote stores: %s", error->message);
+		g_error_free (error);
+		goto out;
+	}
+
+	/* this section done */
+	zif_completion_done (priv->completion);
+
+	/* get sorted list of unique categories */
+	completion_local = zif_completion_get_child (priv->completion);
+	array = backend_get_unique_categories (backend, stores, completion_local, &error);
+	if (array == NULL) {
+		pk_backend_error_code (backend, PK_ERROR_ENUM_GROUP_LIST_INVALID, "failed to add get categories: %s", error->message);
+		g_error_free (error);
+		goto out;
+	}
+
+	/* this section done */
+	zif_completion_done (priv->completion);
+
+	/* emit each cat obj */
+	for (i=0; i<array->len; i++) {
+		cat = g_ptr_array_index (array, i);
+		/* FIXME: in the yum backend, we signify a group with a '@' prefix */
+		if (pk_category_get_parent_id (cat) != NULL)
+			cat_id = g_strdup_printf ("@%s", pk_category_get_id (cat));
+		else
+			cat_id = g_strdup (pk_category_get_id (cat));
+		pk_backend_category (backend,
+				     pk_category_get_parent_id (cat),
+				     cat_id,
+				     pk_category_get_name (cat),
+				     pk_category_get_summary (cat),
+				     pk_category_get_icon (cat));
+		g_free (cat_id);
+	}
+
+	/* this section done */
+	zif_completion_done (priv->completion);
+out:
+	backend_unlock (backend);
+	pk_backend_finished (backend);
+	if (array != NULL)
+		g_ptr_array_unref (array);
+	if (stores != NULL)
+		g_ptr_array_unref (stores);
+	return TRUE;
+}
+
 /**
  * pk_backend_get_categories:
  */
 static void
 backend_get_categories (PkBackend *backend)
 {
-	pk_backend_spawn_helper (priv->spawn, "yumBackend.py", "get-categories", NULL);
+	pk_backend_thread_create (backend, backend_get_categories_thread);
 }
 
 /**
diff --git a/backends/yum/yumBackend.py b/backends/yum/yumBackend.py
index fb4e09b..e0c1c68 100755
--- a/backends/yum/yumBackend.py
+++ b/backends/yum/yumBackend.py
@@ -790,72 +790,6 @@ class PackageKitYumBackend(PackageKitBaseBackend, PackagekitPackage):
                     package_list = pkgfilter.post_process()
                     self._show_package_list(package_list)
 
-    def get_categories(self):
-        '''
-        Implement the get-categories functionality
-        '''
-        self.status(STATUS_QUERY)
-        self.allow_cancel(True)
-        cats = []
-        try:
-            cats = self.yumbase.comps.categories
-        except yum.Errors.RepoError, e:
-            self.error(ERROR_NO_CACHE, "failed to get comps list: %s" %_to_unicode(e), exit=False)
-        except Exception, e:
-            self.error(ERROR_INTERNAL_ERROR, _format_str(traceback.format_exc()))
-        else:
-            if len(cats) == 0:
-                self.error(ERROR_GROUP_LIST_INVALID, "no comps categories", exit=False)
-                return
-            for cat in cats:
-                cat_id = cat.categoryid
-                # yum >= 3.2.10
-                # name = cat.nameByLang(self.lang)
-                # summary = cat.descriptionByLang(self.lang)
-                name = cat.name
-                summary = cat.description
-                fn = "/usr/share/pixmaps/comps/%s.png" % cat_id
-                if os.access(fn, os.R_OK):
-                    icon = cat_id
-                else:
-                    icon = "image-missing"
-                self.category("", cat_id, name, summary, icon)
-                self._get_groups(cat_id)
-
-    def _get_groups(self, cat_id):
-        '''
-        Implement the get-collections functionality
-        '''
-        self.status(STATUS_QUERY)
-        self.allow_cancel(True)
-        if cat_id:
-            cats = [cat_id]
-        else:
-            cats =  [cat.categoryid for cat in self.yumbase.comps.categories]
-        for cat in cats:
-            grps = []
-            for grp_id in self.comps.get_groups(cat):
-                try:
-                    grp = self.yumbase.comps.return_group(grp_id)
-                except Exception, e:
-                    self.error(ERROR_INTERNAL_ERROR, _format_str(traceback.format_exc()))
-                if grp:
-                    grps.append(grp)
-            for grp in sorted(grps):
-                grp_id = grp.groupid
-                cat_id_name = "@%s" % (grp_id)
-                name = grp.nameByLang(self.lang)
-                summary = grp.descriptionByLang(self.lang)
-                icon = "image-missing"
-                fn = "/usr/share/pixmaps/comps/%s.png" % grp_id
-                if os.access(fn, os.R_OK):
-                    icon = grp_id
-                else:
-                    fn = "/usr/share/pixmaps/comps/%s.png" % cat_id
-                    if os.access(fn, os.R_OK):
-                        icon = cat_id
-                self.category(cat, cat_id_name, name, summary, icon)
-
     def download_packages(self, directory, package_ids):
         '''
         Implement the download-packages functionality
commit 95d8a0d83d7516272679ece00cc35698ccfbdcf4
Author: Richard Hughes <richard at hughsie.com>
Date:   Tue Mar 9 09:50:54 2010 +0000

    yum: Use Zif for enabling and disabling repos
    
    This ensures we don't do network IO just for reading a few repo files.
    17x speedup compared to forking yum.

diff --git a/backends/yum/pk-backend-yum.c b/backends/yum/pk-backend-yum.c
index 26ba3b2..7fe957b 100644
--- a/backends/yum/pk-backend-yum.c
+++ b/backends/yum/pk-backend-yum.c
@@ -888,25 +888,81 @@ backend_get_repo_list (PkBackend *backend, PkBitfield filters)
 }
 
 /**
+ * backend_repo_enable_thread:
+ */
+static gboolean
+backend_repo_enable_thread (PkBackend *backend)
+{
+	ZifStoreRemote *repo = NULL;
+	gboolean ret;
+	GError *error = NULL;
+	gchar *warning = NULL;
+	gboolean enabled = pk_backend_get_bool (backend, "enabled");
+	const gchar *repo_id = pk_backend_get_string (backend, "repo_id");
+
+	/* get lock */
+	ret = backend_get_lock (backend);
+	if (!ret) {
+		egg_warning ("failed to get lock");
+		goto out;
+	}
+
+	pk_backend_set_status (backend, PK_STATUS_ENUM_QUERY);
+
+	/* find the right repo */
+	repo = zif_repos_get_store (priv->repos, repo_id, priv->cancellable, priv->completion, &error);
+	if (repo == NULL) {
+		pk_backend_error_code (backend, PK_ERROR_ENUM_REPO_NOT_FOUND, "failed to find repo: %s", error->message);
+		g_error_free (error);
+		goto out;
+	}
+
+	/* set the state */
+	ret = zif_store_remote_set_enabled (repo, enabled, &error);
+	if (!ret) {
+		pk_backend_error_code (backend, PK_ERROR_ENUM_CANNOT_DISABLE_REPOSITORY, "failed to set enable: %s", error->message);
+		g_error_free (error);
+		goto out;
+	}
+
+	/* warn if rawhide */
+	if (g_strstr_len (repo_id, -1, "rawhide") != NULL) {
+		warning = g_strdup_printf ("These packages are untested and still under development."
+					   "This repository is used for development of new releases.\n\n"
+					   "This repository can see significant daily turnover and major "
+					   "functionality changes which cause unexpected problems with "
+					   "other development packages.\n"
+					   "Please use these packages if you want to work with the "
+					   "Fedora developers by testing these new development packages.\n\n"
+					   "If this is not correct, please disable the %s software source.", repo_id);
+		pk_backend_message (backend, PK_MESSAGE_ENUM_REPO_FOR_DEVELOPERS_ONLY, warning);
+	}
+out:
+	backend_unlock (backend);
+	pk_backend_finished (backend);
+	g_free (warning);
+	if (repo != NULL)
+		g_object_unref (repo);
+	return TRUE;
+}
+
+/**
  * pk_backend_repo_enable:
  */
 static void
-backend_repo_enable (PkBackend *backend, const gchar *rid, gboolean enabled)
+backend_repo_enable (PkBackend *backend, const gchar *repo_id, gboolean enabled)
 {
-	if (enabled == TRUE) {
-		pk_backend_spawn_helper (priv->spawn, "yumBackend.py", "repo-enable", rid, "true", NULL);
-	} else {
-		pk_backend_spawn_helper (priv->spawn, "yumBackend.py", "repo-enable", rid, "false", NULL);
-	}
+	pk_backend_thread_create (backend, backend_repo_enable_thread);
 }
 
 /**
  * pk_backend_repo_set_data:
  */
 static void
-backend_repo_set_data (PkBackend *backend, const gchar *rid, const gchar *parameter, const gchar *value)
+backend_repo_set_data (PkBackend *backend, const gchar *repo_id, const gchar *parameter, const gchar *value)
 {
-	pk_backend_spawn_helper (priv->spawn, "yumBackend.py", "repo-set-data", rid, parameter, value, NULL);
+	/* no operation */
+	pk_backend_finished (backend);
 }
 
 /**
diff --git a/backends/yum/yumBackend.py b/backends/yum/yumBackend.py
index ed33d9a..fb4e09b 100755
--- a/backends/yum/yumBackend.py
+++ b/backends/yum/yumBackend.py
@@ -2408,40 +2408,6 @@ class PackageKitYumBackend(PackageKitBaseBackend, PackagekitPackage):
         package_list = pkgfilter.post_process()
         self._show_package_list(package_list)
 
-    def repo_enable(self, repoid, enable):
-        '''
-        Implement the repo-enable functionality
-        '''
-        try:
-            self._check_init()
-        except PkError, e:
-            self.error(e.code, e.details, exit=False)
-            return
-        self.yumbase.conf.cache = 0 # Allow new files
-        self.status(STATUS_INFO)
-        try:
-            repo = self.yumbase.repos.getRepo(repoid)
-            if not enable:
-                if repo.isEnabled():
-                    repo.disablePersistent()
-            else:
-                if not repo.isEnabled():
-                    repo.enablePersistent()
-                    if repoid.find ("rawhide") != -1:
-                        warning = "These packages are untested and still under development." \
-                                  "This repository is used for development of new releases.\n\n" \
-                                  "This repository can see significant daily turnover and major " \
-                                  "functionality changes which cause unexpected problems with " \
-                                  "other development packages.\n" \
-                                  "Please use these packages if you want to work with the " \
-                                  "Fedora developers by testing these new development packages.\n\n" \
-                                  "If this is not correct, please disable the %s software source." % repoid
-                        self.message(MESSAGE_REPO_FOR_DEVELOPERS_ONLY, warning.replace("\n", ";"))
-        except yum.Errors.RepoError, e:
-            self.error(ERROR_REPO_NOT_FOUND, _to_unicode(e))
-        except Exception, e:
-            self.error(ERROR_INTERNAL_ERROR, _format_str(traceback.format_exc()))
-
     def _get_obsoleted(self, name):
         try:
             # make sure yum doesn't explode in some internal fit of rage
commit 690662d6ce5c393e60eb4f8bcf3ad8bf96772816
Author: Richard Hughes <richard at hughsie.com>
Date:   Tue Mar 9 09:38:48 2010 +0000

    yum: Use Zif for getting the repo list (2x speedup)

diff --git a/backends/yum/libzif/zif-repos.c b/backends/yum/libzif/zif-repos.c
index d082c49..dfc5605 100644
--- a/backends/yum/libzif/zif-repos.c
+++ b/backends/yum/libzif/zif-repos.c
@@ -291,9 +291,7 @@ zif_repos_get_stores (ZifRepos *repos, GCancellable *cancellable, ZifCompletion
 {
 	GPtrArray *array = NULL;
 	GError *error_local;
-	ZifStoreRemote *store;
 	gboolean ret;
-	guint i;
 
 	g_return_val_if_fail (ZIF_IS_REPOS (repos), FALSE);
 
@@ -309,11 +307,7 @@ zif_repos_get_stores (ZifRepos *repos, GCancellable *cancellable, ZifCompletion
 	}
 
 	/* make a copy */
-	array = g_ptr_array_new_with_free_func ((GDestroyNotify) g_object_unref);
-	for (i=0; i<repos->priv->list->len; i++) {
-		store = g_ptr_array_index (repos->priv->list, i);
-		g_ptr_array_add (array, g_object_ref (store));
-	}
+	array = g_ptr_array_ref (repos->priv->list);
 out:
 	return array;
 }
@@ -427,6 +421,7 @@ zif_repos_file_monitor_cb (ZifMonitor *monitor, ZifRepos *repos)
 {
 	g_ptr_array_set_size (repos->priv->list, 0);
 	g_ptr_array_set_size (repos->priv->enabled, 0);
+	repos->priv->loaded = FALSE;
 	egg_debug ("repo file changed");
 }
 
diff --git a/backends/yum/pk-backend-yum.c b/backends/yum/pk-backend-yum.c
index 171a2f0..26ba3b2 100644
--- a/backends/yum/pk-backend-yum.c
+++ b/backends/yum/pk-backend-yum.c
@@ -25,8 +25,10 @@
 #include <string.h>
 #include <zif.h>
 
-#define PREUPGRADE_BINARY	"/usr/bin/preupgrade"
-#define YUM_REPOS_DIRECTORY	"/etc/yum.repos.d"
+#define PREUPGRADE_BINARY			"/usr/bin/preupgrade"
+#define YUM_REPOS_DIRECTORY			"/etc/yum.repos.d"
+#define YUM_BACKEND_LOCKING_RETRIES		10
+#define YUM_BACKEND_LOCKING_DELAY		2 /* seconds */
 
 typedef struct {
 	PkBackendSpawn	*spawn;
@@ -90,6 +92,59 @@ backend_completion_subpercentage_changed_cb (ZifCompletion *completion, guint su
 }
 
 /**
+ * backend_get_lock:
+ */
+static gboolean
+backend_get_lock (PkBackend *backend)
+{
+	guint i;
+	guint pid;
+	gboolean ret = FALSE;
+	GError *error = NULL;
+
+	for (i=0; i<YUM_BACKEND_LOCKING_RETRIES; i++) {
+
+		/* try to lock */
+		ret = zif_lock_set_locked (priv->lock, &pid, &error);
+		if (ret)
+			break;
+
+		/* we're now waiting */
+		pk_backend_set_status (backend, PK_STATUS_ENUM_WAITING_FOR_LOCK);
+
+		/* now wait */
+		egg_debug ("Failed to lock on try %i of %i, already locked by PID %i (sleeping for %i seconds): %s\n",
+			   i+1, YUM_BACKEND_LOCKING_RETRIES, pid, YUM_BACKEND_LOCKING_DELAY, error->message);
+		g_clear_error (&error);
+		g_usleep (YUM_BACKEND_LOCKING_DELAY * G_USEC_PER_SEC);
+	}
+
+	/* we failed */
+	if (!ret)
+		pk_backend_error_code (backend, PK_ERROR_ENUM_CANNOT_GET_LOCK, "failed to get lock, held by PID: %i", pid);
+
+	return ret;
+}
+
+/**
+ * backend_unlock:
+ */
+static gboolean
+backend_unlock (PkBackend *backend)
+{
+	gboolean ret;
+	GError *error = NULL;
+
+	/* try to unlock */
+	ret = zif_lock_set_unlocked (priv->lock, &error);
+	if (!ret) {
+		egg_warning ("failed to unlock: %s", error->message);
+		g_error_free (error);
+	}
+	return ret;
+}
+
+/**
  * backend_initialize:
  * This should only be run once per backend load, i.e. not every transaction
  */
@@ -742,15 +797,94 @@ backend_resolve (PkBackend *backend, PkBitfield filters, gchar **package_ids)
 }
 
 /**
+ * backend_get_repo_list_thread:
+ */
+static gboolean
+backend_get_repo_list_thread (PkBackend *backend)
+{
+	gboolean ret;
+	PkBitfield filters = (PkBitfield) pk_backend_get_uint (backend, "filters");
+	guint i;
+	GPtrArray *array = NULL;
+	ZifStoreRemote *store;
+	ZifCompletion *completion_local;
+	const gchar *repo_id;
+	const gchar *name;
+	gboolean enabled;
+	gboolean devel;
+	GError *error = NULL;
+
+	/* get lock */
+	ret = backend_get_lock (backend);
+	if (!ret) {
+		egg_warning ("failed to get lock");
+		goto out;
+	}
+
+	pk_backend_set_status (backend, PK_STATUS_ENUM_QUERY);
+
+	/* setup completion */
+	zif_completion_reset (priv->completion);
+	zif_completion_set_number_steps (priv->completion, 2);
+
+	completion_local = zif_completion_get_child (priv->completion);
+	array = zif_repos_get_stores (priv->repos, priv->cancellable, completion_local, &error);
+	if (array == NULL) {
+		pk_backend_error_code (backend, PK_ERROR_ENUM_REPO_NOT_FOUND, "failed to find repos: %s", error->message);
+		g_error_free (error);
+		goto out;
+	}
+
+	/* none? */
+	if (array->len == 0) {
+		pk_backend_error_code (backend, PK_ERROR_ENUM_REPO_NOT_FOUND, "failed to find any repos");
+		goto out;
+	}
+
+	/* this section done */
+	zif_completion_done (priv->completion);
+
+	/* setup completion */
+	completion_local = zif_completion_get_child (priv->completion);
+	zif_completion_set_number_steps (completion_local, array->len);
+
+	/* looks at each store */
+	for (i=0; i<array->len; i++) {
+		store = g_ptr_array_index (array, i);
+		if (pk_bitfield_contain (filters, PK_FILTER_ENUM_NOT_DEVELOPMENT)) {
+			/* TODO: completion */
+			devel = zif_store_remote_is_devel (store, priv->cancellable, NULL, NULL);
+			if (devel)
+				continue;
+		}
+		repo_id = zif_store_get_id (ZIF_STORE (store));
+		/* TODO: completion */
+		name = zif_store_remote_get_name (store, priv->cancellable, NULL, NULL);
+		/* TODO: completion */
+		enabled = zif_store_remote_get_enabled (store, priv->cancellable, NULL, NULL);
+		pk_backend_repo_detail (backend, repo_id, name, enabled);
+
+		/* this section done */
+		zif_completion_done (completion_local);
+	}
+
+	/* this section done */
+	zif_completion_done (priv->completion);
+out:
+	backend_unlock (backend);
+	pk_backend_finished (backend);
+	if (array != NULL)
+		g_ptr_array_unref (array);
+	return TRUE;
+}
+
+/**
  * pk_backend_get_repo_list:
  */
 static void
 backend_get_repo_list (PkBackend *backend, PkBitfield filters)
 {
-	gchar *filters_text;
-	filters_text = pk_filter_bitfield_to_string (filters);
-	pk_backend_spawn_helper (priv->spawn, "yumBackend.py", "get-repo-list", filters_text, NULL);
-	g_free (filters_text);
+	pk_backend_thread_create (backend, backend_get_repo_list_thread);
 }
 
 /**
diff --git a/backends/yum/yumBackend.py b/backends/yum/yumBackend.py
index b82a8ac..ed33d9a 100755
--- a/backends/yum/yumBackend.py
+++ b/backends/yum/yumBackend.py
@@ -2442,24 +2442,6 @@ class PackageKitYumBackend(PackageKitBaseBackend, PackagekitPackage):
         except Exception, e:
             self.error(ERROR_INTERNAL_ERROR, _format_str(traceback.format_exc()))
 
-    def get_repo_list(self, filters):
-        '''
-        Implement the get-repo-list functionality
-        '''
-        self._check_init()
-        self.yumbase.conf.cache = 0 # Allow new files
-        self.status(STATUS_INFO)
-
-        try:
-            repos = self.yumbase.repos.repos.values()
-        except Exception, e:
-            self.error(ERROR_INTERNAL_ERROR, _format_str(traceback.format_exc()))
-            return
-        for repo in repos:
-            if filters != FILTER_NOT_DEVELOPMENT or not _is_development_repo(repo.id):
-                enabled = repo.isEnabled()
-                self.repo_detail(repo.id, repo.name, enabled)
-
     def _get_obsoleted(self, name):
         try:
             # make sure yum doesn't explode in some internal fit of rage
commit ed290da775936890e13cfc96c24707412b2707b3
Author: Richard Hughes <richard at hughsie.com>
Date:   Tue Mar 9 09:17:56 2010 +0000

    yum: get the group list from Zif rather than hardcoding a fixed list

diff --git a/backends/yum/pk-backend-yum.c b/backends/yum/pk-backend-yum.c
index 6e07d0f..171a2f0 100644
--- a/backends/yum/pk-backend-yum.c
+++ b/backends/yum/pk-backend-yum.c
@@ -210,30 +210,22 @@ backend_destroy (PkBackend *backend)
 static PkBitfield
 backend_get_groups (PkBackend *backend)
 {
-	return pk_bitfield_from_enums (
-		PK_GROUP_ENUM_COLLECTIONS,
-		PK_GROUP_ENUM_NEWEST,
-		PK_GROUP_ENUM_ADMIN_TOOLS,
-		PK_GROUP_ENUM_DESKTOP_GNOME,
-		PK_GROUP_ENUM_DESKTOP_KDE,
-		PK_GROUP_ENUM_DESKTOP_XFCE,
-		PK_GROUP_ENUM_DESKTOP_OTHER,
-		PK_GROUP_ENUM_EDUCATION,
-		PK_GROUP_ENUM_FONTS,
-		PK_GROUP_ENUM_GAMES,
-		PK_GROUP_ENUM_GRAPHICS,
-		PK_GROUP_ENUM_INTERNET,
-		PK_GROUP_ENUM_LEGACY,
-		PK_GROUP_ENUM_LOCALIZATION,
-		PK_GROUP_ENUM_MULTIMEDIA,
-		PK_GROUP_ENUM_OFFICE,
-		PK_GROUP_ENUM_OTHER,
-		PK_GROUP_ENUM_PROGRAMMING,
-		PK_GROUP_ENUM_PUBLISHING,
-		PK_GROUP_ENUM_SERVERS,
-		PK_GROUP_ENUM_SYSTEM,
-		PK_GROUP_ENUM_VIRTUALIZATION,
-		-1);
+	GError *error = NULL;
+	PkBitfield groups;
+
+	/* get the dynamic group list */
+	groups = zif_groups_get_groups (priv->groups, &error);
+	if (groups == 0) {
+		pk_backend_error_code (backend, PK_ERROR_ENUM_GROUP_LIST_INVALID, "failed to get the list of groups: %s", error->message);
+		g_error_free (error);
+		goto out;
+	}
+
+	/* add the virtual groups */
+	pk_bitfield_add (groups, PK_GROUP_ENUM_COLLECTIONS);
+	pk_bitfield_add (groups, PK_GROUP_ENUM_NEWEST);
+out:
+	return groups;
 }
 
 /**
commit b9bc42ec3d7650336f08e9c0f47ca141a3c8c304
Author: Richard Hughes <richard at hughsie.com>
Date:   Tue Mar 9 09:12:03 2010 +0000

    yum: connect up more Zif helper objects in the yum backend

diff --git a/backends/yum/libzif/zif.h b/backends/yum/libzif/zif.h
index 9f54105..d21c0aa 100644
--- a/backends/yum/libzif/zif.h
+++ b/backends/yum/libzif/zif.h
@@ -27,8 +27,16 @@
 #include <zif-config.h>
 #include <zif-completion.h>
 #include <zif-string.h>
+#include <zif-depend.h>
 #include <zif-package.h>
+#include <zif-package-local.h>
+#include <zif-package-remote.h>
+#include <zif-store-local.h>
+#include <zif-store-remote.h>
+#include <zif-repos.h>
+#include <zif-sack.h>
 #include <zif-utils.h>
+#include <zif-groups.h>
 #include <zif-download.h>
 #include <zif-lock.h>
 
diff --git a/backends/yum/pk-backend-yum.c b/backends/yum/pk-backend-yum.c
index db785a4..6e07d0f 100644
--- a/backends/yum/pk-backend-yum.c
+++ b/backends/yum/pk-backend-yum.c
@@ -29,11 +29,16 @@
 #define YUM_REPOS_DIRECTORY	"/etc/yum.repos.d"
 
 typedef struct {
-	PkBackendSpawn *spawn;
-	GFileMonitor *monitor;
-	ZifDownload *download;
-	ZifConfig *config;
-	ZifCompletion *completion;
+	PkBackendSpawn	*spawn;
+	GFileMonitor	*monitor;
+	GCancellable	*cancellable;
+	ZifDownload	*download;
+	ZifConfig	*config;
+	ZifStoreLocal	*store_local;
+	ZifRepos	*repos;
+	ZifGroups	*groups;
+	ZifCompletion	*completion;
+	ZifLock		*lock;
 } PkBackendYumPrivate;
 
 static PkBackendYumPrivate *priv;
@@ -78,6 +83,12 @@ backend_completion_percentage_changed_cb (ZifCompletion *completion, guint perce
 	pk_backend_set_percentage (backend, percentage);
 }
 
+static void
+backend_completion_subpercentage_changed_cb (ZifCompletion *completion, guint subpercentage, PkBackend *backend)
+{
+	pk_backend_set_sub_percentage (backend, subpercentage);
+}
+
 /**
  * backend_initialize:
  * This should only be run once per backend load, i.e. not every transaction
@@ -112,16 +123,55 @@ backend_initialize (PkBackend *backend)
 	/* init rpm */
 	zif_init ();
 
-	/* get zif objects */
+	/* TODO: hook up errors */
+	priv->cancellable = g_cancellable_new ();
+
+	/* ZifCompletion */
+	priv->completion = zif_completion_new ();
+	g_signal_connect (priv->completion, "percentage-changed", G_CALLBACK (backend_completion_percentage_changed_cb), backend);
+	g_signal_connect (priv->completion, "subpercentage-changed", G_CALLBACK (backend_completion_subpercentage_changed_cb), backend);
+
+	/* ZifConfig */
 	priv->config = zif_config_new ();
 	ret = zif_config_set_filename (priv->config, "/etc/yum.conf", &error);
 	if (!ret) {
-		pk_backend_error_code (backend, PK_ERROR_ENUM_TRANSACTION_ERROR, "load yum.conf: %s", error->message);
+		pk_backend_error_code (backend, PK_ERROR_ENUM_FAILED_CONFIG_PARSING, "failed to set config: %s", error->message);
+		g_error_free (error);
 		goto out;
 	}
+
+	/* ZifDownload */
 	priv->download = zif_download_new ();
-	priv->completion = zif_completion_new ();
-	g_signal_connect (priv->completion, "percentage-changed", G_CALLBACK (backend_completion_percentage_changed_cb), backend);
+
+	/* ZifLock */
+	priv->lock = zif_lock_new ();
+
+	/* ZifStoreLocal */
+	priv->store_local = zif_store_local_new ();
+	ret = zif_store_local_set_prefix (priv->store_local, "/", &error);
+	if (!ret) {
+		pk_backend_error_code (backend, PK_ERROR_ENUM_INTERNAL_ERROR, "failed to set prefix: %s", error->message);
+		g_error_free (error);
+		goto out;
+	}
+
+	/* ZifRepos */
+	priv->repos = zif_repos_new ();
+	ret = zif_repos_set_repos_dir (priv->repos, "/etc/yum.repos.d", &error);
+	if (!ret) {
+		pk_backend_error_code (backend, PK_ERROR_ENUM_REPO_CONFIGURATION_ERROR, "failed to set repos dir: %s", error->message);
+		g_error_free (error);
+		goto out;
+	}
+
+	/* ZifGroups */
+	priv->groups = zif_groups_new ();
+	ret = zif_groups_set_mapping_file (priv->groups, "/usr/share/PackageKit/helpers/yum/yum-comps-groups.conf", &error);
+	if (!ret) {
+		pk_backend_error_code (backend, PK_ERROR_ENUM_GROUP_LIST_INVALID, "failed to set mapping file: %s", error->message);
+		g_error_free (error);
+		goto out;
+	}
 out:
 	g_object_unref (file);
 }
@@ -143,6 +193,14 @@ backend_destroy (PkBackend *backend)
 		g_object_unref (priv->download);
 	if (priv->completion != NULL)
 		g_object_unref (priv->completion);
+	if (priv->repos != NULL)
+		g_object_unref (priv->repos);
+	if (priv->groups != NULL)
+		g_object_unref (priv->groups);
+	if (priv->store_local != NULL)
+		g_object_unref (priv->store_local);
+	if (priv->lock != NULL)
+		g_object_unref (priv->lock);
 	g_free (priv);
 }
 
commit a6d8abe4dfbf2029b0ba95545fe9f32a1c26b1d4
Author: zerng07 <zerng07 at fedoraproject.org>
Date:   Tue Mar 9 15:07:40 2010 +0000

    Sending translation for Chinese (Traditional)

diff --git a/po/zh_TW.po b/po/zh_TW.po
index 9365e80..1002103 100644
--- a/po/zh_TW.po
+++ b/po/zh_TW.po
@@ -1,18 +1,17 @@
-# translation of packagekit.master.po to Traditional Chinese
-# translation of packagekit.master.po to
+# translation of packagekit.master.po to traditional Chinese
 # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
 # This file is distributed under the same license as the PACKAGE package.
 #
 # Terry Chuang <tchuang at redhat.com>, 2008, 2009.
-# Chester Cheng <ccheng@紅帽子>, 2009.
+# Cheng-Chia Tseng <pswo10680 at gmail.com>, 2010
 msgid ""
 msgstr ""
 "Project-Id-Version: packagekit.master\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2009-12-09 19:49+0000\n"
-"PO-Revision-Date: 2009-12-10 12:31+1000\n"
-"Last-Translator: Chester Cheng <ccheng@紅帽子>\n"
-"Language-Team: Traditional Chinese <zh_TW at li.org>\n"
+"POT-Creation-Date: 2010-03-09 09:20+0000\n"
+"PO-Revision-Date: 2010-03-09 23:06+0800\n"
+"Last-Translator: Cheng-Chia Tseng <pswo10680 at gmail.com>\n"
+"Language-Team: chinese-l10n at googlegroups.com\n"
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
@@ -21,9 +20,10 @@ msgstr ""
 
 #. TRANSLATORS: this is an atomic transaction
 #. TRANSLATORS: the role is the point of the transaction, e.g. update-system
-#: ../client/pk-console.c:175 ../client/pk-console.c:597
+#: ../client/pk-console.c:175
+#: ../client/pk-console.c:597
 msgid "Transaction"
-msgstr "交易"
+msgstr "處理事項"
 
 #. TRANSLATORS: this is the time the transaction was started in system timezone
 #: ../client/pk-console.c:177
@@ -33,7 +33,7 @@ msgstr "系統時間"
 #. TRANSLATORS: this is if the transaction succeeded or not
 #: ../client/pk-console.c:179
 msgid "Succeeded"
-msgstr "成功"
+msgstr "已成功"
 
 #: ../client/pk-console.c:179
 msgid "True"
@@ -45,9 +45,10 @@ msgstr "False"
 
 #. TRANSLATORS: this is the transactions role, e.g. "update-system"
 #. TRANSLATORS: the trasaction role, e.g. update-system
-#: ../client/pk-console.c:181 ../src/pk-polkit-action-lookup.c:332
+#: ../client/pk-console.c:181
+#: ../src/pk-polkit-action-lookup.c:332
 msgid "Role"
-msgstr "角色"
+msgstr "任務"
 
 #. TRANSLATORS: this is The duration of the transaction
 #: ../client/pk-console.c:186
@@ -56,23 +57,24 @@ msgstr "持續時間"
 
 #: ../client/pk-console.c:186
 msgid "(seconds)"
-msgstr "(秒)"
+msgstr "(秒)"
 
 #. TRANSLATORS: this is The command line used to do the action
 #. TRANSLATORS: the command line of the thing that wants the authentication
-#: ../client/pk-console.c:190 ../src/pk-polkit-action-lookup.c:346
+#: ../client/pk-console.c:190
+#: ../src/pk-polkit-action-lookup.c:346
 msgid "Command line"
 msgstr "指令列"
 
 #. TRANSLATORS: this is the user ID of the user that started the action
 #: ../client/pk-console.c:192
 msgid "User ID"
-msgstr "用戶 ID"
+msgstr "使用者 ID"
 
 #. TRANSLATORS: this is the username, e.g. hughsie
 #: ../client/pk-console.c:199
 msgid "Username"
-msgstr "用戶名稱"
+msgstr "使用者名稱"
 
 #. TRANSLATORS: this is the users real name, e.g. "Richard Hughes"
 #: ../client/pk-console.c:203
@@ -90,7 +92,7 @@ msgstr "受影響的套件:無"
 #. TRANSLATORS: this is the distro, e.g. Fedora 10
 #: ../client/pk-console.c:248
 msgid "Distribution"
-msgstr "發行套件"
+msgstr "發行版"
 
 #. TRANSLATORS: this is type of update, stable or testing
 #: ../client/pk-console.c:250
@@ -99,14 +101,15 @@ msgstr "é¡žåž‹"
 
 #. TRANSLATORS: this is any summary text describing the upgrade
 #. TRANSLATORS: this is the summary of the group
-#: ../client/pk-console.c:252 ../client/pk-console.c:291
+#: ../client/pk-console.c:252
+#: ../client/pk-console.c:291
 msgid "Summary"
 msgstr "摘要"
 
 #. TRANSLATORS: this is the group category name
 #: ../client/pk-console.c:280
 msgid "Category"
-msgstr "類別"
+msgstr "分類"
 
 #. TRANSLATORS: this is group identifier
 #: ../client/pk-console.c:282
@@ -116,7 +119,7 @@ msgstr "ID"
 #. TRANSLATORS: this is the parent group
 #: ../client/pk-console.c:285
 msgid "Parent"
-msgstr "父"
+msgstr "親代"
 
 #. TRANSLATORS: this is the name of the parent group
 #: ../client/pk-console.c:288
@@ -126,19 +129,20 @@ msgstr "名稱"
 #. TRANSLATORS: this is preferred icon for the group
 #: ../client/pk-console.c:294
 msgid "Icon"
-msgstr "圖像"
+msgstr "圖示"
 
 #. TRANSLATORS: this is a header for the package that can be updated
 #: ../client/pk-console.c:340
 msgid "Details about the update:"
-msgstr "有關於更新的詳情:"
+msgstr "關於更新的詳細資料:"
 
 #. TRANSLATORS: details about the update, package name and version
 #. TRANSLATORS: the package that is being processed
 #. TRANSLATORS: the package that is not signed by a known key
 #. TRANSLATORS: the package name that was trying to be installed
 #. TRANSLATORS: title, the names of the packages that the method is processing
-#: ../client/pk-console.c:346 ../client/pk-console.c:616
+#: ../client/pk-console.c:346
+#: ../client/pk-console.c:616
 #: ../lib/packagekit-glib2/pk-task-text.c:126
 #: ../lib/packagekit-glib2/pk-task-text.c:208
 #: ../src/pk-polkit-action-lookup.c:357
@@ -155,18 +159,19 @@ msgstr "æ›´æ–°"
 #. TRANSLATORS: details about the update, any packages that this update obsoletes
 #: ../client/pk-console.c:353
 msgid "Obsoletes"
-msgstr "已淘汰的套件"
+msgstr "廢棄"
 
 #. TRANSLATORS: details about the update, the vendor URLs
 #. TRANSLATORS: the vendor (e.g. vmware) that is providing the EULA
-#: ../client/pk-console.c:357 ../lib/packagekit-glib2/pk-task-text.c:211
+#: ../client/pk-console.c:357
+#: ../lib/packagekit-glib2/pk-task-text.c:211
 msgid "Vendor"
-msgstr "供應商"
+msgstr "廠商"
 
 #. TRANSLATORS: details about the update, the bugzilla URLs
 #: ../client/pk-console.c:361
 msgid "Bugzilla"
-msgstr "供應商"
+msgstr "Bugzilla"
 
 #. TRANSLATORS: details about the update, the CVE URLs
 #: ../client/pk-console.c:365
@@ -196,11 +201,12 @@ msgstr "狀態"
 #. TRANSLATORS: details about the update, date the update was issued
 #: ../client/pk-console.c:385
 msgid "Issued"
-msgstr "已發出"
+msgstr "已發佈的"
 
 #. TRANSLATORS: details about the update, date the update was updated
 #. TRANSLATORS: The action of the package, in past tense
-#: ../client/pk-console.c:389 ../lib/packagekit-glib2/pk-console-shared.c:510
+#: ../client/pk-console.c:389
+#: ../lib/packagekit-glib2/pk-console-shared.c:510
 msgid "Updated"
 msgstr "已更新"
 
@@ -217,27 +223,27 @@ msgstr "已停用"
 #. TRANSLATORS: a package requires the system to be restarted
 #: ../client/pk-console.c:460
 msgid "System restart required by:"
-msgstr "需要系統重新啟動:"
+msgstr "系統重新啟動被此需求:"
 
 #. TRANSLATORS: a package requires the session to be restarted
 #: ../client/pk-console.c:463
 msgid "Session restart required:"
-msgstr "需要重新啟動 session:"
+msgstr "需要重新啟動作業階段:"
 
 #. TRANSLATORS: a package requires the system to be restarted due to a security update
 #: ../client/pk-console.c:466
 msgid "System restart (security) required by:"
-msgstr "需要重新啟動系統(安全性):"
+msgstr "系統重新啟動(安全性)被此需求:"
 
 #. TRANSLATORS: a package requires the session to be restarted due to a security update
 #: ../client/pk-console.c:469
 msgid "Session restart (security) required:"
-msgstr "需要重新啟動 session(安全性):"
+msgstr "需要重新啟動(安全性)作業階段:"
 
 #. TRANSLATORS: a package requires the application to be restarted
 #: ../client/pk-console.c:472
 msgid "Application restart required by:"
-msgstr "需要重新啟動應用程式:"
+msgstr "應用程式重新啟動被此需求:"
 
 #. TRANSLATORS: This a list of details about the package
 #: ../client/pk-console.c:507
@@ -270,358 +276,373 @@ msgid "Status"
 msgstr "狀態"
 
 #. TRANSLATORS: the results from the transaction
-#: ../client/pk-console.c:678
+#: ../client/pk-console.c:679
 msgid "Results:"
 msgstr "結果:"
 
 #. TRANSLATORS: we failed to get any results, which is pretty fatal in my book
-#: ../client/pk-console.c:685
+#: ../client/pk-console.c:686
 msgid "Fatal error"
 msgstr "嚴重錯誤"
 
 #. TRANSLATORS: the transaction failed in a way we could not expect
-#: ../client/pk-console.c:694
+#: ../client/pk-console.c:695
 #: ../contrib/command-not-found/pk-command-not-found.c:432
 #: ../contrib/command-not-found/pk-command-not-found.c:603
 msgid "The transaction failed"
-msgstr "交易失敗"
+msgstr "處理事項失敗"
 
 #. TRANSLATORS: print a message when there are no updates
-#: ../client/pk-console.c:721
+#: ../client/pk-console.c:726
 msgid "There are no updates available at this time."
-msgstr "目前沒有可用的更新。"
+msgstr "此刻尚無更新可用。"
+
+#: ../client/pk-console.c:749
+msgid "There are no upgrades available at this time."
+msgstr "此刻尚無升級可用。"
 
 #. TRANSLATORS: a package needs to restart their system
-#: ../client/pk-console.c:808
+#: ../client/pk-console.c:816
 msgid "Please restart the computer to complete the update."
 msgstr "請重新啟動電腦來完成更新。"
 
 #. TRANSLATORS: a package needs to restart the session
-#: ../client/pk-console.c:811
+#: ../client/pk-console.c:819
 msgid "Please logout and login to complete the update."
 msgstr "請登出並再次登入來完成更新。"
 
 #. TRANSLATORS: a package needs to restart their system (due to security)
-#: ../client/pk-console.c:814
-msgid ""
-"Please restart the computer to complete the update as important security "
-"updates have been installed."
-msgstr "請重新啟動電腦來完成更新,因為已經安裝了重要的安全性更新檔。"
+#: ../client/pk-console.c:822
+msgid "Please restart the computer to complete the update as important security updates have been installed."
+msgstr "因為重大安全性更新已安裝,請重新啟動電腦來完成更新動作。"
 
 #. TRANSLATORS: a package needs to restart the session (due to security)
-#: ../client/pk-console.c:817
-msgid ""
-"Please logout and login to complete the update as important security updates "
-"have been installed."
-msgstr "請登出並再次登入來完成更新,因為已經安裝了重要的安全性更新檔。"
+#: ../client/pk-console.c:825
+msgid "Please logout and login to complete the update as important security updates have been installed."
+msgstr "因為重大安全性更新已安裝,請登出並再次登入來完成更新動作。"
+
+#. TRANSLATORS: The user used 'pkcon install dave.rpm' rather than 'pkcon install-local dave.rpm'
+#: ../client/pk-console.c:851
+#, c-format
+msgid "Extected package name, actually got file. Try using 'pkcon install-local %s' instead."
+msgstr "預期的套件名稱,已實際取得檔案。嘗試使用 'pkcon install-local %s' 來替代。"
 
 #. TRANSLATORS: There was an error getting the list of files for the package. The detailed error follows
-#: ../client/pk-console.c:840
+#: ../client/pk-console.c:859
 #, c-format
 msgid "This tool could not find any available package: %s"
-msgstr "此工具找不到任何可用的套件:%s"
+msgstr "此工具無法找到任何可用的套件:%s"
 
 #. TRANSLATORS: There was an error getting the list of files for the package. The detailed error follows
-#: ../client/pk-console.c:868
+#: ../client/pk-console.c:887
 #, c-format
 msgid "This tool could not find the installed package: %s"
-msgstr "此工具找不到任何已安裝的套件:%s"
+msgstr "此工具無法找到已安裝的套件:%s"
 
 #. TRANSLATORS: There was an error getting the list of files for the package. The detailed error follows
-#: ../client/pk-console.c:896 ../client/pk-console.c:924
+#: ../client/pk-console.c:915
+#: ../client/pk-console.c:943
 #, c-format
 msgid "This tool could not find the package: %s"
-msgstr "此工具找不到套件:%s"
+msgstr "此工具無法找到這個套件:%s"
 
 #. TRANSLATORS: There was an error getting the list of files for the package. The detailed error follows
 #. TRANSLATORS: There was an error getting the dependencies for the package. The detailed error follows
 #. TRANSLATORS: There was an error getting the details about the package. The detailed error follows
 #. TRANSLATORS: The package name was not found in any software sources. The detailed error follows
-#: ../client/pk-console.c:952 ../client/pk-console.c:980
-#: ../client/pk-console.c:1008 ../client/pk-console.c:1036
-#: ../client/pk-console.c:1064
+#: ../client/pk-console.c:971
+#: ../client/pk-console.c:999
+#: ../client/pk-console.c:1027
+#: ../client/pk-console.c:1055
+#: ../client/pk-console.c:1083
 #, c-format
 msgid "This tool could not find all the packages: %s"
-msgstr "此工具找不到所有套件:%s"
+msgstr "此工具無法找到所有套件:%s"
 
 #. TRANSLATORS: This is when the daemon crashed, and we are up shit creek without a paddle
-#: ../client/pk-console.c:1093
+#: ../client/pk-console.c:1112
 msgid "The daemon crashed mid-transaction!"
-msgstr "daemon 損毀了 mid-transaction!"
+msgstr "幕後程式損壞了 mid-transaction!"
 
 #. TRANSLATORS: This is the header to the --help menu
-#: ../client/pk-console.c:1127
+#: ../client/pk-console.c:1146
 msgid "PackageKit Console Interface"
 msgstr "PackageKit 主控台介面"
 
 #. these are commands we can use with pkcon
-#: ../client/pk-console.c:1129
+#: ../client/pk-console.c:1148
 msgid "Subcommands:"
 msgstr "次指令:"
 
 #. TRANSLATORS: we keep a database updated with the time that an action was last executed
-#: ../client/pk-console.c:1208
+#: ../client/pk-console.c:1227
 msgid "Failed to get the time since this action was last completed"
 msgstr "無法取得此動作最後完成後的時間"
 
 #. TRANSLATORS: command line argument, just show the version string
-#: ../client/pk-console.c:1244 ../client/pk-monitor.c:280
+#: ../client/pk-console.c:1263
+#: ../client/pk-monitor.c:306
 msgid "Show the program version and exit"
-msgstr "顯示程式版本然後退出"
+msgstr "顯示程式版本然後離開"
 
 #. TRANSLATORS: command line argument, use a filter to narrow down results
-#: ../client/pk-console.c:1247
+#: ../client/pk-console.c:1266
 msgid "Set the filter, e.g. installed"
-msgstr "設定過濾選項,例如「installed」"
+msgstr "設定過濾條件,例如:installed"
 
 #. TRANSLATORS: command line argument, work asynchronously
-#: ../client/pk-console.c:1250
+#: ../client/pk-console.c:1269
 msgid "Exit without waiting for actions to complete"
-msgstr "不等待動作完成便退出"
+msgstr "不等待動作完成便離開"
 
 #. command line argument, do we ask questions
-#: ../client/pk-console.c:1253
+#: ../client/pk-console.c:1272
 #: ../contrib/debuginfo-install/pk-debuginfo-install.c:527
 msgid "Install the packages without asking for confirmation"
-msgstr "安裝套件,但不需要使用者確認"
+msgstr "安裝套件而不要詢問是否確認"
 
 #. TRANSLATORS: command line argument, this command is not a priority
-#: ../client/pk-console.c:1256
+#: ../client/pk-console.c:1275
 msgid "Run the command using idle network bandwidth and also using less power"
-msgstr "執行這指令,在網路閒置時使用網路頻寬,並使用更少的電力"
+msgstr "使用閒置的網路頻寬與較少的能源來執行指令"
 
 #. TRANSLATORS: command line argument, just output without fancy formatting
-#: ../client/pk-console.c:1259
+#: ../client/pk-console.c:1278
 msgid "Print to screen a machine readable output, rather than using animated widgets"
-msgstr "在螢幕上列印出機器可讀取的格式;而不是使用圖形元件"
+msgstr "將機器可讀的輸出列印到畫面,而不是使用動畫的小工具"
 
 #. TRANSLATORS: we failed to contact the daemon
-#: ../client/pk-console.c:1281
+#: ../client/pk-console.c:1300
 msgid "Failed to contact PackageKit"
-msgstr "無法與 PackageKit 連接"
+msgstr "聯絡 PackageKit 失敗"
 
 #. TRANSLATORS: The user specified an incorrect filter
-#: ../client/pk-console.c:1339
+#: ../client/pk-console.c:1358
 msgid "The filter specified was invalid"
-msgstr "指定的過濾器無效"
+msgstr "指定的過濾條件無效"
 
 #. TRANSLATORS: a search type can be name, details, file, etc
-#: ../client/pk-console.c:1358
+#: ../client/pk-console.c:1377
 msgid "A search type is required, e.g. name"
-msgstr "需要搜尋類型,例如名稱"
+msgstr "需要選取搜尋類型,例如:名稱"
 
 #. TRANSLATORS: the user needs to provide a search term
-#: ../client/pk-console.c:1365 ../client/pk-console.c:1377
-#: ../client/pk-console.c:1389 ../client/pk-console.c:1401
+#: ../client/pk-console.c:1384
+#: ../client/pk-console.c:1396
+#: ../client/pk-console.c:1408
+#: ../client/pk-console.c:1420
 msgid "A search term is required"
-msgstr "需要搜尋關鍵字"
+msgstr "需要輸入搜尋用的關鍵詞"
 
 #. TRANSLATORS: the search type was provided, but invalid
-#: ../client/pk-console.c:1411
+#: ../client/pk-console.c:1430
 msgid "Invalid search type"
 msgstr "無效的搜尋類型"
 
 #. TRANSLATORS: the user did not specify what they wanted to install
-#: ../client/pk-console.c:1417
+#: ../client/pk-console.c:1436
 msgid "A package name to install is required"
-msgstr "需要欲安裝的套件之名稱"
+msgstr "需要有要安裝的套件名稱"
 
 #. TRANSLATORS: the user did not specify what they wanted to install
-#: ../client/pk-console.c:1426
+#: ../client/pk-console.c:1445
 msgid "A filename to install is required"
-msgstr "需要檔名以進行安裝"
+msgstr "需要有要安裝的檔案名稱"
 
 #. TRANSLATORS: geeky error, 99.9999% of users won't see this
-#: ../client/pk-console.c:1438
+#: ../client/pk-console.c:1457
 msgid "A type, key_id and package_id are required"
 msgstr "需要指定一個類型、key_id 以及 package_id"
 
 #. TRANSLATORS: the user did not specify what they wanted to remove
-#: ../client/pk-console.c:1449
+#: ../client/pk-console.c:1468
 msgid "A package name to remove is required"
-msgstr "需要欲移除的套件之名稱"
+msgstr "需要想移除的套件名稱"
 
 #. TRANSLATORS: the user did not specify anything about what to download or where
-#: ../client/pk-console.c:1458
+#: ../client/pk-console.c:1477
 msgid "A destination directory and the package names to download are required"
-msgstr "需要指定目的地目錄以及欲下載的套件之名稱"
+msgstr "需要有目標資料夾與要下載的套件名稱"
 
 #. TRANSLATORS: the directory does not exist, so we can't continue
-#: ../client/pk-console.c:1465
+#: ../client/pk-console.c:1484
 msgid "Directory not found"
 msgstr "找不到目錄"
 
 #. TRANSLATORS: geeky error, 99.9999% of users won't see this
-#: ../client/pk-console.c:1474
+#: ../client/pk-console.c:1493
 msgid "A licence identifier (eula-id) is required"
 msgstr "需要指定一個授權合約的標示符號(eula-id)"
 
 #. TRANSLATORS: geeky error, 99.9999% of users won't see this
-#: ../client/pk-console.c:1485
+#: ../client/pk-console.c:1504
 msgid "A transaction identifier (tid) is required"
-msgstr "需要交易標示符號(tid)"
+msgstr "需要處理事項識別符 (tid)"
 
 #. TRANSLATORS: The user did not specify a package name
-#: ../client/pk-console.c:1506
+#: ../client/pk-console.c:1525
 msgid "A package name to resolve is required"
 msgstr "需要欲解析的套件之名稱"
 
 #. TRANSLATORS: The user did not specify a repository (software source) name
-#: ../client/pk-console.c:1517 ../client/pk-console.c:1528
+#: ../client/pk-console.c:1536
+#: ../client/pk-console.c:1547
 msgid "A repository name is required"
-msgstr "需要軟體庫的名稱"
+msgstr "需要套件庫的名稱"
 
 #. TRANSLATORS: The user didn't provide any data
-#: ../client/pk-console.c:1539
+#: ../client/pk-console.c:1558
 msgid "A repo name, parameter and value are required"
-msgstr "需要指定一個 repo 名稱、參數和數值"
+msgstr "需要指定一個套件庫名稱、參數和值"
 
 #. TRANSLATORS: The user didn't specify what action to use
-#: ../client/pk-console.c:1556
+#: ../client/pk-console.c:1575
 msgid "An action, e.g. 'update-system' is required"
-msgstr "需要指定一項動作,例如「update-system」"
+msgstr "需要指定一項動作,例如:「update-system」"
 
 #. TRANSLATORS: The user specified an invalid action
-#: ../client/pk-console.c:1563
+#: ../client/pk-console.c:1582
 msgid "A correct role is required"
-msgstr "需要正確的角色"
+msgstr "需要正確的任務"
 
 #. TRANSLATORS: The user did not provide a package name
 #. TRANSLATORS: This is when the user fails to supply the package name
-#: ../client/pk-console.c:1573 ../client/pk-console.c:1588
-#: ../client/pk-console.c:1597 ../client/pk-console.c:1617
-#: ../client/pk-console.c:1626 ../client/pk-generate-pack.c:298
+#: ../client/pk-console.c:1592
+#: ../client/pk-console.c:1607
+#: ../client/pk-console.c:1616
+#: ../client/pk-console.c:1636
+#: ../client/pk-console.c:1645
+#: ../client/pk-generate-pack.c:316
 msgid "A package name is required"
-msgstr "需要套件的名稱"
+msgstr "需要套件名稱"
 
 #. TRANSLATORS: each package "provides" certain things, e.g. mime(gstreamer-decoder-mp3), the user didn't specify it
-#: ../client/pk-console.c:1606
+#: ../client/pk-console.c:1625
 msgid "A package provide string is required"
-msgstr "需要提供套件的字串"
+msgstr "需要套件的提供字串"
 
 #. TRANSLATORS: The user tried to use an unsupported option on the command line
-#: ../client/pk-console.c:1686
+#: ../client/pk-console.c:1705
 #, c-format
 msgid "Option '%s' is not supported"
 msgstr "「%s」選項不被支援"
 
 #. TRANSLATORS: Generic failure of what they asked to do
-#: ../client/pk-console.c:1696
+#: ../client/pk-console.c:1715
 msgid "Command failed"
 msgstr "指令失敗"
 
 #. TRANSLATORS: we can exclude certain packages (glibc) when we know they'll exist on the target
-#: ../client/pk-generate-pack.c:237
+#: ../client/pk-generate-pack.c:255
 msgid "Set the file name of dependencies to be excluded"
-msgstr "設定將被排除的相依檔案名稱"
+msgstr "設定要排除的相依檔名"
 
 #. TRANSLATORS: the output location
-#: ../client/pk-generate-pack.c:240
+#: ../client/pk-generate-pack.c:258
 msgid "The output file or directory (the current directory is used if ommitted)"
 msgstr "輸出檔案或目錄(若省略的話,目前的目錄便會被使用)"
 
 #. TRANSLATORS: put a list of packages in the pack
-#: ../client/pk-generate-pack.c:243
+#: ../client/pk-generate-pack.c:261
 msgid "The package to be put into the service pack"
-msgstr "將放入服務套件中的套件"
+msgstr "將放入服務包中的套件"
 
 #. TRANSLATORS: put all pending updates in the pack
-#: ../client/pk-generate-pack.c:246
+#: ../client/pk-generate-pack.c:264
 msgid "Put all updates available in the service pack"
-msgstr "將所有可用的套件放入服務套件中"
+msgstr "將所有可用的套件放入服務包中"
 
 #. TRANSLATORS: This is when the user fails to supply the correct arguments
-#: ../client/pk-generate-pack.c:282
+#: ../client/pk-generate-pack.c:300
 msgid "Neither --package or --updates option selected."
-msgstr "--package 與 --updates 選項皆未被選擇。"
+msgstr "--package 與 --updates 選項皆未選取。"
 
 #. TRANSLATORS: This is when the user fails to supply just one argument
-#: ../client/pk-generate-pack.c:290
+#: ../client/pk-generate-pack.c:308
 msgid "Both options selected."
-msgstr "兩個選項皆被選擇了。"
+msgstr "兩個選項皆被選取。"
 
 #. TRANSLATORS: This is when the user fails to supply the output
-#: ../client/pk-generate-pack.c:306
+#: ../client/pk-generate-pack.c:324
 msgid "A output directory or file name is required"
 msgstr "需要輸出目錄或檔案名稱"
 
 #. TRANSLATORS: This is when the dameon is not-installed/broken and fails to startup
-#: ../client/pk-generate-pack.c:324
+#: ../client/pk-generate-pack.c:342
 msgid "The dameon failed to startup"
-msgstr "daemon 無法啟動"
+msgstr "幕後程式未能啟動"
 
 #. TRANSLATORS: This is when the backend doesn't have the capability to get-depends
 #. TRANSLATORS: This is when the backend doesn't have the capability to download
-#: ../client/pk-generate-pack.c:335 ../client/pk-generate-pack.c:341
+#: ../client/pk-generate-pack.c:353
+#: ../client/pk-generate-pack.c:359
 msgid "The package manager cannot perform this type of operation."
-msgstr "套件管理員無法進行這類型的作業。"
+msgstr "套件管理員無法執行這種類型的操作。"
 
 #. TRANSLATORS: This is when the distro didn't include libarchive support into PK
-#: ../client/pk-generate-pack.c:348
-msgid ""
-"Service packs cannot be created as PackageKit was not built with libarchive "
-"support."
-msgstr "無法建立 Service packs,因為 PackageKit 建立時並不支援 libarchive。"
+#: ../client/pk-generate-pack.c:366
+msgid "Service packs cannot be created as PackageKit was not built with libarchive support."
+msgstr "服務包無法建立,因為建構 PackageKit 時沒有啟用 libarchive 支援。"
 
 #. TRANSLATORS: the user specified an absolute path, but didn't get the extension correct
-#: ../client/pk-generate-pack.c:359
+#: ../client/pk-generate-pack.c:377
 msgid "If specifying a file, the service pack name must end with"
-msgstr "若要指定檔案的話,服務套件名稱必須以此為結尾"
+msgstr "若要指定檔案的話,服務包名稱必須以此為結尾"
 
 #. TRANSLATORS: This is when file already exists
-#: ../client/pk-generate-pack.c:375
+#: ../client/pk-generate-pack.c:393
 msgid "A pack with the same name already exists, do you want to overwrite it?"
-msgstr "擁有相同名稱的套件已經存在,您要覆寫這個檔案嗎?"
+msgstr "擁有相同名稱的服務包已經存在,您要覆寫這個檔案嗎?"
 
 #. TRANSLATORS: This is when the pack was not overwritten
-#: ../client/pk-generate-pack.c:378
+#: ../client/pk-generate-pack.c:396
 msgid "The pack was not overwritten."
-msgstr "套件並未被覆寫。"
+msgstr "服務包未被覆寫。"
 
 #. TRANSLATORS: This is when the temporary directory cannot be created, the directory name follows
-#: ../client/pk-generate-pack.c:391
+#: ../client/pk-generate-pack.c:409
 msgid "Failed to create directory:"
 msgstr "建立目錄失敗:"
 
 #. TRANSLATORS: This is when the list of packages from the remote computer cannot be opened
-#: ../client/pk-generate-pack.c:403
+#: ../client/pk-generate-pack.c:421
 msgid "Failed to open package list."
 msgstr "開啟套件清單失敗。"
 
 #. TRANSLATORS: The package name is being matched up to available packages
-#: ../client/pk-generate-pack.c:412
+#: ../client/pk-generate-pack.c:430
 msgid "Finding package name."
 msgstr "正在尋找套件名稱。"
 
 #. TRANSLATORS: This is when the package cannot be found in any software source. The detailed error follows
-#: ../client/pk-generate-pack.c:416
+#: ../client/pk-generate-pack.c:434
 #, c-format
 msgid "Failed to find package '%s': %s"
 msgstr "找不到套件「%s」:%s"
 
 #. TRANSLATORS: This is telling the user we are in the process of making the pack
-#: ../client/pk-generate-pack.c:424
+#: ../client/pk-generate-pack.c:442
 msgid "Creating service pack..."
-msgstr "正在建立服務套件..."
+msgstr "正在建立服務包..."
 
 #. TRANSLATORS: we succeeded in making the file
-#: ../client/pk-generate-pack.c:439
+#: ../client/pk-generate-pack.c:457
 #, c-format
 msgid "Service pack created '%s'"
-msgstr "服務套件建立了「%s」"
+msgstr "服務包建立了「%s」"
 
 #. TRANSLATORS: we failed to make te file
-#: ../client/pk-generate-pack.c:444
+#: ../client/pk-generate-pack.c:462
 #, c-format
 msgid "Failed to create '%s': %s"
 msgstr "無法建立「%s」:%s"
 
-#: ../client/pk-monitor.c:210
+#: ../client/pk-monitor.c:236
 msgid "Failed to get daemon state"
-msgstr "無法取得 daemon 的狀態"
+msgstr "未能取得幕後程式狀態"
 
 #. TRANSLATORS: this is a program that monitors PackageKit
-#: ../client/pk-monitor.c:296
+#: ../client/pk-monitor.c:322
 msgid "PackageKit Monitor"
 msgstr "PackageKit 監控程式"
 
@@ -639,18 +660,18 @@ msgstr "執行 %s"
 #. TRANSLATORS: show the installed version of a package
 #: ../contrib/browser-plugin/pk-plugin-install.c:507
 msgid "Installed version"
-msgstr "安裝版本"
+msgstr "已安裝的版本"
 
 #. TRANSLATORS: run the application now
 #: ../contrib/browser-plugin/pk-plugin-install.c:515
 #, c-format
 msgid "Run version %s now"
-msgstr "現在執行版本 %s"
+msgstr "立刻執行版本 %s"
 
 #. TRANSLATORS: run the application now
 #: ../contrib/browser-plugin/pk-plugin-install.c:521
 msgid "Run now"
-msgstr "現在執行"
+msgstr "立刻執行"
 
 #. TRANSLATORS: update to a new version of the package
 #: ../contrib/browser-plugin/pk-plugin-install.c:527
@@ -662,7 +683,7 @@ msgstr "更新至版本 %s"
 #: ../contrib/browser-plugin/pk-plugin-install.c:533
 #, c-format
 msgid "Install %s now"
-msgstr "現在安裝 %s"
+msgstr "立刻安裝 %s"
 
 #. TRANSLATORS: the version of the package
 #: ../contrib/browser-plugin/pk-plugin-install.c:536
@@ -677,27 +698,27 @@ msgstr "找不到適合您系統的套件"
 #. TRANSLATORS: package is being installed
 #: ../contrib/browser-plugin/pk-plugin-install.c:546
 msgid "Installing..."
-msgstr "安裝中..."
+msgstr "正在安裝..."
 
 #. TRANSLATORS: downloading repo data so we can search
 #: ../contrib/command-not-found/pk-command-not-found.c:365
 msgid "Downloading details about the software sources."
-msgstr "下載軟體來源的詳細資料。"
+msgstr "正在下載關於軟體來源的詳細資料。"
 
 #. TRANSLATORS: downloading file lists so we can search
 #: ../contrib/command-not-found/pk-command-not-found.c:369
 msgid "Downloading filelists (this may take some time to complete)."
-msgstr "下載檔案清單(這可能會花上一點時間)。"
+msgstr "正在下載檔案清單(這會花上一段時間才能完成)。"
 
 #. TRANSLATORS: waiting for native lock
 #: ../contrib/command-not-found/pk-command-not-found.c:373
 msgid "Waiting for package manager lock."
-msgstr "等待套件管理員解除鎖定。"
+msgstr "正在等待套件管理程式解鎖。"
 
 #. TRANSLATORS: loading package cache so we can search
 #: ../contrib/command-not-found/pk-command-not-found.c:377
 msgid "Loading list of packages."
-msgstr "下載套件清單中"
+msgstr "正在載入套件清單。"
 
 #. TRANSLATORS: we failed to find the package, this shouldn't happen
 #: ../contrib/command-not-found/pk-command-not-found.c:423
@@ -707,7 +728,7 @@ msgstr "搜尋檔案失敗"
 #. TRANSLATORS: we failed to launch the executable, the error follows
 #: ../contrib/command-not-found/pk-command-not-found.c:566
 msgid "Failed to launch:"
-msgstr "啟動失敗"
+msgstr "啟動失敗:"
 
 #. TRANSLATORS: we failed to install the package
 #: ../contrib/command-not-found/pk-command-not-found.c:594
@@ -727,7 +748,7 @@ msgstr "找不到指令。"
 #. TRANSLATORS: tell the user what we think the command is
 #: ../contrib/command-not-found/pk-command-not-found.c:706
 msgid "Similar command is:"
-msgstr "相似指令:"
+msgstr "相似指令為:"
 
 #. TRANSLATORS: Ask the user if we should run the similar command
 #: ../contrib/command-not-found/pk-command-not-found.c:716
@@ -739,7 +760,7 @@ msgstr "執行相似指令:"
 #: ../contrib/command-not-found/pk-command-not-found.c:730
 #: ../contrib/command-not-found/pk-command-not-found.c:739
 msgid "Similar commands are:"
-msgstr "相似指令:"
+msgstr "相似指令有:"
 
 #. TRANSLATORS: ask the user to choose a file to run
 #: ../contrib/command-not-found/pk-command-not-found.c:746
@@ -755,7 +776,7 @@ msgstr "提供此檔案的套件為:"
 #: ../contrib/command-not-found/pk-command-not-found.c:769
 #, c-format
 msgid "Install package '%s' to provide command '%s'?"
-msgstr "是否要安裝「%s」套件來提供「%s」指令?"
+msgstr "是否要安裝「%s」套件以提供「%s」指令?"
 
 #. TRANSLATORS: Show the user a list of packages that provide this command
 #: ../contrib/command-not-found/pk-command-not-found.c:793
@@ -765,7 +786,7 @@ msgstr "提供此檔案的套件有:"
 #. TRANSLATORS: Show the user a list of packages that they can install to provide this command
 #: ../contrib/command-not-found/pk-command-not-found.c:803
 msgid "Suitable packages are:"
-msgstr "適合的套件有:"
+msgstr "合適的套件有:"
 
 #. get selection
 #. TRANSLATORS: ask the user to choose a file to install
@@ -776,39 +797,39 @@ msgstr "請選擇欲安裝的套件"
 #. TRANSLATORS: we are starting to install the packages
 #: ../contrib/debuginfo-install/pk-debuginfo-install.c:197
 msgid "Starting install"
-msgstr "開始安裝"
+msgstr "正在開始安裝"
 
 #. TRANSLATORS: we couldn't find the package name, non-fatal
 #: ../contrib/debuginfo-install/pk-debuginfo-install.c:409
 #, c-format
 msgid "Failed to find the package %s, or already installed: %s"
-msgstr "找不到套件 %s,或已經安裝:%s"
+msgstr "找不到套件 %s,或是已經安裝了:%s"
 
 #. command line argument, simulate what would be done, but don't actually do it
 #: ../contrib/debuginfo-install/pk-debuginfo-install.c:518
 msgid "Don't actually install any packages, only simulate what would be installed"
-msgstr "不實際安裝任何套件,只模擬安裝"
+msgstr "不要真的安裝任何套件,只要模擬要安裝什麼就好"
 
 #. command line argument, do we skip packages that depend on the ones specified
 #: ../contrib/debuginfo-install/pk-debuginfo-install.c:521
 msgid "Do not install dependencies of the core packages"
-msgstr "不安裝核心套件所需的相依性套件"
+msgstr "不要安裝核心套件的相依關係"
 
 #. command line argument, do we operate quietly
 #: ../contrib/debuginfo-install/pk-debuginfo-install.c:524
 msgid "Do not display information or progress"
-msgstr "不顯示訊息或進度"
+msgstr "不要顯示資訊或進度"
 
 #. TRANSLATORS: tool that gets called when the command is not found
 #: ../contrib/debuginfo-install/pk-debuginfo-install.c:542
 msgid "PackageKit Debuginfo Installer"
-msgstr "PackageKit Debuginfo 安裝程式"
+msgstr "PackageKit 除錯資訊安裝程式"
 
 #. TRANSLATORS: the use needs to specify a list of package names on the command line
 #: ../contrib/debuginfo-install/pk-debuginfo-install.c:556
 #, c-format
 msgid "ERROR: Specify package names to install."
-msgstr "錯誤:請指定要安裝的套件名稱。沒有需要安裝的新套件"
+msgstr "錯誤:指定要安裝的套件名稱。"
 
 #. TRANSLATORS: we are getting the list of repositories
 #: ../contrib/debuginfo-install/pk-debuginfo-install.c:592
@@ -836,43 +857,43 @@ msgstr "失敗。"
 #: ../contrib/debuginfo-install/pk-debuginfo-install.c:931
 #, c-format
 msgid "OK."
-msgstr "OK."
+msgstr "確定。"
 
 #. TRANSLATORS: tell the user what we found
 #: ../contrib/debuginfo-install/pk-debuginfo-install.c:620
 #, c-format
 msgid "Found %i enabled and %i disabled sources."
-msgstr "找到 %i 已啟用的來源,以及 %i 已停用的來源。"
+msgstr "找到 %i 個啟用的與 %i 個停用的來源。"
 
 #. TRANSLATORS: we're finding repositories that match out pattern
 #: ../contrib/debuginfo-install/pk-debuginfo-install.c:627
 #, c-format
 msgid "Finding debugging sources"
-msgstr "找到 debug 來源"
+msgstr "正在尋找除錯來源"
 
 #. TRANSLATORS: tell the user what we found
 #: ../contrib/debuginfo-install/pk-debuginfo-install.c:660
 #, c-format
 msgid "Found %i disabled debuginfo repos."
-msgstr "找到 %i 已停用的 debuginfo 軟體庫。"
+msgstr "找到 %i 個停用的除錯資訊套件庫。"
 
 #. TRANSLATORS: we're now enabling all the debug sources we found
 #: ../contrib/debuginfo-install/pk-debuginfo-install.c:667
 #, c-format
 msgid "Enabling debugging sources"
-msgstr "啟用 debug 來源"
+msgstr "正在啟用除錯來源"
 
 #. TRANSLATORS: tell the user how many we enabled
 #: ../contrib/debuginfo-install/pk-debuginfo-install.c:695
 #, c-format
 msgid "Enabled %i debugging sources."
-msgstr "已啟用 %i 個 debug 來源。"
+msgstr "已啟用 %i 個除錯來源。"
 
 #. TRANSLATORS: we're now finding packages that match in all the repos
 #: ../contrib/debuginfo-install/pk-debuginfo-install.c:702
 #, c-format
 msgid "Finding debugging packages"
-msgstr "正在尋找 debug 套件"
+msgstr "正在尋找除錯套件"
 
 #. TRANSLATORS: we couldn't find the package name, non-fatal
 #: ../contrib/debuginfo-install/pk-debuginfo-install.c:714
@@ -884,7 +905,7 @@ msgstr "找不到套件 %s:%s"
 #: ../contrib/debuginfo-install/pk-debuginfo-install.c:737
 #, c-format
 msgid "Failed to find the debuginfo package %s: %s"
-msgstr "找不到 debuginfo 套件 %s:%s"
+msgstr "找不到除錯資訊套件 %s:%s"
 
 #. TRANSLATORS: no debuginfo packages could be found to be installed
 #: ../contrib/debuginfo-install/pk-debuginfo-install.c:765
@@ -902,13 +923,13 @@ msgstr "找到 %i 個套件:"
 #: ../contrib/debuginfo-install/pk-debuginfo-install.c:795
 #, c-format
 msgid "Finding packages that depend on these packages"
-msgstr "尋找與這些套件相依的套件"
+msgstr "正在尋找依賴於這些套件的套件"
 
 #. TRANSLATORS: could not install, detailed error follows
 #: ../contrib/debuginfo-install/pk-debuginfo-install.c:808
 #, c-format
 msgid "Could not find dependant packages: %s"
-msgstr "找不到相依套件:%s"
+msgstr "找不到依賴的套件:%s"
 
 #. TRANSLATORS: tell the user we found some more packages
 #: ../contrib/debuginfo-install/pk-debuginfo-install.c:824
@@ -926,13 +947,13 @@ msgstr "不需要額外的套件。"
 #: ../contrib/debuginfo-install/pk-debuginfo-install.c:837
 #, c-format
 msgid "Found %i packages to install:"
-msgstr "找到 %i 個套件安裝:"
+msgstr "找到 %i 個套件要安裝:"
 
 #. TRANSLATORS: simulate mode is a testing mode where we quit before the action
 #: ../contrib/debuginfo-install/pk-debuginfo-install.c:850
 #, c-format
 msgid "Not installing packages in simulate mode"
-msgstr "不在模擬模式下安裝套件"
+msgstr "在模擬模式內不會安裝套件"
 
 #. TRANSLATORS: we are now installing the debuginfo packages we found earlier
 #. TRANSLATORS: transaction state, installing packages
@@ -940,7 +961,7 @@ msgstr "不在模擬模式下安裝套件"
 #: ../lib/packagekit-glib2/pk-console-shared.c:282
 #, c-format
 msgid "Installing packages"
-msgstr "安裝套件"
+msgstr "正在安裝套件"
 
 #. TRANSLATORS: could not install, detailed error follows
 #: ../contrib/debuginfo-install/pk-debuginfo-install.c:875
@@ -952,113 +973,113 @@ msgstr "無法安裝套件:%s"
 #: ../contrib/debuginfo-install/pk-debuginfo-install.c:907
 #, c-format
 msgid "Disabling sources previously enabled"
-msgstr "正在停用之前啟用的來源"
+msgstr "正在停用先前啟用的來源"
 
 #. TRANSLATORS: no debuginfo packages could be found to be installed, detailed error follows
 #: ../contrib/debuginfo-install/pk-debuginfo-install.c:919
 #, c-format
 msgid "Could not disable the debugging sources: %s"
-msgstr "無法停用 debug 來源:%s"
+msgstr "無法停用除錯來源:%s"
 
 #. TRANSLATORS: we disabled all the debugging repos that we enabled before
 #: ../contrib/debuginfo-install/pk-debuginfo-install.c:934
 #, c-format
 msgid "Disabled %i debugging sources."
-msgstr "已停用 %i 個 debug 來源。"
+msgstr "已停用 %i 個除錯來源。"
 
 #. TRANSLATORS: couldn't open device to write
-#: ../contrib/device-rebind/pk-device-rebind.c:61
+#: ../contrib/device-rebind/pk-device-rebind.c:62
 msgid "Failed to open file"
 msgstr "開啟檔案失敗"
 
 #. TRANSLATORS: could not write to the device
-#: ../contrib/device-rebind/pk-device-rebind.c:70
+#: ../contrib/device-rebind/pk-device-rebind.c:71
 msgid "Failed to write to the file"
-msgstr "無法寫入檔案"
+msgstr "寫入檔案失敗"
 
 #. TRANSLATORS: we failed to release the current driver
-#: ../contrib/device-rebind/pk-device-rebind.c:110
-#: ../contrib/device-rebind/pk-device-rebind.c:147
+#: ../contrib/device-rebind/pk-device-rebind.c:111
+#: ../contrib/device-rebind/pk-device-rebind.c:148
 msgid "Failed to write to device"
-msgstr "無法寫入裝置"
+msgstr "寫入裝置失敗"
 
 #. TRANSLATORS: the device could not be found in sysfs
-#: ../contrib/device-rebind/pk-device-rebind.c:175
+#: ../contrib/device-rebind/pk-device-rebind.c:176
 msgid "Device could not be found"
 msgstr "找不到裝置"
 
 #. TRANSLATORS: we failed to release the current driver
-#: ../contrib/device-rebind/pk-device-rebind.c:202
+#: ../contrib/device-rebind/pk-device-rebind.c:203
 msgid "Failed to unregister driver"
-msgstr "無法解除註冊驅動程式"
+msgstr "取消註冊驅動程式失敗"
 
 #. TRANSLATORS: we failed to bind the old driver
-#: ../contrib/device-rebind/pk-device-rebind.c:211
+#: ../contrib/device-rebind/pk-device-rebind.c:212
 msgid "Failed to register driver"
-msgstr "無法註冊驅動程式"
+msgstr "註冊驅動程式失敗"
 
 #. TRANSLATORS: user did not specify a device sysfs path that exists
-#: ../contrib/device-rebind/pk-device-rebind.c:260
+#: ../contrib/device-rebind/pk-device-rebind.c:261
 msgid "Device path not found"
 msgstr "找不到裝置路徑"
 
 #. TRANSLATORS: user did not specify a valid device sysfs path
-#: ../contrib/device-rebind/pk-device-rebind.c:268
+#: ../contrib/device-rebind/pk-device-rebind.c:269
 msgid "Incorrect device path specified"
-msgstr "指定的裝置路徑錯誤"
+msgstr "指定了不正確的裝置路徑"
 
-#: ../contrib/device-rebind/pk-device-rebind.c:293
+#: ../contrib/device-rebind/pk-device-rebind.c:294
 msgid "Show extra debugging information"
 msgstr "顯示額外的除錯資訊"
 
 #. command line argument, simulate what would be done, but don't actually do it
-#: ../contrib/device-rebind/pk-device-rebind.c:296
+#: ../contrib/device-rebind/pk-device-rebind.c:297
 msgid "Don't actually touch the hardware, only simulate what would be done"
-msgstr "不真正的改動硬體,只模擬結果"
+msgstr "不要真的碰觸這個硬體,只要模擬要進行什麼事就好"
 
 #. TRANSLATORS: command line option: a list of files to install
-#: ../contrib/device-rebind/pk-device-rebind.c:299
+#: ../contrib/device-rebind/pk-device-rebind.c:300
 msgid "Device paths"
 msgstr "裝置路徑"
 
 #. TRANSLATORS: tool that gets called when the device needs reloading after installing firmware
-#: ../contrib/device-rebind/pk-device-rebind.c:314
+#: ../contrib/device-rebind/pk-device-rebind.c:315
 msgid "PackageKit Device Reloader"
-msgstr "PackageKit 裝置重新載入程式"
+msgstr "PackageKit 裝置重新載入器"
 
 #. TRANSLATORS: user did not specify a valid device sysfs path
-#: ../contrib/device-rebind/pk-device-rebind.c:322
+#: ../contrib/device-rebind/pk-device-rebind.c:323
 msgid "You need to specify at least one valid device path"
-msgstr "請指定至少一個正確的裝置路徑"
+msgstr "您需要指定至少一個有效的裝置路徑"
 
 #. TRANSLATORS: user did not specify a valid device sysfs path
-#: ../contrib/device-rebind/pk-device-rebind.c:332
+#: ../contrib/device-rebind/pk-device-rebind.c:333
 msgid "This script can only be used by the root user"
-msgstr "只有 root 使用者才可以使用這個 script"
+msgstr "此指令稿只能由 root 使用者使用"
 
 #. TRANSLATORS: we're going to verify the path first
-#: ../contrib/device-rebind/pk-device-rebind.c:341
+#: ../contrib/device-rebind/pk-device-rebind.c:342
 msgid "Verifying device path"
-msgstr "驗證裝置路徑"
+msgstr "正在驗證裝置路徑"
 
 #. TRANSLATORS: user did not specify a device sysfs path that exists
-#: ../contrib/device-rebind/pk-device-rebind.c:346
+#: ../contrib/device-rebind/pk-device-rebind.c:347
 msgid "Failed to verify device path"
 msgstr "驗證裝置路徑失敗"
 
 #. TRANSLATORS: we're going to try
-#: ../contrib/device-rebind/pk-device-rebind.c:360
+#: ../contrib/device-rebind/pk-device-rebind.c:361
 msgid "Attempting to rebind device"
-msgstr "試圖重新 bind 裝置"
+msgstr "正在試圖重新綁定裝置"
 
 #. TRANSLATORS: we failed to release the current driver
-#: ../contrib/device-rebind/pk-device-rebind.c:365
+#: ../contrib/device-rebind/pk-device-rebind.c:366
 msgid "Failed to rebind device"
-msgstr "重新 bind 裝置失敗"
+msgstr "未能重新綁定裝置"
 
 #: ../data/packagekit-catalog.xml.in.h:1
 msgid "PackageKit Catalog"
-msgstr "PackageKit 目錄"
+msgstr "PackageKit 型錄"
 
 #: ../data/packagekit-package-list.xml.in.h:1
 msgid "PackageKit Package List"
@@ -1066,12 +1087,12 @@ msgstr "PackageKit 套件清單"
 
 #: ../data/packagekit-servicepack.xml.in.h:1
 msgid "PackageKit Service Pack"
-msgstr "PackageKit 服務套件"
+msgstr "PackageKit 服務包"
 
 #: ../lib/packagekit-glib2/pk-console-shared.c:59
 #, c-format
 msgid "Please enter a number from 1 to %i: "
-msgstr "請輸入一組由 1 到 %i 的數字:"
+msgstr "請輸入一個 1 到 %i 之間的數字:"
 
 #. TRANSLATORS: more than one package could be found that matched, to follow is a list of possible packages
 #: ../lib/packagekit-glib2/pk-console-shared.c:183
@@ -1091,22 +1112,22 @@ msgstr "不明的狀態"
 #. TRANSLATORS: transaction state, the daemon is in the process of starting
 #: ../lib/packagekit-glib2/pk-console-shared.c:254
 msgid "Starting"
-msgstr "開始"
+msgstr "正在開始"
 
 #. TRANSLATORS: transaction state, the transaction is waiting for another to complete
 #: ../lib/packagekit-glib2/pk-console-shared.c:258
 msgid "Waiting in queue"
-msgstr "在佇列中等待"
+msgstr "正在依佇列等待"
 
 #. TRANSLATORS: transaction state, just started
 #: ../lib/packagekit-glib2/pk-console-shared.c:262
 msgid "Running"
-msgstr "執行中"
+msgstr "正在執行"
 
 #. TRANSLATORS: transaction state, is querying data
 #: ../lib/packagekit-glib2/pk-console-shared.c:266
 msgid "Querying"
-msgstr "查詢中"
+msgstr "正在查詢"
 
 #. TRANSLATORS: transaction state, getting data from a server
 #: ../lib/packagekit-glib2/pk-console-shared.c:270
@@ -1116,101 +1137,101 @@ msgstr "正在取得資訊"
 #. TRANSLATORS: transaction state, removing packages
 #: ../lib/packagekit-glib2/pk-console-shared.c:274
 msgid "Removing packages"
-msgstr "移除套件中"
+msgstr "正在移除套件"
 
 #. TRANSLATORS: transaction state, downloading package files
 #. TRANSLATORS: The role of the transaction, in present tense
 #: ../lib/packagekit-glib2/pk-console-shared.c:278
 #: ../lib/packagekit-glib2/pk-console-shared.c:656
 msgid "Downloading packages"
-msgstr "下載套件中"
+msgstr "正在下載套件"
 
 #. TRANSLATORS: transaction state, refreshing internal lists
 #: ../lib/packagekit-glib2/pk-console-shared.c:286
 msgid "Refreshing software list"
-msgstr "正在更新軟體清單"
+msgstr "正在重新整理軟體清單"
 
 #. TRANSLATORS: transaction state, installing updates
 #: ../lib/packagekit-glib2/pk-console-shared.c:290
 msgid "Installing updates"
-msgstr "安裝更新"
+msgstr "正在安裝更新"
 
 #. TRANSLATORS: transaction state, removing old packages, and cleaning config files
 #: ../lib/packagekit-glib2/pk-console-shared.c:294
 msgid "Cleaning up packages"
-msgstr "正在清除套件"
+msgstr "正在清理套件"
 
 #. TRANSLATORS: transaction state, obsoleting old packages
 #: ../lib/packagekit-glib2/pk-console-shared.c:298
 msgid "Obsoleting packages"
-msgstr "正在淘汰套件"
+msgstr "正在廢棄套件"
 
 #. TRANSLATORS: transaction state, checking the transaction before we do it
 #: ../lib/packagekit-glib2/pk-console-shared.c:302
 msgid "Resolving dependencies"
-msgstr "正在解決相依性問題"
+msgstr "正在解析相依性"
 
 #. TRANSLATORS: transaction state, checking if we have all the security keys for the operation
 #: ../lib/packagekit-glib2/pk-console-shared.c:306
 msgid "Checking signatures"
-msgstr "正在檢查安全性簽署"
+msgstr "正在檢查簽章"
 
 #. TRANSLATORS: transaction state, when we return to a previous system state
 #. TRANSLATORS: The role of the transaction, in present tense
 #: ../lib/packagekit-glib2/pk-console-shared.c:310
 #: ../lib/packagekit-glib2/pk-console-shared.c:616
 msgid "Rolling back"
-msgstr "正在回溯"
+msgstr "正在回復"
 
 #. TRANSLATORS: transaction state, when we're doing a test transaction
 #: ../lib/packagekit-glib2/pk-console-shared.c:314
 msgid "Testing changes"
-msgstr "正在檢查變更"
+msgstr "正在測試變更"
 
 #. TRANSLATORS: transaction state, when we're writing to the system package database
 #: ../lib/packagekit-glib2/pk-console-shared.c:318
 msgid "Committing changes"
-msgstr "正在進行變動"
+msgstr "正在遞交變更"
 
 #. TRANSLATORS: transaction state, requesting data from a server
 #: ../lib/packagekit-glib2/pk-console-shared.c:322
 msgid "Requesting data"
-msgstr "求取資料中"
+msgstr "正在請求資料"
 
 #. TRANSLATORS: transaction state, all done!
 #: ../lib/packagekit-glib2/pk-console-shared.c:326
 msgid "Finished"
-msgstr "完成"
+msgstr "已完成"
 
 #. TRANSLATORS: transaction state, in the process of cancelling
 #: ../lib/packagekit-glib2/pk-console-shared.c:330
 msgid "Cancelling"
-msgstr "取消"
+msgstr "正在取消"
 
 #. TRANSLATORS: transaction state, downloading metadata
 #: ../lib/packagekit-glib2/pk-console-shared.c:334
 msgid "Downloading repository information"
-msgstr "正在下載軟體庫資訊"
+msgstr "正在下載套件庫資訊"
 
 #. TRANSLATORS: transaction state, downloading metadata
 #: ../lib/packagekit-glib2/pk-console-shared.c:338
 msgid "Downloading list of packages"
-msgstr "下載套件清單中"
+msgstr "正在下載套件清單"
 
 #. TRANSLATORS: transaction state, downloading metadata
 #: ../lib/packagekit-glib2/pk-console-shared.c:342
 msgid "Downloading file lists"
-msgstr "下載檔案清單中"
+msgstr "正在下載檔案清單"
 
 #. TRANSLATORS: transaction state, downloading metadata
 #: ../lib/packagekit-glib2/pk-console-shared.c:346
 msgid "Downloading lists of changes"
-msgstr "下載變更的清單中"
+msgstr "正在下載變更的清單"
 
 #. TRANSLATORS: transaction state, downloading metadata
 #: ../lib/packagekit-glib2/pk-console-shared.c:350
 msgid "Downloading groups"
-msgstr "下載群組中"
+msgstr "正在下載群組"
 
 #. TRANSLATORS: transaction state, downloading metadata
 #: ../lib/packagekit-glib2/pk-console-shared.c:354
@@ -1220,7 +1241,7 @@ msgstr "正在下載更新資訊"
 #. TRANSLATORS: transaction state, repackaging delta files
 #: ../lib/packagekit-glib2/pk-console-shared.c:358
 msgid "Repackaging files"
-msgstr "重新壓製檔案"
+msgstr "正在重新包裝檔案"
 
 #. TRANSLATORS: transaction state, loading databases
 #: ../lib/packagekit-glib2/pk-console-shared.c:362
@@ -1230,7 +1251,7 @@ msgstr "正在載入快取"
 #. TRANSLATORS: transaction state, scanning for running processes
 #: ../lib/packagekit-glib2/pk-console-shared.c:366
 msgid "Scanning applications"
-msgstr "掃描應用程式"
+msgstr "正在掃描應用程式"
 
 #. TRANSLATORS: transaction state, generating a list of packages installed on the system
 #: ../lib/packagekit-glib2/pk-console-shared.c:370
@@ -1240,47 +1261,47 @@ msgstr "正在產生套件清單"
 #. TRANSLATORS: transaction state, when we're waiting for the native tools to exit
 #: ../lib/packagekit-glib2/pk-console-shared.c:374
 msgid "Waiting for package manager lock"
-msgstr "正在等待套件管理員解除鎖定"
+msgstr "正在等候套件管程式解鎖"
 
 #. TRANSLATORS: transaction state, waiting for user to type in a password
 #: ../lib/packagekit-glib2/pk-console-shared.c:378
 msgid "Waiting for authentication"
-msgstr "正在等待授權"
+msgstr "正在等候認證"
 
 #. TRANSLATORS: transaction state, we are updating the list of processes
 #: ../lib/packagekit-glib2/pk-console-shared.c:382
 msgid "Updating running applications"
-msgstr "正在更新執行中的應用程式"
+msgstr "正在更新正在執行中的應用程式"
 
 #. TRANSLATORS: transaction state, we are checking executable files currently in use
 #: ../lib/packagekit-glib2/pk-console-shared.c:386
 msgid "Checking applications in use"
-msgstr "檢查使用中的應用程式"
+msgstr "正在檢查使用中的應用程式"
 
 #. TRANSLATORS: transaction state, we are checking for libraries currently in use
 #: ../lib/packagekit-glib2/pk-console-shared.c:390
 msgid "Checking libraries in use"
-msgstr "檢查使用中的函式庫"
+msgstr "正在檢查使用中的函式庫"
 
 #. TRANSLATORS: transaction state, we are copying package files before or after the transaction
 #: ../lib/packagekit-glib2/pk-console-shared.c:394
 msgid "Copying files"
-msgstr "複製檔案"
+msgstr "正在複製檔案"
 
 #. TRANSLATORS: The type of update
 #: ../lib/packagekit-glib2/pk-console-shared.c:412
 msgid "Trivial"
-msgstr "不重要的"
+msgstr "小"
 
 #. TRANSLATORS: The type of update
 #: ../lib/packagekit-glib2/pk-console-shared.c:416
 msgid "Normal"
-msgstr "正常的"
+msgstr "一般"
 
 #. TRANSLATORS: The type of update
 #: ../lib/packagekit-glib2/pk-console-shared.c:420
 msgid "Important"
-msgstr "重要的"
+msgstr "重大"
 
 #. TRANSLATORS: The type of update
 #: ../lib/packagekit-glib2/pk-console-shared.c:424
@@ -1290,17 +1311,17 @@ msgstr "安全性"
 #. TRANSLATORS: The type of update
 #: ../lib/packagekit-glib2/pk-console-shared.c:428
 msgid "Bug fix "
-msgstr "修正 bug"
+msgstr "錯誤修正"
 
 #. TRANSLATORS: The type of update
 #: ../lib/packagekit-glib2/pk-console-shared.c:432
 msgid "Enhancement"
-msgstr "加強"
+msgstr "增強"
 
 #. TRANSLATORS: The type of update
 #: ../lib/packagekit-glib2/pk-console-shared.c:436
 msgid "Blocked"
-msgstr "已阻絕的"
+msgstr "已阻擋"
 
 #. TRANSLATORS: The state of a package
 #. TRANSLATORS: The action of the package, in past tense
@@ -1312,86 +1333,86 @@ msgstr "已安裝的"
 #. TRANSLATORS: The state of a package, i.e. not installed
 #: ../lib/packagekit-glib2/pk-console-shared.c:446
 msgid "Available"
-msgstr "可用的"
+msgstr "可用"
 
 #. TRANSLATORS: The action of the package, in present tense
 #: ../lib/packagekit-glib2/pk-console-shared.c:464
 msgid "Downloading"
-msgstr "下載中"
+msgstr "正在下載"
 
 #. TRANSLATORS: The action of the package, in present tense
 #: ../lib/packagekit-glib2/pk-console-shared.c:468
 msgid "Updating"
-msgstr "更新中"
+msgstr "正在更新"
 
 #. TRANSLATORS: The action of the package, in present tense
 #. TRANSLATORS: The role of the transaction, in present tense
 #: ../lib/packagekit-glib2/pk-console-shared.c:472
 #: ../lib/packagekit-glib2/pk-console-shared.c:592
 msgid "Installing"
-msgstr "安裝中"
+msgstr "正在安裝"
 
 #. TRANSLATORS: The action of the package, in present tense
 #. TRANSLATORS: The role of the transaction, in present tense
 #: ../lib/packagekit-glib2/pk-console-shared.c:476
 #: ../lib/packagekit-glib2/pk-console-shared.c:588
 msgid "Removing"
-msgstr "移除中"
+msgstr "正在移除"
 
 #. TRANSLATORS: The action of the package, in present tense
 #: ../lib/packagekit-glib2/pk-console-shared.c:480
 msgid "Cleaning up"
-msgstr "清除中"
+msgstr "正在清除"
 
 #. TRANSLATORS: The action of the package, in present tense
 #: ../lib/packagekit-glib2/pk-console-shared.c:484
 msgid "Obsoleting"
-msgstr "已淘汰的"
+msgstr "正在廢棄"
 
 #. TRANSLATORS: The action of the package, in present tense
 #: ../lib/packagekit-glib2/pk-console-shared.c:488
 msgid "Reinstalling"
-msgstr "重新安裝中"
+msgstr "正在重新安裝"
 
 #. TRANSLATORS: The action of the package, in past tense
 #: ../lib/packagekit-glib2/pk-console-shared.c:506
 msgid "Downloaded"
-msgstr "已下載的"
+msgstr "已下載"
 
 #. TRANSLATORS: The action of the package, in past tense
 #: ../lib/packagekit-glib2/pk-console-shared.c:518
 msgid "Removed"
-msgstr "已移除的"
+msgstr "已移除"
 
 #. TRANSLATORS: The action of the package, in past tense
 #: ../lib/packagekit-glib2/pk-console-shared.c:522
 msgid "Cleaned up"
-msgstr "已清除的"
+msgstr "已清除"
 
 #. TRANSLATORS: The action of the package, in past tense
 #: ../lib/packagekit-glib2/pk-console-shared.c:526
 msgid "Obsoleted"
-msgstr "已淘汰的"
+msgstr "已廢棄"
 
 #. TRANSLATORS: The action of the package, in past tense
 #: ../lib/packagekit-glib2/pk-console-shared.c:530
 msgid "Reinstalled"
-msgstr "已重新安裝的"
+msgstr "已重新安裝"
 
 #. TRANSLATORS: The role of the transaction, in present tense
 #: ../lib/packagekit-glib2/pk-console-shared.c:548
 msgid "Unknown role type"
-msgstr "未知的類型"
+msgstr "未知的任務類型"
 
 #. TRANSLATORS: The role of the transaction, in present tense
 #: ../lib/packagekit-glib2/pk-console-shared.c:552
 msgid "Getting dependencies"
-msgstr "取得相依性中"
+msgstr "正在取得相容性"
 
 #. TRANSLATORS: The role of the transaction, in present tense
 #: ../lib/packagekit-glib2/pk-console-shared.c:556
 msgid "Getting update details"
-msgstr "正在取得更新套件"
+msgstr "正在取得更新詳細資料"
 
 #. TRANSLATORS: The role of the transaction, in present tense
 #: ../lib/packagekit-glib2/pk-console-shared.c:560
@@ -1401,7 +1422,7 @@ msgstr "正在取得詳細資料"
 #. TRANSLATORS: The role of the transaction, in present tense
 #: ../lib/packagekit-glib2/pk-console-shared.c:564
 msgid "Getting requires"
-msgstr "正在取得所需的"
+msgstr "正在取得需求"
 
 #. TRANSLATORS: The role of the transaction, in present tense
 #: ../lib/packagekit-glib2/pk-console-shared.c:568
@@ -1411,22 +1432,22 @@ msgstr "正在取得更新"
 #. TRANSLATORS: The role of the transaction, in present tense
 #: ../lib/packagekit-glib2/pk-console-shared.c:572
 msgid "Searching by details"
-msgstr "藉由詳細資料搜尋"
+msgstr "正在依詳細資料搜尋"
 
 #. TRANSLATORS: The role of the transaction, in present tense
 #: ../lib/packagekit-glib2/pk-console-shared.c:576
 msgid "Searching by file"
-msgstr "藉由檔案搜尋"
+msgstr "正在依檔案搜尋"
 
 #. TRANSLATORS: The role of the transaction, in present tense
 #: ../lib/packagekit-glib2/pk-console-shared.c:580
 msgid "Searching groups"
-msgstr "搜尋群組"
+msgstr "正在搜尋群組"
 
 #. TRANSLATORS: The role of the transaction, in present tense
 #: ../lib/packagekit-glib2/pk-console-shared.c:584
 msgid "Searching by name"
-msgstr "藉由名稱搜尋"
+msgstr "正在依名稱搜尋"
 
 #. TRANSLATORS: The role of the transaction, in present tense
 #: ../lib/packagekit-glib2/pk-console-shared.c:596
@@ -1436,7 +1457,7 @@ msgstr "正在安裝檔案"
 #. TRANSLATORS: The role of the transaction, in present tense
 #: ../lib/packagekit-glib2/pk-console-shared.c:600
 msgid "Refreshing cache"
-msgstr "更新快取"
+msgstr "正在重新整理快取"
 
 #. TRANSLATORS: The role of the transaction, in present tense
 #: ../lib/packagekit-glib2/pk-console-shared.c:604
@@ -1451,17 +1472,17 @@ msgstr "正在更新系統"
 #. TRANSLATORS: The role of the transaction, in present tense
 #: ../lib/packagekit-glib2/pk-console-shared.c:612
 msgid "Canceling"
-msgstr "取消中"
+msgstr "正在取消"
 
 #. TRANSLATORS: The role of the transaction, in present tense
 #: ../lib/packagekit-glib2/pk-console-shared.c:620
 msgid "Getting repositories"
-msgstr "正在取得軟體庫"
+msgstr "正在取得套件庫"
 
 #. TRANSLATORS: The role of the transaction, in present tense
 #: ../lib/packagekit-glib2/pk-console-shared.c:624
 msgid "Enabling repository"
-msgstr "正在啟用軟體庫"
+msgstr "正在啟用套件庫"
 
 #. TRANSLATORS: The role of the transaction, in present tense
 #: ../lib/packagekit-glib2/pk-console-shared.c:628
@@ -1471,7 +1492,7 @@ msgstr "正在設定資料"
 #. TRANSLATORS: The role of the transaction, in present tense
 #: ../lib/packagekit-glib2/pk-console-shared.c:632
 msgid "Resolving"
-msgstr "正在解決"
+msgstr "正在解析"
 
 #. TRANSLATORS: The role of the transaction, in present tense
 #: ../lib/packagekit-glib2/pk-console-shared.c:636
@@ -1481,12 +1502,12 @@ msgstr "正在取得檔案清單"
 #. TRANSLATORS: The role of the transaction, in present tense
 #: ../lib/packagekit-glib2/pk-console-shared.c:640
 msgid "Getting provides"
-msgstr "正在取得提供套件的資料"
+msgstr "正在取得提供什麼"
 
 #. TRANSLATORS: The role of the transaction, in present tense
 #: ../lib/packagekit-glib2/pk-console-shared.c:644
 msgid "Installing signature"
-msgstr "正在安裝簽名"
+msgstr "正在安裝簽章"
 
 #. TRANSLATORS: The role of the transaction, in present tense
 #: ../lib/packagekit-glib2/pk-console-shared.c:648
@@ -1496,22 +1517,22 @@ msgstr "正在取得套件"
 #. TRANSLATORS: The role of the transaction, in present tense
 #: ../lib/packagekit-glib2/pk-console-shared.c:652
 msgid "Accepting EULA"
-msgstr "正在接受 EULA"
+msgstr "正在接受終端使用者授權同意書"
 
 #. TRANSLATORS: The role of the transaction, in present tense
 #: ../lib/packagekit-glib2/pk-console-shared.c:660
 msgid "Getting upgrades"
-msgstr "正在取得更新"
+msgstr "正在取得升級"
 
 #. TRANSLATORS: The role of the transaction, in present tense
 #: ../lib/packagekit-glib2/pk-console-shared.c:664
 msgid "Getting categories"
-msgstr "正在取得類別"
+msgstr "正在取得分類"
 
 #. TRANSLATORS: The role of the transaction, in present tense
 #: ../lib/packagekit-glib2/pk-console-shared.c:668
 msgid "Getting transactions"
-msgstr "正在取得交易"
+msgstr "正在取得處理事項"
 
 #. TRANSLATORS: The role of the transaction, in present tense
 #: ../lib/packagekit-glib2/pk-console-shared.c:672
@@ -1532,12 +1553,12 @@ msgstr "正在模擬更新"
 #. TRANSLATORS: ask the user if they are comfortable installing insecure packages
 #: ../lib/packagekit-glib2/pk-task-text.c:69
 msgid "Do you want to allow installing of unsigned software?"
-msgstr "是否允許安裝未簽署的軟體?"
+msgstr "您想要允許未簽署軟體的安裝嗎?"
 
 #. TRANSLATORS: tell the user we've not done anything
 #: ../lib/packagekit-glib2/pk-task-text.c:74
 msgid "The unsigned software will not be installed."
-msgstr "不會安裝未簽署的軟體。"
+msgstr "未簽署的軟體不會被安裝。"
 
 #. TRANSLATORS: the package repository is signed by a key that is not recognised
 #: ../lib/packagekit-glib2/pk-task-text.c:123
@@ -1552,12 +1573,12 @@ msgstr "軟體來源名稱"
 #. TRANSLATORS: the key URL
 #: ../lib/packagekit-glib2/pk-task-text.c:132
 msgid "Key URL"
-msgstr "金鑰的 URL"
+msgstr "金鑰 URL"
 
 #. TRANSLATORS: the username of the key
 #: ../lib/packagekit-glib2/pk-task-text.c:135
 msgid "Key user"
-msgstr "金鑰的使用者"
+msgstr "金鑰使用者"
 
 #. TRANSLATORS: the key ID, usually a few hex digits
 #: ../lib/packagekit-glib2/pk-task-text.c:138
@@ -1567,12 +1588,12 @@ msgstr "金鑰 ID"
 #. TRANSLATORS: the key fingerprint, again, yet more hex
 #: ../lib/packagekit-glib2/pk-task-text.c:141
 msgid "Key fingerprint"
-msgstr "金鑰的指紋"
+msgstr "金鑰指紋"
 
 #. TRANSLATORS: the timestamp (a bit like a machine readable time)
 #: ../lib/packagekit-glib2/pk-task-text.c:144
 msgid "Key Timestamp"
-msgstr "金鑰的時間戳記"
+msgstr "金鑰時間戳記"
 
 #. TRANSLATORS: ask the user if they want to import
 #: ../lib/packagekit-glib2/pk-task-text.c:157
@@ -1587,37 +1608,37 @@ msgstr "簽章未被接受。"
 #. TRANSLATORS: this is another name for a software licence that has to be read before installing
 #: ../lib/packagekit-glib2/pk-task-text.c:205
 msgid "End user licence agreement required"
-msgstr "需要終端用戶授權協議"
+msgstr "需要接受終端使用者授權同意書"
 
 #. TRANSLATORS: the EULA text itself (long and boring)
 #: ../lib/packagekit-glib2/pk-task-text.c:214
 msgid "Agreement"
-msgstr "協議"
+msgstr "同意書"
 
 #. TRANSLATORS: ask the user if they've read and accepted the EULA
 #: ../lib/packagekit-glib2/pk-task-text.c:223
 msgid "Do you accept this agreement?"
-msgstr "您是否接受此協議?"
+msgstr "您是否接受此同意書?"
 
 #. TRANSLATORS: tell the user we've not done anything
 #: ../lib/packagekit-glib2/pk-task-text.c:228
 msgid "The agreement was not accepted."
-msgstr "協議未被接受。"
+msgstr "同意書未被接受。"
 
 #. TRANSLATORS: the user needs to change media inserted into the computer
 #: ../lib/packagekit-glib2/pk-task-text.c:267
 msgid "Media change required"
-msgstr "需要變更媒介"
+msgstr "需要變更媒體"
 
 #. TRANSLATORS: the type, e.g. DVD, CD, etc
 #: ../lib/packagekit-glib2/pk-task-text.c:270
 msgid "Media type"
-msgstr "媒介類型"
+msgstr "媒體類型"
 
 #. TRANSLATORS: the media label, usually like 'disk-1of3'
 #: ../lib/packagekit-glib2/pk-task-text.c:273
 msgid "Media label"
-msgstr "媒介的標籤"
+msgstr "媒體標籤"
 
 #. TRANSLATORS: the media description, usually like 'Fedora 12 disk 5'
 #: ../lib/packagekit-glib2/pk-task-text.c:276
@@ -1627,12 +1648,12 @@ msgstr "文字"
 #. TRANSLATORS: ask the user to insert the media
 #: ../lib/packagekit-glib2/pk-task-text.c:282
 msgid "Please insert the correct media"
-msgstr "請插入正確的媒介"
+msgstr "請插入正確的媒體"
 
 #. TRANSLATORS: tell the user we've not done anything as they are lazy
 #: ../lib/packagekit-glib2/pk-task-text.c:287
 msgid "The correct media was not inserted."
-msgstr "並未插入正確的媒介"
+msgstr "沒有插入正確的媒體。"
 
 #. TRANSLATORS: When processing, we might have to remove other dependencies
 #: ../lib/packagekit-glib2/pk-task-text.c:302
@@ -1642,32 +1663,32 @@ msgstr "下列套件必須被移除掉:"
 #. TRANSLATORS: When processing, we might have to install other dependencies
 #: ../lib/packagekit-glib2/pk-task-text.c:307
 msgid "The following packages have to be installed:"
-msgstr "必須安裝以下套件:"
+msgstr "下列套件要被安裝:"
 
 #. TRANSLATORS: When processing, we might have to update other dependencies
 #: ../lib/packagekit-glib2/pk-task-text.c:312
 msgid "The following packages have to be updated:"
-msgstr "必須更新以下套件:"
+msgstr "下列套件要被更新:"
 
 #. TRANSLATORS: When processing, we might have to reinstall other dependencies
 #: ../lib/packagekit-glib2/pk-task-text.c:317
 msgid "The following packages have to be reinstalled:"
-msgstr "必須重新安裝以下套件:"
+msgstr "下列套件要被重新安裝:"
 
 #. TRANSLATORS: When processing, we might have to downgrade other dependencies
 #: ../lib/packagekit-glib2/pk-task-text.c:322
 msgid "The following packages have to be downgraded:"
-msgstr "必須降級以下套件:"
+msgstr "下列套件要被降級:"
 
 #. TRANSLATORS: ask the user if the proposed changes are okay
 #: ../lib/packagekit-glib2/pk-task-text.c:382
 msgid "Proceed with changes?"
-msgstr "是否進行變更?"
+msgstr "要處理變更嗎?"
 
 #. TRANSLATORS: tell the user we didn't do anything
 #: ../lib/packagekit-glib2/pk-task-text.c:387
 msgid "The transaction did not proceed."
-msgstr "交易並未進行。"
+msgstr "這個處理事項沒有進行。"
 
 #. SECURITY:
 #. - Normal users do not require admin authentication to accept new
@@ -1677,25 +1698,23 @@ msgstr "交易並未進行。"
 #.
 #: ../policy/org.freedesktop.packagekit.policy.in.h:7
 msgid "Accept EULA"
-msgstr "接受 EULA"
+msgstr "接受終端使用者授權條款協議"
 
 #: ../policy/org.freedesktop.packagekit.policy.in.h:8
 msgid "Authentication is required to accept a EULA"
-msgstr "要接受 EULA 需先經過身份認證"
+msgstr "要接受終端使用者授權條款協議需先經過身份認證"
 
 #: ../policy/org.freedesktop.packagekit.policy.in.h:9
 msgid "Authentication is required to cancel a task that was not started by yourself"
-msgstr "若要取消一項並非您自行啟動的工作,您必須先經過身份認證"
+msgstr "若要取消一項並非由您啟動的工作,您必須先經過身份認證"
 
 #: ../policy/org.freedesktop.packagekit.policy.in.h:10
 msgid "Authentication is required to change software source parameters"
 msgstr "要更改軟體來源參數需先經過身份認證"
 
 #: ../policy/org.freedesktop.packagekit.policy.in.h:11
-msgid ""
-"Authentication is required to consider a key used for signing packages as "
-"trusted"
-msgstr "要將一個用來簽署套件的金鑰列為信任的金鑰需先經過身份認證"
+msgid "Authentication is required to consider a key used for signing packages as trusted"
+msgstr "要將一個用來簽署套件的金鑰列為已信任的金鑰需先經過身份認證"
 
 #: ../policy/org.freedesktop.packagekit.policy.in.h:12
 msgid "Authentication is required to install a signed package"
@@ -1703,15 +1722,15 @@ msgstr "要安裝一個已簽署的套件需先經過身份認證"
 
 #: ../policy/org.freedesktop.packagekit.policy.in.h:13
 msgid "Authentication is required to install an untrusted package"
-msgstr "要安裝非信任的套件需先經過身份認證"
+msgstr "要安裝未信任的套件需先經過身份認證"
 
 #: ../policy/org.freedesktop.packagekit.policy.in.h:14
 msgid "Authentication is required to refresh the system sources"
-msgstr "要刷新系統來源需先經過身份認證"
+msgstr "要重新整理系統來源需先經過身份認證"
 
 #: ../policy/org.freedesktop.packagekit.policy.in.h:15
 msgid "Authentication is required to reload the device with a new driver"
-msgstr "要使用新的驅動程式來重新載入裝置,需要先經過身份認證"
+msgstr "要以新驅動程式重新載入裝置的話需要通過認證"
 
 #: ../policy/org.freedesktop.packagekit.policy.in.h:16
 msgid "Authentication is required to remove packages"
@@ -1719,13 +1738,11 @@ msgstr "要移除套件需先經過身份認證"
 
 #: ../policy/org.freedesktop.packagekit.policy.in.h:17
 msgid "Authentication is required to rollback a transaction"
-msgstr "要復原一筆交易,需先經過身份認證"
+msgstr "要回復處理事項需要先經過身份認證"
 
 #: ../policy/org.freedesktop.packagekit.policy.in.h:18
-msgid ""
-"Authentication is required to set the network proxy used for downloading "
-"packages"
-msgstr "要設定用來下載套件的網路 proxy 需先經過身份認證"
+msgid "Authentication is required to set the network proxy used for downloading packages"
+msgstr "要設定用來下載套件的網路代理伺服器 需先經過身份認證"
 
 #: ../policy/org.freedesktop.packagekit.policy.in.h:19
 msgid "Authentication is required to update packages"
@@ -1767,7 +1784,7 @@ msgstr "安裝已簽署的套件"
 #.
 #: ../policy/org.freedesktop.packagekit.policy.in.h:45
 msgid "Install untrusted local file"
-msgstr "安裝非信任的本地檔案"
+msgstr "安裝未信任的本地檔案"
 
 #. SECURITY:
 #. - Normal users do not require admin authentication to refresh the
@@ -1775,7 +1792,7 @@ msgstr "安裝非信任的本地檔案"
 #.
 #: ../policy/org.freedesktop.packagekit.policy.in.h:50
 msgid "Refresh system sources"
-msgstr "刷新系統來源"
+msgstr "重新整理系統來源"
 
 #. SECURITY:
 #. - Normal users require admin authentication to rebind a driver
@@ -1808,7 +1825,7 @@ msgstr "移除套件"
 #.
 #: ../policy/org.freedesktop.packagekit.policy.in.h:74
 msgid "Rollback to a previous transaction"
-msgstr "復原至先前的交易"
+msgstr "回復至上一個處理事項"
 
 #. SECURITY:
 #. - Normal users do not require admin authentication to set the proxy
@@ -1816,7 +1833,7 @@ msgstr "復原至先前的交易"
 #.
 #: ../policy/org.freedesktop.packagekit.policy.in.h:79
 msgid "Set network proxy"
-msgstr "設定網路 proxy"
+msgstr "設定網路代理伺服器"
 
 #. SECURITY:
 #. - Normal users require admin authentication to add signing keys.
@@ -1856,20 +1873,18 @@ msgstr "正確的用戶(一般為 root)沒有執行可執行檔"
 
 #. TRANSLATORS: or we are installed in a prefix
 #: ../src/pk-main.c:93
-msgid ""
-"The org.freedesktop.PackageKit.conf file is not installed in the system "
-"directory:"
+msgid "The org.freedesktop.PackageKit.conf file is not installed in the system directory:"
 msgstr "org.freedesktop.PackageKit.conf 檔案尚未安裝在系統目錄中:"
 
 #. TRANSLATORS: a backend is the system package tool, e.g. yum, apt
 #: ../src/pk-main.c:199
 msgid "Packaging backend to use, e.g. dummy"
-msgstr "欲使用的套件後端,例如「dummy」"
+msgstr "要使用的套件後端程式,例如:dummy"
 
 #. TRANSLATORS: if we should run in the background
 #: ../src/pk-main.c:202
 msgid "Daemonize and detach from the terminal"
-msgstr "Daemon 化並由終端機分離"
+msgstr "幕後化並由終端機分離"
 
 #. TRANSLATORS: if we should not monitor how long we are inactive for
 #: ../src/pk-main.c:205
@@ -1879,17 +1894,17 @@ msgstr "停用閒置計時器"
 #. TRANSLATORS: show version
 #: ../src/pk-main.c:208
 msgid "Show version and exit"
-msgstr "顯示版本並退出"
+msgstr "顯示版本並離開"
 
 #. TRANSLATORS: exit after we've started up, used for user profiling
 #: ../src/pk-main.c:211
 msgid "Exit after a small delay"
-msgstr "經過了短暫的延遲後退出"
+msgstr "經過一段短暫延遲後便離開"
 
 #. TRANSLATORS: exit straight away, used for automatic profiling
 #: ../src/pk-main.c:214
 msgid "Exit after the engine has loaded"
-msgstr "引擎載入後退出"
+msgstr "引擎載入後離開"
 
 #. TRANSLATORS: describing the service that is running
 #: ../src/pk-main.c:229
@@ -1899,7 +1914,7 @@ msgstr "PackageKit 服務"
 #. TRANSLATORS: fatal error, dbus is not running
 #: ../src/pk-main.c:266
 msgid "Cannot connect to the system bus"
-msgstr "無法連至系統 bus"
+msgstr "無法連接至系統 bus"
 
 #. TRANSLATORS: cannot register on system bus, unknown reason -- geeky error follows
 #: ../src/pk-main.c:317
@@ -1908,28 +1923,29 @@ msgstr "嘗試啟動時發生錯誤:"
 
 #: ../src/pk-polkit-action-lookup.c:150
 msgid "To install debugging packages, extra sources need to be enabled"
-msgstr "要安裝 debug 套件,需要啟用額外資源"
+msgstr "要安裝除錯套件,需要啟用額外的來源"
 
 #. TRANSLATORS: is not GPG signed
-#: ../src/pk-polkit-action-lookup.c:171 ../src/pk-polkit-action-lookup.c:190
+#: ../src/pk-polkit-action-lookup.c:171
+#: ../src/pk-polkit-action-lookup.c:190
 msgid "The software is not from a trusted source."
-msgstr "軟體並非來自受信任的來源。"
+msgstr "這個軟體並非來自信任的來源。"
 
 #: ../src/pk-polkit-action-lookup.c:176
 msgid "Do not update this package unless you are sure it is safe to do so."
-msgstr "除非您確定安裝這套件是安全的,否則請勿更新。"
+msgstr "請不要更新此套件,除非您確定這樣做是安全的。"
 
 #: ../src/pk-polkit-action-lookup.c:177
 msgid "Do not update these packages unless you are sure it is safe to do so."
-msgstr "除非您確定安裝這些套件是安全的,否則請勿更新。"
+msgstr "請不要更新這些套件,除非您確定這樣做是安全的。"
 
 #: ../src/pk-polkit-action-lookup.c:195
 msgid "Do not install this package unless you are sure it is safe to do so."
-msgstr "除非您確定安裝這套件是安全的,否則請勿安裝。"
+msgstr "請不要安裝此套件,除非您確定這樣做是安全的。"
 
 #: ../src/pk-polkit-action-lookup.c:196
 msgid "Do not install these packages unless you are sure it is safe to do so."
-msgstr "除非您確定安裝這些套件是安全的,否則請勿安裝。"
+msgstr "請不要安裝這些套件,除非您確定這樣做是安全的。"
 
 #. TRANSLATORS: too many packages to list each one
 #: ../src/pk-polkit-action-lookup.c:273
@@ -1939,33 +1955,98 @@ msgstr "許多套件"
 #. TRANSLATORS: if the transaction is forced to install only trusted packages
 #: ../src/pk-polkit-action-lookup.c:339
 msgid "Only trusted"
-msgstr "只有受信任的"
+msgstr "只有信任的"
 
 #. TRANSLATORS: turn on all debugging
 #: ../src/egg-debug.c:388
 msgid "Show debugging information for all files"
-msgstr "顯示所有檔案的 debug 資訊"
+msgstr "顯示供所有檔案用的額外除錯資訊"
 
 #. TRANSLATORS: a list of modules to debug
 #: ../src/egg-debug.c:459
 msgid "Debug these specific modules"
-msgstr "debug 這些特定模組"
+msgstr "針對這些指定的模組除錯"
 
 #. TRANSLATORS: a list of functions to debug
 #: ../src/egg-debug.c:462
 msgid "Debug these specific functions"
-msgstr "debug 這些特定功能"
+msgstr "針對這些指定的功能除錯"
 
 #. TRANSLATORS: save to a log
 #: ../src/egg-debug.c:465
 msgid "Log debugging data to a file"
-msgstr "將 debug 資料寫入檔案"
+msgstr "將除錯資料紀錄到檔案"
 
 #: ../src/egg-debug.c:469
 msgid "Debugging Options"
-msgstr "Debug 的選項"
+msgstr "除錯選項"
 
 #: ../src/egg-debug.c:469
 msgid "Show debugging options"
-msgstr "顯示 debug 選項"
+msgstr "顯示除錯選項"
+
+#~ msgid "Cannot install when offline"
+#~ msgstr "當離線時無法安裝"
+#~ msgid "Cannot refresh cache whilst offline"
+#~ msgstr "當離線時無法重新整理快取"
+#~ msgid "Please restart the application as it is being used."
+#~ msgstr "請重新啟動應用程式因為該應用程式正被使用中。"
+#~ msgid "This tool could not install the files: %s"
+#~ msgstr "此工具無法安裝檔案:%s"
+#~ msgid "This tool could not remove %s: %s"
+#~ msgstr "此工具無法移除 %s:%s"
+#~ msgid "This tool could not remove the packages: %s"
+#~ msgstr "此工具無法移除套件:%s"
+#~ msgid "Proceed removing additional packages?"
+#~ msgstr "是否要進行移除額外套件?"
+#~ msgid "The package removal was canceled!"
+#~ msgstr "套件移除已取消!"
+#~ msgid "This tool could not download the package %s as it could not be found"
+#~ msgstr "此工具無法下載 %s 套件因為找不到該套件"
+#~ msgid "This tool could not download the packages: %s"
+#~ msgstr "此工具無法下載套件:%s"
+#~ msgid "This tool could not update %s: %s"
+#~ msgstr "此工具無法更新 %s:%s"
+#~ msgid "This tool could not get the requirements for %s: %s"
+#~ msgstr "此工具無法取得 %s 的需求:%s"
+#~ msgid "This tool could not get the dependencies for %s: %s"
+#~ msgstr "此工具無法取得 %s 的相依性:%s"
+#~ msgid "This tool could not get package details for %s: %s"
+#~ msgstr "此工具無法取得 %s 的套件詳細資料:%s"
+#~ msgid "This tool could not find the files for %s: %s"
+#~ msgstr "此工具找不到 %s 的檔案:%s"
+#~ msgid "This tool could not get the file list for %s: %s"
+#~ msgstr "此工具無法取得 %s 的檔案清單:%s"
+#~ msgid "File already exists: %s"
+#~ msgstr "檔案已經存在:%s"
+#~ msgid "This tool could not get package list: %s"
+#~ msgstr "此工具無法取得套件清單:%s"
+#~ msgid "File does not exist: %s"
+#~ msgstr "檔案不存在:%s"
+#~ msgid "Packages to add"
+#~ msgstr "要新增的套件"
+#~ msgid "Packages to remove"
+#~ msgstr "要移除的套件"
+#~ msgid "not found."
+#~ msgstr "找不到。"
+#~ msgid "No packages can be found to install"
+#~ msgstr "找不到要安裝的套件"
+#~ msgid "This tool could not find the update details for %s: %s"
+#~ msgstr "此工具找不到 %s 的更新詳細資料:%s"
+#~ msgid "This tool could not get the update details for %s: %s"
+#~ msgstr "此工具無法取得 %s 的更新詳細資料:%s"
+#~ msgid "Error:"
+#~ msgstr "錯誤:"
+#~ msgid "Do you agree to this license?"
+#~ msgstr "您是否同意此授權合約?"
+#~ msgid "The license was refused."
+#~ msgstr "已拒絕授權合約。"
+#~ msgid "This tool could not connect to system DBUS."
+#~ msgstr "此工具無法連接至系統的 DBUS。"
+#~ msgid "A list file name to create is required"
+#~ msgstr "需要想建立的清單檔名"
+#~ msgid "A list file to open is required"
+#~ msgstr "需要想開啟的清單檔案"
+#~ msgid "Incorrect privileges for this operation"
+#~ msgstr "執行這項操作的權限不對"
 
commit 6306c1879fcc1a3e93269afa45eb3eaffed040b2
Author: logan <logan at fedoraproject.org>
Date:   Tue Mar 9 12:41:03 2010 +0000

    Sending translation for Spanish

diff --git a/po/es.po b/po/es.po
index ca885e3..6b63057 100644
--- a/po/es.po
+++ b/po/es.po
@@ -3,16 +3,17 @@
 #
 # Javier Alejandro Castro <javier.alejandro.castro at gmail.com>, 2008.
 # Jorge González <jorgegonz at svn.gnome.org>, 2009.
-# Héctor Daniel Cabrera <logan at fedoraproject.org>, 2009.
 # Fernando Gonzalez Blanco <fgonz at fedoraproject.org>, 2009.
+# Héctor Daniel Cabrera <logan at fedoraproject.org>, 2009, 2010.
+#
 msgid ""
 msgstr ""
 "Project-Id-Version: packagekit\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2010-01-15 09:07+0000\n"
-"PO-Revision-Date: 2010-01-15 11:12-0300\n"
-"Last-Translator: Claudio Rodrigo Pereyra Diaz <claudio at pereyradiaz.com.ar>\n"
-"Language-Team: Fedora Spanish <fedora-trans-es at redhat.com>\n"
+"POT-Creation-Date: 2010-03-09 09:20+0000\n"
+"PO-Revision-Date: 2010-03-09 09:39-0300\n"
+"Last-Translator: Héctor Daniel Cabrera <logan at fedoraproject.org>\n"
+"Language-Team: Fedora Spanish <trans-es at lists.fedoraproject.org>\n"
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
@@ -278,68 +279,72 @@ msgid "Status"
 msgstr "Estado"
 
 #. TRANSLATORS: the results from the transaction
-#: ../client/pk-console.c:678
+#: ../client/pk-console.c:679
 msgid "Results:"
 msgstr "Resultados:"
 
 #. TRANSLATORS: we failed to get any results, which is pretty fatal in my book
-#: ../client/pk-console.c:685
+#: ../client/pk-console.c:686
 msgid "Fatal error"
 msgstr "Error fatal"
 
 #. TRANSLATORS: the transaction failed in a way we could not expect
-#: ../client/pk-console.c:694
+#: ../client/pk-console.c:695
 #: ../contrib/command-not-found/pk-command-not-found.c:432
 #: ../contrib/command-not-found/pk-command-not-found.c:603
 msgid "The transaction failed"
 msgstr "La transacción no pudo realizarse"
 
 #. TRANSLATORS: print a message when there are no updates
-#: ../client/pk-console.c:721
+#: ../client/pk-console.c:726
 msgid "There are no updates available at this time."
 msgstr "No hay actualizaciones disponibles en este momento."
 
+#: ../client/pk-console.c:749
+msgid "There are no upgrades available at this time."
+msgstr "En este momento no existen actualizaciones disponibles."
+
 #. TRANSLATORS: a package needs to restart their system
-#: ../client/pk-console.c:808
+#: ../client/pk-console.c:816
 msgid "Please restart the computer to complete the update."
 msgstr "Reinicie el equipo para completar la actualización."
 
 #. TRANSLATORS: a package needs to restart the session
-#: ../client/pk-console.c:811
+#: ../client/pk-console.c:819
 msgid "Please logout and login to complete the update."
 msgstr "Cierre la sesión y vuelva a entrar para completar la actualización."
 
 #. TRANSLATORS: a package needs to restart their system (due to security)
-#: ../client/pk-console.c:814
+#: ../client/pk-console.c:822
 msgid "Please restart the computer to complete the update as important security updates have been installed."
 msgstr "Por favor, reinicie el equipo para completar la actualización, ya que se han instalado actualizaciones de seguridad importantes."
 
 #. TRANSLATORS: a package needs to restart the session (due to security)
-#: ../client/pk-console.c:817
+#: ../client/pk-console.c:825
 msgid "Please logout and login to complete the update as important security updates have been installed."
 msgstr "Por favor, cierre la sesión y vuelva a registrarse para completar la actualización, ya que se han instalado actualizaciones de seguridad importantes."
 
 #. TRANSLATORS: The user used 'pkcon install dave.rpm' rather than 'pkcon install-local dave.rpm'
-#: ../client/pk-console.c:843
+#: ../client/pk-console.c:851
 #, c-format
 msgid "Extected package name, actually got file. Try using 'pkcon install-local %s' instead."
 msgstr "Nombre de paquete esperado, actualmente tiene archivo. Trate de usar 'pkcon install-local %s' en su lugar."
 
 #. TRANSLATORS: There was an error getting the list of files for the package. The detailed error follows
-#: ../client/pk-console.c:851
+#: ../client/pk-console.c:859
 #, c-format
 msgid "This tool could not find any available package: %s"
 msgstr "Esta herramienta no pudo encontrar ningún paquete disponible: %s"
 
 #. TRANSLATORS: There was an error getting the list of files for the package. The detailed error follows
-#: ../client/pk-console.c:879
+#: ../client/pk-console.c:887
 #, c-format
 msgid "This tool could not find the installed package: %s"
 msgstr "Esta herramienta no pudo encontrar el paquete instalado: %s"
 
 #. TRANSLATORS: There was an error getting the list of files for the package. The detailed error follows
-#: ../client/pk-console.c:907
-#: ../client/pk-console.c:935
+#: ../client/pk-console.c:915
+#: ../client/pk-console.c:943
 #, c-format
 msgid "This tool could not find the package: %s"
 msgstr "Esta herramienta no pudo encontrar el paquete: %s"
@@ -348,185 +353,185 @@ msgstr "Esta herramienta no pudo encontrar el paquete: %s"
 #. TRANSLATORS: There was an error getting the dependencies for the package. The detailed error follows
 #. TRANSLATORS: There was an error getting the details about the package. The detailed error follows
 #. TRANSLATORS: The package name was not found in any software sources. The detailed error follows
-#: ../client/pk-console.c:963
-#: ../client/pk-console.c:991
-#: ../client/pk-console.c:1019
-#: ../client/pk-console.c:1047
-#: ../client/pk-console.c:1075
+#: ../client/pk-console.c:971
+#: ../client/pk-console.c:999
+#: ../client/pk-console.c:1027
+#: ../client/pk-console.c:1055
+#: ../client/pk-console.c:1083
 #, c-format
 msgid "This tool could not find all the packages: %s"
 msgstr "Esta herramienta no pudo encontrar todos los paquetes: %s"
 
 #. TRANSLATORS: This is when the daemon crashed, and we are up shit creek without a paddle
-#: ../client/pk-console.c:1104
+#: ../client/pk-console.c:1112
 msgid "The daemon crashed mid-transaction!"
 msgstr "El demonio se colgó en medio de una transacción."
 
 #. TRANSLATORS: This is the header to the --help menu
-#: ../client/pk-console.c:1138
+#: ../client/pk-console.c:1146
 msgid "PackageKit Console Interface"
 msgstr "Interfaz de consola de PackageKit"
 
 #. these are commands we can use with pkcon
-#: ../client/pk-console.c:1140
+#: ../client/pk-console.c:1148
 msgid "Subcommands:"
 msgstr "Subcomandos:"
 
 #. TRANSLATORS: we keep a database updated with the time that an action was last executed
-#: ../client/pk-console.c:1219
+#: ../client/pk-console.c:1227
 msgid "Failed to get the time since this action was last completed"
 msgstr "Falló al obtener la hora de la última vez que se completó esta acción"
 
 #. TRANSLATORS: command line argument, just show the version string
-#: ../client/pk-console.c:1255
-#: ../client/pk-monitor.c:280
+#: ../client/pk-console.c:1263
+#: ../client/pk-monitor.c:306
 msgid "Show the program version and exit"
 msgstr "Mostrar la versión del programa y salir"
 
 #. TRANSLATORS: command line argument, use a filter to narrow down results
-#: ../client/pk-console.c:1258
+#: ../client/pk-console.c:1266
 msgid "Set the filter, e.g. installed"
 msgstr "Establecer el filtro, ej. instalado"
 
 #. TRANSLATORS: command line argument, work asynchronously
-#: ../client/pk-console.c:1261
+#: ../client/pk-console.c:1269
 msgid "Exit without waiting for actions to complete"
 msgstr "Salir sin esperar que las acciones se completen"
 
 #. command line argument, do we ask questions
-#: ../client/pk-console.c:1264
+#: ../client/pk-console.c:1272
 #: ../contrib/debuginfo-install/pk-debuginfo-install.c:527
 msgid "Install the packages without asking for confirmation"
 msgstr "Instalar los paquetes sin confirmación"
 
 #. TRANSLATORS: command line argument, this command is not a priority
-#: ../client/pk-console.c:1267
+#: ../client/pk-console.c:1275
 msgid "Run the command using idle network bandwidth and also using less power"
 msgstr "Corra el comando usando ancho de bando libre y también usando menos potencia"
 
 #. TRANSLATORS: command line argument, just output without fancy formatting
-#: ../client/pk-console.c:1270
+#: ../client/pk-console.c:1278
 msgid "Print to screen a machine readable output, rather than using animated widgets"
 msgstr "Imprimir en la pantalla una salida legible por una máquina, en vez de usar controles animados"
 
 #. TRANSLATORS: we failed to contact the daemon
-#: ../client/pk-console.c:1292
+#: ../client/pk-console.c:1300
 msgid "Failed to contact PackageKit"
 msgstr "Falló al contactar con PackageKit"
 
 #. TRANSLATORS: The user specified an incorrect filter
-#: ../client/pk-console.c:1350
+#: ../client/pk-console.c:1358
 msgid "The filter specified was invalid"
 msgstr "El filtro especificado fue inválido"
 
 #. TRANSLATORS: a search type can be name, details, file, etc
-#: ../client/pk-console.c:1369
+#: ../client/pk-console.c:1377
 msgid "A search type is required, e.g. name"
 msgstr "Se necesita un tipo de búsqueda, por ejemplo, nombre"
 
 #. TRANSLATORS: the user needs to provide a search term
-#: ../client/pk-console.c:1376
-#: ../client/pk-console.c:1388
-#: ../client/pk-console.c:1400
-#: ../client/pk-console.c:1412
+#: ../client/pk-console.c:1384
+#: ../client/pk-console.c:1396
+#: ../client/pk-console.c:1408
+#: ../client/pk-console.c:1420
 msgid "A search term is required"
 msgstr "Se necesita un término de búsqueda"
 
 #. TRANSLATORS: the search type was provided, but invalid
-#: ../client/pk-console.c:1422
+#: ../client/pk-console.c:1430
 msgid "Invalid search type"
 msgstr "Tipo de búsqueda inválido"
 
 #. TRANSLATORS: the user did not specify what they wanted to install
-#: ../client/pk-console.c:1428
+#: ../client/pk-console.c:1436
 msgid "A package name to install is required"
 msgstr "Se necesita un nombre de paquete a instalar"
 
 #. TRANSLATORS: the user did not specify what they wanted to install
-#: ../client/pk-console.c:1437
+#: ../client/pk-console.c:1445
 msgid "A filename to install is required"
 msgstr "Se requiere un nombre de archivo a instalar"
 
 #. TRANSLATORS: geeky error, 99.9999% of users won't see this
-#: ../client/pk-console.c:1449
+#: ../client/pk-console.c:1457
 msgid "A type, key_id and package_id are required"
 msgstr "Se necesita un tipo, key_id y package_id"
 
 #. TRANSLATORS: the user did not specify what they wanted to remove
-#: ../client/pk-console.c:1460
+#: ../client/pk-console.c:1468
 msgid "A package name to remove is required"
 msgstr "Necesita un nombre de paquete para eliminar"
 
 #. TRANSLATORS: the user did not specify anything about what to download or where
-#: ../client/pk-console.c:1469
+#: ../client/pk-console.c:1477
 msgid "A destination directory and the package names to download are required"
 msgstr "Se necesita un directorio de destino y los nombres de los paquetes a descargar"
 
 #. TRANSLATORS: the directory does not exist, so we can't continue
-#: ../client/pk-console.c:1476
+#: ../client/pk-console.c:1484
 msgid "Directory not found"
 msgstr "Directorio no encontrado"
 
 #. TRANSLATORS: geeky error, 99.9999% of users won't see this
-#: ../client/pk-console.c:1485
+#: ../client/pk-console.c:1493
 msgid "A licence identifier (eula-id) is required"
 msgstr "Se necesita un identificador de licencia (eula-id)"
 
 #. TRANSLATORS: geeky error, 99.9999% of users won't see this
-#: ../client/pk-console.c:1496
+#: ../client/pk-console.c:1504
 msgid "A transaction identifier (tid) is required"
 msgstr "Se necesita un identificador de transacción (tid)"
 
 #. TRANSLATORS: The user did not specify a package name
-#: ../client/pk-console.c:1517
+#: ../client/pk-console.c:1525
 msgid "A package name to resolve is required"
 msgstr "Se necesita un nombre de paquete para resolver"
 
 #. TRANSLATORS: The user did not specify a repository (software source) name
-#: ../client/pk-console.c:1528
-#: ../client/pk-console.c:1539
+#: ../client/pk-console.c:1536
+#: ../client/pk-console.c:1547
 msgid "A repository name is required"
 msgstr "Se necesita un nombre de repositorio"
 
 #. TRANSLATORS: The user didn't provide any data
-#: ../client/pk-console.c:1550
+#: ../client/pk-console.c:1558
 msgid "A repo name, parameter and value are required"
 msgstr "Debe especificar un nombre de repositorio, parámetro y valor"
 
 #. TRANSLATORS: The user didn't specify what action to use
-#: ../client/pk-console.c:1567
+#: ../client/pk-console.c:1575
 msgid "An action, e.g. 'update-system' is required"
 msgstr "Debe especificar una acción, por ejemplo, «update-system»"
 
 #. TRANSLATORS: The user specified an invalid action
-#: ../client/pk-console.c:1574
+#: ../client/pk-console.c:1582
 msgid "A correct role is required"
 msgstr "Se necesita un rol correcto"
 
 #. TRANSLATORS: The user did not provide a package name
 #. TRANSLATORS: This is when the user fails to supply the package name
-#: ../client/pk-console.c:1584
-#: ../client/pk-console.c:1599
-#: ../client/pk-console.c:1608
-#: ../client/pk-console.c:1628
-#: ../client/pk-console.c:1637
+#: ../client/pk-console.c:1592
+#: ../client/pk-console.c:1607
+#: ../client/pk-console.c:1616
+#: ../client/pk-console.c:1636
+#: ../client/pk-console.c:1645
 #: ../client/pk-generate-pack.c:316
 msgid "A package name is required"
 msgstr "Se necesita un nombre de paquete"
 
 #. TRANSLATORS: each package "provides" certain things, e.g. mime(gstreamer-decoder-mp3), the user didn't specify it
-#: ../client/pk-console.c:1617
+#: ../client/pk-console.c:1625
 msgid "A package provide string is required"
 msgstr "Se necesita la cadena de lo que proporciona el paquete"
 
 #. TRANSLATORS: The user tried to use an unsupported option on the command line
-#: ../client/pk-console.c:1697
+#: ../client/pk-console.c:1705
 #, c-format
 msgid "Option '%s' is not supported"
 msgstr "La opción «%s» no está soportada"
 
 #. TRANSLATORS: Generic failure of what they asked to do
-#: ../client/pk-console.c:1707
+#: ../client/pk-console.c:1715
 msgid "Command failed"
 msgstr "Falló el comando"
 
@@ -635,12 +640,12 @@ msgstr "Paquete de servicio «%s» creado"
 msgid "Failed to create '%s': %s"
 msgstr "Falló al crear «%s»: %s"
 
-#: ../client/pk-monitor.c:210
+#: ../client/pk-monitor.c:236
 msgid "Failed to get daemon state"
 msgstr "Falló al obtener el estado del demonio"
 
 #. TRANSLATORS: this is a program that monitors PackageKit
-#: ../client/pk-monitor.c:296
+#: ../client/pk-monitor.c:322
 msgid "PackageKit Monitor"
 msgstr "Monitor de PackageKit"
 
commit 7ad33dbb308653a28da60a36b374940c9a333175
Author: Richard Hughes <richard at hughsie.com>
Date:   Mon Mar 8 17:24:57 2010 +0000

    trivial: print a message if there are not distro upgrades

diff --git a/client/pk-console.c b/client/pk-console.c
index 136439d..b11cf67 100644
--- a/client/pk-console.c
+++ b/client/pk-console.c
@@ -745,8 +745,10 @@ pk_console_finished_cb (GObject *object, GAsyncResult *res, gpointer data)
 	g_ptr_array_foreach (array, (GFunc) pk_console_distro_upgrade_cb, NULL);
 
 	/* special case */
-	if (array->len == 0 && role == PK_ROLE_ENUM_GET_DISTRO_UPGRADES)
+	if (array->len == 0 && role == PK_ROLE_ENUM_GET_DISTRO_UPGRADES) {
+		g_print ("%s\n", _("There are no upgrades available at this time."));
 		retval = PK_EXIT_CODE_NOTHING_USEFUL;
+	}
 
 	g_ptr_array_unref (array);
 
commit 52a11e4dcc40f0bea25a5e2e0bdec22e95021b3c
Author: Richard Hughes <richard at hughsie.com>
Date:   Mon Mar 8 17:23:04 2010 +0000

    trivial: ensure GetDistroUpgrades is run in a thread to prevent blocking the daemon

diff --git a/backends/yum/libzif/zif-download.c b/backends/yum/libzif/zif-download.c
index 7113a37..5572bcd 100644
--- a/backends/yum/libzif/zif-download.c
+++ b/backends/yum/libzif/zif-download.c
@@ -228,10 +228,10 @@ zif_download_set_proxy (ZifDownload *download, const gchar *http_proxy, GError *
 		connection_timeout = 5;
 
 	/* setup the session */
-	download->priv->session = soup_session_async_new_with_options (SOUP_SESSION_PROXY_URI, proxy,
-								       SOUP_SESSION_USER_AGENT, "zif",
-								       SOUP_SESSION_TIMEOUT, connection_timeout,
-								       NULL);
+	download->priv->session = soup_session_sync_new_with_options (SOUP_SESSION_PROXY_URI, proxy,
+								      SOUP_SESSION_USER_AGENT, "zif",
+								      SOUP_SESSION_TIMEOUT, connection_timeout,
+								      NULL);
 	if (download->priv->session == NULL) {
 		if (error != NULL)
 			*error = g_error_new (1, 0, "could not setup session");
diff --git a/backends/yum/pk-backend-yum.c b/backends/yum/pk-backend-yum.c
index e82ebd8..db785a4 100644
--- a/backends/yum/pk-backend-yum.c
+++ b/backends/yum/pk-backend-yum.c
@@ -303,10 +303,10 @@ backend_get_details (PkBackend *backend, gchar **package_ids)
 }
 
 /**
- * backend_get_distro_upgrades:
- */
-static void
-backend_get_distro_upgrades (PkBackend *backend)
+  * backend_get_distro_upgrades_thread:
+  */
+static gboolean
+backend_get_distro_upgrades_thread (PkBackend *backend)
 {
 	gboolean ret;
 	gchar *distro_id = NULL;
@@ -339,7 +339,7 @@ backend_get_distro_upgrades (PkBackend *backend)
 	/* download new file */
 	filename = g_build_filename ("/var/cache/PackageKit", "releases.txt", NULL);
 	child = zif_completion_get_child (priv->completion);
-	pk_backend_set_status (backend, PK_STATUS_ENUM_DOWNLOAD);
+	pk_backend_set_status (backend, PK_STATUS_ENUM_DOWNLOAD_UPDATEINFO);
 	ret = zif_download_file (priv->download, "http://mirrors.fedoraproject.org/releases.txt", filename, NULL, child, &error);
 	if (!ret) {
 		pk_backend_error_code (backend, PK_ERROR_ENUM_TRANSACTION_ERROR, "failed to download %s: %s", filename, error->message);
@@ -405,6 +405,16 @@ out:
 		g_key_file_free (file);
 	g_strfreev (groups);
 	g_strfreev (split);
+	return TRUE;
+}
+
+/**
+ * backend_get_distro_upgrades:
+ */
+static void
+backend_get_distro_upgrades (PkBackend *backend)
+{
+	pk_backend_thread_create (backend, backend_get_distro_upgrades_thread);
 }
 
 /**
commit 14b1dd1ef2cc3d00fa4a30062ea6271c600b3b0e
Author: Richard Hughes <richard at hughsie.com>
Date:   Mon Mar 8 16:28:07 2010 +0000

    yum: use Zif to get the list of distro-upgrades

diff --git a/backends/yum/Makefile.am b/backends/yum/Makefile.am
index b5f61d1..242040f 100644
--- a/backends/yum/Makefile.am
+++ b/backends/yum/Makefile.am
@@ -6,6 +6,18 @@ dist_helper_DATA = 			\
 	yumMediaManager.py		\
 	yumFilter.py
 
+INCLUDES = \
+	-DI_KNOW_THE_PACKAGEKIT_GLIB2_API_IS_SUBJECT_TO_CHANGE	\
+	-DZIF_COMPILATION					\
+	$(SQLITE_CFLAGS)					\
+	$(RPM_CFLAGS)						\
+	$(ZLIB_CFLAGS)						\
+	$(BZLIB_CFLAGS)						\
+	$(SOUP_CFLAGS)						\
+	$(ARCHIVE_CFLAGS)					\
+	-I$(top_srcdir)/backends/yum/libzif			\
+	-I$(top_builddir)/backends/yum/libzif
+
 plugindir = $(PK_PLUGIN_DIR)
 plugin_LTLIBRARIES = libpk_backend_yum.la
 libpk_backend_yum_la_SOURCES = pk-backend-yum.c
@@ -13,6 +25,68 @@ libpk_backend_yum_la_LIBADD = $(PK_PLUGIN_LIBS)
 libpk_backend_yum_la_LDFLAGS = -module -avoid-version
 libpk_backend_yum_la_CFLAGS = $(PK_PLUGIN_CFLAGS) $(WARNINGFLAGS_C)
 
+libpk_backend_yum_la_SOURCES += 				\
+	libzif/egg-debug.c					\
+	libzif/egg-debug.h					\
+	libzif/egg-string.c					\
+	libzif/egg-string.h					\
+	libzif/zif.h						\
+	libzif/zif-lock.c					\
+	libzif/zif-lock.h					\
+	libzif/zif-completion.c					\
+	libzif/zif-completion.h					\
+	libzif/zif-string.c					\
+	libzif/zif-string.h					\
+	libzif/zif-depend.c					\
+	libzif/zif-depend.h					\
+	libzif/zif-package.c					\
+	libzif/zif-package.h					\
+	libzif/zif-package-local.c				\
+	libzif/zif-package-local.h				\
+	libzif/zif-package-remote.c				\
+	libzif/zif-package-remote.h				\
+	libzif/zif-store.c					\
+	libzif/zif-store.h					\
+	libzif/zif-store-local.c				\
+	libzif/zif-store-local.h				\
+	libzif/zif-store-remote.c				\
+	libzif/zif-store-remote.h				\
+	libzif/zif-repo-md.c					\
+	libzif/zif-repo-md.h					\
+	libzif/zif-repo-md-filelists.c				\
+	libzif/zif-repo-md-filelists.h				\
+	libzif/zif-repo-md-primary.c				\
+	libzif/zif-repo-md-primary.h				\
+	libzif/zif-repo-md-metalink.c				\
+	libzif/zif-repo-md-metalink.h				\
+	libzif/zif-repo-md-mirrorlist.c				\
+	libzif/zif-repo-md-mirrorlist.h				\
+	libzif/zif-repo-md-comps.c				\
+	libzif/zif-repo-md-comps.h				\
+	libzif/zif-sack.c					\
+	libzif/zif-sack.h					\
+	libzif/zif-repos.c					\
+	libzif/zif-repos.h					\
+	libzif/zif-utils.c					\
+	libzif/zif-utils.h					\
+	libzif/zif-groups.c					\
+	libzif/zif-groups.h					\
+	libzif/zif-config.c					\
+	libzif/zif-config.h					\
+	libzif/zif-monitor.c					\
+	libzif/zif-monitor.h					\
+	libzif/zif-download.c					\
+	libzif/zif-download.h
+
+libpk_backend_yum_la_LIBADD +=					\
+	$(SQLITE_LIBS)						\
+	$(ZLIB_LIBS)						\
+	$(BZLIB_LIBS)						\
+	$(RPM_LIBS)						\
+	$(SOUP_LIBS)						\
+	$(ARCHIVE_LIBS)						\
+	$(NULL)
+
 install-data-hook:
 	chmod a+rx $(DESTDIR)$(helperdir)/*.py
 
diff --git a/backends/yum/pk-backend-yum.c b/backends/yum/pk-backend-yum.c
index cc8e17f..e82ebd8 100644
--- a/backends/yum/pk-backend-yum.c
+++ b/backends/yum/pk-backend-yum.c
@@ -23,12 +23,20 @@
 #include <pk-backend.h>
 #include <pk-backend-spawn.h>
 #include <string.h>
+#include <zif.h>
 
 #define PREUPGRADE_BINARY	"/usr/bin/preupgrade"
 #define YUM_REPOS_DIRECTORY	"/etc/yum.repos.d"
 
-static PkBackendSpawn *spawn;
-static GFileMonitor *monitor;
+typedef struct {
+	PkBackendSpawn *spawn;
+	GFileMonitor *monitor;
+	ZifDownload *download;
+	ZifConfig *config;
+	ZifCompletion *completion;
+} PkBackendYumPrivate;
+
+static PkBackendYumPrivate *priv;
 
 /**
  * backend_stderr_cb:
@@ -64,6 +72,12 @@ backend_yum_repos_changed_cb (GFileMonitor *monitor_, GFile *file, GFile *other_
 	pk_backend_repo_list_changed (backend);
 }
 
+static void
+backend_completion_percentage_changed_cb (ZifCompletion *completion, guint percentage, PkBackend *backend)
+{
+	pk_backend_set_percentage (backend, percentage);
+}
+
 /**
  * backend_initialize:
  * This should only be run once per backend load, i.e. not every transaction
@@ -71,26 +85,44 @@ backend_yum_repos_changed_cb (GFileMonitor *monitor_, GFile *file, GFile *other_
 static void
 backend_initialize (PkBackend *backend)
 {
+	gboolean ret;
 	GFile *file;
 	GError *error = NULL;
 
+	/* create private area */
+	priv = g_new0 (PkBackendYumPrivate, 1);
+
 	egg_debug ("backend: initialize");
-	spawn = pk_backend_spawn_new ();
-	pk_backend_spawn_set_filter_stderr (spawn, backend_stderr_cb);
-	pk_backend_spawn_set_filter_stdout (spawn, backend_stdout_cb);
-	pk_backend_spawn_set_name (spawn, "yum");
-	pk_backend_spawn_set_allow_sigkill (spawn, FALSE);
+	priv->spawn = pk_backend_spawn_new ();
+	pk_backend_spawn_set_filter_stderr (priv->spawn, backend_stderr_cb);
+	pk_backend_spawn_set_filter_stdout (priv->spawn, backend_stdout_cb);
+	pk_backend_spawn_set_name (priv->spawn, "yum");
+	pk_backend_spawn_set_allow_sigkill (priv->spawn, FALSE);
 
 	/* setup a file monitor on the repos directory */
 	file = g_file_new_for_path (YUM_REPOS_DIRECTORY);
-	monitor = g_file_monitor_directory (file, G_FILE_MONITOR_NONE, NULL, &error);
-	if (monitor != NULL) {
-		g_signal_connect (monitor, "changed", G_CALLBACK (backend_yum_repos_changed_cb), backend);
+	priv->monitor = g_file_monitor_directory (file, G_FILE_MONITOR_NONE, NULL, &error);
+	if (priv->monitor != NULL) {
+		g_signal_connect (priv->monitor, "changed", G_CALLBACK (backend_yum_repos_changed_cb), backend);
 	} else {
 		egg_warning ("failed to setup monitor: %s", error->message);
 		g_error_free (error);
 	}
 
+	/* init rpm */
+	zif_init ();
+
+	/* get zif objects */
+	priv->config = zif_config_new ();
+	ret = zif_config_set_filename (priv->config, "/etc/yum.conf", &error);
+	if (!ret) {
+		pk_backend_error_code (backend, PK_ERROR_ENUM_TRANSACTION_ERROR, "load yum.conf: %s", error->message);
+		goto out;
+	}
+	priv->download = zif_download_new ();
+	priv->completion = zif_completion_new ();
+	g_signal_connect (priv->completion, "percentage-changed", G_CALLBACK (backend_completion_percentage_changed_cb), backend);
+out:
 	g_object_unref (file);
 }
 
@@ -102,9 +134,16 @@ static void
 backend_destroy (PkBackend *backend)
 {
 	egg_debug ("backend: destroy");
-	g_object_unref (spawn);
-	if (monitor != NULL)
-		g_object_unref (monitor);
+	g_object_unref (priv->spawn);
+	if (priv->monitor != NULL)
+		g_object_unref (priv->monitor);
+	if (priv->config != NULL)
+		g_object_unref (priv->config);
+	if (priv->download != NULL)
+		g_object_unref (priv->download);
+	if (priv->completion != NULL)
+		g_object_unref (priv->completion);
+	g_free (priv);
 }
 
 /**
@@ -219,7 +258,7 @@ static void
 backend_cancel (PkBackend *backend)
 {
 	/* this feels bad... */
-	pk_backend_spawn_kill (spawn);
+	pk_backend_spawn_kill (priv->spawn);
 }
 
 /**
@@ -232,7 +271,7 @@ backend_download_packages (PkBackend *backend, gchar **package_ids, const gchar
 
 	/* send the complete list as stdin */
 	package_ids_temp = pk_package_ids_to_string (package_ids);
-	pk_backend_spawn_helper (spawn, "yumBackend.py", "download-packages", directory, package_ids_temp, NULL);
+	pk_backend_spawn_helper (priv->spawn, "yumBackend.py", "download-packages", directory, package_ids_temp, NULL);
 	g_free (package_ids_temp);
 }
 
@@ -246,7 +285,7 @@ backend_get_depends (PkBackend *backend, PkBitfield filters, gchar **package_ids
 	gchar *package_ids_temp;
 	package_ids_temp = pk_package_ids_to_string (package_ids);
 	filters_text = pk_filter_bitfield_to_string (filters);
-	pk_backend_spawn_helper (spawn, "yumBackend.py", "get-depends", filters_text, package_ids_temp, pk_backend_bool_to_string (recursive), NULL);
+	pk_backend_spawn_helper (priv->spawn, "yumBackend.py", "get-depends", filters_text, package_ids_temp, pk_backend_bool_to_string (recursive), NULL);
 	g_free (filters_text);
 	g_free (package_ids_temp);
 }
@@ -259,7 +298,7 @@ backend_get_details (PkBackend *backend, gchar **package_ids)
 {
 	gchar *package_ids_temp;
 	package_ids_temp = pk_package_ids_to_string (package_ids);
-	pk_backend_spawn_helper (spawn, "yumBackend.py", "get-details", package_ids_temp, NULL);
+	pk_backend_spawn_helper (priv->spawn, "yumBackend.py", "get-details", package_ids_temp, NULL);
 	g_free (package_ids_temp);
 }
 
@@ -269,7 +308,103 @@ backend_get_details (PkBackend *backend, gchar **package_ids)
 static void
 backend_get_distro_upgrades (PkBackend *backend)
 {
-	pk_backend_spawn_helper (spawn, "yumBackend.py", "get-distro-upgrades", NULL);
+	gboolean ret;
+	gchar *distro_id = NULL;
+	gchar *filename = NULL;
+	gchar **groups = NULL;
+	gchar *name = NULL;
+	gchar *proxy = NULL;
+	gchar **split = NULL;
+	guint i;
+	guint last_version = 0;
+	guint newest = G_MAXUINT;
+	guint version;
+	GError *error = NULL;
+	GKeyFile *file = NULL;
+	ZifCompletion *child;
+
+	/* download, then parse */
+	zif_completion_reset (priv->completion);
+	zif_completion_set_number_steps (priv->completion, 2);
+
+	/* set proxy */
+	proxy = pk_backend_get_proxy_http (backend);
+	ret = zif_download_set_proxy (priv->download, proxy, &error);
+	if (!ret) {
+		pk_backend_error_code (backend, PK_ERROR_ENUM_TRANSACTION_ERROR, "failed to set proxy: %s", error->message);
+		g_error_free (error);
+		goto out;
+	}
+
+	/* download new file */
+	filename = g_build_filename ("/var/cache/PackageKit", "releases.txt", NULL);
+	child = zif_completion_get_child (priv->completion);
+	pk_backend_set_status (backend, PK_STATUS_ENUM_DOWNLOAD);
+	ret = zif_download_file (priv->download, "http://mirrors.fedoraproject.org/releases.txt", filename, NULL, child, &error);
+	if (!ret) {
+		pk_backend_error_code (backend, PK_ERROR_ENUM_TRANSACTION_ERROR, "failed to download %s: %s", filename, error->message);
+		g_error_free (error);
+		goto out;
+	}
+	zif_completion_done (priv->completion);
+
+	file = g_key_file_new ();
+	ret = g_key_file_load_from_file (file, filename, G_KEY_FILE_NONE, &error);
+	if (!ret) {
+		pk_backend_error_code (backend, PK_ERROR_ENUM_TRANSACTION_ERROR, "failed to open %s: %s", filename, error->message);
+		g_error_free (error);
+		goto out;
+	}
+
+	/* get all entries */
+	groups = g_key_file_get_groups (file, NULL);
+	for (i=0; groups[i] != NULL; i++) {
+		/* we only care about stable versions */
+		if (!g_key_file_get_boolean (file, groups[i], "stable", NULL))
+			goto out;
+		version = g_key_file_get_integer (file, groups[i], "version", NULL);
+		egg_debug ("%s is update to version %i", groups[i], version);
+		if (version > last_version) {
+			newest = i;
+			last_version = version;
+		}
+	}
+
+	/* nothing found */
+	if (newest == G_MAXUINT) {
+		pk_backend_error_code (backend, PK_ERROR_ENUM_FAILED_CONFIG_PARSING, "could not get latest distro data");
+		goto out;
+	}
+
+	/* are we already on the latest version */
+	version = zif_config_get_uint (priv->config, "releasever", &error);
+	if (version == G_MAXUINT) {
+		pk_backend_error_code (backend, PK_ERROR_ENUM_FAILED_CONFIG_PARSING, "could not get distro present version");
+		goto out;
+	}
+
+	/* all okay, nothing to show */
+	if (version >= last_version)
+		goto out;
+
+	/* if we have an upgrade candidate then pass back data to daemon */
+	split = g_strsplit (groups[newest], " ", -1);
+	name = g_ascii_strdown (split[0], -1);
+	distro_id = g_strdup_printf ("%s-%s", name, split[1]);
+	pk_backend_distro_upgrade (backend, PK_DISTRO_UPGRADE_ENUM_STABLE, distro_id, groups[newest]);
+
+	/* we're done */
+	zif_completion_done (priv->completion);
+out:
+	pk_backend_finished (backend);
+	g_free (distro_id);
+	g_free (filename);
+	g_free (name);
+	g_free (proxy);
+	if (file != NULL)
+		g_key_file_free (file);
+	g_strfreev (groups);
+	g_strfreev (split);
 }
 
 /**
@@ -280,7 +415,7 @@ backend_get_files (PkBackend *backend, gchar **package_ids)
 {
 	gchar *package_ids_temp;
 	package_ids_temp = pk_package_ids_to_string (package_ids);
-	pk_backend_spawn_helper (spawn,  "yumBackend.py", "get-files", package_ids_temp, NULL);
+	pk_backend_spawn_helper (priv->spawn,  "yumBackend.py", "get-files", package_ids_temp, NULL);
 	g_free (package_ids_temp);
 }
 
@@ -294,7 +429,7 @@ backend_get_requires (PkBackend *backend, PkBitfield filters, gchar **package_id
 	gchar *filters_text;
 	package_ids_temp = pk_package_ids_to_string (package_ids);
 	filters_text = pk_filter_bitfield_to_string (filters);
-	pk_backend_spawn_helper (spawn, "yumBackend.py", "get-requires", filters_text, package_ids_temp, pk_backend_bool_to_string (recursive), NULL);
+	pk_backend_spawn_helper (priv->spawn, "yumBackend.py", "get-requires", filters_text, package_ids_temp, pk_backend_bool_to_string (recursive), NULL);
 	g_free (filters_text);
 	g_free (package_ids_temp);
 }
@@ -307,7 +442,7 @@ backend_get_updates (PkBackend *backend, PkBitfield filters)
 {
 	gchar *filters_text;
 	filters_text = pk_filter_bitfield_to_string (filters);
-	pk_backend_spawn_helper (spawn,  "yumBackend.py", "get-updates", filters_text, NULL);
+	pk_backend_spawn_helper (priv->spawn,  "yumBackend.py", "get-updates", filters_text, NULL);
 	g_free (filters_text);
 }
 
@@ -319,7 +454,7 @@ backend_get_packages (PkBackend *backend, PkBitfield filters)
 {
 	gchar *filters_text;
 	filters_text = pk_filter_bitfield_to_string (filters);
-	pk_backend_spawn_helper (spawn, "yumBackend.py", "get-packages", filters_text, NULL);
+	pk_backend_spawn_helper (priv->spawn, "yumBackend.py", "get-packages", filters_text, NULL);
 	g_free (filters_text);
 }
 
@@ -331,7 +466,7 @@ backend_get_update_detail (PkBackend *backend, gchar **package_ids)
 {
 	gchar *package_ids_temp;
 	package_ids_temp = pk_package_ids_to_string (package_ids);
-	pk_backend_spawn_helper (spawn, "yumBackend.py", "get-update-detail", package_ids_temp, NULL);
+	pk_backend_spawn_helper (priv->spawn, "yumBackend.py", "get-update-detail", package_ids_temp, NULL);
 	g_free (package_ids_temp);
 }
 
@@ -345,7 +480,7 @@ backend_install_packages (PkBackend *backend, gboolean only_trusted, gchar **pac
 
 	/* send the complete list as stdin */
 	package_ids_temp = pk_package_ids_to_string (package_ids);
-	pk_backend_spawn_helper (spawn, "yumBackend.py", "install-packages", pk_backend_bool_to_string (only_trusted), package_ids_temp, NULL);
+	pk_backend_spawn_helper (priv->spawn, "yumBackend.py", "install-packages", pk_backend_bool_to_string (only_trusted), package_ids_temp, NULL);
 	g_free (package_ids_temp);
 }
 
@@ -359,7 +494,7 @@ backend_simulate_remove_packages (PkBackend *backend, gchar **package_ids, gbool
 
 	/* send the complete list as stdin */
 	package_ids_temp = pk_package_ids_to_string (package_ids);
-	pk_backend_spawn_helper (spawn, "yumBackend.py", "simulate-remove-packages", package_ids_temp, NULL);
+	pk_backend_spawn_helper (priv->spawn, "yumBackend.py", "simulate-remove-packages", package_ids_temp, NULL);
 	g_free (package_ids_temp);
 }
 
@@ -373,7 +508,7 @@ backend_simulate_update_packages (PkBackend *backend, gchar **package_ids)
 
 	/* send the complete list as stdin */
 	package_ids_temp = pk_package_ids_to_string (package_ids);
-	pk_backend_spawn_helper (spawn, "yumBackend.py", "simulate-update-packages", package_ids_temp, NULL);
+	pk_backend_spawn_helper (priv->spawn, "yumBackend.py", "simulate-update-packages", package_ids_temp, NULL);
 	g_free (package_ids_temp);
 }
 
@@ -387,7 +522,7 @@ backend_simulate_install_packages (PkBackend *backend, gchar **package_ids)
 
 	/* send the complete list as stdin */
 	package_ids_temp = pk_package_ids_to_string (package_ids);
-	pk_backend_spawn_helper (spawn, "yumBackend.py", "simulate-install-packages", package_ids_temp, NULL);
+	pk_backend_spawn_helper (priv->spawn, "yumBackend.py", "simulate-install-packages", package_ids_temp, NULL);
 	g_free (package_ids_temp);
 }
 
@@ -401,7 +536,7 @@ backend_install_files (PkBackend *backend, gboolean only_trusted, gchar **full_p
 
 	/* send the complete list as stdin */
 	package_ids_temp = g_strjoinv (PK_BACKEND_SPAWN_FILENAME_DELIM, full_paths);
-	pk_backend_spawn_helper (spawn, "yumBackend.py", "install-files", pk_backend_bool_to_string (only_trusted), package_ids_temp, NULL);
+	pk_backend_spawn_helper (priv->spawn, "yumBackend.py", "install-files", pk_backend_bool_to_string (only_trusted), package_ids_temp, NULL);
 	g_free (package_ids_temp);
 }
 
@@ -415,7 +550,7 @@ backend_install_signature (PkBackend *backend, PkSigTypeEnum type,
 	const gchar *type_text;
 
 	type_text = pk_sig_type_enum_to_string (type);
-	pk_backend_spawn_helper (spawn, "yumBackend.py", "install-signature", type_text, key_id, package_id, NULL);
+	pk_backend_spawn_helper (priv->spawn, "yumBackend.py", "install-signature", type_text, key_id, package_id, NULL);
 }
 
 /**
@@ -431,7 +566,7 @@ backend_refresh_cache (PkBackend *backend, gboolean force)
 		return;
 	}
 
-	pk_backend_spawn_helper (spawn, "yumBackend.py", "refresh-cache", pk_backend_bool_to_string (force), NULL);
+	pk_backend_spawn_helper (priv->spawn, "yumBackend.py", "refresh-cache", pk_backend_bool_to_string (force), NULL);
 }
 
 /**
@@ -444,7 +579,7 @@ backend_remove_packages (PkBackend *backend, gchar **package_ids, gboolean allow
 
 	/* send the complete list as stdin */
 	package_ids_temp = pk_package_ids_to_string (package_ids);
-	pk_backend_spawn_helper (spawn, "yumBackend.py", "remove-packages", pk_backend_bool_to_string (allow_deps), pk_backend_bool_to_string (autoremove), package_ids_temp, NULL);
+	pk_backend_spawn_helper (priv->spawn, "yumBackend.py", "remove-packages", pk_backend_bool_to_string (allow_deps), pk_backend_bool_to_string (autoremove), package_ids_temp, NULL);
 	g_free (package_ids_temp);
 }
 
@@ -458,7 +593,7 @@ backend_search_details (PkBackend *backend, PkBitfield filters, gchar **values)
 	gchar *search;
 	filters_text = pk_filter_bitfield_to_string (filters);
 	search = g_strjoinv ("&", values);
-	pk_backend_spawn_helper (spawn, "yumBackend.py", "search-details", filters_text, search, NULL);
+	pk_backend_spawn_helper (priv->spawn, "yumBackend.py", "search-details", filters_text, search, NULL);
 	g_free (filters_text);
 	g_free (search);
 }
@@ -473,7 +608,7 @@ backend_search_files (PkBackend *backend, PkBitfield filters, gchar **values)
 	gchar *search;
 	filters_text = pk_filter_bitfield_to_string (filters);
 	search = g_strjoinv ("&", values);
-	pk_backend_spawn_helper (spawn, "yumBackend.py", "search-file", filters_text, search, NULL);
+	pk_backend_spawn_helper (priv->spawn, "yumBackend.py", "search-file", filters_text, search, NULL);
 	g_free (filters_text);
 	g_free (search);
 }
@@ -488,7 +623,7 @@ backend_search_groups (PkBackend *backend, PkBitfield filters, gchar **values)
 	gchar *search;
 	filters_text = pk_filter_bitfield_to_string (filters);
 	search = g_strjoinv ("&", values);
-	pk_backend_spawn_helper (spawn, "yumBackend.py", "search-group", filters_text, search, NULL);
+	pk_backend_spawn_helper (priv->spawn, "yumBackend.py", "search-group", filters_text, search, NULL);
 	g_free (filters_text);
 	g_free (search);
 }
@@ -503,7 +638,7 @@ backend_search_names (PkBackend *backend, PkBitfield filters, gchar **values)
 	gchar *search;
 	filters_text = pk_filter_bitfield_to_string (filters);
 	search = g_strjoinv ("&", values);
-	pk_backend_spawn_helper (spawn, "yumBackend.py", "search-name", filters_text, search, NULL);
+	pk_backend_spawn_helper (priv->spawn, "yumBackend.py", "search-name", filters_text, search, NULL);
 	g_free (filters_text);
 	g_free (search);
 }
@@ -518,7 +653,7 @@ backend_update_packages (PkBackend *backend, gboolean only_trusted, gchar **pack
 
 	/* send the complete list as stdin */
 	package_ids_temp = pk_package_ids_to_string (package_ids);
-	pk_backend_spawn_helper (spawn, "yumBackend.py", "update-packages", pk_backend_bool_to_string (only_trusted), package_ids_temp, NULL);
+	pk_backend_spawn_helper (priv->spawn, "yumBackend.py", "update-packages", pk_backend_bool_to_string (only_trusted), package_ids_temp, NULL);
 	g_free (package_ids_temp);
 }
 
@@ -528,7 +663,7 @@ backend_update_packages (PkBackend *backend, gboolean only_trusted, gchar **pack
 static void
 backend_update_system (PkBackend *backend, gboolean only_trusted)
 {
-	pk_backend_spawn_helper (spawn, "yumBackend.py", "update-system", pk_backend_bool_to_string (only_trusted), NULL);
+	pk_backend_spawn_helper (priv->spawn, "yumBackend.py", "update-system", pk_backend_bool_to_string (only_trusted), NULL);
 }
 
 /**
@@ -541,7 +676,7 @@ backend_resolve (PkBackend *backend, PkBitfield filters, gchar **package_ids)
 	gchar *package_ids_temp;
 	filters_text = pk_filter_bitfield_to_string (filters);
 	package_ids_temp = pk_package_ids_to_string (package_ids);
-	pk_backend_spawn_helper (spawn, "yumBackend.py", "resolve", filters_text, package_ids_temp, NULL);
+	pk_backend_spawn_helper (priv->spawn, "yumBackend.py", "resolve", filters_text, package_ids_temp, NULL);
 	g_free (filters_text);
 	g_free (package_ids_temp);
 }
@@ -554,7 +689,7 @@ backend_get_repo_list (PkBackend *backend, PkBitfield filters)
 {
 	gchar *filters_text;
 	filters_text = pk_filter_bitfield_to_string (filters);
-	pk_backend_spawn_helper (spawn, "yumBackend.py", "get-repo-list", filters_text, NULL);
+	pk_backend_spawn_helper (priv->spawn, "yumBackend.py", "get-repo-list", filters_text, NULL);
 	g_free (filters_text);
 }
 
@@ -565,9 +700,9 @@ static void
 backend_repo_enable (PkBackend *backend, const gchar *rid, gboolean enabled)
 {
 	if (enabled == TRUE) {
-		pk_backend_spawn_helper (spawn, "yumBackend.py", "repo-enable", rid, "true", NULL);
+		pk_backend_spawn_helper (priv->spawn, "yumBackend.py", "repo-enable", rid, "true", NULL);
 	} else {
-		pk_backend_spawn_helper (spawn, "yumBackend.py", "repo-enable", rid, "false", NULL);
+		pk_backend_spawn_helper (priv->spawn, "yumBackend.py", "repo-enable", rid, "false", NULL);
 	}
 }
 
@@ -577,7 +712,7 @@ backend_repo_enable (PkBackend *backend, const gchar *rid, gboolean enabled)
 static void
 backend_repo_set_data (PkBackend *backend, const gchar *rid, const gchar *parameter, const gchar *value)
 {
-	pk_backend_spawn_helper (spawn, "yumBackend.py", "repo-set-data", rid, parameter, value, NULL);
+	pk_backend_spawn_helper (priv->spawn, "yumBackend.py", "repo-set-data", rid, parameter, value, NULL);
 }
 
 /**
@@ -592,7 +727,7 @@ backend_what_provides (PkBackend *backend, PkBitfield filters, PkProvidesEnum pr
 	provides_text = pk_provides_enum_to_string (provides);
 	filters_text = pk_filter_bitfield_to_string (filters);
 	search = g_strjoinv ("&", values);
-	pk_backend_spawn_helper (spawn, "yumBackend.py", "what-provides", filters_text, provides_text, search, NULL);
+	pk_backend_spawn_helper (priv->spawn, "yumBackend.py", "what-provides", filters_text, provides_text, search, NULL);
 	g_free (filters_text);
 	g_free (search);
 }
@@ -603,7 +738,7 @@ backend_what_provides (PkBackend *backend, PkBitfield filters, PkProvidesEnum pr
 static void
 backend_get_categories (PkBackend *backend)
 {
-	pk_backend_spawn_helper (spawn, "yumBackend.py", "get-categories", NULL);
+	pk_backend_spawn_helper (priv->spawn, "yumBackend.py", "get-categories", NULL);
 }
 
 /**
@@ -616,7 +751,7 @@ backend_simulate_install_files (PkBackend *backend, gchar **full_paths)
 
 	/* send the complete list as stdin */
 	package_ids_temp = g_strjoinv (PK_BACKEND_SPAWN_FILENAME_DELIM, full_paths);
-	pk_backend_spawn_helper (spawn, "yumBackend.py", "simulate-install-files", package_ids_temp, NULL);
+	pk_backend_spawn_helper (priv->spawn, "yumBackend.py", "simulate-install-files", package_ids_temp, NULL);
 	g_free (package_ids_temp);
 }
 
diff --git a/backends/yum/yumBackend.py b/backends/yum/yumBackend.py
index 87ed876..b82a8ac 100755
--- a/backends/yum/yumBackend.py
+++ b/backends/yum/yumBackend.py
@@ -2319,56 +2319,6 @@ class PackageKitYumBackend(PackageKitBaseBackend, PackagekitPackage):
         package_id = self._pkg_to_id(pkg)
         self.package(package_id, status, pkg.summary)
 
-    def get_distro_upgrades(self):
-        '''
-        Implement the get-distro-upgrades functionality
-        '''
-        try:
-            self._check_init()
-        except PkError, e:
-            self.error(e.code, e.details, exit=False)
-            return
-        self.yumbase.conf.cache = 0 # Allow new files
-        self.allow_cancel(True)
-        self.percentage(None)
-        self.status(STATUS_QUERY)
-
-        # if we're RHEL, then we don't have preupgrade
-        if not os.path.exists('/usr/share/preupgrade/releases.list'):
-            return
-
-        # parse the releases file
-        config = ConfigParser.ConfigParser()
-        config.read('/usr/share/preupgrade/releases.list')
-
-        # find the newest release
-        newest = None
-        last_version = 0
-        for section in config.sections():
-            # we only care about stable versions
-            if config.has_option(section, 'stable') and config.getboolean(section, 'stable'):
-                version = config.getfloat(section, 'version')
-                if (version > last_version):
-                    newest = section
-                    last_version = version
-
-        # got no valid data
-        if not newest:
-            self.error(ERROR_FAILED_CONFIG_PARSING, "could not get latest distro data")
-
-        # are we already on the latest version
-        try:
-            present_version = float(self.yumbase.conf.yumvar['releasever'])
-        except Exception, e:
-            self.error(ERROR_INTERNAL_ERROR, _format_str(traceback.format_exc()))
-        if (present_version >= last_version):
-            return
-
-        # if we have an upgrade candidate then pass back data to daemon
-        tok = newest.split(" ")
-        name = "%s-%s" % (tok[0].lower(), tok[1])
-        self.distro_upgrade(DISTRO_UPGRADE_STABLE, name, newest)
-
     def _get_status(self, notice):
         ut = notice['type']
         if ut == 'security':
diff --git a/configure.ac b/configure.ac
index b65ad88..3fab046 100644
--- a/configure.ac
+++ b/configure.ac
@@ -675,6 +675,59 @@ fi
 AC_DEFINE_UNQUOTED(DEFAULT_BACKEND, "$with_default_backend", [default backend prefix])
 AC_SUBST(DEFAULT_BACKEND, "$with_default_backend")
 
+if test x$enable_yum = xyes; then
+	PKG_CHECK_MODULES(SQLITE, sqlite3)
+	AC_SUBST(SQLITE_CFLAGS)
+	AC_SUBST(SQLITE_LIBS)
+
+	PKG_CHECK_MODULES(RPM, rpm)
+	AC_SUBST(RPM_CFLAGS)
+	AC_SUBST(RPM_LIBS)
+
+	PKG_CHECK_MODULES(SOUP, libsoup-2.4)
+	AC_SUBST(SOUP_CFLAGS)
+	AC_SUBST(SOUP_LIBS)
+
+	dnl ---------------------------------------------------------------------------
+	dnl - libarchive
+	dnl ---------------------------------------------------------------------------
+	AC_CHECK_HEADERS(archive.h,
+			 HAVE_ARCHIVE_H="yes",
+			 HAVE_ARCHIVE_H="no")
+	if test "x$HAVE_ARCHIVE_H" = "xyes"; then
+		ARCHIVE_LIBS=-larchive
+		AC_SUBST(ARCHIVE_LIBS)
+	else
+		AC_MSG_ERROR([Cannot find archive.h])
+	fi
+
+	dnl ---------------------------------------------------------------------------
+	dnl - libbzip2
+	dnl ---------------------------------------------------------------------------
+	AC_CHECK_HEADERS(bzlib.h,
+			 HAVE_BZLIB_H="yes",
+			 HAVE_BZLIB_H="no")
+	if test "x$HAVE_BZLIB_H" = "xyes"; then
+		BZLIB_LIBS=-lbz2
+		AC_SUBST(BZLIB_LIBS)
+	else
+		AC_MSG_ERROR([Cannot find bzlib.h])
+	fi
+
+	dnl ---------------------------------------------------------------------------
+	dnl - zlib
+	dnl ---------------------------------------------------------------------------
+	AC_CHECK_HEADERS(zlib.h,
+			 HAVE_ZLIB_H="yes",
+			 HAVE_ZLIB_H="no")
+	if test "x$HAVE_BZLIB_H" = "xyes"; then
+		ZLIB_LIBS=-lz
+		AC_SUBST(ZLIB_LIBS)
+	else
+		AC_MSG_ERROR([Cannot find zlib.h])
+	fi
+fi
+
 if test x$enable_apt = xyes; then
 	PY_CHECK_MOD([apt_pkg],,,AC_MSG_ERROR([Apt backend needs python-apt]))
 	PY_CHECK_MOD([UpdateManager.Core.MetaRelease],,
diff --git a/contrib/PackageKit.spec.in b/contrib/PackageKit.spec.in
index 28b01bb..1a3b4df 100644
--- a/contrib/PackageKit.spec.in
+++ b/contrib/PackageKit.spec.in
@@ -60,6 +60,12 @@ BuildRequires: gobject-introspection-devel
 #BuildRequires: gtk-sharp2-devel
 #BuildRequires: mono-core
 
+# for the fancy new yum accelerator
+BuildRequires: rpm-devel
+BuildRequires: libsoup-devel
+BuildRequires: bzip2-devel
+BuildRequires: zlib-devel
+
 # functionality moved to udev itself
 Obsoletes: PackageKit-udev-helper < %{version}-%{release}
 Obsoletes: udev-packagekit < %{version}-%{release}
commit d33a3c9ab21fb6f1bf461c5851790a1144d61259
Author: Richard Hughes <richard at hughsie.com>
Date:   Mon Mar 8 16:26:34 2010 +0000

    yum: add the 'Zif' accelerator so we don't have to use yum for small local queries
    
    This just imports some source files, the actual zif project lives here:
    http://github.com/hughsie/zif
    
    Note: we're not going to use zif to replace yum, just to accelerate
    some things that have to be faster.

diff --git a/backends/yum/libzif/egg-debug.c b/backends/yum/libzif/egg-debug.c
new file mode 120000
index 0000000..c07e03a
--- /dev/null
+++ b/backends/yum/libzif/egg-debug.c
@@ -0,0 +1 @@
+../../../src/egg-debug.c
\ No newline at end of file
diff --git a/backends/yum/libzif/egg-debug.h b/backends/yum/libzif/egg-debug.h
new file mode 120000
index 0000000..005d030
--- /dev/null
+++ b/backends/yum/libzif/egg-debug.h
@@ -0,0 +1 @@
+../../../src/egg-debug.h
\ No newline at end of file
diff --git a/backends/yum/libzif/egg-string.c b/backends/yum/libzif/egg-string.c
new file mode 120000
index 0000000..2f33770
--- /dev/null
+++ b/backends/yum/libzif/egg-string.c
@@ -0,0 +1 @@
+../../../src/egg-string.c
\ No newline at end of file
diff --git a/backends/yum/libzif/egg-string.h b/backends/yum/libzif/egg-string.h
new file mode 120000
index 0000000..1440094
--- /dev/null
+++ b/backends/yum/libzif/egg-string.h
@@ -0,0 +1 @@
+../../../src/egg-string.h
\ No newline at end of file
diff --git a/backends/yum/libzif/zif-completion.c b/backends/yum/libzif/zif-completion.c
new file mode 100644
index 0000000..7e6f52f
--- /dev/null
+++ b/backends/yum/libzif/zif-completion.c
@@ -0,0 +1,650 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2009 Richard Hughes <richard at hughsie.com>
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+/**
+ * SECTION:zif-completion
+ * @short_description: A #ZifCompletion object allows progress reporting
+ *
+ * Objects can use zif_completion_set_percentage() if the absolute percentage
+ * is known. Percentages should always go up, not down.
+ *
+ * Modules usually set the number of steps that are expected using
+ * zif_completion_set_number_steps() and then after each section is completed,
+ * the zif_completion_done() function should be called. This will automatically
+ * call zif_completion_set_percentage() with the correct values.
+ *
+ * #ZifCompletion allows sub-modules to be "chained up" to the parent module
+ * so that as the sub-module progresses, so does the parent.
+ * The child can be reused for each section, and chains can be deep.
+ *
+ * To get a child object, you should use zif_completion_get_child() and then
+ * use the result in any sub-process. You should ensure that the child object
+ * is not re-used without calling zif_completion_done().
+ *
+ * There are a few nice touches in this module, so that if a module only has
+ * one progress step, the child progress is used for updates.
+ *
+ *
+ * <example>
+ *   <title>Using a #ZifCompletion.</title>
+ *   <programlisting>
+ * static void
+ * _do_something (ZifCompletion *completion)
+ * {
+ * 	ZifCompletion *completion_local;
+ *
+ * 	// setup correct number of steps
+ * 	zif_completion_set_number_steps (completion, 2);
+ *
+ * 	// run a sub function
+ * 	completion_local = zif_completion_get_child (completion);
+ * 	_do_something_else1 (completion_local);
+ *
+ * 	// this section done
+ * 	zif_completion_done (completion);
+ *
+ * 	// run another sub function
+ * 	completion_local = zif_completion_get_child (completion);
+ * 	_do_something_else2 (completion_local);
+ *
+ * 	// this section done (all complete)
+ * 	zif_completion_done (completion);
+ * }
+ *   </programlisting>
+ * </example>
+ */
+
+#ifdef HAVE_CONFIG_H
+#  include <config.h>
+#endif
+
+#include <glib.h>
+
+#include "zif-utils.h"
+#include "zif-completion.h"
+
+#include "egg-debug.h"
+
+#define ZIF_COMPLETION_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), ZIF_TYPE_COMPLETION, ZifCompletionPrivate))
+
+struct _ZifCompletionPrivate
+{
+	guint			 steps;
+	guint			 current;
+	guint			 last_percentage;
+	ZifCompletion		*child;
+	gulong			 percentage_child_id;
+	gulong			 subpercentage_child_id;
+};
+
+enum {
+	SIGNAL_PERCENTAGE_CHANGED,
+	SIGNAL_SUBPERCENTAGE_CHANGED,
+	SIGNAL_LAST
+};
+
+static guint signals [SIGNAL_LAST] = { 0 };
+
+G_DEFINE_TYPE (ZifCompletion, zif_completion, G_TYPE_OBJECT)
+
+/**
+ * zif_completion_discrete_to_percent:
+ * @discrete: The discrete level
+ * @steps: The number of discrete steps
+ *
+ * We have to be carefull when converting from discrete->%.
+ *
+ * Return value: The percentage for this discrete value.
+ **/
+static gfloat
+zif_completion_discrete_to_percent (guint discrete, guint steps)
+{
+	/* check we are in range */
+	if (discrete > steps)
+		return 100;
+	if (steps == 0) {
+		egg_warning ("steps is 0!");
+		return 0;
+	}
+	return ((gfloat) discrete * (100.0f / (gfloat) (steps)));
+}
+
+/**
+ * zif_completion_set_percentage:
+ * @completion: the #ZifCompletion object
+ * @percentage: A manual percentage value
+ *
+ * Set a percentage manually.
+ * NOTE: this must be above what was previously set, or it will be rejected.
+ *
+ * Return value: %TRUE if the signal was propagated, %FALSE for failure
+ **/
+gboolean
+zif_completion_set_percentage (ZifCompletion *completion, guint percentage)
+{
+	/* is it the same */
+	if (percentage == completion->priv->last_percentage)
+		goto out;
+
+	/* is it less */
+	if (percentage < completion->priv->last_percentage) {
+		egg_warning ("percentage cannot go down from %i to %i on %p!", completion->priv->last_percentage, percentage, completion);
+		return FALSE;
+	}
+
+	/* emit and save */
+	g_signal_emit (completion, signals [SIGNAL_PERCENTAGE_CHANGED], 0, percentage);
+	completion->priv->last_percentage = percentage;
+out:
+	return TRUE;
+}
+
+/**
+ * zif_completion_get_percentage:
+ * @completion: the #ZifCompletion object
+ *
+ * Get the percentage completion.
+ *
+ * Return value: A percentage value, or G_MAXUINT for error
+ **/
+guint
+zif_completion_get_percentage (ZifCompletion *completion)
+{
+	return completion->priv->last_percentage;
+}
+
+/**
+ * zif_completion_set_subpercentage:
+ **/
+static gboolean
+zif_completion_set_subpercentage (ZifCompletion *completion, guint percentage)
+{
+	/* just emit */
+	g_signal_emit (completion, signals [SIGNAL_SUBPERCENTAGE_CHANGED], 0, percentage);
+	return TRUE;
+}
+
+/**
+ * zif_completion_child_percentage_changed_cb:
+ **/
+static void
+zif_completion_child_percentage_changed_cb (ZifCompletion *child, guint percentage, ZifCompletion *completion)
+{
+	gfloat offset;
+	gfloat range;
+	gfloat extra;
+
+	/* propagate up the stack if ZifCompletion has only one step */
+	if (completion->priv->steps == 1) {
+		zif_completion_set_percentage (completion, percentage);
+		return;
+	}
+
+	/* did we call done on a completion that did not have a size set? */
+	if (completion->priv->steps == 0) {
+		egg_warning ("done on a completion %p that did not have a size set!", completion);
+		zif_debug_crash ();
+		return;
+	}
+
+	/* always provide two levels of signals */
+	zif_completion_set_subpercentage (completion, percentage);
+
+	/* already at >= 100% */
+	if (completion->priv->current >= completion->priv->steps) {
+		egg_warning ("already at %i/%i steps on %p", completion->priv->current, completion->priv->steps, completion);
+		return;
+	}
+
+	/* get the offset */
+	offset = zif_completion_discrete_to_percent (completion->priv->current, completion->priv->steps);
+
+	/* get the range between the parent step and the next parent step */
+	range = zif_completion_discrete_to_percent (completion->priv->current+1, completion->priv->steps) - offset;
+	if (range < 0.01) {
+		egg_warning ("range=%f (from %i to %i), should be impossible", range, completion->priv->current+1, completion->priv->steps);
+		return;
+	}
+
+	/* get the extra contributed by the child */
+	extra = ((gfloat) percentage / 100.0f) * range;
+
+	/* emit from the parent */
+	zif_completion_set_percentage (completion, (guint) (offset + extra));
+}
+
+/**
+ * zif_completion_child_subpercentage_changed_cb:
+ **/
+static void
+zif_completion_child_subpercentage_changed_cb (ZifCompletion *child, guint percentage, ZifCompletion *completion)
+{
+	/* discard this, unless the ZifCompletion has only one step */
+	if (completion->priv->steps != 1)
+		return;
+
+	/* propagate up the stack as if the parent didn't exist */
+	zif_completion_set_subpercentage (completion, percentage);
+}
+
+/**
+ * zif_completion_reset:
+ * @completion: the #ZifCompletion object
+ *
+ * Resets the #ZifCompletion object to unset
+ *
+ * Return value: %TRUE for success, %FALSE for failure
+ **/
+gboolean
+zif_completion_reset (ZifCompletion *completion)
+{
+	g_return_val_if_fail (ZIF_IS_COMPLETION (completion), FALSE);
+
+	/* reset values */
+	completion->priv->steps = 0;
+	completion->priv->current = 0;
+	completion->priv->last_percentage = 0;
+
+	/* disconnect client */
+	if (completion->priv->percentage_child_id != 0) {
+		g_signal_handler_disconnect (completion->priv->child, completion->priv->percentage_child_id);
+		completion->priv->percentage_child_id = 0;
+	}
+	if (completion->priv->subpercentage_child_id != 0) {
+		g_signal_handler_disconnect (completion->priv->child, completion->priv->subpercentage_child_id);
+		completion->priv->subpercentage_child_id = 0;
+	}
+
+	/* unref child */
+	if (completion->priv->child != NULL) {
+		g_object_unref (completion->priv->child);
+		completion->priv->child = NULL;
+	}
+
+	return TRUE;
+}
+
+/**
+ * zif_completion_get_child:
+ * @completion: the #ZifCompletion object
+ *
+ * Monitor a child completion and proxy back up to the parent completion.
+ * Yo udo not have to g_object_unref() this value.
+ *
+ * Return value: a new %ZifCompletion or %NULL for failure
+ **/
+ZifCompletion *
+zif_completion_get_child (ZifCompletion *completion)
+{
+	ZifCompletion *child = NULL;
+
+	g_return_val_if_fail (ZIF_IS_COMPLETION (completion), FALSE);
+
+	/* already set child */
+	if (completion->priv->child != NULL) {
+		g_signal_handler_disconnect (completion->priv->child, completion->priv->percentage_child_id);
+		g_signal_handler_disconnect (completion->priv->child, completion->priv->subpercentage_child_id);
+		g_object_unref (completion->priv->child);
+	}
+
+	/* connect up signals */
+	child = zif_completion_new ();
+	completion->priv->child = g_object_ref (child);
+	completion->priv->percentage_child_id =
+		g_signal_connect (child, "percentage-changed", G_CALLBACK (zif_completion_child_percentage_changed_cb), completion);
+	completion->priv->subpercentage_child_id =
+		g_signal_connect (child, "subpercentage-changed", G_CALLBACK (zif_completion_child_subpercentage_changed_cb), completion);
+
+	/* reset child */
+	child->priv->current = 0;
+	child->priv->last_percentage = 0;
+
+	return child;
+}
+
+/**
+ * zif_completion_set_number_steps:
+ * @completion: the #ZifCompletion object
+ * @steps: The number of sub-tasks in this transaction
+ *
+ * Sets the number of sub-tasks, i.e. how many times the zif_completion_done()
+ * function will be called in the loop.
+ *
+ * Return value: %TRUE for success, %FALSE for failure
+ **/
+gboolean
+zif_completion_set_number_steps (ZifCompletion *completion, guint steps)
+{
+	g_return_val_if_fail (ZIF_IS_COMPLETION (completion), FALSE);
+	g_return_val_if_fail (steps != 0, FALSE);
+
+	/* did we call done on a completion that did not have a size set? */
+	if (completion->priv->steps != 0) {
+		egg_warning ("steps already set (%i)!", completion->priv->steps);
+		zif_debug_crash ();
+		return FALSE;
+	}
+
+	/* imply reset */
+	zif_completion_reset (completion);
+
+	/* set steps */
+	completion->priv->steps = steps;
+
+	return TRUE;
+}
+
+/**
+ * zif_completion_done:
+ * @completion: the #ZifCompletion object
+ *
+ * Called when the current sub-task has finished.
+ *
+ * Return value: %TRUE for success, %FALSE for failure
+ **/
+gboolean
+zif_completion_done (ZifCompletion *completion)
+{
+	gfloat percentage;
+
+	g_return_val_if_fail (ZIF_IS_COMPLETION (completion), FALSE);
+
+	/* did we call done on a completion that did not have a size set? */
+	if (completion->priv->steps == 0) {
+		egg_warning ("done on a completion %p that did not have a size set!", completion);
+		zif_debug_crash ();
+		return FALSE;
+	}
+
+	/* is already at 100%? */
+	if (completion->priv->current == completion->priv->steps) {
+		egg_warning ("already at 100%% completion");
+		return FALSE;
+	}
+
+	/* another */
+	completion->priv->current++;
+
+	/* find new percentage */
+	percentage = zif_completion_discrete_to_percent (completion->priv->current, completion->priv->steps);
+	zif_completion_set_percentage (completion, (guint) percentage);
+
+	/* reset child if it exists */
+	if (completion->priv->child != NULL)
+		zif_completion_reset (completion->priv->child);
+
+	return TRUE;
+}
+
+/**
+ * zif_completion_finalize:
+ **/
+static void
+zif_completion_finalize (GObject *object)
+{
+	ZifCompletion *completion;
+
+	g_return_if_fail (object != NULL);
+	g_return_if_fail (ZIF_IS_COMPLETION (object));
+	completion = ZIF_COMPLETION (object);
+
+	/* unref child too */
+	zif_completion_reset (completion);
+
+	G_OBJECT_CLASS (zif_completion_parent_class)->finalize (object);
+}
+
+/**
+ * zif_completion_class_init:
+ **/
+static void
+zif_completion_class_init (ZifCompletionClass *klass)
+{
+	GObjectClass *object_class = G_OBJECT_CLASS (klass);
+	object_class->finalize = zif_completion_finalize;
+
+	signals [SIGNAL_PERCENTAGE_CHANGED] =
+		g_signal_new ("percentage-changed",
+			      G_TYPE_FROM_CLASS (object_class), G_SIGNAL_RUN_LAST,
+			      G_STRUCT_OFFSET (ZifCompletionClass, percentage_changed),
+			      NULL, NULL, g_cclosure_marshal_VOID__UINT,
+			      G_TYPE_NONE, 1, G_TYPE_UINT);
+
+	signals [SIGNAL_SUBPERCENTAGE_CHANGED] =
+		g_signal_new ("subpercentage-changed",
+			      G_TYPE_FROM_CLASS (object_class), G_SIGNAL_RUN_LAST,
+			      G_STRUCT_OFFSET (ZifCompletionClass, subpercentage_changed),
+			      NULL, NULL, g_cclosure_marshal_VOID__UINT,
+			      G_TYPE_NONE, 1, G_TYPE_UINT);
+
+	g_type_class_add_private (klass, sizeof (ZifCompletionPrivate));
+}
+
+/**
+ * zif_completion_init:
+ **/
+static void
+zif_completion_init (ZifCompletion *completion)
+{
+	completion->priv = ZIF_COMPLETION_GET_PRIVATE (completion);
+	completion->priv->child = NULL;
+	completion->priv->steps = 0;
+	completion->priv->current = 0;
+	completion->priv->last_percentage = 0;
+	completion->priv->percentage_child_id = 0;
+	completion->priv->subpercentage_child_id = 0;
+}
+
+/**
+ * zif_completion_new:
+ *
+ * Return value: A new #ZifCompletion class instance.
+ **/
+ZifCompletion *
+zif_completion_new (void)
+{
+	ZifCompletion *completion;
+	completion = g_object_new (ZIF_TYPE_COMPLETION, NULL);
+	return ZIF_COMPLETION (completion);
+}
+
+/***************************************************************************
+ ***                          MAKE CHECK TESTS                           ***
+ ***************************************************************************/
+#ifdef EGG_TEST
+#include "egg-test.h"
+
+static guint _updates = 0;
+static guint _last_percent = 0;
+static guint _last_subpercent = 0;
+
+static void
+zif_completion_test_percentage_changed_cb (ZifCompletion *completion, guint value, gpointer data)
+{
+	_last_percent = value;
+	_updates++;
+}
+
+static void
+zif_completion_test_subpercentage_changed_cb (ZifCompletion *completion, guint value, gpointer data)
+{
+	_last_subpercent = value;
+}
+
+void
+zif_completion_test (EggTest *test)
+{
+	ZifCompletion *completion;
+	ZifCompletion *child;
+	gboolean ret;
+
+	if (!egg_test_start (test, "ZifCompletion"))
+		return;
+
+	/************************************************************/
+	egg_test_title (test, "get completion");
+	completion = zif_completion_new ();
+	egg_test_assert (test, completion != NULL);
+	g_signal_connect (completion, "percentage-changed", G_CALLBACK (zif_completion_test_percentage_changed_cb), NULL);
+	g_signal_connect (completion, "subpercentage-changed", G_CALLBACK (zif_completion_test_subpercentage_changed_cb), NULL);
+
+	/************************************************************/
+	egg_test_title (test, "set steps");
+	ret = zif_completion_set_number_steps (completion, 5);
+	egg_test_assert (test, ret);
+
+	/************************************************************/
+	egg_test_title (test, "done one step");
+	ret = zif_completion_done (completion);
+	egg_test_assert (test, ret);
+
+	/************************************************************/
+	egg_test_title (test, "ensure 1 update");
+	egg_test_assert (test, (_updates == 1));
+
+	/************************************************************/
+	egg_test_title (test, "ensure correct percent");
+	egg_test_assert (test, (_last_percent == 20));
+
+	/************************************************************/
+	egg_test_title (test, "done the rest");
+	ret = zif_completion_done (completion);
+	ret = zif_completion_done (completion);
+	ret = zif_completion_done (completion);
+	ret = zif_completion_done (completion);
+	egg_test_assert (test, ret);
+
+	/************************************************************/
+	egg_test_title (test, "done one extra");
+	ret = zif_completion_done (completion);
+	egg_test_assert (test, !ret);
+
+	/************************************************************/
+	egg_test_title (test, "ensure 5 updates");
+	egg_test_assert (test, (_updates == 5));
+
+	/************************************************************/
+	egg_test_title (test, "ensure correct percent");
+	egg_test_assert (test, (_last_percent == 100));
+
+	g_object_unref (completion);
+
+	/* reset */
+	_updates = 0;
+	completion = zif_completion_new ();
+	zif_completion_set_number_steps (completion, 2);
+	g_signal_connect (completion, "percentage-changed", G_CALLBACK (zif_completion_test_percentage_changed_cb), NULL);
+	g_signal_connect (completion, "subpercentage-changed", G_CALLBACK (zif_completion_test_subpercentage_changed_cb), NULL);
+
+	// completion: |-----------------------|-----------------------|
+	// step1:      |-----------------------|
+	// child:                              |-------------|---------|
+
+	/* PARENT UPDATE */
+	zif_completion_done (completion);
+
+	/************************************************************/
+	egg_test_title (test, "ensure 1 update");
+	egg_test_assert (test, (_updates == 1));
+
+	/************************************************************/
+	egg_test_title (test, "ensure correct percent");
+	egg_test_assert (test, (_last_percent == 50));
+
+	/* now test with a child */
+	child = zif_completion_get_child (completion);
+	zif_completion_set_number_steps (child, 2);
+
+	/* CHILD UPDATE */
+	zif_completion_done (child);
+
+	/************************************************************/
+	egg_test_title (test, "ensure 2 updates");
+	egg_test_assert (test, (_updates == 2));
+
+	/************************************************************/
+	egg_test_title (test, "ensure correct percent");
+	egg_test_assert (test, (_last_percent == 75));
+
+	/* CHILD UPDATE */
+	zif_completion_done (child);
+
+	/************************************************************/
+	egg_test_title (test, "ensure 3 updates");
+	if (_updates == 3)
+		egg_test_success (test, NULL);
+	else
+		egg_test_failed (test, "got %i updates", _updates);
+
+	/************************************************************/
+	egg_test_title (test, "ensure correct percent");
+	egg_test_assert (test, (_last_percent == 100));
+
+	/* PARENT UPDATE */
+	zif_completion_done (completion);
+
+	/************************************************************/
+	egg_test_title (test, "ensure 3 updates (and we ignored the duplicate)");
+	if (_updates == 3)
+		egg_test_success (test, NULL);
+	else
+		egg_test_failed (test, "got %i updates", _updates);
+
+	/************************************************************/
+	egg_test_title (test, "ensure still correct percent");
+	egg_test_assert (test, (_last_percent == 100));
+
+	egg_debug ("unref completion");
+	g_object_unref (completion);
+
+	egg_debug ("unref child");
+	g_object_unref (child);
+
+	egg_debug ("reset");
+	/* reset */
+	_updates = 0;
+	completion = zif_completion_new ();
+	zif_completion_set_number_steps (completion, 1);
+	g_signal_connect (completion, "percentage-changed", G_CALLBACK (zif_completion_test_percentage_changed_cb), NULL);
+	g_signal_connect (completion, "subpercentage-changed", G_CALLBACK (zif_completion_test_subpercentage_changed_cb), NULL);
+
+	/* now test with a child */
+	child = zif_completion_get_child (completion);
+	zif_completion_set_number_steps (child, 2);
+
+	/* CHILD SET VALUE */
+	zif_completion_set_percentage (child, 33);
+
+	/************************************************************/
+	egg_test_title (test, "ensure 1 updates for completion with one step");
+	egg_test_assert (test, (_updates == 1));
+
+	/************************************************************/
+	egg_test_title (test, "ensure using child value as parent");
+	egg_test_assert (test, (_last_percent == 33));
+
+	g_object_unref (completion);
+	g_object_unref (child);
+
+	egg_test_end (test);
+}
+#endif
+
diff --git a/backends/yum/libzif/zif-completion.h b/backends/yum/libzif/zif-completion.h
new file mode 100644
index 0000000..33a2598
--- /dev/null
+++ b/backends/yum/libzif/zif-completion.h
@@ -0,0 +1,79 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2009 Richard Hughes <richard at hughsie.com>
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#if !defined (__ZIF_H_INSIDE__) && !defined (ZIF_COMPILATION)
+#error "Only <zif.h> can be included directly."
+#endif
+
+#ifndef __ZIF_COMPLETION_H
+#define __ZIF_COMPLETION_H
+
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+#define ZIF_TYPE_COMPLETION		(zif_completion_get_type ())
+#define ZIF_COMPLETION(o)		(G_TYPE_CHECK_INSTANCE_CAST ((o), ZIF_TYPE_COMPLETION, ZifCompletion))
+#define ZIF_COMPLETION_CLASS(k)		(G_TYPE_CHECK_CLASS_CAST((k), ZIF_TYPE_COMPLETION, ZifCompletionClass))
+#define ZIF_IS_COMPLETION(o)		(G_TYPE_CHECK_INSTANCE_TYPE ((o), ZIF_TYPE_COMPLETION))
+#define ZIF_IS_COMPLETION_CLASS(k)	(G_TYPE_CHECK_CLASS_TYPE ((k), ZIF_TYPE_COMPLETION))
+#define ZIF_COMPLETION_GET_CLASS(o)	(G_TYPE_INSTANCE_GET_CLASS ((o), ZIF_TYPE_COMPLETION, ZifCompletionClass))
+
+typedef struct _ZifCompletion		ZifCompletion;
+typedef struct _ZifCompletionPrivate	ZifCompletionPrivate;
+typedef struct _ZifCompletionClass	ZifCompletionClass;
+
+struct _ZifCompletion
+{
+	GObject			 parent;
+	ZifCompletionPrivate	*priv;
+};
+
+struct _ZifCompletionClass
+{
+	GObjectClass	 parent_class;
+	/* Signals */
+	void		(* percentage_changed)		(ZifCompletion	*completion,
+							 guint		 value);
+	void		(* subpercentage_changed)	(ZifCompletion	*completion,
+							 guint		 value);
+	/* Padding for future expansion */
+	void (*_zif_reserved1) (void);
+	void (*_zif_reserved2) (void);
+	void (*_zif_reserved3) (void);
+	void (*_zif_reserved4) (void);
+};
+
+GType		 zif_completion_get_type		(void);
+ZifCompletion	*zif_completion_new			(void);
+ZifCompletion	*zif_completion_get_child		(ZifCompletion		*completion);
+gboolean	 zif_completion_set_number_steps	(ZifCompletion		*completion,
+							 guint			 steps);
+gboolean	 zif_completion_set_percentage		(ZifCompletion		*completion,
+							 guint			 percentage);
+guint		 zif_completion_get_percentage		(ZifCompletion		*completion);
+gboolean	 zif_completion_done			(ZifCompletion		*completion);
+gboolean	 zif_completion_reset			(ZifCompletion		*completion);
+
+G_END_DECLS
+
+#endif /* __ZIF_COMPLETION_H */
+
diff --git a/backends/yum/libzif/zif-config.c b/backends/yum/libzif/zif-config.c
new file mode 100644
index 0000000..a8dd1cd
--- /dev/null
+++ b/backends/yum/libzif/zif-config.c
@@ -0,0 +1,762 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2008 Richard Hughes <richard at hughsie.com>
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+/**
+ * SECTION:zif-config
+ * @short_description: A #ZifConfig object manages system wide config options
+ *
+ * #ZifConfig allows settings to be read from a central config file. Some
+ * values can be overridden in a running instance.
+ *
+ * The values that are overridden can be reset back to the defaults without
+ * re-reading the config file.
+ *
+ * Different types of data can be read (string, bool, uint, time).
+ * Before reading any data, the backing config file has to be set with
+ * zif_config_set_filename() and any reads prior to that will fail.
+ */
+
+#include <string.h>
+
+#include <glib.h>
+#include <packagekit-glib2/packagekit.h>
+#include <rpm/rpmlib.h>
+
+#include "zif-config.h"
+#include "zif-utils.h"
+#include "zif-monitor.h"
+
+#include "egg-debug.h"
+#include "egg-string.h"
+
+#define ZIF_CONFIG_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), ZIF_TYPE_CONFIG, ZifConfigPrivate))
+
+struct _ZifConfigPrivate
+{
+	GKeyFile		*keyfile;
+	gboolean		 loaded;
+	ZifMonitor		*monitor;
+	GHashTable		*hash;
+	gchar			**basearch_list;
+};
+
+G_DEFINE_TYPE (ZifConfig, zif_config, G_TYPE_OBJECT)
+static gpointer zif_config_object = NULL;
+
+/**
+ * zif_config_get_string:
+ * @config: the #ZifConfig object
+ * @key: the key name to retrieve, e.g. "cachedir"
+ * @error: a #GError which is used on failure, or %NULL
+ *
+ * Gets a string value from a local setting, falling back to the config file.
+ *
+ * Return value: the allocated value, or %NULL
+ **/
+gchar *
+zif_config_get_string (ZifConfig *config, const gchar *key, GError **error)
+{
+	gchar *value = NULL;
+	const gchar *value_tmp;
+	const gchar *info;
+	GError *error_local = NULL;
+
+	g_return_val_if_fail (ZIF_IS_CONFIG (config), NULL);
+	g_return_val_if_fail (key != NULL, NULL);
+
+	/* not loaded yet */
+	if (!config->priv->loaded) {
+		if (error != NULL)
+			*error = g_error_new (1, 0, "config not loaded");
+		goto out;
+	}
+
+	/* exists as local override */
+	value_tmp = g_hash_table_lookup (config->priv->hash, key);
+	if (value_tmp != NULL) {
+		value = g_strdup (value_tmp);
+		goto out;
+	}
+
+	/* get value */
+	value = g_key_file_get_string (config->priv->keyfile, "main", key, &error_local);
+	if (value != NULL)
+		goto out;
+
+	/* special keys, FIXME: add to yum */
+	if (g_strcmp0 (key, "reposdir") == 0) {
+		value = g_strdup ("/etc/yum.repos.d");
+		goto free_error;
+	}
+	if (g_strcmp0 (key, "pidfile") == 0) {
+		value = g_strdup ("/var/run/yum.pid");
+		goto free_error;
+	}
+
+	/* special rpmkeys */
+	if (g_strcmp0 (key, "osinfo") == 0) {
+		rpmGetOsInfo (&info, NULL);
+		value = g_strdup (info);
+		goto free_error;
+	}
+	if (g_strcmp0 (key, "archinfo") == 0) {
+		rpmGetArchInfo (&info, NULL);
+		value = g_strdup (info);
+		goto free_error;
+	}
+
+	/* dumb metadata */
+	if (g_strcmp0 (key, "basearch") == 0) {
+		rpmGetArchInfo (&info, NULL);
+		if (g_strcmp0 (info, "i486") == 0 ||
+		    g_strcmp0 (info, "i586") == 0 ||
+		    g_strcmp0 (info, "i686") == 0)
+			info = "i386";
+		value = g_strdup (info);
+		goto free_error;
+	}
+
+	/* nothing matched */
+	if (error != NULL)
+		*error = g_error_new (1, 0, "failed to read %s: %s", key, error_local->message);
+free_error:
+	g_error_free (error_local);
+out:
+	return value;
+}
+
+/**
+ * zif_config_get_boolean:
+ * @config: the #ZifConfig object
+ * @key: the key name to retrieve, e.g. "keepcache"
+ * @error: a #GError which is used on failure, or %NULL
+ *
+ * Gets a boolean value from a local setting, falling back to the config file.
+ *
+ * Return value: %TRUE or %FALSE
+ **/
+gboolean
+zif_config_get_boolean (ZifConfig *config, const gchar *key, GError **error)
+{
+	gchar *value;
+	gboolean ret = FALSE;
+
+	g_return_val_if_fail (ZIF_IS_CONFIG (config), FALSE);
+	g_return_val_if_fail (key != NULL, FALSE);
+
+	/* get string value */
+	value = zif_config_get_string (config, key, error);
+	if (value == NULL)
+		goto out;
+
+	/* convert to bool */
+	ret = zif_boolean_from_text (value);
+
+out:
+	g_free (value);
+	return ret;
+}
+
+/**
+ * zif_config_get_uint:
+ * @config: the #ZifConfig object
+ * @key: the key name to retrieve, e.g. "keepcache"
+ * @error: a #GError which is used on failure, or %NULL
+ *
+ * Gets a unsigned integer value from a local setting, falling back to the config file.
+ *
+ * Return value: the data value, or %G_MAXUINT for error
+ **/
+guint
+zif_config_get_uint (ZifConfig *config, const gchar *key, GError **error)
+{
+	gchar *value;
+	gboolean ret;
+	guint retval = G_MAXUINT;
+
+	g_return_val_if_fail (ZIF_IS_CONFIG (config), G_MAXUINT);
+	g_return_val_if_fail (key != NULL, G_MAXUINT);
+
+	/* get string value */
+	value = zif_config_get_string (config, key, error);
+	if (value == NULL)
+		goto out;
+
+	/* convert to int */
+	ret = egg_strtouint (value, &retval);
+	if (!ret) {
+		if (error != NULL)
+			*error = g_error_new (1, 0, "failed to convert '%s' to unsigned integer", value);
+		goto out;
+	}
+
+out:
+	g_free (value);
+	return retval;
+}
+
+/**
+ * zif_config_string_to_time:
+ *
+ * Converts: 10s to 10
+ *           10m to 600 (10*60)
+ *           10h to 36000 (10*60*60)
+ *           10d to 864000 (10*60*60*24)
+ **/
+static guint
+zif_config_string_to_time (const gchar *value)
+{
+	gboolean ret;
+	guint len;
+	guint timeval = 0;
+	gchar suffix;
+	gchar *value_copy = NULL;
+
+	g_return_val_if_fail (value != NULL, FALSE);
+
+	/* long enough */
+	len = egg_strlen (value, 10);
+	if (len < 2)
+		goto out;
+
+	/* get suffix */
+	suffix = value[len-1];
+
+	/* remove suffix */
+	value_copy = g_strdup (value);
+	value_copy[len-1] = '\0';
+
+	/* convert to number */
+	ret = egg_strtouint (value_copy, &timeval);
+	if (!ret) {
+		egg_warning ("failed to convert %s", value_copy);
+		goto out;
+	}
+
+	/* seconds, minutes, hours, days */
+	if (suffix == 's')
+		timeval *= 1;
+	else if (suffix == 'm')
+		timeval *= 60;
+	else if (suffix == 'h')
+		timeval *= 60*60;
+	else if (suffix == 'd')
+		timeval *= 24*60*60;
+	else {
+		egg_warning ("unknown suffix: '%c'", suffix);
+		timeval = 0;
+	}
+out:
+	g_free (value_copy);
+	return timeval;
+}
+
+/**
+ * zif_config_get_time:
+ * @config: the #ZifConfig object
+ * @key: the key name to retrieve, e.g. "metadata_expire"
+ * @error: a #GError which is used on failure, or %NULL
+ *
+ * Gets a time value from a local setting, falling back to the config file.
+ *
+ * Return value: the data value
+ **/
+guint
+zif_config_get_time (ZifConfig *config, const gchar *key, GError **error)
+{
+	gchar *value;
+	guint timeval = 0;
+
+	g_return_val_if_fail (ZIF_IS_CONFIG (config), FALSE);
+	g_return_val_if_fail (key != NULL, FALSE);
+
+	/* get string value */
+	value = zif_config_get_string (config, key, error);
+	if (value == NULL)
+		goto out;
+
+	/* convert to time */
+	timeval = zif_config_string_to_time (value);
+out:
+	g_free (value);
+	return timeval;
+}
+
+/**
+ * zif_config_expand_substitutions:"
+ * @config: the #ZifConfig object
+ * @text: string to scan, e.g. "http://fedora/$releasever/$basearch/moo.rpm"
+ * @error: a #GError which is used on failure, or %NULL
+ *
+ * Replaces substitutions in text with the actual values of the running system.
+ *
+ * Return value: A new allocated string or %NULL for error, free with g_free()
+ **/
+gchar *
+zif_config_expand_substitutions (ZifConfig *config, const gchar *text, GError **error)
+{
+	gchar *basearch = NULL;
+	gchar *releasever = NULL;
+	gchar *name1 = NULL;
+	gchar *name2 = NULL;
+
+	g_return_val_if_fail (ZIF_IS_CONFIG (config), NULL);
+	g_return_val_if_fail (text != NULL, NULL);
+
+	/* get data */
+	basearch = zif_config_get_string (config, "basearch", error);
+	if (basearch == NULL)
+		goto out;
+
+	releasever = zif_config_get_string (config, "releasever", error);
+	if (releasever == NULL)
+		goto out;
+
+	/* do the replacements */
+	name1 = egg_strreplace (text, "$releasever", releasever);
+	name2 = egg_strreplace (name1, "$basearch", basearch);
+
+out:
+	g_free (basearch);
+	g_free (releasever);
+	g_free (name1);
+	return name2;
+}
+
+/**
+ * zif_config_get_basearch_array:
+ * @config: the #ZifConfig object
+ *
+ * Gets the list of architectures that packages are native on for this machine.
+ *
+ * Return value: A array of strings, do not free, e.g. [ "i386", "i486", "noarch" ]
+ **/
+gchar **
+zif_config_get_basearch_array (ZifConfig *config)
+{
+	g_return_val_if_fail (ZIF_IS_CONFIG (config), NULL);
+	return config->priv->basearch_list;
+}
+
+/**
+ * zif_config_set_filename:
+ * @config: the #ZifConfig object
+ * @filename: the system wide config file, e.g. "/etc/yum.conf"
+ * @error: a #GError which is used on failure, or %NULL
+ *
+ * Sets the filename to use as the system wide config file.
+ *
+ * Return value: %TRUE for success, %FALSE for failure
+ **/
+gboolean
+zif_config_set_filename (ZifConfig *config, const gchar *filename, GError **error)
+{
+	gboolean ret;
+	GError *error_local = NULL;
+	gchar *basearch = NULL;
+	gchar *releasever = NULL;
+	const gchar *text;
+	GPtrArray *array;
+	guint i;
+
+	g_return_val_if_fail (ZIF_IS_CONFIG (config), FALSE);
+	g_return_val_if_fail (filename != NULL, FALSE);
+	g_return_val_if_fail (!config->priv->loaded, FALSE);
+
+	/* check file exists */
+	ret = g_file_test (filename, G_FILE_TEST_IS_REGULAR);
+	if (!ret) {
+		if (error != NULL)
+			*error = g_error_new (1, 0, "config file %s does not exist", filename);
+		goto out;
+	}
+
+	/* setup watch */
+	ret = zif_monitor_add_watch (config->priv->monitor, filename, &error_local);
+	if (!ret) {
+		if (error != NULL)
+			*error = g_error_new (1, 0, "failed to setup watch: %s", error_local->message);
+		g_error_free (error_local);
+		goto out;
+	}
+
+	/* load file */
+	ret = g_key_file_load_from_file (config->priv->keyfile, filename, G_KEY_FILE_NONE, &error_local);
+	if (!ret) {
+		if (error != NULL)
+			*error = g_error_new (1, 0, "failed to load config file: %s", error_local->message);
+		g_error_free (error_local);
+		goto out;
+	}
+
+	/* done */
+	config->priv->loaded = TRUE;
+
+	/* calculate the release version if not specified in the config file */
+	releasever = zif_config_get_string (config, "releasever", NULL);
+	if (releasever == NULL) {
+		/* get distro constants from fedora-release */
+		ret = g_file_get_contents ("/etc/fedora-release", &releasever, NULL, &error_local);
+		if (!ret) {
+			if (error != NULL)
+				*error = g_error_new (1, 0, "failed to get distro release version: %s", error_local->message);
+			g_error_free (error_local);
+			goto out;
+		}
+
+		/* get the value from 'Fedora release 11.92 (Rawhide)' */
+		g_strdelimit (releasever, " ", '\0');
+
+		/* set local */
+		ret = zif_config_set_local (config, "releasever", releasever+15, &error_local);
+		if (!ret) {
+			if (error != NULL)
+				*error = g_error_new (1, 0, "failed to set distro release version: %s", error_local->message);
+			g_error_free (error_local);
+			goto out;
+		}
+	}
+
+	/* calculate the valid basearchs */
+	basearch = zif_config_get_string (config, "basearch", &error_local);
+	if (basearch == NULL) {
+		if (error != NULL)
+			*error = g_error_new (1, 0, "failed to get basearch: %s", error_local->message);
+		g_error_free (error_local);
+		ret = FALSE;
+		goto out;
+	}
+
+	/* add valid archs to array */
+	array = g_ptr_array_new_with_free_func ((GDestroyNotify) g_free);
+	g_ptr_array_add (array, g_strdup (basearch));
+	g_ptr_array_add (array, g_strdup ("noarch"));
+	if (g_strcmp0 (basearch, "i386") == 0) {
+		g_ptr_array_add (array, g_strdup ("i486"));
+		g_ptr_array_add (array, g_strdup ("i586"));
+		g_ptr_array_add (array, g_strdup ("i686"));
+	}
+
+	/* copy into GStrv array */
+	config->priv->basearch_list = g_new0 (gchar*, array->len+1);
+	for (i=0; i < array->len; i++) {
+		text = g_ptr_array_index (array, i);
+		config->priv->basearch_list[i] = g_strdup (text);
+	}
+	g_ptr_array_unref (array);
+out:
+	g_free (basearch);
+	g_free (releasever);
+	return ret;
+}
+
+/**
+ * zif_config_reset_default:
+ * @config: the #ZifConfig object
+ * @error: a #GError which is used on failure, or %NULL
+ *
+ * Removes any local settings previously set.
+ *
+ * Return value: %TRUE for success, %FALSE for failure
+ **/
+gboolean
+zif_config_reset_default (ZifConfig *config, GError **error)
+{
+	g_return_val_if_fail (ZIF_IS_CONFIG (config), FALSE);
+	g_hash_table_remove_all (config->priv->hash);
+	return TRUE;
+}
+
+/**
+ * zif_config_set_local:
+ * @config: the #ZifConfig object
+ * @key: the key name to save, e.g. "keepcache"
+ * @value: the key data to save, e.g. "always"
+ * @error: a #GError which is used on failure, or %NULL
+ *
+ * Sets a local value which is used in preference to the config value.
+ *
+ * Return value: %TRUE for success, %FALSE for failure
+ **/
+gboolean
+zif_config_set_local (ZifConfig *config, const gchar *key, const gchar *value, GError **error)
+{
+	const gchar *value_tmp;
+	gboolean ret = TRUE;
+
+	g_return_val_if_fail (ZIF_IS_CONFIG (config), FALSE);
+	g_return_val_if_fail (key != NULL, FALSE);
+
+	/* already exists? */
+	value_tmp = g_hash_table_lookup (config->priv->hash, key);
+	if (value_tmp != NULL) {
+		if (error != NULL)
+			*error = g_error_new (1, 0, "already set key %s to %s, cannot overwrite with %s", key, value_tmp, value);
+		ret = FALSE;
+		goto out;
+	}
+
+	/* insert into table */
+	g_hash_table_insert (config->priv->hash, g_strdup (key), g_strdup (value));
+out:
+	return ret;
+}
+
+/**
+ * zif_config_file_monitor_cb:
+ **/
+static void
+zif_config_file_monitor_cb (ZifMonitor *monitor, ZifConfig *config)
+{
+	egg_warning ("config file changed");
+	config->priv->loaded = FALSE;
+}
+
+/**
+ * zif_config_finalize:
+ **/
+static void
+zif_config_finalize (GObject *object)
+{
+	ZifConfig *config;
+	g_return_if_fail (ZIF_IS_CONFIG (object));
+	config = ZIF_CONFIG (object);
+
+	g_key_file_free (config->priv->keyfile);
+	g_hash_table_unref (config->priv->hash);
+	g_object_unref (config->priv->monitor);
+	g_strfreev (config->priv->basearch_list);
+
+	G_OBJECT_CLASS (zif_config_parent_class)->finalize (object);
+}
+
+/**
+ * zif_config_class_init:
+ **/
+static void
+zif_config_class_init (ZifConfigClass *klass)
+{
+	GObjectClass *object_class = G_OBJECT_CLASS (klass);
+	object_class->finalize = zif_config_finalize;
+	g_type_class_add_private (klass, sizeof (ZifConfigPrivate));
+}
+
+/**
+ * zif_config_init:
+ **/
+static void
+zif_config_init (ZifConfig *config)
+{
+	config->priv = ZIF_CONFIG_GET_PRIVATE (config);
+	config->priv->keyfile = g_key_file_new ();
+	config->priv->loaded = FALSE;
+	config->priv->hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
+	config->priv->basearch_list = NULL;
+	config->priv->monitor = zif_monitor_new ();
+	g_signal_connect (config->priv->monitor, "changed", G_CALLBACK (zif_config_file_monitor_cb), config);
+}
+
+/**
+ * zif_config_new:
+ *
+ * Return value: A new #ZifConfig class instance.
+ **/
+ZifConfig *
+zif_config_new (void)
+{
+	if (zif_config_object != NULL) {
+		g_object_ref (zif_config_object);
+	} else {
+		zif_config_object = g_object_new (ZIF_TYPE_CONFIG, NULL);
+		g_object_add_weak_pointer (zif_config_object, &zif_config_object);
+	}
+	return ZIF_CONFIG (zif_config_object);
+}
+
+/***************************************************************************
+ ***                          MAKE CHECK TESTS                           ***
+ ***************************************************************************/
+#ifdef EGG_TEST
+#include "egg-test.h"
+
+void
+zif_config_test (EggTest *test)
+{
+	ZifConfig *config;
+	gboolean ret;
+	GError *error = NULL;
+	gchar *value;
+	guint time;
+	guint len;
+	gchar **array;
+
+	if (!egg_test_start (test, "ZifConfig"))
+		return;
+
+	/************************************************************/
+	egg_test_title (test, "get config");
+	config = zif_config_new ();
+	egg_test_assert (test, config != NULL);
+
+	/************************************************************/
+	egg_test_title (test, "set filename");
+	ret = zif_config_set_filename (config, "../test/etc/yum.conf", &error);
+	if (ret)
+		egg_test_success (test, NULL);
+	else
+		egg_test_failed (test, "failed to set filename '%s'", error->message);
+
+	/************************************************************/
+	egg_test_title (test, "get cachedir");
+	value = zif_config_get_string (config, "cachedir", NULL);
+	if (egg_strequal (value, "../test/cache"))
+		egg_test_success (test, NULL);
+	else
+		egg_test_failed (test, "invalid value '%s'", value);
+	g_free (value);
+
+	/************************************************************/
+	egg_test_title (test, "get cachexxxdir");
+	value = zif_config_get_string (config, "cachexxxdir", NULL);
+	if (value == NULL)
+		egg_test_success (test, NULL);
+	else
+		egg_test_failed (test, "invalid value '%s'", value);
+	g_free (value);
+
+	/************************************************************/
+	egg_test_title (test, "get exactarch");
+	ret = zif_config_get_boolean (config, "exactarch", NULL);
+	egg_test_assert (test, ret);
+
+	/************************************************************/
+	egg_test_title (test, "set local cachedir");
+	ret = zif_config_set_local (config, "cachedir", "/tmp/cache", NULL);
+	egg_test_assert (test, ret);
+
+	/************************************************************/
+	egg_test_title (test, "set local cachedir (again, should fail)");
+	ret = zif_config_set_local (config, "cachedir", "/tmp/cache", NULL);
+	egg_test_assert (test, !ret);
+
+	/************************************************************/
+	egg_test_title (test, "get cachedir");
+	value = zif_config_get_string (config, "cachedir", NULL);
+	if (egg_strequal (value, "/tmp/cache"))
+		egg_test_success (test, NULL);
+	else
+		egg_test_failed (test, "invalid value '%s'", value);
+	g_free (value);
+
+	/************************************************************/
+	egg_test_title (test, "reset back to defaults");
+	ret = zif_config_reset_default (config, NULL);
+	egg_test_assert (test, ret);
+
+	/************************************************************/
+	egg_test_title (test, "get cachedir");
+	value = zif_config_get_string (config, "cachedir", NULL);
+	if (egg_strequal (value, "../test/cache"))
+		egg_test_success (test, NULL);
+	else
+		egg_test_failed (test, "invalid value '%s'", value);
+	g_free (value);
+
+	/************************************************************/
+	egg_test_title (test, "do substitutions (none)");
+	value = zif_config_expand_substitutions (config, "http://fedora/4/6/moo.rpm", NULL);
+	if (egg_strequal (value, "http://fedora/4/6/moo.rpm"))
+		egg_test_success (test, NULL);
+	else
+		egg_test_failed (test, "invalid value '%s'", value);
+	g_free (value);
+
+	/************************************************************/
+	egg_test_title (test, "do substitutions (both)");
+	value = zif_config_expand_substitutions (config, "http://fedora/$releasever/$basearch/moo.rpm", NULL);
+	if (egg_strequal (value, "http://fedora/11/i386/moo.rpm"))
+		egg_test_success (test, NULL);
+	else
+		egg_test_failed (test, "invalid value '%s'", value);
+	g_free (value);
+
+	/************************************************************/
+	egg_test_title (test, "get basearch array size");
+	array = zif_config_get_basearch_array (config);
+	len = g_strv_length (array);
+	if (len == 5)
+		egg_test_success (test, NULL);
+	else
+		egg_test_failed (test, "invalid size '%i'", len);
+
+	/************************************************************/
+	egg_test_title (test, "get basearch array value");
+	if (egg_strequal (array[0], "i386"))
+		egg_test_success (test, NULL);
+	else
+		egg_test_failed (test, "invalid value '%s'", array[0]);
+
+	/************************************************************/
+	egg_test_title (test, "convert time (invalid)");
+	time = zif_config_string_to_time ("");
+	egg_test_assert (test, (time == 0));
+
+	/************************************************************/
+	egg_test_title (test, "convert time (no suffix)");
+	time = zif_config_string_to_time ("10");
+	egg_test_assert (test, (time == 0));
+
+	/************************************************************/
+	egg_test_title (test, "convert time (invalid suffix)");
+	time = zif_config_string_to_time ("10f");
+	egg_test_assert (test, (time == 0));
+
+	/************************************************************/
+	egg_test_title (test, "convert time (mixture)");
+	time = zif_config_string_to_time ("10d10s");
+	egg_test_assert (test, (time == 0));
+
+	/************************************************************/
+	egg_test_title (test, "convert time (seconds)");
+	time = zif_config_string_to_time ("10s");
+	egg_test_assert (test, (time == 10));
+
+	/************************************************************/
+	egg_test_title (test, "convert time (minutes)");
+	time = zif_config_string_to_time ("10m");
+	egg_test_assert (test, (time == 600));
+
+	/************************************************************/
+	egg_test_title (test, "convert time (hours)");
+	time = zif_config_string_to_time ("10h");
+	egg_test_assert (test, (time == 36000));
+
+	/************************************************************/
+	egg_test_title (test, "convert time (days)");
+	time = zif_config_string_to_time ("10d");
+	egg_test_assert (test, (time == 864000));
+
+	g_object_unref (config);
+
+	egg_test_end (test);
+}
+#endif
+
diff --git a/backends/yum/libzif/zif-config.h b/backends/yum/libzif/zif-config.h
new file mode 100644
index 0000000..14c45cd
--- /dev/null
+++ b/backends/yum/libzif/zif-config.h
@@ -0,0 +1,85 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2008 Richard Hughes <richard at hughsie.com>
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#if !defined (__ZIF_H_INSIDE__) && !defined (ZIF_COMPILATION)
+#error "Only <zif.h> can be included directly."
+#endif
+
+#ifndef __ZIF_CONFIG_H
+#define __ZIF_CONFIG_H
+
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+#define ZIF_TYPE_CONFIG		(zif_config_get_type ())
+#define ZIF_CONFIG(o)		(G_TYPE_CHECK_INSTANCE_CAST ((o), ZIF_TYPE_CONFIG, ZifConfig))
+#define ZIF_CONFIG_CLASS(k)	(G_TYPE_CHECK_CLASS_CAST((k), ZIF_TYPE_CONFIG, ZifConfigClass))
+#define ZIF_IS_CONFIG(o)	(G_TYPE_CHECK_INSTANCE_TYPE ((o), ZIF_TYPE_CONFIG))
+#define ZIF_IS_CONFIG_CLASS(k)	(G_TYPE_CHECK_CLASS_TYPE ((k), ZIF_TYPE_CONFIG))
+#define ZIF_CONFIG_GET_CLASS(o)	(G_TYPE_INSTANCE_GET_CLASS ((o), ZIF_TYPE_CONFIG, ZifConfigClass))
+
+typedef struct _ZifConfig		ZifConfig;
+typedef struct _ZifConfigPrivate	ZifConfigPrivate;
+typedef struct _ZifConfigClass		ZifConfigClass;
+
+struct _ZifConfig
+{
+	GObject			 parent;
+	ZifConfigPrivate	*priv;
+};
+
+struct _ZifConfigClass
+{
+	GObjectClass		 parent_class;
+};
+
+GType		 zif_config_get_type		(void);
+ZifConfig	*zif_config_new			(void);
+gboolean	 zif_config_set_filename	(ZifConfig	*config,
+						 const gchar	*filename,
+						 GError		**error);
+gchar		*zif_config_get_string		(ZifConfig	*config,
+						 const gchar	*key,
+						 GError		**error);
+gboolean	 zif_config_get_boolean		(ZifConfig	*config,
+						 const gchar	*key,
+						 GError		**error);
+guint		 zif_config_get_uint		(ZifConfig	*config,
+						 const gchar	*key,
+						 GError		**error);
+guint		 zif_config_get_time		(ZifConfig	*config,
+						 const gchar	*key,
+						 GError		**error);
+gboolean	 zif_config_set_local		(ZifConfig	*config,
+						 const gchar	*key,
+						 const gchar	*value,
+						 GError		**error);
+gboolean	 zif_config_reset_default	(ZifConfig	*config,
+						 GError		**error);
+gchar		*zif_config_expand_substitutions (ZifConfig	*config,
+						 const gchar	*text,
+						 GError		**error);
+gchar		**zif_config_get_basearch_array	(ZifConfig	*config);
+
+G_END_DECLS
+
+#endif /* __ZIF_CONFIG_H */
diff --git a/backends/yum/libzif/zif-depend.c b/backends/yum/libzif/zif-depend.c
new file mode 100644
index 0000000..cfde807
--- /dev/null
+++ b/backends/yum/libzif/zif-depend.c
@@ -0,0 +1,163 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2009 Richard Hughes <richard at hughsie.com>
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#  include <config.h>
+#endif
+
+#include <glib.h>
+
+#include "egg-debug.h"
+
+#include "zif-utils.h"
+#include "zif-depend.h"
+
+/**
+ * zif_depend_flag_to_string:
+ **/
+const gchar *
+zif_depend_flag_to_string (ZifDependFlag flag)
+{
+	if (flag == ZIF_DEPEND_FLAG_ANY)
+		return "~";
+	if (flag == ZIF_DEPEND_FLAG_LESS)
+		return "<";
+	if (flag == ZIF_DEPEND_FLAG_GREATER)
+		return ">";
+	if (flag == ZIF_DEPEND_FLAG_EQUAL)
+		return "=";
+	return "unknown";
+}
+
+/**
+ * zif_depend_new:
+ **/
+ZifDepend *
+zif_depend_new (const gchar *name, ZifDependFlag flag, const gchar *version)
+{
+	ZifDepend *depend;
+	depend = g_new0 (ZifDepend, 1);
+	depend->count = 1;
+	depend->name = g_strdup (name);
+	depend->flag = flag;
+	depend->version = g_strdup (version);
+	return depend;
+}
+
+/**
+ * zif_depend_new_value:
+ **/
+ZifDepend *
+zif_depend_new_value (gchar *name, ZifDependFlag flag, gchar *version)
+{
+	ZifDepend *depend;
+	depend = g_new0 (ZifDepend, 1);
+	depend->count = 1;
+	depend->name = name;
+	depend->flag = flag;
+	depend->version = version;
+	return depend;
+}
+
+/**
+ * zif_depend_ref:
+ **/
+ZifDepend *
+zif_depend_ref (ZifDepend *depend)
+{
+	g_return_val_if_fail (depend != NULL, NULL);
+	depend->count++;
+	return depend;
+}
+
+/**
+ * zif_depend_unref:
+ **/
+ZifDepend *
+zif_depend_unref (ZifDepend *depend)
+{
+	if (depend == NULL)
+		zif_debug_crash ();
+
+	g_return_val_if_fail (depend != NULL, NULL);
+	depend->count--;
+	if (depend->count == 0) {
+		g_free (depend->name);
+		g_free (depend->version);
+		g_free (depend);
+		depend = NULL;
+	}
+	return depend;
+}
+
+/**
+ * zif_depend_to_string:
+ **/
+gchar *
+zif_depend_to_string (const ZifDepend *depend)
+{
+	g_return_val_if_fail (depend != NULL, NULL);
+	if (depend->version == NULL)
+		return g_strdup (depend->name);
+	return g_strdup_printf ("%s %s %s", depend->name, zif_depend_flag_to_string (depend->flag), depend->version);
+}
+
+/***************************************************************************
+ ***                          MAKE CHECK TESTS                           ***
+ ***************************************************************************/
+#ifdef EGG_TEST
+#include "egg-test.h"
+
+void
+zif_depend_test (EggTest *test)
+{
+	ZifDepend *depend;
+
+	if (!egg_test_start (test, "ZifDepend"))
+		return;
+
+	/************************************************************/
+	egg_test_title (test, "create");
+	depend = zif_depend_new ("kernel", ZIF_DEPEND_FLAG_GREATER, "2.6.0");
+	if (g_strcmp0 (depend->name, "kernel") == 0 && depend->count == 1)
+		egg_test_success (test, NULL);
+	else
+		egg_test_failed (test, "incorrect value %s:%i", depend->name, depend->count);
+
+	/************************************************************/
+	egg_test_title (test, "ref");
+	zif_depend_ref (depend);
+	egg_test_assert (test, depend->count == 2);
+
+	/************************************************************/
+	egg_test_title (test, "unref");
+	zif_depend_unref (depend);
+	egg_test_assert (test, depend->count == 1);
+
+	/************************************************************/
+	egg_test_title (test, "unref");
+	depend = zif_depend_unref (depend);
+	egg_test_assert (test, depend == NULL);
+
+	egg_test_end (test);
+}
+#endif
+
diff --git a/backends/yum/libzif/zif-depend.h b/backends/yum/libzif/zif-depend.h
new file mode 100644
index 0000000..2226bf1
--- /dev/null
+++ b/backends/yum/libzif/zif-depend.h
@@ -0,0 +1,62 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2009 Richard Hughes <richard at hughsie.com>
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#if !defined (__ZIF_H_INSIDE__) && !defined (ZIF_COMPILATION)
+#error "Only <zif.h> can be included directly."
+#endif
+
+#ifndef __ZIF_DEPEND_H
+#define __ZIF_DEPEND_H
+
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+typedef enum {
+	ZIF_DEPEND_FLAG_ANY,
+	ZIF_DEPEND_FLAG_LESS,
+	ZIF_DEPEND_FLAG_GREATER,
+	ZIF_DEPEND_FLAG_EQUAL,
+	ZIF_DEPEND_FLAG_UNKNOWN
+} ZifDependFlag;
+
+typedef struct {
+	gchar		*name;
+	ZifDependFlag	 flag;
+	gchar		*version;
+	guint		 count;
+} ZifDepend;
+
+ZifDepend	*zif_depend_new			(const gchar		*name,
+						 ZifDependFlag		 flag,
+						 const gchar		*version);
+ZifDepend	*zif_depend_new_value		(gchar			*name,
+						 ZifDependFlag		 flag,
+						 gchar			*version);
+ZifDepend	*zif_depend_ref			(ZifDepend		*depend);
+ZifDepend	*zif_depend_unref		(ZifDepend		*depend);
+gchar		*zif_depend_to_string		(const ZifDepend	*depend);
+const gchar	*zif_depend_flag_to_string	(ZifDependFlag		 flag);
+
+G_END_DECLS
+
+#endif /* __ZIF_DEPEND_H */
+
diff --git a/backends/yum/libzif/zif-download.c b/backends/yum/libzif/zif-download.c
new file mode 100644
index 0000000..7113a37
--- /dev/null
+++ b/backends/yum/libzif/zif-download.c
@@ -0,0 +1,397 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2009 Richard Hughes <richard at hughsie.com>
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+/**
+ * SECTION:zif-download
+ * @short_description: Generic object to download packages.
+ *
+ * This object is a trivial wrapper around libsoup.
+ */
+
+#ifdef HAVE_CONFIG_H
+#  include <config.h>
+#endif
+
+#include <glib.h>
+#include <libsoup/soup.h>
+
+#include "zif-config.h"
+#include "zif-download.h"
+#include "zif-completion.h"
+
+#include "egg-debug.h"
+
+#define ZIF_DOWNLOAD_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), ZIF_TYPE_DOWNLOAD, ZifDownloadPrivate))
+
+/**
+ * ZifDownloadPrivate:
+ *
+ * Private #ZifDownload data
+ **/
+struct _ZifDownloadPrivate
+{
+	gchar			*proxy;
+	SoupSession		*session;
+	SoupMessage		*msg;
+	ZifCompletion		*completion;
+	ZifConfig		*config;
+};
+
+static gpointer zif_download_object = NULL;
+
+G_DEFINE_TYPE (ZifDownload, zif_download, G_TYPE_OBJECT)
+
+/**
+ * zif_download_file_got_chunk_cb:
+ **/
+static void
+zif_download_file_got_chunk_cb (SoupMessage *msg, SoupBuffer *chunk, ZifDownload *download)
+{
+	guint percentage;
+	guint header_size;
+	guint body_length;
+
+	/* get data */
+	body_length = (guint) msg->response_body->length;
+	header_size = soup_message_headers_get_content_length (msg->response_headers);
+
+	/* how can this happen */
+	if (header_size < body_length) {
+		egg_warning ("length=%i/%i", body_length, header_size);
+		goto out;
+	}
+
+	/* calulate percentage */
+	percentage = (100 * body_length) / header_size;
+	if (percentage == 100) {
+		egg_warning ("ignoring percentage: %i", percentage);
+		goto out;
+	}
+
+	egg_debug ("DOWNLOAD: %i%% (%i, %i) - %p, %p", percentage, body_length, header_size, msg, download);
+	zif_completion_set_percentage (download->priv->completion, percentage);
+
+out:
+	return;
+}
+
+/**
+ * zif_download_file_finished_cb:
+ **/
+static void
+zif_download_file_finished_cb (SoupMessage *msg, ZifDownload *download)
+{
+	egg_debug ("done!");
+	g_object_unref (download->priv->msg);
+	download->priv->msg = NULL;
+}
+
+/**
+ * zif_download_cancel:
+ **/
+gboolean
+zif_download_cancel (ZifDownload *download, GError **error)
+{
+	gboolean ret = FALSE;
+
+	g_return_val_if_fail (ZIF_IS_DOWNLOAD (download), FALSE);
+
+	if (download->priv->msg == NULL) {
+		if (error != NULL)
+			*error = g_error_new (1, 0, "no download in progress");
+		goto out;
+	}
+
+	/* cancel */
+	soup_session_cancel_message (download->priv->session, download->priv->msg, SOUP_STATUS_CANCELLED);
+	ret = TRUE;
+out:
+	return ret;
+}
+
+/**
+ * zif_download_file:
+ * @download: the #ZifDownload object
+ * @uri: the full remote URI
+ * @filename: the local filename to save to
+ * @cancellable: a #GCancellable which is used to cancel tasks, or %NULL
+ * @completion: a #ZifCompletion to use for progress reporting
+ * @error: a #GError which is used on failure, or %NULL
+ *
+ * Downloads a file.
+ *
+ * Return value: %TRUE for success, %FALSE for failure
+ **/
+gboolean
+zif_download_file (ZifDownload *download, const gchar *uri, const gchar *filename, GCancellable *cancellable, ZifCompletion *completion, GError **error)
+{
+	gboolean ret = FALSE;
+	SoupURI *base_uri;
+	SoupMessage *msg = NULL;
+	GError *error_local = NULL;
+
+	g_return_val_if_fail (ZIF_IS_DOWNLOAD (download), FALSE);
+	g_return_val_if_fail (uri != NULL, FALSE);
+	g_return_val_if_fail (filename != NULL, FALSE);
+	g_return_val_if_fail (download->priv->msg == NULL, FALSE);
+	g_return_val_if_fail (download->priv->session != NULL, FALSE);
+
+	/* save an instance of the completion object */
+	download->priv->completion = g_object_ref (completion);
+
+	base_uri = soup_uri_new (uri);
+	if (base_uri == NULL) {
+		if (error != NULL)
+			*error = g_error_new (1, 0, "could not parse uri: %s", uri);
+		goto out;
+	}
+
+	/* GET package */
+	msg = soup_message_new_from_uri (SOUP_METHOD_GET, base_uri);
+	if (msg == NULL) {
+		if (error != NULL)
+			*error = g_error_new (1, 0, "could not setup message");
+		goto out;
+	}
+
+	/* we want progress updates */
+	g_signal_connect (msg, "got-chunk", G_CALLBACK (zif_download_file_got_chunk_cb), download);
+	g_signal_connect (msg, "finished", G_CALLBACK (zif_download_file_finished_cb), download);
+
+	/* we need this for cancelling */
+	download->priv->msg = g_object_ref (msg);
+
+	/* request */
+//	soup_message_set_flags (msg, SOUP_MESSAGE_NO_REDIRECT);
+
+	/* send sync */
+	soup_session_send_message (download->priv->session, msg);
+
+	/* find length */
+	if (!SOUP_STATUS_IS_SUCCESSFUL (msg->status_code)) {
+		if (error != NULL)
+			*error = g_error_new (1, 0, "failed to get valid response for %s: %s", uri, soup_status_get_phrase (msg->status_code));
+		goto out;
+	}
+
+	/* write file */
+	ret = g_file_set_contents (filename, msg->response_body->data, msg->response_body->length, &error_local);
+	if (!ret) {
+		if (error != NULL)
+			*error = g_error_new (1, 0, "failed to write file: %s",  error_local->message);
+		g_error_free (error_local);
+		goto out;
+	}
+out:
+	g_object_unref (download->priv->completion);
+	download->priv->completion = NULL;
+	if (base_uri != NULL)
+		soup_uri_free (base_uri);
+	if (msg != NULL)
+		g_object_unref (msg);
+	return ret;
+}
+
+/**
+ * zif_download_set_proxy:
+ **/
+gboolean
+zif_download_set_proxy (ZifDownload *download, const gchar *http_proxy, GError **error)
+{
+	gboolean ret = FALSE;
+	SoupURI *proxy = NULL;
+	guint connection_timeout;
+
+	g_return_val_if_fail (ZIF_IS_DOWNLOAD (download), FALSE);
+
+	/* get default value from the config file */
+	connection_timeout = zif_config_get_uint (download->priv->config, "connection_timeout", NULL);
+	if (connection_timeout == G_MAXUINT)
+		connection_timeout = 5;
+
+	/* setup the session */
+	download->priv->session = soup_session_async_new_with_options (SOUP_SESSION_PROXY_URI, proxy,
+								       SOUP_SESSION_USER_AGENT, "zif",
+								       SOUP_SESSION_TIMEOUT, connection_timeout,
+								       NULL);
+	if (download->priv->session == NULL) {
+		if (error != NULL)
+			*error = g_error_new (1, 0, "could not setup session");
+		goto out;
+	}
+	ret = TRUE;
+out:
+	return ret;
+}
+
+/**
+ * zif_download_finalize:
+ **/
+static void
+zif_download_finalize (GObject *object)
+{
+	ZifDownload *download;
+
+	g_return_if_fail (object != NULL);
+	g_return_if_fail (ZIF_IS_DOWNLOAD (object));
+	download = ZIF_DOWNLOAD (object);
+
+	g_free (download->priv->proxy);
+	if (download->priv->msg != NULL)
+		g_object_unref (download->priv->msg);
+	if (download->priv->session != NULL)
+		g_object_unref (download->priv->session);
+	g_object_unref (download->priv->config);
+
+	G_OBJECT_CLASS (zif_download_parent_class)->finalize (object);
+}
+
+/**
+ * zif_download_class_init:
+ **/
+static void
+zif_download_class_init (ZifDownloadClass *klass)
+{
+	GObjectClass *object_class = G_OBJECT_CLASS (klass);
+	object_class->finalize = zif_download_finalize;
+
+	g_type_class_add_private (klass, sizeof (ZifDownloadPrivate));
+}
+
+/**
+ * zif_download_init:
+ **/
+static void
+zif_download_init (ZifDownload *download)
+{
+	download->priv = ZIF_DOWNLOAD_GET_PRIVATE (download);
+	download->priv->msg = NULL;
+	download->priv->session = NULL;
+	download->priv->proxy = NULL;
+	download->priv->completion = NULL;
+	download->priv->config = zif_config_new ();
+}
+
+/**
+ * zif_download_new:
+ *
+ * Return value: A new download class instance.
+ **/
+ZifDownload *
+zif_download_new (void)
+{
+	if (zif_download_object != NULL) {
+		g_object_ref (zif_download_object);
+	} else {
+		zif_download_object = g_object_new (ZIF_TYPE_DOWNLOAD, NULL);
+		g_object_add_weak_pointer (zif_download_object, &zif_download_object);
+	}
+	return ZIF_DOWNLOAD (zif_download_object);
+}
+
+/***************************************************************************
+ ***                          MAKE CHECK TESTS                           ***
+ ***************************************************************************/
+#ifdef EGG_TEST
+#include "egg-test.h"
+
+static guint _updates = 0;
+
+static void
+zif_download_progress_changed (ZifDownload *download, guint value, gpointer data)
+{
+	_updates++;
+}
+
+static gboolean
+zif_download_cancel_cb (ZifDownload *download)
+{
+	gboolean ret;
+	GError *error = NULL;
+	ret = zif_download_cancel (download, &error);
+	if (!ret)
+		egg_error ("failed to cancel '%s'", error->message);
+	return FALSE;
+}
+
+void
+zif_download_test (EggTest *test)
+{
+	ZifDownload *download;
+	ZifCompletion *completion;
+	gboolean ret;
+	GError *error = NULL;
+
+	if (!egg_test_start (test, "ZifDownload"))
+		return;
+
+	/************************************************************/
+	egg_test_title (test, "get download");
+	download = zif_download_new ();
+	egg_test_assert (test, download != NULL);
+
+	completion = zif_completion_new ();
+	g_signal_connect (completion, "percentage-changed", G_CALLBACK (zif_download_progress_changed), NULL);
+
+	/************************************************************/
+	egg_test_title (test, "set proxy");
+	ret = zif_download_set_proxy (download, NULL, NULL);
+	egg_test_assert (test, ret);
+
+	/************************************************************/
+	egg_test_title (test, "cancel not yet started download");
+	ret = zif_download_cancel (download, NULL);
+	egg_test_assert (test, !ret);
+
+	/************************************************************/
+	egg_test_title (test, "download file");
+	ret = zif_download_file (download, "http://people.freedesktop.org/~hughsient/temp/Screenshot.png", "../test/downloads", NULL, completion, &error);
+	if (ret)
+		egg_test_success (test, NULL);
+	else
+		egg_test_failed (test, "failed to load '%s'", error->message);
+
+	/************************************************************/
+	egg_test_title (test, "enough updates");
+	if (_updates > 5)
+		egg_test_success (test, "got %i updates", _updates);
+	else
+		egg_test_failed (test, "got %i updates", _updates);
+
+	/* setup cancel */
+	g_timeout_add (50, (GSourceFunc) zif_download_cancel_cb, download);
+
+	/************************************************************/
+	egg_test_title (test, "download second file (should be cancelled)");
+	zif_completion_reset (completion);
+	ret = zif_download_file (download, "http://people.freedesktop.org/~hughsient/temp/Screenshot.png", "../test/downloads", NULL, completion, &error);
+	if (!ret)
+		egg_test_success (test, NULL);
+	else
+		egg_test_failed (test, "failed to load '%s'", error->message);
+
+	g_object_unref (download);
+	g_object_unref (completion);
+
+	egg_test_end (test);
+}
+#endif
+
diff --git a/backends/yum/libzif/zif-download.h b/backends/yum/libzif/zif-download.h
new file mode 100644
index 0000000..191496c
--- /dev/null
+++ b/backends/yum/libzif/zif-download.h
@@ -0,0 +1,73 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2009 Richard Hughes <richard at hughsie.com>
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#if !defined (__ZIF_H_INSIDE__) && !defined (ZIF_COMPILATION)
+#error "Only <zif.h> can be included directly."
+#endif
+
+#ifndef __ZIF_DOWNLOAD_H
+#define __ZIF_DOWNLOAD_H
+
+#include <glib-object.h>
+#include "zif-completion.h"
+
+G_BEGIN_DECLS
+
+#define ZIF_TYPE_DOWNLOAD		(zif_download_get_type ())
+#define ZIF_DOWNLOAD(o)			(G_TYPE_CHECK_INSTANCE_CAST ((o), ZIF_TYPE_DOWNLOAD, ZifDownload))
+#define ZIF_DOWNLOAD_CLASS(k)		(G_TYPE_CHECK_CLASS_CAST((k), ZIF_TYPE_DOWNLOAD, ZifDownloadClass))
+#define ZIF_IS_DOWNLOAD(o)		(G_TYPE_CHECK_INSTANCE_TYPE ((o), ZIF_TYPE_DOWNLOAD))
+#define ZIF_IS_DOWNLOAD_CLASS(k)	(G_TYPE_CHECK_CLASS_TYPE ((k), ZIF_TYPE_DOWNLOAD))
+#define ZIF_DOWNLOAD_GET_CLASS(o)	(G_TYPE_INSTANCE_GET_CLASS ((o), ZIF_TYPE_DOWNLOAD, ZifDownloadClass))
+
+typedef struct _ZifDownload		ZifDownload;
+typedef struct _ZifDownloadPrivate	ZifDownloadPrivate;
+typedef struct _ZifDownloadClass	ZifDownloadClass;
+
+struct _ZifDownload
+{
+	GObject				 parent;
+	ZifDownloadPrivate	*priv;
+};
+
+struct _ZifDownloadClass
+{
+	GObjectClass	parent_class;
+};
+
+GType		 zif_download_get_type			(void);
+ZifDownload	*zif_download_new			(void);
+gboolean	 zif_download_set_proxy			(ZifDownload		*download,
+							 const gchar		*http_proxy,
+							 GError			**error);
+gboolean	 zif_download_file			(ZifDownload		*download,
+							 const gchar		*uri,
+							 const gchar		*filename,
+							 GCancellable		*cancellable,
+							 ZifCompletion		*completion,
+							 GError			**error);
+gboolean	 zif_download_cancel			(ZifDownload		*download,
+							 GError			**error);
+
+G_END_DECLS
+
+#endif /* __ZIF_DOWNLOAD_H */
+
diff --git a/backends/yum/libzif/zif-groups.c b/backends/yum/libzif/zif-groups.c
new file mode 100644
index 0000000..c0f444b
--- /dev/null
+++ b/backends/yum/libzif/zif-groups.c
@@ -0,0 +1,440 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2008 Richard Hughes <richard at hughsie.com>
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+/**
+ * SECTION:zif-groups
+ * @short_description: A #ZifGroups class handles category to group mapping
+ *
+ * In Zif, we have a few groups that are enumerated, and categories that are
+ * not enumerated and are custom to the vendor. The mapping from categories
+ * to groups (and vice versa) is done with a mapping file which has to be
+ * set using zif_groups_set_mapping_file() before any queries are done.
+ */
+
+#include <string.h>
+
+#include <glib.h>
+
+#include "zif-groups.h"
+#include "zif-monitor.h"
+
+#include "egg-debug.h"
+#include "egg-string.h"
+
+#define ZIF_GROUPS_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), ZIF_TYPE_GROUPS, ZifGroupsPrivate))
+
+/**
+ * ZifGroupsPrivate:
+ *
+ * Private #ZifGroups data
+ **/
+struct _ZifGroupsPrivate
+{
+	gboolean		 loaded;
+	PkBitfield		 groups;
+	GPtrArray		*categories;
+	GHashTable		*hash;
+	gchar			*mapping_file;
+	ZifMonitor		*monitor;
+};
+
+G_DEFINE_TYPE (ZifGroups, zif_groups, G_TYPE_OBJECT)
+static gpointer zif_groups_object = NULL;
+
+/**
+ * zif_groups_set_mapping_file:
+ * @groups: the #ZifGroups object
+ * @mapping_file: mapping file from categories to groups
+ * @error: a #GError which is used on failure, or %NULL
+ *
+ * This sets up the file that is used to map categories to group enums.
+ *
+ * Return value: %TRUE for success, %FALSE for failure
+ **/
+gboolean
+zif_groups_set_mapping_file (ZifGroups *groups, const gchar *mapping_file, GError **error)
+{
+	gboolean ret;
+	GError *error_local = NULL;
+
+	g_return_val_if_fail (ZIF_IS_GROUPS (groups), FALSE);
+	g_return_val_if_fail (groups->priv->mapping_file == NULL, FALSE);
+	g_return_val_if_fail (!groups->priv->loaded, FALSE);
+	g_return_val_if_fail (mapping_file != NULL, FALSE);
+
+	/* check file exists */
+	ret = g_file_test (mapping_file, G_FILE_TEST_IS_REGULAR);
+	if (!ret) {
+		if (error != NULL)
+			*error = g_error_new (1, 0, "mapping file %s does not exist", mapping_file);
+		goto out;
+	}
+
+	/* setup watch */
+	ret = zif_monitor_add_watch (groups->priv->monitor, mapping_file, &error_local);
+	if (!ret) {
+		if (error != NULL)
+			*error = g_error_new (1, 0, "failed to setup watch: %s", error_local->message);
+		g_error_free (error_local);
+		goto out;
+	}
+
+	groups->priv->mapping_file = g_strdup (mapping_file);
+out:
+	return ret;
+}
+
+/**
+ * zif_groups_load:
+ * @groups: the #ZifGroups object
+ * @error: a #GError which is used on failure, or %NULL
+ *
+ * Loads the mapping file from disk into memory.
+ *
+ * Return value: %TRUE for success, %FALSE for failure
+ **/
+gboolean
+zif_groups_load (ZifGroups *groups, GError **error)
+{
+	gboolean ret = TRUE;
+	gchar *data = NULL;
+	gchar **lines = NULL;
+	gchar **cols;
+	gchar **entries;
+	guint i, j;
+	PkGroupEnum group;
+	GError *error_local = NULL;
+
+	g_return_val_if_fail (ZIF_IS_GROUPS (groups), FALSE);
+	g_return_val_if_fail (groups->priv->categories->len == 0, FALSE);
+
+	/* already loaded */
+	if (groups->priv->loaded)
+		goto out;
+
+	/* no mapping file */
+	if (groups->priv->mapping_file == NULL) {
+		egg_warning ("no mapping file, so cannot load group lists");
+		goto out;
+	}
+
+	/* get data */
+	ret = g_file_get_contents (groups->priv->mapping_file, &data, NULL, &error_local);
+	if (!ret) {
+		if (error != NULL)
+			*error = g_error_new (1, 0, "failed to get groups data: %s", error_local->message);
+		g_error_free (error_local);
+		goto out;
+	}
+
+	/* process each line */
+	lines = g_strsplit (data, "\n", 0);
+	for (i=0; lines[i] != NULL; i++) {
+		cols = g_strsplit (lines[i], "=", -1);
+		if (g_strv_length (cols) != 2)
+			goto cont;
+
+		/* add to groups list */
+		group = pk_group_enum_from_text (cols[0]);
+		pk_bitfield_add (groups->priv->groups, group);
+
+		/* add entries to cats list and dist */
+		entries = g_strsplit (cols[1], ",", -1);
+		for (j=0; entries[j] != NULL; j++) {
+			g_ptr_array_add (groups->priv->categories, g_strdup (entries[j]));
+			g_hash_table_insert (groups->priv->hash, g_strdup (entries[j]), GUINT_TO_POINTER(group));
+		}
+		g_strfreev (entries);
+cont:
+		g_strfreev (cols);
+	}
+
+	groups->priv->loaded = TRUE;
+
+out:
+	g_free (data);
+	g_strfreev (lines);
+	return ret;
+}
+
+/**
+ * zif_groups_get_groups:
+ * @groups: the #ZifGroups object
+ * @error: a #GError which is used on failure, or %NULL
+ *
+ * Gets the groups supported by the packaging system.
+ *
+ * Return value: A #PkBitfield of the groups that are supported
+ **/
+PkBitfield
+zif_groups_get_groups (ZifGroups *groups, GError **error)
+{
+	GError *error_local;
+	gboolean ret;
+
+	g_return_val_if_fail (ZIF_IS_GROUPS (groups), 0);
+
+	/* if not already loaded, load */
+	if (!groups->priv->loaded) {
+		ret = zif_groups_load (groups, &error_local);
+		if (!ret) {
+			if (error != NULL)
+				*error = g_error_new (1, 0, "failed to load config file: %s", error_local->message);
+			g_error_free (error_local);
+			goto out;
+		}
+	}
+out:
+	return groups->priv->groups;
+}
+
+/**
+ * zif_groups_get_categories:
+ * @groups: the #ZifGroups object
+ * @error: a #GError which is used on failure, or %NULL
+ *
+ * Gets the categories supported by the packaging system.
+ *
+ * Return value: category list as an array of strings
+ **/
+GPtrArray *
+zif_groups_get_categories (ZifGroups *groups, GError **error)
+{
+	guint i;
+	GPtrArray *array = NULL;
+	GError *error_local;
+	gboolean ret;
+
+	g_return_val_if_fail (ZIF_IS_GROUPS (groups), NULL);
+
+	/* if not already loaded, load */
+	if (!groups->priv->loaded) {
+		ret = zif_groups_load (groups, &error_local);
+		if (!ret) {
+			if (error != NULL)
+				*error = g_error_new (1, 0, "failed to load config file: %s", error_local->message);
+			g_error_free (error_local);
+			goto out;
+		}
+	}
+
+	array = g_ptr_array_new_with_free_func ((GDestroyNotify) g_free);
+	for (i=0; i<groups->priv->categories->len; i++)
+		g_ptr_array_add (array, g_strdup (g_ptr_array_index (groups->priv->categories, i)));
+out:
+	return array;
+}
+
+/**
+ * zif_groups_get_group_for_cat:
+ * @groups: the #ZifGroups object
+ * @cat: the category name, e.g. "games/action"
+ * @error: a #GError which is used on failure, or %NULL
+ *
+ * Returns the group enumerated type for the category.
+ *
+ * Return value: the specific #PkGroupEnum or %PK_GROUP_ENUM_UNKNOWN
+ **/
+PkGroupEnum
+zif_groups_get_group_for_cat (ZifGroups *groups, const gchar *cat, GError **error)
+{
+	gpointer data;
+	PkGroupEnum group = PK_GROUP_ENUM_UNKNOWN;
+	GError *error_local;
+	gboolean ret;
+
+	g_return_val_if_fail (ZIF_IS_GROUPS (groups), PK_GROUP_ENUM_UNKNOWN);
+	g_return_val_if_fail (cat != NULL, PK_GROUP_ENUM_UNKNOWN);
+
+	/* if not already loaded, load */
+	if (!groups->priv->loaded) {
+		ret = zif_groups_load (groups, &error_local);
+		if (!ret) {
+			if (error != NULL)
+				*error = g_error_new (1, 0, "failed to load config file: %s", error_local->message);
+			g_error_free (error_local);
+			goto out;
+		}
+	}
+
+	/* get cat -> group mapping */
+	data = g_hash_table_lookup (groups->priv->hash, cat);
+	if (data == NULL)
+		goto out;
+
+	group = GPOINTER_TO_INT(data);
+out:
+	return group;
+}
+
+/**
+ * zif_groups_file_monitor_cb:
+ **/
+static void
+zif_groups_file_monitor_cb (ZifMonitor *monitor, ZifGroups *groups)
+{
+	/* free invalid data */
+	groups->priv->loaded = FALSE;
+	g_ptr_array_set_size (groups->priv->categories, 0);
+	g_hash_table_remove_all (groups->priv->hash);
+
+	egg_debug ("mapping file changed");
+}
+
+/**
+ * zif_groups_finalize:
+ **/
+static void
+zif_groups_finalize (GObject *object)
+{
+	ZifGroups *groups;
+	g_return_if_fail (ZIF_IS_GROUPS (object));
+	groups = ZIF_GROUPS (object);
+
+	g_ptr_array_unref (groups->priv->categories);
+	g_hash_table_unref (groups->priv->hash);
+	g_free (groups->priv->mapping_file);
+	g_object_unref (groups->priv->monitor);
+
+	G_OBJECT_CLASS (zif_groups_parent_class)->finalize (object);
+}
+
+/**
+ * zif_groups_class_init:
+ **/
+static void
+zif_groups_class_init (ZifGroupsClass *klass)
+{
+	GObjectClass *object_class = G_OBJECT_CLASS (klass);
+	object_class->finalize = zif_groups_finalize;
+	g_type_class_add_private (klass, sizeof (ZifGroupsPrivate));
+}
+
+/**
+ * zif_groups_init:
+ **/
+static void
+zif_groups_init (ZifGroups *groups)
+{
+	groups->priv = ZIF_GROUPS_GET_PRIVATE (groups);
+	groups->priv->mapping_file = NULL;
+	groups->priv->loaded = FALSE;
+	groups->priv->groups = 0;
+	groups->priv->categories = g_ptr_array_new_with_free_func ((GDestroyNotify) g_free);
+	groups->priv->hash = g_hash_table_new_full (g_str_hash, g_str_equal, (GDestroyNotify) g_free, NULL);
+	groups->priv->monitor = zif_monitor_new ();
+	g_signal_connect (groups->priv->monitor, "changed", G_CALLBACK (zif_groups_file_monitor_cb), groups);
+}
+
+/**
+ * zif_groups_new:
+ *
+ * Return value: A new #ZifGroups class instance.
+ **/
+ZifGroups *
+zif_groups_new (void)
+{
+	if (zif_groups_object != NULL) {
+		g_object_ref (zif_groups_object);
+	} else {
+		zif_groups_object = g_object_new (ZIF_TYPE_GROUPS, NULL);
+		g_object_add_weak_pointer (zif_groups_object, &zif_groups_object);
+	}
+	return ZIF_GROUPS (zif_groups_object);
+}
+
+/***************************************************************************
+ ***                          MAKE CHECK TESTS                           ***
+ ***************************************************************************/
+#ifdef EGG_TEST
+#include "egg-test.h"
+
+void
+zif_groups_test (EggTest *test)
+{
+	ZifGroups *groups;
+	gboolean ret;
+	GPtrArray *array;
+	GError *error = NULL;
+	PkGroupEnum group;
+	PkBitfield groups_bit;
+	gchar *text;
+
+	if (!egg_test_start (test, "ZifGroups"))
+		return;
+
+	/************************************************************/
+	egg_test_title (test, "get groups");
+	groups = zif_groups_new ();
+	egg_test_assert (test, groups != NULL);
+
+	/************************************************************/
+	egg_test_title (test, "set mapping file");
+	ret = zif_groups_set_mapping_file (groups, "../test/share/yum-comps-groups.conf", &error);
+	if (ret)
+		egg_test_success (test, NULL);
+	else
+		egg_test_failed (test, "failed to set file '%s'", error->message);
+
+	/************************************************************/
+	egg_test_title (test, "load");
+	ret = zif_groups_load (groups, &error);
+	if (ret)
+		egg_test_success (test, NULL);
+	else
+		egg_test_failed (test, "failed to load '%s'", error->message);
+
+	/************************************************************/
+	egg_test_title (test, "get groups");
+	groups_bit = zif_groups_get_groups (groups, NULL);
+	text = pk_group_bitfield_to_string (groups_bit);
+	if (egg_strequal (text, "admin-tools;desktop-gnome;desktop-kde;desktop-other;"
+				"education;fonts;games;graphics;internet;"
+				"legacy;localization;multimedia;office;other;programming;"
+				"publishing;servers;system;virtualization"))
+		egg_test_success (test, NULL);
+	else
+		egg_test_failed (test, "invalid groups '%s'", text);
+	g_free (text);
+
+	/************************************************************/
+	egg_test_title (test, "get categories");
+	array = zif_groups_get_categories (groups, NULL);
+	if (array->len > 100)
+		egg_test_success (test, NULL);
+	else
+		egg_test_failed (test, "invalid size '%i'", array->len);
+	g_ptr_array_unref (array);
+
+	/************************************************************/
+	egg_test_title (test, "get group for cat");
+	group = zif_groups_get_group_for_cat (groups, "language-support;kashubian-support", NULL);
+	if (egg_strequal (pk_group_enum_to_text (group), "localization"))
+		egg_test_success (test, NULL);
+	else
+		egg_test_failed (test, "invalid groups '%s'", pk_group_enum_to_text (group));
+
+	g_object_unref (groups);
+
+	egg_test_end (test);
+}
+#endif
+
diff --git a/backends/yum/libzif/zif-groups.h b/backends/yum/libzif/zif-groups.h
new file mode 100644
index 0000000..2b7778f
--- /dev/null
+++ b/backends/yum/libzif/zif-groups.h
@@ -0,0 +1,73 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2008 Richard Hughes <richard at hughsie.com>
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#if !defined (__ZIF_H_INSIDE__) && !defined (ZIF_COMPILATION)
+#error "Only <zif.h> can be included directly."
+#endif
+
+#ifndef __ZIF_GROUPS_H
+#define __ZIF_GROUPS_H
+
+#include <glib-object.h>
+#include <packagekit-glib2/packagekit.h>
+
+G_BEGIN_DECLS
+
+#define ZIF_TYPE_GROUPS		(zif_groups_get_type ())
+#define ZIF_GROUPS(o)		(G_TYPE_CHECK_INSTANCE_CAST ((o), ZIF_TYPE_GROUPS, ZifGroups))
+#define ZIF_GROUPS_CLASS(k)	(G_TYPE_CHECK_CLASS_CAST((k), ZIF_TYPE_GROUPS, ZifGroupsClass))
+#define ZIF_IS_GROUPS(o)	(G_TYPE_CHECK_INSTANCE_TYPE ((o), ZIF_TYPE_GROUPS))
+#define ZIF_IS_GROUPS_CLASS(k)	(G_TYPE_CHECK_CLASS_TYPE ((k), ZIF_TYPE_GROUPS))
+#define ZIF_GROUPS_GET_CLASS(o)	(G_TYPE_INSTANCE_GET_CLASS ((o), ZIF_TYPE_GROUPS, ZifGroupsClass))
+
+typedef struct _ZifGroups		ZifGroups;
+typedef struct _ZifGroupsPrivate	ZifGroupsPrivate;
+typedef struct _ZifGroupsClass		ZifGroupsClass;
+
+struct _ZifGroups
+{
+	GObject			 parent;
+	ZifGroupsPrivate	*priv;
+};
+
+struct _ZifGroupsClass
+{
+	GObjectClass		 parent_class;
+};
+
+GType		 zif_groups_get_type		(void);
+ZifGroups	*zif_groups_new			(void);
+gboolean	 zif_groups_set_mapping_file	(ZifGroups	*groups,
+						 const gchar	*mapping_file,
+						 GError		**error);
+gboolean	 zif_groups_load		(ZifGroups	*groups,
+						 GError		**error);
+PkBitfield	 zif_groups_get_groups		(ZifGroups	*groups,
+						 GError		**error);
+GPtrArray	*zif_groups_get_categories	(ZifGroups	*groups,
+						 GError		**error);
+PkGroupEnum	 zif_groups_get_group_for_cat	(ZifGroups	*groups,
+						 const gchar	*cat,
+						 GError		**error);
+
+G_END_DECLS
+
+#endif /* __ZIF_GROUPS_H */
diff --git a/backends/yum/libzif/zif-lock.c b/backends/yum/libzif/zif-lock.c
new file mode 100644
index 0000000..afc3949
--- /dev/null
+++ b/backends/yum/libzif/zif-lock.c
@@ -0,0 +1,432 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2009 Richard Hughes <richard at hughsie.com>
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+/**
+ * SECTION:zif-lock
+ * @short_description: Generic object to lock the package system.
+ *
+ * This object works with the generic lock file.
+ */
+
+#ifdef HAVE_CONFIG_H
+#  include <config.h>
+#endif
+
+#include <sys/types.h>
+#include <unistd.h>
+#include <glib.h>
+#include <glib/gstdio.h>
+
+#include "zif-lock.h"
+#include "zif-config.h"
+
+#include "egg-debug.h"
+
+#define ZIF_LOCK_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), ZIF_TYPE_LOCK, ZifLockPrivate))
+
+/**
+ * ZifLockPrivate:
+ *
+ * Private #ZifLock data
+ **/
+struct _ZifLockPrivate
+{
+	gchar			*filename;
+	ZifConfig		*config;
+	gboolean		 self_locked;
+};
+
+static gpointer zif_lock_object = NULL;
+
+G_DEFINE_TYPE (ZifLock, zif_lock, G_TYPE_OBJECT)
+
+/**
+ * zif_lock_get_pid:
+ **/
+static guint
+zif_lock_get_pid (ZifLock *lock)
+{
+	gboolean ret;
+	GError *error = NULL;
+	guint64 pid = 0;
+	gchar *contents = NULL;
+	gchar *endptr = NULL;
+
+	g_return_val_if_fail (ZIF_IS_LOCK (lock), FALSE);
+
+	/* file doesn't exists */
+	ret = g_file_test (lock->priv->filename, G_FILE_TEST_EXISTS);
+	if (!ret)
+		goto out;
+
+	/* get contents */
+	ret = g_file_get_contents (lock->priv->filename, &contents, NULL, &error);
+	if (!ret) {
+		egg_warning ("failed to get data: %s", error->message);
+		g_error_free (error);
+		goto out;
+	}
+
+	/* convert to int */
+	pid = g_ascii_strtoull (contents, &endptr, 10);
+
+	/* failed to parse */
+	if (contents == endptr) {
+		egg_warning ("failed to parse pid: %s", contents);
+		pid = 0;
+		goto out;
+	}
+
+	/* too large */
+	if (pid > G_MAXUINT) {
+		egg_warning ("pid too large %" G_GUINT64_FORMAT, pid);
+		pid = 0;
+		goto out;
+	}
+
+out:
+	g_free (contents);
+	return (guint) pid;
+}
+
+/**
+ * zif_lock_is_locked:
+ * @lock: the #ZifLock object
+ * @pid: the PID of the process holding the lock, or %NULL
+ *
+ * Gets the lock state.
+ *
+ * Return value: %TRUE if we are already locked
+ **/
+gboolean
+zif_lock_is_locked (ZifLock *lock, guint *pid)
+{
+	guint pid_tmp;
+	gboolean ret = FALSE;
+	gchar *filename = NULL;
+
+	g_return_val_if_fail (ZIF_IS_LOCK (lock), FALSE);
+
+	/* optimise as we hold the lock */
+	if (lock->priv->self_locked) {
+		ret = TRUE;
+		if (pid != NULL)
+			*pid = getpid ();
+		goto out;
+	}
+
+	/* get pid */
+	pid_tmp = zif_lock_get_pid (lock);
+	if (pid_tmp == 0)
+		goto out;
+
+	/* pid is not still running? */
+	filename = g_strdup_printf ("/proc/%i/cmdline", pid_tmp);
+	ret = g_file_test (filename, G_FILE_TEST_EXISTS);
+	if (!ret)
+		goto out;
+
+	/* return pid */
+	if (pid != NULL)
+		*pid = pid_tmp;
+out:
+	g_free (filename);
+	return ret;
+}
+
+/**
+ * zif_lock_set_locked:
+ * @lock: the #ZifLock object
+ * @pid: the PID of the process holding the lock, or %NULL
+ * @error: a #GError which is used on failure, or %NULL
+ *
+ * Tries to lock the packaging system.
+ *
+ * Return value: %TRUE if we locked, else %FALSE and the error is set
+ **/
+gboolean
+zif_lock_set_locked (ZifLock *lock, guint *pid, GError **error)
+{
+	gboolean ret = FALSE;
+	guint pid_tmp = 0;
+	gchar *pid_text = NULL;
+	GError *error_local = NULL;
+
+	g_return_val_if_fail (ZIF_IS_LOCK (lock), FALSE);
+
+	/* already locked */
+	ret = zif_lock_is_locked (lock, &pid_tmp);
+	if (ret) {
+		if (error != NULL)
+			*error = g_error_new (1, 0, "already locked by %i", pid_tmp);
+		if (pid != NULL)
+			*pid = pid_tmp;
+		ret = FALSE;
+		goto out;
+	}
+
+	/* no lock file set */
+	if (lock->priv->filename == NULL) {
+		if (error != NULL)
+			*error = g_error_new (1, 0, "lock file not set");
+		ret = FALSE;
+		goto out;
+	}
+
+	/* save our pid */
+	pid_tmp = getpid ();
+	pid_text = g_strdup_printf ("%i", pid_tmp);
+	ret = g_file_set_contents (lock->priv->filename, pid_text, -1, &error_local);
+	if (!ret) {
+		if (error != NULL)
+			*error = g_error_new (1, 0, "failed to write: %s", error_local->message);
+		g_error_free (error_local);
+		goto out;
+	}
+
+	/* optimise as we now hold the lock */
+	lock->priv->self_locked = TRUE;
+
+	/* return pid */
+	if (pid != NULL)
+		*pid = pid_tmp;
+out:
+	g_free (pid_text);
+	return ret;
+}
+
+/**
+ * zif_lock_set_unlocked:
+ * @lock: the #ZifLock object
+ * @error: a #GError which is used on failure, or %NULL
+ *
+ * Unlocks the packaging system.
+ *
+ * Return value: %TRUE for success, %FALSE for failure
+ **/
+gboolean
+zif_lock_set_unlocked (ZifLock *lock, GError **error)
+{
+	gboolean ret = FALSE;
+	guint pid = 0;
+	guint pid_tmp;
+	gint retval;
+
+	g_return_val_if_fail (ZIF_IS_LOCK (lock), FALSE);
+
+	/* optimise as we hold the lock */
+	if (lock->priv->self_locked) {
+		lock->priv->self_locked = FALSE;
+		goto skip_checks;
+	}
+
+	/* are we already locked */
+	ret = zif_lock_is_locked (lock, &pid);
+	if (!ret) {
+		if (error != NULL)
+			*error = g_error_new (1, 0, "not locked");
+		goto out;
+	}
+
+	/* is it locked by somethine that isn't us? */
+	pid_tmp = getpid ();
+	if (pid != pid_tmp) {
+		if (error != NULL)
+			*error = g_error_new (1, 0, "locked by %i, cannot unlock", pid_tmp);
+		ret = FALSE;
+		goto out;
+	}
+
+skip_checks:
+
+	/* remove file */
+	retval = g_unlink (lock->priv->filename);
+	if (retval != 0) {
+		if (error != NULL)
+			*error = g_error_new (1, 0, "cannot remove %s, cannot unlock", lock->priv->filename);
+		ret = FALSE;
+		goto out;
+	}
+
+	/* success */
+	ret = TRUE;
+out:
+	return ret;
+}
+
+/**
+ * zif_lock_finalize:
+ **/
+static void
+zif_lock_finalize (GObject *object)
+{
+	ZifLock *lock;
+
+	g_return_if_fail (object != NULL);
+	g_return_if_fail (ZIF_IS_LOCK (object));
+	lock = ZIF_LOCK (object);
+
+	/* unlock if we hold the lock */
+	if (lock->priv->self_locked)
+		zif_lock_set_unlocked (lock, NULL);
+
+	g_free (lock->priv->filename);
+	g_object_unref (lock->priv->config);
+
+	G_OBJECT_CLASS (zif_lock_parent_class)->finalize (object);
+}
+
+/**
+ * zif_lock_class_init:
+ **/
+static void
+zif_lock_class_init (ZifLockClass *klass)
+{
+	GObjectClass *object_class = G_OBJECT_CLASS (klass);
+	object_class->finalize = zif_lock_finalize;
+
+	g_type_class_add_private (klass, sizeof (ZifLockPrivate));
+}
+
+/**
+ * zif_lock_init:
+ **/
+static void
+zif_lock_init (ZifLock *lock)
+{
+	GError *error = NULL;
+	lock->priv = ZIF_LOCK_GET_PRIVATE (lock);
+	lock->priv->self_locked = FALSE;
+	lock->priv->config = zif_config_new ();
+	lock->priv->filename = zif_config_get_string (lock->priv->config, "pidfile", &error);
+	if (lock->priv->filename == NULL) {
+		egg_warning ("failed to get pidfile: %s", error->message);
+		g_error_free (error);
+	}
+}
+
+/**
+ * zif_lock_new:
+ *
+ * Return value: A new lock class instance.
+ **/
+ZifLock *
+zif_lock_new (void)
+{
+	if (zif_lock_object != NULL) {
+		g_object_ref (zif_lock_object);
+	} else {
+		zif_lock_object = g_object_new (ZIF_TYPE_LOCK, NULL);
+		g_object_add_weak_pointer (zif_lock_object, &zif_lock_object);
+	}
+	return ZIF_LOCK (zif_lock_object);
+}
+
+/***************************************************************************
+ ***                          MAKE CHECK TESTS                           ***
+ ***************************************************************************/
+#ifdef EGG_TEST
+#include "egg-test.h"
+
+void
+zif_lock_test (EggTest *test)
+{
+	ZifLock *lock;
+	ZifConfig *config;
+	gboolean ret;
+	GError *error = NULL;
+	gchar *pidfile;
+	guint pid = 0;
+
+	if (!egg_test_start (test, "ZifLock"))
+		return;
+
+	/************************************************************/
+	egg_test_title (test, "get config");
+	config = zif_config_new ();
+	egg_test_assert (test, config != NULL);
+
+	/************************************************************/
+	egg_test_title (test, "set filename");
+	ret = zif_config_set_filename (config, "../test/etc/yum.conf", &error);
+	if (ret)
+		egg_test_success (test, NULL);
+	else
+		egg_test_failed (test, "failed to set filename '%s'", error->message);
+
+	/************************************************************/
+	egg_test_title (test, "get lock");
+	lock = zif_lock_new ();
+	egg_test_assert (test, lock != NULL);
+
+	/************************************************************/
+	egg_test_title (test, "get pidfile");
+	pidfile = zif_config_get_string (config, "pidfile", NULL);
+	if (egg_strequal (pidfile, "../test/run/zif.lock"))
+		egg_test_success (test, NULL);
+	else
+		egg_test_failed (test, "invalid value '%s'", pidfile);
+
+	/* remove file */
+	g_unlink (pidfile);
+
+	/************************************************************/
+	egg_test_title (test, "ensure non-locked");
+	ret = zif_lock_is_locked (lock, &pid);
+	egg_test_assert (test, !ret);
+
+	/************************************************************/
+	egg_test_title (test, "unlock not yet locked lock");
+	ret = zif_lock_set_unlocked (lock, NULL);
+	egg_test_assert (test, !ret);
+
+	/************************************************************/
+	egg_test_title (test, "lock that should succeed");
+	ret = zif_lock_set_locked (lock, &pid, NULL);
+	egg_test_assert (test, ret);
+
+	/************************************************************/
+	egg_test_title (test, "ensure locked");
+	ret = zif_lock_is_locked (lock, &pid);
+	egg_test_assert (test, ret);
+
+	/************************************************************/
+	egg_test_title (test, "ensure pid is us");
+	egg_test_assert (test, (pid == getpid ()));
+
+	/************************************************************/
+	egg_test_title (test, "unlock that should succeed");
+	ret = zif_lock_set_unlocked (lock, NULL);
+	egg_test_assert (test, ret);
+
+	/************************************************************/
+	egg_test_title (test, "unlock again that should fail");
+	ret = zif_lock_set_unlocked (lock, NULL);
+	egg_test_assert (test, !ret);
+
+	g_object_unref (lock);
+	g_object_unref (config);
+	g_free (pidfile);
+
+	egg_test_end (test);
+}
+#endif
+
diff --git a/backends/yum/libzif/zif-lock.h b/backends/yum/libzif/zif-lock.h
new file mode 100644
index 0000000..5e84dc9
--- /dev/null
+++ b/backends/yum/libzif/zif-lock.h
@@ -0,0 +1,69 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2009 Richard Hughes <richard at hughsie.com>
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#if !defined (__ZIF_H_INSIDE__) && !defined (ZIF_COMPILATION)
+#error "Only <zif.h> can be included directly."
+#endif
+
+#ifndef __ZIF_LOCK_H
+#define __ZIF_LOCK_H
+
+#include <glib-object.h>
+#include "zif-completion.h"
+
+G_BEGIN_DECLS
+
+#define ZIF_TYPE_LOCK		(zif_lock_get_type ())
+#define ZIF_LOCK(o)		(G_TYPE_CHECK_INSTANCE_CAST ((o), ZIF_TYPE_LOCK, ZifLock))
+#define ZIF_LOCK_CLASS(k)	(G_TYPE_CHECK_CLASS_CAST((k), ZIF_TYPE_LOCK, ZifLockClass))
+#define ZIF_IS_LOCK(o)		(G_TYPE_CHECK_INSTANCE_TYPE ((o), ZIF_TYPE_LOCK))
+#define ZIF_IS_LOCK_CLASS(k)	(G_TYPE_CHECK_CLASS_TYPE ((k), ZIF_TYPE_LOCK))
+#define ZIF_LOCK_GET_CLASS(o)	(G_TYPE_INSTANCE_GET_CLASS ((o), ZIF_TYPE_LOCK, ZifLockClass))
+
+typedef struct _ZifLock		ZifLock;
+typedef struct _ZifLockPrivate	ZifLockPrivate;
+typedef struct _ZifLockClass	ZifLockClass;
+
+struct _ZifLock
+{
+	GObject				 parent;
+	ZifLockPrivate	*priv;
+};
+
+struct _ZifLockClass
+{
+	GObjectClass	parent_class;
+};
+
+GType		 zif_lock_get_type			(void);
+ZifLock		*zif_lock_new				(void);
+gboolean	 zif_lock_is_locked			(ZifLock		*lock,
+							 guint			*pid);
+gboolean	 zif_lock_set_locked			(ZifLock		*lock,
+							 guint			*pid,
+							 GError			**error);
+gboolean	 zif_lock_set_unlocked			(ZifLock		*lock,
+							 GError			**error);
+
+G_END_DECLS
+
+#endif /* __ZIF_LOCK_H */
+
diff --git a/backends/yum/libzif/zif-monitor.c b/backends/yum/libzif/zif-monitor.c
new file mode 100644
index 0000000..3d34c75
--- /dev/null
+++ b/backends/yum/libzif/zif-monitor.c
@@ -0,0 +1,236 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2008 Richard Hughes <richard at hughsie.com>
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+/**
+ * SECTION:zif-monitor
+ * @short_description: Generic object to monitor files for changes.
+ *
+ * This object is a trivial multiplexted wrapper around GIO.
+ */
+
+#ifdef HAVE_CONFIG_H
+#  include <config.h>
+#endif
+
+#include <glib.h>
+#include <glib/gstdio.h>
+#include <gio/gio.h>
+#include <sys/types.h>
+#include <utime.h>
+
+#include "zif-utils.h"
+#include "zif-monitor.h"
+
+#include "egg-debug.h"
+#include "egg-string.h"
+
+#define ZIF_MONITOR_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), ZIF_TYPE_MONITOR, ZifMonitorPrivate))
+
+/**
+ * ZifMonitorPrivate:
+ *
+ * Private #ZifMonitor data
+ **/
+struct _ZifMonitorPrivate
+{
+	GPtrArray		*array;
+};
+
+enum {
+	ZIF_MONITOR_SIGNAL_CHANGED,
+	ZIF_MONITOR_SIGNAL_LAST_SIGNAL
+};
+
+static guint signals [ZIF_MONITOR_SIGNAL_LAST_SIGNAL] = { 0 };
+
+G_DEFINE_TYPE (ZifMonitor, zif_monitor, G_TYPE_OBJECT)
+
+/**
+ * zif_monitor_file_monitor_cb:
+ **/
+static void
+zif_monitor_file_monitor_cb (GFileMonitor *file_monitor, GFile *file, GFile *other, GFileMonitorEvent event, ZifMonitor *monitor)
+{
+	gchar *filename;
+	filename = g_file_get_path (file);
+	egg_debug ("file changed: %s", filename);
+	g_signal_emit (monitor, signals [ZIF_MONITOR_SIGNAL_CHANGED], 0);
+	g_free (filename);
+}
+
+/**
+ * zif_monitor_add_watch:
+ * @monitor: the #ZifMonitor object
+ * @filename: the full filename to watch
+ * @error: a #GError which is used on failure, or %NULL
+ *
+ * Sets up a watch on the file, and reports the 'changed' signal when the
+ * file is changed.
+ *
+ * Return value: %TRUE for success, %FALSE for failure
+ **/
+gboolean
+zif_monitor_add_watch (ZifMonitor *monitor, const gchar *filename, GError **error)
+{
+	GFile *file;
+	GError *error_local = NULL;
+	gboolean ret = TRUE;
+	GFileMonitor *file_monitor;
+
+	g_return_val_if_fail (ZIF_IS_MONITOR (monitor), FALSE);
+	g_return_val_if_fail (filename != NULL, FALSE);
+
+	/* watch this file */
+	file = g_file_new_for_path (filename);
+	file_monitor = g_file_monitor (file, G_FILE_MONITOR_NONE, NULL, &error_local);
+	if (file_monitor == NULL) {
+		if (error != NULL)
+			*error = g_error_new (1, 0, "failed to add monitor: %s", error_local->message);
+		g_error_free (error_local);
+		g_object_unref (file_monitor);
+		ret = FALSE;
+		goto out;
+	}
+
+	/* setup callback */
+	g_file_monitor_set_rate_limit (file_monitor, 100);
+	g_signal_connect (file_monitor, "changed", G_CALLBACK (zif_monitor_file_monitor_cb), monitor);
+
+	/* add to array */
+	g_ptr_array_add (monitor->priv->array, file_monitor);
+out:
+	g_object_unref (file);
+	return ret;
+}
+
+/**
+ * zif_monitor_finalize:
+ **/
+static void
+zif_monitor_finalize (GObject *object)
+{
+	ZifMonitor *monitor;
+
+	g_return_if_fail (object != NULL);
+	g_return_if_fail (ZIF_IS_MONITOR (object));
+	monitor = ZIF_MONITOR (object);
+
+	g_ptr_array_unref (monitor->priv->array);
+
+	G_OBJECT_CLASS (zif_monitor_parent_class)->finalize (object);
+}
+
+/**
+ * zif_monitor_class_init:
+ **/
+static void
+zif_monitor_class_init (ZifMonitorClass *klass)
+{
+	GObjectClass *object_class = G_OBJECT_CLASS (klass);
+	object_class->finalize = zif_monitor_finalize;
+	signals [ZIF_MONITOR_SIGNAL_CHANGED] =
+		g_signal_new ("changed",
+			      G_TYPE_FROM_CLASS (object_class), G_SIGNAL_RUN_LAST,
+			      0, NULL, NULL, g_cclosure_marshal_VOID__VOID,
+			      G_TYPE_NONE, 0);
+	g_type_class_add_private (klass, sizeof (ZifMonitorPrivate));
+}
+
+/**
+ * zif_monitor_init:
+ **/
+static void
+zif_monitor_init (ZifMonitor *monitor)
+{
+	monitor->priv = ZIF_MONITOR_GET_PRIVATE (monitor);
+	monitor->priv->array = g_ptr_array_new_with_free_func ((GDestroyNotify) g_object_unref);
+}
+
+/**
+ * zif_monitor_new:
+ *
+ * Return value: A new #ZifMonitor class instance.
+ **/
+ZifMonitor *
+zif_monitor_new (void)
+{
+	ZifMonitor *monitor;
+	monitor = g_object_new (ZIF_TYPE_MONITOR, NULL);
+	return ZIF_MONITOR (monitor);
+}
+
+/***************************************************************************
+ ***                          MAKE CHECK TESTS                           ***
+ ***************************************************************************/
+#ifdef EGG_TEST
+#include "egg-test.h"
+
+static void
+zif_monitor_test_file_monitor_cb (ZifMonitor *monitor, EggTest *test)
+{
+	egg_test_loop_quit (test);
+}
+
+static gboolean
+zif_monitor_test_touch (gpointer data)
+{
+	utime ("../test/repos/fedora.repo", NULL);
+	return FALSE;
+}
+
+void
+zif_monitor_test (EggTest *test)
+{
+	ZifMonitor *monitor;
+	gboolean ret;
+	GError *error = NULL;
+
+	if (!egg_test_start (test, "ZifMonitor"))
+		return;
+
+	/************************************************************/
+	egg_test_title (test, "get monitor");
+	monitor = zif_monitor_new ();
+	egg_test_assert (test, monitor != NULL);
+
+	g_signal_connect (monitor, "changed", G_CALLBACK (zif_monitor_test_file_monitor_cb), test);
+
+	/************************************************************/
+	egg_test_title (test, "load");
+	ret = zif_monitor_add_watch (monitor, "../test/repos/fedora.repo", &error);
+	if (ret)
+		egg_test_success (test, NULL);
+	else
+		egg_test_failed (test, "failed to load '%s'", error->message);
+
+	/* touch in 10ms */
+	g_timeout_add (10, (GSourceFunc) zif_monitor_test_touch, NULL);
+
+	/* wait for changed */
+	egg_test_loop_wait (test, 2000);
+	egg_test_loop_check (test);
+
+	g_object_unref (monitor);
+
+	egg_test_end (test);
+}
+#endif
+
diff --git a/backends/yum/libzif/zif-monitor.h b/backends/yum/libzif/zif-monitor.h
new file mode 100644
index 0000000..2724853
--- /dev/null
+++ b/backends/yum/libzif/zif-monitor.h
@@ -0,0 +1,64 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2008 Richard Hughes <richard at hughsie.com>
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#if !defined (__ZIF_H_INSIDE__) && !defined (ZIF_COMPILATION)
+#error "Only <zif.h> can be included directly."
+#endif
+
+#ifndef __ZIF_MONITOR_H
+#define __ZIF_MONITOR_H
+
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+#define ZIF_TYPE_MONITOR		(zif_monitor_get_type ())
+#define ZIF_MONITOR(o)			(G_TYPE_CHECK_INSTANCE_CAST ((o), ZIF_TYPE_MONITOR, ZifMonitor))
+#define ZIF_MONITOR_CLASS(k)		(G_TYPE_CHECK_CLASS_CAST((k), ZIF_TYPE_MONITOR, ZifMonitorClass))
+#define ZIF_IS_MONITOR(o)		(G_TYPE_CHECK_INSTANCE_TYPE ((o), ZIF_TYPE_MONITOR))
+#define ZIF_IS_MONITOR_CLASS(k)		(G_TYPE_CHECK_CLASS_TYPE ((k), ZIF_TYPE_MONITOR))
+#define ZIF_MONITOR_GET_CLASS(o)	(G_TYPE_INSTANCE_GET_CLASS ((o), ZIF_TYPE_MONITOR, ZifMonitorClass))
+
+typedef struct _ZifMonitor		ZifMonitor;
+typedef struct _ZifMonitorPrivate	ZifMonitorPrivate;
+typedef struct _ZifMonitorClass		ZifMonitorClass;
+
+struct _ZifMonitor
+{
+	GObject			 parent;
+	ZifMonitorPrivate	*priv;
+};
+
+struct _ZifMonitorClass
+{
+	GObjectClass		 parent_class;
+};
+
+GType		 zif_monitor_get_type		(void);
+ZifMonitor	*zif_monitor_new		(void);
+gboolean	 zif_monitor_add_watch		(ZifMonitor	*monitor,
+						 const gchar	*filename,
+						 GError		**error);
+
+G_END_DECLS
+
+#endif /* __ZIF_MONITOR_H */
+
diff --git a/backends/yum/libzif/zif-package-local.c b/backends/yum/libzif/zif-package-local.c
new file mode 100644
index 0000000..273cab1
--- /dev/null
+++ b/backends/yum/libzif/zif-package-local.c
@@ -0,0 +1,669 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2008 Richard Hughes <richard at hughsie.com>
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+/**
+ * SECTION:zif-package-local
+ * @short_description: Local package object
+ *
+ * This object is a subclass of #ZifPackage
+ */
+
+#ifdef HAVE_CONFIG_H
+#  include <config.h>
+#endif
+
+#include <glib.h>
+#include <packagekit-glib2/packagekit.h>
+#include <rpm/rpmlib.h>
+#include <rpm/rpmdb.h>
+#include <rpm/rpmts.h>
+
+#include "egg-debug.h"
+
+#include "zif-utils.h"
+#include "zif-package.h"
+#include "zif-package-local.h"
+#include "zif-groups.h"
+#include "zif-string.h"
+#include "zif-depend.h"
+
+#define ZIF_PACKAGE_LOCAL_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), ZIF_TYPE_PACKAGE_LOCAL, ZifPackageLocalPrivate))
+
+/**
+ * ZifPackageLocalPrivate:
+ *
+ * Private #ZifPackageLocal data
+ **/
+struct _ZifPackageLocalPrivate
+{
+	ZifGroups		*groups;
+	Header			 header;
+};
+
+G_DEFINE_TYPE (ZifPackageLocal, zif_package_local, ZIF_TYPE_PACKAGE)
+
+/**
+ * zif_get_header_string:
+ **/
+static ZifString *
+zif_get_header_string (Header header, rpmTag tag)
+{
+	gint retval;
+	ZifString *data = NULL;
+	rpmtd td;
+
+	td = rpmtdNew ();
+	retval = headerGet (header, tag, td, HEADERGET_MINMEM);
+
+	if (retval != 1)
+		goto out;
+	data = zif_string_new (rpmtdGetString (td));
+out:
+	rpmtdFreeData (td);
+	rpmtdFree (td);
+	return data;
+}
+
+/**
+ * zif_get_header_u32:
+ **/
+static guint
+zif_get_header_u32 (Header header, rpmTag tag)
+{
+	gint retval;
+	uint32_t *data_p;
+	guint data = 0;
+	rpmtd td;
+
+	td = rpmtdNew ();
+	retval = headerGet (header, RPMTAG_SIZE, td, HEADERGET_MINMEM);
+	if (retval != 1)
+		goto out;
+	data_p = rpmtdGetUint32 (td);
+	if (data_p != NULL)
+		data = *data_p;
+out:
+	rpmtdFreeData (td);
+	rpmtdFree (td);
+	return data;
+}
+
+/**
+ * zif_get_header_uint32_index:
+ **/
+static GPtrArray *
+zif_get_header_uint32_index (Header header, rpmTag tag, guint length)
+{
+	gint retval;
+	guint32 *data;
+	GPtrArray *array = NULL;
+	rpmtd td;
+	guint i;
+
+	td = rpmtdNew ();
+	retval = headerGet (header, tag, td, HEADERGET_MINMEM);
+	if (retval != 1)
+		goto out;
+	array = g_ptr_array_new ();
+	data = rpmtdGetUint32 (td);
+	for (i=0;i<length; i++)
+		g_ptr_array_add (array, GUINT_TO_POINTER (*(data+i)));
+out:
+	rpmtdFreeData (td);
+	rpmtdFree (td);
+	return array;
+}
+
+/**
+ * zif_get_header_string_array:
+ **/
+static GPtrArray *
+zif_get_header_string_array (Header header, rpmTag tag)
+{
+	gint retval;
+	const gchar *data;
+	GPtrArray *array = NULL;
+	rpmtd td;
+
+	td = rpmtdNew ();
+	retval = headerGet (header, tag, td, HEADERGET_MINMEM);
+	if (retval != 1)
+		goto out;
+	array = g_ptr_array_new_with_free_func (g_free);
+	data = rpmtdGetString (td);
+	while (data != NULL) {
+		g_ptr_array_add (array, g_strdup (data));
+		data = rpmtdNextString (td);
+	}
+out:
+	rpmtdFreeData (td);
+	rpmtdFree (td);
+	return array;
+}
+
+/**
+ * zif_package_local_id_from_header:
+ **/
+static gchar *
+zif_package_local_id_from_header (Header header)
+{
+	gchar *package_id;
+	const gchar *name = NULL;
+	const gchar *epoch = NULL;
+	const gchar *version = NULL;
+	const gchar *release = NULL;
+	const gchar *arch = NULL;
+	struct rpmtd_s value;
+
+	/* get NEVRA */
+	if (headerGet(header, RPMTAG_NAME, &value, HEADERGET_DEFAULT))
+		name = rpmtdGetString (&value);
+	if (headerGet(header, RPMTAG_EPOCH, &value, HEADERGET_DEFAULT))
+		epoch = rpmtdGetString (&value);
+	if (headerGet(header, RPMTAG_VERSION, &value, HEADERGET_DEFAULT))
+		version = rpmtdGetString (&value);
+	if (headerGet(header, RPMTAG_RELEASE, &value, HEADERGET_DEFAULT))
+		release = rpmtdGetString (&value);
+	if (headerGet(header, RPMTAG_ARCH, &value, HEADERGET_DEFAULT))
+		arch = rpmtdGetString (&value);
+
+	/* trivial */
+	if (epoch == NULL) {
+		package_id = zif_package_id_from_nevra (name, NULL, version, release, arch, "installed");
+		goto out;
+	}
+
+	/* with epoch */
+	package_id = zif_package_id_from_nevra (name, epoch, version, release, arch, "installed");
+out:
+	return package_id;
+}
+
+/**
+ * zif_package_local_get_depends_from_name_flags_version:
+ **/
+static GPtrArray *
+zif_package_local_get_depends_from_name_flags_version (GPtrArray *names, GPtrArray *flags, GPtrArray *versions)
+{
+	guint i;
+	rpmsenseFlags rpmflags;
+	ZifDepend *depend;
+	ZifDependFlag flag;
+	const gchar *name;
+	const gchar *version;
+	GPtrArray *array;
+
+	/* create requires */
+	array = g_ptr_array_new_with_free_func ((GDestroyNotify) zif_depend_unref);
+	for (i=0; i<names->len; i++) {
+		name = g_ptr_array_index (names, i);
+		version = g_ptr_array_index (versions, i);
+
+		/* no version string */
+		if (version == NULL || version[0] == '\0') {
+			depend = zif_depend_new (name, ZIF_DEPEND_FLAG_ANY, NULL);
+			g_ptr_array_add (array, depend);
+			continue;
+		}
+
+		/* ignore rpmlib flags */
+		rpmflags = GPOINTER_TO_UINT (g_ptr_array_index (flags, i));
+		if ((rpmflags & RPMSENSE_RPMLIB) > 0)
+			continue;
+
+		/* convert to enums */
+		flag = ZIF_DEPEND_FLAG_UNKNOWN;
+		if ((rpmflags & RPMSENSE_LESS) > 0) {
+			flag = ZIF_DEPEND_FLAG_LESS;
+		} else if ((rpmflags & RPMSENSE_GREATER) > 0) {
+			flag = ZIF_DEPEND_FLAG_GREATER;
+		} else if ((rpmflags & RPMSENSE_EQUAL) > 0) {
+			flag = ZIF_DEPEND_FLAG_EQUAL;
+		}
+
+		/* unknown */
+		if (flag == ZIF_DEPEND_FLAG_UNKNOWN) {
+//			egg_debug ("ignoring %s %s %s", name, zif_depend_flag_to_string (flag), version);
+			continue;
+		}
+
+		depend = zif_depend_new (name, flag, version);
+		g_ptr_array_add (array, depend);
+	}
+	return array;
+}
+
+/*
+ * zif_package_local_ensure_data:
+ */
+static gboolean
+zif_package_local_ensure_data (ZifPackage *pkg, ZifPackageEnsureType type, GError **error)
+{
+	GPtrArray *files;
+	GPtrArray *dirnames;
+	GPtrArray *basenames;
+	GPtrArray *fileindex;
+	guint i;
+	gchar *filename;
+	guint size;
+	ZifString *tmp;
+	PkGroupEnum group;
+//	GPtrArray *tmparray;
+	GPtrArray *depends;
+//	GPtrArray *provides;
+	GPtrArray *flags;
+	GPtrArray *names;
+	GPtrArray *versions;
+	gboolean ret = TRUE;
+	Header header = ZIF_PACKAGE_LOCAL(pkg)->priv->header;
+
+	/* eigh? */
+	if (header == NULL) {
+		g_set_error (error, 1, 0, "no header for %s", zif_package_get_id (pkg));
+		ret = FALSE;
+		goto out;
+	}
+
+	if (type == ZIF_PACKAGE_ENSURE_TYPE_FILES) {
+		/* files */
+		basenames = zif_get_header_string_array (header, RPMTAG_BASENAMES);
+
+		/* create the files */
+		if (basenames != NULL) {
+
+			/* get the mapping */
+			dirnames = zif_get_header_string_array (header, RPMTAG_DIRNAMES);
+			fileindex = zif_get_header_uint32_index (header, RPMTAG_DIRINDEXES, basenames->len);
+			if (basenames->len != fileindex->len)
+				egg_error ("internal error, basenames length is not the same as index length, possibly corrupt db?");
+			if (fileindex->len > fileindex->len)
+				egg_error ("internal error, fileindex length is bigger than index length, possibly corrupt db?");
+
+			files = g_ptr_array_new_with_free_func (g_free);
+			for (i=0; i<basenames->len-2 /* why -1? I'm not sure */; i++) {
+				guint idx;
+				idx = GPOINTER_TO_UINT (g_ptr_array_index (fileindex, i));
+				if (idx > dirnames->len) {
+					egg_warning ("index bigger than dirnames (%i > %i) for package %s [%s], i=%i, dn=%i, bn=%i, fi=%i",
+						     idx, dirnames->len, zif_package_get_package_id (pkg),
+						     (const gchar *) g_ptr_array_index (basenames, i),
+						     i, dirnames->len, basenames->len, fileindex->len);
+					continue;
+				}
+				filename = g_strconcat (g_ptr_array_index (dirnames, idx), g_ptr_array_index (basenames, i), NULL);
+				g_ptr_array_add (files, filename);
+			}
+			zif_package_set_files (pkg, files);
+			g_ptr_array_unref (files);
+
+			/* free, as we have files */
+			g_ptr_array_unref (dirnames);
+			g_ptr_array_unref (basenames);
+			g_ptr_array_unref (fileindex);
+		} else {
+			files = g_ptr_array_new_with_free_func (g_free);
+			zif_package_set_files (pkg, files);
+			g_ptr_array_unref (files);
+		}
+	} else if (type == ZIF_PACKAGE_ENSURE_TYPE_SUMMARY) {
+		/* summary */
+		tmp = zif_get_header_string (header, RPMTAG_SUMMARY);
+		zif_package_set_summary (pkg, tmp);
+		zif_string_unref (tmp);
+
+	} else if (type == ZIF_PACKAGE_ENSURE_TYPE_LICENCE) {
+		/* license */
+		tmp = zif_get_header_string (header, RPMTAG_LICENSE);
+		zif_package_set_license (pkg, tmp);
+		zif_string_unref (tmp);
+
+	} else if (type == ZIF_PACKAGE_ENSURE_TYPE_DESCRIPTION) {
+		/* description */
+		tmp = zif_get_header_string (header, RPMTAG_DESCRIPTION);
+		if (tmp == NULL) {
+			egg_warning ("no description for %s", zif_package_get_id (pkg));
+			tmp = zif_string_new ("");
+		}
+		zif_package_set_description (pkg, tmp);
+		zif_string_unref (tmp);
+
+	} else if (type == ZIF_PACKAGE_ENSURE_TYPE_URL) {
+		/* url */
+		tmp = zif_get_header_string (header, RPMTAG_URL);
+		if (tmp != NULL) {
+			zif_package_set_url (pkg, tmp);
+			zif_string_unref (tmp);
+		}
+
+	} else if (type == ZIF_PACKAGE_ENSURE_TYPE_SIZE) {
+		/* size */
+		size = zif_get_header_u32 (header, RPMTAG_SIZE);
+		if (size != 0)
+			zif_package_set_size (pkg, size);
+
+	} else if (type == ZIF_PACKAGE_ENSURE_TYPE_GROUP) {
+		/* category && group */
+		tmp = zif_get_header_string (header, RPMTAG_GROUP);
+		zif_package_set_category (pkg, tmp);
+		group = zif_groups_get_group_for_cat (ZIF_PACKAGE_LOCAL (pkg)->priv->groups, zif_string_get_value (tmp), NULL);
+		if (group != PK_GROUP_ENUM_UNKNOWN)
+			zif_package_set_group (pkg, group);
+		zif_string_unref (tmp);
+
+	} else if (type == ZIF_PACKAGE_ENSURE_TYPE_REQUIRES) {
+		/* requires */
+		names = zif_get_header_string_array (header, RPMTAG_REQUIRENAME);
+		if (names == NULL) {
+			depends = g_ptr_array_new_with_free_func ((GDestroyNotify) zif_depend_unref);
+			zif_package_set_requires (pkg, depends);
+			g_ptr_array_unref (depends);
+		} else {
+			versions = zif_get_header_string_array (header, RPMTAG_REQUIREVERSION);
+			flags = zif_get_header_uint32_index (header, RPMTAG_REQUIREFLAGS, names->len);
+			depends = zif_package_local_get_depends_from_name_flags_version (names, flags, versions);
+			zif_package_set_requires (pkg, depends);
+			g_ptr_array_unref (depends);
+			g_ptr_array_unref (names);
+			g_ptr_array_unref (versions);
+			g_ptr_array_unref (flags);
+		}
+
+	} else if (type == ZIF_PACKAGE_ENSURE_TYPE_PROVIDES) {
+		/* provides */
+		names = zif_get_header_string_array (header, RPMTAG_PROVIDENAME);
+		if (names == NULL) {
+			depends = g_ptr_array_new_with_free_func ((GDestroyNotify) zif_depend_unref);
+			zif_package_set_provides (pkg, depends);
+			g_ptr_array_unref (depends);
+		} else {
+			versions = zif_get_header_string_array (header, RPMTAG_PROVIDEVERSION);
+			flags = zif_get_header_uint32_index (header, RPMTAG_PROVIDEFLAGS, names->len);
+			depends = zif_package_local_get_depends_from_name_flags_version (names, flags, versions);
+			zif_package_set_provides (pkg, depends);
+			g_ptr_array_unref (depends);
+			g_ptr_array_unref (names);
+			g_ptr_array_unref (versions);
+			g_ptr_array_unref (flags);
+		}
+
+	} else if (type == ZIF_PACKAGE_ENSURE_TYPE_CONFLICTS) {
+		/* conflicts */
+		names = zif_get_header_string_array (header, RPMTAG_CONFLICTNAME);
+		if (names == NULL) {
+			depends = g_ptr_array_new_with_free_func ((GDestroyNotify) zif_depend_unref);
+			//zif_package_set_conflicts (pkg, depends);
+			g_ptr_array_unref (depends);
+		} else {
+			versions = zif_get_header_string_array (header, RPMTAG_CONFLICTVERSION);
+			flags = zif_get_header_uint32_index (header, RPMTAG_CONFLICTFLAGS, names->len);
+			depends = zif_package_local_get_depends_from_name_flags_version (names, flags, versions);
+			//zif_package_set_conflicts (pkg, depends);
+			g_ptr_array_unref (depends);
+			g_ptr_array_unref (names);
+			g_ptr_array_unref (versions);
+			g_ptr_array_unref (flags);
+		}
+
+	} else if (type == ZIF_PACKAGE_ENSURE_TYPE_OBSOLETES) {
+		/* obsoletes */
+		names = zif_get_header_string_array (header, RPMTAG_OBSOLETENAME);
+		if (names == NULL) {
+			depends = g_ptr_array_new_with_free_func ((GDestroyNotify) zif_depend_unref);
+			//zif_package_set_obsoletes (pkg, depends);
+			g_ptr_array_unref (depends);
+		} else {
+			versions = zif_get_header_string_array (header, RPMTAG_OBSOLETEVERSION);
+			flags = zif_get_header_uint32_index (header, RPMTAG_OBSOLETEFLAGS, names->len);
+			depends = zif_package_local_get_depends_from_name_flags_version (names, flags, versions);
+			//zif_package_set_obsoletes (pkg, depends);
+			g_ptr_array_unref (depends);
+			g_ptr_array_unref (names);
+			g_ptr_array_unref (versions);
+			g_ptr_array_unref (flags);
+		}
+	}
+out:
+	return ret;
+}
+
+/**
+ * zif_package_local_set_from_header:
+ * @pkg: the #ZifPackageLocal object
+ * @header: a rpm #Header structure
+ * @error: a #GError which is used on failure, or %NULL
+ *
+ * Sets the local package from an RPM header object.
+ *
+ * Return value: %TRUE for success, %FALSE for failure
+ **/
+gboolean
+zif_package_local_set_from_header (ZifPackageLocal *pkg, Header header, GError **error)
+{
+	gchar *package_id;
+
+	g_return_val_if_fail (ZIF_IS_PACKAGE_LOCAL (pkg), FALSE);
+	g_return_val_if_fail (header != NULL, FALSE);
+
+	zif_package_set_installed (ZIF_PACKAGE (pkg), TRUE);
+
+	/* save header so we can read when required */
+	pkg->priv->header = headerLink (header);
+
+	/* id */
+	package_id = zif_package_local_id_from_header (header);
+	zif_package_set_id (ZIF_PACKAGE (pkg), package_id);
+	g_free (package_id);
+
+	return TRUE;
+}
+
+/**
+ * zif_package_local_rpmrc_to_string:
+ **/
+static const gchar *
+zif_package_local_rpmrc_to_string (rpmRC rc)
+{
+	if (rc == RPMRC_OK)
+		return "Generic success";
+	if (rc == RPMRC_NOTFOUND)
+		return "Generic not found";
+	if (rc == RPMRC_FAIL)
+		return "Generic failure";
+	if (rc == RPMRC_NOTTRUSTED)
+		return "Signature is OK, but key is not trusted";
+	if (rc == RPMRC_NOKEY)
+		return "Public key is unavailable";
+	return "Unknown error";
+}
+
+/**
+ * zif_package_local_set_from_filename:
+ * @pkg: the #ZifPackageLocal object
+ * @filename: the local filename
+ * @error: a #GError which is used on failure, or %NULL
+ *
+ * Sets a local package object from a local file.
+ *
+ * Return value: %TRUE for success, %FALSE for failure
+ **/
+gboolean
+zif_package_local_set_from_filename (ZifPackageLocal *pkg, const gchar *filename, GError **error)
+{
+	rpmRC rc;
+	FD_t fd = NULL;
+	Header hdr = NULL;
+	rpmts ts;
+	gboolean ret = FALSE;
+	GError *error_local = NULL;
+
+	/* open the file for reading */
+	fd = Fopen(filename, "r.fdio"); 
+	if (fd == NULL) {
+		if (error != NULL)
+			*error = g_error_new (1, 0, "failed to open %s", filename);
+		goto out;
+	}
+	if (Ferror(fd)) {
+		if (error != NULL)
+			*error = g_error_new (1, 0, "failed to open %s: %s", filename, Fstrerror(fd));
+		goto out;
+	}
+
+	/* create an empty transaction set */
+	ts = rpmtsCreate ();
+
+	/* we don't want to abort on missing keys */
+	rpmtsSetVSFlags (ts, _RPMVSF_NOSIGNATURES);
+
+	/* read in the file */
+	rc = rpmReadPackageFile (ts, fd, filename, &hdr);
+	if (rc != RPMRC_OK) {
+		if (error != NULL)
+			*error = g_error_new (1, 0, "failed to read %s: %s", filename, zif_package_local_rpmrc_to_string (rc));
+		goto out;
+	}
+
+	/* convert and upscale */
+	headerConvert (hdr, HEADERCONV_RETROFIT_V3);
+
+	/* set from header */
+	ret = zif_package_local_set_from_header (pkg, hdr, &error_local);
+	if (!ret) {
+		if (error != NULL)
+			*error = g_error_new (1, 0, "failed to set from header: %s", error_local->message);
+		g_error_free (error_local);
+		goto out;
+	}
+
+	/* close the database used by the transaction */
+	rc = rpmtsCloseDB (ts);
+	if (rc != RPMRC_OK) {
+		if (error != NULL)
+			*error = g_error_new (1, 0, "failed to close: %s", zif_package_local_rpmrc_to_string (rc));
+		ret = FALSE;
+		goto out;
+	}
+out:
+	/* close header and file */
+	if (hdr != NULL)
+		headerFree (hdr);
+	if (fd != NULL)
+		Fclose (fd);
+	return ret;
+}
+
+/**
+ * zif_package_local_finalize:
+ **/
+static void
+zif_package_local_finalize (GObject *object)
+{
+	ZifPackageLocal *pkg;
+
+	g_return_if_fail (object != NULL);
+	g_return_if_fail (ZIF_IS_PACKAGE_LOCAL (object));
+	pkg = ZIF_PACKAGE_LOCAL (object);
+
+	g_object_unref (pkg->priv->groups);
+	if (pkg->priv->header != NULL)
+		headerUnlink (pkg->priv->header);
+
+	G_OBJECT_CLASS (zif_package_local_parent_class)->finalize (object);
+}
+
+/**
+ * zif_package_local_class_init:
+ **/
+static void
+zif_package_local_class_init (ZifPackageLocalClass *klass)
+{
+	GObjectClass *object_class = G_OBJECT_CLASS (klass);
+	ZifPackageClass *package_class = ZIF_PACKAGE_CLASS (klass);
+	object_class->finalize = zif_package_local_finalize;
+
+	package_class->ensure_data = zif_package_local_ensure_data;
+
+	g_type_class_add_private (klass, sizeof (ZifPackageLocalPrivate));
+}
+
+/**
+ * zif_package_local_init:
+ **/
+static void
+zif_package_local_init (ZifPackageLocal *pkg)
+{
+	pkg->priv = ZIF_PACKAGE_LOCAL_GET_PRIVATE (pkg);
+	pkg->priv->groups = zif_groups_new ();
+	pkg->priv->header = NULL;
+}
+
+/**
+ * zif_package_local_new:
+ *
+ * Return value: A new #ZifPackageLocal class instance.
+ **/
+ZifPackageLocal *
+zif_package_local_new (void)
+{
+	ZifPackageLocal *pkg;
+	pkg = g_object_new (ZIF_TYPE_PACKAGE_LOCAL, NULL);
+	return ZIF_PACKAGE_LOCAL (pkg);
+}
+
+/***************************************************************************
+ ***                          MAKE CHECK TESTS                           ***
+ ***************************************************************************/
+#ifdef EGG_TEST
+#include "egg-test.h"
+
+void
+zif_package_local_test (EggTest *test)
+{
+	ZifPackageLocal *pkg;
+	gboolean ret;
+	GError *error = NULL;
+	gchar *filename;
+
+	if (!egg_test_start (test, "ZifPackageLocal"))
+		return;
+
+	/************************************************************/
+	egg_test_title (test, "get package_local");
+	pkg = zif_package_local_new ();
+	egg_test_assert (test, pkg != NULL);
+
+	/************************************************************/
+	egg_test_title (test, "load file");
+	filename = egg_test_get_data_file ("accountsdialog-0.4.1-1.fc13.i686.rpm");
+	ret = zif_package_local_set_from_filename (pkg, filename, &error);
+	if (!ret) {
+		egg_test_failed (test, "failed to set from filename: %s", error->message);
+		g_error_free (error);
+	}
+	g_free (filename);
+	egg_test_success (test, NULL);
+
+	g_object_unref (pkg);
+
+	egg_test_end (test);
+}
+#endif
+
diff --git a/backends/yum/libzif/zif-package-local.h b/backends/yum/libzif/zif-package-local.h
new file mode 100644
index 0000000..5bc2e4b
--- /dev/null
+++ b/backends/yum/libzif/zif-package-local.h
@@ -0,0 +1,71 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2008 Richard Hughes <richard at hughsie.com>
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#if !defined (__ZIF_H_INSIDE__) && !defined (ZIF_COMPILATION)
+#error "Only <zif.h> can be included directly."
+#endif
+
+#ifndef __ZIF_PACKAGE_LOCAL_H
+#define __ZIF_PACKAGE_LOCAL_H
+
+#include <glib-object.h>
+#include <rpm/rpmlib.h>
+#include <rpm/rpmdb.h>
+
+#include "zif-package.h"
+
+G_BEGIN_DECLS
+
+#define ZIF_TYPE_PACKAGE_LOCAL		(zif_package_local_get_type ())
+#define ZIF_PACKAGE_LOCAL(o)		(G_TYPE_CHECK_INSTANCE_CAST ((o), ZIF_TYPE_PACKAGE_LOCAL, ZifPackageLocal))
+#define ZIF_PACKAGE_LOCAL_CLASS(k)	(G_TYPE_CHECK_CLASS_CAST((k), ZIF_TYPE_PACKAGE_LOCAL, ZifPackageLocalClass))
+#define ZIF_IS_PACKAGE_LOCAL(o)		(G_TYPE_CHECK_INSTANCE_TYPE ((o), ZIF_TYPE_PACKAGE_LOCAL))
+#define ZIF_IS_PACKAGE_LOCAL_CLASS(k)	(G_TYPE_CHECK_CLASS_TYPE ((k), ZIF_TYPE_PACKAGE_LOCAL))
+#define ZIF_PACKAGE_LOCAL_GET_CLASS(o)	(G_TYPE_INSTANCE_GET_CLASS ((o), ZIF_TYPE_PACKAGE_LOCAL, ZifPackageLocalClass))
+
+typedef struct _ZifPackageLocal		ZifPackageLocal;
+typedef struct _ZifPackageLocalPrivate	ZifPackageLocalPrivate;
+typedef struct _ZifPackageLocalClass	ZifPackageLocalClass;
+
+struct _ZifPackageLocal
+{
+	ZifPackage		 parent;
+	ZifPackageLocalPrivate	*priv;
+};
+
+struct _ZifPackageLocalClass
+{
+	ZifPackageClass		 parent_class;
+};
+
+GType			 zif_package_local_get_type		(void);
+ZifPackageLocal		*zif_package_local_new			(void);
+gboolean		 zif_package_local_set_from_header	(ZifPackageLocal *pkg,
+								 Header		 header,
+								 GError		**error);
+gboolean		 zif_package_local_set_from_filename	(ZifPackageLocal *pkg,
+								 const gchar	*filename,
+								 GError		**error);
+
+G_END_DECLS
+
+#endif /* __ZIF_PACKAGE_LOCAL_H */
+
diff --git a/backends/yum/libzif/zif-package-remote.c b/backends/yum/libzif/zif-package-remote.c
new file mode 100644
index 0000000..ae6fa67
--- /dev/null
+++ b/backends/yum/libzif/zif-package-remote.c
@@ -0,0 +1,216 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2008 Richard Hughes <richard at hughsie.com>
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+/**
+ * SECTION:zif-package-remote
+ * @short_description: Remote package object
+ *
+ * This object is a subclass of #ZifPackage
+ */
+
+#ifdef HAVE_CONFIG_H
+#  include <config.h>
+#endif
+
+#include <glib.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include "egg-debug.h"
+
+#include "zif-utils.h"
+#include "zif-package-remote.h"
+#include "zif-groups.h"
+#include "zif-string.h"
+
+#define ZIF_PACKAGE_REMOTE_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), ZIF_TYPE_PACKAGE_REMOTE, ZifPackageRemotePrivate))
+
+/**
+ * ZifPackageRemotePrivate:
+ *
+ * Private #ZifPackageRemote data
+ **/
+struct _ZifPackageRemotePrivate
+{
+	ZifGroups		*groups;
+	gchar			*sql_id;
+};
+
+G_DEFINE_TYPE (ZifPackageRemote, zif_package_remote, ZIF_TYPE_PACKAGE)
+
+/**
+ * zif_package_remote_set_from_repo:
+ * @pkg: the #ZifPackageRemote object
+ * @length: length of data and type arrays
+ * @type: data type array
+ * @data: data value array
+ * @repo_id: the repository id
+ * @error: a #GError which is used on failure, or %NULL
+ *
+ * Sets details on a remote package from repo data derived from the metadata xml.
+ *
+ * Return value: %TRUE for success, %FALSE for failure
+ **/
+gboolean
+zif_package_remote_set_from_repo (ZifPackageRemote *pkg, guint length, gchar **type, gchar **data, const gchar *repo_id, GError **error)
+{
+	guint i;
+	const gchar *name = NULL;
+	const gchar *epoch = NULL;
+	const gchar *version = NULL;
+	const gchar *release = NULL;
+	const gchar *arch = NULL;
+	gchar *package_id;
+	ZifString *string;
+
+	g_return_val_if_fail (ZIF_IS_PACKAGE_REMOTE (pkg), FALSE);
+	g_return_val_if_fail (type != NULL, FALSE);
+	g_return_val_if_fail (data != NULL, FALSE);
+
+	/* get the ID */
+	for (i=0; i<length; i++) {
+		if (g_strcmp0 (type[i], "name") == 0) {
+			name = data[i];
+		} else if (g_strcmp0 (type[i], "epoch") == 0) {
+			epoch = data[i];
+		} else if (g_strcmp0 (type[i], "version") == 0) {
+			version = data[i];
+		} else if (g_strcmp0 (type[i], "release") == 0) {
+			release = data[i];
+		} else if (g_strcmp0 (type[i], "arch") == 0) {
+			arch = data[i];
+		} else if (g_strcmp0 (type[i], "summary") == 0) {
+			string = zif_string_new (data[i]);
+			zif_package_set_summary (ZIF_PACKAGE (pkg), string);
+			zif_string_unref (string);
+		} else if (g_strcmp0 (type[i], "description") == 0) {
+			string = zif_string_new (data[i]);
+			zif_package_set_description (ZIF_PACKAGE (pkg), string);
+			zif_string_unref (string);
+		} else if (g_strcmp0 (type[i], "url") == 0) {
+			string = zif_string_new (data[i]);
+			zif_package_set_url (ZIF_PACKAGE (pkg), string);
+			zif_string_unref (string);
+		} else if (g_strcmp0 (type[i], "rpm_license") == 0) {
+			string = zif_string_new (data[i]);
+			zif_package_set_license (ZIF_PACKAGE (pkg), string);
+			zif_string_unref (string);
+		} else if (g_strcmp0 (type[i], "rpm_group") == 0) {
+			string = zif_string_new (data[i]);
+			zif_package_set_category (ZIF_PACKAGE (pkg), string);
+			zif_string_unref (string);
+		} else if (g_strcmp0 (type[i], "size_package") == 0) {
+			zif_package_set_size (ZIF_PACKAGE (pkg), atoi (data[i]));
+		} else if (g_strcmp0 (type[i], "pkgId") == 0) {
+			pkg->priv->sql_id = g_strdup (data[i]);
+		} else if (g_strcmp0 (type[i], "location_href") == 0) {
+			string = zif_string_new (data[i]);
+			zif_package_set_location_href (ZIF_PACKAGE (pkg), string);
+			zif_string_unref (string);
+		} else {
+			egg_warning ("unregognised: %s=%s", type[i], data[i]);
+		}
+	}
+	zif_package_set_installed (ZIF_PACKAGE (pkg), FALSE);
+	package_id = zif_package_id_from_nevra (name, epoch, version, release, arch, repo_id);
+	zif_package_set_id (ZIF_PACKAGE (pkg), package_id);
+	g_free (package_id);
+	return TRUE;
+}
+
+/**
+ * zif_package_remote_finalize:
+ **/
+static void
+zif_package_remote_finalize (GObject *object)
+{
+	ZifPackageRemote *pkg;
+
+	g_return_if_fail (object != NULL);
+	g_return_if_fail (ZIF_IS_PACKAGE_REMOTE (object));
+	pkg = ZIF_PACKAGE_REMOTE (object);
+
+	g_free (pkg->priv->sql_id);
+	g_object_unref (pkg->priv->groups);
+
+	G_OBJECT_CLASS (zif_package_remote_parent_class)->finalize (object);
+}
+
+/**
+ * zif_package_remote_class_init:
+ **/
+static void
+zif_package_remote_class_init (ZifPackageRemoteClass *klass)
+{
+	GObjectClass *object_class = G_OBJECT_CLASS (klass);
+	object_class->finalize = zif_package_remote_finalize;
+	g_type_class_add_private (klass, sizeof (ZifPackageRemotePrivate));
+}
+
+/**
+ * zif_package_remote_init:
+ **/
+static void
+zif_package_remote_init (ZifPackageRemote *pkg)
+{
+	pkg->priv = ZIF_PACKAGE_REMOTE_GET_PRIVATE (pkg);
+	pkg->priv->sql_id = NULL;
+	pkg->priv->groups = zif_groups_new ();
+}
+
+/**
+ * zif_package_remote_new:
+ *
+ * Return value: A new #ZifPackageRemote class instance.
+ **/
+ZifPackageRemote *
+zif_package_remote_new (void)
+{
+	ZifPackageRemote *pkg;
+	pkg = g_object_new (ZIF_TYPE_PACKAGE_REMOTE, NULL);
+	return ZIF_PACKAGE_REMOTE (pkg);
+}
+
+/***************************************************************************
+ ***                          MAKE CHECK TESTS                           ***
+ ***************************************************************************/
+#ifdef EGG_TEST
+#include "egg-test.h"
+
+void
+zif_package_remote_test (EggTest *test)
+{
+	ZifPackageRemote *pkg;
+
+	if (!egg_test_start (test, "ZifPackageRemote"))
+		return;
+
+	/************************************************************/
+	egg_test_title (test, "get package_remote");
+	pkg = zif_package_remote_new ();
+	egg_test_assert (test, pkg != NULL);
+
+	g_object_unref (pkg);
+
+	egg_test_end (test);
+}
+#endif
+
diff --git a/backends/yum/libzif/zif-package-remote.h b/backends/yum/libzif/zif-package-remote.h
new file mode 100644
index 0000000..09277ed
--- /dev/null
+++ b/backends/yum/libzif/zif-package-remote.h
@@ -0,0 +1,69 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2008 Richard Hughes <richard at hughsie.com>
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#if !defined (__ZIF_H_INSIDE__) && !defined (ZIF_COMPILATION)
+#error "Only <zif.h> can be included directly."
+#endif
+
+#ifndef __ZIF_PACKAGE_REMOTE_H
+#define __ZIF_PACKAGE_REMOTE_H
+
+#include <glib-object.h>
+
+#include "zif-package.h"
+
+G_BEGIN_DECLS
+
+#define ZIF_TYPE_PACKAGE_REMOTE		(zif_package_remote_get_type ())
+#define ZIF_PACKAGE_REMOTE(o)		(G_TYPE_CHECK_INSTANCE_CAST ((o), ZIF_TYPE_PACKAGE_REMOTE, ZifPackageRemote))
+#define ZIF_PACKAGE_REMOTE_CLASS(k)	(G_TYPE_CHECK_CLASS_CAST((k), ZIF_TYPE_PACKAGE_REMOTE, ZifPackageRemoteClass))
+#define ZIF_IS_PACKAGE_REMOTE(o)	(G_TYPE_CHECK_INSTANCE_TYPE ((o), ZIF_TYPE_PACKAGE_REMOTE))
+#define ZIF_IS_PACKAGE_REMOTE_CLASS(k)	(G_TYPE_CHECK_CLASS_TYPE ((k), ZIF_TYPE_PACKAGE_REMOTE))
+#define ZIF_PACKAGE_REMOTE_GET_CLASS(o)	(G_TYPE_INSTANCE_GET_CLASS ((o), ZIF_TYPE_PACKAGE_REMOTE, ZifPackageRemoteClass))
+
+typedef struct _ZifPackageRemote	ZifPackageRemote;
+typedef struct _ZifPackageRemotePrivate	ZifPackageRemotePrivate;
+typedef struct _ZifPackageRemoteClass	ZifPackageRemoteClass;
+
+struct _ZifPackageRemote
+{
+	ZifPackage		 parent;
+	ZifPackageRemotePrivate	*priv;
+};
+
+struct _ZifPackageRemoteClass
+{
+	ZifPackageClass		 parent_class;
+};
+
+GType			 zif_package_remote_get_type		(void);
+ZifPackageRemote	*zif_package_remote_new			(void);
+gboolean		 zif_package_remote_set_from_repo	(ZifPackageRemote *pkg,
+								 guint		 length,
+								 gchar		**type,
+								 gchar		**data,
+								 const gchar	*repo_id,
+								 GError		**error);
+
+G_END_DECLS
+
+#endif /* __ZIF_PACKAGE_REMOTE_H */
+
diff --git a/backends/yum/libzif/zif-package.c b/backends/yum/libzif/zif-package.c
new file mode 100644
index 0000000..c36ee3e
--- /dev/null
+++ b/backends/yum/libzif/zif-package.c
@@ -0,0 +1,1188 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2008 Richard Hughes <richard at hughsie.com>
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+/**
+ * SECTION:zif-package
+ * @short_description: Generic object to represent an installed or remote package.
+ *
+ * This object is subclassed by #ZifPackageLocal and #ZifPackageRemote.
+ */
+
+#ifdef HAVE_CONFIG_H
+#  include <config.h>
+#endif
+
+#include <glib.h>
+#include <string.h>
+#include <stdlib.h>
+#include <packagekit-glib2/packagekit.h>
+
+#include "egg-debug.h"
+
+#include "zif-depend.h"
+#include "zif-utils.h"
+#include "zif-config.h"
+#include "zif-package.h"
+#include "zif-repos.h"
+#include "zif-groups.h"
+#include "zif-string.h"
+
+#define ZIF_PACKAGE_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), ZIF_TYPE_PACKAGE, ZifPackagePrivate))
+
+struct _ZifPackagePrivate
+{
+	ZifConfig		*config;
+	ZifGroups		*groups;
+	ZifRepos		*repos;
+	gchar			**package_id_split;
+	gchar			*package_id;
+	ZifString		*summary;
+	ZifString		*description;
+	ZifString		*license;
+	ZifString		*url;
+	ZifString		*category;
+	ZifString		*location_href;
+	PkGroupEnum		 group;
+	guint64			 size;
+	GPtrArray		*files;
+	GPtrArray		*requires;
+	GPtrArray		*provides;
+	gboolean		 installed;
+};
+
+G_DEFINE_TYPE (ZifPackage, zif_package, G_TYPE_OBJECT)
+
+/**
+ * zif_package_compare:
+ * @a: the first package to compare
+ * @b: the second package to compare
+ *
+ * Compares one package versions against each other.
+ *
+ * Return value: 1 for a>b, 0 for a==b, -1 for b>a
+ **/
+gint
+zif_package_compare (ZifPackage *a, ZifPackage *b)
+{
+	const gchar *package_ida;
+	const gchar *package_idb;
+	gchar **splita;
+	gchar **splitb;
+	gint val = 0;
+
+	g_return_val_if_fail (ZIF_IS_PACKAGE (a), 0);
+	g_return_val_if_fail (ZIF_IS_PACKAGE (b), 0);
+
+	/* shallow copy */
+	package_ida = zif_package_get_id (a);
+	package_idb = zif_package_get_id (b);
+	splita = pk_package_id_split (package_ida);
+	splitb = pk_package_id_split (package_idb);
+
+	/* check name the same */
+	if (g_strcmp0 (splita[PK_PACKAGE_ID_NAME], splitb[PK_PACKAGE_ID_NAME]) != 0) {
+		egg_warning ("comparing between %s and %s", package_ida, package_idb);
+		goto out;
+	}
+
+	/* do a version compare */
+	val = zif_compare_evr (splita[PK_PACKAGE_ID_VERSION], splitb[PK_PACKAGE_ID_VERSION]);
+out:
+	g_strfreev (splita);
+	g_strfreev (splitb);
+	return val;
+}
+
+/**
+ * zif_package_array_get_newest:
+ * @array: array of %ZifPackage's
+ * @error: a #GError which is used on failure, or %NULL
+ *
+ * Returns the newest package from a list.
+ *
+ * Return value: a single %ZifPackage, or %NULL in the case of an error
+ **/
+ZifPackage *
+zif_package_array_get_newest (GPtrArray *array, GError **error)
+{
+	ZifPackage *package_newest;
+	ZifPackage *package = NULL;
+	guint i;
+	gint retval;
+
+	/* no results */
+	if (array->len == 0) {
+		if (error != NULL)
+			*error = g_error_new (1, 0, "nothing in array");
+		goto out;
+	}
+
+	/* start with the first package being the newest */
+	package_newest = g_ptr_array_index (array, 0);
+
+	/* find newest in rest of the array */
+	for (i=1; i<array->len; i++) {
+		package = g_ptr_array_index (array, i);
+		retval = zif_package_compare (package, package_newest);
+		if (retval > 0)
+			package_newest = package;
+	}
+
+	/* return reference so we can unref the list */
+	package = g_object_ref (package_newest);
+out:
+	return package;
+}
+
+/**
+ * zif_package_download:
+ * @package: the #ZifPackage object
+ * @directory: the local directory to save to
+ * @cancellable: a #GCancellable which is used to cancel tasks, or %NULL
+ * @completion: a #ZifCompletion to use for progress reporting
+ * @error: a #GError which is used on failure, or %NULL
+ *
+ * Downloads a package.
+ *
+ * Return value: %TRUE for success, %FALSE for failure
+ **/
+gboolean
+zif_package_download (ZifPackage *package, const gchar *directory, GCancellable *cancellable, ZifCompletion *completion, GError **error)
+{
+	gboolean ret = FALSE;
+	ZifStoreRemote *repo = NULL;
+	GError *error_local = NULL;
+	ZifCompletion *completion_local = NULL;
+
+	g_return_val_if_fail (ZIF_IS_PACKAGE (package), FALSE);
+	g_return_val_if_fail (directory != NULL, FALSE);
+	g_return_val_if_fail (package->priv->package_id_split != NULL, FALSE);
+
+	/* check we are not installed */
+	if (package->priv->installed) {
+		if (error != NULL)
+			*error = g_error_new (1, 0, "cannot download installed packages");
+		goto out;
+	}
+
+	/* two steps, TODO: the second will take longer than the first */
+	zif_completion_set_number_steps (completion, 2);
+
+	/* find correct repo */
+	completion_local = zif_completion_get_child (completion);
+	repo = zif_repos_get_store (package->priv->repos, package->priv->package_id_split[PK_PACKAGE_ID_DATA], cancellable, completion_local, &error_local);
+	if (repo == NULL) {
+		if (error != NULL)
+			*error = g_error_new (1, 0, "cannot find remote repo: %s", error_local->message);
+		g_error_free (error_local);
+		goto out;
+	}
+
+	/* this section done */
+	zif_completion_done (completion);
+
+	/* create a chain of completions */
+	completion_local = zif_completion_get_child (completion);
+
+	/* download from the repo */
+	ret = zif_store_remote_download (repo, zif_string_get_value (package->priv->location_href), directory, cancellable, completion_local, &error_local);
+	if (!ret) {
+		if (error != NULL)
+			*error = g_error_new (1, 0, "cannot download from repo: %s", error_local->message);
+		g_error_free (error_local);
+		goto out;
+	}
+
+	/* this section done */
+	zif_completion_done (completion);
+out:
+	if (repo != NULL)
+		g_object_unref (repo);
+	return ret;
+}
+
+/**
+ * zif_package_print:
+ * @package: the #ZifPackage object
+ *
+ * Prints details about a package to %STDOUT.
+ **/
+void
+zif_package_print (ZifPackage *package)
+{
+	guint i;
+	gchar *text;
+	const ZifDepend *depend;
+	GPtrArray *array;
+
+	g_return_if_fail (ZIF_IS_PACKAGE (package));
+	g_return_if_fail (package->priv->package_id_split != NULL);
+
+	g_print ("id=%s\n", package->priv->package_id);
+	g_print ("summary=%s\n", zif_string_get_value (package->priv->summary));
+	g_print ("description=%s\n", zif_string_get_value (package->priv->description));
+	g_print ("license=%s\n", zif_string_get_value (package->priv->license));
+	g_print ("group=%s\n", pk_group_enum_to_text (package->priv->group));
+	g_print ("category=%s\n", zif_string_get_value (package->priv->category));
+	if (package->priv->url != NULL)
+		g_print ("url=%s\n", zif_string_get_value (package->priv->url));
+	g_print ("size=%"G_GUINT64_FORMAT"\n", package->priv->size);
+
+	if (package->priv->files != NULL) {
+		g_print ("files:\n");
+		array = package->priv->files;
+		for (i=0; i<array->len; i++)
+			g_print ("\t%s\n", (const gchar *) g_ptr_array_index (array, i));
+	}
+	if (package->priv->requires != NULL) {
+		g_print ("requires:\n");
+		array = package->priv->requires;
+		for (i=0; i<array->len; i++) {
+			depend = g_ptr_array_index (array, i);
+			text = zif_depend_to_string (depend);
+			g_print ("\t%s\n", text);
+			g_free (text);
+		}
+	}
+	if (package->priv->provides != NULL) {
+		g_print ("provides:\n");
+		array = package->priv->provides;
+		for (i=0; i<array->len; i++) {
+			depend = g_ptr_array_index (array, i);
+			text = zif_depend_to_string (depend);
+			g_print ("\t%s\n", text);
+			g_free (text);
+		}
+	}
+}
+
+/**
+ * zif_package_is_devel:
+ * @package: the #ZifPackage object
+ *
+ * Finds out if a package is a development package.
+ *
+ * Return value: %TRUE or %FALSE
+ **/
+gboolean
+zif_package_is_devel (ZifPackage *package)
+{
+	g_return_val_if_fail (ZIF_IS_PACKAGE (package), FALSE);
+	g_return_val_if_fail (package->priv->package_id_split != NULL, FALSE);
+
+	if (g_str_has_suffix (package->priv->package_id_split[PK_PACKAGE_ID_NAME], "-debuginfo"))
+		return TRUE;
+	if (g_str_has_suffix (package->priv->package_id_split[PK_PACKAGE_ID_NAME], "-devel"))
+		return TRUE;
+	if (g_str_has_suffix (package->priv->package_id_split[PK_PACKAGE_ID_NAME], "-static"))
+		return TRUE;
+	if (g_str_has_suffix (package->priv->package_id_split[PK_PACKAGE_ID_NAME], "-libs"))
+		return TRUE;
+	return FALSE;
+}
+
+/**
+ * zif_package_is_gui:
+ * @package: the #ZifPackage object
+ *
+ * Finds out if a package is a GUI package.
+ *
+ * Return value: %TRUE or %FALSE
+ **/
+gboolean
+zif_package_is_gui (ZifPackage *package)
+{
+	guint i;
+	const ZifDepend *depend;
+	GPtrArray *array;
+
+	g_return_val_if_fail (ZIF_IS_PACKAGE (package), FALSE);
+	g_return_val_if_fail (package->priv->package_id_split != NULL, FALSE);
+
+	/* get list of requires */
+	array = zif_package_get_requires (package, NULL);
+	if (array == NULL)
+		goto out;
+	for (i=0; i<array->len; i++) {
+		depend = g_ptr_array_index (array, i);
+		if (g_strstr_len (depend->name, -1, "gtk") != NULL)
+			return TRUE;
+		if (g_strstr_len (depend->name, -1, "kde") != NULL)
+			return TRUE;
+	}
+	g_ptr_array_unref (array);
+out:
+	return FALSE;
+}
+
+/**
+ * zif_package_is_installed:
+ * @package: the #ZifPackage object
+ *
+ * Finds out if a package is installed.
+ *
+ * Return value: %TRUE or %FALSE
+ **/
+gboolean
+zif_package_is_installed (ZifPackage *package)
+{
+	g_return_val_if_fail (ZIF_IS_PACKAGE (package), FALSE);
+	g_return_val_if_fail (package->priv->package_id_split != NULL, FALSE);
+	return package->priv->installed;
+}
+
+/**
+ * zif_package_is_native:
+ * @package: the #ZifPackage object
+ *
+ * Finds out if a package is the native architecture for the system.
+ *
+ * Return value: %TRUE or %FALSE
+ **/
+gboolean
+zif_package_is_native (ZifPackage *package)
+{
+	gchar **array;
+	guint i;
+	const gchar *arch;
+	gboolean ret = FALSE;
+
+	g_return_val_if_fail (ZIF_IS_PACKAGE (package), FALSE);
+	g_return_val_if_fail (package->priv->package_id_split != NULL, FALSE);
+
+	/* is package in arch array */
+	arch = package->priv->package_id_split[PK_PACKAGE_ID_ARCH];
+	array = zif_config_get_basearch_array (package->priv->config);
+	for (i=0; array[i] != NULL; i++) {
+		if (g_strcmp0 (array[i], arch) == 0) {
+			ret = TRUE;
+			break;
+		}
+	}
+	return ret;
+}
+
+/**
+ * zif_package_is_free:
+ * @package: the #ZifPackage object
+ *
+ * Check the string license_text for free licenses, indicated by
+ * their short names as documented at
+ * http://fedoraproject.org/wiki/Licensing
+ *
+ * Licenses can be grouped by " or " to indicate that the package
+ * can be redistributed under any of the licenses in the group.
+ * For instance: GPLv2+ or Artistic or FooLicense.
+ *
+ * Also, if a license ends with "+", the "+" is removed before
+ * comparing it to the list of valid licenses.  So if license
+ * "FooLicense" is free, then "FooLicense+" is considered free.
+ *
+ * Groups of licenses can be grouped with " and " to indicate
+ * that parts of the package are distributed under one group of
+ * licenses, while other parts of the package are distributed
+ * under another group.  Groups may be wrapped in parenthesis.
+ * For instance:
+ * (GPLv2+ or Artistic) and (GPL+ or Artistic) and FooLicense.
+ *
+ * At least one license in each group must be free for the
+ * package to be considered Free Software.  If the license_text
+ * is empty, the package is considered non-free.
+ *
+ * Return value: %TRUE or %FALSE
+ **/
+gboolean
+zif_package_is_free (ZifPackage *package)
+{
+	gboolean one_free_group = FALSE;
+	gboolean group_is_free;
+	gchar **groups;
+	gchar **licenses;
+	guint i;
+	guint j;
+
+	g_return_val_if_fail (ZIF_IS_PACKAGE (package), FALSE);
+	g_return_val_if_fail (package->priv->package_id_split != NULL, FALSE);
+
+	/* split AND clase */
+	groups = g_strsplit (zif_string_get_value (package->priv->license), " and ", 0);
+	for (i=0; groups[i] != NULL; i++) {
+		/* remove grouping */
+		g_strdelimit (groups[i], "()", ' ');
+
+		/* split OR clase */
+		licenses = g_strsplit (groups[i], " or ", 0);
+
+		group_is_free = FALSE;
+		for (j=0; licenses[j] != NULL; j++) {
+
+			/* remove 'and later' */
+			g_strdelimit (licenses[j], "+", ' ');
+			g_strstrip (licenses[j]);
+
+			/* nothing to process */
+			if (licenses[j][0] == '\0')
+				continue;
+
+			/* a valid free license */
+			if (pk_license_enum_from_text (licenses[j]) != PK_LICENSE_ENUM_UNKNOWN) {
+				one_free_group = TRUE;
+				group_is_free = TRUE;
+				break;
+			}
+		}
+		g_strfreev (licenses);
+
+		if (!group_is_free)
+			return FALSE;
+	}
+	g_strfreev (groups);
+
+	if (!one_free_group)
+		return FALSE;
+
+	return TRUE;
+}
+
+/**
+ * zif_package_get_id:
+ * @package: the #ZifPackage object
+ *
+ * Gets the id uniquely identifying the package in all repos.
+ *
+ * Return value: the PackageId representing the package.
+ **/
+const gchar *
+zif_package_get_id (ZifPackage *package)
+{
+	g_return_val_if_fail (ZIF_IS_PACKAGE (package), NULL);
+	g_return_val_if_fail (package->priv->package_id != NULL, NULL);
+	return package->priv->package_id;
+}
+
+/**
+ * zif_package_get_package_id:
+ * @package: the #ZifPackage object
+ *
+ * Gets the id (as text) uniquely identifying the package in all repos.
+ *
+ * Return value: The %package_id representing the package.
+ **/
+const gchar *
+zif_package_get_package_id (ZifPackage *package)
+{
+	g_return_val_if_fail (ZIF_IS_PACKAGE (package), NULL);
+	g_return_val_if_fail (package->priv->package_id_split != NULL, NULL);
+	return package->priv->package_id;
+}
+
+/**
+ * zif_package_ensure_data:
+ **/
+static gboolean
+zif_package_ensure_data (ZifPackage *package, ZifPackageEnsureType type, GError **error)
+{
+	ZifPackageClass *klass = ZIF_PACKAGE_GET_CLASS (package);
+
+	g_return_val_if_fail (ZIF_IS_PACKAGE (package), FALSE);
+
+	/* no support */
+	if (klass->ensure_data == NULL)
+		return TRUE;
+
+	return klass->ensure_data (package, type, error);
+}
+
+/**
+ * zif_package_get_summary:
+ * @package: the #ZifPackage object
+ * @error: a #GError which is used on failure, or %NULL
+ *
+ * Gets the package summary.
+ *
+ * Return value: the reference counted #ZifString or %NULL, use zif_string_unref() when done
+ **/
+ZifString *
+zif_package_get_summary (ZifPackage *package, GError **error)
+{
+	gboolean ret;
+
+	g_return_val_if_fail (ZIF_IS_PACKAGE (package), NULL);
+	g_return_val_if_fail (package->priv->package_id_split != NULL, NULL);
+
+	/* not exists */
+	if (package->priv->summary == NULL) {
+		ret = zif_package_ensure_data (package, ZIF_PACKAGE_ENSURE_TYPE_SUMMARY, error);
+		if (!ret)
+			return NULL;
+	}
+
+	/* return refcounted */
+	return zif_string_ref (package->priv->summary);
+}
+
+/**
+ * zif_package_get_description:
+ * @package: the #ZifPackage object
+ * @error: a #GError which is used on failure, or %NULL
+ *
+ * Gets the package description.
+ *
+ * Return value: the reference counted #ZifString or %NULL, use zif_string_unref() when done
+ **/
+ZifString *
+zif_package_get_description (ZifPackage *package, GError **error)
+{
+	gboolean ret;
+
+	g_return_val_if_fail (ZIF_IS_PACKAGE (package), NULL);
+	g_return_val_if_fail (package->priv->package_id_split != NULL, NULL);
+
+	/* not exists */
+	if (package->priv->description == NULL) {
+		ret = zif_package_ensure_data (package, ZIF_PACKAGE_ENSURE_TYPE_DESCRIPTION, error);
+		if (!ret)
+			return NULL;
+	}
+
+	/* return refcounted */
+	return zif_string_ref (package->priv->description);
+}
+
+/**
+ * zif_package_get_license:
+ * @package: the #ZifPackage object
+ * @error: a #GError which is used on failure, or %NULL
+ *
+ * Gets the package licence.
+ *
+ * Return value: the reference counted #ZifString or %NULL, use zif_string_unref() when done
+ **/
+ZifString *
+zif_package_get_license (ZifPackage *package, GError **error)
+{
+	gboolean ret;
+
+	g_return_val_if_fail (ZIF_IS_PACKAGE (package), NULL);
+	g_return_val_if_fail (package->priv->package_id_split != NULL, NULL);
+
+	/* not exists */
+	if (package->priv->license == NULL) {
+		ret = zif_package_ensure_data (package, ZIF_PACKAGE_ENSURE_TYPE_LICENCE, error);
+		if (!ret)
+			return NULL;
+	}
+
+	/* return refcounted */
+	return zif_string_ref (package->priv->license);
+}
+
+/**
+ * zif_package_get_url:
+ * @package: the #ZifPackage object
+ * @error: a #GError which is used on failure, or %NULL
+ *
+ * Gets the homepage URL for the package.
+ *
+ * Return value: the reference counted #ZifString or %NULL, use zif_string_unref() when done
+ **/
+ZifString *
+zif_package_get_url (ZifPackage *package, GError **error)
+{
+	gboolean ret;
+
+	g_return_val_if_fail (ZIF_IS_PACKAGE (package), NULL);
+	g_return_val_if_fail (package->priv->package_id_split != NULL, NULL);
+
+	/* not exists */
+	if (package->priv->url == NULL) {
+		ret = zif_package_ensure_data (package, ZIF_PACKAGE_ENSURE_TYPE_URL, error);
+		if (!ret)
+			return NULL;
+	}
+
+	/* return refcounted */
+	return zif_string_ref (package->priv->url);
+}
+
+/**
+ * zif_package_get_filename:
+ * @package: the #ZifPackage object
+ * @error: a #GError which is used on failure, or %NULL
+ *
+ * Gets the remote filename for the package, e.g. Packages/net-snmp-5.4.2-3.fc10.i386.rpm
+ *
+ * Return value: the reference counted #ZifString or %NULL, use zif_string_unref() when done
+ **/
+ZifString *
+zif_package_get_filename (ZifPackage *package, GError **error)
+{
+	g_return_val_if_fail (ZIF_IS_PACKAGE (package), NULL);
+	g_return_val_if_fail (package->priv->package_id_split != NULL, NULL);
+
+	/* not exists */
+	if (package->priv->location_href == NULL) {
+		if (error != NULL)
+			*error = g_error_new (1, 0, "no data for %s", package->priv->package_id_split[PK_PACKAGE_ID_NAME]);
+		return NULL;
+	}
+
+	/* return refcounted */
+	return zif_string_ref (package->priv->location_href);
+}
+
+/**
+ * zif_package_get_category:
+ * @package: the #ZifPackage object
+ * @error: a #GError which is used on failure, or %NULL
+ *
+ * Gets the category the packag is in.
+ *
+ * Return value: the reference counted #ZifString or %NULL, use zif_string_unref() when done
+ **/
+ZifString *
+zif_package_get_category (ZifPackage *package, GError **error)
+{
+	gboolean ret;
+
+	g_return_val_if_fail (ZIF_IS_PACKAGE (package), NULL);
+	g_return_val_if_fail (package->priv->package_id_split != NULL, NULL);
+
+	/* not exists */
+	if (package->priv->category == NULL) {
+		ret = zif_package_ensure_data (package, ZIF_PACKAGE_ENSURE_TYPE_GROUP, error);
+		if (!ret)
+			return NULL;
+	}
+
+	/* return refcounted */
+	return zif_string_ref (package->priv->category);
+}
+
+/**
+ * zif_package_get_group:
+ * @package: the #ZifPackage object
+ * @error: a #GError which is used on failure, or %NULL
+ *
+ * Gets the package group.
+ *
+ * Return value: %TRUE for success, %FALSE for failure
+ **/
+PkGroupEnum
+zif_package_get_group (ZifPackage *package, GError **error)
+{
+	gboolean ret;
+
+	/* not exists */
+	if (package->priv->group == PK_GROUP_ENUM_UNKNOWN) {
+		ret = zif_package_ensure_data (package, ZIF_PACKAGE_ENSURE_TYPE_FILES, error);
+		if (!ret)
+			return PK_GROUP_ENUM_UNKNOWN;
+	}
+
+	g_return_val_if_fail (ZIF_IS_PACKAGE (package), PK_GROUP_ENUM_UNKNOWN);
+	g_return_val_if_fail (package->priv->package_id_split != NULL, PK_GROUP_ENUM_UNKNOWN);
+	return package->priv->group;
+}
+
+/**
+ * zif_package_get_size:
+ * @package: the #ZifPackage object
+ * @error: a #GError which is used on failure, or %NULL
+ *
+ * Gets the size of the package.
+ * This is the installed size for installed packages, and the download size for
+ * remote packages.
+ *
+ * Return value: %TRUE for success, %FALSE for failure
+ **/
+guint64
+zif_package_get_size (ZifPackage *package, GError **error)
+{
+	gboolean ret;
+
+	if (package->priv->size == 0) {
+		ret = zif_package_ensure_data (package, ZIF_PACKAGE_ENSURE_TYPE_SIZE, error);
+		if (!ret)
+			return 0;
+	}
+
+	g_return_val_if_fail (ZIF_IS_PACKAGE (package), 0);
+	g_return_val_if_fail (package->priv->package_id_split != NULL, 0);
+	return package->priv->size;
+}
+
+/**
+ * zif_package_get_files:
+ * @package: the #ZifPackage object
+ * @error: a #GError which is used on failure, or %NULL
+ *
+ * Gets the file list for the package.
+ *
+ * Return value: the reference counted #GPtrArray, use g_ptr_array_unref() when done
+ **/
+GPtrArray *
+zif_package_get_files (ZifPackage *package, GError **error)
+{
+	gboolean ret;
+
+	g_return_val_if_fail (ZIF_IS_PACKAGE (package), NULL);
+	g_return_val_if_fail (package->priv->package_id_split != NULL, NULL);
+
+	/* not exists */
+	if (package->priv->files == NULL) {
+		ret = zif_package_ensure_data (package, ZIF_PACKAGE_ENSURE_TYPE_FILES, error);
+		if (!ret)
+			return NULL;
+	}
+
+	/* return refcounted */
+	return g_ptr_array_ref (package->priv->files);
+}
+
+/**
+ * zif_package_get_requires:
+ * @package: the #ZifPackage object
+ * @error: a #GError which is used on failure, or %NULL
+ *
+ * Gets all the package requires.
+ *
+ * Return value: the reference counted #GPtrArray, use g_ptr_array_unref() when done
+ **/
+GPtrArray *
+zif_package_get_requires (ZifPackage *package, GError **error)
+{
+	gboolean ret;
+
+	g_return_val_if_fail (ZIF_IS_PACKAGE (package), NULL);
+	g_return_val_if_fail (package->priv->package_id_split != NULL, NULL);
+
+	/* not exists */
+	if (package->priv->requires == NULL) {
+		ret = zif_package_ensure_data (package, ZIF_PACKAGE_ENSURE_TYPE_REQUIRES, error);
+		if (!ret)
+			return NULL;
+	}
+
+	/* return refcounted */
+	return g_ptr_array_ref (package->priv->requires);
+}
+
+/**
+ * zif_package_get_provides:
+ * @package: the #ZifPackage object
+ * @error: a #GError which is used on failure, or %NULL
+ *
+ * Get all the package provides.
+ *
+ * Return value: the reference counted #GPtrArray, use g_ptr_array_unref() when done
+ **/
+GPtrArray *
+zif_package_get_provides (ZifPackage *package, GError **error)
+{
+	gboolean ret;
+
+	g_return_val_if_fail (ZIF_IS_PACKAGE (package), NULL);
+	g_return_val_if_fail (package->priv->package_id_split != NULL, NULL);
+
+	/* not exists */
+	if (package->priv->requires == NULL) {
+		ret = zif_package_ensure_data (package, ZIF_PACKAGE_ENSURE_TYPE_PROVIDES, error);
+		if (!ret)
+			return NULL;
+	}
+
+	/* return refcounted */
+	return g_ptr_array_ref (package->priv->provides);
+}
+
+/**
+ * zif_package_set_installed:
+ * @package: the #ZifPackage object
+ * @installed: If the package is installed
+ *
+ * Sets the package installed status.
+ *
+ * Return value: %TRUE for success, %FALSE for failure
+ **/
+gboolean
+zif_package_set_installed (ZifPackage *package, gboolean installed)
+{
+	g_return_val_if_fail (ZIF_IS_PACKAGE (package), FALSE);
+	package->priv->installed = installed;
+	return TRUE;
+}
+
+/**
+ * zif_package_set_id:
+ * @package: the #ZifPackage object
+ * @package_id: A PackageId defining the object
+ *
+ * Sets the unique id for the package.
+ *
+ * Return value: %TRUE for success, %FALSE for failure
+ **/
+gboolean
+zif_package_set_id (ZifPackage *package, const gchar *package_id)
+{
+	g_return_val_if_fail (ZIF_IS_PACKAGE (package), FALSE);
+	g_return_val_if_fail (package_id != NULL, FALSE);
+	g_return_val_if_fail (package->priv->package_id == NULL, FALSE);
+
+	package->priv->package_id = g_strdup (package_id);
+	package->priv->package_id_split = pk_package_id_split (package_id);
+	return TRUE;
+}
+
+/**
+ * zif_package_set_summary:
+ * @package: the #ZifPackage object
+ * @summary: the package summary
+ *
+ * Sets the package summary.
+ *
+ * Return value: %TRUE for success, %FALSE for failure
+ **/
+gboolean
+zif_package_set_summary (ZifPackage *package, ZifString *summary)
+{
+	g_return_val_if_fail (ZIF_IS_PACKAGE (package), FALSE);
+	g_return_val_if_fail (summary != NULL, FALSE);
+	g_return_val_if_fail (package->priv->summary == NULL, FALSE);
+
+	package->priv->summary = zif_string_ref (summary);
+	return TRUE;
+}
+
+/**
+ * zif_package_set_description:
+ * @package: the #ZifPackage object
+ * @description: the package description
+ *
+ * Sets the package description.
+ *
+ * Return value: %TRUE for success, %FALSE for failure
+ **/
+gboolean
+zif_package_set_description (ZifPackage *package, ZifString *description)
+{
+	g_return_val_if_fail (ZIF_IS_PACKAGE (package), FALSE);
+	g_return_val_if_fail (description != NULL, FALSE);
+	g_return_val_if_fail (package->priv->description == NULL, FALSE);
+
+	package->priv->description = zif_string_ref (description);
+	return TRUE;
+}
+
+/**
+ * zif_package_set_license:
+ * @package: the #ZifPackage object
+ * @license: license
+ *
+ * Sets the package license.
+ *
+ * Return value: %TRUE for success, %FALSE for failure
+ **/
+gboolean
+zif_package_set_license (ZifPackage *package, ZifString *license)
+{
+	g_return_val_if_fail (ZIF_IS_PACKAGE (package), FALSE);
+	g_return_val_if_fail (license != NULL, FALSE);
+	g_return_val_if_fail (package->priv->license == NULL, FALSE);
+
+	package->priv->license = zif_string_ref (license);
+	return TRUE;
+}
+
+/**
+ * zif_package_set_url:
+ * @package: the #ZifPackage object
+ * @url: The package homepage URL
+ *
+ * Sets the project homepage URL.
+ *
+ * Return value: %TRUE for success, %FALSE for failure
+ **/
+gboolean
+zif_package_set_url (ZifPackage *package, ZifString *url)
+{
+	g_return_val_if_fail (ZIF_IS_PACKAGE (package), FALSE);
+	g_return_val_if_fail (url != NULL, FALSE);
+	g_return_val_if_fail (package->priv->url == NULL, FALSE);
+
+	package->priv->url = zif_string_ref (url);
+	return TRUE;
+}
+
+/**
+ * zif_package_set_location_href:
+ * @package: the #ZifPackage object
+ * @location_href: the remote download filename
+ *
+ * Sets the remote download location.
+ *
+ * Return value: %TRUE for success, %FALSE for failure
+ **/
+gboolean
+zif_package_set_location_href (ZifPackage *package, ZifString *location_href)
+{
+	g_return_val_if_fail (ZIF_IS_PACKAGE (package), FALSE);
+	g_return_val_if_fail (location_href != NULL, FALSE);
+	g_return_val_if_fail (package->priv->location_href == NULL, FALSE);
+
+	package->priv->location_href = zif_string_ref (location_href);
+	return TRUE;
+}
+
+/**
+ * zif_package_set_category:
+ * @package: the #ZifPackage object
+ * @category: category
+ *
+ * Sets the package category.
+ *
+ * Return value: %TRUE for success, %FALSE for failure
+ **/
+gboolean
+zif_package_set_category (ZifPackage *package, ZifString *category)
+{
+	g_return_val_if_fail (ZIF_IS_PACKAGE (package), FALSE);
+	g_return_val_if_fail (category != NULL, FALSE);
+	g_return_val_if_fail (package->priv->category == NULL, FALSE);
+
+	package->priv->category = zif_string_ref (category);
+	return TRUE;
+}
+
+/**
+ * zif_package_set_group:
+ * @package: the #ZifPackage object
+ * @group: the package group
+ *
+ * Sets the package group.
+ *
+ * Return value: %TRUE for success, %FALSE for failure
+ **/
+gboolean
+zif_package_set_group (ZifPackage *package, PkGroupEnum group)
+{
+	g_return_val_if_fail (ZIF_IS_PACKAGE (package), FALSE);
+	g_return_val_if_fail (group != PK_GROUP_ENUM_UNKNOWN, FALSE);
+	g_return_val_if_fail (package->priv->group == PK_GROUP_ENUM_UNKNOWN, FALSE);
+
+	package->priv->group = group;
+	return TRUE;
+}
+
+/**
+ * zif_package_set_size:
+ * @package: the #ZifPackage object
+ * @size: the package size in bytes
+ *
+ * Sets the package size in bytes.
+ *
+ * Return value: %TRUE for success, %FALSE for failure
+ **/
+gboolean
+zif_package_set_size (ZifPackage *package, guint64 size)
+{
+	g_return_val_if_fail (ZIF_IS_PACKAGE (package), FALSE);
+	g_return_val_if_fail (size != 0, FALSE);
+	g_return_val_if_fail (package->priv->size == 0, FALSE);
+
+	package->priv->size = size;
+	return TRUE;
+}
+
+/**
+ * zif_package_set_files:
+ * @package: the #ZifPackage object
+ * @files: the package filelist
+ *
+ * Sets the package file list.
+ *
+ * Return value: %TRUE for success, %FALSE for failure
+ **/
+gboolean
+zif_package_set_files (ZifPackage *package, GPtrArray *files)
+{
+	g_return_val_if_fail (ZIF_IS_PACKAGE (package), FALSE);
+	g_return_val_if_fail (files != NULL, FALSE);
+	g_return_val_if_fail (package->priv->files == NULL, FALSE);
+
+	package->priv->files = g_ptr_array_ref (files);
+	return TRUE;
+}
+
+/**
+ * zif_package_set_requires:
+ * @package: the #ZifPackage object
+ * @requires: the package requires
+ *
+ * Sets the package requires.
+ *
+ * Return value: %TRUE for success, %FALSE for failure
+ **/
+gboolean
+zif_package_set_requires (ZifPackage *package, GPtrArray *requires)
+{
+	g_return_val_if_fail (ZIF_IS_PACKAGE (package), FALSE);
+	g_return_val_if_fail (requires != NULL, FALSE);
+	g_return_val_if_fail (package->priv->requires == NULL, FALSE);
+
+	package->priv->requires = g_ptr_array_ref (requires);
+	return TRUE;
+}
+
+/**
+ * zif_package_set_provides:
+ * @package: the #ZifPackage object
+ * @provides: the package provides
+ *
+ * Sets the package provides
+ *
+ * Return value: %TRUE for success, %FALSE for failure
+ **/
+gboolean
+zif_package_set_provides (ZifPackage *package, GPtrArray *provides)
+{
+	g_return_val_if_fail (ZIF_IS_PACKAGE (package), FALSE);
+	g_return_val_if_fail (provides != NULL, FALSE);
+	g_return_val_if_fail (package->priv->provides == NULL, FALSE);
+
+	package->priv->provides = g_ptr_array_ref (provides);
+	return TRUE;
+}
+
+/**
+ * zif_package_finalize:
+ **/
+static void
+zif_package_finalize (GObject *object)
+{
+	ZifPackage *package;
+
+	g_return_if_fail (object != NULL);
+	g_return_if_fail (ZIF_IS_PACKAGE (object));
+	package = ZIF_PACKAGE (object);
+
+	g_free (package->priv->package_id_split);
+	g_free (package->priv->package_id);
+	if (package->priv->summary != NULL)
+		zif_string_unref (package->priv->summary);
+	if (package->priv->description != NULL)
+		zif_string_unref (package->priv->description);
+	if (package->priv->license != NULL)
+		zif_string_unref (package->priv->license);
+	if (package->priv->url != NULL)
+		zif_string_unref (package->priv->url);
+	if (package->priv->category != NULL)
+		zif_string_unref (package->priv->category);
+	if (package->priv->location_href != NULL)
+		zif_string_unref (package->priv->location_href);
+	if (package->priv->files != NULL)
+		g_ptr_array_unref (package->priv->files);
+	if (package->priv->requires != NULL)
+		g_ptr_array_unref (package->priv->requires);
+	if (package->priv->provides != NULL)
+		g_ptr_array_unref (package->priv->provides);
+	g_object_unref (package->priv->repos);
+	g_object_unref (package->priv->groups);
+	g_object_unref (package->priv->config);
+
+	G_OBJECT_CLASS (zif_package_parent_class)->finalize (object);
+}
+
+/**
+ * zif_package_class_init:
+ **/
+static void
+zif_package_class_init (ZifPackageClass *klass)
+{
+	GObjectClass *object_class = G_OBJECT_CLASS (klass);
+	object_class->finalize = zif_package_finalize;
+	g_type_class_add_private (klass, sizeof (ZifPackagePrivate));
+}
+
+/**
+ * zif_package_init:
+ **/
+static void
+zif_package_init (ZifPackage *package)
+{
+	package->priv = ZIF_PACKAGE_GET_PRIVATE (package);
+	package->priv->package_id_split = NULL;
+	package->priv->package_id = NULL;
+	package->priv->summary = NULL;
+	package->priv->description = NULL;
+	package->priv->license = NULL;
+	package->priv->url = NULL;
+	package->priv->category = NULL;
+	package->priv->files = NULL;
+	package->priv->requires = NULL;
+	package->priv->provides = NULL;
+	package->priv->location_href = NULL;
+	package->priv->installed = FALSE;
+	package->priv->group = PK_GROUP_ENUM_UNKNOWN;
+	package->priv->size = 0;
+	package->priv->repos = zif_repos_new ();
+	package->priv->groups = zif_groups_new ();
+	package->priv->config = zif_config_new ();
+}
+
+/**
+ * zif_package_new:
+ *
+ * Return value: A new #ZifPackage class instance.
+ **/
+ZifPackage *
+zif_package_new (void)
+{
+	ZifPackage *package;
+	package = g_object_new (ZIF_TYPE_PACKAGE, NULL);
+	return ZIF_PACKAGE (package);
+}
+
+/***************************************************************************
+ ***                          MAKE CHECK TESTS                           ***
+ ***************************************************************************/
+#ifdef EGG_TEST
+#include "egg-test.h"
+
+void
+zif_package_test (EggTest *test)
+{
+	ZifPackage *package;
+
+	if (!egg_test_start (test, "ZifPackage"))
+		return;
+
+	/************************************************************/
+	egg_test_title (test, "get package");
+	package = zif_package_new ();
+	egg_test_assert (test, package != NULL);
+
+	g_object_unref (package);
+
+	egg_test_end (test);
+}
+#endif
+
diff --git a/backends/yum/libzif/zif-package.h b/backends/yum/libzif/zif-package.h
new file mode 100644
index 0000000..d66c5b9
--- /dev/null
+++ b/backends/yum/libzif/zif-package.h
@@ -0,0 +1,156 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2008-2009 Richard Hughes <richard at hughsie.com>
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#if !defined (__ZIF_H_INSIDE__) && !defined (ZIF_COMPILATION)
+#error "Only <zif.h> can be included directly."
+#endif
+
+#ifndef __ZIF_PACKAGE_H
+#define __ZIF_PACKAGE_H
+
+#include <glib-object.h>
+#include <gio/gio.h>
+#include <packagekit-glib2/packagekit.h>
+
+#include "zif-string.h"
+#include "zif-completion.h"
+
+G_BEGIN_DECLS
+
+#define ZIF_TYPE_PACKAGE		(zif_package_get_type ())
+#define ZIF_PACKAGE(o)			(G_TYPE_CHECK_INSTANCE_CAST ((o), ZIF_TYPE_PACKAGE, ZifPackage))
+#define ZIF_PACKAGE_CLASS(k)		(G_TYPE_CHECK_CLASS_CAST((k), ZIF_TYPE_PACKAGE, ZifPackageClass))
+#define ZIF_IS_PACKAGE(o)		(G_TYPE_CHECK_INSTANCE_TYPE ((o), ZIF_TYPE_PACKAGE))
+#define ZIF_IS_PACKAGE_CLASS(k)		(G_TYPE_CHECK_CLASS_TYPE ((k), ZIF_TYPE_PACKAGE))
+#define ZIF_PACKAGE_GET_CLASS(o)	(G_TYPE_INSTANCE_GET_CLASS ((o), ZIF_TYPE_PACKAGE, ZifPackageClass))
+
+typedef struct _ZifPackage		ZifPackage;
+typedef struct _ZifPackagePrivate	ZifPackagePrivate;
+typedef struct _ZifPackageClass		ZifPackageClass;
+
+typedef enum {
+	ZIF_PACKAGE_ENSURE_TYPE_FILES,
+	ZIF_PACKAGE_ENSURE_TYPE_SUMMARY,
+	ZIF_PACKAGE_ENSURE_TYPE_LICENCE,
+	ZIF_PACKAGE_ENSURE_TYPE_DESCRIPTION,
+	ZIF_PACKAGE_ENSURE_TYPE_URL,
+	ZIF_PACKAGE_ENSURE_TYPE_SIZE,
+	ZIF_PACKAGE_ENSURE_TYPE_GROUP,
+	ZIF_PACKAGE_ENSURE_TYPE_REQUIRES,
+	ZIF_PACKAGE_ENSURE_TYPE_PROVIDES,
+	ZIF_PACKAGE_ENSURE_TYPE_CONFLICTS,
+	ZIF_PACKAGE_ENSURE_TYPE_OBSOLETES,
+	ZIF_PACKAGE_ENSURE_TYPE_LAST
+} ZifPackageEnsureType;
+
+struct _ZifPackage
+{
+	GObject			 parent;
+	ZifPackagePrivate	*priv;
+};
+
+struct _ZifPackageClass
+{
+	GObjectClass	parent_class;
+
+	/* vtable */
+	gboolean	 (*ensure_data)			(ZifPackage	*package,
+							 ZifPackageEnsureType type,
+							 GError		**error);
+};
+
+GType			 zif_package_get_type		(void);
+ZifPackage		*zif_package_new		(void);
+
+/* public getters */
+const gchar		*zif_package_get_id		(ZifPackage	*package);
+ZifString		*zif_package_get_summary	(ZifPackage	*package,
+							 GError		**error);
+ZifString		*zif_package_get_description	(ZifPackage	*package,
+							 GError		**error);
+ZifString		*zif_package_get_license	(ZifPackage	*package,
+							 GError		**error);
+ZifString		*zif_package_get_url		(ZifPackage	*package,
+							 GError		**error);
+ZifString		*zif_package_get_filename	(ZifPackage	*package,
+							 GError		**error);
+ZifString		*zif_package_get_category	(ZifPackage	*package,
+							 GError		**error);
+PkGroupEnum		 zif_package_get_group		(ZifPackage	*package,
+							 GError		**error);
+guint64			 zif_package_get_size		(ZifPackage	*package,
+							 GError		**error);
+GPtrArray		*zif_package_get_files		(ZifPackage	*package,
+							 GError		**error);
+GPtrArray		*zif_package_get_requires	(ZifPackage	*package,
+							 GError		**error);
+GPtrArray		*zif_package_get_provides	(ZifPackage	*package,
+							 GError		**error);
+
+/* internal setters: TODO, in seporate -internal header file */
+gboolean		 zif_package_set_installed	(ZifPackage	*package,
+							 gboolean	 installed);
+gboolean		 zif_package_set_id		(ZifPackage	*package,
+							 const gchar	*package_id);
+gboolean		 zif_package_set_summary	(ZifPackage	*package,
+							 ZifString	*summary);
+gboolean		 zif_package_set_description	(ZifPackage	*package,
+							 ZifString	*description);
+gboolean		 zif_package_set_license	(ZifPackage	*package,
+							 ZifString	*license);
+gboolean		 zif_package_set_url		(ZifPackage	*package,
+							 ZifString	*url);
+gboolean		 zif_package_set_location_href	(ZifPackage	*package,
+							 ZifString	*location_href);
+gboolean		 zif_package_set_category	(ZifPackage	*package,
+							 ZifString	*category);
+gboolean		 zif_package_set_group		(ZifPackage	*package,
+							 PkGroupEnum	 group);
+gboolean		 zif_package_set_size		(ZifPackage	*package,
+							 guint64	 size);
+gboolean		 zif_package_set_files		(ZifPackage	*package,
+							 GPtrArray	*files);
+gboolean		 zif_package_set_requires	(ZifPackage	*package,
+							 GPtrArray	*requires);
+gboolean		 zif_package_set_provides	(ZifPackage	*package,
+							 GPtrArray	*provides);
+/* actions */
+gboolean		 zif_package_download		(ZifPackage	*package,
+							 const gchar	*directory,
+							 GCancellable	*cancellable,
+							 ZifCompletion	*completion,
+							 GError		**error);
+const gchar		*zif_package_get_package_id	(ZifPackage	*package);
+void			 zif_package_print		(ZifPackage	*package);
+gboolean		 zif_package_is_devel		(ZifPackage	*package);
+gboolean		 zif_package_is_gui		(ZifPackage	*package);
+gboolean		 zif_package_is_installed	(ZifPackage	*package);
+gboolean		 zif_package_is_free		(ZifPackage	*package);
+gboolean		 zif_package_is_native		(ZifPackage	*package);
+gint			 zif_package_compare		(ZifPackage	*a,
+							 ZifPackage	*b);
+ZifPackage		*zif_package_array_get_newest	(GPtrArray	*array,
+							 GError		**error);
+
+G_END_DECLS
+
+#endif /* __ZIF_PACKAGE_H */
+
diff --git a/backends/yum/libzif/zif-repo-md-comps.c b/backends/yum/libzif/zif-repo-md-comps.c
new file mode 100644
index 0000000..bed4d8a
--- /dev/null
+++ b/backends/yum/libzif/zif-repo-md-comps.c
@@ -0,0 +1,930 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2009 Richard Hughes <richard at hughsie.com>
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+/**
+ * SECTION:zif-repo-md-comps
+ * @short_description: Comps metadata functionality
+ *
+ * Provide access to the comps repo metadata.
+ * This object is a subclass of #ZifRepoMd
+ */
+
+#ifdef HAVE_CONFIG_H
+#  include <config.h>
+#endif
+
+#include <stdlib.h>
+#include <glib.h>
+
+#include "zif-repo-md.h"
+#include "zif-repo-md-comps.h"
+
+#include "egg-debug.h"
+#include "egg-string.h"
+
+#define ZIF_REPO_MD_COMPS_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), ZIF_TYPE_REPO_MD_COMPS, ZifRepoMdCompsPrivate))
+
+typedef enum {
+	ZIF_REPO_MD_COMPS_SECTION_GROUP,
+	ZIF_REPO_MD_COMPS_SECTION_CATEGORY,
+	ZIF_REPO_MD_COMPS_SECTION_UNKNOWN
+} ZifRepoMdCompsSection;
+
+typedef enum {
+	ZIF_REPO_MD_COMPS_SECTION_GROUP_ID,
+	ZIF_REPO_MD_COMPS_SECTION_GROUP_NAME,
+	ZIF_REPO_MD_COMPS_SECTION_GROUP_DESCRIPTION,
+	ZIF_REPO_MD_COMPS_SECTION_GROUP_VISIBLE,
+	ZIF_REPO_MD_COMPS_SECTION_GROUP_PACKAGELIST,
+	ZIF_REPO_MD_COMPS_SECTION_GROUP_PACKAGE,
+	ZIF_REPO_MD_COMPS_SECTION_GROUP_UNKNOWN
+} ZifRepoMdCompsSectionGroup;
+
+typedef enum {
+	ZIF_REPO_MD_COMPS_SECTION_GROUP_TYPE_DEFAULT,
+	ZIF_REPO_MD_COMPS_SECTION_GROUP_TYPE_OPTIONAL,
+	ZIF_REPO_MD_COMPS_SECTION_GROUP_TYPE_CONDITIONAL,
+	ZIF_REPO_MD_COMPS_SECTION_GROUP_TYPE_UNKNOWN
+} ZifRepoMdCompsSectionGroupType;
+
+typedef enum {
+	ZIF_REPO_MD_COMPS_SECTION_CATEGORY_ID,
+	ZIF_REPO_MD_COMPS_SECTION_CATEGORY_NAME,
+	ZIF_REPO_MD_COMPS_SECTION_CATEGORY_DESCRIPTION,
+	ZIF_REPO_MD_COMPS_SECTION_CATEGORY_GROUPLIST,
+	ZIF_REPO_MD_COMPS_SECTION_CATEGORY_GROUP,
+	ZIF_REPO_MD_COMPS_SECTION_CATEGORY_UNKNOWN
+} ZifRepoMdCompsSectionCategory;
+
+typedef struct {
+	gchar				*id;
+	gchar				*name;
+	gchar				*description;
+	gboolean			 visible;
+	GPtrArray			*packagelist;		/* stored as gchar */
+} ZifRepoMdCompsGroupData;
+
+typedef struct {
+	gchar				*id;
+	gchar				*name;
+	gchar				*description;
+	GPtrArray			*grouplist;		/* stored as gchar */
+} ZifRepoMdCompsCategoryData;
+
+/**
+ * ZifRepoMdCompsPrivate:
+ *
+ * Private #ZifRepoMdComps data
+ **/
+struct _ZifRepoMdCompsPrivate
+{
+	gboolean			 loaded;
+	GPtrArray			*array_groups;	 	/* stored as ZifRepoMdCompsGroupData */
+	GPtrArray			*array_categories;	/* stored as ZifRepoMdCompsCategoryData */
+	/* for parser */
+	ZifRepoMdCompsSection		 section;
+	ZifRepoMdCompsSectionGroup	 section_group;
+	ZifRepoMdCompsSectionGroupType	 section_group_type;
+	ZifRepoMdCompsSectionCategory	 section_category;
+	ZifRepoMdCompsGroupData		*group_data_temp;
+	ZifRepoMdCompsCategoryData	*category_data_temp;
+};
+
+G_DEFINE_TYPE (ZifRepoMdComps, zif_repo_md_comps, ZIF_TYPE_REPO_MD)
+
+/**
+ * zif_repo_md_comps_group_data_new:
+ **/
+static ZifRepoMdCompsGroupData *
+zif_repo_md_comps_group_data_new (void)
+{
+	ZifRepoMdCompsGroupData *data;
+	data = g_new0 (ZifRepoMdCompsGroupData, 1);
+	data->packagelist = g_ptr_array_new_with_free_func ((GDestroyNotify) g_free);
+	return data;
+}
+
+/**
+ * zif_repo_md_comps_category_data_new:
+ **/
+static ZifRepoMdCompsCategoryData *
+zif_repo_md_comps_category_data_new (void)
+{
+	ZifRepoMdCompsCategoryData *data;
+	data = g_new0 (ZifRepoMdCompsCategoryData, 1);
+	data->grouplist = g_ptr_array_new_with_free_func ((GDestroyNotify) g_free);
+	return data;
+}
+
+/**
+ * zif_repo_md_comps_group_data_free:
+ **/
+static void
+zif_repo_md_comps_group_data_free (ZifRepoMdCompsGroupData *data)
+{
+	g_free (data->id);
+	g_free (data->name);
+	g_free (data->description);
+	g_ptr_array_unref (data->packagelist);
+	g_free (data);
+}
+
+/**
+ * zif_repo_md_comps_category_data_free:
+ **/
+static void
+zif_repo_md_comps_category_data_free (ZifRepoMdCompsCategoryData *data)
+{
+	g_free (data->id);
+	g_free (data->name);
+	g_free (data->description);
+	g_ptr_array_unref (data->grouplist);
+	g_free (data);
+}
+
+#if 0
+/**
+ * zif_repo_md_comps_protocol_type_from_text:
+ **/
+static ZifRepoMdCompsProtocolType
+zif_repo_md_comps_protocol_type_from_text (const gchar *type_text)
+{
+	if (g_strcmp0 (type_text, "ftp") == 0)
+		return ZIF_REPO_MD_COMPS_PROTOCOL_TYPE_FTP;
+	if (g_strcmp0 (type_text, "http") == 0)
+		return ZIF_REPO_MD_COMPS_PROTOCOL_TYPE_HTTP;
+	if (g_strcmp0 (type_text, "rsync") == 0)
+		return ZIF_REPO_MD_COMPS_PROTOCOL_TYPE_RSYNC;
+	return ZIF_REPO_MD_COMPS_PROTOCOL_TYPE_UNKNOWN;
+}
+#endif
+
+/**
+ * zif_repo_md_comps_parser_start_element:
+ **/
+static void
+zif_repo_md_comps_parser_start_element (GMarkupParseContext *context, const gchar *element_name,
+					const gchar **attribute_names, const gchar **attribute_values,
+					gpointer user_data, GError **error)
+{
+	guint i;
+	ZifRepoMdComps *comps = user_data;
+
+	g_return_if_fail (ZIF_IS_REPO_MD_COMPS (comps));
+
+	/* group element */
+	if (comps->priv->section == ZIF_REPO_MD_COMPS_SECTION_UNKNOWN) {
+
+		/* start of group */
+		if (g_strcmp0 (element_name, "group") == 0) {
+			comps->priv->section = ZIF_REPO_MD_COMPS_SECTION_GROUP;
+			comps->priv->group_data_temp = zif_repo_md_comps_group_data_new ();
+			goto out;
+		}
+
+		/* start of category */
+		if (g_strcmp0 (element_name, "category") == 0) {
+			comps->priv->section = ZIF_REPO_MD_COMPS_SECTION_CATEGORY;
+			comps->priv->category_data_temp = zif_repo_md_comps_category_data_new ();
+			goto out;
+		}
+
+		goto out;
+	}
+
+	/* group element */
+	if (comps->priv->section == ZIF_REPO_MD_COMPS_SECTION_GROUP) {
+		/* id */
+		if (g_strcmp0 (element_name, "id") == 0) {
+			comps->priv->section_group = ZIF_REPO_MD_COMPS_SECTION_GROUP_ID;
+			goto out;
+		}
+		if (g_strcmp0 (element_name, "name") == 0) {
+			comps->priv->section_group = ZIF_REPO_MD_COMPS_SECTION_GROUP_NAME;
+			goto out;
+		}
+		if (g_strcmp0 (element_name, "description") == 0) {
+			comps->priv->section_group = ZIF_REPO_MD_COMPS_SECTION_GROUP_DESCRIPTION;
+			goto out;
+		}
+		if (g_strcmp0 (element_name, "uservisible") == 0) {
+			comps->priv->section_group = ZIF_REPO_MD_COMPS_SECTION_GROUP_VISIBLE;
+			goto out;
+		}
+		if (g_strcmp0 (element_name, "packagelist") == 0) {
+			comps->priv->section_group = ZIF_REPO_MD_COMPS_SECTION_GROUP_PACKAGELIST;
+			goto out;
+		}
+		if (g_strcmp0 (element_name, "packagereq") == 0) {
+			comps->priv->section_group = ZIF_REPO_MD_COMPS_SECTION_GROUP_PACKAGE;
+
+			/* find the package type as a bonus */
+			comps->priv->section_group_type = ZIF_REPO_MD_COMPS_SECTION_GROUP_TYPE_UNKNOWN;
+			for (i=0; attribute_names[i] != NULL; i++) {
+				if (g_strcmp0 (element_name, "type") == 0) {
+					if (g_strcmp0 (attribute_values[i], "default"))
+						comps->priv->section_group_type = ZIF_REPO_MD_COMPS_SECTION_GROUP_TYPE_DEFAULT;
+					break;
+				}
+			}
+			goto out;
+		}
+	}
+
+	/* category element */
+	if (comps->priv->section == ZIF_REPO_MD_COMPS_SECTION_CATEGORY) {
+		/* id */
+		if (g_strcmp0 (element_name, "id") == 0) {
+			comps->priv->section_category = ZIF_REPO_MD_COMPS_SECTION_CATEGORY_ID;
+			goto out;
+		}
+		if (g_strcmp0 (element_name, "name") == 0) {
+			comps->priv->section_category = ZIF_REPO_MD_COMPS_SECTION_CATEGORY_NAME;
+			goto out;
+		}
+		if (g_strcmp0 (element_name, "description") == 0) {
+			comps->priv->section_category = ZIF_REPO_MD_COMPS_SECTION_CATEGORY_DESCRIPTION;
+			goto out;
+		}
+		if (g_strcmp0 (element_name, "grouplist") == 0) {
+			comps->priv->section_category = ZIF_REPO_MD_COMPS_SECTION_CATEGORY_GROUPLIST;
+			goto out;
+		}
+		if (g_strcmp0 (element_name, "groupid") == 0) {
+			comps->priv->section_category = ZIF_REPO_MD_COMPS_SECTION_CATEGORY_GROUP;
+			goto out;
+		}
+	}
+out:
+	return;
+}
+
+/**
+ * zif_repo_md_comps_parser_end_element:
+ **/
+static void
+zif_repo_md_comps_parser_end_element (GMarkupParseContext *context, const gchar *element_name,
+				      gpointer user_data, GError **error)
+{
+	ZifRepoMdComps *comps = user_data;
+
+	/* end of group */
+	if (g_strcmp0 (element_name, "group") == 0) {
+		comps->priv->section = ZIF_REPO_MD_COMPS_SECTION_UNKNOWN;
+
+		/* add to array */
+		g_ptr_array_add (comps->priv->array_groups, comps->priv->group_data_temp);
+
+		if (FALSE)
+		egg_debug ("added GROUP '%s' name:%s, desc:%s, visible:%i, list=%p",
+			   comps->priv->group_data_temp->id,
+			   comps->priv->group_data_temp->name,
+			   comps->priv->group_data_temp->description,
+			   comps->priv->group_data_temp->visible,
+			   comps->priv->group_data_temp->packagelist);
+
+		comps->priv->group_data_temp = NULL;
+		goto out;
+	}
+
+	/* start of group */
+	if (g_strcmp0 (element_name, "category") == 0) {
+		comps->priv->section = ZIF_REPO_MD_COMPS_SECTION_UNKNOWN;
+
+		/* add to array */
+		g_ptr_array_add (comps->priv->array_categories, comps->priv->category_data_temp);
+
+		if (FALSE)
+		egg_debug ("added CATEGORY '%s' name:%s, desc:%s, list=%p",
+			   comps->priv->category_data_temp->id,
+			   comps->priv->category_data_temp->name,
+			   comps->priv->category_data_temp->description,
+			   comps->priv->category_data_temp->grouplist);
+
+		comps->priv->category_data_temp = NULL;
+		goto out;
+	}
+out:
+	return;
+}
+
+/**
+ * zif_repo_md_comps_parser_text:
+ **/
+static void
+zif_repo_md_comps_parser_text (GMarkupParseContext *context, const gchar *text, gsize text_len,
+			       gpointer user_data, GError **error)
+
+{
+	ZifRepoMdComps *comps = user_data;
+
+	/* skip whitespace */
+	if (text_len < 1 || text[0] == ' ' || text[0] == '\t' || text[0] == '\n')
+		goto out;
+
+	/* group section */
+	if (comps->priv->section == ZIF_REPO_MD_COMPS_SECTION_GROUP) {
+		if (comps->priv->section_group == ZIF_REPO_MD_COMPS_SECTION_GROUP_ID) {
+			comps->priv->group_data_temp->id = g_strdup (text);
+			comps->priv->section_group = ZIF_REPO_MD_COMPS_SECTION_GROUP_UNKNOWN;
+			goto out;
+		}
+		if (comps->priv->section_group == ZIF_REPO_MD_COMPS_SECTION_GROUP_NAME) {
+			/* ignore translated versions for now */
+			if (comps->priv->group_data_temp->name != NULL)
+				goto out;
+			comps->priv->group_data_temp->name = g_strdup (text);
+			comps->priv->section_group = ZIF_REPO_MD_COMPS_SECTION_GROUP_UNKNOWN;
+			goto out;
+		}
+		if (comps->priv->section_group == ZIF_REPO_MD_COMPS_SECTION_GROUP_DESCRIPTION) {
+			/* ignore translated versions for now */
+			if (comps->priv->group_data_temp->description != NULL)
+				goto out;
+			comps->priv->group_data_temp->description = g_strdup (text);
+			comps->priv->section_group = ZIF_REPO_MD_COMPS_SECTION_GROUP_UNKNOWN;
+			goto out;
+		}
+		if (comps->priv->section_group == ZIF_REPO_MD_COMPS_SECTION_GROUP_VISIBLE) {
+			/* TODO: parse true and false */
+			comps->priv->group_data_temp->visible = atoi (text);
+			comps->priv->section_group = ZIF_REPO_MD_COMPS_SECTION_GROUP_UNKNOWN;
+			goto out;
+		}
+		if (comps->priv->section_group == ZIF_REPO_MD_COMPS_SECTION_GROUP_PACKAGE) {
+			g_ptr_array_add (comps->priv->group_data_temp->packagelist, g_strdup (text));
+			comps->priv->section_group = ZIF_REPO_MD_COMPS_SECTION_GROUP_UNKNOWN;
+			goto out;
+		}
+		goto out;
+	}
+
+	/* category section */
+	if (comps->priv->section == ZIF_REPO_MD_COMPS_SECTION_CATEGORY) {
+		if (comps->priv->section_category == ZIF_REPO_MD_COMPS_SECTION_CATEGORY_ID) {
+			comps->priv->category_data_temp->id = g_strdup (text);
+			comps->priv->section_category = ZIF_REPO_MD_COMPS_SECTION_CATEGORY_UNKNOWN;
+			goto out;
+		}
+		if (comps->priv->section_category == ZIF_REPO_MD_COMPS_SECTION_CATEGORY_NAME) {
+			/* ignore translated versions for now */
+			if (comps->priv->category_data_temp->name != NULL)
+				goto out;
+			comps->priv->category_data_temp->name = g_strdup (text);
+			comps->priv->section_category = ZIF_REPO_MD_COMPS_SECTION_CATEGORY_UNKNOWN;
+			goto out;
+		}
+		if (comps->priv->section_category == ZIF_REPO_MD_COMPS_SECTION_CATEGORY_DESCRIPTION) {
+			/* ignore translated versions for now */
+			if (comps->priv->category_data_temp->description != NULL)
+				goto out;
+			comps->priv->category_data_temp->description = g_strdup (text);
+			comps->priv->section_category = ZIF_REPO_MD_COMPS_SECTION_CATEGORY_UNKNOWN;
+			goto out;
+		}
+		if (comps->priv->section_category == ZIF_REPO_MD_COMPS_SECTION_CATEGORY_GROUP) {
+			g_ptr_array_add (comps->priv->category_data_temp->grouplist, g_strdup (text));
+			comps->priv->section_category = ZIF_REPO_MD_COMPS_SECTION_CATEGORY_UNKNOWN;
+			goto out;
+		}
+		goto out;
+	}
+out:
+	return;
+}
+
+/**
+ * zif_repo_md_comps_unload:
+ **/
+static gboolean
+zif_repo_md_comps_unload (ZifRepoMd *md, GCancellable *cancellable, ZifCompletion *completion, GError **error)
+{
+	gboolean ret = FALSE;
+	return ret;
+}
+
+/**
+ * zif_repo_md_comps_load:
+ **/
+static gboolean
+zif_repo_md_comps_load (ZifRepoMd *md, GCancellable *cancellable, ZifCompletion *completion, GError **error)
+{
+	gboolean ret = TRUE;
+	gchar *contents = NULL;
+	const gchar *filename;
+	gsize size;
+	GMarkupParseContext *context = NULL;
+	const GMarkupParser gpk_repo_md_comps_markup_parser = {
+		zif_repo_md_comps_parser_start_element,
+		zif_repo_md_comps_parser_end_element,
+		zif_repo_md_comps_parser_text,
+		NULL, /* passthrough */
+		NULL /* error */
+	};
+	ZifRepoMdComps *comps = ZIF_REPO_MD_COMPS (md);
+
+	g_return_val_if_fail (ZIF_IS_REPO_MD_COMPS (md), FALSE);
+
+	/* already loaded */
+	if (comps->priv->loaded)
+		goto out;
+
+	/* get filename */
+	filename = zif_repo_md_get_filename_uncompressed (md);
+	if (filename == NULL) {
+		if (error != NULL)
+			*error = g_error_new (1, 0, "failed to get filename for comps");
+		goto out;
+	}
+
+	/* open database */
+	egg_debug ("filename = %s", filename);
+
+	/* get repo contents */
+	ret = g_file_get_contents (filename, &contents, &size, error);
+	if (!ret)
+		goto out;
+
+	/* create parser */
+	context = g_markup_parse_context_new (&gpk_repo_md_comps_markup_parser, G_MARKUP_PREFIX_ERROR_POSITION, comps, NULL);
+
+	/* parse data */
+	ret = g_markup_parse_context_parse (context, contents, (gssize) size, error);
+	if (!ret)
+		goto out;
+
+	comps->priv->loaded = TRUE;
+out:
+	if (context != NULL)
+		g_markup_parse_context_free (context);
+	g_free (contents);
+	return ret;
+}
+
+/**
+ * zif_repo_md_comps_get_categories:
+ * @md: the #ZifRepoMdComps object
+ * @cancellable: the %GCancellable, or %NULL
+ * @completion: the %ZifCompletion object
+ * @error: a #GError which is used on failure, or %NULL
+ *
+ * Gets the available list of categories.
+ *
+ * Return value: %PkCategory array of categories
+ **/
+GPtrArray *
+zif_repo_md_comps_get_categories (ZifRepoMdComps *md, GCancellable *cancellable,
+				  ZifCompletion *completion, GError **error)
+{
+	GPtrArray *array = NULL;
+	guint i;
+	guint len;
+	gboolean ret;
+	GError *error_local = NULL;
+	const ZifRepoMdCompsCategoryData *data;
+	PkCategory *category;
+
+	g_return_val_if_fail (ZIF_IS_REPO_MD_COMPS (md), NULL);
+
+	/* if not already loaded, load */
+	if (!md->priv->loaded) {
+		ret = zif_repo_md_load (ZIF_REPO_MD (md), cancellable, completion, &error_local);
+		if (!ret) {
+			if (error != NULL)
+				*error = g_error_new (1, 0, "failed to get load comps: %s", error_local->message);
+			g_error_free (error_local);
+			goto out;
+		}
+	}
+
+	/* get categories */
+	array = g_ptr_array_new_with_free_func ((GDestroyNotify) g_object_unref);
+	len = md->priv->array_categories->len;
+	for (i=0; i<len; i++) {
+		data = g_ptr_array_index (md->priv->array_categories, i);
+		category = pk_category_new ();
+		pk_category_set_id (category, data->id);
+		pk_category_set_name (category, data->name);
+		pk_category_set_summary (category, data->description);
+		g_ptr_array_add (array, category);
+	}
+out:
+	return array;
+}
+
+/**
+ * zif_repo_md_comps_get_category_for_group:
+ **/
+static PkCategory *
+zif_repo_md_comps_get_category_for_group (ZifRepoMdComps *md, const gchar *group_id)
+{
+	guint i;
+	guint len;
+	PkCategory *category = NULL;
+	ZifRepoMdCompsGroupData *data;
+
+	/* find group matching group_id */
+	len = md->priv->array_groups->len;
+	for (i=0; i<len; i++) {
+		data = g_ptr_array_index (md->priv->array_groups, i);
+		if (g_strcmp0 (group_id, data->id) == 0) {
+			category = pk_category_new ();
+			pk_category_set_id (category, data->id);
+			pk_category_set_name (category, data->name);
+			pk_category_set_summary (category, data->description);
+			break;
+		}
+	}
+	return category;
+}
+
+/**
+ * zif_repo_md_comps_get_groups_for_category:
+ * @md: the #ZifRepoMdComps object
+ * @category_id: the category to search for
+ * @cancellable: the %GCancellable, or %NULL
+ * @completion: the %ZifCompletion object
+ * @error: a #GError which is used on failure, or %NULL
+ *
+ * Gets the list of groups for a specific category.
+ *
+ * Return value: %PkCategory array of groups
+ **/
+GPtrArray *
+zif_repo_md_comps_get_groups_for_category (ZifRepoMdComps *md, const gchar *category_id,
+					   GCancellable *cancellable, ZifCompletion *completion, GError **error)
+{
+	GPtrArray *array = NULL;
+	guint i;
+	guint j;
+	guint len;
+	gboolean ret;
+	GError *error_local = NULL;
+	const ZifRepoMdCompsCategoryData *data;
+	const gchar *id;
+	PkCategory *category;
+
+	g_return_val_if_fail (ZIF_IS_REPO_MD_COMPS (md), NULL);
+	g_return_val_if_fail (category_id != NULL, NULL);
+
+	/* if not already loaded, load */
+	if (!md->priv->loaded) {
+		ret = zif_repo_md_load (ZIF_REPO_MD (md), cancellable, completion, &error_local);
+		if (!ret) {
+			if (error != NULL)
+				*error = g_error_new (1, 0, "failed to get load comps: %s", error_local->message);
+			g_error_free (error_local);
+			goto out;
+		}
+	}
+
+	/* get categories */
+	len = md->priv->array_categories->len;
+	for (i=0; i<len; i++) {
+		data = g_ptr_array_index (md->priv->array_categories, i);
+
+		/* category matches */
+		if (g_strcmp0 (category_id, data->id) == 0) {
+			array = g_ptr_array_new_with_free_func ((GDestroyNotify) g_object_unref);
+			for (j=0; j<data->grouplist->len; j++) {
+				id = g_ptr_array_index (data->grouplist, j);
+				/* find group matching group_id */
+				category = zif_repo_md_comps_get_category_for_group (md, id);
+				if (category != NULL)
+					g_ptr_array_add (array, category);
+			}
+			break;
+		}
+	}
+
+	/* nothing found */
+	if (array == NULL) {
+		if (error != NULL)
+			*error = g_error_new (1, 0, "could not find category: %s", category_id);
+	}
+out:
+	return array;
+}
+
+/**
+ * zif_repo_md_comps_get_packages_for_group:
+ * @md: the #ZifRepoMdComps object
+ * @group_id: the group to search for
+ * @cancellable: the %GCancellable, or %NULL
+ * @completion: the %ZifCompletion object
+ * @error: a #GError which is used on failure, or %NULL
+ *
+ * Gets the package names for a group.
+ *
+ * Return value: gchar pointer array of package names (not %ZifPackage's)
+ **/
+GPtrArray *
+zif_repo_md_comps_get_packages_for_group (ZifRepoMdComps *md, const gchar *group_id,
+					  GCancellable *cancellable, ZifCompletion *completion, GError **error)
+{
+	GPtrArray *array = NULL;
+	guint i;
+	guint j;
+	guint len;
+	gboolean ret;
+	GError *error_local = NULL;
+	const ZifRepoMdCompsGroupData *data;
+	const gchar *packagename;
+
+	g_return_val_if_fail (ZIF_IS_REPO_MD_COMPS (md), NULL);
+	g_return_val_if_fail (group_id != NULL, NULL);
+
+	/* if not already loaded, load */
+	if (!md->priv->loaded) {
+		ret = zif_repo_md_load (ZIF_REPO_MD (md), cancellable, completion, &error_local);
+		if (!ret) {
+			if (error != NULL)
+				*error = g_error_new (1, 0, "failed to get load comps: %s", error_local->message);
+			g_error_free (error_local);
+			goto out;
+		}
+	}
+
+	/* get packages in this group */
+	len = md->priv->array_groups->len;
+	for (i=0; i<len; i++) {
+		data = g_ptr_array_index (md->priv->array_groups, i);
+
+		/* category matches */
+		if (g_strcmp0 (group_id, data->id) == 0) {
+			array = g_ptr_array_new_with_free_func ((GDestroyNotify) g_free);
+			for (j=0; j<data->packagelist->len; j++) {
+				packagename = g_ptr_array_index (data->packagelist, j);
+				g_ptr_array_add (array, g_strdup (packagename));
+			}
+			break;
+		}
+	}
+
+	/* nothing found */
+	if (array == NULL) {
+		if (error != NULL)
+			*error = g_error_new (1, 0, "could not find group: %s", group_id);
+	}
+out:
+	return array;
+}
+
+/**
+ * zif_repo_md_comps_finalize:
+ **/
+static void
+zif_repo_md_comps_finalize (GObject *object)
+{
+	ZifRepoMdComps *md;
+
+	g_return_if_fail (object != NULL);
+	g_return_if_fail (ZIF_IS_REPO_MD_COMPS (object));
+	md = ZIF_REPO_MD_COMPS (object);
+
+	g_ptr_array_unref (md->priv->array_groups);
+	g_ptr_array_unref (md->priv->array_categories);
+
+	G_OBJECT_CLASS (zif_repo_md_comps_parent_class)->finalize (object);
+}
+
+/**
+ * zif_repo_md_comps_class_init:
+ **/
+static void
+zif_repo_md_comps_class_init (ZifRepoMdCompsClass *klass)
+{
+	GObjectClass *object_class = G_OBJECT_CLASS (klass);
+	ZifRepoMdClass *repo_md_class = ZIF_REPO_MD_CLASS (klass);
+	object_class->finalize = zif_repo_md_comps_finalize;
+
+	/* map */
+	repo_md_class->load = zif_repo_md_comps_load;
+	repo_md_class->unload = zif_repo_md_comps_unload;
+	g_type_class_add_private (klass, sizeof (ZifRepoMdCompsPrivate));
+}
+
+/**
+ * zif_repo_md_comps_init:
+ **/
+static void
+zif_repo_md_comps_init (ZifRepoMdComps *md)
+{
+	md->priv = ZIF_REPO_MD_COMPS_GET_PRIVATE (md);
+	md->priv->loaded = FALSE;
+	md->priv->section = ZIF_REPO_MD_COMPS_SECTION_UNKNOWN;
+	md->priv->section_group = ZIF_REPO_MD_COMPS_SECTION_GROUP_UNKNOWN;
+	md->priv->section_group_type = ZIF_REPO_MD_COMPS_SECTION_GROUP_TYPE_UNKNOWN;
+	md->priv->section_category = ZIF_REPO_MD_COMPS_SECTION_CATEGORY_UNKNOWN;
+	md->priv->group_data_temp = NULL;
+	md->priv->category_data_temp = NULL;
+	md->priv->array_groups = g_ptr_array_new_with_free_func ((GDestroyNotify) zif_repo_md_comps_group_data_free);
+	md->priv->array_categories = g_ptr_array_new_with_free_func ((GDestroyNotify) zif_repo_md_comps_category_data_free);
+}
+
+/**
+ * zif_repo_md_comps_new:
+ *
+ * Return value: A new #ZifRepoMdComps class instance.
+ **/
+ZifRepoMdComps *
+zif_repo_md_comps_new (void)
+{
+	ZifRepoMdComps *md;
+	md = g_object_new (ZIF_TYPE_REPO_MD_COMPS, NULL);
+	return ZIF_REPO_MD_COMPS (md);
+}
+
+/***************************************************************************
+ ***                          MAKE CHECK TESTS                           ***
+ ***************************************************************************/
+#ifdef EGG_TEST
+#include "egg-test.h"
+
+void
+zif_repo_md_comps_test (EggTest *test)
+{
+	ZifRepoMdComps *md;
+	gboolean ret;
+	GError *error = NULL;
+	GPtrArray *array;
+	const gchar *id;
+	GCancellable *cancellable;
+	ZifCompletion *completion;
+	PkCategory *category;
+
+	if (!egg_test_start (test, "ZifRepoMdComps"))
+		return;
+
+	/* use */
+	cancellable = g_cancellable_new ();
+	completion = zif_completion_new ();
+
+	/************************************************************/
+	egg_test_title (test, "get repo_md_comps md");
+	md = zif_repo_md_comps_new ();
+	egg_test_assert (test, md != NULL);
+
+	/************************************************************/
+	egg_test_title (test, "loaded");
+	egg_test_assert (test, !md->priv->loaded);
+
+	/************************************************************/
+	egg_test_title (test, "set id");
+	ret = zif_repo_md_set_id (ZIF_REPO_MD (md), "fedora");
+	if (ret)
+		egg_test_success (test, NULL);
+	else
+		egg_test_failed (test, "failed to set");
+
+	/************************************************************/
+	egg_test_title (test, "set type");
+	ret = zif_repo_md_set_mdtype (ZIF_REPO_MD (md), ZIF_REPO_MD_TYPE_COMPS_XML);
+	if (ret)
+		egg_test_success (test, NULL);
+	else
+		egg_test_failed (test, "failed to set");
+
+	/************************************************************/
+	egg_test_title (test, "set filename");
+	ret = zif_repo_md_set_filename (ZIF_REPO_MD (md), "../test/cache/comps-rawhide.xml");
+	if (ret)
+		egg_test_success (test, NULL);
+	else
+		egg_test_failed (test, "failed to set");
+
+	/************************************************************/
+	egg_test_title (test, "set checksum type");
+	ret = zif_repo_md_set_checksum_type (ZIF_REPO_MD (md), G_CHECKSUM_SHA256);
+	if (ret)
+		egg_test_success (test, NULL);
+	else
+		egg_test_failed (test, "failed to set");
+
+	/************************************************************/
+	egg_test_title (test, "set checksum uncompressed");
+	ret = zif_repo_md_set_checksum_uncompressed (ZIF_REPO_MD (md), "14f17b894303b4dc9683511104848f75d98cea8f76c107bf25e1b4db5741f6a8");
+	if (ret)
+		egg_test_success (test, NULL);
+	else
+		egg_test_failed (test, "failed to set");
+
+	/************************************************************/
+	egg_test_title (test, "get categories");
+	array = zif_repo_md_comps_get_categories (md, cancellable, completion, &error);
+	if (array != NULL)
+		egg_test_success (test, NULL);
+	else
+		egg_test_failed (test, "failed to get categories '%s'", error->message);
+
+	/************************************************************/
+	egg_test_title (test, "loaded");
+	egg_test_assert (test, md->priv->loaded);
+
+	/************************************************************/
+	egg_test_title (test, "correct number");
+	if (array->len == 1)
+		egg_test_success (test, NULL);
+	else
+		egg_test_failed (test, "incorrect value %i", array->len);
+
+	/************************************************************/
+	egg_test_title (test, "correct id value");
+	category = g_ptr_array_index (array, 0);
+	if (g_strcmp0 (pk_category_get_id (category), "apps") == 0)
+		egg_test_success (test, NULL);
+	else
+		egg_test_failed (test, "failed to get correct id '%s'", pk_category_get_id (category));
+
+	/************************************************************/
+	egg_test_title (test, "correct name value");
+	category = g_ptr_array_index (array, 0);
+	if (g_strcmp0 (pk_category_get_name (category), "Applications") == 0)
+		egg_test_success (test, NULL);
+	else
+		egg_test_failed (test, "failed to get correct name '%s'", pk_category_get_name (category));
+
+	/************************************************************/
+	egg_test_title (test, "correct summary value");
+	category = g_ptr_array_index (array, 0);
+	if (g_strcmp0 (pk_category_get_summary (category), "Applications to perform a variety of tasks") == 0)
+		egg_test_success (test, NULL);
+	else
+		egg_test_failed (test, "failed to get correct summary '%s'", pk_category_get_summary (category));
+
+	g_ptr_array_unref (array);
+
+	/************************************************************/
+	egg_test_title (test, "get groups for category");
+	array = zif_repo_md_comps_get_groups_for_category (md, "apps", cancellable, completion, &error);
+	if (array != NULL)
+		egg_test_success (test, NULL);
+	else
+		egg_test_failed (test, "failed to get categories '%s'", error->message);
+
+	/************************************************************/
+	egg_test_title (test, "correct number");
+	if (array->len == 2)
+		egg_test_success (test, NULL);
+	else
+		egg_test_failed (test, "incorrect value %i", array->len);
+
+	/************************************************************/
+	egg_test_title (test, "correct id value");
+	category = g_ptr_array_index (array, 0);
+	if (g_strcmp0 (pk_category_get_id (category), "admin-tools") == 0)
+		egg_test_success (test, NULL);
+	else
+		egg_test_failed (test, "failed to get correct id '%s'", pk_category_get_id (category));
+	g_ptr_array_unref (array);
+
+	/************************************************************/
+	egg_test_title (test, "get packages for group");
+	array = zif_repo_md_comps_get_packages_for_group (md, "admin-tools", cancellable, completion, &error);
+	if (array != NULL)
+		egg_test_success (test, NULL);
+	else
+		egg_test_failed (test, "failed to get categories '%s'", error->message);
+
+	/************************************************************/
+	egg_test_title (test, "correct number");
+	if (array->len == 2)
+		egg_test_success (test, NULL);
+	else
+		egg_test_failed (test, "incorrect value %i", array->len);
+
+	/************************************************************/
+	egg_test_title (test, "correct value");
+	id = g_ptr_array_index (array, 0);
+	if (g_strcmp0 (id, "gnome-packagekit") == 0)
+		egg_test_success (test, NULL);
+	else
+		egg_test_failed (test, "failed to get correct id '%s'", id);
+	g_ptr_array_unref (array);
+
+	g_object_unref (md);
+	g_object_unref (cancellable);
+	g_object_unref (completion);
+
+	egg_test_end (test);
+}
+#endif
+
diff --git a/backends/yum/libzif/zif-repo-md-comps.h b/backends/yum/libzif/zif-repo-md-comps.h
new file mode 100644
index 0000000..e2cef0d
--- /dev/null
+++ b/backends/yum/libzif/zif-repo-md-comps.h
@@ -0,0 +1,78 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2009 Richard Hughes <richard at hughsie.com>
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#if !defined (__ZIF_H_INSIDE__) && !defined (ZIF_COMPILATION)
+#error "Only <zif.h> can be included directly."
+#endif
+
+#ifndef __ZIF_REPO_MD_COMPS_H
+#define __ZIF_REPO_MD_COMPS_H
+
+#include <glib-object.h>
+
+#include "zif-repo-md.h"
+
+G_BEGIN_DECLS
+
+#define ZIF_TYPE_REPO_MD_COMPS		(zif_repo_md_comps_get_type ())
+#define ZIF_REPO_MD_COMPS(o)		(G_TYPE_CHECK_INSTANCE_CAST ((o), ZIF_TYPE_REPO_MD_COMPS, ZifRepoMdComps))
+#define ZIF_REPO_MD_COMPS_CLASS(k)	(G_TYPE_CHECK_CLASS_CAST((k), ZIF_TYPE_REPO_MD_COMPS, ZifRepoMdCompsClass))
+#define ZIF_IS_REPO_MD_COMPS(o)		(G_TYPE_CHECK_INSTANCE_TYPE ((o), ZIF_TYPE_REPO_MD_COMPS))
+#define ZIF_IS_REPO_MD_COMPS_CLASS(k)	(G_TYPE_CHECK_CLASS_TYPE ((k), ZIF_TYPE_REPO_MD_COMPS))
+#define ZIF_REPO_MD_COMPS_GET_CLASS(o)	(G_TYPE_INSTANCE_GET_CLASS ((o), ZIF_TYPE_REPO_MD_COMPS, ZifRepoMdCompsClass))
+
+typedef struct _ZifRepoMdComps		ZifRepoMdComps;
+typedef struct _ZifRepoMdCompsPrivate	ZifRepoMdCompsPrivate;
+typedef struct _ZifRepoMdCompsClass	ZifRepoMdCompsClass;
+
+struct _ZifRepoMdComps
+{
+	ZifRepoMd			 parent;
+	ZifRepoMdCompsPrivate		*priv;
+};
+
+struct _ZifRepoMdCompsClass
+{
+	ZifRepoMdClass			 parent_class;
+};
+
+GType		 zif_repo_md_comps_get_type		(void);
+ZifRepoMdComps	*zif_repo_md_comps_new			(void);
+
+GPtrArray	*zif_repo_md_comps_get_categories		(ZifRepoMdComps		*md,
+								 GCancellable		*cancellable,
+								 ZifCompletion		*completion,
+								 GError			**error);
+GPtrArray	*zif_repo_md_comps_get_groups_for_category	(ZifRepoMdComps		*md,
+								 const gchar		*category_id,
+								 GCancellable		*cancellable,
+								 ZifCompletion		*completion,
+								 GError			**error);
+GPtrArray	*zif_repo_md_comps_get_packages_for_group	(ZifRepoMdComps		*md,
+								 const gchar		*group_id,
+								 GCancellable		*cancellable,
+								 ZifCompletion		*completion,
+								 GError			**error);
+
+G_END_DECLS
+
+#endif /* __ZIF_REPO_MD_COMPS_H */
+
diff --git a/backends/yum/libzif/zif-repo-md-filelists.c b/backends/yum/libzif/zif-repo-md-filelists.c
new file mode 100644
index 0000000..d9202be
--- /dev/null
+++ b/backends/yum/libzif/zif-repo-md-filelists.c
@@ -0,0 +1,446 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2009 Richard Hughes <richard at hughsie.com>
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+/**
+ * SECTION:zif-repo-md-filelists
+ * @short_description: File list metadata functionality
+ *
+ * Provide access to the file list metadata.
+ * This object is a subclass of #ZifRepoMd
+ */
+
+#ifdef HAVE_CONFIG_H
+#  include <config.h>
+#endif
+
+#include <glib.h>
+#include <string.h>
+#include <stdlib.h>
+#include <sqlite3.h>
+#include <gio/gio.h>
+
+#include "zif-repo-md.h"
+#include "zif-repo-md-filelists.h"
+
+#include "egg-debug.h"
+#include "egg-string.h"
+
+#define ZIF_REPO_MD_FILELISTS_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), ZIF_TYPE_REPO_MD_FILELISTS, ZifRepoMdFilelistsPrivate))
+
+/**
+ * ZifRepoMdFilelistsPrivate:
+ *
+ * Private #ZifRepoMdFilelists data
+ **/
+struct _ZifRepoMdFilelistsPrivate
+{
+	gboolean		 loaded;
+	sqlite3			*db;
+};
+
+typedef struct {
+	gchar			*filename;
+	GPtrArray		*array;
+} ZifRepoMdFilelistsData;
+
+G_DEFINE_TYPE (ZifRepoMdFilelists, zif_repo_md_filelists, ZIF_TYPE_REPO_MD)
+
+/**
+ * zif_repo_md_filelists_unload:
+ **/
+static gboolean
+zif_repo_md_filelists_unload (ZifRepoMd *md, GCancellable *cancellable, ZifCompletion *completion, GError **error)
+{
+	gboolean ret = FALSE;
+	return ret;
+}
+
+/**
+ * zif_repo_md_filelists_load:
+ **/
+static gboolean
+zif_repo_md_filelists_load (ZifRepoMd *md, GCancellable *cancellable, ZifCompletion *completion, GError **error)
+{
+	const gchar *filename;
+	gint rc;
+	ZifRepoMdFilelists *filelists = ZIF_REPO_MD_FILELISTS (md);
+
+	g_return_val_if_fail (ZIF_IS_REPO_MD_FILELISTS (md), FALSE);
+
+	/* already loaded */
+	if (filelists->priv->loaded)
+		goto out;
+
+	/* get filename */
+	filename = zif_repo_md_get_filename_uncompressed (md);
+	if (filename == NULL) {
+		if (error != NULL)
+			*error = g_error_new (1, 0, "failed to get filename for filelists");
+		goto out;
+	}
+
+	/* open database */
+	egg_debug ("filename = %s", filename);
+	rc = sqlite3_open (filename, &filelists->priv->db);
+	if (rc != 0) {
+		egg_warning ("Can't open database: %s\n", sqlite3_errmsg (filelists->priv->db));
+		if (error != NULL)
+			*error = g_error_new (1, 0, "can't open database: %s", sqlite3_errmsg (filelists->priv->db));
+		goto out;
+	}
+
+	/* we don't need to keep syncing */
+	sqlite3_exec (filelists->priv->db, "PRAGMA synchronous=OFF", NULL, NULL, NULL);
+	filelists->priv->loaded = TRUE;
+out:
+	return filelists->priv->loaded;
+}
+
+/**
+ * zif_store_remote_sqlite_get_id_cb:
+ **/
+static gint
+zif_repo_md_filelists_sqlite_get_id_cb (void *data, gint argc, gchar **argv, gchar **col_name)
+{
+	gchar **pkgid = (gchar **) data;
+	*pkgid = g_strdup (argv[0]);
+	return 0;
+}
+
+/**
+ * zif_repo_md_filelists_sqlite_get_files_cb:
+ **/
+static gint
+zif_repo_md_filelists_sqlite_get_files_cb (void *data, gint argc, gchar **argv, gchar **col_name)
+{
+	gint i;
+	gchar **filenames = NULL;
+	gchar **filenames_r = NULL;
+	gchar **id_r = NULL;
+	ZifRepoMdFilelistsData *fldata = (ZifRepoMdFilelistsData *) data;
+
+	/* get pointers to the arguments */
+	for (i=0;i<argc;i++) {
+		if (g_strcmp0 (col_name[i], "pkgKey") == 0)
+			id_r = &argv[i];
+		else if (g_strcmp0 (col_name[i], "filenames") == 0)
+			filenames_r = &argv[i];
+	}
+
+	/* either is undereferencable */
+	if (filenames_r == NULL || id_r == NULL) {
+		egg_warning ("no file data");
+		goto out;
+	}
+
+	/* split the filenames */
+	filenames = g_strsplit (*filenames_r, "/", -1);
+	for (i=0; filenames[i] != NULL ;i++) {
+		/* do we match */
+		if (g_strcmp0 (fldata->filename, filenames[i]) == 0) {
+			egg_debug ("found %s for %s", filenames[i], *id_r);
+			g_ptr_array_add (fldata->array, GUINT_TO_POINTER (atoi (*id_r)));
+		}
+	}
+out:
+	g_strfreev (filenames);
+	return 0;
+}
+
+/**
+ * zif_repo_md_filelists_search_file:
+ * @md: the #ZifRepoMdFilelists object
+ * @search: the full path that should be searched for
+ * @cancellable: a #GCancellable which is used to cancel tasks, or %NULL
+ * @completion: a #ZifCompletion to use for progress reporting
+ * @error: a #GError which is used on failure, or %NULL
+ *
+ * Gets a list of all packages that contain the file.
+ * Results are pkgId's descriptors, i.e. 64 bit hashes as test.
+ *
+ * Return value: a string list of pkgId's
+ **/
+GPtrArray *
+zif_repo_md_filelists_search_file (ZifRepoMdFilelists *md, const gchar *search, GCancellable *cancellable, ZifCompletion *completion, GError **error)
+{
+	GPtrArray *array = NULL;
+	gchar *statement = NULL;
+	gchar *error_msg = NULL;
+	gint rc;
+	gboolean ret;
+	guint i;
+	GError *error_local = NULL;
+	gchar *filename = NULL;
+	gchar *dirname = NULL;
+	ZifRepoMdFilelistsData *data = NULL;
+
+	g_return_val_if_fail (ZIF_IS_REPO_MD_FILELISTS (md), FALSE);
+
+	/* if not already loaded, load */
+	if (!md->priv->loaded) {
+		ret = zif_repo_md_filelists_load (ZIF_REPO_MD (md), cancellable, completion, &error_local);
+		if (!ret) {
+			if (error != NULL)
+				*error = g_error_new (1, 0, "failed to load store file: %s", error_local->message);
+			g_error_free (error_local);
+			goto out;
+		}
+	}
+
+	/* split the search term into directory and filename */
+	dirname = g_path_get_dirname (search);
+	filename = g_path_get_basename (search);
+	egg_debug ("dirname=%s, filename=%s", dirname, filename);
+
+	/* create data struct we can pass to the callback */
+	data = g_new0 (ZifRepoMdFilelistsData, 1);
+	data->filename = g_path_get_basename (search);
+	data->array = g_ptr_array_new ();
+
+	/* populate _array with guint pkgKey */
+	statement = g_strdup_printf ("SELECT filenames, pkgKey FROM filelist WHERE dirname = '%s'", dirname);
+	rc = sqlite3_exec (md->priv->db, statement, zif_repo_md_filelists_sqlite_get_files_cb, data, &error_msg);
+	g_free (statement);
+	if (rc != SQLITE_OK) {
+		if (error != NULL)
+			*error = g_error_new (1, 0, "SQL error (failed to get keys): %s\n", error_msg);
+		sqlite3_free (error_msg);
+		goto out;
+	}
+
+	/* convert each pkgKey */
+	array = g_ptr_array_new_with_free_func ((GDestroyNotify) g_free);
+	for (i=0; i<data->array->len; i++) {
+		guint key;
+		gchar *pkgid = NULL;
+
+		/* convert the pkgKey to a pkgId */
+		key = GPOINTER_TO_UINT (g_ptr_array_index (data->array, i));
+		statement = g_strdup_printf ("SELECT pkgId FROM packages WHERE pkgKey = %i LIMIT 1", key);
+		rc = sqlite3_exec (md->priv->db, statement, zif_repo_md_filelists_sqlite_get_id_cb, &pkgid, &error_msg);
+		g_free (statement);
+		if (rc != SQLITE_OK) {
+			if (error != NULL)
+				*error = g_error_new (1, 0, "SQL error (failed to get packages): %s", error_msg);
+			sqlite3_free (error_msg);
+			goto out;
+		}
+
+		/* we failed to get any results */
+		if (pkgid == NULL) {
+			if (error != NULL)
+				*error = g_error_new (1, 0, "failed to resolve pkgKey: %i", key);
+			goto out;
+		}
+
+		/* added to tracked array, so no need to free pkgid */
+		g_ptr_array_add (array, pkgid);
+	}
+out:
+	if (data != NULL) {
+		g_free (data->filename);
+		g_ptr_array_unref (data->array);
+		g_free (data);
+	}
+	g_free (dirname);
+	g_free (filename);
+	return array;
+}
+
+/**
+ * zif_repo_md_filelists_finalize:
+ **/
+static void
+zif_repo_md_filelists_finalize (GObject *object)
+{
+	ZifRepoMdFilelists *md;
+
+	g_return_if_fail (object != NULL);
+	g_return_if_fail (ZIF_IS_REPO_MD_FILELISTS (object));
+	md = ZIF_REPO_MD_FILELISTS (object);
+
+	sqlite3_close (md->priv->db);
+
+	G_OBJECT_CLASS (zif_repo_md_filelists_parent_class)->finalize (object);
+}
+
+/**
+ * zif_repo_md_filelists_class_init:
+ **/
+static void
+zif_repo_md_filelists_class_init (ZifRepoMdFilelistsClass *klass)
+{
+	GObjectClass *object_class = G_OBJECT_CLASS (klass);
+	ZifRepoMdClass *repo_md_class = ZIF_REPO_MD_CLASS (klass);
+	object_class->finalize = zif_repo_md_filelists_finalize;
+
+	/* map */
+	repo_md_class->load = zif_repo_md_filelists_load;
+	repo_md_class->unload = zif_repo_md_filelists_unload;
+	g_type_class_add_private (klass, sizeof (ZifRepoMdFilelistsPrivate));
+}
+
+/**
+ * zif_repo_md_filelists_init:
+ **/
+static void
+zif_repo_md_filelists_init (ZifRepoMdFilelists *md)
+{
+	md->priv = ZIF_REPO_MD_FILELISTS_GET_PRIVATE (md);
+	md->priv->loaded = FALSE;
+	md->priv->db = NULL;
+}
+
+/**
+ * zif_repo_md_filelists_new:
+ *
+ * Return value: A new #ZifRepoMdFilelists class instance.
+ **/
+ZifRepoMdFilelists *
+zif_repo_md_filelists_new (void)
+{
+	ZifRepoMdFilelists *md;
+	md = g_object_new (ZIF_TYPE_REPO_MD_FILELISTS, NULL);
+	return ZIF_REPO_MD_FILELISTS (md);
+}
+
+/***************************************************************************
+ ***                          MAKE CHECK TESTS                           ***
+ ***************************************************************************/
+#ifdef EGG_TEST
+#include "egg-test.h"
+
+void
+zif_repo_md_filelists_test (EggTest *test)
+{
+	ZifRepoMdFilelists *md;
+	gboolean ret;
+	GError *error = NULL;
+	GPtrArray *array;
+	const gchar *pkgid;
+	GCancellable *cancellable;
+	ZifCompletion *completion;
+
+	if (!egg_test_start (test, "ZifRepoMdFilelists"))
+		return;
+
+	/* use */
+	cancellable = g_cancellable_new ();
+	completion = zif_completion_new ();
+
+	/************************************************************/
+	egg_test_title (test, "get store_remote md");
+	md = zif_repo_md_filelists_new ();
+	egg_test_assert (test, md != NULL);
+
+	/************************************************************/
+	egg_test_title (test, "loaded");
+	egg_test_assert (test, !md->priv->loaded);
+
+	/************************************************************/
+	egg_test_title (test, "set id");
+	ret = zif_repo_md_set_id (ZIF_REPO_MD (md), "fedora");
+	if (ret)
+		egg_test_success (test, NULL);
+	else
+		egg_test_failed (test, "failed to set");
+
+	/************************************************************/
+	egg_test_title (test, "set type");
+	ret = zif_repo_md_set_mdtype (ZIF_REPO_MD (md), ZIF_REPO_MD_TYPE_FILELISTS_DB);
+	if (ret)
+		egg_test_success (test, NULL);
+	else
+		egg_test_failed (test, "failed to set");
+
+	/************************************************************/
+	egg_test_title (test, "set checksum type");
+	ret = zif_repo_md_set_checksum_type (ZIF_REPO_MD (md), G_CHECKSUM_SHA256);
+	if (ret)
+		egg_test_success (test, NULL);
+	else
+		egg_test_failed (test, "failed to set");
+
+	/************************************************************/
+	egg_test_title (test, "set checksum compressed");
+	ret = zif_repo_md_set_checksum (ZIF_REPO_MD (md), "e00e88a8b6eee3798544764b6fe31ef8c9d071a824177c7cdc4fe749289198a9");
+	if (ret)
+		egg_test_success (test, NULL);
+	else
+		egg_test_failed (test, "failed to set");
+
+	/************************************************************/
+	egg_test_title (test, "set checksum uncompressed");
+	ret = zif_repo_md_set_checksum_uncompressed (ZIF_REPO_MD (md), "2b4336cb43e75610662bc0b3a362ca4cb7ba874528735a27c0d55148c3901792");
+	if (ret)
+		egg_test_success (test, NULL);
+	else
+		egg_test_failed (test, "failed to set");
+
+	/************************************************************/
+	egg_test_title (test, "set filename");
+	ret = zif_repo_md_set_filename (ZIF_REPO_MD (md), "../test/cache/fedora/e00e88a8b6eee3798544764b6fe31ef8c9d071a824177c7cdc4fe749289198a9-filelists.sqlite.bz2");
+	if (ret)
+		egg_test_success (test, NULL);
+	else
+		egg_test_failed (test, "failed to set");
+
+	/************************************************************/
+	egg_test_title (test, "load");
+	ret = zif_repo_md_load (ZIF_REPO_MD (md), cancellable, completion, &error);
+	if (ret)
+		egg_test_success (test, NULL);
+	else
+		egg_test_failed (test, "failed to load '%s'", error->message);
+
+	/************************************************************/
+	egg_test_title (test, "loaded");
+	egg_test_assert (test, md->priv->loaded);
+
+	/************************************************************/
+	egg_test_title (test, "search for files");
+	array = zif_repo_md_filelists_search_file (md, "/usr/bin/gnome-power-manager", cancellable, completion, &error);
+	if (array != NULL)
+		egg_test_success (test, NULL);
+	else
+		egg_test_failed (test, "failed to search '%s'", error->message);
+
+	/************************************************************/
+	egg_test_title (test, "correct number");
+	egg_test_assert (test, array->len == 1);
+
+	/************************************************************/
+	egg_test_title (test, "correct value");
+	pkgid = g_ptr_array_index (array, 0);
+	if (pkgid[0] != '\0' && strlen (pkgid) == 64)
+		egg_test_success (test, NULL);
+	else
+		egg_test_failed (test, "failed to get a correct pkgId '%s' (%i)", pkgid, strlen (pkgid));
+	g_ptr_array_unref (array);
+
+	g_object_unref (md);
+	g_object_unref (cancellable);
+	g_object_unref (completion);
+
+	egg_test_end (test);
+}
+#endif
+
diff --git a/backends/yum/libzif/zif-repo-md-filelists.h b/backends/yum/libzif/zif-repo-md-filelists.h
new file mode 100644
index 0000000..465fd4f
--- /dev/null
+++ b/backends/yum/libzif/zif-repo-md-filelists.h
@@ -0,0 +1,68 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2009 Richard Hughes <richard at hughsie.com>
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#if !defined (__ZIF_H_INSIDE__) && !defined (ZIF_COMPILATION)
+#error "Only <zif.h> can be included directly."
+#endif
+
+#ifndef __ZIF_REPO_MD_FILELISTS_H
+#define __ZIF_REPO_MD_FILELISTS_H
+
+#include <glib-object.h>
+
+#include "zif-repo-md.h"
+
+G_BEGIN_DECLS
+
+#define ZIF_TYPE_REPO_MD_FILELISTS		(zif_repo_md_filelists_get_type ())
+#define ZIF_REPO_MD_FILELISTS(o)		(G_TYPE_CHECK_INSTANCE_CAST ((o), ZIF_TYPE_REPO_MD_FILELISTS, ZifRepoMdFilelists))
+#define ZIF_REPO_MD_FILELISTS_CLASS(k)		(G_TYPE_CHECK_CLASS_CAST((k), ZIF_TYPE_REPO_MD_FILELISTS, ZifRepoMdFilelistsClass))
+#define ZIF_IS_REPO_MD_FILELISTS(o)		(G_TYPE_CHECK_INSTANCE_TYPE ((o), ZIF_TYPE_REPO_MD_FILELISTS))
+#define ZIF_IS_REPO_MD_FILELISTS_CLASS(k)	(G_TYPE_CHECK_CLASS_TYPE ((k), ZIF_TYPE_REPO_MD_FILELISTS))
+#define ZIF_REPO_MD_FILELISTS_GET_CLASS(o)	(G_TYPE_INSTANCE_GET_CLASS ((o), ZIF_TYPE_REPO_MD_FILELISTS, ZifRepoMdFilelistsClass))
+
+typedef struct _ZifRepoMdFilelists		ZifRepoMdFilelists;
+typedef struct _ZifRepoMdFilelistsPrivate	ZifRepoMdFilelistsPrivate;
+typedef struct _ZifRepoMdFilelistsClass		ZifRepoMdFilelistsClass;
+
+struct _ZifRepoMdFilelists
+{
+	ZifRepoMd			 parent;
+	ZifRepoMdFilelistsPrivate	*priv;
+};
+
+struct _ZifRepoMdFilelistsClass
+{
+	ZifRepoMdClass			 parent_class;
+};
+
+GType			 zif_repo_md_filelists_get_type		(void);
+ZifRepoMdFilelists	*zif_repo_md_filelists_new		(void);
+GPtrArray		*zif_repo_md_filelists_search_file	(ZifRepoMdFilelists	*md,
+								 const gchar		*search,
+								 GCancellable		*cancellable,
+								 ZifCompletion		*completion,
+								 GError			**error);
+
+G_END_DECLS
+
+#endif /* __ZIF_REPO_MD_FILELISTS_H */
+
diff --git a/backends/yum/libzif/zif-repo-md-metalink.c b/backends/yum/libzif/zif-repo-md-metalink.c
new file mode 100644
index 0000000..8f07a2e
--- /dev/null
+++ b/backends/yum/libzif/zif-repo-md-metalink.c
@@ -0,0 +1,483 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2009 Richard Hughes <richard at hughsie.com>
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+/**
+ * SECTION:zif-repo-md-metalink
+ * @short_description: Metalink metadata functionality
+ *
+ * Provide access to the metalink repo metadata.
+ * This object is a subclass of #ZifRepoMd
+ */
+
+#ifdef HAVE_CONFIG_H
+#  include <config.h>
+#endif
+
+#include <stdlib.h>
+#include <glib.h>
+
+#include "zif-repo-md.h"
+#include "zif-repo-md-metalink.h"
+#include "zif-config.h"
+
+#include "egg-debug.h"
+#include "egg-string.h"
+
+#define ZIF_REPO_MD_METALINK_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), ZIF_TYPE_REPO_MD_METALINK, ZifRepoMdMetalinkPrivate))
+
+typedef enum {
+	ZIF_REPO_MD_METALINK_PARSER_SECTION_URL,
+	ZIF_REPO_MD_METALINK_PARSER_SECTION_UNKNOWN
+} ZifRepoMdMetalinkParserSection;
+
+typedef enum {
+	ZIF_REPO_MD_METALINK_PROTOCOL_TYPE_FTP,
+	ZIF_REPO_MD_METALINK_PROTOCOL_TYPE_HTTP,
+	ZIF_REPO_MD_METALINK_PROTOCOL_TYPE_RSYNC,
+	ZIF_REPO_MD_METALINK_PROTOCOL_TYPE_UNKNOWN
+} ZifRepoMdMetalinkProtocolType;
+
+typedef struct {
+	ZifRepoMdMetalinkProtocolType	 protocol;
+	gchar				*uri;
+	guint				 preference;
+} ZifRepoMdMetalinkData;
+
+/**
+ * ZifRepoMdMetalinkPrivate:
+ *
+ * Private #ZifRepoMdMetalink data
+ **/
+struct _ZifRepoMdMetalinkPrivate
+{
+	gboolean			 loaded;
+	GPtrArray			*array;
+	ZifConfig			*config;
+	/* for parser */
+	ZifRepoMdMetalinkParserSection	 section;
+	ZifRepoMdMetalinkData		*temp;
+};
+
+G_DEFINE_TYPE (ZifRepoMdMetalink, zif_repo_md_metalink, ZIF_TYPE_REPO_MD)
+
+/**
+ * zif_repo_md_metalink_protocol_type_from_text:
+ **/
+static ZifRepoMdMetalinkProtocolType
+zif_repo_md_metalink_protocol_type_from_text (const gchar *type_text)
+{
+	if (g_strcmp0 (type_text, "ftp") == 0)
+		return ZIF_REPO_MD_METALINK_PROTOCOL_TYPE_FTP;
+	if (g_strcmp0 (type_text, "http") == 0)
+		return ZIF_REPO_MD_METALINK_PROTOCOL_TYPE_HTTP;
+	if (g_strcmp0 (type_text, "rsync") == 0)
+		return ZIF_REPO_MD_METALINK_PROTOCOL_TYPE_RSYNC;
+	return ZIF_REPO_MD_METALINK_PROTOCOL_TYPE_UNKNOWN;
+}
+
+/**
+ * zif_repo_md_metalink_parser_start_element:
+ **/
+static void
+zif_repo_md_metalink_parser_start_element (GMarkupParseContext *context, const gchar *element_name,
+					   const gchar **attribute_names, const gchar **attribute_values,
+					   gpointer user_data, GError **error)
+{
+	guint i;
+	ZifRepoMdMetalink *metalink = user_data;
+
+	g_return_if_fail (ZIF_IS_REPO_MD_METALINK (metalink));
+	g_return_if_fail (metalink->priv->temp == NULL);
+
+	/* just ignore non url entries */
+	if (g_strcmp0 (element_name, "url") != 0) {
+		metalink->priv->temp = NULL;
+		metalink->priv->section = ZIF_REPO_MD_METALINK_PARSER_SECTION_UNKNOWN;
+		goto out;
+	}
+
+	/* create new element */
+	metalink->priv->section = ZIF_REPO_MD_METALINK_PARSER_SECTION_URL;
+	metalink->priv->temp = g_new0 (ZifRepoMdMetalinkData, 1);
+
+	/* read keys */
+	for (i=0; attribute_names[i] != NULL; i++) {
+		if (g_strcmp0 (attribute_names[i], "protocol") == 0)
+			metalink->priv->temp->protocol = zif_repo_md_metalink_protocol_type_from_text (attribute_values[i]);
+		if (g_strcmp0 (attribute_names[i], "preference") == 0)
+			metalink->priv->temp->preference = atoi (attribute_values[i]);
+	}
+
+	/* add to array */
+	g_ptr_array_add (metalink->priv->array, metalink->priv->temp);
+out:
+	return;
+}
+
+/**
+ * zif_repo_md_metalink_parser_end_element:
+ **/
+static void
+zif_repo_md_metalink_parser_end_element (GMarkupParseContext *context, const gchar *element_name,
+					 gpointer user_data, GError **error)
+{
+	ZifRepoMdMetalink *metalink = user_data;
+	metalink->priv->temp = NULL;
+	metalink->priv->section = ZIF_REPO_MD_METALINK_PARSER_SECTION_UNKNOWN;
+}
+
+/**
+ * zif_repo_md_metalink_parser_text:
+ **/
+static void
+zif_repo_md_metalink_parser_text (GMarkupParseContext *context, const gchar *text, gsize text_len,
+				  gpointer user_data, GError **error)
+
+{
+	ZifRepoMdMetalink *metalink = user_data;
+
+	if (metalink->priv->section != ZIF_REPO_MD_METALINK_PARSER_SECTION_URL)
+		goto out;
+
+	/* shouldn't happen */
+	if (metalink->priv->temp == NULL) {
+		egg_warning ("no data, so cannot save %s!", text);
+		goto out;
+	}
+
+	/* save uri */
+	if (metalink->priv->temp->uri != NULL) {
+		egg_warning ("previously set uri to '%s', cannot overwrite with '%s'", metalink->priv->temp->uri, text);
+		goto out;
+	}
+	metalink->priv->temp->uri = g_strdup (text);
+out:
+	return;
+}
+
+/**
+ * zif_repo_md_metalink_unload:
+ **/
+static gboolean
+zif_repo_md_metalink_unload (ZifRepoMd *md, GCancellable *cancellable, ZifCompletion *completion, GError **error)
+{
+	gboolean ret = FALSE;
+	return ret;
+}
+
+/**
+ * zif_repo_md_metalink_load:
+ **/
+static gboolean
+zif_repo_md_metalink_load (ZifRepoMd *md, GCancellable *cancellable, ZifCompletion *completion, GError **error)
+{
+	gboolean ret = TRUE;
+	gchar *contents = NULL;
+	const gchar *filename;
+	gsize size;
+	GMarkupParseContext *context = NULL;
+	const GMarkupParser gpk_repo_md_metalink_markup_parser = {
+		zif_repo_md_metalink_parser_start_element,
+		zif_repo_md_metalink_parser_end_element,
+		zif_repo_md_metalink_parser_text,
+		NULL, /* passthrough */
+		NULL /* error */
+	};
+	ZifRepoMdMetalink *metalink = ZIF_REPO_MD_METALINK (md);
+
+	g_return_val_if_fail (ZIF_IS_REPO_MD_METALINK (md), FALSE);
+
+	/* already loaded */
+	if (metalink->priv->loaded)
+		goto out;
+
+	/* get filename */
+	filename = zif_repo_md_get_filename_uncompressed (md);
+	if (filename == NULL) {
+		if (error != NULL)
+			*error = g_error_new (1, 0, "failed to get filename for metalink");
+		goto out;
+	}
+
+	/* open database */
+	egg_debug ("filename = %s", filename);
+
+	/* get repo contents */
+	ret = g_file_get_contents (filename, &contents, &size, error);
+	if (!ret)
+		goto out;
+
+	/* create parser */
+	context = g_markup_parse_context_new (&gpk_repo_md_metalink_markup_parser, G_MARKUP_PREFIX_ERROR_POSITION, metalink, NULL);
+
+	/* parse data */
+	ret = g_markup_parse_context_parse (context, contents, (gssize) size, error);
+	if (!ret)
+		goto out;
+
+	metalink->priv->loaded = TRUE;
+out:
+	if (context != NULL)
+		g_markup_parse_context_free (context);
+	g_free (contents);
+	return ret;
+}
+
+/**
+ * zif_repo_md_metalink_get_uris:
+ * @md: the #ZifRepoMdMetalink object
+ * @threshold: the threshold in percent
+ * @cancellable: a #GCancellable which is used to cancel tasks, or %NULL
+ * @completion: a #ZifCompletion to use for progress reporting
+ * @error: a #GError which is used on failure, or %NULL
+ *
+ * Finds all mirrors we should use.
+ *
+ * Return value: the uris to use as an array of strings
+ **/
+GPtrArray *
+zif_repo_md_metalink_get_uris (ZifRepoMdMetalink *md, guint threshold, GCancellable *cancellable, ZifCompletion *completion, GError **error)
+{
+	gboolean ret;
+	guint len;
+	gchar *uri;
+	GPtrArray *array = NULL;
+	GError *error_local = NULL;
+	ZifRepoMdMetalinkData *data;
+	guint i;
+	ZifRepoMdMetalink *metalink = ZIF_REPO_MD_METALINK (md);
+
+	g_return_val_if_fail (ZIF_IS_REPO_MD_METALINK (md), FALSE);
+
+	/* if not already loaded, load */
+	if (!metalink->priv->loaded) {
+		ret = zif_repo_md_load (ZIF_REPO_MD (md), cancellable, completion, &error_local);
+		if (!ret) {
+			if (error != NULL)
+				*error = g_error_new (1, 0, "failed to get mirrors from metalink: %s", error_local->message);
+			g_error_free (error_local);
+			goto out;
+		}
+	}
+
+	/* get list */
+	array = g_ptr_array_new_with_free_func ((GDestroyNotify) g_free);
+	len = metalink->priv->array->len;
+	for (i=0; i<len; i++) {
+		data = g_ptr_array_index (metalink->priv->array, i);
+
+		/* ignore not http mirrors */
+		if (data->protocol != ZIF_REPO_MD_METALINK_PROTOCOL_TYPE_HTTP)
+			continue;
+
+		/* ignore low priority */
+		if (data->preference >= threshold) {
+			uri = zif_config_expand_substitutions (md->priv->config, data->uri, &error_local);
+			if (uri == NULL) {
+				if (error != NULL)
+					*error = g_error_new (1, 0, "failed to expand substitutions: %s", error_local->message);
+				g_error_free (error_local);
+				/* rip apart what we've done already */
+				g_ptr_array_unref (array);
+				array = NULL;
+				goto out;
+			}
+			g_ptr_array_add (array, uri);
+		}
+	}
+out:
+	return array;
+}
+
+/**
+ * zif_repo_md_metalink_free_data:
+ **/
+static void
+zif_repo_md_metalink_free_data (ZifRepoMdMetalinkData *data)
+{
+	g_free (data->uri);
+	g_free (data);
+}
+
+/**
+ * zif_repo_md_metalink_finalize:
+ **/
+static void
+zif_repo_md_metalink_finalize (GObject *object)
+{
+	ZifRepoMdMetalink *md;
+
+	g_return_if_fail (object != NULL);
+	g_return_if_fail (ZIF_IS_REPO_MD_METALINK (object));
+	md = ZIF_REPO_MD_METALINK (object);
+
+	g_ptr_array_unref (md->priv->array);
+	g_object_unref (md->priv->config);
+
+	G_OBJECT_CLASS (zif_repo_md_metalink_parent_class)->finalize (object);
+}
+
+/**
+ * zif_repo_md_metalink_class_init:
+ **/
+static void
+zif_repo_md_metalink_class_init (ZifRepoMdMetalinkClass *klass)
+{
+	GObjectClass *object_class = G_OBJECT_CLASS (klass);
+	ZifRepoMdClass *repo_md_class = ZIF_REPO_MD_CLASS (klass);
+	object_class->finalize = zif_repo_md_metalink_finalize;
+
+	/* map */
+	repo_md_class->load = zif_repo_md_metalink_load;
+	repo_md_class->unload = zif_repo_md_metalink_unload;
+	g_type_class_add_private (klass, sizeof (ZifRepoMdMetalinkPrivate));
+}
+
+/**
+ * zif_repo_md_metalink_init:
+ **/
+static void
+zif_repo_md_metalink_init (ZifRepoMdMetalink *md)
+{
+	md->priv = ZIF_REPO_MD_METALINK_GET_PRIVATE (md);
+	md->priv->loaded = FALSE;
+	md->priv->config = zif_config_new ();
+	md->priv->array = g_ptr_array_new_with_free_func ((GDestroyNotify) zif_repo_md_metalink_free_data);
+}
+
+/**
+ * zif_repo_md_metalink_new:
+ *
+ * Return value: A new #ZifRepoMdMetalink class instance.
+ **/
+ZifRepoMdMetalink *
+zif_repo_md_metalink_new (void)
+{
+	ZifRepoMdMetalink *md;
+	md = g_object_new (ZIF_TYPE_REPO_MD_METALINK, NULL);
+	return ZIF_REPO_MD_METALINK (md);
+}
+
+/***************************************************************************
+ ***                          MAKE CHECK TESTS                           ***
+ ***************************************************************************/
+#ifdef EGG_TEST
+#include "egg-test.h"
+
+void
+zif_repo_md_metalink_test (EggTest *test)
+{
+	ZifRepoMdMetalink *md;
+	gboolean ret;
+	GError *error = NULL;
+	GPtrArray *array;
+	const gchar *uri;
+	GCancellable *cancellable;
+	ZifCompletion *completion;
+	ZifConfig *config;
+
+	if (!egg_test_start (test, "ZifRepoMdMetalink"))
+		return;
+
+	/* use */
+	cancellable = g_cancellable_new ();
+	completion = zif_completion_new ();
+	config = zif_config_new ();
+	zif_config_set_filename (config, "../test/etc/yum.conf", NULL);
+
+	/************************************************************/
+	egg_test_title (test, "get repo_md_metalink md");
+	md = zif_repo_md_metalink_new ();
+	egg_test_assert (test, md != NULL);
+
+	/************************************************************/
+	egg_test_title (test, "loaded");
+	egg_test_assert (test, !md->priv->loaded);
+
+	/************************************************************/
+	egg_test_title (test, "set id");
+	ret = zif_repo_md_set_id (ZIF_REPO_MD (md), "fedora");
+	if (ret)
+		egg_test_success (test, NULL);
+	else
+		egg_test_failed (test, "failed to set");
+
+	/************************************************************/
+	egg_test_title (test, "set type");
+	ret = zif_repo_md_set_mdtype (ZIF_REPO_MD (md), ZIF_REPO_MD_TYPE_METALINK);
+	if (ret)
+		egg_test_success (test, NULL);
+	else
+		egg_test_failed (test, "failed to set");
+
+	/************************************************************/
+	egg_test_title (test, "set filename");
+	ret = zif_repo_md_set_filename (ZIF_REPO_MD (md), "../test/cache/fedora/metalink.xml");
+	if (ret)
+		egg_test_success (test, NULL);
+	else
+		egg_test_failed (test, "failed to set");
+
+	/************************************************************/
+	egg_test_title (test, "load");
+	ret = zif_repo_md_load (ZIF_REPO_MD (md), cancellable, completion, &error);
+	if (ret)
+		egg_test_success (test, NULL);
+	else
+		egg_test_failed (test, "failed to load '%s'", error->message);
+
+	/************************************************************/
+	egg_test_title (test, "loaded");
+	egg_test_assert (test, md->priv->loaded);
+
+	/************************************************************/
+	egg_test_title (test, "get uris");
+	array = zif_repo_md_metalink_get_uris (md, 50, cancellable, completion, &error);
+	if (array != NULL)
+		egg_test_success (test, NULL);
+	else
+		egg_test_failed (test, "failed to search '%s'", error->message);
+
+	/************************************************************/
+	egg_test_title (test, "correct number");
+	if (array->len == 47)
+		egg_test_success (test, NULL);
+	else
+		egg_test_failed (test, "incorrect value %i", array->len);
+
+	/************************************************************/
+	egg_test_title (test, "correct value");
+	uri = g_ptr_array_index (array, 0);
+	if (g_strcmp0 (uri, "http://www.mirrorservice.org/sites/download.fedora.redhat.com/pub/fedora/linux/releases/12/Everything/i386/os/repodata/repomd.xml") == 0)
+		egg_test_success (test, NULL);
+	else
+		egg_test_failed (test, "failed to get correct url '%s'", uri);
+	g_ptr_array_unref (array);
+
+	g_object_unref (md);
+	g_object_unref (cancellable);
+	g_object_unref (completion);
+	g_object_unref (config);
+
+	egg_test_end (test);
+}
+#endif
+
diff --git a/backends/yum/libzif/zif-repo-md-metalink.h b/backends/yum/libzif/zif-repo-md-metalink.h
new file mode 100644
index 0000000..3d2971f
--- /dev/null
+++ b/backends/yum/libzif/zif-repo-md-metalink.h
@@ -0,0 +1,68 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2009 Richard Hughes <richard at hughsie.com>
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#if !defined (__ZIF_H_INSIDE__) && !defined (ZIF_COMPILATION)
+#error "Only <zif.h> can be included directly."
+#endif
+
+#ifndef __ZIF_REPO_MD_METALINK_H
+#define __ZIF_REPO_MD_METALINK_H
+
+#include <glib-object.h>
+
+#include "zif-repo-md.h"
+
+G_BEGIN_DECLS
+
+#define ZIF_TYPE_REPO_MD_METALINK		(zif_repo_md_metalink_get_type ())
+#define ZIF_REPO_MD_METALINK(o)			(G_TYPE_CHECK_INSTANCE_CAST ((o), ZIF_TYPE_REPO_MD_METALINK, ZifRepoMdMetalink))
+#define ZIF_REPO_MD_METALINK_CLASS(k)		(G_TYPE_CHECK_CLASS_CAST((k), ZIF_TYPE_REPO_MD_METALINK, ZifRepoMdMetalinkClass))
+#define ZIF_IS_REPO_MD_METALINK(o)		(G_TYPE_CHECK_INSTANCE_TYPE ((o), ZIF_TYPE_REPO_MD_METALINK))
+#define ZIF_IS_REPO_MD_METALINK_CLASS(k)	(G_TYPE_CHECK_CLASS_TYPE ((k), ZIF_TYPE_REPO_MD_METALINK))
+#define ZIF_REPO_MD_METALINK_GET_CLASS(o)	(G_TYPE_INSTANCE_GET_CLASS ((o), ZIF_TYPE_REPO_MD_METALINK, ZifRepoMdMetalinkClass))
+
+typedef struct _ZifRepoMdMetalink		ZifRepoMdMetalink;
+typedef struct _ZifRepoMdMetalinkPrivate	ZifRepoMdMetalinkPrivate;
+typedef struct _ZifRepoMdMetalinkClass		ZifRepoMdMetalinkClass;
+
+struct _ZifRepoMdMetalink
+{
+	ZifRepoMd			 parent;
+	ZifRepoMdMetalinkPrivate	*priv;
+};
+
+struct _ZifRepoMdMetalinkClass
+{
+	ZifRepoMdClass			 parent_class;
+};
+
+GType		 zif_repo_md_metalink_get_type		(void);
+ZifRepoMdMetalink *zif_repo_md_metalink_new		(void);
+GPtrArray	*zif_repo_md_metalink_get_uris		(ZifRepoMdMetalink	*md,
+							 guint			 threshold,
+							 GCancellable		*cancellable,
+							 ZifCompletion		*completion,
+							 GError			**error);
+
+G_END_DECLS
+
+#endif /* __ZIF_REPO_MD_METALINK_H */
+
diff --git a/backends/yum/libzif/zif-repo-md-mirrorlist.c b/backends/yum/libzif/zif-repo-md-mirrorlist.c
new file mode 100644
index 0000000..80384ec
--- /dev/null
+++ b/backends/yum/libzif/zif-repo-md-mirrorlist.c
@@ -0,0 +1,342 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2009 Richard Hughes <richard at hughsie.com>
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+/**
+ * SECTION:zif-repo-md-mirrorlist
+ * @short_description: Mirrorlist metadata functionality
+ *
+ * Provide access to the mirrorlist repo metadata.
+ * This object is a subclass of #ZifRepoMd
+ */
+
+#ifdef HAVE_CONFIG_H
+#  include <config.h>
+#endif
+
+#include <stdlib.h>
+#include <glib.h>
+
+#include "zif-repo-md.h"
+#include "zif-repo-md-mirrorlist.h"
+#include "zif-config.h"
+
+#include "egg-debug.h"
+#include "egg-string.h"
+
+#define ZIF_REPO_MD_MIRRORLIST_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), ZIF_TYPE_REPO_MD_MIRRORLIST, ZifRepoMdMirrorlistPrivate))
+
+/**
+ * ZifRepoMdMirrorlistPrivate:
+ *
+ * Private #ZifRepoMdMirrorlist data
+ **/
+struct _ZifRepoMdMirrorlistPrivate
+{
+	gboolean			 loaded;
+	GPtrArray			*array;
+	ZifConfig			*config;
+};
+
+G_DEFINE_TYPE (ZifRepoMdMirrorlist, zif_repo_md_mirrorlist, ZIF_TYPE_REPO_MD)
+
+/**
+ * zif_repo_md_mirrorlist_unload:
+ **/
+static gboolean
+zif_repo_md_mirrorlist_unload (ZifRepoMd *md, GCancellable *cancellable, ZifCompletion *completion, GError **error)
+{
+	gboolean ret = FALSE;
+	return ret;
+}
+
+/**
+ * zif_repo_md_mirrorlist_load:
+ **/
+static gboolean
+zif_repo_md_mirrorlist_load (ZifRepoMd *md, GCancellable *cancellable, ZifCompletion *completion, GError **error)
+{
+	gboolean ret = TRUE;
+	gchar *contents = NULL;
+	const gchar *filename;
+	gchar **lines = NULL;
+	guint i;
+	ZifRepoMdMirrorlist *mirrorlist = ZIF_REPO_MD_MIRRORLIST (md);
+
+	g_return_val_if_fail (ZIF_IS_REPO_MD_MIRRORLIST (md), FALSE);
+
+	/* already loaded */
+	if (mirrorlist->priv->loaded)
+		goto out;
+
+	/* get filename */
+	filename = zif_repo_md_get_filename_uncompressed (md);
+	if (filename == NULL) {
+		if (error != NULL)
+			*error = g_error_new (1, 0, "failed to get filename for mirrorlist");
+		goto out;
+	}
+
+	/* open database */
+	egg_debug ("filename = %s", filename);
+
+	/* get repo contents */
+	ret = g_file_get_contents (filename, &contents, NULL, error);
+	if (!ret)
+		goto out;
+
+	/* split, and add uris */
+	lines = g_strsplit (contents, "\n", -1);
+	for (i=0; lines[i] != NULL; i++) {
+		if (lines[i][0] == '\0' ||
+		    lines[i][0] == '#')
+			continue;
+		if (g_str_has_prefix (lines[i], "http://"))
+			g_ptr_array_add (mirrorlist->priv->array, g_strdup (lines[i]));
+	}
+
+	mirrorlist->priv->loaded = TRUE;
+out:
+	g_strfreev (lines);
+	g_free (contents);
+	return ret;
+}
+
+/**
+ * zif_repo_md_mirrorlist_get_uris:
+ * @md: the #ZifRepoMdMirrorlist object
+ * @cancellable: a #GCancellable which is used to cancel tasks, or %NULL
+ * @completion: a #ZifCompletion to use for progress reporting
+ * @error: a #GError which is used on failure, or %NULL
+ *
+ * Finds all mirrors we should use.
+ *
+ * Return value: the uris to use as an array of strings
+ **/
+GPtrArray *
+zif_repo_md_mirrorlist_get_uris (ZifRepoMdMirrorlist *md, GCancellable *cancellable, ZifCompletion *completion, GError **error)
+{
+	gboolean ret;
+	guint len;
+	GPtrArray *array = NULL;
+	GError *error_local = NULL;
+	const gchar *data;
+	gchar *uri;
+	guint i;
+	ZifRepoMdMirrorlist *mirrorlist = ZIF_REPO_MD_MIRRORLIST (md);
+
+	g_return_val_if_fail (ZIF_IS_REPO_MD_MIRRORLIST (md), FALSE);
+
+	/* if not already loaded, load */
+	if (!mirrorlist->priv->loaded) {
+		ret = zif_repo_md_load (ZIF_REPO_MD (md), cancellable, completion, &error_local);
+		if (!ret) {
+			if (error != NULL)
+				*error = g_error_new (1, 0, "failed to get uris from mirrorlist: %s", error_local->message);
+			g_error_free (error_local);
+			goto out;
+		}
+	}
+
+	/* get list */
+	array = g_ptr_array_new_with_free_func ((GDestroyNotify) g_free);
+	len = mirrorlist->priv->array->len;
+	for (i=0; i<len; i++) {
+		data = g_ptr_array_index (mirrorlist->priv->array, i);
+		uri = zif_config_expand_substitutions (md->priv->config, data, &error_local);
+		if (uri == NULL) {
+			if (error != NULL)
+				*error = g_error_new (1, 0, "failed to expand substitutions: %s", error_local->message);
+			g_error_free (error_local);
+			/* rip apart what we've done already */
+			g_ptr_array_unref (array);
+			array = NULL;
+			goto out;
+		}
+		g_ptr_array_add (array, uri);
+	}
+out:
+	return array;
+}
+
+/**
+ * zif_repo_md_mirrorlist_finalize:
+ **/
+static void
+zif_repo_md_mirrorlist_finalize (GObject *object)
+{
+	ZifRepoMdMirrorlist *md;
+
+	g_return_if_fail (object != NULL);
+	g_return_if_fail (ZIF_IS_REPO_MD_MIRRORLIST (object));
+	md = ZIF_REPO_MD_MIRRORLIST (object);
+
+	g_ptr_array_unref (md->priv->array);
+	g_object_unref (md->priv->config);
+
+	G_OBJECT_CLASS (zif_repo_md_mirrorlist_parent_class)->finalize (object);
+}
+
+/**
+ * zif_repo_md_mirrorlist_class_init:
+ **/
+static void
+zif_repo_md_mirrorlist_class_init (ZifRepoMdMirrorlistClass *klass)
+{
+	GObjectClass *object_class = G_OBJECT_CLASS (klass);
+	ZifRepoMdClass *repo_md_class = ZIF_REPO_MD_CLASS (klass);
+	object_class->finalize = zif_repo_md_mirrorlist_finalize;
+
+	/* map */
+	repo_md_class->load = zif_repo_md_mirrorlist_load;
+	repo_md_class->unload = zif_repo_md_mirrorlist_unload;
+	g_type_class_add_private (klass, sizeof (ZifRepoMdMirrorlistPrivate));
+}
+
+/**
+ * zif_repo_md_mirrorlist_init:
+ **/
+static void
+zif_repo_md_mirrorlist_init (ZifRepoMdMirrorlist *md)
+{
+	md->priv = ZIF_REPO_MD_MIRRORLIST_GET_PRIVATE (md);
+	md->priv->loaded = FALSE;
+	md->priv->config = zif_config_new ();
+	md->priv->array = g_ptr_array_new_with_free_func ((GDestroyNotify) g_free);
+}
+
+/**
+ * zif_repo_md_mirrorlist_new:
+ *
+ * Return value: A new #ZifRepoMdMirrorlist class instance.
+ **/
+ZifRepoMdMirrorlist *
+zif_repo_md_mirrorlist_new (void)
+{
+	ZifRepoMdMirrorlist *md;
+	md = g_object_new (ZIF_TYPE_REPO_MD_MIRRORLIST, NULL);
+	return ZIF_REPO_MD_MIRRORLIST (md);
+}
+
+/***************************************************************************
+ ***                          MAKE CHECK TESTS                           ***
+ ***************************************************************************/
+#ifdef EGG_TEST
+#include "egg-test.h"
+
+void
+zif_repo_md_mirrorlist_test (EggTest *test)
+{
+	ZifRepoMdMirrorlist *md;
+	gboolean ret;
+	GError *error = NULL;
+	GPtrArray *array;
+	const gchar *uri;
+	GCancellable *cancellable;
+	ZifCompletion *completion;
+	ZifConfig *config;
+
+	if (!egg_test_start (test, "ZifRepoMdMirrorlist"))
+		return;
+
+	/* use */
+	cancellable = g_cancellable_new ();
+	completion = zif_completion_new ();
+	config = zif_config_new ();
+	zif_config_set_filename (config, "../test/etc/yum.conf", NULL);
+
+	/************************************************************/
+	egg_test_title (test, "get repo_md_mirrorlist md");
+	md = zif_repo_md_mirrorlist_new ();
+	egg_test_assert (test, md != NULL);
+
+	/************************************************************/
+	egg_test_title (test, "loaded");
+	egg_test_assert (test, !md->priv->loaded);
+
+	/************************************************************/
+	egg_test_title (test, "set id");
+	ret = zif_repo_md_set_id (ZIF_REPO_MD (md), "fedora");
+	if (ret)
+		egg_test_success (test, NULL);
+	else
+		egg_test_failed (test, "failed to set");
+
+	/************************************************************/
+	egg_test_title (test, "set type");
+	ret = zif_repo_md_set_mdtype (ZIF_REPO_MD (md), ZIF_REPO_MD_TYPE_MIRRORLIST);
+	if (ret)
+		egg_test_success (test, NULL);
+	else
+		egg_test_failed (test, "failed to set");
+
+	/************************************************************/
+	egg_test_title (test, "set filename");
+	ret = zif_repo_md_set_filename (ZIF_REPO_MD (md), "../test/cache/mirrorlist.txt");
+	if (ret)
+		egg_test_success (test, NULL);
+	else
+		egg_test_failed (test, "failed to set");
+
+	/************************************************************/
+	egg_test_title (test, "load");
+	ret = zif_repo_md_load (ZIF_REPO_MD (md), cancellable, completion, &error);
+	if (ret)
+		egg_test_success (test, NULL);
+	else
+		egg_test_failed (test, "failed to load '%s'", error->message);
+
+	/************************************************************/
+	egg_test_title (test, "loaded");
+	egg_test_assert (test, md->priv->loaded);
+
+	/************************************************************/
+	egg_test_title (test, "get uris");
+	array = zif_repo_md_mirrorlist_get_uris (md, cancellable, completion, &error);
+	if (array != NULL)
+		egg_test_success (test, NULL);
+	else
+		egg_test_failed (test, "failed to search '%s'", error->message);
+
+	/************************************************************/
+	egg_test_title (test, "correct number");
+	if (array->len == 3)
+		egg_test_success (test, NULL);
+	else
+		egg_test_failed (test, "incorrect value %i", array->len);
+
+	/************************************************************/
+	egg_test_title (test, "correct value");
+	uri = g_ptr_array_index (array, 0);
+	if (g_strcmp0 (uri, "http://rpm.livna.org/repo/11/i386/") == 0)
+		egg_test_success (test, NULL);
+	else
+		egg_test_failed (test, "failed to get correct url '%s'", uri);
+	g_ptr_array_unref (array);
+
+	g_object_unref (md);
+	g_object_unref (cancellable);
+	g_object_unref (completion);
+	g_object_unref (config);
+
+	egg_test_end (test);
+}
+#endif
+
diff --git a/backends/yum/libzif/zif-repo-md-mirrorlist.h b/backends/yum/libzif/zif-repo-md-mirrorlist.h
new file mode 100644
index 0000000..77cb548
--- /dev/null
+++ b/backends/yum/libzif/zif-repo-md-mirrorlist.h
@@ -0,0 +1,67 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2009 Richard Hughes <richard at hughsie.com>
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#if !defined (__ZIF_H_INSIDE__) && !defined (ZIF_COMPILATION)
+#error "Only <zif.h> can be included directly."
+#endif
+
+#ifndef __ZIF_REPO_MD_MIRRORLIST_H
+#define __ZIF_REPO_MD_MIRRORLIST_H
+
+#include <glib-object.h>
+
+#include "zif-repo-md.h"
+
+G_BEGIN_DECLS
+
+#define ZIF_TYPE_REPO_MD_MIRRORLIST		(zif_repo_md_mirrorlist_get_type ())
+#define ZIF_REPO_MD_MIRRORLIST(o)		(G_TYPE_CHECK_INSTANCE_CAST ((o), ZIF_TYPE_REPO_MD_MIRRORLIST, ZifRepoMdMirrorlist))
+#define ZIF_REPO_MD_MIRRORLIST_CLASS(k)		(G_TYPE_CHECK_CLASS_CAST((k), ZIF_TYPE_REPO_MD_MIRRORLIST, ZifRepoMdMirrorlistClass))
+#define ZIF_IS_REPO_MD_MIRRORLIST(o)		(G_TYPE_CHECK_INSTANCE_TYPE ((o), ZIF_TYPE_REPO_MD_MIRRORLIST))
+#define ZIF_IS_REPO_MD_MIRRORLIST_CLASS(k)	(G_TYPE_CHECK_CLASS_TYPE ((k), ZIF_TYPE_REPO_MD_MIRRORLIST))
+#define ZIF_REPO_MD_MIRRORLIST_GET_CLASS(o)	(G_TYPE_INSTANCE_GET_CLASS ((o), ZIF_TYPE_REPO_MD_MIRRORLIST, ZifRepoMdMirrorlistClass))
+
+typedef struct _ZifRepoMdMirrorlist		ZifRepoMdMirrorlist;
+typedef struct _ZifRepoMdMirrorlistPrivate	ZifRepoMdMirrorlistPrivate;
+typedef struct _ZifRepoMdMirrorlistClass	ZifRepoMdMirrorlistClass;
+
+struct _ZifRepoMdMirrorlist
+{
+	ZifRepoMd			 parent;
+	ZifRepoMdMirrorlistPrivate	*priv;
+};
+
+struct _ZifRepoMdMirrorlistClass
+{
+	ZifRepoMdClass			 parent_class;
+};
+
+GType		 zif_repo_md_mirrorlist_get_type		(void);
+ZifRepoMdMirrorlist *zif_repo_md_mirrorlist_new		(void);
+GPtrArray	*zif_repo_md_mirrorlist_get_uris	(ZifRepoMdMirrorlist	*md,
+							 GCancellable		*cancellable,
+							 ZifCompletion		*completion,
+							 GError			**error);
+
+G_END_DECLS
+
+#endif /* __ZIF_REPO_MD_MIRRORLIST_H */
+
diff --git a/backends/yum/libzif/zif-repo-md-primary.c b/backends/yum/libzif/zif-repo-md-primary.c
new file mode 100644
index 0000000..3bcf3cf
--- /dev/null
+++ b/backends/yum/libzif/zif-repo-md-primary.c
@@ -0,0 +1,558 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2009 Richard Hughes <richard at hughsie.com>
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+/**
+ * SECTION:zif-repo-md-primary
+ * @short_description: Primary metadata functionality
+ *
+ * Provide access to the primary repo metadata.
+ * This object is a subclass of #ZifRepoMd
+ */
+
+#ifdef HAVE_CONFIG_H
+#  include <config.h>
+#endif
+
+#include <glib.h>
+#include <string.h>
+#include <stdlib.h>
+#include <sqlite3.h>
+#include <gio/gio.h>
+
+#include "zif-repo-md.h"
+#include "zif-repo-md-primary.h"
+#include "zif-package-remote.h"
+
+#include "egg-debug.h"
+#include "egg-string.h"
+
+#define ZIF_REPO_MD_PRIMARY_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), ZIF_TYPE_REPO_MD_PRIMARY, ZifRepoMdPrimaryPrivate))
+
+/**
+ * ZifRepoMdPrimaryPrivate:
+ *
+ * Private #ZifRepoMdPrimary data
+ **/
+struct _ZifRepoMdPrimaryPrivate
+{
+	gboolean		 loaded;
+	sqlite3			*db;
+};
+
+typedef struct {
+	const gchar		*id;
+	GPtrArray		*packages;
+} ZifRepoMdPrimaryData;
+
+G_DEFINE_TYPE (ZifRepoMdPrimary, zif_repo_md_primary, ZIF_TYPE_REPO_MD)
+
+/**
+ * zif_repo_md_primary_unload:
+ **/
+static gboolean
+zif_repo_md_primary_unload (ZifRepoMd *md, GCancellable *cancellable, ZifCompletion *completion, GError **error)
+{
+	gboolean ret = FALSE;
+	return ret;
+}
+
+/**
+ * zif_repo_md_primary_load:
+ **/
+static gboolean
+zif_repo_md_primary_load (ZifRepoMd *md, GCancellable *cancellable, ZifCompletion *completion, GError **error)
+{
+	const gchar *filename;
+	gint rc;
+	ZifRepoMdPrimary *primary = ZIF_REPO_MD_PRIMARY (md);
+
+	g_return_val_if_fail (ZIF_IS_REPO_MD_PRIMARY (md), FALSE);
+
+	/* already loaded */
+	if (primary->priv->loaded)
+		goto out;
+
+	/* get filename */
+	filename = zif_repo_md_get_filename_uncompressed (md);
+	if (filename == NULL) {
+		if (error != NULL)
+			*error = g_error_new (1, 0, "failed to get filename for primary");
+		goto out;
+	}
+
+	/* open database */
+	egg_debug ("filename = %s", filename);
+	rc = sqlite3_open (filename, &primary->priv->db);
+	if (rc != 0) {
+		egg_warning ("Can't open database: %s\n", sqlite3_errmsg (primary->priv->db));
+		if (error != NULL)
+			*error = g_error_new (1, 0, "can't open database: %s", sqlite3_errmsg (primary->priv->db));
+		goto out;
+	}
+
+	/* we don't need to keep syncing */
+	sqlite3_exec (primary->priv->db, "PRAGMA synchronous=OFF", NULL, NULL, NULL);
+	primary->priv->loaded = TRUE;
+out:
+	return primary->priv->loaded;
+}
+
+/**
+ * zif_repo_md_primary_sqlite_create_package_cb:
+ **/
+static gint
+zif_repo_md_primary_sqlite_create_package_cb (void *data, gint argc, gchar **argv, gchar **col_name)
+{
+	ZifRepoMdPrimaryData *fldata = (ZifRepoMdPrimaryData *) data;
+	ZifPackageRemote *package;
+
+	package = zif_package_remote_new ();
+	zif_package_remote_set_from_repo (package, argc, col_name, argv, fldata->id, NULL);
+	g_ptr_array_add (fldata->packages, package);
+
+	return 0;
+}
+
+/**
+ * zif_repo_md_primary_search:
+ **/
+static GPtrArray *
+zif_repo_md_primary_search (ZifRepoMdPrimary *md, const gchar *pred, GCancellable *cancellable, ZifCompletion *completion, GError **error)
+{
+	gchar *statement = NULL;
+	gchar *error_msg = NULL;
+	gint rc;
+	gboolean ret;
+	GError *error_local = NULL;
+	ZifRepoMdPrimaryData *data = NULL;
+	GPtrArray *array = NULL;
+
+	/* if not already loaded, load */
+	if (!md->priv->loaded) {
+		ret = zif_repo_md_load (ZIF_REPO_MD (md), cancellable, completion, &error_local);
+		if (!ret) {
+			if (error != NULL)
+				*error = g_error_new (1, 0, "failed to load repo_md_primary file: %s", error_local->message);
+			g_error_free (error_local);
+			goto out;
+		}
+	}
+
+	/* create data struct we can pass to the callback */
+	data = g_new0 (ZifRepoMdPrimaryData, 1);
+	data->id = zif_repo_md_get_id (ZIF_REPO_MD (md));
+	data->packages = g_ptr_array_new_with_free_func ((GDestroyNotify) g_object_unref);
+
+	statement = g_strdup_printf ("SELECT pkgId, name, arch, version, "
+				     "epoch, release, summary, description, url, "
+				     "rpm_license, rpm_group, size_package, location_href FROM packages %s", pred);
+	rc = sqlite3_exec (md->priv->db, statement, zif_repo_md_primary_sqlite_create_package_cb, data, &error_msg);
+	if (rc != SQLITE_OK) {
+		if (error != NULL)
+			*error = g_error_new (1, 0, "SQL error: %s\n", error_msg);
+		sqlite3_free (error_msg);
+		g_ptr_array_unref (data->packages);
+		goto out;
+	}
+	/* list of packages */
+	array = data->packages;
+out:
+	g_free (data);
+	g_free (statement);
+	return array;
+}
+
+/**
+ * zif_repo_md_primary_resolve:
+ * @md: the #ZifRepoMdPrimary object
+ * @search: the search term, e.g. "gnome-power-manager"
+ * @cancellable: a #GCancellable which is used to cancel tasks, or %NULL
+ * @completion: a #ZifCompletion to use for progress reporting
+ * @error: a #GError which is used on failure, or %NULL
+ *
+ * Finds all remote packages that match the name exactly.
+ *
+ * Return value: an array of #ZifPackageRemote's
+ **/
+GPtrArray *
+zif_repo_md_primary_resolve (ZifRepoMdPrimary *md, const gchar *search, GCancellable *cancellable, ZifCompletion *completion, GError **error)
+{
+	gchar *pred;
+	GPtrArray *array;
+
+	g_return_val_if_fail (ZIF_IS_REPO_MD_PRIMARY (md), FALSE);
+
+	/* search with predicate */
+	pred = g_strdup_printf ("WHERE name = '%s'", search);
+	array = zif_repo_md_primary_search (md, pred, cancellable, completion, error);
+	g_free (pred);
+
+	return array;
+}
+
+/**
+ * zif_repo_md_primary_search_name:
+ * @md: the #ZifRepoMdPrimary object
+ * @search: the search term, e.g. "power"
+ * @cancellable: a #GCancellable which is used to cancel tasks, or %NULL
+ * @completion: a #ZifCompletion to use for progress reporting
+ * @error: a #GError which is used on failure, or %NULL
+ *
+ * Finds all packages that match the name.
+ *
+ * Return value: an array of #ZifPackageRemote's
+ **/
+GPtrArray *
+zif_repo_md_primary_search_name (ZifRepoMdPrimary *md, const gchar *search, GCancellable *cancellable, ZifCompletion *completion, GError **error)
+{
+	gchar *pred;
+	GPtrArray *array;
+
+	g_return_val_if_fail (ZIF_IS_REPO_MD_PRIMARY (md), FALSE);
+
+	/* search with predicate */
+	pred = g_strdup_printf ("WHERE name LIKE '%%%s%%'", search);
+	array = zif_repo_md_primary_search (md, pred, cancellable, completion, error);
+	g_free (pred);
+
+	return array;
+}
+
+/**
+ * zif_repo_md_primary_search_details:
+ * @md: the #ZifRepoMdPrimary object
+ * @search: the search term, e.g. "advanced"
+ * @cancellable: a #GCancellable which is used to cancel tasks, or %NULL
+ * @completion: a #ZifCompletion to use for progress reporting
+ * @error: a #GError which is used on failure, or %NULL
+ *
+ * Finds all packages that match the name or description.
+ *
+ * Return value: an array of #ZifPackageRemote's
+ **/
+GPtrArray *
+zif_repo_md_primary_search_details (ZifRepoMdPrimary *md, const gchar *search, GCancellable *cancellable, ZifCompletion *completion, GError **error)
+{
+	gchar *pred;
+	GPtrArray *array;
+
+	g_return_val_if_fail (ZIF_IS_REPO_MD_PRIMARY (md), FALSE);
+
+	/* search with predicate */
+	pred = g_strdup_printf ("WHERE name LIKE '%%%s%%' OR summary LIKE '%%%s%%' OR description LIKE '%%%s%%'", search, search, search);
+	array = zif_repo_md_primary_search (md, pred, cancellable, completion, error);
+	g_free (pred);
+
+	return array;
+}
+
+/**
+ * zif_repo_md_primary_search_group:
+ * @md: the #ZifRepoMdPrimary object
+ * @search: the search term, e.g. "games/console"
+ * @cancellable: a #GCancellable which is used to cancel tasks, or %NULL
+ * @completion: a #ZifCompletion to use for progress reporting
+ * @error: a #GError which is used on failure, or %NULL
+ *
+ * Finds all packages that match the group.
+ *
+ * Return value: an array of #ZifPackageRemote's
+ **/
+GPtrArray *
+zif_repo_md_primary_search_group (ZifRepoMdPrimary *md, const gchar *search, GCancellable *cancellable, ZifCompletion *completion, GError **error)
+{
+	gchar *pred;
+	GPtrArray *array;
+
+	g_return_val_if_fail (ZIF_IS_REPO_MD_PRIMARY (md), FALSE);
+
+	/* FIXME: search with predicate */
+	pred = g_strdup_printf ("WHERE group = '%s'", search);
+	array = zif_repo_md_primary_search (md, pred, cancellable, completion, error);
+	g_free (pred);
+
+	return array;
+}
+
+/**
+ * zif_repo_md_primary_search_pkgid:
+ * @md: the #ZifRepoMdPrimary object
+ * @search: the search term as a 64 bit hash
+ * @cancellable: a #GCancellable which is used to cancel tasks, or %NULL
+ * @completion: a #ZifCompletion to use for progress reporting
+ * @error: a #GError which is used on failure, or %NULL
+ *
+ * Finds all packages that match the given pkgId.
+ *
+ * Return value: an array of #ZifPackageRemote's
+ **/
+GPtrArray *
+zif_repo_md_primary_search_pkgid (ZifRepoMdPrimary *md, const gchar *search, GCancellable *cancellable, ZifCompletion *completion, GError **error)
+{
+	gchar *pred;
+	GPtrArray *array;
+
+	g_return_val_if_fail (ZIF_IS_REPO_MD_PRIMARY (md), FALSE);
+
+	/* FIXME: search with predicate */
+	pred = g_strdup_printf ("WHERE pkgid = '%s'", search);
+	array = zif_repo_md_primary_search (md, pred, cancellable, completion, error);
+	g_free (pred);
+
+	return array;
+}
+
+/**
+ * zif_repo_md_primary_find_package:
+ * @md: the #ZifRepoMdPrimary object
+ * @package_id: the PackageId to match
+ * @cancellable: a #GCancellable which is used to cancel tasks, or %NULL
+ * @completion: a #ZifCompletion to use for progress reporting
+ * @error: a #GError which is used on failure, or %NULL
+ *
+ * Finds all packages that match PackageId.
+ *
+ * Return value: an array of #ZifPackageRemote's
+ **/
+GPtrArray *
+zif_repo_md_primary_find_package (ZifRepoMdPrimary *md, const gchar *package_id, GCancellable *cancellable, ZifCompletion *completion, GError **error)
+{
+	gchar *pred;
+	GPtrArray *array;
+	gchar **split;
+
+	g_return_val_if_fail (ZIF_IS_REPO_MD_PRIMARY (md), FALSE);
+
+	/* search with predicate, TODO: search version (epoch+release) */
+	split = pk_package_id_split (package_id);
+	pred = g_strdup_printf ("WHERE name = '%s' AND arch = '%s'", split[PK_PACKAGE_ID_NAME], split[PK_PACKAGE_ID_ARCH]);
+	array = zif_repo_md_primary_search (md, pred, cancellable, completion, error);
+	g_free (pred);
+	g_strfreev (split);
+
+	return array;
+}
+
+/**
+ * zif_repo_md_primary_get_packages:
+ * @md: the #ZifRepoMdPrimary object
+ * @cancellable: a #GCancellable which is used to cancel tasks, or %NULL
+ * @completion: a #ZifCompletion to use for progress reporting
+ * @error: a #GError which is used on failure, or %NULL
+ *
+ * Returns all packages in the repo.
+ *
+ * Return value: an array of #ZifPackageRemote's
+ **/
+GPtrArray *
+zif_repo_md_primary_get_packages (ZifRepoMdPrimary *md, GCancellable *cancellable, ZifCompletion *completion, GError **error)
+{
+	GPtrArray *array;
+
+	g_return_val_if_fail (ZIF_IS_REPO_MD_PRIMARY (md), FALSE);
+
+	/* search with predicate */
+	array = zif_repo_md_primary_search (md, "", cancellable, completion, error);
+	return array;
+}
+
+/**
+ * zif_repo_md_primary_finalize:
+ **/
+static void
+zif_repo_md_primary_finalize (GObject *object)
+{
+	ZifRepoMdPrimary *md;
+
+	g_return_if_fail (object != NULL);
+	g_return_if_fail (ZIF_IS_REPO_MD_PRIMARY (object));
+	md = ZIF_REPO_MD_PRIMARY (object);
+
+	sqlite3_close (md->priv->db);
+
+	G_OBJECT_CLASS (zif_repo_md_primary_parent_class)->finalize (object);
+}
+
+/**
+ * zif_repo_md_primary_class_init:
+ **/
+static void
+zif_repo_md_primary_class_init (ZifRepoMdPrimaryClass *klass)
+{
+	GObjectClass *object_class = G_OBJECT_CLASS (klass);
+	ZifRepoMdClass *repo_md_class = ZIF_REPO_MD_CLASS (klass);
+	object_class->finalize = zif_repo_md_primary_finalize;
+
+	/* map */
+	repo_md_class->load = zif_repo_md_primary_load;
+	repo_md_class->unload = zif_repo_md_primary_unload;
+	g_type_class_add_private (klass, sizeof (ZifRepoMdPrimaryPrivate));
+}
+
+/**
+ * zif_repo_md_primary_init:
+ **/
+static void
+zif_repo_md_primary_init (ZifRepoMdPrimary *md)
+{
+	md->priv = ZIF_REPO_MD_PRIMARY_GET_PRIVATE (md);
+	md->priv->loaded = FALSE;
+	md->priv->db = NULL;
+}
+
+/**
+ * zif_repo_md_primary_new:
+ *
+ * Return value: A new #ZifRepoMdPrimary class instance.
+ **/
+ZifRepoMdPrimary *
+zif_repo_md_primary_new (void)
+{
+	ZifRepoMdPrimary *md;
+	md = g_object_new (ZIF_TYPE_REPO_MD_PRIMARY, NULL);
+	return ZIF_REPO_MD_PRIMARY (md);
+}
+
+/***************************************************************************
+ ***                          MAKE CHECK TESTS                           ***
+ ***************************************************************************/
+#ifdef EGG_TEST
+#include "egg-test.h"
+
+void
+zif_repo_md_primary_test (EggTest *test)
+{
+	ZifRepoMdPrimary *md;
+	gboolean ret;
+	GError *error = NULL;
+	GPtrArray *array;
+	ZifPackage *package;
+	ZifString *summary;
+	GCancellable *cancellable;
+	ZifCompletion *completion;
+
+	if (!egg_test_start (test, "ZifRepoMdPrimary"))
+		return;
+
+	/* use */
+	cancellable = g_cancellable_new ();
+	completion = zif_completion_new ();
+
+	/************************************************************/
+	egg_test_title (test, "get repo_md_primary md");
+	md = zif_repo_md_primary_new ();
+	egg_test_assert (test, md != NULL);
+
+	/************************************************************/
+	egg_test_title (test, "loaded");
+	egg_test_assert (test, !md->priv->loaded);
+
+	/************************************************************/
+	egg_test_title (test, "set id");
+	ret = zif_repo_md_set_id (ZIF_REPO_MD (md), "fedora");
+	if (ret)
+		egg_test_success (test, NULL);
+	else
+		egg_test_failed (test, "failed to set");
+
+	/************************************************************/
+	egg_test_title (test, "set type");
+	ret = zif_repo_md_set_mdtype (ZIF_REPO_MD (md), ZIF_REPO_MD_TYPE_PRIMARY_DB);
+	if (ret)
+		egg_test_success (test, NULL);
+	else
+		egg_test_failed (test, "failed to set");
+
+	/************************************************************/
+	egg_test_title (test, "set checksum type");
+	ret = zif_repo_md_set_checksum_type (ZIF_REPO_MD (md), G_CHECKSUM_SHA256);
+	if (ret)
+		egg_test_success (test, NULL);
+	else
+		egg_test_failed (test, "failed to set");
+
+	/************************************************************/
+	egg_test_title (test, "set checksum compressed");
+	ret = zif_repo_md_set_checksum (ZIF_REPO_MD (md), "35d817e2bac701525fa72cec57387a2e3457bf32642adeee1e345cc180044c86");
+	if (ret)
+		egg_test_success (test, NULL);
+	else
+		egg_test_failed (test, "failed to set");
+
+	/************************************************************/
+	egg_test_title (test, "set checksum uncompressed");
+	ret = zif_repo_md_set_checksum_uncompressed (ZIF_REPO_MD (md), "9b2b072a83b5175bc88d03ee64b52b39c0d40fec1516baa62dba81eea73cc645");
+	if (ret)
+		egg_test_success (test, NULL);
+	else
+		egg_test_failed (test, "failed to set");
+
+	/************************************************************/
+	egg_test_title (test, "set filename");
+	ret = zif_repo_md_set_filename (ZIF_REPO_MD (md), "../test/cache/fedora/35d817e2bac701525fa72cec57387a2e3457bf32642adeee1e345cc180044c86-primary.sqlite.bz2");
+	if (ret)
+		egg_test_success (test, NULL);
+	else
+		egg_test_failed (test, "failed to set");
+
+	/************************************************************/
+	egg_test_title (test, "load");
+	ret = zif_repo_md_load (ZIF_REPO_MD (md), cancellable, completion, &error);
+	if (ret)
+		egg_test_success (test, NULL);
+	else
+		egg_test_failed (test, "failed to load '%s'", error->message);
+
+	/************************************************************/
+	egg_test_title (test, "loaded");
+	egg_test_assert (test, md->priv->loaded);
+
+	/************************************************************/
+	egg_test_title (test, "search for files");
+	array = zif_repo_md_primary_resolve (md, "gnome-power-manager", cancellable, completion, &error);
+	if (array != NULL)
+		egg_test_success (test, NULL);
+	else
+		egg_test_failed (test, "failed to search '%s'", error->message);
+
+	/************************************************************/
+	egg_test_title (test, "correct number");
+	egg_test_assert (test, array->len == 1);
+
+	/************************************************************/
+	egg_test_title (test, "correct value");
+	package = g_ptr_array_index (array, 0);
+	summary = zif_package_get_summary (package, NULL);
+	if (g_strcmp0 (zif_string_get_value (summary), "GNOME Power Manager") == 0)
+		egg_test_success (test, NULL);
+	else
+		egg_test_failed (test, "failed to get correct summary '%s'", zif_string_get_value (summary));
+	zif_string_unref (summary);
+	g_ptr_array_unref (array);
+
+	g_object_unref (cancellable);
+	g_object_unref (completion);
+	g_object_unref (md);
+
+	egg_test_end (test);
+}
+#endif
+
diff --git a/backends/yum/libzif/zif-repo-md-primary.h b/backends/yum/libzif/zif-repo-md-primary.h
new file mode 100644
index 0000000..a48df46
--- /dev/null
+++ b/backends/yum/libzif/zif-repo-md-primary.h
@@ -0,0 +1,103 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2009 Richard Hughes <richard at hughsie.com>
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#if !defined (__ZIF_H_INSIDE__) && !defined (ZIF_COMPILATION)
+#error "Only <zif.h> can be included directly."
+#endif
+
+#ifndef __ZIF_REPO_MD_PRIMARY_H
+#define __ZIF_REPO_MD_PRIMARY_H
+
+#include <glib-object.h>
+#include <packagekit-glib2/packagekit.h>
+
+#include "zif-repo-md.h"
+
+G_BEGIN_DECLS
+
+#define ZIF_TYPE_REPO_MD_PRIMARY		(zif_repo_md_primary_get_type ())
+#define ZIF_REPO_MD_PRIMARY(o)			(G_TYPE_CHECK_INSTANCE_CAST ((o), ZIF_TYPE_REPO_MD_PRIMARY, ZifRepoMdPrimary))
+#define ZIF_REPO_MD_PRIMARY_CLASS(k)		(G_TYPE_CHECK_CLASS_CAST((k), ZIF_TYPE_REPO_MD_PRIMARY, ZifRepoMdPrimaryClass))
+#define ZIF_IS_REPO_MD_PRIMARY(o)		(G_TYPE_CHECK_INSTANCE_TYPE ((o), ZIF_TYPE_REPO_MD_PRIMARY))
+#define ZIF_IS_REPO_MD_PRIMARY_CLASS(k)		(G_TYPE_CHECK_CLASS_TYPE ((k), ZIF_TYPE_REPO_MD_PRIMARY))
+#define ZIF_REPO_MD_PRIMARY_GET_CLASS(o)	(G_TYPE_INSTANCE_GET_CLASS ((o), ZIF_TYPE_REPO_MD_PRIMARY, ZifRepoMdPrimaryClass))
+
+typedef struct _ZifRepoMdPrimary		ZifRepoMdPrimary;
+typedef struct _ZifRepoMdPrimaryPrivate		ZifRepoMdPrimaryPrivate;
+typedef struct _ZifRepoMdPrimaryClass		ZifRepoMdPrimaryClass;
+
+struct _ZifRepoMdPrimary
+{
+	ZifRepoMd			 parent;
+	ZifRepoMdPrimaryPrivate		*priv;
+};
+
+struct _ZifRepoMdPrimaryClass
+{
+	ZifRepoMdClass			 parent_class;
+};
+
+GType		 zif_repo_md_primary_get_type		(void);
+ZifRepoMdPrimary *zif_repo_md_primary_new		(void);
+GPtrArray	*zif_repo_md_primary_search_file	(ZifRepoMdPrimary	*md,
+							 const gchar		*search,
+							 GCancellable		*cancellable,
+							 ZifCompletion		*completion,
+							 GError			**error);
+GPtrArray	*zif_repo_md_primary_search_name	(ZifRepoMdPrimary	*md,
+							 const gchar		*search,
+							 GCancellable		*cancellable,
+							 ZifCompletion		*completion,
+							 GError			**error);
+GPtrArray	*zif_repo_md_primary_search_details	(ZifRepoMdPrimary	*md,
+							 const gchar		*search,
+							 GCancellable		*cancellable,
+							 ZifCompletion		*completion,
+							 GError			**error);
+GPtrArray	*zif_repo_md_primary_search_group	(ZifRepoMdPrimary	*md,
+							 const gchar		*search,
+							 GCancellable		*cancellable,
+							 ZifCompletion		*completion,
+							 GError			**error);
+GPtrArray	*zif_repo_md_primary_search_pkgid	(ZifRepoMdPrimary	*md,
+							 const gchar		*search,
+							 GCancellable		*cancellable,
+							 ZifCompletion		*completion,
+							 GError			**error);
+GPtrArray	*zif_repo_md_primary_resolve		(ZifRepoMdPrimary	*md,
+							 const gchar		*search,
+							 GCancellable		*cancellable,
+							 ZifCompletion		*completion,
+							 GError			**error);
+GPtrArray	*zif_repo_md_primary_get_packages	(ZifRepoMdPrimary	*md,
+							 GCancellable		*cancellable,
+							 ZifCompletion		*completion,
+							 GError			**error);
+GPtrArray	*zif_repo_md_primary_find_package	(ZifRepoMdPrimary	*md,
+							 const gchar		*package_id,
+							 GCancellable		*cancellable,
+							 ZifCompletion		*completion,
+							 GError			**error);
+
+G_END_DECLS
+
+#endif /* __ZIF_REPO_MD_PRIMARY_H */
+
diff --git a/backends/yum/libzif/zif-repo-md.c b/backends/yum/libzif/zif-repo-md.c
new file mode 100644
index 0000000..58c3045
--- /dev/null
+++ b/backends/yum/libzif/zif-repo-md.c
@@ -0,0 +1,868 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2009 Richard Hughes <richard at hughsie.com>
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+/**
+ * SECTION:zif-repo-md
+ * @short_description: Metadata file common functionality
+ *
+ * This provides an abstract metadata class.
+ * It is implemented by #ZifRepoMdFilelists, #ZifRepoMdMaster and #ZifRepoMdPrimary.
+ */
+
+#ifdef HAVE_CONFIG_H
+#  include <config.h>
+#endif
+
+#include <glib.h>
+#include <glib/gstdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include "zif-utils.h"
+#include "zif-repo-md.h"
+#include "zif-config.h"
+
+#include "egg-debug.h"
+#include "egg-string.h"
+
+#define ZIF_REPO_MD_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), ZIF_TYPE_REPO_MD, ZifRepoMdPrivate))
+
+/**
+ * ZifRepoMdPrivate:
+ *
+ * Private #ZifRepoMd data
+ **/
+struct _ZifRepoMdPrivate
+{
+	gboolean		 loaded;
+	gchar			*id;			/* fedora */
+	gchar			*filename;		/* /var/cache/yum/fedora/repo.sqlite.bz2 */
+	gchar			*filename_uncompressed;	/* /var/cache/yum/fedora/repo.sqlite */
+	guint			 timestamp;
+	gchar			*location;		/* repodata/35d817e-primary.sqlite.bz2 */
+	gchar			*checksum;		/* of compressed file */
+	gchar			*checksum_uncompressed;	/* of uncompressed file */
+	GChecksumType		 checksum_type;
+	ZifRepoMdType		 type;
+	ZifStoreRemote		*remote;
+	ZifConfig		*config;
+};
+
+G_DEFINE_TYPE (ZifRepoMd, zif_repo_md, G_TYPE_OBJECT)
+
+/**
+ * zif_repo_md_get_id:
+ * @md: the #ZifRepoMd object
+ *
+ * Gets the md identifier, usually the repo name.
+ *
+ * Return value: the repo id.
+ **/
+const gchar *
+zif_repo_md_get_id (ZifRepoMd *md)
+{
+	g_return_val_if_fail (ZIF_IS_REPO_MD (md), NULL);
+	return md->priv->id;
+}
+
+/**
+ * zif_repo_md_get_filename:
+ * @md: the #ZifRepoMd object
+ *
+ * Gets the compressed filename of the repo.
+ *
+ * Return value: the filename
+ **/
+const gchar *
+zif_repo_md_get_filename (ZifRepoMd *md)
+{
+	g_return_val_if_fail (ZIF_IS_REPO_MD (md), NULL);
+	return md->priv->filename;
+}
+
+/**
+ * zif_repo_md_get_location:
+ * @md: the #ZifRepoMd object
+ *
+ * Gets the location of the repo.
+ *
+ * Return value: the location
+ **/
+const gchar *
+zif_repo_md_get_location (ZifRepoMd *md)
+{
+	g_return_val_if_fail (ZIF_IS_REPO_MD (md), NULL);
+	return md->priv->location;
+}
+
+/**
+ * zif_repo_md_get_mdtype:
+ * @md: the #ZifRepoMd object
+ *
+ * Gets the type of the repo.
+ *
+ * Return value: the type
+ **/
+ZifRepoMdType
+zif_repo_md_get_mdtype (ZifRepoMd *md)
+{
+	g_return_val_if_fail (ZIF_IS_REPO_MD (md), ZIF_REPO_MD_TYPE_UNKNOWN);
+	return md->priv->type;
+}
+
+/**
+ * zif_repo_md_get_filename_uncompressed:
+ * @md: the #ZifRepoMd object
+ *
+ * Gets the uncompressed filename of the repo.
+ *
+ * Return value: the filename
+ **/
+const gchar *
+zif_repo_md_get_filename_uncompressed (ZifRepoMd *md)
+{
+	g_return_val_if_fail (ZIF_IS_REPO_MD (md), NULL);
+	return md->priv->filename_uncompressed;
+}
+
+/**
+ * zif_repo_md_set_filename:
+ * @md: the #ZifRepoMd object
+ * @filename: the base filename, e.g. "master.xml.bz2"
+ *
+ * Sets the filename of the compressed file.
+ *
+ * Return value: %TRUE for success, %FALSE for failure
+ **/
+gboolean
+zif_repo_md_set_filename (ZifRepoMd *md, const gchar *filename)
+{
+	g_return_val_if_fail (ZIF_IS_REPO_MD (md), FALSE);
+	g_return_val_if_fail (md->priv->filename == NULL, FALSE);
+	g_return_val_if_fail (filename != NULL, FALSE);
+
+	/* this is the compressed name */
+	md->priv->filename = g_strdup (filename);
+
+	/* this is the uncompressed name */
+	md->priv->filename_uncompressed = zif_file_get_uncompressed_name (filename);
+
+	return TRUE;
+}
+
+/**
+ * zif_repo_md_set_timestamp:
+ * @md: the #ZifRepoMd object
+ * @timestamp: the timestamp value
+ *
+ * Sets the timestamp of the compressed file.
+ *
+ * Return value: %TRUE for success, %FALSE for failure
+ **/
+gboolean
+zif_repo_md_set_timestamp (ZifRepoMd *md, guint timestamp)
+{
+	g_return_val_if_fail (ZIF_IS_REPO_MD (md), FALSE);
+	g_return_val_if_fail (md->priv->timestamp == 0, FALSE);
+	g_return_val_if_fail (timestamp != 0, FALSE);
+
+	/* save new value */
+	md->priv->timestamp = timestamp;
+	return TRUE;
+}
+
+/**
+ * zif_repo_md_set_location:
+ * @md: the #ZifRepoMd object
+ * @location: the location
+ *
+ * Sets the location of the compressed file, e.g. "repodata/35d817e-primary.sqlite.bz2"
+ *
+ * Return value: %TRUE for success, %FALSE for failure
+ **/
+gboolean
+zif_repo_md_set_location (ZifRepoMd *md, const gchar *location)
+{
+	g_return_val_if_fail (ZIF_IS_REPO_MD (md), FALSE);
+	g_return_val_if_fail (md->priv->location == NULL, FALSE);
+	g_return_val_if_fail (location != NULL, FALSE);
+
+	/* save new value */
+	md->priv->location = g_strdup (location);
+	return TRUE;
+}
+
+/**
+ * zif_repo_md_set_checksum:
+ * @md: the #ZifRepoMd object
+ * @checksum: the checksum value
+ *
+ * Sets the checksum of the compressed file.
+ *
+ * Return value: %TRUE for success, %FALSE for failure
+ **/
+gboolean
+zif_repo_md_set_checksum (ZifRepoMd *md, const gchar *checksum)
+{
+	g_return_val_if_fail (ZIF_IS_REPO_MD (md), FALSE);
+	g_return_val_if_fail (md->priv->checksum == NULL, FALSE);
+	g_return_val_if_fail (checksum != NULL, FALSE);
+
+	/* save new value */
+	md->priv->checksum = g_strdup (checksum);
+	return TRUE;
+}
+
+/**
+ * zif_repo_md_set_checksum_uncompressed:
+ * @md: the #ZifRepoMd object
+ * @checksum_uncompressed: the uncompressed checksum value
+ *
+ * Sets the checksum of the uncompressed file.
+ *
+ * Return value: %TRUE for success, %FALSE for failure
+ **/
+gboolean
+zif_repo_md_set_checksum_uncompressed (ZifRepoMd *md, const gchar *checksum_uncompressed)
+{
+	g_return_val_if_fail (ZIF_IS_REPO_MD (md), FALSE);
+	g_return_val_if_fail (md->priv->checksum_uncompressed == NULL, FALSE);
+	g_return_val_if_fail (checksum_uncompressed != NULL, FALSE);
+
+	/* save new value */
+	md->priv->checksum_uncompressed = g_strdup (checksum_uncompressed);
+	return TRUE;
+}
+
+/**
+ * zif_repo_md_set_checksum_type:
+ * @md: the #ZifRepoMd object
+ * @checksum_type: the checksum type
+ *
+ * Sets the checksum_type of the files.
+ *
+ * Return value: %TRUE for success, %FALSE for failure
+ **/
+gboolean
+zif_repo_md_set_checksum_type (ZifRepoMd *md, GChecksumType checksum_type)
+{
+	g_return_val_if_fail (ZIF_IS_REPO_MD (md), FALSE);
+	g_return_val_if_fail (md->priv->checksum_type == 0, FALSE);
+
+	/* save new value */
+	md->priv->checksum_type = checksum_type;
+	return TRUE;
+}
+
+/**
+ * zif_repo_md_set_mdtype:
+ * @md: the #ZifRepoMd object
+ * @type: the metadata type
+ *
+ * Sets the type of the metadata, e.g. ZIF_REPO_MD_TYPE_FILELISTS_DB.
+ *
+ * Return value: %TRUE for success, %FALSE for failure
+ **/
+gboolean
+zif_repo_md_set_mdtype (ZifRepoMd *md, ZifRepoMdType type)
+{
+	gboolean ret = TRUE;
+
+	g_return_val_if_fail (ZIF_IS_REPO_MD (md), FALSE);
+	g_return_val_if_fail (md->priv->type == ZIF_REPO_MD_TYPE_UNKNOWN, FALSE);
+	g_return_val_if_fail (type != ZIF_REPO_MD_TYPE_UNKNOWN, FALSE);
+
+	/* save new value */
+	md->priv->type = type;
+
+	/* metalink is not specified in the repomd.xml file */
+	if (type == ZIF_REPO_MD_TYPE_METALINK) {
+		zif_repo_md_set_location (md, "metalink.xml");
+		goto out;
+	}
+
+	/* mirrorlist is not specified in the repomd.xml file */
+	if (type == ZIF_REPO_MD_TYPE_MIRRORLIST) {
+		zif_repo_md_set_location (md, "mirrorlist.txt");
+		goto out;
+	}
+
+	/* check we've got the needed data */
+	if (md->priv->location != NULL && (md->priv->checksum == NULL || md->priv->timestamp == 0)) {
+		egg_warning ("cannot load md for %s (loc=%s, checksum=%s, checksum_open=%s, timestamp=%i)",
+			     zif_repo_md_type_to_text (type), md->priv->location,
+			     md->priv->checksum, md->priv->checksum_uncompressed, md->priv->timestamp);
+		ret = FALSE;
+		goto out;
+	}
+out:
+	return ret;
+}
+
+/**
+ * zif_repo_md_set_id:
+ * @md: the #ZifRepoMd object
+ * @id: the repository id, e.g. "fedora"
+ *
+ * Sets the repository ID for this metadata.
+ *
+ * Return value: %TRUE for success, %FALSE for failure
+ **/
+gboolean
+zif_repo_md_set_id (ZifRepoMd *md, const gchar *id)
+{
+	g_return_val_if_fail (ZIF_IS_REPO_MD (md), FALSE);
+	g_return_val_if_fail (md->priv->id == NULL, FALSE);
+	g_return_val_if_fail (id != NULL, FALSE);
+
+	md->priv->id = g_strdup (id);
+	return TRUE;
+}
+
+/**
+ * zif_repo_md_set_id:
+ * @md: the #ZifRepoMd object
+ * @id: the repository id, e.g. "fedora"
+ *
+ * Sets the repository ID for this metadata.
+ *
+ * Return value: %TRUE for success, %FALSE for failure
+ **/
+gboolean
+zif_repo_md_set_store_remote (ZifRepoMd *md, ZifStoreRemote *remote)
+{
+	g_return_val_if_fail (ZIF_IS_REPO_MD (md), FALSE);
+	g_return_val_if_fail (md->priv->remote == NULL, FALSE);
+	g_return_val_if_fail (remote != NULL, FALSE);
+
+	/* do not take a reference, else the parent device never goes away */
+	md->priv->remote = remote;
+	return TRUE;
+}
+
+/**
+ * zif_repo_md_delete_file:
+ **/
+static gboolean
+zif_repo_md_delete_file (const gchar *filename)
+{
+	gint retval;
+	gboolean ret;
+
+	/* file exists? */
+	ret = g_file_test (filename, G_FILE_TEST_EXISTS);
+	if (!ret)
+		goto out;
+
+	egg_warning ("deleting %s", filename);
+
+	/* remove */
+	retval = g_unlink (filename);
+	if (retval != 0) {
+		egg_warning ("failed to delete %s", filename);
+		ret = FALSE;
+	}
+out:
+	return ret;
+}
+
+/**
+ * zif_repo_md_load:
+ * @md: the #ZifRepoMd object
+ * @cancellable: a #GCancellable which is used to cancel tasks, or %NULL
+ * @completion: a #ZifCompletion to use for progress reporting
+ * @error: a #GError which is used on failure, or %NULL
+ *
+ * Load the metadata store.
+ *
+ * - Check compressed file
+ *   if invalid:
+ *       delete_it()
+ *       if online:
+ *           download_it()
+ *           if failure:
+ *               abort
+ *           check_it()
+ *           if failure:
+ *               abort
+ *       else
+ *           abort
+ *
+ * - Check uncompressed file
+ *   if invalid:
+ *       delete_it()
+ *       decompress_it()
+ *           if failure:
+ *               abort()
+ *       check_it()
+ *       if failure:
+ *           abort
+ *
+ * Return value: %TRUE for success, %FALSE for failure
+ **/
+gboolean
+zif_repo_md_load (ZifRepoMd *md, GCancellable *cancellable, ZifCompletion *completion, GError **error)
+{
+	gboolean ret;
+	gboolean uncompressed_check;
+	GError *error_local = NULL;
+	ZifRepoMdClass *klass = ZIF_REPO_MD_GET_CLASS (md);
+	ZifCompletion *completion_local;
+
+	/* no support */
+	if (klass->load == NULL) {
+		if (error != NULL)
+			*error = g_error_new (1, 0, "operation cannot be performed on this md");
+		return FALSE;
+	}
+
+	/* setup completion */
+	zif_completion_set_number_steps (completion, 3);
+
+	g_return_val_if_fail (ZIF_IS_REPO_MD (md), FALSE);
+
+	/* optimise: if uncompressed file is okay, then don't even check the compressed file */
+	uncompressed_check = zif_repo_md_file_check (md, TRUE, &error_local);
+	if (uncompressed_check) {
+		zif_completion_done (completion);
+		goto skip_compressed_check;
+	}
+
+	/* display any warning */
+	egg_warning ("failed checksum for uncompressed: %s", error_local->message);
+	g_clear_error (&error_local);
+
+	/* check compressed file */
+	ret = zif_repo_md_file_check (md, FALSE, &error_local);
+	if (!ret) {
+		egg_warning ("failed checksum for compressed: %s", error_local->message);
+		g_clear_error (&error_local);
+
+		/* delete file if it exists */
+		zif_repo_md_delete_file (md->priv->filename);
+
+		/* if not online, then this is fatal */
+		ret = zif_config_get_boolean (md->priv->config, "network", NULL);
+		if (!ret) {
+			if (error != NULL)
+				*error = g_error_new (1, 0, "failed to check %s checksum for %s and offline",
+						      zif_repo_md_type_to_text (md->priv->type), md->priv->id);
+			goto out;
+		}
+
+		/* TODO: download file */
+		//ret = download (&error_local)
+		if (!ret) {
+			if (error != NULL)
+				*error = g_error_new (1, 0, "failed to download missing compressed file: %s", error_local->message);
+			goto out;
+		}
+
+		/* check newly downloaded compressed file */
+		ret = zif_repo_md_file_check (md, FALSE, &error_local);
+		if (!ret) {
+			if (error != NULL)
+				*error = g_error_new (1, 0, "failed checksum on downloaded file: %s", error_local->message);
+			goto out;
+		}
+	}
+
+	/* this section done */
+	zif_completion_done (completion);
+
+	/* check uncompressed file */
+	if (!uncompressed_check) {
+
+		/* delete file if it exists */
+		zif_repo_md_delete_file (md->priv->filename_uncompressed);
+
+		/* decompress file */
+		egg_debug ("decompressing file");
+		completion_local = zif_completion_get_child (completion);
+		ret = zif_file_decompress (md->priv->filename, md->priv->filename_uncompressed,
+					   cancellable, completion_local, &error_local);
+		if (!ret) {
+			if (error != NULL)
+				*error = g_error_new (1, 0, "failed to decompress: %s", error_local->message);
+			goto out;
+		}
+
+		/* check newly uncompressed file */
+		ret = zif_repo_md_file_check (md, TRUE, &error_local);
+		if (!ret) {
+			if (error != NULL)
+				*error = g_error_new (1, 0, "failed checksum on decompressed file: %s", error_local->message);
+			goto out;
+		}
+	}
+
+skip_compressed_check:
+
+	/* this section done */
+	zif_completion_done (completion);
+
+	/* do subclassed load */
+	completion_local = zif_completion_get_child (completion);
+	ret = klass->load (md, cancellable, completion_local, error);
+
+	/* this section done */
+	zif_completion_done (completion);
+out:
+	return ret;
+}
+
+/**
+ * zif_repo_md_unload:
+ * @md: the #ZifRepoMd object
+ * @cancellable: a #GCancellable which is used to cancel tasks, or %NULL
+ * @completion: a #ZifCompletion to use for progress reporting
+ * @error: a #GError which is used on failure, or %NULL
+ *
+ * Unload the metadata store.
+ *
+ * Return value: %TRUE for success, %FALSE for failure
+ **/
+gboolean
+zif_repo_md_unload (ZifRepoMd *md, GCancellable *cancellable, ZifCompletion *completion, GError **error)
+{
+	ZifRepoMdClass *klass = ZIF_REPO_MD_GET_CLASS (md);
+
+	g_return_val_if_fail (ZIF_IS_REPO_MD (md), FALSE);
+
+	/* no support */
+	if (klass->unload == NULL) {
+		if (error != NULL)
+			*error = g_error_new (1, 0, "operation cannot be performed on this md");
+		return FALSE;
+	}
+
+	return klass->unload (md, cancellable, completion, error);
+}
+
+/**
+ * zif_repo_md_clean:
+ * @md: the #ZifRepoMd object
+ * @error: a #GError which is used on failure, or %NULL
+ *
+ * Clean the metadata store.
+ *
+ * Return value: %TRUE for success, %FALSE for failure
+ **/
+gboolean
+zif_repo_md_clean (ZifRepoMd *md, GError **error)
+{
+	gboolean ret = FALSE;
+	gboolean exists;
+	const gchar *filename;
+	GFile *file;
+	GError *error_local = NULL;
+
+	g_return_val_if_fail (ZIF_IS_REPO_MD (md), FALSE);
+
+	/* get filename */
+	filename = zif_repo_md_get_filename (md);
+	if (filename == NULL) {
+		if (error != NULL)
+			*error = g_error_new (1, 0, "failed to get filename for %s", zif_repo_md_type_to_text (md->priv->type));
+		ret = FALSE;
+		goto out;
+	}
+
+	/* file does not exist */
+	exists = g_file_test (filename, G_FILE_TEST_EXISTS);
+	if (exists) {
+		file = g_file_new_for_path (filename);
+		ret = g_file_delete (file, NULL, &error_local);
+		g_object_unref (file);
+		if (!ret) {
+			if (error != NULL)
+				*error = g_error_new (1, 0, "failed to delete metadata file %s: %s", filename, error_local->message);
+			g_error_free (error_local);
+			goto out;
+		}
+	}
+
+	/* get filename */
+	filename = zif_repo_md_get_filename_uncompressed (md);
+	if (filename == NULL) {
+		if (error != NULL)
+			*error = g_error_new (1, 0, "failed to get uncompressed filename for %s", zif_repo_md_type_to_text (md->priv->type));
+		ret = FALSE;
+		goto out;
+	}
+
+	/* file does not exist */
+	exists = g_file_test (filename, G_FILE_TEST_EXISTS);
+	if (exists) {
+		file = g_file_new_for_path (filename);
+		ret = g_file_delete (file, NULL, &error_local);
+		g_object_unref (file);
+		if (!ret) {
+			if (error != NULL)
+				*error = g_error_new (1, 0, "failed to delete metadata file %s: %s", filename, error_local->message);
+			g_error_free (error_local);
+			goto out;
+		}
+	}
+
+	/* okay */
+	ret = TRUE;
+out:
+	return ret;
+}
+
+/**
+ * zif_repo_md_type_to_text:
+ **/
+const gchar *
+zif_repo_md_type_to_text (ZifRepoMdType type)
+{
+	if (type == ZIF_REPO_MD_TYPE_FILELISTS)
+		return "filelists";
+	if (type == ZIF_REPO_MD_TYPE_FILELISTS_DB)
+		return "filelists_db";
+	if (type == ZIF_REPO_MD_TYPE_PRIMARY)
+		return "primary";
+	if (type == ZIF_REPO_MD_TYPE_PRIMARY_DB)
+		return "primary_db";
+	if (type == ZIF_REPO_MD_TYPE_OTHER)
+		return "other";
+	if (type == ZIF_REPO_MD_TYPE_OTHER_DB)
+		return "other_db";
+	if (type == ZIF_REPO_MD_TYPE_COMPS)
+		return "group";
+	if (type == ZIF_REPO_MD_TYPE_COMPS_XML)
+		return "group_gz";
+	if (type == ZIF_REPO_MD_TYPE_METALINK)
+		return "metalink";
+	if (type == ZIF_REPO_MD_TYPE_MIRRORLIST)
+		return "mirrorlist";
+	if (type == ZIF_REPO_MD_TYPE_PRESTODELTA)
+		return "prestodelta";
+	if (type == ZIF_REPO_MD_TYPE_UPDATEINFO)
+		return "updateinfo";
+	return "unknown";
+}
+
+/**
+ * zif_repo_md_file_check:
+ * @md: the #ZifRepoMd object
+ * @use_uncompressed: If we should check only the uncompresed version
+ * @error: a #GError which is used on failure, or %NULL
+ *
+ * Check the metadata files to make sure they are valid.
+ *
+ * Return value: %TRUE for success, %FALSE for failure
+ **/
+gboolean
+zif_repo_md_file_check (ZifRepoMd *md, gboolean use_uncompressed, GError **error)
+{
+	gboolean ret = FALSE;
+	GError *error_local = NULL;
+	gchar *data = NULL;
+	gchar *checksum = NULL;
+	const gchar *filename;
+	const gchar *checksum_wanted;
+	gsize length;
+
+	g_return_val_if_fail (ZIF_IS_REPO_MD (md), FALSE);
+	g_return_val_if_fail (md->priv->id != NULL, FALSE);
+
+	/* metalink has no checksum... */
+	if (md->priv->type == ZIF_REPO_MD_TYPE_METALINK ||
+	    md->priv->type == ZIF_REPO_MD_TYPE_MIRRORLIST) {
+		egg_debug ("skipping checksum check on %s", zif_repo_md_type_to_text (md->priv->type));
+		ret = TRUE;
+		goto out;
+	}
+
+	/* get correct filename */
+	if (use_uncompressed)
+		filename = md->priv->filename_uncompressed;
+	else
+		filename = md->priv->filename;
+
+	/* get contents */
+	ret = g_file_get_contents (filename, &data, &length, &error_local);
+	if (!ret) {
+		if (error != NULL)
+			*error = g_error_new (1, 0, "failed to get contents of %s: %s", filename, error_local->message);
+		g_error_free (error_local);
+		goto out;
+	}
+
+	/* get the one we want */
+	if (use_uncompressed)
+		checksum_wanted = md->priv->checksum_uncompressed;
+	else
+		checksum_wanted = md->priv->checksum;
+
+	/* no checksum set */
+	if (checksum_wanted == NULL) {
+		if (error != NULL)
+			*error = g_error_new (1, 0, "checksum not set for %s", filename);
+		ret = FALSE;
+		goto out;
+	}
+
+	/* compute checksum */
+	checksum = g_compute_checksum_for_data (md->priv->checksum_type, (guchar*) data, length);
+
+	/* matches? */
+	ret = (g_strcmp0 (checksum, checksum_wanted) == 0);
+	if (!ret) {
+		if (error != NULL)
+			*error = g_error_new (1, 0, "checksum incorrect, wanted %s, got %s for %s", checksum_wanted, checksum, filename);
+		goto out;
+	}
+	egg_debug ("%s checksum correct (%s)", filename, checksum_wanted);
+out:
+	g_free (data);
+	g_free (checksum);
+	return ret;
+}
+
+/**
+ * zif_repo_md_finalize:
+ **/
+static void
+zif_repo_md_finalize (GObject *object)
+{
+	ZifRepoMd *md;
+
+	g_return_if_fail (object != NULL);
+	g_return_if_fail (ZIF_IS_REPO_MD (object));
+	md = ZIF_REPO_MD (object);
+
+	g_free (md->priv->id);
+	g_free (md->priv->filename);
+	g_free (md->priv->location);
+	g_free (md->priv->checksum);
+	g_free (md->priv->checksum_uncompressed);
+
+	g_object_unref (md->priv->config);
+
+	G_OBJECT_CLASS (zif_repo_md_parent_class)->finalize (object);
+}
+
+/**
+ * zif_repo_md_class_init:
+ **/
+static void
+zif_repo_md_class_init (ZifRepoMdClass *klass)
+{
+	GObjectClass *object_class = G_OBJECT_CLASS (klass);
+	object_class->finalize = zif_repo_md_finalize;
+	g_type_class_add_private (klass, sizeof (ZifRepoMdPrivate));
+}
+
+/**
+ * zif_repo_md_init:
+ **/
+static void
+zif_repo_md_init (ZifRepoMd *md)
+{
+	md->priv = ZIF_REPO_MD_GET_PRIVATE (md);
+	md->priv->type = ZIF_REPO_MD_TYPE_UNKNOWN;
+	md->priv->loaded = FALSE;
+	md->priv->id = NULL;
+	md->priv->filename = NULL;
+	md->priv->timestamp = 0;
+	md->priv->location = NULL;
+	md->priv->checksum = NULL;
+	md->priv->checksum_uncompressed = NULL;
+	md->priv->checksum_type = 0;
+	md->priv->remote = NULL;
+	md->priv->config = zif_config_new ();
+}
+
+/**
+ * zif_repo_md_new:
+ *
+ * Return value: A new #ZifRepoMd class instance.
+ **/
+ZifRepoMd *
+zif_repo_md_new (void)
+{
+	ZifRepoMd *md;
+	md = g_object_new (ZIF_TYPE_REPO_MD, NULL);
+	return ZIF_REPO_MD (md);
+}
+
+/***************************************************************************
+ ***                          MAKE CHECK TESTS                           ***
+ ***************************************************************************/
+#ifdef EGG_TEST
+#include "egg-test.h"
+
+void
+zif_repo_md_test (EggTest *test)
+{
+	ZifRepoMd *md;
+	gboolean ret;
+	GError *error = NULL;
+	GCancellable *cancellable;
+	ZifCompletion *completion;
+
+	if (!egg_test_start (test, "ZifRepoMd"))
+		return;
+
+	/* use */
+	cancellable = g_cancellable_new ();
+	completion = zif_completion_new ();
+
+	/************************************************************/
+	egg_test_title (test, "get store_remote md");
+	md = zif_repo_md_new ();
+	egg_test_assert (test, md != NULL);
+
+	/************************************************************/
+	egg_test_title (test, "loaded");
+	egg_test_assert (test, !md->priv->loaded);
+
+	/************************************************************/
+	egg_test_title (test, "set id");
+	ret = zif_repo_md_set_id (md, "fedora");
+	if (ret)
+		egg_test_success (test, NULL);
+	else
+		egg_test_failed (test, "failed to set");
+
+	/************************************************************/
+	egg_test_title (test, "load");
+	ret = zif_repo_md_load (md, cancellable, completion, &error);
+	if (ret)
+		egg_test_success (test, NULL);
+	else
+		egg_test_failed (test, "failed to load '%s'", error->message);
+
+	/************************************************************/
+	egg_test_title (test, "loaded");
+	egg_test_assert (test, md->priv->loaded);
+
+	g_object_unref (md);
+	g_object_unref (cancellable);
+	g_object_unref (completion);
+
+	egg_test_end (test);
+}
+#endif
+
diff --git a/backends/yum/libzif/zif-repo-md.h b/backends/yum/libzif/zif-repo-md.h
new file mode 100644
index 0000000..301412e
--- /dev/null
+++ b/backends/yum/libzif/zif-repo-md.h
@@ -0,0 +1,137 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2009 Richard Hughes <richard at hughsie.com>
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#if !defined (__ZIF_H_INSIDE__) && !defined (ZIF_COMPILATION)
+#error "Only <zif.h> can be included directly."
+#endif
+
+#ifndef __ZIF_REPO_MD_H
+#define __ZIF_REPO_MD_H
+
+#include <glib-object.h>
+#include <gio/gio.h>
+
+#include "zif-repo-md.h"
+#include "zif-completion.h"
+#include "zif-store-remote.h"
+
+G_BEGIN_DECLS
+
+#define ZIF_TYPE_REPO_MD		(zif_repo_md_get_type ())
+#define ZIF_REPO_MD(o)			(G_TYPE_CHECK_INSTANCE_CAST ((o), ZIF_TYPE_REPO_MD, ZifRepoMd))
+#define ZIF_REPO_MD_CLASS(k)		(G_TYPE_CHECK_CLASS_CAST((k), ZIF_TYPE_REPO_MD, ZifRepoMdClass))
+#define ZIF_IS_REPO_MD(o)		(G_TYPE_CHECK_INSTANCE_TYPE ((o), ZIF_TYPE_REPO_MD))
+#define ZIF_IS_REPO_MD_CLASS(k)		(G_TYPE_CHECK_CLASS_TYPE ((k), ZIF_TYPE_REPO_MD))
+#define ZIF_REPO_MD_GET_CLASS(o)	(G_TYPE_INSTANCE_GET_CLASS ((o), ZIF_TYPE_REPO_MD, ZifRepoMdClass))
+
+typedef struct _ZifRepoMd		ZifRepoMd;
+typedef struct _ZifRepoMdPrivate	ZifRepoMdPrivate;
+typedef struct _ZifRepoMdClass		ZifRepoMdClass;
+
+struct _ZifRepoMd
+{
+	GObject			 parent;
+	ZifRepoMdPrivate	*priv;
+};
+
+struct _ZifRepoMdClass
+{
+	GObjectClass				 parent_class;
+	/* vtable */
+	gboolean	 (*load)		(ZifRepoMd		*md,
+						 GCancellable		*cancellable,
+						 ZifCompletion		*completion,
+						 GError			**error);
+	gboolean	 (*unload)		(ZifRepoMd		*md,
+						 GCancellable		*cancellable,
+						 ZifCompletion		*completion,
+						 GError			**error);
+};
+
+/* types of metadata */
+typedef enum {
+	ZIF_REPO_MD_TYPE_PRIMARY,
+	ZIF_REPO_MD_TYPE_PRIMARY_DB,
+	ZIF_REPO_MD_TYPE_FILELISTS,
+	ZIF_REPO_MD_TYPE_FILELISTS_DB,
+	ZIF_REPO_MD_TYPE_OTHER,
+	ZIF_REPO_MD_TYPE_OTHER_DB,
+	ZIF_REPO_MD_TYPE_COMPS,
+	ZIF_REPO_MD_TYPE_COMPS_XML,
+	ZIF_REPO_MD_TYPE_METALINK,
+	ZIF_REPO_MD_TYPE_MIRRORLIST,
+	ZIF_REPO_MD_TYPE_PRESTODELTA,
+	ZIF_REPO_MD_TYPE_UPDATEINFO,
+	ZIF_REPO_MD_TYPE_UNKNOWN
+} ZifRepoMdType;
+
+GType		 zif_repo_md_get_type			(void);
+ZifRepoMd	*zif_repo_md_new			(void);
+
+/* setters */
+gboolean	 zif_repo_md_set_mdtype			(ZifRepoMd	*md,
+							 ZifRepoMdType	 type);
+gboolean	 zif_repo_md_set_store_remote		(ZifRepoMd	*md,
+							 ZifStoreRemote	*remote);
+gboolean	 zif_repo_md_set_id			(ZifRepoMd	*md,
+							 const gchar	*id);
+gboolean	 zif_repo_md_set_filename		(ZifRepoMd	*md,
+							 const gchar	*filename);
+gboolean	 zif_repo_md_set_timestamp		(ZifRepoMd	*md,
+							 guint		 timestamp);
+gboolean	 zif_repo_md_set_location		(ZifRepoMd	*md,
+							 const gchar	*location);
+gboolean	 zif_repo_md_set_checksum		(ZifRepoMd	*md,
+							 const gchar	*checksum);
+gboolean	 zif_repo_md_set_checksum_uncompressed	(ZifRepoMd	*md,
+							 const gchar	*checksum_uncompressed);
+gboolean	 zif_repo_md_set_checksum_type		(ZifRepoMd	*md,
+							 GChecksumType	 checksum_type);
+const gchar	*zif_repo_md_type_to_text		(ZifRepoMdType	 type);
+
+/* getters */
+const gchar	*zif_repo_md_get_id			(ZifRepoMd	*md);
+ZifRepoMdType	 zif_repo_md_get_mdtype			(ZifRepoMd	*md);
+const gchar	*zif_repo_md_get_filename		(ZifRepoMd	*md);
+const gchar	*zif_repo_md_get_filename_uncompressed	(ZifRepoMd	*md);
+guint		 zif_repo_md_get_age			(ZifRepoMd	*md,
+							 GError		**error);
+const gchar	*zif_repo_md_get_location		(ZifRepoMd	*md);
+
+/* actions */
+gboolean	 zif_repo_md_load			(ZifRepoMd	*md,
+							 GCancellable	*cancellable,
+							 ZifCompletion	*completion,
+							 GError		**error);
+gboolean	 zif_repo_md_unload			(ZifRepoMd	*md,
+							 GCancellable	*cancellable,
+							 ZifCompletion	*completion,
+							 GError		**error);
+gboolean	 zif_repo_md_clean			(ZifRepoMd	*md,
+							 GError		**error);
+gboolean	 zif_repo_md_file_check			(ZifRepoMd	*md,
+							 gboolean	 use_uncompressed,
+							 GError		**error);
+
+G_END_DECLS
+
+#endif /* __ZIF_REPO_MD_H */
+
diff --git a/backends/yum/libzif/zif-repos.c b/backends/yum/libzif/zif-repos.c
new file mode 100644
index 0000000..d082c49
--- /dev/null
+++ b/backends/yum/libzif/zif-repos.c
@@ -0,0 +1,610 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2008 Richard Hughes <richard at hughsie.com>
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+/**
+ * SECTION:zif-repos
+ * @short_description: A #ZifRepos object manages software sources
+ *
+ * A #ZifRepos is an object that allows easy interfacing with remote
+ * repositories.
+ */
+
+#ifdef HAVE_CONFIG_H
+#  include <config.h>
+#endif
+
+#include <glib.h>
+#include <string.h>
+
+#include "zif-config.h"
+#include "zif-completion.h"
+#include "zif-store-remote.h"
+#include "zif-repos.h"
+#include "zif-utils.h"
+#include "zif-monitor.h"
+
+#include "egg-debug.h"
+#include "egg-string.h"
+
+#define ZIF_REPOS_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), ZIF_TYPE_REPOS, ZifReposPrivate))
+
+struct _ZifReposPrivate
+{
+	gboolean		 loaded;
+	gchar			*repos_dir;
+	ZifMonitor		*monitor;
+	GPtrArray		*list;
+	GPtrArray		*enabled;
+};
+
+G_DEFINE_TYPE (ZifRepos, zif_repos, G_TYPE_OBJECT)
+static gpointer zif_repos_object = NULL;
+
+/**
+ * zif_repos_set_repos_dir:
+ * @repos: the #ZifRepos object
+ * @repos_dir: the directory, e.g. "/etc/yum.repos.d"
+ * @error: a #GError which is used on failure, or %NULL
+ *
+ * Set the repository directory.
+ *
+ * Return value: %TRUE for success, %FALSE for failure
+ **/
+gboolean
+zif_repos_set_repos_dir (ZifRepos *repos, const gchar *repos_dir, GError **error)
+{
+	gboolean ret;
+	GError *error_local = NULL;
+
+	g_return_val_if_fail (ZIF_IS_REPOS (repos), FALSE);
+	g_return_val_if_fail (repos->priv->repos_dir == NULL, FALSE);
+	g_return_val_if_fail (!repos->priv->loaded, FALSE);
+	g_return_val_if_fail (repos_dir != NULL, FALSE);
+
+	/* check directory exists */
+	ret = g_file_test (repos_dir, G_FILE_TEST_IS_DIR);
+	if (!ret) {
+		if (error != NULL)
+			*error = g_error_new (1, 0, "repo directory %s does not exist", repos_dir);
+		goto out;
+	}
+
+	/* setup watch */
+	ret = zif_monitor_add_watch (repos->priv->monitor, repos_dir, &error_local);
+	if (!ret) {
+		if (error != NULL)
+			*error = g_error_new (1, 0, "failed to setup watch: %s", error_local->message);
+		g_error_free (error_local);
+		goto out;
+	}
+
+	repos->priv->repos_dir = g_strdup (repos_dir);
+out:
+	return ret;
+}
+
+/**
+ * zif_repos_get_for_filename:
+ **/
+static gboolean
+zif_repos_get_for_filename (ZifRepos *repos, const gchar *filename, GCancellable *cancellable, ZifCompletion *completion, GError **error)
+{
+	GError *error_local = NULL;
+	GKeyFile *file;
+	gchar **repos_groups = NULL;
+	ZifStoreRemote *store;
+	ZifCompletion *completion_local;
+	gboolean ret;
+	gchar *path;
+	guint i;
+
+	/* find all the id's in this file */
+	file = g_key_file_new ();
+	path = g_build_filename (repos->priv->repos_dir, filename, NULL);
+	ret = g_key_file_load_from_file (file, path, G_KEY_FILE_NONE, &error_local);
+	if (!ret) {
+		if (error != NULL)
+			*error = g_error_new (1, 0, "failed to load %s: %s", path, error_local->message);
+		g_error_free (error_local);
+		goto out;
+	}
+
+	/* for each group, add a store object */
+	repos_groups = g_key_file_get_groups (file, NULL);
+
+	/* set number of stores */
+	zif_completion_set_number_steps (completion, g_strv_length (repos_groups));
+
+	/* create each repo */
+	for (i=0; repos_groups[i] != NULL; i++) {
+		store = zif_store_remote_new ();
+		completion_local = zif_completion_get_child (completion);
+		ret = zif_store_remote_set_from_file (store, path, repos_groups[i], cancellable, completion_local, &error_local);
+		if (!ret) {
+			if (error != NULL)
+				*error = g_error_new (1, 0, "failed to set from %s: %s", path, error_local->message);
+			g_error_free (error_local);
+			break;
+		}
+		g_ptr_array_add (repos->priv->list, store);
+
+		/* this section done */
+		zif_completion_done (completion);
+	}
+out:
+	g_strfreev (repos_groups);
+	g_free (path);
+	g_key_file_free (file);
+	return ret;
+}
+
+/**
+ * zif_repos_load:
+ * @repos: the #ZifRepos object
+ * @cancellable: a #GCancellable which is used to cancel tasks, or %NULL
+ * @completion: a #ZifCompletion to use for progress reporting
+ * @error: a #GError which is used on failure, or %NULL
+ *
+ * Load the repository, and parse it's config file.
+ *
+ * Return value: %TRUE for success, %FALSE for failure
+ **/
+gboolean
+zif_repos_load (ZifRepos *repos, GCancellable *cancellable, ZifCompletion *completion, GError **error)
+{
+	gboolean ret = TRUE;
+	ZifStoreRemote *store;
+	ZifCompletion *completion_local;
+	GError *error_local = NULL;
+	GDir *dir;
+	const gchar *filename;
+	guint i;
+	GPtrArray *repofiles = NULL;
+
+	g_return_val_if_fail (ZIF_IS_REPOS (repos), FALSE);
+	g_return_val_if_fail (repos->priv->repos_dir != NULL, FALSE);
+
+	/* already loaded */
+	if (repos->priv->loaded)
+		goto out;
+
+	/* search repos dir */
+	dir = g_dir_open (repos->priv->repos_dir, 0, &error_local);
+	if (dir == NULL) {
+		if (error != NULL)
+			*error = g_error_new (1, 0, "failed to list directory: %s", error_local->message);
+		g_error_free (error_local);
+		ret = FALSE;
+		goto out;
+	}
+
+	/* find the repo files we care about */
+	repofiles = g_ptr_array_new_with_free_func ((GDestroyNotify) g_free);
+	filename = g_dir_read_name (dir);
+	while (filename != NULL) {
+		if (g_str_has_suffix (filename, ".repo"))
+			g_ptr_array_add (repofiles, g_strdup (filename));
+		filename = g_dir_read_name (dir);
+	}
+	g_dir_close (dir);
+
+	/* setup completion with the correct number of steps */
+	zif_completion_set_number_steps (completion, repofiles->len + 1);
+
+	/* for each repo files */
+	for (i=0; i < repofiles->len; i++) {
+
+		/* setup watch */
+		filename = g_ptr_array_index (repofiles, i);
+		ret = zif_monitor_add_watch (repos->priv->monitor, filename, &error_local);
+		if (!ret) {
+			if (error != NULL)
+				*error = g_error_new (1, 0, "failed to setup watch: %s", error_local->message);
+			g_error_free (error_local);
+			break;
+		}
+
+		/* add all repos for filename */
+		completion_local = zif_completion_get_child (completion);
+		ret = zif_repos_get_for_filename (repos, filename, cancellable, completion_local, &error_local);
+		if (!ret) {
+			if (error != NULL)
+				*error = g_error_new (1, 0, "failed to get filename %s: %s", filename, error_local->message);
+			g_error_free (error_local);
+			g_ptr_array_set_size (repos->priv->list, 0);
+			ret = FALSE;
+			break;
+		}
+
+		/* this section done */
+		zif_completion_done (completion);
+	}
+
+	/* we failed one file, abandon attempt */
+	if (!ret)
+		goto out;
+
+	/* find enabled */
+	for (i=0; i<repos->priv->list->len; i++) {
+		store = g_ptr_array_index (repos->priv->list, i);
+
+		/* get repo enabled state */
+		completion_local = zif_completion_get_child (completion);
+		ret = zif_store_remote_get_enabled (store, cancellable, completion_local, &error_local);
+		if (error_local != NULL) {
+			if (error != NULL)
+				*error = g_error_new (1, 0, "failed to get repo state for %s: %s", zif_store_get_id (ZIF_STORE (store)), error_local->message);
+			g_ptr_array_set_size (repos->priv->enabled, 0);
+			ret = FALSE;
+			goto out;
+		}
+
+		/* if enabled, add to array */
+		if (ret)
+			g_ptr_array_add (repos->priv->enabled, g_object_ref (store));
+	}
+
+	/* this section done */
+	zif_completion_done (completion);
+
+	/* all loaded okay */
+	repos->priv->loaded = TRUE;
+	ret = TRUE;
+
+out:
+	if (repofiles != NULL)
+		g_ptr_array_unref (repofiles);
+	return ret;
+}
+
+/**
+ * zif_repos_get_stores:
+ * @repos: the #ZifRepos object
+ * @cancellable: a #GCancellable which is used to cancel tasks, or %NULL
+ * @completion: a #ZifCompletion to use for progress reporting
+ * @error: a #GError which is used on failure, or %NULL
+ *
+ * Gets the enabled and disabled remote stores.
+ *
+ * Return value: a list of #ZifStore's
+ **/
+GPtrArray *
+zif_repos_get_stores (ZifRepos *repos, GCancellable *cancellable, ZifCompletion *completion, GError **error)
+{
+	GPtrArray *array = NULL;
+	GError *error_local;
+	ZifStoreRemote *store;
+	gboolean ret;
+	guint i;
+
+	g_return_val_if_fail (ZIF_IS_REPOS (repos), FALSE);
+
+	/* if not already loaded, load */
+	if (!repos->priv->loaded) {
+		ret = zif_repos_load (repos, cancellable, completion, &error_local);
+		if (!ret) {
+			if (error != NULL)
+				*error = g_error_new (1, 0, "failed to load repos: %s", error_local->message);
+			g_error_free (error_local);
+			goto out;
+		}
+	}
+
+	/* make a copy */
+	array = g_ptr_array_new_with_free_func ((GDestroyNotify) g_object_unref);
+	for (i=0; i<repos->priv->list->len; i++) {
+		store = g_ptr_array_index (repos->priv->list, i);
+		g_ptr_array_add (array, g_object_ref (store));
+	}
+out:
+	return array;
+}
+
+/**
+ * zif_repos_get_stores_enabled:
+ * @repos: the #ZifRepos object
+ * @cancellable: a #GCancellable which is used to cancel tasks, or %NULL
+ * @completion: a #ZifCompletion to use for progress reporting
+ * @error: a #GError which is used on failure, or %NULL
+ *
+ * Gets the enabled remote stores.
+ *
+ * Return value: a list of #ZifStore's
+ **/
+GPtrArray *
+zif_repos_get_stores_enabled (ZifRepos *repos, GCancellable *cancellable, ZifCompletion *completion, GError **error)
+{
+	GPtrArray *array = NULL;
+	GError *error_local;
+	ZifStoreRemote *store;
+	gboolean ret;
+	guint i;
+
+	g_return_val_if_fail (ZIF_IS_REPOS (repos), FALSE);
+
+	/* if not already loaded, load */
+	if (!repos->priv->loaded) {
+		ret = zif_repos_load (repos, cancellable, completion, &error_local);
+		if (!ret) {
+			if (error != NULL)
+				*error = g_error_new (1, 0, "failed to load enabled repos: %s", error_local->message);
+			g_error_free (error_local);
+			goto out;
+		}
+	}
+
+	/* make a copy */
+	array = g_ptr_array_new_with_free_func ((GDestroyNotify) g_object_unref);
+	for (i=0; i<repos->priv->enabled->len; i++) {
+		store = g_ptr_array_index (repos->priv->enabled, i);
+		g_ptr_array_add (array, g_object_ref (store));
+	}
+out:
+	return array;
+}
+
+/**
+ * zif_repos_get_store:
+ * @repos: the #ZifRepos object
+ * @id: the repository id, e.g. "fedora"
+ * @cancellable: a #GCancellable which is used to cancel tasks, or %NULL
+ * @completion: a #ZifCompletion to use for progress reporting
+ * @error: a #GError which is used on failure, or %NULL
+ *
+ * Gets the store matching the ID.
+ *
+ * Return value: A #ZifStoreRemote object, or %NULL
+ **/
+ZifStoreRemote *
+zif_repos_get_store (ZifRepos *repos, const gchar *id, GCancellable *cancellable, ZifCompletion *completion, GError **error)
+{
+	guint i;
+	ZifStoreRemote *store = NULL;
+	ZifStoreRemote *store_tmp;
+	const gchar *id_tmp;
+	GError *error_local;
+	gboolean ret;
+
+	g_return_val_if_fail (ZIF_IS_REPOS (repos), FALSE);
+	g_return_val_if_fail (id != NULL, FALSE);
+
+	/* if not already loaded, load */
+	if (!repos->priv->loaded) {
+		ret = zif_repos_load (repos, cancellable, completion, &error_local);
+		if (!ret) {
+			if (error != NULL)
+				*error = g_error_new (1, 0, "failed to load repos: %s", error_local->message);
+			g_error_free (error_local);
+			goto out;
+		}
+	}
+
+	/* search though all the cached repos */
+	for (i=0; i<repos->priv->list->len; i++) {
+		store_tmp = g_ptr_array_index (repos->priv->list, i);
+
+		/* get the id */
+		id_tmp = zif_store_get_id (ZIF_STORE (store_tmp));
+		if (id_tmp == NULL) {
+			if (error != NULL)
+				*error = g_error_new (1, 0, "failed to get id");
+			goto out;
+		}
+
+		/* is it what we want? */
+		if (strcmp (id_tmp, id) == 0) {
+			store = g_object_ref (store_tmp);
+			break;
+		}
+	}
+out:
+	return store;
+}
+
+/**
+ * zif_repos_file_monitor_cb:
+ **/
+static void
+zif_repos_file_monitor_cb (ZifMonitor *monitor, ZifRepos *repos)
+{
+	g_ptr_array_set_size (repos->priv->list, 0);
+	g_ptr_array_set_size (repos->priv->enabled, 0);
+	egg_debug ("repo file changed");
+}
+
+/**
+ * zif_repos_finalize:
+ **/
+static void
+zif_repos_finalize (GObject *object)
+{
+	ZifRepos *repos;
+
+	g_return_if_fail (object != NULL);
+	g_return_if_fail (ZIF_IS_REPOS (object));
+	repos = ZIF_REPOS (object);
+
+	g_object_unref (repos->priv->monitor);
+	g_free (repos->priv->repos_dir);
+
+	g_ptr_array_unref (repos->priv->list);
+	g_ptr_array_unref (repos->priv->enabled);
+
+	G_OBJECT_CLASS (zif_repos_parent_class)->finalize (object);
+}
+
+/**
+ * zif_repos_class_init:
+ **/
+static void
+zif_repos_class_init (ZifReposClass *klass)
+{
+	GObjectClass *object_class = G_OBJECT_CLASS (klass);
+	object_class->finalize = zif_repos_finalize;
+	g_type_class_add_private (klass, sizeof (ZifReposPrivate));
+}
+
+/**
+ * zif_repos_init:
+ **/
+static void
+zif_repos_init (ZifRepos *repos)
+{
+	repos->priv = ZIF_REPOS_GET_PRIVATE (repos);
+	repos->priv->repos_dir = NULL;
+	repos->priv->list = g_ptr_array_new_with_free_func ((GDestroyNotify) g_object_unref);
+	repos->priv->enabled = g_ptr_array_new_with_free_func ((GDestroyNotify) g_object_unref);
+	repos->priv->monitor = zif_monitor_new ();
+	g_signal_connect (repos->priv->monitor, "changed", G_CALLBACK (zif_repos_file_monitor_cb), repos);
+}
+
+/**
+ * zif_repos_new:
+ *
+ * Return value: A new #ZifRepos class instance.
+ **/
+ZifRepos *
+zif_repos_new (void)
+{
+	if (zif_repos_object != NULL) {
+		g_object_ref (zif_repos_object);
+	} else {
+		zif_repos_object = g_object_new (ZIF_TYPE_REPOS, NULL);
+		g_object_add_weak_pointer (zif_repos_object, &zif_repos_object);
+	}
+	return ZIF_REPOS (zif_repos_object);
+}
+
+/***************************************************************************
+ ***                          MAKE CHECK TESTS                           ***
+ ***************************************************************************/
+#ifdef EGG_TEST
+#include "egg-test.h"
+#include "zif-lock.h"
+
+void
+zif_repos_test (EggTest *test)
+{
+	ZifStoreRemote *store;
+	ZifConfig *config;
+	ZifRepos *repos;
+	ZifLock *lock;
+	ZifCompletion *completion;
+	GPtrArray *array;
+	GError *error = NULL;
+	const gchar *value;
+	guint i;
+	gchar *repos_dir;
+	gboolean ret;
+
+	if (!egg_test_start (test, "ZifRepos"))
+		return;
+
+	/* set this up as dummy */
+	config = zif_config_new ();
+	zif_config_set_filename (config, "../test/etc/yum.conf", NULL);
+	repos_dir = zif_config_get_string (config, "reposdir", NULL);
+
+	/************************************************************/
+	egg_test_title (test, "get lock");
+	lock = zif_lock_new ();
+	egg_test_assert (test, lock != NULL);
+
+	/************************************************************/
+	egg_test_title (test, "lock");
+	ret = zif_lock_set_locked (lock, NULL, NULL);
+	egg_test_assert (test, ret);
+
+	/************************************************************/
+	egg_test_title (test, "get repos");
+	repos = zif_repos_new ();
+	egg_test_assert (test, repos != NULL);
+
+	/* use completion object */
+	completion = zif_completion_new ();
+
+	/************************************************************/
+	egg_test_title (test, "set repos dir %s", repos_dir);
+	ret = zif_repos_set_repos_dir (repos, repos_dir, &error);
+	if (ret)
+		egg_test_success (test, NULL);
+	else
+		egg_test_failed (test, "failed to set repos dir '%s'", error->message);
+
+	/************************************************************/
+	egg_test_title (test, "get list of repos");
+	array = zif_repos_get_stores (repos, NULL, completion, &error);
+	if (array != NULL)
+		egg_test_success (test, NULL);
+	else
+		egg_test_failed (test, "failed to load metadata '%s'", error->message);
+
+	/************************************************************/
+	egg_test_title (test, "list correct length");
+	if (array->len == 2)
+		egg_test_success (test, NULL);
+	else
+		egg_test_failed (test, "incorrect length %i", array->len);
+
+	for (i=0; i<array->len; i++) {
+		store = g_ptr_array_index (array, i);
+		zif_store_print (ZIF_STORE (store));
+	}
+	g_ptr_array_unref (array);
+
+	/************************************************************/
+	egg_test_title (test, "get list of enabled repos");
+	array = zif_repos_get_stores_enabled (repos, NULL, completion, &error);
+	if (array != NULL)
+		egg_test_success (test, NULL);
+	else
+		egg_test_failed (test, "failed to load metadata '%s'", error->message);
+
+	/************************************************************/
+	egg_test_title (test, "enabled correct length");
+	if (array->len == 2)
+		egg_test_success (test, NULL);
+	else
+		egg_test_failed (test, "incorrect length %i", array->len);
+
+	/* get ref for next test */
+	store = g_object_ref (g_ptr_array_index (array, 0));
+	g_ptr_array_unref (array);
+
+	/************************************************************/
+	egg_test_title (test, "get name");
+	value = zif_store_remote_get_name (store, NULL, completion, NULL);
+	if (egg_strequal (value, "Fedora 11 - i386"))
+		egg_test_success (test, NULL);
+	else
+		egg_test_failed (test, "invalid name '%s'", value);
+	g_object_unref (store);
+
+	g_object_unref (completion);
+	g_object_unref (repos);
+	g_object_unref (config);
+	g_object_unref (lock);
+	g_free (repos_dir);
+
+	egg_test_end (test);
+}
+#endif
+
diff --git a/backends/yum/libzif/zif-repos.h b/backends/yum/libzif/zif-repos.h
new file mode 100644
index 0000000..f9f83f2
--- /dev/null
+++ b/backends/yum/libzif/zif-repos.h
@@ -0,0 +1,81 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2008 Richard Hughes <richard at hughsie.com>
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#if !defined (__ZIF_H_INSIDE__) && !defined (ZIF_COMPILATION)
+#error "Only <zif.h> can be included directly."
+#endif
+
+#ifndef __ZIF_REPOS_H
+#define __ZIF_REPOS_H
+
+#include <glib-object.h>
+#include "zif-store-remote.h"
+
+G_BEGIN_DECLS
+
+#define ZIF_TYPE_REPOS		(zif_repos_get_type ())
+#define ZIF_REPOS(o)		(G_TYPE_CHECK_INSTANCE_CAST ((o), ZIF_TYPE_REPOS, ZifRepos))
+#define ZIF_REPOS_CLASS(k)	(G_TYPE_CHECK_CLASS_CAST((k), ZIF_TYPE_REPOS, ZifReposClass))
+#define ZIF_IS_REPOS(o)		(G_TYPE_CHECK_INSTANCE_TYPE ((o), ZIF_TYPE_REPOS))
+#define ZIF_IS_REPOS_CLASS(k)	(G_TYPE_CHECK_CLASS_TYPE ((k), ZIF_TYPE_REPOS))
+#define ZIF_REPOS_GET_CLASS(o)	(G_TYPE_INSTANCE_GET_CLASS ((o), ZIF_TYPE_REPOS, ZifReposClass))
+
+typedef struct _ZifRepos	ZifRepos;
+typedef struct _ZifReposPrivate	ZifReposPrivate;
+typedef struct _ZifReposClass	ZifReposClass;
+
+struct _ZifRepos
+{
+	GObject			 parent;
+	ZifReposPrivate		*priv;
+};
+
+struct _ZifReposClass
+{
+	GObjectClass		 parent_class;
+};
+
+GType		 zif_repos_get_type		(void);
+ZifRepos	*zif_repos_new			(void);
+gboolean	 zif_repos_set_repos_dir	(ZifRepos		*repos,
+						 const gchar		*repos_dir,
+						 GError			**error);
+gboolean	 zif_repos_load			(ZifRepos		*repos,
+						 GCancellable		*cancellable,
+						 ZifCompletion		*completion,
+						 GError			**error);
+GPtrArray	*zif_repos_get_stores		(ZifRepos		*repos,
+						 GCancellable		*cancellable,
+						 ZifCompletion		*completion,
+						 GError			**error);
+GPtrArray	*zif_repos_get_stores_enabled	(ZifRepos		*repos,
+						 GCancellable		*cancellable,
+						 ZifCompletion		*completion,
+						 GError			**error);
+ZifStoreRemote	*zif_repos_get_store		(ZifRepos		*repos,
+						 const gchar		*id,
+						 GCancellable		*cancellable,
+						 ZifCompletion		*completion,
+						 GError			**error);
+G_END_DECLS
+
+#endif /* __ZIF_REPOS_H */
+
diff --git a/backends/yum/libzif/zif-sack.c b/backends/yum/libzif/zif-sack.c
new file mode 100644
index 0000000..090bb7d
--- /dev/null
+++ b/backends/yum/libzif/zif-sack.c
@@ -0,0 +1,784 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2008 Richard Hughes <richard at hughsie.com>
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+/**
+ * SECTION:zif-sack
+ * @short_description: A sack is a container that holds one or more stores
+ *
+ * A #ZifSack is a container that #ZifStore's are kept. Global operations can
+ * be done on the sack and not the indervidual stores.
+ */
+
+#ifdef HAVE_CONFIG_H
+#  include <config.h>
+#endif
+
+#include <glib.h>
+#include <packagekit-glib2/packagekit.h>
+
+#include "zif-config.h"
+#include "zif-completion.h"
+#include "zif-store.h"
+#include "zif-store-local.h"
+#include "zif-sack.h"
+#include "zif-package.h"
+#include "zif-utils.h"
+#include "zif-repos.h"
+
+#include "egg-debug.h"
+#include "egg-string.h"
+
+#define ZIF_SACK_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), ZIF_TYPE_SACK, ZifSackPrivate))
+
+struct _ZifSackPrivate
+{
+	GPtrArray		*array;
+};
+
+/* in PackageKit we split categories from groups using a special @ prefix (bodge) */
+#define PK_ROLE_ENUM_SEARCH_CATEGORY	PK_ROLE_ENUM_UNKNOWN + 1
+
+G_DEFINE_TYPE (ZifSack, zif_sack, G_TYPE_OBJECT)
+
+/**
+ * zif_sack_add_store:
+ * @sack: the #ZifSack object
+ * @store: the #ZifStore to add
+ *
+ * Add a single #ZifStore to the #ZifSack.
+ *
+ * Return value: %TRUE for success, %FALSE for failure
+ **/
+gboolean
+zif_sack_add_store (ZifSack *sack, ZifStore *store)
+{
+	g_return_val_if_fail (ZIF_IS_SACK (sack), FALSE);
+	g_return_val_if_fail (store != NULL, FALSE);
+
+	g_ptr_array_add (sack->priv->array, g_object_ref (store));
+	return TRUE;
+}
+
+/**
+ * zif_sack_add_stores:
+ * @sack: the #ZifSack object
+ * @stores: the array of #ZifStore's to add
+ *
+ * Add an array of #ZifStore's to the #ZifSack.
+ *
+ * Return value: %TRUE for success, %FALSE for failure
+ **/
+gboolean
+zif_sack_add_stores (ZifSack *sack, GPtrArray *stores)
+{
+	guint i;
+	ZifStore *store;
+	gboolean ret = FALSE;
+
+	g_return_val_if_fail (ZIF_IS_SACK (sack), FALSE);
+	g_return_val_if_fail (stores != NULL, FALSE);
+
+	for (i=0; i<stores->len; i++) {
+		store = g_ptr_array_index (stores, i);
+		ret = zif_sack_add_store (sack, store);
+		if (!ret)
+			break;
+	}
+	return ret;
+}
+
+/**
+ * zif_sack_add_local:
+ * @sack: the #ZifSack object
+ * @cancellable: a #GCancellable which is used to cancel tasks, or %NULL
+ * @completion: a #ZifCompletion to use for progress reporting
+ * @error: a #GError which is used on failure, or %NULL
+ *
+ * Convenience function to add local store to the #ZifSack.
+ *
+ * Return value: %TRUE for success, %FALSE for failure
+ **/
+gboolean
+zif_sack_add_local (ZifSack *sack, GCancellable *cancellable, ZifCompletion *completion, GError **error)
+{
+	ZifStoreLocal *store;
+
+	g_return_val_if_fail (ZIF_IS_SACK (sack), FALSE);
+
+	store = zif_store_local_new ();
+	zif_sack_add_store (sack, ZIF_STORE (store));
+	g_object_unref (store);
+
+	return TRUE;
+}
+
+/**
+ * zif_sack_add_remote:
+ * @sack: the #ZifSack object
+ * @cancellable: a #GCancellable which is used to cancel tasks, or %NULL
+ * @completion: a #ZifCompletion to use for progress reporting
+ * @error: a #GError which is used on failure, or %NULL
+ *
+ * Convenience function to add remote stores to the #ZifSack.
+ *
+ * Return value: %TRUE for success, %FALSE for failure
+ **/
+gboolean
+zif_sack_add_remote (ZifSack *sack, GCancellable *cancellable, ZifCompletion *completion, GError **error)
+{
+	GPtrArray *array;
+	ZifRepos *repos;
+	GError *error_local = NULL;
+	gboolean ret = TRUE;
+
+	g_return_val_if_fail (ZIF_IS_SACK (sack), FALSE);
+
+	/* get stores */
+	repos = zif_repos_new ();
+	array = zif_repos_get_stores (repos, cancellable, completion, &error_local);
+	if (array == NULL) {
+		if (error != NULL)
+			*error = g_error_new (1, 0, "failed to get enabled stores: %s", error_local->message);
+		g_error_free (error_local);
+		ret = FALSE;
+		goto out;
+	}
+
+	/* add */
+	zif_sack_add_stores (ZIF_SACK (sack), array);
+
+	/* free */
+	g_ptr_array_unref (array);
+out:
+	g_object_unref (repos);
+	return ret;
+}
+
+/**
+ * zif_sack_add_remote_enabled:
+ * @sack: the #ZifSack object
+ * @cancellable: a #GCancellable which is used to cancel tasks, or %NULL
+ * @completion: a #ZifCompletion to use for progress reporting
+ * @error: a #GError which is used on failure, or %NULL
+ *
+ * Convenience function to add enabled remote stores to the #ZifSack.
+ *
+ * Return value: %TRUE for success, %FALSE for failure
+ **/
+gboolean
+zif_sack_add_remote_enabled (ZifSack *sack, GCancellable *cancellable, ZifCompletion *completion, GError **error)
+{
+	GPtrArray *array;
+	ZifRepos *repos;
+	GError *error_local = NULL;
+	gboolean ret = TRUE;
+
+	g_return_val_if_fail (ZIF_IS_SACK (sack), FALSE);
+
+	/* get stores */
+	repos = zif_repos_new ();
+	array = zif_repos_get_stores_enabled (repos, cancellable, completion, &error_local);
+	if (array == NULL) {
+		if (error != NULL)
+			*error = g_error_new (1, 0, "failed to get enabled stores: %s", error_local->message);
+		g_error_free (error_local);
+		ret = FALSE;
+		goto out;
+	}
+
+	/* add */
+	zif_sack_add_stores (ZIF_SACK (sack), array);
+
+	/* free */
+	g_ptr_array_unref (array);
+out:
+	g_object_unref (repos);
+	return ret;
+}
+
+/**
+ * zif_sack_repos_search:
+ **/
+static GPtrArray *
+zif_sack_repos_search (ZifSack *sack, PkRoleEnum role, const gchar *search, GCancellable *cancellable, ZifCompletion *completion, GError **error)
+{
+	guint i, j;
+	GPtrArray *array = NULL;
+	GPtrArray *stores;
+	GPtrArray *part;
+	ZifStore *store;
+	ZifPackage *package;
+	GError *error_local = NULL;
+	ZifCompletion *completion_local = NULL;
+
+	/* find results in each store */
+	stores = sack->priv->array;
+
+	/* nothing to do */
+	if (stores->len == 0) {
+		egg_warning ("nothing to do");
+		if (error != NULL)
+			*error = g_error_new (1, 0, "nothing to do as no stores in sack");
+		goto out;
+	}
+
+	/* set number of stores */
+	zif_completion_set_number_steps (completion, stores->len);
+
+	/* do each one */
+	array = g_ptr_array_new_with_free_func ((GDestroyNotify) g_object_unref);
+	for (i=0; i<stores->len; i++) {
+		store = g_ptr_array_index (stores, i);
+
+		/* create a chain of completions */
+		completion_local = zif_completion_get_child (completion);
+
+		/* get results for this store */
+		if (role == PK_ROLE_ENUM_RESOLVE)
+			part = zif_store_resolve (store, search, cancellable, completion_local, &error_local);
+		else if (role == PK_ROLE_ENUM_SEARCH_NAME)
+			part = zif_store_search_name (store, search, cancellable, completion_local, &error_local);
+		else if (role == PK_ROLE_ENUM_SEARCH_DETAILS)
+			part = zif_store_search_details (store, search, cancellable, completion_local, &error_local);
+		else if (role == PK_ROLE_ENUM_SEARCH_GROUP)
+			part = zif_store_search_group (store, search, cancellable, completion_local, &error_local);
+		else if (role == PK_ROLE_ENUM_SEARCH_CATEGORY)
+			part = zif_store_search_category (store, search, cancellable, completion_local, &error_local);
+		else if (role == PK_ROLE_ENUM_SEARCH_FILE)
+			part = zif_store_search_file (store, search, cancellable, completion_local, &error_local);
+		else if (role == PK_ROLE_ENUM_GET_PACKAGES)
+			part = zif_store_get_packages (store, cancellable, completion_local, &error_local);
+		else if (role == PK_ROLE_ENUM_GET_UPDATES)
+			part = zif_store_get_updates (store, cancellable, completion_local, &error_local);
+		else if (role == PK_ROLE_ENUM_WHAT_PROVIDES)
+			part = zif_store_what_provides (store, search, cancellable, completion_local, &error_local);
+		else if (role == PK_ROLE_ENUM_GET_CATEGORIES)
+			part = zif_store_get_categories (store, cancellable, completion_local, &error_local);
+		else
+			egg_error ("internal error: %s", pk_role_enum_to_text (role));
+		if (part == NULL) {
+			if (error != NULL)
+				*error = g_error_new (1, 0, "failed to %s in %s: %s", pk_role_enum_to_text (role), zif_store_get_id (store), error_local->message);
+			g_error_free (error_local);
+			g_ptr_array_unref (array);
+			array = NULL;
+			goto out;
+		}
+
+		for (j=0; j<part->len; j++) {
+			package = g_ptr_array_index (part, j);
+			g_ptr_array_add (array, g_object_ref (package));
+		}
+		g_ptr_array_unref (part);
+
+		/* this section done */
+		zif_completion_done (completion);
+	}
+out:
+	return array;
+}
+
+/**
+ * zif_sack_find_package:
+ * @sack: the #ZifSack object
+ * @package_id: the PackageId which defines the package
+ * @cancellable: a #GCancellable which is used to cancel tasks, or %NULL
+ * @completion: a #ZifCompletion to use for progress reporting
+ * @error: a #GError which is used on failure, or %NULL
+ *
+ * Find a single package in the #ZifSack.
+ *
+ * Return value: A single #ZifPackage or %NULL
+ **/
+ZifPackage *
+zif_sack_find_package (ZifSack *sack, const gchar *package_id, GCancellable *cancellable, ZifCompletion *completion, GError **error)
+{
+	guint i;
+	GPtrArray *stores;
+	ZifStore *store;
+	ZifPackage *package = NULL;
+	ZifCompletion *completion_local = NULL;
+
+	g_return_val_if_fail (ZIF_IS_SACK (sack), NULL);
+
+	/* find results in each store */
+	stores = sack->priv->array;
+
+	/* nothing to do */
+	if (stores->len == 0) {
+		egg_debug ("nothing to do");
+		goto out;
+	}
+
+	/* create a chain of completions */
+	zif_completion_set_number_steps (completion, stores->len);
+
+	/* do each one */
+	for (i=0; i<stores->len; i++) {
+		store = g_ptr_array_index (stores, i);
+
+		completion_local = zif_completion_get_child (completion);
+		package = zif_store_find_package (store, package_id, cancellable, completion_local, NULL);
+		if (package != NULL)
+			break;
+
+		/* this section done */
+		zif_completion_done (completion);
+	}
+out:
+	return package;
+}
+
+/**
+ * zif_sack_clean:
+ * @sack: the #ZifSack object
+ * @cancellable: a #GCancellable which is used to cancel tasks, or %NULL
+ * @completion: a #ZifCompletion to use for progress reporting
+ * @error: a #GError which is used on failure, or %NULL
+ *
+ * Cleans the #ZifStoreRemote objects by deleting cache.
+ *
+ * Return value: %TRUE for success, %FALSE for failure
+ **/
+gboolean
+zif_sack_clean (ZifSack *sack, GCancellable *cancellable, ZifCompletion *completion, GError **error)
+{
+	guint i;
+	GPtrArray *stores;
+	ZifStore *store;
+	gboolean ret = TRUE;
+	GError *error_local = NULL;
+	ZifCompletion *completion_local = NULL;
+
+	g_return_val_if_fail (ZIF_IS_SACK (sack), FALSE);
+
+	/* clean each store */
+	stores = sack->priv->array;
+
+	/* nothing to do */
+	if (stores->len == 0) {
+		egg_debug ("nothing to do");
+		goto out;
+	}
+
+	/* set number of stores */
+	zif_completion_set_number_steps (completion, stores->len);
+
+	/* do each one */
+	for (i=0; i<stores->len; i++) {
+		store = g_ptr_array_index (stores, i);
+
+		/* clean this one */
+		completion_local = zif_completion_get_child (completion);
+		ret = zif_store_clean (store, cancellable, completion_local, &error_local);
+		if (!ret) {
+			if (error != NULL)
+				*error = g_error_new (1, 0, "failed to clean %s: %s", zif_store_get_id (store), error_local->message);
+			g_error_free (error_local);
+			goto out;
+		}
+
+		/* this section done */
+		zif_completion_done (completion);
+	}
+out:
+	return ret;
+}
+
+/**
+ * zif_sack_refresh:
+ * @sack: the #ZifSack object
+ * @force: if the data should be re-downloaded if it's still valid
+ * @cancellable: a #GCancellable which is used to cancel tasks, or %NULL
+ * @completion: a #ZifCompletion to use for progress reporting
+ * @error: a #GError which is used on failure, or %NULL
+ *
+ * Refreshs the #ZifStoreRemote objects by downloading new data
+ *
+ * Return value: %TRUE for success, %FALSE for failure
+ **/
+gboolean
+zif_sack_refresh (ZifSack *sack, gboolean force, GCancellable *cancellable, ZifCompletion *completion, GError **error)
+{
+	guint i;
+	GPtrArray *stores;
+	ZifStore *store;
+	gboolean ret = TRUE;
+	GError *error_local = NULL;
+	ZifCompletion *completion_local = NULL;
+
+	g_return_val_if_fail (ZIF_IS_SACK (sack), FALSE);
+
+	/* refresh each store */
+	stores = sack->priv->array;
+
+	/* nothing to do */
+	if (stores->len == 0) {
+		egg_debug ("nothing to do");
+		goto out;
+	}
+
+	/* create a chain of completions */
+	zif_completion_set_number_steps (completion, stores->len);
+
+	/* do each one */
+	for (i=0; i<stores->len; i++) {
+		store = g_ptr_array_index (stores, i);
+
+		egg_warning ("refreshing %s", zif_store_get_id (store));
+
+		/* refresh this one */
+		completion_local = zif_completion_get_child (completion);
+		ret = zif_store_refresh (store, force, cancellable, completion_local, &error_local);
+		if (!ret) {
+			//if (error != NULL)
+			//	*error = g_error_new (1, 0, "failed to refresh %s: %s", zif_store_get_id (store), error_local->message);
+			//g_error_free (error_local);
+			//goto out;
+			/* non-fatal */
+			g_print ("failed to refresh %s: %s\n", zif_store_get_id (store), error_local->message);
+			g_clear_error (&error_local);
+			ret = TRUE;
+		}
+
+		/* this section done */
+		zif_completion_done (completion);
+	}
+out:
+	return ret;
+}
+
+/**
+ * zif_sack_resolve:
+ * @sack: the #ZifSack object
+ * @search: the search term, e.g. "gnome-power-manager"
+ * @cancellable: a #GCancellable which is used to cancel tasks, or %NULL
+ * @completion: a #ZifCompletion to use for progress reporting
+ * @error: a #GError which is used on failure, or %NULL
+ *
+ * Finds packages matching the package name exactly.
+ *
+ * Return value: an array of #ZifPackage's
+ **/
+GPtrArray *
+zif_sack_resolve (ZifSack *sack, const gchar *search, GCancellable *cancellable, ZifCompletion *completion, GError **error)
+{
+	g_return_val_if_fail (ZIF_IS_SACK (sack), NULL);
+	return zif_sack_repos_search (sack, PK_ROLE_ENUM_RESOLVE, search, cancellable, completion, error);
+}
+
+/**
+ * zif_sack_search_name:
+ * @sack: the #ZifSack object
+ * @search: the search term, e.g. "power"
+ * @cancellable: a #GCancellable which is used to cancel tasks, or %NULL
+ * @completion: a #ZifCompletion to use for progress reporting
+ * @error: a #GError which is used on failure, or %NULL
+ *
+ * Find packages that match the package name in some part.
+ *
+ * Return value: an array of #ZifPackage's
+ **/
+GPtrArray *
+zif_sack_search_name (ZifSack *sack, const gchar *search, GCancellable *cancellable, ZifCompletion *completion, GError **error)
+{
+	g_return_val_if_fail (ZIF_IS_SACK (sack), NULL);
+	return zif_sack_repos_search (sack, PK_ROLE_ENUM_SEARCH_NAME, search, cancellable, completion, error);
+}
+
+/**
+ * zif_sack_search_details:
+ * @sack: the #ZifSack object
+ * @search: the search term, e.g. "trouble"
+ * @cancellable: a #GCancellable which is used to cancel tasks, or %NULL
+ * @completion: a #ZifCompletion to use for progress reporting
+ * @error: a #GError which is used on failure, or %NULL
+ *
+ * Find packages that match some detail about the package.
+ *
+ * Return value: an array of #ZifPackage's
+ **/
+GPtrArray *
+zif_sack_search_details (ZifSack *sack, const gchar *search, GCancellable *cancellable, ZifCompletion *completion, GError **error)
+{
+	g_return_val_if_fail (ZIF_IS_SACK (sack), NULL);
+	return zif_sack_repos_search (sack, PK_ROLE_ENUM_SEARCH_DETAILS, search, cancellable, completion, error);
+}
+
+/**
+ * zif_sack_search_group:
+ * @sack: the #ZifSack object
+ * @group_enum: the group enumerated value, e.g. "games"
+ * @cancellable: a #GCancellable which is used to cancel tasks, or %NULL
+ * @completion: a #ZifCompletion to use for progress reporting
+ * @error: a #GError which is used on failure, or %NULL
+ *
+ * Find packages that belong in a specific group.
+ *
+ * Return value: an array of #ZifPackage's
+ **/
+GPtrArray *
+zif_sack_search_group (ZifSack *sack, const gchar *group_enum, GCancellable *cancellable, ZifCompletion *completion, GError **error)
+{
+	g_return_val_if_fail (ZIF_IS_SACK (sack), NULL);
+	return zif_sack_repos_search (sack, PK_ROLE_ENUM_SEARCH_GROUP, group_enum, cancellable, completion, error);
+}
+
+/**
+ * zif_sack_search_category:
+ * @sack: the #ZifSack object
+ * @group_id: the group id, e.g. "gnome-system-tools"
+ * @cancellable: a #GCancellable which is used to cancel tasks, or %NULL
+ * @completion: a #ZifCompletion to use for progress reporting
+ * @error: a #GError which is used on failure, or %NULL
+ *
+ * Find packages that belong in a specific category.
+ *
+ * Return value: an array of #ZifPackage's
+ **/
+GPtrArray *
+zif_sack_search_category (ZifSack *sack, const gchar *group_id, GCancellable *cancellable, ZifCompletion *completion, GError **error)
+{
+	guint i, j;
+	GPtrArray *array;
+	ZifPackage *package;
+	const gchar *package_id;
+	const gchar *package_id_tmp;
+	gchar **split;
+
+	g_return_val_if_fail (ZIF_IS_SACK (sack), NULL);
+
+	/* get all results from all repos */
+	array = zif_sack_repos_search (sack, PK_ROLE_ENUM_SEARCH_CATEGORY, group_id, cancellable, completion, error);
+	if (array == NULL)
+		goto out;
+
+	/* remove duplicate package_ids */
+	for (i=0; i<array->len; i++) {
+		package = g_ptr_array_index (array, i);
+		package_id = zif_package_get_id (package);
+		for (j=0; j<array->len; j++) {
+			if (i == j)
+				continue;
+			package = g_ptr_array_index (array, j);
+			package_id_tmp = zif_package_get_id (package);
+			if (g_strcmp0 (package_id, package_id_tmp) == 0) {
+				split = pk_package_id_split (package_id);
+				egg_warning ("duplicate %s-%s", split[PK_PACKAGE_ID_NAME], split[PK_PACKAGE_ID_VERSION]);
+				g_ptr_array_remove_index (array, j);
+				g_strfreev (split);
+			}
+		}
+	}
+out:
+	return array;
+}
+
+/**
+ * zif_sack_search_file:
+ * @sack: the #ZifSack object
+ * @search: the search term, e.g. "/usr/bin/gnome-power-manager"
+ * @cancellable: a #GCancellable which is used to cancel tasks, or %NULL
+ * @completion: a #ZifCompletion to use for progress reporting
+ * @error: a #GError which is used on failure, or %NULL
+ *
+ * Find packages that provide the specified file.
+ *
+ * Return value: an array of #ZifPackage's
+ **/
+GPtrArray *
+zif_sack_search_file (ZifSack *sack, const gchar *search, GCancellable *cancellable, ZifCompletion *completion, GError **error)
+{
+	g_return_val_if_fail (ZIF_IS_SACK (sack), NULL);
+	return zif_sack_repos_search (sack, PK_ROLE_ENUM_SEARCH_FILE, search, cancellable, completion, error);
+}
+
+/**
+ * zif_sack_get_packages:
+ * @sack: the #ZifSack object
+ * @cancellable: a #GCancellable which is used to cancel tasks, or %NULL
+ * @completion: a #ZifCompletion to use for progress reporting
+ * @error: a #GError which is used on failure, or %NULL
+ *
+ * Return all packages in the #ZifSack's.
+ *
+ * Return value: an array of #ZifPackage's
+ **/
+GPtrArray *
+zif_sack_get_packages (ZifSack *sack, GCancellable *cancellable, ZifCompletion *completion, GError **error)
+{
+	g_return_val_if_fail (ZIF_IS_SACK (sack), NULL);
+	return zif_sack_repos_search (sack, PK_ROLE_ENUM_GET_PACKAGES, NULL, cancellable, completion, error);
+}
+
+/**
+ * zif_sack_get_updates:
+ * @sack: the #ZifSack object
+ * @cancellable: a #GCancellable which is used to cancel tasks, or %NULL
+ * @completion: a #ZifCompletion to use for progress reporting
+ * @error: a #GError which is used on failure, or %NULL
+ *
+ * Return a list of packages that are updatable.
+ *
+ * Return value: an array of #ZifPackage's
+ **/
+GPtrArray *
+zif_sack_get_updates (ZifSack *sack, GCancellable *cancellable, ZifCompletion *completion, GError **error)
+{
+	g_return_val_if_fail (ZIF_IS_SACK (sack), NULL);
+	return zif_sack_repos_search (sack, PK_ROLE_ENUM_GET_UPDATES, NULL, cancellable, completion, error);
+}
+
+/**
+ * zif_sack_what_provides:
+ * @sack: the #ZifSack object
+ * @search: the search term, e.g. "gstreamer(codec-mp3)"
+ * @cancellable: a #GCancellable which is used to cancel tasks, or %NULL
+ * @completion: a #ZifCompletion to use for progress reporting
+ * @error: a #GError which is used on failure, or %NULL
+ *
+ * Find packages that provide a specific string.
+ *
+ * Return value: an array of #ZifPackage's
+ **/
+GPtrArray *
+zif_sack_what_provides (ZifSack *sack, const gchar *search, GCancellable *cancellable, ZifCompletion *completion, GError **error)
+{
+	g_return_val_if_fail (ZIF_IS_SACK (sack), NULL);
+
+	/* if this is a path, then we use the file list and treat like a SearchFile */
+	if (g_str_has_prefix (search, "/"))
+		return zif_sack_repos_search (sack, PK_ROLE_ENUM_SEARCH_FILE, search, cancellable, completion, error);
+	return zif_sack_repos_search (sack, PK_ROLE_ENUM_WHAT_PROVIDES, search, cancellable, completion, error);
+}
+
+/**
+ * zif_sack_get_categories:
+ * @sack: the #ZifSack object
+ * @cancellable: a #GCancellable which is used to cancel tasks, or %NULL
+ * @completion: a #ZifCompletion to use for progress reporting
+ * @error: a #GError which is used on failure, or %NULL
+ *
+ * Return a list of custom categories from all repos.
+ *
+ * Return value: an array of #PkCategory's
+ **/
+GPtrArray *
+zif_sack_get_categories (ZifSack *sack, GCancellable *cancellable, ZifCompletion *completion, GError **error)
+{
+	guint i, j;
+	GPtrArray *array;
+	PkCategory *obj;
+	PkCategory *obj_tmp;
+	gchar *parent_id;
+	gchar *parent_id_tmp;
+	gchar *cat_id;
+	gchar *cat_id_tmp;
+
+	g_return_val_if_fail (ZIF_IS_SACK (sack), NULL);
+
+	/* get all results from all repos */
+	array = zif_sack_repos_search (sack, PK_ROLE_ENUM_GET_CATEGORIES, NULL, cancellable, completion, error);
+	if (array == NULL)
+		goto out;
+
+	/* remove duplicate parents and groups */
+	for (i=0; i<array->len; i++) {
+		obj = g_ptr_array_index (array, i);
+		g_object_get (obj,
+			      "parent-id", &parent_id,
+			      "cat-id", &cat_id,
+			      NULL);
+		for (j=0; j<array->len; j++) {
+			if (i == j)
+				continue;
+			obj_tmp = g_ptr_array_index (array, j);
+			g_object_get (obj_tmp,
+				      "parent-id", &parent_id_tmp,
+				      "cat-id", &cat_id_tmp,
+				      NULL);
+			if (g_strcmp0 (parent_id_tmp, parent_id) == 0 &&
+			    g_strcmp0 (cat_id_tmp, cat_id) == 0) {
+				egg_warning ("duplicate %s-%s", parent_id, cat_id);
+				g_object_unref (obj_tmp);
+				g_ptr_array_remove_index (array, j);
+			}
+			g_free (parent_id);
+			g_free (cat_id);
+		}
+		g_free (parent_id);
+		g_free (cat_id);
+	}
+out:
+	return array;
+}
+
+/**
+ * zif_sack_finalize:
+ **/
+static void
+zif_sack_finalize (GObject *object)
+{
+	ZifSack *sack;
+
+	g_return_if_fail (object != NULL);
+	g_return_if_fail (ZIF_IS_SACK (object));
+	sack = ZIF_SACK (object);
+
+	g_ptr_array_unref (sack->priv->array);
+
+	G_OBJECT_CLASS (zif_sack_parent_class)->finalize (object);
+}
+
+/**
+ * zif_sack_class_init:
+ **/
+static void
+zif_sack_class_init (ZifSackClass *klass)
+{
+	GObjectClass *object_class = G_OBJECT_CLASS (klass);
+	object_class->finalize = zif_sack_finalize;
+	g_type_class_add_private (klass, sizeof (ZifSackPrivate));
+}
+
+/**
+ * zif_sack_init:
+ **/
+static void
+zif_sack_init (ZifSack *sack)
+{
+	sack->priv = ZIF_SACK_GET_PRIVATE (sack);
+	sack->priv->array = g_ptr_array_new_with_free_func ((GDestroyNotify) g_object_unref);
+}
+
+/**
+ * zif_sack_new:
+ *
+ * Return value: A new #ZifSack class instance.
+ **/
+ZifSack *
+zif_sack_new (void)
+{
+	ZifSack *sack;
+	sack = g_object_new (ZIF_TYPE_SACK, NULL);
+	return ZIF_SACK (sack);
+}
+
diff --git a/backends/yum/libzif/zif-sack.h b/backends/yum/libzif/zif-sack.h
new file mode 100644
index 0000000..ee588d5
--- /dev/null
+++ b/backends/yum/libzif/zif-sack.h
@@ -0,0 +1,146 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2008 Richard Hughes <richard at hughsie.com>
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#if !defined (__ZIF_H_INSIDE__) && !defined (ZIF_COMPILATION)
+#error "Only <zif.h> can be included directly."
+#endif
+
+#ifndef __ZIF_SACK_H
+#define __ZIF_SACK_H
+
+#include <glib-object.h>
+
+#include "zif-store.h"
+#include "zif-package.h"
+#include "zif-completion.h"
+
+G_BEGIN_DECLS
+
+#define ZIF_TYPE_SACK		(zif_sack_get_type ())
+#define ZIF_SACK(o)		(G_TYPE_CHECK_INSTANCE_CAST ((o), ZIF_TYPE_SACK, ZifSack))
+#define ZIF_SACK_CLASS(k)	(G_TYPE_CHECK_CLASS_CAST((k), ZIF_TYPE_SACK, ZifSackClass))
+#define ZIF_IS_SACK(o)		(G_TYPE_CHECK_INSTANCE_TYPE ((o), ZIF_TYPE_SACK))
+#define ZIF_IS_SACK_CLASS(k)	(G_TYPE_CHECK_CLASS_TYPE ((k), ZIF_TYPE_SACK))
+#define ZIF_SACK_GET_CLASS(o)	(G_TYPE_INSTANCE_GET_CLASS ((o), ZIF_TYPE_SACK, ZifSackClass))
+
+typedef struct _ZifSack		ZifSack;
+typedef struct _ZifSackPrivate	ZifSackPrivate;
+typedef struct _ZifSackClass	ZifSackClass;
+
+struct _ZifSack
+{
+	GObject			 parent;
+	ZifSackPrivate		*priv;
+};
+
+struct _ZifSackClass
+{
+	GObjectClass		 parent_class;
+};
+
+GType		 zif_sack_get_type		(void);
+ZifSack		*zif_sack_new			(void);
+
+/* stores */
+gboolean	 zif_sack_add_store		(ZifSack		*sack,
+						 ZifStore		*store);
+gboolean	 zif_sack_add_stores		(ZifSack		*sack,
+						 GPtrArray		*stores);
+gboolean	 zif_sack_add_local		(ZifSack		*sack,
+						 GCancellable		*cancellable,
+						 ZifCompletion		*completion,
+						 GError			**error);
+gboolean	 zif_sack_add_remote		(ZifSack		*sack,
+						 GCancellable		*cancellable,
+						 ZifCompletion		*completion,
+						 GError			**error);
+gboolean	 zif_sack_add_remote_enabled	(ZifSack		*sack,
+						 GCancellable		*cancellable,
+						 ZifCompletion		*completion,
+						 GError			**error);
+
+/* methods */
+gboolean	 zif_sack_clean			(ZifSack		*sack,
+						 GCancellable		*cancellable,
+						 ZifCompletion		*completion,
+						 GError			**error);
+gboolean	 zif_sack_refresh		(ZifSack		*sack,
+						 gboolean		 force,
+						 GCancellable		*cancellable,
+						 ZifCompletion		*completion,
+						 GError			**error);
+GPtrArray	*zif_sack_resolve		(ZifSack		*sack,
+						 const gchar		*search,
+						 GCancellable		*cancellable,
+						 ZifCompletion		*completion,
+						 GError			**error);
+GPtrArray	*zif_sack_search_name		(ZifSack		*sack,
+						 const gchar		*search,
+						 GCancellable		*cancellable,
+						 ZifCompletion		*completion,
+						 GError			**error);
+GPtrArray	*zif_sack_search_details	(ZifSack		*sack,
+						 const gchar		*search,
+						 GCancellable		*cancellable,
+						 ZifCompletion		*completion,
+						 GError			**error);
+GPtrArray	*zif_sack_search_group		(ZifSack		*sack,
+						 const gchar		*group_enum,
+						 GCancellable		*cancellable,
+						 ZifCompletion		*completion,
+						 GError			**error);
+GPtrArray	*zif_sack_search_category	(ZifSack		*sack,
+						 const gchar		*group_id,
+						 GCancellable		*cancellable,
+						 ZifCompletion		*completion,
+						 GError			**error);
+GPtrArray	*zif_sack_search_file		(ZifSack		*sack,
+						 const gchar		*search,
+						 GCancellable		*cancellable,
+						 ZifCompletion		*completion,
+						 GError			**error);
+GPtrArray	*zif_sack_what_provides		(ZifSack		*sack,
+						 const gchar		*search,
+						 GCancellable		*cancellable,
+						 ZifCompletion		*completion,
+						 GError			**error);
+GPtrArray	*zif_sack_get_packages		(ZifSack		*sack,
+						 GCancellable		*cancellable,
+						 ZifCompletion		*completion,
+						 GError			**error);
+GPtrArray	*zif_sack_get_updates		(ZifSack		*sack,
+						 GCancellable		*cancellable,
+						 ZifCompletion		*completion,
+						 GError			**error);
+ZifPackage	*zif_sack_find_package		(ZifSack		*sack,
+						 const gchar		*package_id,
+						 GCancellable		*cancellable,
+						 ZifCompletion		*completion,
+						 GError			**error);
+GPtrArray	*zif_sack_get_categories	(ZifSack		*sack,
+						 GCancellable		*cancellable,
+						 ZifCompletion		*completion,
+						 GError			**error);
+
+G_END_DECLS
+
+#endif /* __ZIF_SACK_H */
+
diff --git a/backends/yum/libzif/zif-self-test.c b/backends/yum/libzif/zif-self-test.c
new file mode 100644
index 0000000..274290e
--- /dev/null
+++ b/backends/yum/libzif/zif-self-test.c
@@ -0,0 +1,82 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2008 Richard Hughes <richard at hughsie.com>
+ * Copyright (C) 2008 Shishir Goel <crazyontheedge at gmail.com>
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "config.h"
+
+#include <glib.h>
+#include <glib-object.h>
+#include "egg-test.h"
+#include "egg-debug.h"
+
+/* prototypes */
+void zif_completion_test (EggTest *test);
+void zif_monitor_test (EggTest *test);
+void zif_config_test (EggTest *test);
+void zif_utils_test (EggTest *test);
+void zif_package_test (EggTest *test);
+void zif_package_local_test (EggTest *test);
+void zif_store_local_test (EggTest *test);
+void zif_groups_test (EggTest *test);
+void zif_store_remote_test (EggTest *test);
+void zif_repo_md_metalink_test (EggTest *test);
+void zif_repo_md_primary_test (EggTest *test);
+void zif_repo_md_filelists_test (EggTest *test);
+void zif_repo_md_comps_test (EggTest *test);
+void zif_repos_test (EggTest *test);
+void zif_download_test (EggTest *test);
+void zif_string_test (EggTest *test);
+void zif_lock_test (EggTest *test);
+
+int
+main (int argc, char **argv)
+{
+	EggTest *test;
+
+	g_type_init ();
+	g_thread_init (NULL);
+	test = egg_test_init ();
+	egg_debug_init (TRUE);
+	zif_init ();
+
+	/* tests go here */
+	zif_lock_test (test);
+	zif_completion_test (test);
+	zif_config_test (test);
+	zif_string_test (test);
+	zif_repo_md_metalink_test (test);
+	zif_repo_md_mirrorlist_test (test);
+	zif_repo_md_filelists_test (test);
+	zif_repo_md_primary_test (test);
+	zif_repo_md_comps_test (test);
+	zif_download_test (test);
+	zif_monitor_test (test);
+	zif_package_test (test);
+	zif_store_local_test (test);
+	zif_package_local_test (test);
+	zif_groups_test (test);
+	zif_store_remote_test (test);
+	zif_repos_test (test);
+	zif_utils_test (test);
+
+	return (egg_test_finish (test));
+}
+
diff --git a/backends/yum/libzif/zif-store-local.c b/backends/yum/libzif/zif-store-local.c
new file mode 100644
index 0000000..f9f7f51
--- /dev/null
+++ b/backends/yum/libzif/zif-store-local.c
@@ -0,0 +1,1298 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2008 Richard Hughes <richard at hughsie.com>
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+/**
+ * SECTION:zif-store-local
+ * @short_description: A local store is a store that can operate on installed packages
+ *
+ * A #ZifStoreLocal is a subclassed #ZifStore and operates on installed objects.
+ */
+
+#ifdef HAVE_CONFIG_H
+#  include <config.h>
+#endif
+
+#define _GNU_SOURCE
+#include <string.h>
+
+#include <glib.h>
+#include <rpm/rpmlib.h>
+#include <rpm/rpmdb.h>
+#include <fcntl.h>
+#include <packagekit-glib2/packagekit.h>
+
+#include "zif-store.h"
+#include "zif-store-local.h"
+#include "zif-groups.h"
+#include "zif-package-local.h"
+#include "zif-monitor.h"
+#include "zif-string.h"
+#include "zif-depend.h"
+#include "zif-lock.h"
+
+#include "egg-debug.h"
+#include "egg-string.h"
+
+#define ZIF_STORE_LOCAL_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), ZIF_TYPE_STORE_LOCAL, ZifStoreLocalPrivate))
+
+struct _ZifStoreLocalPrivate
+{
+	gboolean		 loaded;
+	gchar			*prefix;
+	GPtrArray		*packages;
+	ZifGroups		*groups;
+	ZifMonitor		*monitor;
+	ZifLock			*lock;
+};
+
+
+G_DEFINE_TYPE (ZifStoreLocal, zif_store_local, ZIF_TYPE_STORE)
+static gpointer zif_store_local_object = NULL;
+
+/**
+ * zif_store_local_set_prefix:
+ * @store: the #ZifStoreLocal object
+ * @prefix: the install root, e.g. "/"
+ * @error: a #GError which is used on failure, or %NULL
+ *
+ * Sets the prefix to use for the install root.
+ *
+ * Return value: %TRUE for success, %FALSE for failure
+ **/
+gboolean
+zif_store_local_set_prefix (ZifStoreLocal *store, const gchar *prefix, GError **error)
+{
+	gboolean ret;
+	GError *error_local = NULL;
+	gchar *filename = NULL;
+
+	g_return_val_if_fail (ZIF_IS_STORE_LOCAL (store), FALSE);
+	g_return_val_if_fail (store->priv->prefix == NULL, FALSE);
+	g_return_val_if_fail (!store->priv->loaded, FALSE);
+	g_return_val_if_fail (prefix != NULL, FALSE);
+
+	/* check file exists */
+	ret = g_file_test (prefix, G_FILE_TEST_IS_DIR);
+	if (!ret) {
+		if (error != NULL)
+			*error = g_error_new (1, 0, "prefix %s does not exist", prefix);
+		goto out;
+	}
+
+	/* setup watch */
+	filename = g_build_filename (prefix, "var", "lib", "rpm", "Packages", NULL);
+	ret = zif_monitor_add_watch (store->priv->monitor, filename, &error_local);
+	if (!ret) {
+		if (error != NULL)
+			*error = g_error_new (1, 0, "failed to setup watch: %s", error_local->message);
+		g_error_free (error_local);
+		goto out;
+	}
+
+	store->priv->prefix = g_strdup (prefix);
+out:
+	g_free (filename);
+	return ret;
+}
+
+/**
+ * zif_store_local_load:
+ **/
+static gboolean
+zif_store_local_load (ZifStore *store, GCancellable *cancellable, ZifCompletion *completion, GError **error)
+{
+	gint retval;
+	gboolean ret = TRUE;
+	rpmdbMatchIterator mi;
+	Header header;
+	ZifPackageLocal *package;
+	rpmdb db;
+	GError *error_local = NULL;
+	ZifStoreLocal *local = ZIF_STORE_LOCAL (store);
+
+	g_return_val_if_fail (ZIF_IS_STORE_LOCAL (store), FALSE);
+	g_return_val_if_fail (local->priv->prefix != NULL, FALSE);
+	g_return_val_if_fail (local->priv->packages != NULL, FALSE);
+
+	/* not locked */
+	ret = zif_lock_is_locked (local->priv->lock, NULL);
+	if (!ret) {
+		egg_warning ("not locked");
+		if (error != NULL)
+			*error = g_error_new (1, 0, "not locked");
+		goto out;
+	}
+
+	/* already loaded */
+	if (local->priv->loaded)
+		goto out;
+
+	/* setup completion with the correct number of steps */
+	zif_completion_set_number_steps (completion, 2);
+
+	retval = rpmdbOpen (local->priv->prefix, &db, O_RDONLY, 0777);
+	if (retval != 0) {
+		if (error != NULL)
+			*error = g_error_new (1, 0, "failed to open rpmdb");
+		ret = FALSE;
+		goto out;
+	}
+
+	/* this section done */
+	zif_completion_done (completion);
+
+	/* get list */
+	mi = rpmdbInitIterator (db, RPMDBI_PACKAGES, NULL, 0);
+	if (mi == NULL)
+		egg_warning ("failed to get iterator");
+	do {
+		header = rpmdbNextIterator (mi);
+		if (header == NULL)
+			break;
+		package = zif_package_local_new ();
+		ret = zif_package_local_set_from_header (package, header, &error_local);
+		if (!ret) {
+			if (error != NULL)
+				*error = g_error_new (1, 0, "failed to set from header: %s", error_local->message);
+			g_error_free (error_local);
+			g_object_unref (package);
+			break;
+		}
+		g_ptr_array_add (local->priv->packages, package);
+	} while (TRUE);
+	rpmdbFreeIterator (mi);
+	rpmdbClose (db);
+
+	/* this section done */
+	zif_completion_done (completion);
+
+	/* okay */
+	local->priv->loaded = TRUE;
+out:
+	return ret;
+}
+
+/**
+ * zif_store_local_search_name:
+ **/
+static GPtrArray *
+zif_store_local_search_name (ZifStore *store, const gchar *search, GCancellable *cancellable, ZifCompletion *completion, GError **error)
+{
+	guint i;
+	GPtrArray *array = NULL;
+	ZifPackage *package;
+	const gchar *package_id;
+	gchar **split;
+	GError *error_local = NULL;
+	gboolean ret;
+	ZifCompletion *completion_local = NULL;
+	ZifStoreLocal *local = ZIF_STORE_LOCAL (store);
+
+	g_return_val_if_fail (ZIF_IS_STORE_LOCAL (store), NULL);
+	g_return_val_if_fail (search != NULL, NULL);
+	g_return_val_if_fail (local->priv->prefix != NULL, NULL);
+
+	/* not locked */
+	ret = zif_lock_is_locked (local->priv->lock, NULL);
+	if (!ret) {
+		egg_warning ("not locked");
+		if (error != NULL)
+			*error = g_error_new (1, 0, "not locked");
+		goto out;
+	}
+
+	/* we have a different number of steps depending if we are loaded or not */
+	if (local->priv->loaded)
+		zif_completion_set_number_steps (completion, 1);
+	else
+		zif_completion_set_number_steps (completion, 2);
+
+	/* if not already loaded, load */
+	if (!local->priv->loaded) {
+		completion_local = zif_completion_get_child (completion);
+		ret = zif_store_local_load (store, cancellable, completion_local, &error_local);
+		if (!ret) {
+			if (error != NULL)
+				*error = g_error_new (1, 0, "failed to load package store: %s", error_local->message);
+			g_error_free (error_local);
+			goto out;
+		}
+
+		/* this section done */
+		zif_completion_done (completion);
+	}
+
+	/* check we have packages */
+	if (local->priv->packages->len == 0) {
+		egg_warning ("no packages in sack, so nothing to do!");
+		if (error != NULL)
+			*error = g_error_new (1, 0, "no packages in local sack");
+		goto out;
+	}
+
+	/* setup completion with the correct number of steps */
+	completion_local = zif_completion_get_child (completion);
+	zif_completion_set_number_steps (completion_local, local->priv->packages->len);
+
+	/* iterate list */
+	array = g_ptr_array_new_with_free_func ((GDestroyNotify) g_object_unref);
+	for (i=0;i<local->priv->packages->len;i++) {
+		package = g_ptr_array_index (local->priv->packages, i);
+		package_id = zif_package_get_id (package);
+		split = pk_package_id_split (package_id);
+		if (strcasestr (split[PK_PACKAGE_ID_NAME], search) != NULL)
+			g_ptr_array_add (array, g_object_ref (package));
+		g_strfreev (split);
+
+		/* this section done */
+		zif_completion_done (completion_local);
+	}
+
+	/* this section done */
+	zif_completion_done (completion);
+out:
+	return array;
+}
+
+/**
+ * zif_store_local_search_category:
+ **/
+static GPtrArray *
+zif_store_local_search_category (ZifStore *store, const gchar *search, GCancellable *cancellable, ZifCompletion *completion, GError **error)
+{
+	guint i;
+	GPtrArray *array = NULL;
+	ZifPackage *package;
+	ZifString *category;
+	GError *error_local = NULL;
+	gboolean ret;
+	ZifCompletion *completion_local = NULL;
+	ZifStoreLocal *local = ZIF_STORE_LOCAL (store);
+
+	g_return_val_if_fail (ZIF_IS_STORE_LOCAL (store), NULL);
+	g_return_val_if_fail (search != NULL, NULL);
+	g_return_val_if_fail (local->priv->prefix != NULL, NULL);
+
+	/* not locked */
+	ret = zif_lock_is_locked (local->priv->lock, NULL);
+	if (!ret) {
+		egg_warning ("not locked");
+		if (error != NULL)
+			*error = g_error_new (1, 0, "not locked");
+		goto out;
+	}
+
+	/* we have a different number of steps depending if we are loaded or not */
+	if (local->priv->loaded)
+		zif_completion_set_number_steps (completion, 1);
+	else
+		zif_completion_set_number_steps (completion, 2);
+
+	/* if not already loaded, load */
+	if (!local->priv->loaded) {
+		completion_local = zif_completion_get_child (completion);
+		ret = zif_store_local_load (store, cancellable, completion_local, &error_local);
+		if (!ret) {
+			if (error != NULL)
+				*error = g_error_new (1, 0, "failed to load package store: %s", error_local->message);
+			g_error_free (error_local);
+			goto out;
+		}
+
+		/* this section done */
+		zif_completion_done (completion);
+	}
+
+	/* check we have packages */
+	if (local->priv->packages->len == 0) {
+		egg_warning ("no packages in sack, so nothing to do!");
+		if (error != NULL)
+			*error = g_error_new (1, 0, "no packages in local sack");
+		goto out;
+	}
+
+	/* setup completion with the correct number of steps */
+	completion_local = zif_completion_get_child (completion);
+	zif_completion_set_number_steps (completion_local, local->priv->packages->len);
+
+	/* iterate list */
+	array = g_ptr_array_new_with_free_func ((GDestroyNotify) g_object_unref);
+	for (i=0;i<local->priv->packages->len;i++) {
+		package = g_ptr_array_index (local->priv->packages, i);
+		category = zif_package_get_category (package, NULL);
+		if (strcmp (zif_string_get_value (category), search) == 0)
+			g_ptr_array_add (array, g_object_ref (package));
+		zif_string_unref (category);
+
+		/* this section done */
+		zif_completion_done (completion_local);
+	}
+
+	/* this section done */
+	zif_completion_done (completion);
+out:
+	return array;
+}
+
+/**
+ * zif_store_local_earch_details:
+ **/
+static GPtrArray *
+zif_store_local_search_details (ZifStore *store, const gchar *search, GCancellable *cancellable, ZifCompletion *completion, GError **error)
+{
+	guint i;
+	GPtrArray *array = NULL;
+	ZifPackage *package;
+	const gchar *package_id;
+	ZifString *description;
+	gchar **split;
+	GError *error_local = NULL;
+	gboolean ret;
+	ZifCompletion *completion_local = NULL;
+	ZifStoreLocal *local = ZIF_STORE_LOCAL (store);
+
+	g_return_val_if_fail (ZIF_IS_STORE_LOCAL (store), NULL);
+	g_return_val_if_fail (search != NULL, NULL);
+	g_return_val_if_fail (local->priv->prefix != NULL, NULL);
+
+	/* not locked */
+	ret = zif_lock_is_locked (local->priv->lock, NULL);
+	if (!ret) {
+		egg_warning ("not locked");
+		if (error != NULL)
+			*error = g_error_new (1, 0, "not locked");
+		goto out;
+	}
+
+	/* we have a different number of steps depending if we are loaded or not */
+	if (local->priv->loaded)
+		zif_completion_set_number_steps (completion, 1);
+	else
+		zif_completion_set_number_steps (completion, 2);
+
+	/* if not already loaded, load */
+	if (!local->priv->loaded) {
+		completion_local = zif_completion_get_child (completion);
+		ret = zif_store_local_load (store, cancellable, completion_local, &error_local);
+		if (!ret) {
+			if (error != NULL)
+				*error = g_error_new (1, 0, "failed to load package store: %s", error_local->message);
+			g_error_free (error_local);
+			goto out;
+		}
+
+		/* this section done */
+		zif_completion_done (completion);
+	}
+
+	/* check we have packages */
+	if (local->priv->packages->len == 0) {
+		egg_warning ("no packages in sack, so nothing to do!");
+		if (error != NULL)
+			*error = g_error_new (1, 0, "no packages in local sack");
+		goto out;
+	}
+
+	/* setup completion with the correct number of steps */
+	completion_local = zif_completion_get_child (completion);
+	zif_completion_set_number_steps (completion_local, local->priv->packages->len);
+
+	/* iterate list */
+	array = g_ptr_array_new_with_free_func ((GDestroyNotify) g_object_unref);
+	for (i=0;i<local->priv->packages->len;i++) {
+		package = g_ptr_array_index (local->priv->packages, i);
+		package_id = zif_package_get_id (package);
+		description = zif_package_get_description (package, NULL);
+		split = pk_package_id_split (package_id);
+		if (strcasestr (split[PK_PACKAGE_ID_NAME], search) != NULL)
+			g_ptr_array_add (array, g_object_ref (package));
+		else if (strcasestr (zif_string_get_value (description), search) != NULL)
+			g_ptr_array_add (array, g_object_ref (package));
+		zif_string_unref (description);
+		g_strfreev (split);
+
+		/* this section done */
+		zif_completion_done (completion_local);
+	}
+
+	/* this section done */
+	zif_completion_done (completion);
+out:
+	return array;
+}
+
+/**
+ * zif_store_local_search_group:
+ **/
+static GPtrArray *
+zif_store_local_search_group (ZifStore *store, const gchar *search, GCancellable *cancellable, ZifCompletion *completion, GError **error)
+{
+	guint i;
+	GPtrArray *array = NULL;
+	ZifPackage *package;
+	PkGroupEnum group_tmp;
+	GError *error_local = NULL;
+	gboolean ret;
+	PkGroupEnum group;
+	ZifCompletion *completion_local = NULL;
+	ZifStoreLocal *local = ZIF_STORE_LOCAL (store);
+
+	g_return_val_if_fail (ZIF_IS_STORE_LOCAL (store), NULL);
+	g_return_val_if_fail (local->priv->prefix != NULL, NULL);
+
+	/* not locked */
+	ret = zif_lock_is_locked (local->priv->lock, NULL);
+	if (!ret) {
+		egg_warning ("not locked");
+		if (error != NULL)
+			*error = g_error_new (1, 0, "not locked");
+		goto out;
+	}
+
+	/* we have a different number of steps depending if we are loaded or not */
+	if (local->priv->loaded)
+		zif_completion_set_number_steps (completion, 1);
+	else
+		zif_completion_set_number_steps (completion, 2);
+
+	/* if not already loaded, load */
+	if (!local->priv->loaded) {
+		completion_local = zif_completion_get_child (completion);
+		ret = zif_store_local_load (store, cancellable, completion_local, &error_local);
+		if (!ret) {
+			if (error != NULL)
+				*error = g_error_new (1, 0, "failed to load package store: %s", error_local->message);
+			g_error_free (error_local);
+			goto out;
+		}
+
+		/* this section done */
+		zif_completion_done (completion);
+	}
+
+	/* check we have packages */
+	if (local->priv->packages->len == 0) {
+		egg_warning ("no packages in sack, so nothing to do!");
+		if (error != NULL)
+			*error = g_error_new (1, 0, "no packages in local sack");
+		goto out;
+	}
+
+	/* setup completion with the correct number of steps */
+	completion_local = zif_completion_get_child (completion);
+	zif_completion_set_number_steps (completion_local, local->priv->packages->len);
+
+	/* iterate list */
+	group = pk_group_enum_from_text (search);
+	array = g_ptr_array_new_with_free_func ((GDestroyNotify) g_object_unref);
+	for (i=0;i<local->priv->packages->len;i++) {
+		package = g_ptr_array_index (local->priv->packages, i);
+		group_tmp = zif_package_get_group (package, NULL);
+		if (group == group_tmp)
+			g_ptr_array_add (array, g_object_ref (package));
+
+		/* this section done */
+		zif_completion_done (completion_local);
+	}
+
+	/* this section done */
+	zif_completion_done (completion);
+out:
+	return array;
+}
+
+/**
+ * zif_store_local_search_file:
+ **/
+static GPtrArray *
+zif_store_local_search_file (ZifStore *store, const gchar *search, GCancellable *cancellable, ZifCompletion *completion, GError **error)
+{
+	guint i, j;
+	GPtrArray *array = NULL;
+	ZifPackage *package;
+	GPtrArray *files;
+	GError *error_local = NULL;
+	const gchar *filename;
+	gboolean ret;
+	ZifCompletion *completion_local = NULL;
+	ZifStoreLocal *local = ZIF_STORE_LOCAL (store);
+
+	g_return_val_if_fail (ZIF_IS_STORE_LOCAL (store), NULL);
+	g_return_val_if_fail (local->priv->prefix != NULL, NULL);
+
+	/* not locked */
+	ret = zif_lock_is_locked (local->priv->lock, NULL);
+	if (!ret) {
+		egg_warning ("not locked");
+		if (error != NULL)
+			*error = g_error_new (1, 0, "not locked");
+		goto out;
+	}
+
+	/* we have a different number of steps depending if we are loaded or not */
+	if (local->priv->loaded)
+		zif_completion_set_number_steps (completion, 1);
+	else
+		zif_completion_set_number_steps (completion, 2);
+
+	/* if not already loaded, load */
+	if (!local->priv->loaded) {
+		completion_local = zif_completion_get_child (completion);
+		ret = zif_store_local_load (store, cancellable, completion_local, &error_local);
+		if (!ret) {
+			if (error != NULL)
+				*error = g_error_new (1, 0, "failed to load package store: %s", error_local->message);
+			g_error_free (error_local);
+			goto out;
+		}
+
+		/* this section done */
+		zif_completion_done (completion);
+	}
+
+	/* check we have packages */
+	if (local->priv->packages->len == 0) {
+		egg_warning ("no packages in sack, so nothing to do!");
+		if (error != NULL)
+			*error = g_error_new (1, 0, "no packages in local sack");
+		goto out;
+	}
+
+	/* setup completion with the correct number of steps */
+	completion_local = zif_completion_get_child (completion);
+	zif_completion_set_number_steps (completion_local, local->priv->packages->len);
+
+	/* iterate list */
+	array = g_ptr_array_new_with_free_func ((GDestroyNotify) g_object_unref);
+	for (i=0;i<local->priv->packages->len;i++) {
+		package = g_ptr_array_index (local->priv->packages, i);
+		files = zif_package_get_files (package, &error_local);
+		if (files == NULL) {
+			if (error != NULL)
+				*error = g_error_new (1, 0, "failed to get file lists: %s", error_local->message);
+			g_error_free (error_local);
+			g_ptr_array_unref (array);
+			array = NULL;
+			break;
+		}
+		for (j=0; j<files->len; j++) {
+			filename = g_ptr_array_index (files, j);
+			if (g_strcmp0 (search, filename) == 0)
+				g_ptr_array_add (array, g_object_ref (package));
+		}
+		g_ptr_array_unref (files);
+
+		/* this section done */
+		zif_completion_done (completion_local);
+	}
+out:
+	return array;
+}
+
+/**
+ * zif_store_local_resolve:
+ **/
+static GPtrArray *
+zif_store_local_resolve (ZifStore *store, const gchar *search, GCancellable *cancellable, ZifCompletion *completion, GError **error)
+{
+	guint i;
+	GPtrArray *array = NULL;
+	ZifPackage *package;
+	const gchar *package_id;
+	GError *error_local = NULL;
+	gboolean ret;
+	gchar **split;
+	ZifCompletion *completion_local = NULL;
+	ZifStoreLocal *local = ZIF_STORE_LOCAL (store);
+
+	g_return_val_if_fail (ZIF_IS_STORE_LOCAL (store), NULL);
+	g_return_val_if_fail (search != NULL, NULL);
+	g_return_val_if_fail (local->priv->prefix != NULL, NULL);
+
+	/* not locked */
+	ret = zif_lock_is_locked (local->priv->lock, NULL);
+	if (!ret) {
+		egg_warning ("not locked");
+		if (error != NULL)
+			*error = g_error_new (1, 0, "not locked");
+		goto out;
+	}
+
+	/* we have a different number of steps depending if we are loaded or not */
+	if (local->priv->loaded)
+		zif_completion_set_number_steps (completion, 1);
+	else
+		zif_completion_set_number_steps (completion, 2);
+
+	/* if not already loaded, load */
+	if (!local->priv->loaded) {
+		completion_local = zif_completion_get_child (completion);
+		ret = zif_store_local_load (store, cancellable, completion_local, &error_local);
+		if (!ret) {
+			if (error != NULL)
+				*error = g_error_new (1, 0, "failed to load package store: %s", error_local->message);
+			g_error_free (error_local);
+			goto out;
+		}
+
+		/* this section done */
+		zif_completion_done (completion);
+	}
+
+	/* check we have packages */
+	if (local->priv->packages->len == 0) {
+		egg_warning ("no packages in sack, so nothing to do!");
+		if (error != NULL)
+			*error = g_error_new (1, 0, "no packages in local sack");
+		goto out;
+	}
+
+	/* setup completion with the correct number of steps */
+	completion_local = zif_completion_get_child (completion);
+	zif_completion_set_number_steps (completion_local, local->priv->packages->len);
+
+	/* iterate list */
+	array = g_ptr_array_new_with_free_func ((GDestroyNotify) g_object_unref);
+	for (i=0;i<local->priv->packages->len;i++) {
+		package = g_ptr_array_index (local->priv->packages, i);
+		package_id = zif_package_get_id (package);
+		split = pk_package_id_split (package_id);
+		if (strcmp (split[PK_PACKAGE_ID_NAME], search) == 0)
+			g_ptr_array_add (array, g_object_ref (package));
+		g_strfreev (split);
+
+		/* this section done */
+		zif_completion_done (completion_local);
+	}
+
+	/* this section done */
+	zif_completion_done (completion);
+out:
+	return array;
+}
+
+/**
+ * zif_store_local_what_provides:
+ **/
+static GPtrArray *
+zif_store_local_what_provides (ZifStore *store, const gchar *search, GCancellable *cancellable, ZifCompletion *completion, GError **error)
+{
+	guint i;
+	guint j;
+	GPtrArray *array = NULL;
+	ZifPackage *package;
+	GPtrArray *provides;
+	GError *error_local = NULL;
+	gboolean ret;
+	const ZifDepend *provide;
+	ZifCompletion *completion_local = NULL;
+	ZifStoreLocal *local = ZIF_STORE_LOCAL (store);
+
+	g_return_val_if_fail (ZIF_IS_STORE_LOCAL (store), NULL);
+	g_return_val_if_fail (search != NULL, NULL);
+	g_return_val_if_fail (local->priv->prefix != NULL, NULL);
+
+	/* not locked */
+	ret = zif_lock_is_locked (local->priv->lock, NULL);
+	if (!ret) {
+		egg_warning ("not locked");
+		if (error != NULL)
+			*error = g_error_new (1, 0, "not locked");
+		goto out;
+	}
+
+	/* we have a different number of steps depending if we are loaded or not */
+	if (local->priv->loaded)
+		zif_completion_set_number_steps (completion, 1);
+	else
+		zif_completion_set_number_steps (completion, 2);
+
+	/* if not already loaded, load */
+	if (!local->priv->loaded) {
+		completion_local = zif_completion_get_child (completion);
+		ret = zif_store_local_load (store, cancellable, completion_local, &error_local);
+		if (!ret) {
+			if (error != NULL)
+				*error = g_error_new (1, 0, "failed to load package store: %s", error_local->message);
+			g_error_free (error_local);
+			goto out;
+		}
+
+		/* this section done */
+		zif_completion_done (completion);
+	}
+
+	/* check we have packages */
+	if (local->priv->packages->len == 0) {
+		egg_warning ("no packages in sack, so nothing to do!");
+		if (error != NULL)
+			*error = g_error_new (1, 0, "no packages in local sack");
+		goto out;
+	}
+
+	/* setup completion with the correct number of steps */
+	completion_local = zif_completion_get_child (completion);
+	zif_completion_set_number_steps (completion_local, local->priv->packages->len);
+
+	/* iterate list */
+	array = g_ptr_array_new_with_free_func ((GDestroyNotify) g_object_unref);
+	for (i=0;i<local->priv->packages->len;i++) {
+		package = g_ptr_array_index (local->priv->packages, i);
+		provides = zif_package_get_provides (package, NULL);
+		for (j=0; j<provides->len; j++) {
+			provide = g_ptr_array_index (provides, j);
+			if (strcmp (provide->name, search) == 0) {
+				g_ptr_array_add (array, g_object_ref (package));
+				break;
+			}
+		}
+
+		/* this section done */
+		zif_completion_done (completion_local);
+	}
+
+	/* this section done */
+	zif_completion_done (completion);
+out:
+	return array;
+}
+
+/**
+ * zif_store_local_get_packages:
+ **/
+static GPtrArray *
+zif_store_local_get_packages (ZifStore *store, GCancellable *cancellable, ZifCompletion *completion, GError **error)
+{
+	guint i;
+	GPtrArray *array = NULL;
+	ZifPackage *package;
+	GError *error_local = NULL;
+	gboolean ret;
+	ZifCompletion *completion_local = NULL;
+	ZifStoreLocal *local = ZIF_STORE_LOCAL (store);
+
+	g_return_val_if_fail (ZIF_IS_STORE_LOCAL (store), NULL);
+	g_return_val_if_fail (local->priv->prefix != NULL, NULL);
+
+	/* not locked */
+	ret = zif_lock_is_locked (local->priv->lock, NULL);
+	if (!ret) {
+		egg_warning ("not locked");
+		if (error != NULL)
+			*error = g_error_new (1, 0, "not locked");
+		goto out;
+	}
+
+	/* we have a different number of steps depending if we are loaded or not */
+	if (local->priv->loaded)
+		zif_completion_set_number_steps (completion, 1);
+	else
+		zif_completion_set_number_steps (completion, 2);
+
+	/* if not already loaded, load */
+	if (!local->priv->loaded) {
+		completion_local = zif_completion_get_child (completion);
+		ret = zif_store_local_load (store, cancellable, completion_local, &error_local);
+		if (!ret) {
+			if (error != NULL)
+				*error = g_error_new (1, 0, "failed to load package store: %s", error_local->message);
+			g_error_free (error_local);
+			goto out;
+		}
+
+		/* this section done */
+		zif_completion_done (completion);
+	}
+
+	/* check we have packages */
+	if (local->priv->packages->len == 0) {
+		egg_warning ("no packages in sack, so nothing to do!");
+		if (error != NULL)
+			*error = g_error_new (1, 0, "no packages in local sack");
+		goto out;
+	}
+
+	/* setup completion with the correct number of steps */
+	completion_local = zif_completion_get_child (completion);
+	zif_completion_set_number_steps (completion_local, local->priv->packages->len);
+
+	/* iterate list */
+	array = g_ptr_array_new_with_free_func ((GDestroyNotify) g_object_unref);
+	for (i=0;i<local->priv->packages->len;i++) {
+		package = g_ptr_array_index (local->priv->packages, i);
+		g_ptr_array_add (array, g_object_ref (package));
+
+		/* this section done */
+		zif_completion_done (completion_local);
+	}
+
+	/* this section done */
+	zif_completion_done (completion);
+out:
+	return array;
+}
+
+/**
+ * zif_store_local_find_package:
+ **/
+static ZifPackage *
+zif_store_local_find_package (ZifStore *store, const gchar *package_id, GCancellable *cancellable, ZifCompletion *completion, GError **error)
+{
+	guint i;
+	GPtrArray *array = NULL;
+	ZifPackage *package = NULL;
+	ZifPackage *package_tmp = NULL;
+	GError *error_local = NULL;
+	gboolean ret;
+	const gchar *package_id_tmp;
+	ZifCompletion *completion_local = NULL;
+	ZifStoreLocal *local = ZIF_STORE_LOCAL (store);
+
+	g_return_val_if_fail (ZIF_IS_STORE_LOCAL (store), NULL);
+	g_return_val_if_fail (local->priv->prefix != NULL, NULL);
+
+	/* not locked */
+	ret = zif_lock_is_locked (local->priv->lock, NULL);
+	if (!ret) {
+		egg_warning ("not locked");
+		if (error != NULL)
+			*error = g_error_new (1, 0, "not locked");
+		goto out;
+	}
+
+	/* we have a different number of steps depending if we are loaded or not */
+	if (local->priv->loaded)
+		zif_completion_set_number_steps (completion, 1);
+	else
+		zif_completion_set_number_steps (completion, 2);
+
+	/* if not already loaded, load */
+	if (!local->priv->loaded) {
+		completion_local = zif_completion_get_child (completion);
+		ret = zif_store_local_load (store, cancellable, completion_local, &error_local);
+		if (!ret) {
+			if (error != NULL)
+				*error = g_error_new (1, 0, "failed to load package store: %s", error_local->message);
+			g_error_free (error_local);
+			goto out;
+		}
+
+		/* this section done */
+		zif_completion_done (completion);
+	}
+
+	/* check we have packages */
+	if (local->priv->packages->len == 0) {
+		egg_warning ("no packages in sack, so nothing to do!");
+		if (error != NULL)
+			*error = g_error_new (1, 0, "no packages in local sack");
+		goto out;
+	}
+
+	/* setup completion with the correct number of steps */
+	completion_local = zif_completion_get_child (completion);
+	zif_completion_set_number_steps (completion_local, local->priv->packages->len);
+
+	/* iterate list */
+	array = g_ptr_array_new_with_free_func ((GDestroyNotify) g_object_unref);
+	for (i=0;i<local->priv->packages->len;i++) {
+		package_tmp = g_ptr_array_index (local->priv->packages, i);
+		package_id_tmp = zif_package_get_id (package);
+		if (g_strcmp0 (package_id_tmp, package_id) == 0)
+			g_ptr_array_add (array, g_object_ref (package_tmp));
+
+		/* this section done */
+		zif_completion_done (completion_local);
+	}
+
+	/* nothing */
+	if (array->len == 0) {
+		if (error != NULL)
+			*error = g_error_new (1, 0, "failed to find package");
+		goto out;
+	}
+
+	/* more than one match */
+	if (array->len > 1) {
+		if (error != NULL)
+			*error = g_error_new (1, 0, "more than one match");
+		goto out;
+	}
+
+	/* return ref to package */
+	package = g_object_ref (g_ptr_array_index (array, 0));
+
+	/* this section done */
+	zif_completion_done (completion);
+out:
+	g_ptr_array_unref (array);
+	return package;
+}
+
+/**
+ * zif_store_local_get_id:
+ **/
+static const gchar *
+zif_store_local_get_id (ZifStore *store)
+{
+	g_return_val_if_fail (ZIF_IS_STORE_LOCAL (store), NULL);
+	return "installed";
+}
+
+/**
+ * zif_store_local_print:
+ **/
+static void
+zif_store_local_print (ZifStore *store)
+{
+	guint i;
+	ZifPackage *package;
+	ZifStoreLocal *local = ZIF_STORE_LOCAL (store);
+
+	g_return_if_fail (ZIF_IS_STORE_LOCAL (store));
+	g_return_if_fail (local->priv->prefix != NULL);
+	g_return_if_fail (local->priv->packages->len != 0);
+
+	for (i=0;i<local->priv->packages->len;i++) {
+		package = g_ptr_array_index (local->priv->packages, i);
+		zif_package_print (package);
+	}
+}
+
+/**
+ * zif_store_local_file_monitor_cb:
+ **/
+static void
+zif_store_local_file_monitor_cb (ZifMonitor *monitor, ZifStoreLocal *store)
+{
+	store->priv->loaded = FALSE;
+
+	g_ptr_array_set_size (store->priv->packages, 0);
+
+	egg_debug ("rpmdb changed");
+}
+
+/**
+ * zif_store_local_finalize:
+ **/
+static void
+zif_store_local_finalize (GObject *object)
+{
+	ZifStoreLocal *store;
+
+	g_return_if_fail (object != NULL);
+	g_return_if_fail (ZIF_IS_STORE_LOCAL (object));
+	store = ZIF_STORE_LOCAL (object);
+
+	g_ptr_array_unref (store->priv->packages);
+	g_object_unref (store->priv->groups);
+	g_object_unref (store->priv->monitor);
+	g_object_unref (store->priv->lock);
+	g_free (store->priv->prefix);
+
+	G_OBJECT_CLASS (zif_store_local_parent_class)->finalize (object);
+}
+
+/**
+ * zif_store_local_class_init:
+ **/
+static void
+zif_store_local_class_init (ZifStoreLocalClass *klass)
+{
+	GObjectClass *object_class = G_OBJECT_CLASS (klass);
+	ZifStoreClass *store_class = ZIF_STORE_CLASS (klass);
+	object_class->finalize = zif_store_local_finalize;
+
+	/* map */
+	store_class->load = zif_store_local_load;
+	store_class->search_name = zif_store_local_search_name;
+	store_class->search_category = zif_store_local_search_category;
+	store_class->search_details = zif_store_local_search_details;
+	store_class->search_group = zif_store_local_search_group;
+	store_class->search_file = zif_store_local_search_file;
+	store_class->resolve = zif_store_local_resolve;
+	store_class->what_provides = zif_store_local_what_provides;
+	store_class->get_packages = zif_store_local_get_packages;
+	store_class->find_package = zif_store_local_find_package;
+	store_class->get_id = zif_store_local_get_id;
+	store_class->print = zif_store_local_print;
+
+	g_type_class_add_private (klass, sizeof (ZifStoreLocalPrivate));
+}
+
+/**
+ * zif_store_local_init:
+ **/
+static void
+zif_store_local_init (ZifStoreLocal *store)
+{
+	store->priv = ZIF_STORE_LOCAL_GET_PRIVATE (store);
+	store->priv->packages = g_ptr_array_new_with_free_func ((GDestroyNotify) g_object_unref);
+	store->priv->groups = zif_groups_new ();
+	store->priv->monitor = zif_monitor_new ();
+	store->priv->lock = zif_lock_new ();
+	store->priv->prefix = NULL;
+	store->priv->loaded = FALSE;
+	g_signal_connect (store->priv->monitor, "changed", G_CALLBACK (zif_store_local_file_monitor_cb), store);
+}
+
+/**
+ * zif_store_local_new:
+ *
+ * Return value: A new #ZifStoreLocal class instance.
+ **/
+ZifStoreLocal *
+zif_store_local_new (void)
+{
+	if (zif_store_local_object != NULL) {
+		g_object_ref (zif_store_local_object);
+	} else {
+		zif_store_local_object = g_object_new (ZIF_TYPE_STORE_LOCAL, NULL);
+		g_object_add_weak_pointer (zif_store_local_object, &zif_store_local_object);
+	}
+	return ZIF_STORE_LOCAL (zif_store_local_object);
+}
+
+/***************************************************************************
+ ***                          MAKE CHECK TESTS                           ***
+ ***************************************************************************/
+#ifdef EGG_TEST
+#include "egg-test.h"
+
+#include "zif-config.h"
+
+void
+zif_store_local_test (EggTest *test)
+{
+	ZifStoreLocal *store;
+	gboolean ret;
+	GPtrArray *array;
+	ZifPackage *package;
+	ZifGroups *groups;
+	ZifLock *lock;
+	ZifConfig *config;
+	ZifCompletion *completion;
+	GError *error = NULL;
+	guint elapsed;
+	const gchar *text;
+	ZifString *string;
+	const gchar *package_id;
+	gchar **split;
+
+	if (!egg_test_start (test, "ZifStoreLocal"))
+		return;
+
+	/* set this up as dummy */
+	config = zif_config_new ();
+	zif_config_set_filename (config, "../test/etc/yum.conf", NULL);
+
+	/* use completion object */
+	completion = zif_completion_new ();
+
+	/************************************************************/
+	egg_test_title (test, "get groups");
+	groups = zif_groups_new ();
+	ret = zif_groups_set_mapping_file (groups, "../test/share/yum-comps-groups.conf", NULL);
+	egg_test_assert (test, ret);
+
+	/************************************************************/
+	egg_test_title (test, "get store");
+	store = zif_store_local_new ();
+	egg_test_assert (test, store != NULL);
+
+	/************************************************************/
+	egg_test_title (test, "get lock");
+	lock = zif_lock_new ();
+	egg_test_assert (test, lock != NULL);
+
+	/************************************************************/
+	egg_test_title (test, "lock");
+	ret = zif_lock_set_locked (lock, NULL, NULL);
+	egg_test_assert (test, ret);
+
+	/************************************************************/
+	egg_test_title (test, "set prefix");
+	ret = zif_store_local_set_prefix (store, "/", &error);
+	if (ret)
+		egg_test_success (test, NULL);
+	else
+		egg_test_failed (test, "failed to set prefix '%s'", error->message);
+
+	/************************************************************/
+	egg_test_title (test, "load");
+	ret = zif_store_local_load (ZIF_STORE (store), NULL, completion, &error);
+	elapsed = egg_test_elapsed (test);
+	if (ret)
+		egg_test_success (test, NULL);
+	else
+		egg_test_failed (test, "failed to load '%s'", error->message);
+
+	/************************************************************/
+	egg_test_title (test, "check time < 1000ms");
+	if (elapsed < 1000)
+		egg_test_success (test, "time to load = %ims", elapsed);
+	else
+		egg_test_failed (test, "time to load = %ims", elapsed);
+
+	/************************************************************/
+	egg_test_title (test, "load (again)");
+	zif_completion_reset (completion);
+	ret = zif_store_local_load (ZIF_STORE (store), NULL, completion, &error);
+	elapsed = egg_test_elapsed (test);
+	if (ret)
+		egg_test_success (test, NULL);
+	else
+		egg_test_failed (test, "failed to load '%s'", error->message);
+
+	/************************************************************/
+	egg_test_title (test, "check time < 10ms");
+	if (elapsed < 10)
+		egg_test_success (test, "time to load = %ims", elapsed);
+	else
+		egg_test_failed (test, "time to load = %ims", elapsed);
+
+	/************************************************************/
+	egg_test_title (test, "resolve");
+	zif_completion_reset (completion);
+	array = zif_store_local_resolve (ZIF_STORE (store), "kernel", NULL, completion, NULL);
+	elapsed = egg_test_elapsed (test);
+	if (array->len >= 1)
+		egg_test_success (test, NULL);
+	else
+		egg_test_failed (test, "incorrect length %i", array->len);
+	g_ptr_array_unref (array);
+
+	/************************************************************/
+	egg_test_title (test, "check time < 10ms");
+	if (elapsed < 1000) /* TODO: reduce back down to 10ms */
+		egg_test_success (test, "time to load = %ims", elapsed);
+	else
+		egg_test_failed (test, "time to load = %ims", elapsed);
+
+	/************************************************************/
+	egg_test_title (test, "search name");
+	zif_completion_reset (completion);
+	array = zif_store_local_search_name (ZIF_STORE (store), "gnome-p", NULL, completion, NULL);
+	if (array->len > 10)
+		egg_test_success (test, NULL);
+	else
+		egg_test_failed (test, "incorrect length %i", array->len);
+	g_ptr_array_unref (array);
+
+	/************************************************************/
+	egg_test_title (test, "search details");
+	zif_completion_reset (completion);
+	array = zif_store_local_search_details (ZIF_STORE (store), "manage packages", NULL, completion, NULL);
+	if (array->len == 1)
+		egg_test_success (test, NULL);
+	else
+		egg_test_failed (test, "incorrect length %i", array->len);
+	g_ptr_array_unref (array);
+
+	/************************************************************/
+	egg_test_title (test, "what-provides");
+	zif_completion_reset (completion);
+	array = zif_store_local_what_provides (ZIF_STORE (store), "config(PackageKit)", NULL, completion, NULL);
+	if (array->len == 1)
+		egg_test_success (test, NULL);
+	else
+		egg_test_failed (test, "incorrect length %i", array->len);
+
+	/* get this package */
+	package = g_ptr_array_index (array, 0);
+
+	/************************************************************/
+	egg_test_title (test, "get id");
+	package_id = zif_package_get_id (package);
+	split = pk_package_id_split (package_id);
+	if (egg_strequal (split[PK_PACKAGE_ID_NAME], "PackageKit"))
+		egg_test_success (test, NULL);
+	else
+		egg_test_failed (test, "incorrect name: %s", split[PK_PACKAGE_ID_NAME]);
+	g_strfreev (split);
+
+	/************************************************************/
+	egg_test_title (test, "get package id");
+	text = zif_package_get_package_id (package);
+	if (g_str_has_suffix (text, ";installed"))
+		egg_test_success (test, NULL);
+	else
+		egg_test_failed (test, "incorrect package_id: %s", text);
+
+	/************************************************************/
+	egg_test_title (test, "get summary");
+	string = zif_package_get_summary (package, NULL);
+	if (egg_strequal (zif_string_get_value (string), "Package management service"))
+		egg_test_success (test, NULL);
+	else
+		egg_test_failed (test, "incorrect summary: %s", zif_string_get_value (string));
+	zif_string_unref (string);
+
+	/************************************************************/
+	egg_test_title (test, "get license");
+	string = zif_package_get_license (package, NULL);
+	if (egg_strequal (zif_string_get_value (string), "GPLv2+"))
+		egg_test_success (test, NULL);
+	else
+		egg_test_failed (test, "incorrect license: %s", zif_string_get_value (string));
+	zif_string_unref (string);
+
+	/************************************************************/
+	egg_test_title (test, "get category");
+	string = zif_package_get_category (package, NULL);
+	if (egg_strequal (zif_string_get_value (string), "System Environment/Libraries"))
+		egg_test_success (test, NULL);
+	else
+		egg_test_failed (test, "incorrect category: %s", zif_string_get_value (string));
+	zif_string_unref (string);
+
+	/************************************************************/
+	egg_test_title (test, "is devel");
+	ret = zif_package_is_devel (package);
+	egg_test_assert (test, !ret);
+
+	/************************************************************/
+	egg_test_title (test, "is gui");
+	ret = zif_package_is_gui (package);
+	egg_test_assert (test, ret);
+
+	/************************************************************/
+	egg_test_title (test, "is installed");
+	ret = zif_package_is_installed (package);
+	egg_test_assert (test, ret);
+
+	/************************************************************/
+	egg_test_title (test, "is free");
+	ret = zif_package_is_free (package);
+	egg_test_assert (test, ret);
+
+	g_ptr_array_unref (array);
+
+	g_object_unref (store);
+	g_object_unref (groups);
+	g_object_unref (config);
+	g_object_unref (lock);
+	g_object_unref (completion);
+
+	egg_test_end (test);
+}
+#endif
+
diff --git a/backends/yum/libzif/zif-store-local.h b/backends/yum/libzif/zif-store-local.h
new file mode 100644
index 0000000..74e4004
--- /dev/null
+++ b/backends/yum/libzif/zif-store-local.h
@@ -0,0 +1,68 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2008 Richard Hughes <richard at hughsie.com>
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#if !defined (__ZIF_H_INSIDE__) && !defined (ZIF_COMPILATION)
+#error "Only <zif.h> can be included directly."
+#endif
+
+#ifndef __ZIF_STORE_LOCAL_H
+#define __ZIF_STORE_LOCAL_H
+
+#include <glib-object.h>
+#include <packagekit-glib2/packagekit.h>
+
+#include "zif-store.h"
+#include "zif-package.h"
+
+G_BEGIN_DECLS
+
+#define ZIF_TYPE_STORE_LOCAL		(zif_store_local_get_type ())
+#define ZIF_STORE_LOCAL(o)		(G_TYPE_CHECK_INSTANCE_CAST ((o), ZIF_TYPE_STORE_LOCAL, ZifStoreLocal))
+#define ZIF_STORE_LOCAL_CLASS(k)	(G_TYPE_CHECK_CLASS_CAST((k), ZIF_TYPE_STORE_LOCAL, ZifStoreLocalClass))
+#define ZIF_IS_STORE_LOCAL(o)		(G_TYPE_CHECK_INSTANCE_TYPE ((o), ZIF_TYPE_STORE_LOCAL))
+#define ZIF_IS_STORE_LOCAL_CLASS(k)	(G_TYPE_CHECK_CLASS_TYPE ((k), ZIF_TYPE_STORE_LOCAL))
+#define ZIF_STORE_LOCAL_GET_CLASS(o)	(G_TYPE_INSTANCE_GET_CLASS ((o), ZIF_TYPE_STORE_LOCAL, ZifStoreLocalClass))
+
+typedef struct _ZifStoreLocal		ZifStoreLocal;
+typedef struct _ZifStoreLocalPrivate	ZifStoreLocalPrivate;
+typedef struct _ZifStoreLocalClass	ZifStoreLocalClass;
+
+struct _ZifStoreLocal
+{
+	ZifStore		 parent;
+	ZifStoreLocalPrivate	*priv;
+};
+
+struct _ZifStoreLocalClass
+{
+	ZifStoreClass		 parent_class;
+};
+
+GType		 zif_store_local_get_type	(void);
+ZifStoreLocal	*zif_store_local_new		(void);
+gboolean	 zif_store_local_set_prefix	(ZifStoreLocal		*store,
+						 const gchar		*prefix,
+						 GError			**error);
+
+G_END_DECLS
+
+#endif /* __ZIF_STORE_LOCAL_H */
+
diff --git a/backends/yum/libzif/zif-store-remote.c b/backends/yum/libzif/zif-store-remote.c
new file mode 100644
index 0000000..e10f7d0
--- /dev/null
+++ b/backends/yum/libzif/zif-store-remote.c
@@ -0,0 +1,2750 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2008 Richard Hughes <richard at hughsie.com>
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+/**
+ * SECTION:zif-store-remote
+ * @short_description: A remote store is a store that can operate on remote packages
+ *
+ * A #ZifStoreRemote is a subclassed #ZifStore and operates on remote objects.
+ * A repository is another name for a #ZifStoreRemote.
+ */
+
+#ifdef HAVE_CONFIG_H
+#  include <config.h>
+#endif
+
+#include <glib.h>
+#include <stdlib.h>
+#include <gio/gio.h>
+
+#include "zif-config.h"
+#include "zif-download.h"
+#include "zif-lock.h"
+#include "zif-monitor.h"
+#include "zif-package.h"
+#include "zif-package-remote.h"
+#include "zif-repo-md-comps.h"
+#include "zif-repo-md-filelists.h"
+#include "zif-repo-md-metalink.h"
+#include "zif-repo-md-mirrorlist.h"
+#include "zif-repo-md-primary.h"
+#include "zif-store.h"
+#include "zif-store-local.h"
+#include "zif-store-remote.h"
+#include "zif-utils.h"
+
+#include "egg-debug.h"
+#include "egg-string.h"
+
+#define ZIF_STORE_REMOTE_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), ZIF_TYPE_STORE_REMOTE, ZifStoreRemotePrivate))
+
+typedef enum {
+	ZIF_STORE_REMOTE_PARSER_SECTION_CHECKSUM,
+	ZIF_STORE_REMOTE_PARSER_SECTION_CHECKSUM_UNCOMPRESSED,
+	ZIF_STORE_REMOTE_PARSER_SECTION_TIMESTAMP,
+	ZIF_STORE_REMOTE_PARSER_SECTION_UNKNOWN
+} ZifStoreRemoteParserSection;
+
+struct _ZifStoreRemotePrivate
+{
+	gchar			*id;			/* fedora */
+	gchar			*name;			/* Fedora $arch */
+	gchar			*name_expanded;		/* Fedora 1386 */
+	gchar			*directory;		/* /var/cache/yum/fedora */
+	gchar			*repomd_filename;	/* /var/cache/yum/fedora/repomd.xml */
+	GPtrArray		*baseurls;		/* http://download.fedora.org/ */
+	gchar			*mirrorlist;
+	gchar			*metalink;
+	gchar			*cache_dir;		/* /var/cache/yum */
+	gchar			*repo_filename;		/* /etc/yum.repos.d/fedora.repo */
+	gboolean		 enabled;
+	gboolean		 loaded;
+	gboolean		 loaded_metadata;
+	ZifRepoMd		*md_primary;
+	ZifRepoMd		*md_filelists;
+	ZifRepoMd		*md_metalink;
+	ZifRepoMd		*md_mirrorlist;
+	ZifRepoMd		*md_comps;
+	ZifConfig		*config;
+	ZifMonitor		*monitor;
+	ZifLock			*lock;
+	GPtrArray		*packages;
+	/* temp data for the xml parser */
+	ZifRepoMdType		 parser_type;
+	ZifRepoMdType		 parser_section;
+};
+
+G_DEFINE_TYPE (ZifStoreRemote, zif_store_remote, ZIF_TYPE_STORE)
+
+static gboolean zif_store_remote_load_metadata (ZifStoreRemote *store, GCancellable *cancellable, ZifCompletion *completion, GError **error);
+
+/**
+ * zif_store_remote_checksum_type_from_text:
+ **/
+static GChecksumType
+zif_store_remote_checksum_type_from_text (const gchar *type)
+{
+	if (g_strcmp0 (type, "sha") == 0)
+		return G_CHECKSUM_SHA1;
+	if (g_strcmp0 (type, "sha1") == 0)
+		return G_CHECKSUM_SHA1;
+	if (g_strcmp0 (type, "sha256") == 0)
+		return G_CHECKSUM_SHA256;
+	return G_CHECKSUM_MD5;
+}
+
+/**
+ * zif_store_remote_get_md_from_type:
+ **/
+static ZifRepoMd *
+zif_store_remote_get_md_from_type (ZifStoreRemote *store, ZifRepoMdType type)
+{
+	g_return_val_if_fail (ZIF_IS_STORE_REMOTE (store), NULL);
+	g_return_val_if_fail (type != ZIF_REPO_MD_TYPE_UNKNOWN, NULL);
+
+	if (type == ZIF_REPO_MD_TYPE_FILELISTS_DB)
+		return store->priv->md_filelists;
+	if (type == ZIF_REPO_MD_TYPE_PRIMARY_DB)
+		return store->priv->md_primary;
+	if (type == ZIF_REPO_MD_TYPE_OTHER_DB)
+		return NULL;
+	if (type == ZIF_REPO_MD_TYPE_COMPS_XML)
+		return store->priv->md_comps;
+	if (type == ZIF_REPO_MD_TYPE_METALINK)
+		return store->priv->md_metalink;
+	if (type == ZIF_REPO_MD_TYPE_MIRRORLIST)
+		return store->priv->md_mirrorlist;
+	return NULL;
+}
+
+/**
+ * zif_store_remote_parser_start_element:
+ **/
+static void
+zif_store_remote_parser_start_element (GMarkupParseContext *context, const gchar *element_name,
+				       const gchar **attribute_names, const gchar **attribute_values,
+				       gpointer user_data, GError **error)
+{
+	guint i, j;
+	ZifRepoMd *md;
+	ZifStoreRemote *store = user_data;
+	GString *string;
+
+	/* data */
+	if (g_strcmp0 (element_name, "data") == 0) {
+
+		/* reset */
+		store->priv->parser_type = ZIF_REPO_MD_TYPE_UNKNOWN;
+
+		/* find type */
+		for (i=0; attribute_names[i] != NULL; i++) {
+			if (g_strcmp0 (attribute_names[i], "type") == 0) {
+				if (g_strcmp0 (attribute_values[i], "primary") == 0)
+					store->priv->parser_type = ZIF_REPO_MD_TYPE_PRIMARY;
+				else if (g_strcmp0 (attribute_values[i], "primary_db") == 0)
+					store->priv->parser_type = ZIF_REPO_MD_TYPE_PRIMARY_DB;
+				else if (g_strcmp0 (attribute_values[i], "filelists") == 0)
+					store->priv->parser_type = ZIF_REPO_MD_TYPE_FILELISTS;
+				else if (g_strcmp0 (attribute_values[i], "filelists_db") == 0)
+					store->priv->parser_type = ZIF_REPO_MD_TYPE_FILELISTS_DB;
+				else if (g_strcmp0 (attribute_values[i], "other") == 0)
+					store->priv->parser_type = ZIF_REPO_MD_TYPE_OTHER;
+				else if (g_strcmp0 (attribute_values[i], "other_db") == 0)
+					store->priv->parser_type = ZIF_REPO_MD_TYPE_OTHER_DB;
+				else if (g_strcmp0 (attribute_values[i], "group") == 0)
+					store->priv->parser_type = ZIF_REPO_MD_TYPE_COMPS;
+				else if (g_strcmp0 (attribute_values[i], "group_gz") == 0)
+					store->priv->parser_type = ZIF_REPO_MD_TYPE_COMPS_XML;
+				else if (g_strcmp0 (attribute_values[i], "prestodelta") == 0)
+					store->priv->parser_type = ZIF_REPO_MD_TYPE_PRESTODELTA;
+				else if (g_strcmp0 (attribute_values[i], "updateinfo") == 0)
+					store->priv->parser_type = ZIF_REPO_MD_TYPE_UPDATEINFO;
+				else {
+					if (error != NULL) {
+						/* we didn't recognise the file type */
+						string = g_string_new ("");
+						g_string_append_printf (string, "unhandled data type '%s', expecting ", attribute_values[i]);
+
+						/* list all the types we support */
+						for (j=0; j<ZIF_REPO_MD_TYPE_UNKNOWN; j++)
+							g_string_append_printf (string, "%s, ", zif_repo_md_type_to_text (j));
+
+						/* remove triling comma and space */
+						g_string_set_size (string, string->len - 2);
+
+						/* return error */
+						*error = g_error_new (1, 0, "%s", string->str);
+						g_string_free (string, TRUE);
+					}
+				}
+				break;
+			}
+		}
+		store->priv->parser_section = ZIF_STORE_REMOTE_PARSER_SECTION_UNKNOWN;
+		goto out;
+	}
+
+	/* not a section we recognise */
+	if (store->priv->parser_type == ZIF_REPO_MD_TYPE_UNKNOWN)
+		goto out;
+
+	/* get MetaData object */
+	md = zif_store_remote_get_md_from_type (store, store->priv->parser_type);
+	if (md == NULL)
+		goto out;
+
+	/* location */
+	if (g_strcmp0 (element_name, "location") == 0) {
+		for (i=0; attribute_names[i] != NULL; i++) {
+			if (g_strcmp0 (attribute_names[i], "href") == 0) {
+				zif_repo_md_set_location (md, attribute_values[i]);
+				break;
+			}
+		}
+		store->priv->parser_section = ZIF_STORE_REMOTE_PARSER_SECTION_UNKNOWN;
+		goto out;
+	}
+
+	/* checksum */
+	if (g_strcmp0 (element_name, "checksum") == 0) {
+		for (i=0; attribute_names[i] != NULL; i++) {
+			if (g_strcmp0 (attribute_names[i], "type") == 0) {
+				zif_repo_md_set_checksum_type (md, zif_store_remote_checksum_type_from_text (attribute_values[i]));
+				break;
+			}
+		}
+		store->priv->parser_section = ZIF_STORE_REMOTE_PARSER_SECTION_CHECKSUM;
+		goto out;
+	}
+
+	/* checksum */
+	if (g_strcmp0 (element_name, "open-checksum") == 0) {
+		store->priv->parser_section = ZIF_STORE_REMOTE_PARSER_SECTION_CHECKSUM_UNCOMPRESSED;
+		goto out;
+	}
+
+	/* timestamp */
+	if (g_strcmp0 (element_name, "timestamp") == 0) {
+		store->priv->parser_section = ZIF_STORE_REMOTE_PARSER_SECTION_TIMESTAMP;
+		goto out;
+	}
+out:
+	return;
+}
+
+/**
+ * zif_store_remote_parser_end_element:
+ **/
+static void
+zif_store_remote_parser_end_element (GMarkupParseContext *context, const gchar *element_name,
+				     gpointer user_data, GError **error)
+{
+	ZifStoreRemote *store = user_data;
+
+	/* reset */
+	store->priv->parser_section = ZIF_STORE_REMOTE_PARSER_SECTION_UNKNOWN;
+	if (g_strcmp0 (element_name, "data") == 0)
+		store->priv->parser_type = ZIF_REPO_MD_TYPE_UNKNOWN;
+}
+
+/**
+ * zif_store_remote_parser_text:
+ **/
+static void
+zif_store_remote_parser_text (GMarkupParseContext *context, const gchar *text, gsize text_len,
+			      gpointer user_data, GError **error)
+
+{
+	ZifRepoMd *md;
+	ZifStoreRemote *store = user_data;
+
+	if (store->priv->parser_type == ZIF_REPO_MD_TYPE_UNKNOWN)
+		return;
+
+	/* get MetaData object */
+	md = zif_store_remote_get_md_from_type (store, store->priv->parser_type);
+	if (md == NULL)
+		return;
+
+	if (store->priv->parser_section == ZIF_STORE_REMOTE_PARSER_SECTION_CHECKSUM)
+		zif_repo_md_set_checksum (md, text);
+	else if (store->priv->parser_section == ZIF_STORE_REMOTE_PARSER_SECTION_CHECKSUM_UNCOMPRESSED)
+		zif_repo_md_set_checksum_uncompressed (md, text);
+	else if (store->priv->parser_section == ZIF_STORE_REMOTE_PARSER_SECTION_TIMESTAMP)
+		zif_repo_md_set_timestamp (md, atol (text));
+}
+
+/**
+ * zif_store_remote_download_try:
+ **/
+static gboolean
+zif_store_remote_download_try (ZifStoreRemote *store, const gchar *uri, const gchar *filename,
+			       GCancellable *cancellable, ZifCompletion *completion, GError **error)
+{
+	gboolean ret = FALSE;
+	GError *error_local = NULL;
+	ZifDownload *download = NULL;
+
+	/* download object */
+	download = zif_download_new ();
+	egg_debug ("trying to download %s", uri);
+	ret = zif_download_file (download, uri, filename, cancellable, completion, &error_local);
+	if (!ret) {
+		if (error != NULL)
+			*error = g_error_new (1, 0, "failed to download %s from %s: %s", filename, uri, error_local->message);
+		g_error_free (error_local);
+		goto out;
+	}
+out:
+	g_object_unref (download);
+	return ret;
+}
+
+/**
+ * zif_store_remote_download:
+ * @store: the #ZifStoreRemote object
+ * @filename: the completion filename to download, e.g. "Packages/hal-0.0.1.rpm"
+ * @directory: the directory to put the downloaded file, e.g. "/var/cache/zif"
+ * @cancellable: a #GCancellable which is used to cancel tasks, or %NULL
+ * @completion: a #ZifCompletion to use for progress reporting
+ * @error: a #GError which is used on failure, or %NULL
+ *
+ * Downloads a remote package to a local directory.
+ * NOTE: if @filename is "Packages/hal-0.0.1.rpm" and @directory is "/var/cache/zif"
+ * then the downloaded file will "/var/cache/zif/hal-0.0.1.rpm"
+ *
+ * Return value: %TRUE for success, %FALSE for failure
+ **/
+gboolean
+zif_store_remote_download (ZifStoreRemote *store, const gchar *filename, const gchar *directory,
+			   GCancellable *cancellable, ZifCompletion *completion, GError **error)
+{
+	guint i;
+	guint len;
+	gboolean ret = FALSE;
+	gchar *uri = NULL;
+	GError *error_local = NULL;
+	gchar *filename_local = NULL;
+	gchar *basename = NULL;
+	gchar *dirname = NULL;
+	const gchar *baseurl;
+	ZifCompletion *completion_local;
+
+	g_return_val_if_fail (ZIF_IS_STORE_REMOTE (store), FALSE);
+	g_return_val_if_fail (store->priv->id != NULL, FALSE);
+	g_return_val_if_fail (filename != NULL, FALSE);
+	g_return_val_if_fail (directory != NULL, FALSE);
+
+	/* if not online, then this is fatal */
+	ret = zif_config_get_boolean (store->priv->config, "network", NULL);
+	if (!ret) {
+		if (error != NULL)
+			*error = g_error_new (1, 0, "failed to download %s as offline", filename);
+		goto out;
+	}
+
+	/* setup completion */
+	if (store->priv->loaded_metadata)
+		zif_completion_set_number_steps (completion, 1);
+	else
+		zif_completion_set_number_steps (completion, 2);
+
+	/* if not already loaded, load */
+	if (!store->priv->loaded_metadata) {
+		completion_local = zif_completion_get_child (completion);
+		ret = zif_store_remote_load_metadata (store, cancellable, completion_local, &error_local);
+		if (!ret) {
+			if (error != NULL)
+				*error = g_error_new (1, 0, "failed to load metadata: %s", error_local->message);
+			g_error_free (error_local);
+			goto out;
+		}
+
+		/* this section done */
+		zif_completion_done (completion);
+	}
+
+	/* we need at least one baseurl */
+	if (store->priv->baseurls->len == 0) {
+		if (error != NULL)
+			*error = g_error_new (1, 0, "no baseurls for %s", store->priv->id);
+		goto out;
+	}
+
+	/* get the location to download to */
+	basename = g_path_get_basename (filename);
+	filename_local = g_build_filename (directory, basename, NULL);
+
+	/* ensure path is valid */
+	dirname = g_path_get_dirname (filename);
+	if (!g_file_test (dirname, G_FILE_TEST_EXISTS)) {
+		egg_debug ("creating directory %s", dirname);
+		g_mkdir_with_parents (dirname, 0777);
+	}
+
+	/* try to use all uris */
+	len = store->priv->baseurls->len;
+	for (i=0; i<len; i++) {
+
+		/* build url */
+		baseurl = g_ptr_array_index (store->priv->baseurls, i);
+		uri = g_build_filename (baseurl, "repodata", basename, NULL);
+
+		/* try download */
+		completion_local = zif_completion_get_child (completion);
+		ret = zif_store_remote_download_try (store, uri, filename_local, cancellable, completion_local, &error_local);
+
+		/* free */
+		g_free (uri);
+
+		/* succeeded, otherwise retry with new mirrors */
+		if (ret)
+			break;
+
+		/* free error */
+		zif_completion_reset (completion_local);
+		egg_debug ("failed to download (non-fatal): %s", error_local->message);
+		g_error_free (error_local);
+	}
+
+	/* this section done */
+	zif_completion_done (completion);
+
+	/* nothing */
+	if (!ret) {
+		if (error != NULL)
+			*error = g_error_new (1, 0, "failed to download from any sources");
+		goto out;
+	}
+out:
+	g_free (basename);
+	g_free (dirname);
+	g_free (filename_local);
+	return ret;
+}
+
+/**
+ * zif_store_remote_add_metalink:
+ **/
+static gboolean
+zif_store_remote_add_metalink (ZifStoreRemote *store, GCancellable *cancellable, ZifCompletion *completion, GError **error)
+{
+	guint i;
+	GPtrArray *array;
+	GError *error_local = NULL;
+	const gchar *uri;
+	const gchar *filename;
+	gboolean ret;
+	ZifCompletion *completion_local;
+
+	/* if we're loading the metadata with an empty cache, the file won't yet exist. So download it */
+	filename = zif_repo_md_get_filename_uncompressed (store->priv->md_metalink);
+	ret = g_file_test (filename, G_FILE_TEST_EXISTS);
+	if (!ret) {
+		completion_local = zif_completion_get_child (completion);
+		ret = zif_store_remote_download (store, store->priv->mirrorlist, store->priv->directory, cancellable, completion_local, &error_local);
+		if (!ret) {
+			if (error != NULL)
+				*error = g_error_new (1, 0, "failed to download missing mirrorlist: %s", error_local->message);
+			g_error_free (error_local);
+			goto out;
+		}
+	}
+
+	/* get mirrors */
+	array = zif_repo_md_metalink_get_uris (ZIF_REPO_MD_METALINK (store->priv->md_metalink), 50, cancellable, completion, &error_local);
+	if (array == NULL) {
+		if (error != NULL)
+			*error = g_error_new (1, 0, "failed to add mirrors: %s", error_local->message);
+		g_error_free (error_local);
+		goto out;
+	}
+
+	/* add array */
+	for (i=0; i<array->len; i++) {
+		uri = g_ptr_array_index (array, i);
+		g_ptr_array_add (store->priv->baseurls, g_strdup (uri));
+	}
+
+	/* free */
+	g_ptr_array_unref (array);
+out:
+	return (array != NULL);
+}
+
+/**
+ * zif_store_remote_add_mirrorlist:
+ **/
+static gboolean
+zif_store_remote_add_mirrorlist (ZifStoreRemote *store, GCancellable *cancellable, ZifCompletion *completion, GError **error)
+{
+	guint i;
+	GPtrArray *array;
+	GError *error_local = NULL;
+	const gchar *uri;
+	const gchar *filename;
+	gboolean ret;
+	ZifCompletion *completion_local;
+
+	/* if we're loading the metadata with an empty cache, the file won't yet exist. So download it */
+	filename = zif_repo_md_get_filename_uncompressed (store->priv->md_mirrorlist);
+	ret = g_file_test (filename, G_FILE_TEST_EXISTS);
+	if (!ret) {
+		completion_local = zif_completion_get_child (completion);
+		ret = zif_store_remote_download (store, store->priv->mirrorlist, store->priv->directory, cancellable, completion_local, &error_local);
+		if (!ret) {
+			if (error != NULL)
+				*error = g_error_new (1, 0, "failed to download missing mirrorlist: %s", error_local->message);
+			g_error_free (error_local);
+			goto out;
+		}
+	}
+
+	/* get mirrors */
+	array = zif_repo_md_mirrorlist_get_uris (ZIF_REPO_MD_MIRRORLIST (store->priv->md_mirrorlist), cancellable, completion, &error_local);
+	if (array == NULL) {
+		if (error != NULL)
+			*error = g_error_new (1, 0, "failed to add mirrors: %s", error_local->message);
+		g_error_free (error_local);
+		goto out;
+	}
+
+	/* add array */
+	for (i=0; i<array->len; i++) {
+		uri = g_ptr_array_index (array, i);
+		g_ptr_array_add (store->priv->baseurls, g_strdup (uri));
+	}
+
+	/* free */
+	g_ptr_array_unref (array);
+out:
+	return (array != NULL);
+
+}
+
+/**
+ * zif_store_remote_load_metadata:
+ *
+ * This function does the following things:
+ *
+ * - opens repomd.xml (downloading it if it doesn't exist)
+ * - parses the contents, and populates the ZifMd types
+ * - parses metalink and mirrorlink into lists of plain urls
+ * - checks all the compressed metadata checksums are valid, else they are deleted
+ * - checks all the uncompressed metadata checksums are valid, else they are deleted
+ **/
+static gboolean
+zif_store_remote_load_metadata (ZifStoreRemote *store, GCancellable *cancellable, ZifCompletion *completion, GError **error)
+{
+	guint i;
+	ZifCompletion *completion_local;
+	const gchar *location;
+	gboolean ret = TRUE;
+	gchar *contents = NULL;
+	gchar *basename;
+	gchar *filename;
+	gsize size;
+	GError *error_local = NULL;
+	ZifRepoMd *md;
+	GMarkupParseContext *context = NULL;
+	const GMarkupParser gpk_store_remote_markup_parser = {
+		zif_store_remote_parser_start_element,
+		zif_store_remote_parser_end_element,
+		zif_store_remote_parser_text,
+		NULL, /* passthrough */
+		NULL /* error */
+	};
+
+	g_return_val_if_fail (ZIF_IS_STORE_REMOTE (store), FALSE);
+
+	/* not locked */
+	ret = zif_lock_is_locked (store->priv->lock, NULL);
+	if (!ret) {
+		egg_warning ("not locked");
+		if (error != NULL)
+			*error = g_error_new (1, 0, "not locked");
+		goto out;
+	}
+
+	/* already loaded */
+	if (store->priv->loaded_metadata)
+		goto out;
+
+	/* setup completion */
+	zif_completion_set_number_steps (completion, 3);
+
+	/* repomd file does not exist */
+	ret = g_file_test (store->priv->repomd_filename, G_FILE_TEST_EXISTS);
+	if (!ret) {
+		/* if not online, then this is fatal */
+		ret = zif_config_get_boolean (store->priv->config, "network", NULL);
+		if (!ret) {
+			if (error != NULL)
+				*error = g_error_new (1, 0, "failed to download repomd as offline");
+			goto out;
+		}
+
+		/* download new file */
+		completion_local = zif_completion_get_child (completion);
+		store->priv->loaded_metadata = TRUE;
+		ret = zif_store_remote_download (store, store->priv->repomd_filename, store->priv->directory, cancellable, completion_local, &error_local);
+		store->priv->loaded_metadata = FALSE;
+		if (!ret) {
+			if (error != NULL)
+				*error = g_error_new (1, 0, "failed to download missing repomd: %s", error_local->message);
+			g_error_free (error_local);
+			goto out;
+		}
+	}
+
+	/* get repo contents */
+	ret = g_file_get_contents (store->priv->repomd_filename, &contents, &size, error);
+	if (!ret)
+		goto out;
+
+	/* create parser */
+	context = g_markup_parse_context_new (&gpk_store_remote_markup_parser, G_MARKUP_PREFIX_ERROR_POSITION, store, NULL);
+
+	/* parse data */
+	ret = g_markup_parse_context_parse (context, contents, (gssize) size, error);
+	if (!ret)
+		goto out;
+
+	/* set MD id and filename for each repo type */
+	for (i=0; i<ZIF_REPO_MD_TYPE_UNKNOWN; i++) {
+		md = zif_store_remote_get_md_from_type (store, i);
+		if (md == NULL) {
+			/* TODO: until we've created ZifRepoMdComps and ZifRepoMdOther we'll get warnings here */
+			egg_warning ("failed to get local store for %s with %s", zif_repo_md_type_to_text (i), store->priv->id);
+			continue;
+		}
+
+		/* no metalink? */
+		if (i == ZIF_REPO_MD_TYPE_METALINK &&
+		    store->priv->metalink == NULL)
+			continue;
+
+		/* no mirrorlist? */
+		if (i == ZIF_REPO_MD_TYPE_MIRRORLIST &&
+		    store->priv->mirrorlist == NULL)
+			continue;
+
+		/* set parent reference */
+		zif_repo_md_set_store_remote (md, store);
+
+		/* set MD type */
+		zif_repo_md_set_mdtype (md, i);
+
+		/* location not set */
+		location = zif_repo_md_get_location (md);
+		if (location == NULL) {
+			/* messed up repo file, this is fatal */
+			if (i == ZIF_REPO_MD_TYPE_PRIMARY_DB) {
+				if (error != NULL)
+					*error = g_error_new (1, 0, "failed to get primary metadata location for %s", store->priv->id);
+				ret = FALSE;
+				goto out;
+			}
+			egg_warning ("no location set for %s with %s", zif_repo_md_type_to_text (i), store->priv->id);
+			continue;
+		}
+
+		/* set MD id and filename */
+		basename = g_path_get_basename (location);
+		filename = g_build_filename (store->priv->directory, basename, NULL);
+		zif_repo_md_set_id (md, store->priv->id);
+		zif_repo_md_set_filename (md, filename);
+		g_free (basename);
+		g_free (filename);
+	}
+
+	/* this section done */
+	zif_completion_done (completion);
+
+	/* extract details from mirrorlist */
+	if (store->priv->mirrorlist != NULL) {
+		completion_local = zif_completion_get_child (completion);
+		ret = zif_store_remote_add_mirrorlist (store, cancellable, completion_local, &error_local);
+		if (!ret) {
+			if (error != NULL)
+				*error = g_error_new (1, 0, "failed to add mirrorlist: %s", error_local->message);
+			g_error_free (error_local);
+			goto out;
+		}
+	}
+
+	/* this section done */
+	zif_completion_done (completion);
+
+	/* extract details from metalink */
+	if (store->priv->metalink != NULL) {
+		completion_local = zif_completion_get_child (completion);
+		ret = zif_store_remote_add_metalink (store, cancellable, completion_local, &error_local);
+		if (!ret) {
+			if (error != NULL)
+				*error = g_error_new (1, 0, "failed to add metalink: %s", error_local->message);
+			g_error_free (error_local);
+			goto out;
+		}
+	}
+
+	/* all okay */
+	store->priv->loaded_metadata = TRUE;
+
+	/* this section done */
+	zif_completion_done (completion);
+out:
+	if (context != NULL)
+		g_markup_parse_context_free (context);
+	g_free (contents);
+	return ret;
+}
+
+/**
+ * zif_store_file_decompress:
+ **/
+static gboolean
+zif_store_file_decompress (const gchar *filename, GCancellable *cancellable, ZifCompletion *completion, GError **error)
+{
+	gboolean ret = TRUE;
+	gboolean compressed;
+	gchar *filename_uncompressed = NULL;
+
+	/* only do for compressed filenames */
+	compressed = zif_file_is_compressed_name (filename);
+	if (!compressed) {
+		egg_debug ("%s not compressed", filename);
+		goto out;
+	}
+
+	/* get new name */
+	filename_uncompressed = zif_file_get_uncompressed_name (filename);
+
+	/* decompress */
+	ret = zif_file_decompress (filename, filename_uncompressed, cancellable, completion, error);
+out:
+	g_free (filename_uncompressed);
+	return ret;
+}
+
+/**
+ * zif_store_remote_refresh:
+ **/
+static gboolean
+zif_store_remote_refresh (ZifStore *store, gboolean force, GCancellable *cancellable, ZifCompletion *completion, GError **error)
+{
+	gboolean ret = FALSE;
+	GError *error_local = NULL;
+	const gchar *filename;
+	ZifCompletion *completion_local = NULL;
+	ZifStoreRemote *remote = ZIF_STORE_REMOTE (store);
+	ZifRepoMd *md;
+	guint i;
+
+	g_return_val_if_fail (ZIF_IS_STORE_REMOTE (store), FALSE);
+	g_return_val_if_fail (remote->priv->id != NULL, FALSE);
+
+	/* if not online, then this is fatal */
+	ret = zif_config_get_boolean (remote->priv->config, "network", NULL);
+	if (!ret) {
+		if (error != NULL)
+			*error = g_error_new (1, 0, "failed to refresh as offline");
+		goto out;
+	}
+
+	/* setup completion with the correct number of steps */
+	zif_completion_set_number_steps (completion, (ZIF_REPO_MD_TYPE_UNKNOWN * 2) + 2);
+
+	/* not locked */
+	ret = zif_lock_is_locked (remote->priv->lock, NULL);
+	if (!ret) {
+		egg_warning ("not locked");
+		if (error != NULL)
+			*error = g_error_new (1, 0, "not locked");
+		goto out;
+	}
+
+	/* get local completion object */
+	completion_local = zif_completion_get_child (completion);
+
+	/* download new file */
+	ret = zif_store_remote_download (remote, remote->priv->repomd_filename, remote->priv->directory, cancellable, completion_local, &error_local);
+	if (!ret) {
+		if (error != NULL)
+			*error = g_error_new (1, 0, "failed to download repomd: %s", error_local->message);
+		g_error_free (error_local);
+		goto out;
+	}
+
+	/* this section done */
+	zif_completion_done (completion);
+
+	/* reload */
+	completion_local = zif_completion_get_child (completion);
+	ret = zif_store_remote_load_metadata (remote, cancellable, completion_local, &error_local);
+	if (!ret) {
+		if (error != NULL)
+			*error = g_error_new (1, 0, "failed to load updated metadata: %s", error_local->message);
+		g_error_free (error_local);
+		goto out;
+	}
+
+	/* this section done */
+	zif_completion_done (completion);
+
+	/* refresh each repo type */
+	for (i=0; i<ZIF_REPO_MD_TYPE_UNKNOWN; i++) {
+		md = zif_store_remote_get_md_from_type (remote, i);
+		if (md == NULL) {
+			egg_debug ("failed to get local store for %s", zif_repo_md_type_to_text (i));
+			continue;
+		}
+
+		/* get filename */
+		filename = zif_repo_md_get_filename (md);
+		if (filename == NULL) {
+			egg_warning ("no filename set for %s", zif_repo_md_type_to_text (i));
+			continue;
+		}
+
+		/* does current uncompressed file equal what repomd says it should be */
+		ret = zif_repo_md_file_check (md, TRUE, &error_local);
+		if (ret && !force) {
+			egg_debug ("%s is okay", zif_repo_md_type_to_text (i));
+			continue;
+		}
+
+		/* download new file */
+		completion_local = zif_completion_get_child (completion);
+		ret = zif_store_remote_download (remote, filename, remote->priv->directory, cancellable, completion_local, &error_local);
+		if (!ret) {
+			if (error != NULL)
+				*error = g_error_new (1, 0, "failed to refresh %s (%s): %s", zif_repo_md_type_to_text (i), filename, error_local->message);
+			g_error_free (error_local);
+			goto out;
+		}
+
+		/* this section done */
+		zif_completion_done (completion);
+
+		/* decompress */
+		completion_local = zif_completion_get_child (completion);
+		ret = zif_store_file_decompress (filename, cancellable, completion_local, &error_local);
+		if (!ret) {
+			if (error != NULL)
+				*error = g_error_new (1, 0, "failed to decompress %s for %s: %s",
+						      filename, zif_repo_md_type_to_text (i), error_local->message);
+			g_error_free (error_local);
+			goto out;
+		}
+
+		/* this section done */
+		zif_completion_done (completion);
+	}
+
+out:
+	return ret;
+}
+
+/**
+ * zif_store_remote_load:
+ **/
+static gboolean
+zif_store_remote_load (ZifStore *store, GCancellable *cancellable, ZifCompletion *completion, GError **error)
+{
+	GKeyFile *file = NULL;
+	gboolean ret = TRUE;
+	gchar *enabled = NULL;
+	GError *error_local = NULL;
+	gchar *temp;
+	ZifStoreRemote *remote = ZIF_STORE_REMOTE (store);
+
+	g_return_val_if_fail (ZIF_IS_STORE_REMOTE (store), FALSE);
+	g_return_val_if_fail (remote->priv->id != NULL, FALSE);
+	g_return_val_if_fail (remote->priv->repo_filename != NULL, FALSE);
+
+	/* not locked */
+	ret = zif_lock_is_locked (remote->priv->lock, NULL);
+	if (!ret) {
+		egg_warning ("not locked");
+		if (error != NULL)
+			*error = g_error_new (1, 0, "not locked");
+		goto out;
+	}
+
+	/* already loaded */
+	if (remote->priv->loaded)
+		goto out;
+
+	/* setup completion with the correct number of steps */
+	zif_completion_set_number_steps (completion, 2);
+
+	file = g_key_file_new ();
+	ret = g_key_file_load_from_file (file, remote->priv->repo_filename, G_KEY_FILE_NONE, &error_local);
+	if (!ret) {
+		if (error != NULL)
+			*error = g_error_new (1, 0, "failed to load %s: %s", remote->priv->repo_filename, error_local->message);
+		g_error_free (error_local);
+		goto out;
+	}
+
+	/* this section done */
+	zif_completion_done (completion);
+
+	/* name */
+	remote->priv->name = g_key_file_get_string (file, remote->priv->id, "name", &error_local);
+	if (error_local != NULL) {
+		if (error != NULL)
+			*error = g_error_new (1, 0, "failed to get name: %s", error_local->message);
+		g_error_free (error_local);
+		ret = FALSE;
+		goto out;
+	}
+
+	/* enabled */
+	enabled = g_key_file_get_string (file, remote->priv->id, "enabled", &error_local);
+	if (enabled == NULL) {
+		if (error != NULL)
+			*error = g_error_new (1, 0, "failed to get enabled: %s", error_local->message);
+		g_error_free (error_local);
+		ret = FALSE;
+		goto out;
+	}
+
+	/* convert to bool */
+	remote->priv->enabled = zif_boolean_from_text (enabled);
+
+	/* expand out */
+	remote->priv->name_expanded = zif_config_expand_substitutions (remote->priv->config, remote->priv->name, NULL);
+
+	/* get base url (allowed to be blank) */
+	temp = g_key_file_get_string (file, remote->priv->id, "baseurl", NULL);
+	if (temp != NULL && temp[0] != '\0')
+		g_ptr_array_add (remote->priv->baseurls, zif_config_expand_substitutions (remote->priv->config, temp, NULL));
+	g_free (temp);
+
+	/* get mirror list (allowed to be blank) */
+	temp = g_key_file_get_string (file, remote->priv->id, "mirrorlist", NULL);
+	if (temp != NULL && temp[0] != '\0')
+		remote->priv->mirrorlist = zif_config_expand_substitutions (remote->priv->config, temp, NULL);
+	g_free (temp);
+
+	/* get metalink (allowed to be blank) */
+	temp = g_key_file_get_string (file, remote->priv->id, "metalink", NULL);
+	if (temp != NULL && temp[0] != '\0')
+		remote->priv->metalink = zif_config_expand_substitutions (remote->priv->config, temp, NULL);
+	g_free (temp);
+
+	/* urgh.. yum allows mirrorlist= to be used as well as metalink= for metalink URLs */
+	if (remote->priv->metalink == NULL &&
+	    remote->priv->mirrorlist != NULL &&
+	    g_strstr_len (remote->priv->mirrorlist, -1, "metalink?") != NULL) {
+		/* swap */
+		remote->priv->metalink = remote->priv->mirrorlist;
+		remote->priv->mirrorlist = NULL;
+	}
+
+	/* we need either a base url or mirror list for an enabled store */
+	if (remote->priv->enabled && remote->priv->baseurls->len == 0 && remote->priv->metalink == NULL && remote->priv->mirrorlist == NULL) {
+		if (error != NULL)
+			*error = g_error_new (1, 0, "baseurl, metalink or mirrorlist required");
+		ret = FALSE;
+		goto out;
+	}
+
+	/* okay */
+	remote->priv->loaded = TRUE;
+
+	/* this section done */
+	zif_completion_done (completion);
+out:
+	g_free (enabled);
+	if (file != NULL)
+		g_key_file_free (file);
+	return ret;
+}
+
+/**
+ * zif_store_remote_clean:
+ **/
+static gboolean
+zif_store_remote_clean (ZifStore *store, GCancellable *cancellable, ZifCompletion *completion, GError **error)
+{
+	gboolean ret = FALSE;
+	gboolean exists;
+	GError *error_local = NULL;
+	GFile *file;
+	ZifStoreRemote *remote = ZIF_STORE_REMOTE (store);
+	ZifCompletion *completion_local;
+	ZifRepoMd *md;
+	guint i;
+	const gchar *location;
+
+	g_return_val_if_fail (ZIF_IS_STORE_REMOTE (store), FALSE);
+	g_return_val_if_fail (remote->priv->id != NULL, FALSE);
+
+	/* not locked */
+	ret = zif_lock_is_locked (remote->priv->lock, NULL);
+	if (!ret) {
+		egg_warning ("not locked");
+		if (error != NULL)
+			*error = g_error_new (1, 0, "not locked");
+		goto out;
+	}
+
+	/* setup completion with the correct number of steps */
+	if (remote->priv->loaded_metadata)
+		zif_completion_set_number_steps (completion, 1+ZIF_REPO_MD_TYPE_UNKNOWN);
+	else
+		zif_completion_set_number_steps (completion, 2+ZIF_REPO_MD_TYPE_UNKNOWN);
+
+	/* load metadata */
+	if (!remote->priv->loaded_metadata) {
+		completion_local = zif_completion_get_child (completion);
+		ret = zif_store_remote_load_metadata (remote, cancellable, completion_local, &error_local);
+		if (!ret) {
+//			if (error != NULL)
+//				*error = g_error_new (1, 0, "failed to load xml: %s", error_local->message);
+			/* ignore this error */
+			g_print ("failed to load xml: %s\n", error_local->message);
+			g_error_free (error_local);
+			ret = TRUE;
+			goto out;
+		}
+
+		/* this section done */
+		zif_completion_done (completion);
+	}
+
+	/* set MD id and filename for each repo type */
+	for (i=0; i<ZIF_REPO_MD_TYPE_UNKNOWN; i++) {
+		md = zif_store_remote_get_md_from_type (remote, i);
+		if (md == NULL) {
+			/* TODO: until we've created ZifRepoMdComps and ZifRepoMdOther we'll get warnings here */
+			egg_warning ("failed to get local store for %s with %s", zif_repo_md_type_to_text (i), remote->priv->id);
+			goto skip;
+		}
+
+		/* location not set */
+		location = zif_repo_md_get_location (md);
+		if (location == NULL) {
+			egg_warning ("no location set for %s with %s", zif_repo_md_type_to_text (i), remote->priv->id);
+			goto skip;
+		}
+
+		/* clean md */
+		ret = zif_repo_md_clean (md, &error_local);
+		if (!ret) {
+			if (error != NULL)
+				*error = g_error_new (1, 0, "failed to clean %s: %s", zif_repo_md_type_to_text (i), error_local->message);
+			g_error_free (error_local);
+			goto out;
+		}
+skip:
+		/* this section done */
+		zif_completion_done (completion);
+	}
+
+	/* clean master (last) */
+	exists = g_file_test (remote->priv->repomd_filename, G_FILE_TEST_EXISTS);
+	if (exists) {
+		file = g_file_new_for_path (remote->priv->repomd_filename);
+		ret = g_file_delete (file, NULL, &error_local);
+		g_object_unref (file);
+		if (!ret) {
+			if (error != NULL)
+				*error = g_error_new (1, 0, "failed to delete metadata file %s: %s",
+						      remote->priv->repomd_filename, error_local->message);
+			g_error_free (error_local);
+			goto out;
+		}
+	}
+
+	/* this section done */
+	zif_completion_done (completion);
+out:
+	return ret;
+}
+
+/**
+ * zif_store_remote_set_from_file:
+ * @cancellable: a #GCancellable which is used to cancel tasks, or %NULL
+ * @completion: a #ZifCompletion to use for progress reporting
+ **/
+gboolean
+zif_store_remote_set_from_file (ZifStoreRemote *store, const gchar *repo_filename, const gchar *id,
+				GCancellable *cancellable, ZifCompletion *completion, GError **error)
+{
+	GError *error_local = NULL;
+	gboolean ret = TRUE;
+
+	g_return_val_if_fail (ZIF_IS_STORE_REMOTE (store), FALSE);
+	g_return_val_if_fail (repo_filename != NULL, FALSE);
+	g_return_val_if_fail (id != NULL, FALSE);
+	g_return_val_if_fail (store->priv->id == NULL, FALSE);
+	g_return_val_if_fail (!store->priv->loaded, FALSE);
+
+	/* not locked */
+	ret = zif_lock_is_locked (store->priv->lock, NULL);
+	if (!ret) {
+		egg_warning ("not locked");
+		if (error != NULL)
+			*error = g_error_new (1, 0, "not locked");
+		goto out;
+	}
+
+	/* save */
+	egg_debug ("setting store %s", id);
+	store->priv->id = g_strdup (id);
+	store->priv->repo_filename = g_strdup (repo_filename);
+	store->priv->directory = g_build_filename (store->priv->cache_dir, store->priv->id, NULL);
+
+	/* repomd location */
+	store->priv->repomd_filename = g_build_filename (store->priv->cache_dir, store->priv->id, "repomd.xml", NULL);
+
+	/* setup watch */
+	ret = zif_monitor_add_watch (store->priv->monitor, repo_filename, &error_local);
+	if (!ret) {
+		if (error != NULL)
+			*error = g_error_new (1, 0, "failed to setup watch: %s", error_local->message);
+		g_error_free (error_local);
+		goto out;
+	}
+
+	/* get data */
+	ret = zif_store_remote_load (ZIF_STORE (store), cancellable, completion, &error_local);
+	if (!ret) {
+		if (error != NULL)
+			*error = g_error_new (1, 0, "failed to load %s: %s", id, error_local->message);
+		g_error_free (error_local);
+		goto out;
+	}
+out:
+	/* save */
+	return ret;
+}
+
+/**
+ * zif_store_remote_set_enabled:
+ * @store: the #ZifStoreRemote object
+ * @enabled: If the object should be enabled
+ * @error: a #GError which is used on failure, or %NULL
+ *
+ * Enable or disable a remote repository.
+ *
+ * Return value: %TRUE for success, %FALSE for failure
+ **/
+gboolean
+zif_store_remote_set_enabled (ZifStoreRemote *store, gboolean enabled, GError **error)
+{
+	GKeyFile *file;
+	gboolean ret;
+	GError *error_local = NULL;
+	gchar *data;
+
+	g_return_val_if_fail (ZIF_IS_STORE_REMOTE (store), FALSE);
+	g_return_val_if_fail (store->priv->id != NULL, FALSE);
+
+	/* not locked */
+	ret = zif_lock_is_locked (store->priv->lock, NULL);
+	if (!ret) {
+		egg_warning ("not locked");
+		if (error != NULL)
+			*error = g_error_new (1, 0, "not locked");
+		goto out;
+	}
+
+	/* load file */
+	file = g_key_file_new ();
+	ret = g_key_file_load_from_file (file, store->priv->repo_filename, G_KEY_FILE_KEEP_COMMENTS, &error_local);
+	if (!ret) {
+		if (error != NULL)
+			*error = g_error_new (1, 0, "failed to load store file: %s", error_local->message);
+		g_error_free (error_local);
+		goto out;
+	}
+
+	/* toggle enabled */
+	store->priv->enabled = enabled;
+	g_key_file_set_boolean (file, store->priv->id, "enabled", store->priv->enabled);
+
+	/* save new data to file */
+	data = g_key_file_to_data (file, NULL, NULL);
+	ret = g_file_set_contents (store->priv->repo_filename, data, -1, &error_local);
+	if (!ret) {
+		if (error != NULL)
+			*error = g_error_new (1, 0, "failed to save: %s", error_local->message);
+		g_error_free (error_local);
+		goto out;
+	}
+
+	g_free (data);
+	g_key_file_free (file);
+out:
+	return ret;
+}
+
+/**
+ * zif_store_remote_print:
+ **/
+static void
+zif_store_remote_print (ZifStore *store)
+{
+	ZifStoreRemote *remote = ZIF_STORE_REMOTE (store);
+
+	g_return_if_fail (ZIF_IS_STORE_REMOTE (store));
+	g_return_if_fail (remote->priv->id != NULL);
+
+	g_print ("id: %s\n", remote->priv->id);
+	g_print ("name: %s\n", remote->priv->name);
+	g_print ("name-expanded: %s\n", remote->priv->name_expanded);
+	g_print ("enabled: %i\n", remote->priv->enabled);
+}
+
+/**
+ * zif_store_remote_resolve:
+ **/
+static GPtrArray *
+zif_store_remote_resolve (ZifStore *store, const gchar *search, GCancellable *cancellable, ZifCompletion *completion, GError **error)
+{
+	gboolean ret;
+	GError *error_local = NULL;
+	GPtrArray *array = NULL;
+	ZifStoreRemote *remote = ZIF_STORE_REMOTE (store);
+	ZifCompletion *completion_local;
+
+	g_return_val_if_fail (ZIF_IS_STORE_REMOTE (store), FALSE);
+	g_return_val_if_fail (remote->priv->id != NULL, FALSE);
+
+	/* not locked */
+	ret = zif_lock_is_locked (remote->priv->lock, NULL);
+	if (!ret) {
+		egg_warning ("not locked");
+		if (error != NULL)
+			*error = g_error_new (1, 0, "not locked");
+		goto out;
+	}
+
+	/* setup completion */
+	if (remote->priv->loaded_metadata)
+		zif_completion_set_number_steps (completion, 1);
+	else
+		zif_completion_set_number_steps (completion, 2);
+
+	/* load metadata */
+	if (!remote->priv->loaded_metadata) {
+		completion_local = zif_completion_get_child (completion);
+		ret = zif_store_remote_load_metadata (remote, cancellable, completion_local, &error_local);
+		if (!ret) {
+			if (error != NULL)
+				*error = g_error_new (1, 0, "failed to load xml: %s", error_local->message);
+			g_error_free (error_local);
+			goto out;
+		}
+
+		/* this section done */
+		zif_completion_done (completion);
+	}
+
+	completion_local = zif_completion_get_child (completion);
+	array = zif_repo_md_primary_resolve (ZIF_REPO_MD_PRIMARY (remote->priv->md_primary), search, cancellable, completion_local, error);
+
+	/* this section done */
+	zif_completion_done (completion);
+out:
+	return array;
+}
+
+/**
+ * zif_store_remote_search_name:
+ **/
+static GPtrArray *
+zif_store_remote_search_name (ZifStore *store, const gchar *search, GCancellable *cancellable, ZifCompletion *completion, GError **error)
+{
+	gboolean ret;
+	GError *error_local = NULL;
+	GPtrArray *array = NULL;
+	ZifStoreRemote *remote = ZIF_STORE_REMOTE (store);
+	ZifCompletion *completion_local;
+
+	g_return_val_if_fail (ZIF_IS_STORE_REMOTE (store), FALSE);
+	g_return_val_if_fail (remote->priv->id != NULL, FALSE);
+
+	/* not locked */
+	ret = zif_lock_is_locked (remote->priv->lock, NULL);
+	if (!ret) {
+		egg_warning ("not locked");
+		if (error != NULL)
+			*error = g_error_new (1, 0, "not locked");
+		goto out;
+	}
+
+	/* setup completion */
+	if (remote->priv->loaded_metadata)
+		zif_completion_set_number_steps (completion, 1);
+	else
+		zif_completion_set_number_steps (completion, 2);
+
+	/* load metadata */
+	if (!remote->priv->loaded_metadata) {
+		completion_local = zif_completion_get_child (completion);
+		ret = zif_store_remote_load_metadata (remote, cancellable, completion_local, &error_local);
+		if (!ret) {
+			if (error != NULL)
+				*error = g_error_new (1, 0, "failed to load xml: %s", error_local->message);
+			g_error_free (error_local);
+			goto out;
+		}
+
+		/* this section done */
+		zif_completion_done (completion);
+	}
+
+	completion_local = zif_completion_get_child (completion);
+	array = zif_repo_md_primary_search_name (ZIF_REPO_MD_PRIMARY (remote->priv->md_primary), search, cancellable, completion_local, error);
+
+	/* this section done */
+	zif_completion_done (completion);
+out:
+	return array;
+}
+
+/**
+ * zif_store_remote_search_details:
+ **/
+static GPtrArray *
+zif_store_remote_search_details (ZifStore *store, const gchar *search, GCancellable *cancellable, ZifCompletion *completion, GError **error)
+{
+	gboolean ret;
+	GError *error_local = NULL;
+	GPtrArray *array = NULL;
+	ZifStoreRemote *remote = ZIF_STORE_REMOTE (store);
+	ZifCompletion *completion_local;
+
+	g_return_val_if_fail (ZIF_IS_STORE_REMOTE (store), FALSE);
+	g_return_val_if_fail (remote->priv->id != NULL, FALSE);
+
+	/* not locked */
+	ret = zif_lock_is_locked (remote->priv->lock, NULL);
+	if (!ret) {
+		egg_warning ("not locked");
+		if (error != NULL)
+			*error = g_error_new (1, 0, "not locked");
+		goto out;
+	}
+
+	/* setup completion */
+	if (remote->priv->loaded_metadata)
+		zif_completion_set_number_steps (completion, 1);
+	else
+		zif_completion_set_number_steps (completion, 2);
+
+	/* load metadata */
+	if (!remote->priv->loaded_metadata) {
+		completion_local = zif_completion_get_child (completion);
+		ret = zif_store_remote_load_metadata (remote, cancellable, completion_local, &error_local);
+		if (!ret) {
+			if (error != NULL)
+				*error = g_error_new (1, 0, "failed to load xml: %s", error_local->message);
+			g_error_free (error_local);
+			goto out;
+		}
+
+		/* this section done */
+		zif_completion_done (completion);
+	}
+
+	completion_local = zif_completion_get_child (completion);
+	array = zif_repo_md_primary_search_details (ZIF_REPO_MD_PRIMARY (remote->priv->md_primary), search, cancellable, completion_local, error);
+
+	/* this section done */
+	zif_completion_done (completion);
+out:
+	return array;
+}
+
+/**
+ * zif_store_remote_search_category_resolve:
+ **/
+static ZifPackage *
+zif_store_remote_search_category_resolve (ZifStore *store, const gchar *name, GCancellable *cancellable, ZifCompletion *completion, GError **error)
+{
+	ZifStoreLocal *store_local = NULL;
+	GError *error_local = NULL;
+	GPtrArray *array = NULL;
+	ZifPackage *package = NULL;
+	ZifCompletion *completion_local;
+
+	store_local = zif_store_local_new ();
+
+	/* setup steps */
+	zif_completion_set_number_steps (completion, 2);
+
+	/* is already installed? */
+	completion_local = zif_completion_get_child (completion);
+	array = zif_store_resolve (ZIF_STORE (store_local), name, cancellable, completion_local, &error_local);
+	if (array == NULL) {
+		if (error != NULL)
+			*error = g_error_new (1, 0, "failed to resolve installed package %s: %s", name, error_local->message);
+		g_error_free (error_local);
+		goto out;
+	}
+
+	/* this section done */
+	zif_completion_done (completion);
+
+	/* get newest, ignore error */
+	package = zif_package_array_get_newest (array, NULL);
+	if (package != NULL) {
+		/* we don't need to do the second part */
+		zif_completion_done (completion);
+		goto out;
+	}
+
+	/* clear array */
+	g_ptr_array_unref (array);
+
+	/* is available in this repo? */
+	completion_local = zif_completion_get_child (completion);
+	array = zif_store_resolve (ZIF_STORE (store), name, cancellable, completion_local, &error_local);
+	if (array == NULL) {
+		if (error != NULL)
+			*error = g_error_new (1, 0, "failed to resolve installed package %s: %s", name, error_local->message);
+		g_error_free (error_local);
+		goto out;
+	}
+
+	/* this section done */
+	zif_completion_done (completion);
+
+	/* get newest, ignore error */
+	package = zif_package_array_get_newest (array, NULL);
+	if (package != NULL)
+		goto out;
+
+	/* we suck */
+	if (error != NULL)
+		*error = g_error_new (1, 0, "failed to resolve installed package %s installed or in this repo", name);
+out:
+	if (array != NULL)
+		g_ptr_array_unref (array);
+	if (store_local != NULL)
+		g_object_unref (store_local);
+	return package;
+}
+
+/**
+ * zif_store_remote_search_category:
+ **/
+static GPtrArray *
+zif_store_remote_search_category (ZifStore *store, const gchar *group_id, GCancellable *cancellable, ZifCompletion *completion, GError **error)
+{
+	gboolean ret;
+	GError *error_local = NULL;
+	GPtrArray *array = NULL;
+	GPtrArray *array_names = NULL;
+	ZifStoreRemote *remote = ZIF_STORE_REMOTE (store);
+	ZifCompletion *completion_local;
+	ZifCompletion *completion_loop;
+	ZifPackage *package;
+	const gchar *name;
+	const gchar *location;
+	guint i;
+
+	g_return_val_if_fail (ZIF_IS_STORE_REMOTE (store), FALSE);
+	g_return_val_if_fail (remote->priv->id != NULL, FALSE);
+
+	/* not locked */
+	ret = zif_lock_is_locked (remote->priv->lock, NULL);
+	if (!ret) {
+		egg_warning ("not locked");
+		if (error != NULL)
+			*error = g_error_new (1, 0, "not locked");
+		goto out;
+	}
+
+	/* setup completion */
+	if (remote->priv->loaded_metadata)
+		zif_completion_set_number_steps (completion, 2);
+	else
+		zif_completion_set_number_steps (completion, 3);
+
+	/* load metadata */
+	if (!remote->priv->loaded_metadata) {
+		completion_local = zif_completion_get_child (completion);
+		ret = zif_store_remote_load_metadata (remote, cancellable, completion_local, &error_local);
+		if (!ret) {
+			if (error != NULL)
+				*error = g_error_new (1, 0, "failed to load xml: %s", error_local->message);
+			g_error_free (error_local);
+			goto out;
+		}
+
+		/* this section done */
+		zif_completion_done (completion);
+	}
+
+	/* does this repo have comps data? */
+	location = zif_repo_md_get_location (remote->priv->md_comps);
+	if (location == NULL) {
+		/* empty array, as we want success */
+		array = g_ptr_array_new_with_free_func ((GDestroyNotify) g_object_unref);
+		goto out;
+	}
+
+	/* get package names for group */
+	completion_local = zif_completion_get_child (completion);
+	array_names = zif_repo_md_comps_get_packages_for_group (ZIF_REPO_MD_COMPS (remote->priv->md_comps),
+								group_id, cancellable, completion_local, &error_local);
+	if (array_names == NULL) {
+		/* ignore when group isn't present, TODO: use GError code */
+		if (g_str_has_prefix (error_local->message, "could not find group")) {
+			array = g_ptr_array_new_with_free_func ((GDestroyNotify) g_object_unref);
+			g_error_free (error_local);
+			goto out;
+		}
+		if (error != NULL)
+			*error = g_error_new (1, 0, "failed to get packages for group %s: %s", group_id, error_local->message);
+		g_error_free (error_local);
+		goto out;
+	}
+
+	/* this section done */
+	zif_completion_done (completion);
+
+	/* setup completion */
+	completion_local = zif_completion_get_child (completion);
+	zif_completion_set_number_steps (completion_local, array_names->len);
+
+	/* results array */
+	array = g_ptr_array_new_with_free_func ((GDestroyNotify) g_object_unref);
+
+	/* resolve names */
+	for (i=0; i<array_names->len; i++) {
+		name = g_ptr_array_index (array_names, i);
+
+		/* completion */
+		completion_loop = zif_completion_get_child (completion_local);
+		package = zif_store_remote_search_category_resolve (store, name, cancellable, completion_loop, &error_local);
+		if (package == NULL) {
+			/* ignore when package isn't present, TODO: use GError code */
+			if (g_str_has_prefix (error_local->message, "failed to resolve")) {
+				g_error_free (error_local);
+				egg_warning ("Failed to find %s installed or in repo %s", name, remote->priv->id);
+				goto ignore_error;
+			}
+
+			if (error != NULL)
+				*error = g_error_new (1, 0, "failed to get resolve %s for %s: %s", name, group_id, error_local->message);
+			g_error_free (error_local);
+
+			/* undo all our hard work */
+			g_ptr_array_unref (array);
+			array = NULL;
+			goto out;
+		}
+
+		/* add to array */
+		g_ptr_array_add (array, package);
+ignore_error:
+		/* this section done */
+		zif_completion_done (completion_local);
+	}
+
+	/* this section done */
+	zif_completion_done (completion);
+out:
+	if (array_names != NULL)
+		g_ptr_array_unref (array_names);
+	return array;
+}
+
+/**
+ * zif_store_remote_search_group:
+ **/
+static GPtrArray *
+zif_store_remote_search_group (ZifStore *store, const gchar *search, GCancellable *cancellable, ZifCompletion *completion, GError **error)
+{
+	gboolean ret;
+	GError *error_local = NULL;
+	GPtrArray *array = NULL;
+	ZifStoreRemote *remote = ZIF_STORE_REMOTE (store);
+	ZifCompletion *completion_local;
+
+	g_return_val_if_fail (ZIF_IS_STORE_REMOTE (store), FALSE);
+	g_return_val_if_fail (remote->priv->id != NULL, FALSE);
+
+	/* not locked */
+	ret = zif_lock_is_locked (remote->priv->lock, NULL);
+	if (!ret) {
+		egg_warning ("not locked");
+		if (error != NULL)
+			*error = g_error_new (1, 0, "not locked");
+		goto out;
+	}
+
+	/* setup completion */
+	if (remote->priv->loaded_metadata)
+		zif_completion_set_number_steps (completion, 1);
+	else
+		zif_completion_set_number_steps (completion, 2);
+
+	/* load metadata */
+	if (!remote->priv->loaded_metadata) {
+		completion_local = zif_completion_get_child (completion);
+		ret = zif_store_remote_load_metadata (remote, cancellable, completion_local, &error_local);
+		if (!ret) {
+			if (error != NULL)
+				*error = g_error_new (1, 0, "failed to load xml: %s", error_local->message);
+			g_error_free (error_local);
+			goto out;
+		}
+
+		/* this section done */
+		zif_completion_done (completion);
+	}
+
+	completion_local = zif_completion_get_child (completion);
+	array = zif_repo_md_primary_search_group (ZIF_REPO_MD_PRIMARY (remote->priv->md_primary), search, cancellable, completion_local, error);
+
+	/* this section done */
+	zif_completion_done (completion);
+out:
+	return array;
+}
+
+/**
+ * zif_store_remote_find_package:
+ **/
+static ZifPackage *
+zif_store_remote_find_package (ZifStore *store, const gchar *package_id, GCancellable *cancellable, ZifCompletion *completion, GError **error)
+{
+	gboolean ret;
+	GPtrArray *array = NULL;
+	ZifPackage *package = NULL;
+	GError *error_local = NULL;
+	ZifStoreRemote *remote = ZIF_STORE_REMOTE (store);
+	ZifCompletion *completion_local;
+
+	g_return_val_if_fail (ZIF_IS_STORE_REMOTE (store), FALSE);
+	g_return_val_if_fail (remote->priv->id != NULL, FALSE);
+
+	/* not locked */
+	ret = zif_lock_is_locked (remote->priv->lock, NULL);
+	if (!ret) {
+		egg_warning ("not locked");
+		if (error != NULL)
+			*error = g_error_new (1, 0, "not locked");
+		goto out;
+	}
+
+	/* setup completion */
+	if (remote->priv->loaded_metadata)
+		zif_completion_set_number_steps (completion, 1);
+	else
+		zif_completion_set_number_steps (completion, 2);
+
+	/* load metadata */
+	if (!remote->priv->loaded_metadata) {
+		completion_local = zif_completion_get_child (completion);
+		ret = zif_store_remote_load_metadata (remote, cancellable, completion_local, &error_local);
+		if (!ret) {
+			if (error != NULL)
+				*error = g_error_new (1, 0, "failed to load xml: %s", error_local->message);
+			g_error_free (error_local);
+			goto out;
+		}
+
+		/* this section done */
+		zif_completion_done (completion);
+	}
+
+	/* search with predicate, TODO: search version (epoch+release) */
+	completion_local = zif_completion_get_child (completion);
+	array = zif_repo_md_primary_find_package (ZIF_REPO_MD_PRIMARY (remote->priv->md_primary), package_id, cancellable, completion_local, &error_local);
+	if (array == NULL) {
+		if (error != NULL)
+			*error = g_error_new (1, 0, "failed to search: %s", error_local->message);
+		g_error_free (error_local);
+		goto out;
+	}
+
+	/* this section done */
+	zif_completion_done (completion);
+
+	/* nothing */
+	if (array->len == 0) {
+		if (error != NULL)
+			*error = g_error_new (1, 0, "failed to find package");
+		goto out;
+	}
+
+	/* more than one match */
+	if (array->len > 1) {
+		if (error != NULL)
+			*error = g_error_new (1, 0, "more than one match");
+		goto out;
+	}
+
+	/* return ref to package */
+	package = g_object_ref (g_ptr_array_index (array, 0));
+out:
+	g_ptr_array_unref (array);
+	return package;
+}
+
+/**
+ * zif_store_remote_get_packages:
+ **/
+static GPtrArray *
+zif_store_remote_get_packages (ZifStore *store, GCancellable *cancellable, ZifCompletion *completion, GError **error)
+{
+	gboolean ret;
+	GError *error_local = NULL;
+	GPtrArray *array = NULL;
+	ZifStoreRemote *remote = ZIF_STORE_REMOTE (store);
+	ZifCompletion *completion_local;
+
+	g_return_val_if_fail (ZIF_IS_STORE_REMOTE (store), FALSE);
+	g_return_val_if_fail (remote->priv->id != NULL, FALSE);
+
+	/* not locked */
+	ret = zif_lock_is_locked (remote->priv->lock, NULL);
+	if (!ret) {
+		egg_warning ("not locked");
+		if (error != NULL)
+			*error = g_error_new (1, 0, "not locked");
+		goto out;
+	}
+
+	/* setup completion */
+	if (remote->priv->loaded_metadata)
+		zif_completion_set_number_steps (completion, 1);
+	else
+		zif_completion_set_number_steps (completion, 2);
+
+	/* load metadata */
+	if (!remote->priv->loaded_metadata) {
+		completion_local = zif_completion_get_child (completion);
+		ret = zif_store_remote_load_metadata (remote, cancellable, completion_local, &error_local);
+		if (!ret) {
+			if (error != NULL)
+				*error = g_error_new (1, 0, "failed to load xml: %s", error_local->message);
+			g_error_free (error_local);
+			goto out;
+		}
+
+		/* this section done */
+		zif_completion_done (completion);
+	}
+
+	completion_local = zif_completion_get_child (completion);
+	array = zif_repo_md_primary_get_packages (ZIF_REPO_MD_PRIMARY (remote->priv->md_primary), cancellable, completion_local, error);
+
+	/* this section done */
+	zif_completion_done (completion);
+out:
+	return array;
+}
+
+/**
+ * zif_store_remote_get_categories:
+ **/
+static GPtrArray *
+zif_store_remote_get_categories (ZifStore *store, GCancellable *cancellable, ZifCompletion *completion, GError **error)
+{
+	gboolean ret;
+	guint i, j;
+	const gchar *location;
+	GError *error_local = NULL;
+	GPtrArray *array = NULL;
+	GPtrArray *array_cats = NULL;
+	GPtrArray *array_groups;
+	ZifStoreRemote *remote = ZIF_STORE_REMOTE (store);
+	ZifCompletion *completion_local;
+	ZifCompletion *completion_loop;
+//	PkCategory *comps_category;
+	PkCategory *group;
+	PkCategory *category;
+	PkCategory *category_tmp;
+
+	g_return_val_if_fail (ZIF_IS_STORE_REMOTE (store), FALSE);
+	g_return_val_if_fail (remote->priv->id != NULL, FALSE);
+
+	/* not locked */
+	ret = zif_lock_is_locked (remote->priv->lock, NULL);
+	if (!ret) {
+		egg_warning ("not locked");
+		if (error != NULL)
+			*error = g_error_new (1, 0, "not locked");
+		goto out;
+	}
+
+	/* setup completion */
+	if (remote->priv->loaded_metadata)
+		zif_completion_set_number_steps (completion, 2);
+	else
+		zif_completion_set_number_steps (completion, 3);
+
+	/* load metadata */
+	if (!remote->priv->loaded_metadata) {
+		completion_local = zif_completion_get_child (completion);
+		ret = zif_store_remote_load_metadata (remote, cancellable, completion_local, &error_local);
+		if (!ret) {
+			if (error != NULL)
+				*error = g_error_new (1, 0, "failed to load xml: %s", error_local->message);
+			g_error_free (error_local);
+			goto out;
+		}
+
+		/* this section done */
+		zif_completion_done (completion);
+	}
+
+	/* does this repo have comps data? */
+	location = zif_repo_md_get_location (remote->priv->md_comps);
+	if (location == NULL) {
+		/* empty array, as we want success */
+		array = g_ptr_array_new_with_free_func ((GDestroyNotify) g_object_unref);
+		goto out;
+	}
+
+	/* get list of categories */
+	completion_local = zif_completion_get_child (completion);
+	array_cats = zif_repo_md_comps_get_categories (ZIF_REPO_MD_COMPS (remote->priv->md_comps), cancellable, completion_local, &error_local);
+	if (array_cats == NULL) {
+		if (error != NULL)
+			*error = g_error_new (1, 0, "failed to get categories: %s", error_local->message);
+		g_error_free (error_local);
+		goto out;
+	}
+
+	/* this section done */
+	zif_completion_done (completion);
+
+	/* results array */
+	array = g_ptr_array_new_with_free_func ((GDestroyNotify) g_object_unref);
+
+	/* no results */
+	if (array_cats->len == 0)
+		goto skip;
+
+	/* setup steps */
+	completion_local = zif_completion_get_child (completion);
+	zif_completion_set_number_steps (completion_local, array_cats->len);
+
+	/* get groups for categories */
+	for (i=0; i<array_cats->len; i++) {
+		category = g_ptr_array_index (array_cats, i);
+
+		/* get the groups for this category */
+		completion_loop = zif_completion_get_child (completion_local);
+		array_groups = zif_repo_md_comps_get_groups_for_category (ZIF_REPO_MD_COMPS (remote->priv->md_comps),
+									  pk_category_get_id (category), cancellable, completion_loop, &error_local);
+		if (array_groups == NULL) {
+			if (error != NULL)
+				*error = g_error_new (1, 0, "failed to get groups for %s: %s", pk_category_get_id (category), error_local->message);
+			g_error_free (error_local);
+
+			/* undo the work we've already done */
+			g_ptr_array_unref (array);
+			array = NULL;
+			goto out;
+		}
+
+		/* only add categories which have groups */
+		if (array_groups->len > 0) {
+
+			/* first, add the parent */
+			g_ptr_array_add (array, g_object_ref (category));
+
+			/* second, add the groups belonging to this parent */
+			for (j=0; j<array_groups->len; j++) {
+				group = g_ptr_array_index (array_groups, j);
+				category_tmp = pk_category_new ();
+				g_object_set (category_tmp,
+					      "parent-id", pk_category_get_id (category),
+					      "cat-id", pk_category_get_id (group),
+					      "name", pk_category_get_name (group),
+					      "summary", pk_category_get_summary (group),
+					      NULL);
+				g_ptr_array_add (array, category_tmp);
+			}
+		}
+
+		/* this section done */
+		zif_completion_done (completion_local);
+	}
+skip:
+	/* this section done */
+	zif_completion_done (completion);
+out:
+	if (array_cats != NULL)
+		g_ptr_array_unref (array_cats);
+	return array;
+}
+
+/**
+ * zif_store_remote_get_updates:
+ **/
+static GPtrArray *
+zif_store_remote_get_updates (ZifStore *store, GCancellable *cancellable, ZifCompletion *completion, GError **error)
+{
+	gboolean ret;
+	ZifStore *store_local;
+	GPtrArray *packages;
+	GPtrArray *updates;
+	GPtrArray *array = NULL;
+	ZifPackage *package;
+	ZifPackage *update;
+	GError *error_local = NULL;
+	guint i, j;
+	gint val;
+	const gchar *package_id;
+	const gchar *package_id_update;
+	ZifStoreRemote *remote = ZIF_STORE_REMOTE (store);
+	ZifCompletion *completion_local;
+	gchar **split;
+	gchar **split_update;
+
+	/* not locked */
+	ret = zif_lock_is_locked (remote->priv->lock, NULL);
+	if (!ret) {
+		egg_warning ("not locked");
+		if (error != NULL)
+			*error = g_error_new (1, 0, "not locked");
+		goto out;
+	}
+
+	/* setup completion */
+	if (remote->priv->loaded_metadata)
+		zif_completion_set_number_steps (completion, 2);
+	else
+		zif_completion_set_number_steps (completion, 3);
+
+	/* load metadata */
+	if (!remote->priv->loaded_metadata) {
+		completion_local = zif_completion_get_child (completion);
+		ret = zif_store_remote_load_metadata (remote, cancellable, completion_local, &error_local);
+		if (!ret) {
+			if (error != NULL)
+				*error = g_error_new (1, 0, "failed to load xml: %s", error_local->message);
+			g_error_free (error_local);
+			goto out;
+		}
+
+		/* this section done */
+		zif_completion_done (completion);
+	}
+
+	/* get list of local packages */
+	store_local = ZIF_STORE (zif_store_local_new ());
+	completion_local = zif_completion_get_child (completion);
+	packages = zif_store_get_packages (store_local, cancellable, completion_local, &error_local);
+	if (packages == NULL) {
+		if (error != NULL)
+			*error = g_error_new (1, 0, "failed to get local store: %s", error_local->message);
+		g_error_free (error_local);
+		goto out;
+	}
+	egg_debug ("searching with %i packages", packages->len);
+
+	/* this section done */
+	zif_completion_done (completion);
+
+	/* create array for packages to update */
+	array = g_ptr_array_new_with_free_func ((GDestroyNotify) g_object_unref);
+
+	/* find each one in a remote repo */
+	for (i=0; i<packages->len; i++) {
+		package = ZIF_PACKAGE (g_ptr_array_index (packages, i));
+		package_id = zif_package_get_id (package);
+
+		/* find package name in repo */
+		completion_local = zif_completion_get_child (completion);
+		split = pk_package_id_split (package_id);
+		updates = zif_repo_md_primary_resolve (ZIF_REPO_MD_PRIMARY (remote->priv->md_primary), split[PK_PACKAGE_ID_NAME], cancellable, completion_local, NULL);
+		g_strfreev (split);
+		if (updates == NULL) {
+			egg_debug ("not found %s", split[PK_PACKAGE_ID_NAME]);
+			continue;
+		}
+
+		/* find updates */
+		for (j=0; j<updates->len; j++) {
+			update = ZIF_PACKAGE (g_ptr_array_index (updates, j));
+
+			/* newer? */
+			val = zif_package_compare (update, package);
+			if (val > 0) {
+				package_id_update = zif_package_get_id (update);
+				split = pk_package_id_split (package_id);
+				split_update = pk_package_id_split (package_id_update);
+				egg_debug ("*** update %s from %s to %s", split[PK_PACKAGE_ID_NAME], split[PK_PACKAGE_ID_VERSION], split_update[PK_PACKAGE_ID_VERSION]);
+				g_strfreev (split);
+				g_strfreev (split_update);
+				g_ptr_array_add (array, g_object_ref (update));
+			}
+		}
+		g_ptr_array_unref (updates);
+	}
+
+	/* this section done */
+	zif_completion_done (completion);
+
+	g_ptr_array_unref (packages);
+	g_object_unref (store_local);
+out:
+	return array;
+}
+
+/**
+ * zif_store_remote_what_provides:
+ **/
+static GPtrArray *
+zif_store_remote_what_provides (ZifStore *store, const gchar *search, GCancellable *cancellable, ZifCompletion *completion, GError **error)
+{
+	gboolean ret;
+	GError *error_local = NULL;
+	ZifStoreRemote *remote = ZIF_STORE_REMOTE (store);
+
+	/* not locked */
+	ret = zif_lock_is_locked (remote->priv->lock, NULL);
+	if (!ret) {
+		egg_warning ("not locked");
+		if (error != NULL)
+			*error = g_error_new (1, 0, "not locked");
+		goto out;
+	}
+
+	/* load metadata */
+	if (!remote->priv->loaded_metadata) {
+		ret = zif_store_remote_load_metadata (remote, cancellable, completion, &error_local);
+		if (!ret) {
+			if (error != NULL)
+				*error = g_error_new (1, 0, "failed to load xml: %s", error_local->message);
+			g_error_free (error_local);
+			goto out;
+		}
+	}
+	//FIXME: load other MD
+out:
+	return g_ptr_array_new_with_free_func ((GDestroyNotify) g_object_unref);
+}
+
+/**
+ * zif_store_remote_search_file:
+ **/
+static GPtrArray *
+zif_store_remote_search_file (ZifStore *store, const gchar *search, GCancellable *cancellable, ZifCompletion *completion, GError **error)
+{
+	gboolean ret;
+	GError *error_local = NULL;
+	GPtrArray *pkgids;
+	GPtrArray *array = NULL;
+	GPtrArray *tmp;
+	ZifPackage *package;
+	ZifCompletion *completion_local;
+	const gchar *pkgid;
+	guint i, j;
+	ZifStoreRemote *remote = ZIF_STORE_REMOTE (store);
+
+	/* not locked */
+	ret = zif_lock_is_locked (remote->priv->lock, NULL);
+	if (!ret) {
+		egg_warning ("not locked");
+		if (error != NULL)
+			*error = g_error_new (1, 0, "not locked");
+		goto out;
+	}
+
+	/* setup completion */
+	if (remote->priv->loaded_metadata)
+		zif_completion_set_number_steps (completion, 2);
+	else
+		zif_completion_set_number_steps (completion, 3);
+
+	/* load metadata */
+	if (!remote->priv->loaded_metadata) {
+		completion_local = zif_completion_get_child (completion);
+		ret = zif_store_remote_load_metadata (remote, cancellable, completion_local, &error_local);
+		if (!ret) {
+			if (error != NULL)
+				*error = g_error_new (1, 0, "failed to load xml: %s", error_local->message);
+			g_error_free (error_local);
+			goto out;
+		}
+
+		/* this section done */
+		zif_completion_done (completion);
+	}
+
+	/* gets a list of pkgId's that match this file */
+	completion_local = zif_completion_get_child (completion);
+	pkgids = zif_repo_md_filelists_search_file (ZIF_REPO_MD_FILELISTS (remote->priv->md_filelists), search, cancellable, completion_local, &error_local);
+	if (pkgids == NULL) {
+		if (error != NULL)
+			*error = g_error_new (1, 0, "failed to load get list of pkgids: %s", error_local->message);
+		g_error_free (error_local);
+		goto out;
+	}
+
+	/* this section done */
+	zif_completion_done (completion);
+
+	/* resolve the pkgId to a set of packages */
+	array = g_ptr_array_new_with_free_func ((GDestroyNotify) g_object_unref);
+	for (i=0; i<pkgids->len; i++) {
+		pkgid = g_ptr_array_index (pkgids, i);
+
+		/* get the results (should just be one) */
+		completion_local = zif_completion_get_child (completion);
+		tmp = zif_repo_md_primary_search_pkgid (ZIF_REPO_MD_PRIMARY (remote->priv->md_primary), pkgid, cancellable, completion_local, &error_local);
+		if (tmp == NULL) {
+			if (error != NULL)
+				*error = g_error_new (1, 0, "failed to resolve pkgId to package: %s", error_local->message);
+			g_error_free (error_local);
+			/* free what we've collected already */
+			g_ptr_array_unref (array);
+			array = NULL;
+			goto out;
+		}
+
+		/* add to main array */
+		for (j=0; j<tmp->len; j++) {
+			package = g_ptr_array_index (tmp, j);
+			g_ptr_array_add (array, g_object_ref (package));
+		}
+
+		/* free temp array */
+		g_ptr_array_unref (tmp);
+	}
+
+	/* this section done */
+	zif_completion_done (completion);
+out:
+	return array;
+}
+
+/**
+ * zif_store_remote_is_devel:
+ * @store: the #ZifStoreRemote object
+ * @cancellable: a #GCancellable which is used to cancel tasks, or %NULL
+ * @completion: a #ZifCompletion to use for progress reporting
+ * @error: a #GError which is used on failure, or %NULL
+ *
+ * Finds out if the repository is a development repository.
+ *
+ * Return value: %TRUE or %FALSE
+ **/
+gboolean
+zif_store_remote_is_devel (ZifStoreRemote *store, GCancellable *cancellable, ZifCompletion *completion, GError **error)
+{
+	gboolean ret;
+	GError *error_local = NULL;
+
+	g_return_val_if_fail (ZIF_IS_STORE_REMOTE (store), FALSE);
+	g_return_val_if_fail (store->priv->id != NULL, FALSE);
+
+	/* not locked */
+	ret = zif_lock_is_locked (store->priv->lock, NULL);
+	if (!ret) {
+		egg_warning ("not locked");
+		if (error != NULL)
+			*error = g_error_new (1, 0, "not locked");
+		goto out;
+	}
+
+	/* if not already loaded, load */
+	if (!store->priv->loaded) {
+		ret = zif_store_remote_load (ZIF_STORE (store), cancellable, completion, &error_local);
+		if (!ret) {
+			if (error != NULL)
+				*error = g_error_new (1, 0, "failed to load store file: %s", error_local->message);
+			g_error_free (error_local);
+			goto out;
+		}
+	}
+
+	/* do tests */
+	if (g_str_has_suffix (store->priv->id, "-debuginfo"))
+		return TRUE;
+	if (g_str_has_suffix (store->priv->id, "-testing"))
+		return TRUE;
+	if (g_str_has_suffix (store->priv->id, "-debug"))
+		return TRUE;
+	if (g_str_has_suffix (store->priv->id, "-development"))
+		return TRUE;
+	if (g_str_has_suffix (store->priv->id, "-source"))
+		return TRUE;
+out:
+	return FALSE;
+}
+
+/**
+ * zif_store_remote_get_id:
+ * @store: the #ZifStoreRemote object
+ *
+ * Get the id of this repository.
+ *
+ * Return value: The repository id, e.g. "fedora"
+ **/
+static const gchar *
+zif_store_remote_get_id (ZifStore *store)
+{
+	ZifStoreRemote *remote = ZIF_STORE_REMOTE (store);
+	g_return_val_if_fail (ZIF_IS_STORE_REMOTE (store), NULL);
+	return remote->priv->id;
+}
+
+/**
+ * zif_store_remote_get_name:
+ * @store: the #ZifStoreRemote object
+ * @cancellable: a #GCancellable which is used to cancel tasks, or %NULL
+ * @completion: a #ZifCompletion to use for progress reporting
+ * @error: a #GError which is used on failure, or %NULL
+ *
+ * Get the name of this repository.
+ *
+ * Return value: The repository name, e.g. "Fedora"
+ **/
+const gchar *
+zif_store_remote_get_name (ZifStoreRemote *store, GCancellable *cancellable, ZifCompletion *completion, GError **error)
+{
+	gboolean ret;
+	GError *error_local = NULL;
+
+	g_return_val_if_fail (ZIF_IS_STORE_REMOTE (store), NULL);
+	g_return_val_if_fail (store->priv->id != NULL, NULL);
+
+	/* not locked */
+	ret = zif_lock_is_locked (store->priv->lock, NULL);
+	if (!ret) {
+		egg_warning ("not locked");
+		if (error != NULL)
+			*error = g_error_new (1, 0, "not locked");
+		goto out;
+	}
+
+	/* if not already loaded, load */
+	if (!store->priv->loaded) {
+		ret = zif_store_remote_load (ZIF_STORE (store), cancellable, completion, &error_local);
+		if (!ret) {
+			if (error != NULL)
+				*error = g_error_new (1, 0, "failed to load store file: %s", error_local->message);
+			g_error_free (error_local);
+			goto out;
+		}
+	}
+out:
+	return store->priv->name_expanded;
+}
+
+/**
+ * zif_store_remote_get_enabled:
+ * @store: the #ZifStoreRemote object
+ * @cancellable: a #GCancellable which is used to cancel tasks, or %NULL
+ * @completion: a #ZifCompletion to use for progress reporting
+ * @error: a #GError which is used on failure, or %NULL
+ *
+ * Find out if this repository is enabled or not.
+ *
+ * Return value: %TRUE or %FALSE
+ **/
+gboolean
+zif_store_remote_get_enabled (ZifStoreRemote *store, GCancellable *cancellable, ZifCompletion *completion, GError **error)
+{
+	GError *error_local = NULL;
+	gboolean ret;
+
+	g_return_val_if_fail (ZIF_IS_STORE_REMOTE (store), FALSE);
+	g_return_val_if_fail (store->priv->id != NULL, FALSE);
+
+	/* not locked */
+	ret = zif_lock_is_locked (store->priv->lock, NULL);
+	if (!ret) {
+		egg_warning ("not locked");
+		if (error != NULL)
+			*error = g_error_new (1, 0, "not locked");
+		goto out;
+	}
+
+	/* if not already loaded, load */
+	if (!store->priv->loaded) {
+		ret = zif_store_remote_load (ZIF_STORE (store), cancellable, completion, &error_local);
+		if (!ret) {
+			if (error != NULL)
+				*error = g_error_new (1, 0, "failed to load store file: %s", error_local->message);
+			g_error_free (error_local);
+			goto out;
+		}
+	}
+out:
+	return store->priv->enabled;
+}
+
+/**
+ * zif_store_remote_file_monitor_cb:
+ **/
+static void
+zif_store_remote_file_monitor_cb (ZifMonitor *monitor, ZifStoreRemote *store)
+{
+	/* free invalid data */
+	g_free (store->priv->id);
+	g_free (store->priv->name);
+	g_free (store->priv->name_expanded);
+	g_free (store->priv->repo_filename);
+	g_ptr_array_set_size (store->priv->baseurls, 0);
+	g_free (store->priv->mirrorlist);
+	g_free (store->priv->metalink);
+
+	store->priv->loaded = FALSE;
+	store->priv->loaded_metadata = FALSE;
+	store->priv->enabled = FALSE;
+	store->priv->id = NULL;
+	store->priv->name = NULL;
+	store->priv->name_expanded = NULL;
+	store->priv->repo_filename = NULL;
+	store->priv->mirrorlist = NULL;
+	store->priv->metalink = NULL;
+
+	egg_debug ("store file changed");
+}
+
+/**
+ * zif_store_remote_finalize:
+ **/
+static void
+zif_store_remote_finalize (GObject *object)
+{
+	ZifStoreRemote *store;
+
+	g_return_if_fail (object != NULL);
+	g_return_if_fail (ZIF_IS_STORE_REMOTE (object));
+	store = ZIF_STORE_REMOTE (object);
+
+	g_free (store->priv->id);
+	g_free (store->priv->name);
+	g_free (store->priv->name_expanded);
+	g_free (store->priv->repo_filename);
+	g_free (store->priv->mirrorlist);
+	g_free (store->priv->metalink);
+	g_free (store->priv->cache_dir);
+	g_free (store->priv->repomd_filename);
+	g_free (store->priv->directory);
+
+	g_object_unref (store->priv->md_primary);
+	g_object_unref (store->priv->md_filelists);
+	g_object_unref (store->priv->md_comps);
+	g_object_unref (store->priv->md_metalink);
+	g_object_unref (store->priv->md_mirrorlist);
+	g_object_unref (store->priv->config);
+	g_object_unref (store->priv->monitor);
+	g_object_unref (store->priv->lock);
+
+	g_ptr_array_unref (store->priv->baseurls);
+
+	G_OBJECT_CLASS (zif_store_remote_parent_class)->finalize (object);
+}
+
+/**
+ * zif_store_remote_class_init:
+ **/
+static void
+zif_store_remote_class_init (ZifStoreRemoteClass *klass)
+{
+	GObjectClass *object_class = G_OBJECT_CLASS (klass);
+	ZifStoreClass *store_class = ZIF_STORE_CLASS (klass);
+	object_class->finalize = zif_store_remote_finalize;
+
+	/* map */
+	store_class->load = zif_store_remote_load;
+	store_class->clean = zif_store_remote_clean;
+	store_class->refresh = zif_store_remote_refresh;
+	store_class->search_name = zif_store_remote_search_name;
+	store_class->search_category = zif_store_remote_search_category;
+	store_class->search_details = zif_store_remote_search_details;
+	store_class->search_group = zif_store_remote_search_group;
+	store_class->search_file = zif_store_remote_search_file;
+	store_class->resolve = zif_store_remote_resolve;
+	store_class->what_provides = zif_store_remote_what_provides;
+	store_class->get_packages = zif_store_remote_get_packages;
+	store_class->get_updates = zif_store_remote_get_updates;
+	store_class->find_package = zif_store_remote_find_package;
+	store_class->get_categories = zif_store_remote_get_categories;
+	store_class->get_id = zif_store_remote_get_id;
+	store_class->print = zif_store_remote_print;
+
+	g_type_class_add_private (klass, sizeof (ZifStoreRemotePrivate));
+}
+
+/**
+ * zif_store_remote_init:
+ **/
+static void
+zif_store_remote_init (ZifStoreRemote *store)
+{
+	GError *error = NULL;
+	gchar *cache_dir = NULL;
+
+	store->priv = ZIF_STORE_REMOTE_GET_PRIVATE (store);
+	store->priv->loaded = FALSE;
+	store->priv->loaded_metadata = FALSE;
+	store->priv->id = NULL;
+	store->priv->name = NULL;
+	store->priv->directory = NULL;
+	store->priv->name_expanded = NULL;
+	store->priv->enabled = FALSE;
+	store->priv->repo_filename = NULL;
+	store->priv->baseurls = g_ptr_array_new_with_free_func ((GDestroyNotify) g_free);
+	store->priv->mirrorlist = NULL;
+	store->priv->metalink = NULL;
+	store->priv->config = zif_config_new ();
+	store->priv->monitor = zif_monitor_new ();
+	store->priv->lock = zif_lock_new ();
+	store->priv->md_filelists = ZIF_REPO_MD (zif_repo_md_filelists_new ());
+	store->priv->md_primary = ZIF_REPO_MD (zif_repo_md_primary_new ());
+	store->priv->md_metalink = ZIF_REPO_MD (zif_repo_md_metalink_new ());
+	store->priv->md_mirrorlist = ZIF_REPO_MD (zif_repo_md_mirrorlist_new ());
+	store->priv->md_comps = ZIF_REPO_MD (zif_repo_md_comps_new ());
+	store->priv->parser_type = ZIF_REPO_MD_TYPE_UNKNOWN;
+	store->priv->parser_section = ZIF_STORE_REMOTE_PARSER_SECTION_UNKNOWN;
+	g_signal_connect (store->priv->monitor, "changed", G_CALLBACK (zif_store_remote_file_monitor_cb), store);
+
+	/* get cache */
+	cache_dir = zif_config_get_string (store->priv->config, "cachedir", &error);
+	if (cache_dir == NULL) {
+		egg_error ("failed to get cachedir: %s", error->message);
+		g_error_free (error);
+		goto out;
+	}
+
+	/* expand */
+	store->priv->cache_dir = zif_config_expand_substitutions (store->priv->config, cache_dir, &error);
+	if (store->priv->cache_dir == NULL) {
+		egg_error ("failed to get expand substitutions: %s", error->message);
+		g_error_free (error);
+		goto out;
+	}
+out:
+	g_free (cache_dir);
+}
+
+/**
+ * zif_store_remote_new:
+ *
+ * Return value: A new #ZifStoreRemote class instance.
+ **/
+ZifStoreRemote *
+zif_store_remote_new (void)
+{
+	ZifStoreRemote *store;
+	store = g_object_new (ZIF_TYPE_STORE_REMOTE, NULL);
+	return ZIF_STORE_REMOTE (store);
+}
+
+/***************************************************************************
+ ***                          MAKE CHECK TESTS                           ***
+ ***************************************************************************/
+#ifdef EGG_TEST
+#include "egg-test.h"
+#include "zif-groups.h"
+
+void
+zif_store_remote_test (EggTest *test)
+{
+	ZifGroups *groups;
+	ZifStoreRemote *store;
+	ZifStoreLocal *store_local;
+	ZifConfig *config;
+	ZifLock *lock;
+	ZifCompletion *completion;
+	GPtrArray *array;
+	gboolean ret;
+	GError *error = NULL;
+	const gchar *id;
+	PkCategory *category;
+	guint i;
+
+	if (!egg_test_start (test, "ZifStoreRemote"))
+		return;
+
+	/* set this up as dummy */
+	config = zif_config_new ();
+	zif_config_set_filename (config, "../test/etc/yum.conf", NULL);
+
+	/* use completion object */
+	completion = zif_completion_new ();
+
+	/************************************************************/
+	egg_test_title (test, "get store");
+	store = zif_store_remote_new ();
+	egg_test_assert (test, store != NULL);
+
+	/************************************************************/
+	egg_test_title (test, "get lock");
+	lock = zif_lock_new ();
+	egg_test_assert (test, lock != NULL);
+
+	/************************************************************/
+	egg_test_title (test, "lock");
+	ret = zif_lock_set_locked (lock, NULL, NULL);
+	egg_test_assert (test, ret);
+
+	/************************************************************/
+	egg_test_title (test, "load from a file");
+	zif_completion_reset (completion);
+	ret = zif_store_remote_set_from_file (store, "../test/repos/fedora.repo", "fedora", NULL, completion, &error);
+	if (ret)
+		egg_test_success (test, NULL);
+	else
+		egg_test_failed (test, "failed to load '%s'", error->message);
+
+	/* setup state */
+	groups = zif_groups_new ();
+	zif_groups_set_mapping_file (groups, "../test/share/yum-comps-groups.conf", NULL);
+	store_local = zif_store_local_new ();
+	zif_store_local_set_prefix (store_local, "/", NULL);
+
+	/************************************************************/
+	egg_test_title (test, "get updates");
+	zif_completion_reset (completion);
+	array = zif_store_remote_get_updates (ZIF_STORE (store), NULL, completion, &error);
+	if (array == NULL)
+		egg_test_failed (test, "no data: %s", error->message);
+	else if (array->len > 0)
+		egg_test_success (test, NULL);
+	else
+		egg_test_success (test, "no updates"); //TODO: failure
+	g_ptr_array_unref (array);
+
+	/************************************************************/
+	egg_test_title (test, "is devel");
+	ret = zif_store_remote_is_devel (store, NULL, completion, NULL);
+	egg_test_assert (test, !ret);
+
+	/************************************************************/
+	egg_test_title (test, "is enabled");
+	ret = zif_store_remote_get_enabled (store, NULL, completion, NULL);
+	egg_test_assert (test, ret);
+
+	/************************************************************/
+	egg_test_title (test, "get id");
+	id = zif_store_get_id (ZIF_STORE (store));
+	if (egg_strequal (id, "fedora"))
+		egg_test_success (test, NULL);
+	else
+		egg_test_failed (test, "invalid id '%s'", id);
+
+	/************************************************************/
+	egg_test_title (test, "get name");
+	id = zif_store_remote_get_name (store, NULL, completion, NULL);
+	if (egg_strequal (id, "Fedora 11 - i386"))
+		egg_test_success (test, NULL);
+	else
+		egg_test_failed (test, "invalid name '%s'", id);
+
+	/************************************************************/
+	egg_test_title (test, "load metadata");
+	zif_completion_reset (completion);
+	ret = zif_store_remote_load (ZIF_STORE (store), NULL, completion, &error);
+	if (ret)
+		egg_test_success (test, NULL);
+	else
+		egg_test_failed (test, "failed to load metadata '%s'", error->message);
+
+	/************************************************************/
+	egg_test_title (test, "resolve");
+	zif_completion_reset (completion);
+	array = zif_store_remote_resolve (ZIF_STORE (store), "kernel", NULL, completion, &error);
+	if (array != NULL)
+		egg_test_success (test, NULL);
+	else
+		egg_test_failed (test, "failed to resolve '%s'", error->message);
+
+	/************************************************************/
+	egg_test_title (test, "correct number");
+	if (array->len >= 1)
+		egg_test_success (test, NULL);
+	else
+		egg_test_failed (test, "incorrect length %i", array->len);
+
+	g_ptr_array_unref (array);
+
+	/************************************************************/
+	egg_test_title (test, "search name");
+	zif_completion_reset (completion);
+	array = zif_store_remote_search_name (ZIF_STORE (store), "power-manager", NULL, completion, &error);
+	if (array != NULL)
+		egg_test_success (test, NULL);
+	else
+		egg_test_failed (test, "failed to search name '%s'", error->message);
+
+	/************************************************************/
+	egg_test_title (test, "search name correct number");
+	if (array->len == 3)
+		egg_test_success (test, NULL);
+	else
+		egg_test_failed (test, "incorrect length %i", array->len);
+
+	g_ptr_array_unref (array);
+
+	/************************************************************/
+	egg_test_title (test, "search details");
+	zif_completion_reset (completion);
+	array = zif_store_remote_search_details (ZIF_STORE (store), "browser plugin", NULL, completion, &error);
+	if (array != NULL)
+		egg_test_success (test, NULL);
+	else
+		egg_test_failed (test, "failed to search details '%s'", error->message);
+
+	/************************************************************/
+	egg_test_title (test, "search details correct number");
+	if (array->len == 5)
+		egg_test_success (test, NULL);
+	else
+		egg_test_failed (test, "incorrect length %i", array->len);
+
+	g_ptr_array_unref (array);
+
+	/************************************************************/
+	egg_test_title (test, "search file");
+	zif_completion_reset (completion);
+	array = zif_store_remote_search_file (ZIF_STORE (store), "/usr/bin/gnome-power-manager", NULL, completion, &error);
+	if (array != NULL)
+		egg_test_success (test, NULL);
+	else
+		egg_test_failed (test, "failed to search details '%s'", error->message);
+
+	/************************************************************/
+	egg_test_title (test, "search file correct number");
+	if (array->len == 1)
+		egg_test_success (test, NULL);
+	else
+		egg_test_failed (test, "incorrect length %i", array->len);
+
+	g_ptr_array_unref (array);
+
+	/************************************************************/
+	egg_test_title (test, "set disabled");
+	ret = zif_store_remote_set_enabled (store, FALSE, &error);
+	if (ret)
+		egg_test_success (test, NULL);
+	else
+		egg_test_failed (test, "failed to disable '%s'", error->message);
+
+	/************************************************************/
+	egg_test_title (test, "is enabled");
+	ret = zif_store_remote_get_enabled (store, NULL, completion, NULL);
+	egg_test_assert (test, !ret);
+
+	/************************************************************/
+	egg_test_title (test, "set enabled");
+	ret = zif_store_remote_set_enabled (store, TRUE, &error);
+	if (ret)
+		egg_test_success (test, NULL);
+	else
+		egg_test_failed (test, "failed to enable '%s'", error->message);
+
+	/************************************************************/
+	egg_test_title (test, "is enabled");
+	ret = zif_store_remote_get_enabled (store, NULL, completion, NULL);
+	egg_test_assert (test, ret);
+
+	/************************************************************/
+	egg_test_title (test, "get packages");
+	zif_completion_reset (completion);
+	array = zif_store_remote_get_packages (ZIF_STORE (store), NULL, completion, &error);
+	if (array != NULL)
+		egg_test_success (test, NULL);
+	else
+		egg_test_failed (test, "failed to get packages '%s'", error->message);
+
+	/************************************************************/
+	egg_test_title (test, "correct number");
+	if (array->len > 10000)
+		egg_test_success (test, NULL);
+	else
+		egg_test_failed (test, "incorrect length %i", array->len);
+
+	g_ptr_array_unref (array);
+
+	/************************************************************/
+	egg_test_title (test, "get categories");
+	zif_completion_reset (completion);
+	array = zif_store_remote_get_categories (ZIF_STORE (store), NULL, completion, &error);
+	if (array == NULL)
+		egg_test_failed (test, "no data: %s", error->message);
+	else if (array->len > 0)
+		egg_test_success (test, NULL);
+	else
+		egg_test_failed (test, "no categories"); //TODO: failure
+
+	/* get first object */
+	category = g_ptr_array_index (array, 0);
+
+	/************************************************************/
+	egg_test_title (test, "test parent_id");
+	if (pk_category_get_parent_id (category) == NULL)
+		egg_test_success (test, NULL);
+	else
+		egg_test_failed (test, "incorrect data: %s", pk_category_get_parent_id (category));
+
+	/************************************************************/
+	egg_test_title (test, "test cat_id");
+	if (g_strcmp0 (pk_category_get_id (category), "language-support") == 0)
+		egg_test_success (test, NULL);
+	else
+		egg_test_failed (test, "incorrect data: %s", pk_category_get_id (category));
+
+	/************************************************************/
+	egg_test_title (test, "test name");
+	if (g_strcmp0 (pk_category_get_name (category), "Languages") == 0)
+		egg_test_success (test, NULL);
+	else
+		egg_test_failed (test, "incorrect data: %s", pk_category_get_name (category));
+
+	g_ptr_array_unref (array);
+
+	/************************************************************/
+	egg_test_title (test, "search category");
+	zif_completion_reset (completion);
+	array = zif_store_remote_search_category (ZIF_STORE (store), "admin-tools", NULL, completion, &error);
+	if (array == NULL)
+		egg_test_failed (test, "no data: %s", error->message);
+	else if (array->len > 0)
+		egg_test_success (test, NULL);
+	else
+		egg_test_failed (test, "no results");
+
+	g_ptr_array_unref (array);
+
+	g_object_unref (store);
+	g_object_unref (config);
+	g_object_unref (lock);
+	g_object_unref (completion);
+	g_object_unref (groups);
+	g_object_unref (store_local);
+
+	egg_test_end (test);
+}
+#endif
+
diff --git a/backends/yum/libzif/zif-store-remote.h b/backends/yum/libzif/zif-store-remote.h
new file mode 100644
index 0000000..fe236d8
--- /dev/null
+++ b/backends/yum/libzif/zif-store-remote.h
@@ -0,0 +1,96 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2008 Richard Hughes <richard at hughsie.com>
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#if !defined (__ZIF_H_INSIDE__) && !defined (ZIF_COMPILATION)
+#error "Only <zif.h> can be included directly."
+#endif
+
+#ifndef __ZIF_STORE_REMOTE_H
+#define __ZIF_STORE_REMOTE_H
+
+#include <glib-object.h>
+#include <packagekit-glib2/packagekit.h>
+
+#include "zif-store.h"
+#include "zif-package.h"
+
+G_BEGIN_DECLS
+
+#define ZIF_TYPE_STORE_REMOTE		(zif_store_remote_get_type ())
+#define ZIF_STORE_REMOTE(o)		(G_TYPE_CHECK_INSTANCE_CAST ((o), ZIF_TYPE_STORE_REMOTE, ZifStoreRemote))
+#define ZIF_STORE_REMOTE_CLASS(k)	(G_TYPE_CHECK_CLASS_CAST((k), ZIF_TYPE_STORE_REMOTE, ZifStoreRemoteClass))
+#define ZIF_IS_STORE_REMOTE(o)		(G_TYPE_CHECK_INSTANCE_TYPE ((o), ZIF_TYPE_STORE_REMOTE))
+#define ZIF_IS_STORE_REMOTE_CLASS(k)	(G_TYPE_CHECK_CLASS_TYPE ((k), ZIF_TYPE_STORE_REMOTE))
+#define ZIF_STORE_REMOTE_GET_CLASS(o)	(G_TYPE_INSTANCE_GET_CLASS ((o), ZIF_TYPE_STORE_REMOTE, ZifStoreRemoteClass))
+
+typedef struct _ZifStoreRemote		ZifStoreRemote;
+typedef struct _ZifStoreRemotePrivate	ZifStoreRemotePrivate;
+typedef struct _ZifStoreRemoteClass	ZifStoreRemoteClass;
+
+struct _ZifStoreRemote
+{
+	ZifStore		 parent;
+	ZifStoreRemotePrivate	*priv;
+};
+
+struct _ZifStoreRemoteClass
+{
+	ZifStoreClass		 parent_class;
+};
+
+GType		 zif_store_remote_get_type		(void);
+ZifStoreRemote	*zif_store_remote_new			(void);
+gboolean	 zif_store_remote_set_from_file		(ZifStoreRemote		*store,
+							 const gchar		*filename,
+							 const gchar		*id,
+							 GCancellable		*cancellable,
+							 ZifCompletion		*completion,
+							 GError			**error);
+gboolean	 zif_store_remote_is_devel		(ZifStoreRemote		*store,
+							 GCancellable		*cancellable,
+							 ZifCompletion		*completion,
+							 GError			**error);
+const gchar	*zif_store_remote_get_name		(ZifStoreRemote		*store,
+							 GCancellable		*cancellable,
+							 ZifCompletion		*completion,
+							 GError			**error);
+gboolean	 zif_store_remote_get_enabled		(ZifStoreRemote		*store,
+							 GCancellable		*cancellable,
+							 ZifCompletion		*completion,
+							 GError			**error);
+gboolean	 zif_store_remote_set_enabled		(ZifStoreRemote		*store,
+							 gboolean		 enabled,
+							 GError			**error);
+gboolean	 zif_store_remote_download		(ZifStoreRemote		*store,
+							 const gchar		*filename,
+							 const gchar		*directory,
+							 GCancellable		*cancellable,
+							 ZifCompletion		*completion,
+							 GError			**error);
+gboolean	 zif_store_remote_check			(ZifStoreRemote		*store,
+							 GCancellable		*cancellable,
+							 ZifCompletion		*completion,
+							 GError			**error);
+
+G_END_DECLS
+
+#endif /* __ZIF_STORE_REMOTE_H */
+
diff --git a/backends/yum/libzif/zif-store.c b/backends/yum/libzif/zif-store.c
new file mode 100644
index 0000000..152fd37
--- /dev/null
+++ b/backends/yum/libzif/zif-store.c
@@ -0,0 +1,537 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2008 Richard Hughes <richard at hughsie.com>
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+/**
+ * SECTION:zif-store
+ * @short_description: A store is an abstract collection of packages
+ *
+ * #ZifStoreLocal and #ZifStoreRemote both implement #ZifStore.
+ */
+
+#ifdef HAVE_CONFIG_H
+#  include <config.h>
+#endif
+
+#include <glib.h>
+#include <packagekit-glib2/packagekit.h>
+
+#include "zif-store.h"
+#include "zif-package.h"
+
+#include "egg-debug.h"
+#include "egg-string.h"
+
+G_DEFINE_TYPE (ZifStore, zif_store, G_TYPE_OBJECT)
+
+/**
+ * zif_store_load:
+ * @store: the #ZifStore object
+ * @cancellable: a #GCancellable which is used to cancel tasks, or %NULL
+ * @completion: a #ZifCompletion to use for progress reporting
+ * @error: a #GError which is used on failure, or %NULL
+ *
+ * Loads the #ZifStore object.
+ *
+ * Return value: %TRUE for success, %FALSE for failure
+ **/
+gboolean
+zif_store_load (ZifStore *store, GCancellable *cancellable, ZifCompletion *completion, GError **error)
+{
+	ZifStoreClass *klass = ZIF_STORE_GET_CLASS (store);
+
+	g_return_val_if_fail (ZIF_IS_STORE (store), FALSE);
+
+	/* no support */
+	if (klass->load == NULL) {
+		if (error != NULL)
+			*error = g_error_new (1, 0, "operation cannot be performed on this store");
+		return FALSE;
+	}
+
+	return klass->load (store, cancellable, completion, error);
+}
+
+/**
+ * zif_store_clean:
+ * @store: the #ZifStore object
+ * @cancellable: a #GCancellable which is used to cancel tasks, or %NULL
+ * @completion: a #ZifCompletion to use for progress reporting
+ * @error: a #GError which is used on failure, or %NULL
+ *
+ * Cleans the #ZifStore objects by deleting cache.
+ *
+ * Return value: %TRUE for success, %FALSE for failure
+ **/
+gboolean
+zif_store_clean (ZifStore *store, GCancellable *cancellable, ZifCompletion *completion, GError **error)
+{
+	ZifStoreClass *klass = ZIF_STORE_GET_CLASS (store);
+
+	g_return_val_if_fail (ZIF_IS_STORE (store), FALSE);
+
+	/* no support */
+	if (klass->clean == NULL) {
+		if (error != NULL)
+			*error = g_error_new (1, 0, "operation cannot be performed on this store");
+		return FALSE;
+	}
+
+	return klass->clean (store, cancellable, completion, error);
+}
+
+/**
+ * zif_store_refresh:
+ * @store: the #ZifStore object
+ * @force: if the data should be re-downloaded if it's still valid
+ * @cancellable: a #GCancellable which is used to cancel tasks, or %NULL
+ * @completion: a #ZifCompletion to use for progress reporting
+ * @error: a #GError which is used on failure, or %NULL
+ *
+ * refresh the #ZifStore objects by downloading new data if required.
+ *
+ * Return value: %TRUE for success, %FALSE for failure
+ **/
+gboolean
+zif_store_refresh (ZifStore *store, gboolean force, GCancellable *cancellable, ZifCompletion *completion, GError **error)
+{
+	ZifStoreClass *klass = ZIF_STORE_GET_CLASS (store);
+
+	g_return_val_if_fail (ZIF_IS_STORE (store), FALSE);
+
+	/* no support */
+	if (klass->refresh == NULL) {
+		if (error != NULL)
+			*error = g_error_new (1, 0, "operation cannot be performed on this store");
+		return FALSE;
+	}
+
+	return klass->refresh (store, force, cancellable, completion, error);
+}
+
+/**
+ * zif_store_search_name:
+ * @store: the #ZifStore object
+ * @search: the search term, e.g. "power"
+ * @cancellable: a #GCancellable which is used to cancel tasks, or %NULL
+ * @completion: a #ZifCompletion to use for progress reporting
+ * @error: a #GError which is used on failure, or %NULL
+ *
+ * Find packages that match the package name in some part.
+ *
+ * Return value: an array of #ZifPackage's
+ **/
+GPtrArray *
+zif_store_search_name (ZifStore *store, const gchar *search, GCancellable *cancellable, ZifCompletion *completion, GError **error)
+{
+	ZifStoreClass *klass = ZIF_STORE_GET_CLASS (store);
+
+	g_return_val_if_fail (ZIF_IS_STORE (store), FALSE);
+	g_return_val_if_fail (search != NULL, NULL);
+
+	/* no support */
+	if (klass->search_name == NULL) {
+		if (error != NULL)
+			*error = g_error_new (1, 0, "operation cannot be performed on this store");
+		return FALSE;
+	}
+
+	return klass->search_name (store, search, cancellable, completion, error);
+}
+
+/**
+ * zif_store_search_category:
+ * @store: the #ZifStore object
+ * @search: the search term, e.g. "gnome/games"
+ * @cancellable: a #GCancellable which is used to cancel tasks, or %NULL
+ * @completion: a #ZifCompletion to use for progress reporting
+ * @error: a #GError which is used on failure, or %NULL
+ *
+ * Return packages in a specific category.
+ *
+ * Return value: an array of #ZifPackage's
+ **/
+GPtrArray *
+zif_store_search_category (ZifStore *store, const gchar *search, GCancellable *cancellable, ZifCompletion *completion, GError **error)
+{
+	ZifStoreClass *klass = ZIF_STORE_GET_CLASS (store);
+
+	g_return_val_if_fail (ZIF_IS_STORE (store), FALSE);
+	g_return_val_if_fail (search != NULL, NULL);
+
+	/* no support */
+	if (klass->search_category == NULL) {
+		if (error != NULL)
+			*error = g_error_new (1, 0, "operation cannot be performed on this store");
+		return FALSE;
+	}
+
+	return klass->search_category (store, search, cancellable, completion, error);
+}
+
+/**
+ * zif_store_search_details:
+ * @store: the #ZifStore object
+ * @search: the search term, e.g. "trouble"
+ * @cancellable: a #GCancellable which is used to cancel tasks, or %NULL
+ * @completion: a #ZifCompletion to use for progress reporting
+ * @error: a #GError which is used on failure, or %NULL
+ *
+ * Find packages that match some detail about the package.
+ *
+ * Return value: an array of #ZifPackage's
+ **/
+GPtrArray *
+zif_store_search_details (ZifStore *store, const gchar *search, GCancellable *cancellable, ZifCompletion *completion, GError **error)
+{
+	ZifStoreClass *klass = ZIF_STORE_GET_CLASS (store);
+
+	g_return_val_if_fail (ZIF_IS_STORE (store), FALSE);
+	g_return_val_if_fail (search != NULL, NULL);
+
+	/* no support */
+	if (klass->search_details == NULL) {
+		if (error != NULL)
+			*error = g_error_new (1, 0, "operation cannot be performed on this store");
+		return FALSE;
+	}
+
+	return klass->search_details (store, search, cancellable, completion, error);
+}
+
+/**
+ * zif_store_search_group:
+ * @store: the #ZifStore object
+ * @search: the search term, e.g. "games"
+ * @cancellable: a #GCancellable which is used to cancel tasks, or %NULL
+ * @completion: a #ZifCompletion to use for progress reporting
+ * @error: a #GError which is used on failure, or %NULL
+ *
+ * Find packages that belong in a specific group.
+ *
+ * Return value: an array of #ZifPackage's
+ **/
+GPtrArray *
+zif_store_search_group (ZifStore *store, const gchar *search, GCancellable *cancellable, ZifCompletion *completion, GError **error)
+{
+	ZifStoreClass *klass = ZIF_STORE_GET_CLASS (store);
+
+	g_return_val_if_fail (ZIF_IS_STORE (store), FALSE);
+	g_return_val_if_fail (search != NULL, NULL);
+
+	/* no support */
+	if (klass->search_group == NULL) {
+		if (error != NULL)
+			*error = g_error_new (1, 0, "operation cannot be performed on this store");
+		return FALSE;
+	}
+
+	return klass->search_group (store, search, cancellable, completion, error);
+}
+
+/**
+ * zif_store_search_file:
+ * @store: the #ZifStore object
+ * @search: the search term, e.g. "/usr/bin/gnome-power-manager"
+ * @cancellable: a #GCancellable which is used to cancel tasks, or %NULL
+ * @completion: a #ZifCompletion to use for progress reporting
+ * @error: a #GError which is used on failure, or %NULL
+ *
+ * Find packages that provide the specified file.
+ *
+ * Return value: an array of #ZifPackage's
+ **/
+GPtrArray *
+zif_store_search_file (ZifStore *store, const gchar *search, GCancellable *cancellable, ZifCompletion *completion, GError **error)
+{
+	ZifStoreClass *klass = ZIF_STORE_GET_CLASS (store);
+
+	g_return_val_if_fail (ZIF_IS_STORE (store), FALSE);
+	g_return_val_if_fail (search != NULL, NULL);
+
+	/* no support */
+	if (klass->search_file == NULL) {
+		if (error != NULL)
+			*error = g_error_new (1, 0, "operation cannot be performed on this store");
+		return FALSE;
+	}
+
+	return klass->search_file (store, search, cancellable, completion, error);
+}
+
+/**
+ * zif_store_resolve:
+ * @store: the #ZifStore object
+ * @search: the search term, e.g. "gnome-power-manager"
+ * @cancellable: a #GCancellable which is used to cancel tasks, or %NULL
+ * @completion: a #ZifCompletion to use for progress reporting
+ * @error: a #GError which is used on failure, or %NULL
+ *
+ * Finds packages matching the package name exactly.
+ *
+ * Return value: an array of #ZifPackage's
+ **/
+GPtrArray *
+zif_store_resolve (ZifStore *store, const gchar *search, GCancellable *cancellable, ZifCompletion *completion, GError **error)
+{
+	ZifStoreClass *klass = ZIF_STORE_GET_CLASS (store);
+
+	g_return_val_if_fail (ZIF_IS_STORE (store), FALSE);
+	g_return_val_if_fail (search != NULL, NULL);
+
+	/* no support */
+	if (klass->resolve == NULL) {
+		if (error != NULL)
+			*error = g_error_new (1, 0, "operation cannot be performed on this store");
+		return FALSE;
+	}
+
+	return klass->resolve (store, search, cancellable, completion, error);
+}
+
+/**
+ * zif_store_what_provides:
+ * @store: the #ZifStore object
+ * @search: the search term, e.g. "gstreamer(codec-mp3)"
+ * @cancellable: a #GCancellable which is used to cancel tasks, or %NULL
+ * @completion: a #ZifCompletion to use for progress reporting
+ * @error: a #GError which is used on failure, or %NULL
+ *
+ * Find packages that provide a specific string.
+ *
+ * Return value: an array of #ZifPackage's
+ **/
+GPtrArray *
+zif_store_what_provides (ZifStore *store, const gchar *search, GCancellable *cancellable, ZifCompletion *completion, GError **error)
+{
+	ZifStoreClass *klass = ZIF_STORE_GET_CLASS (store);
+
+	g_return_val_if_fail (ZIF_IS_STORE (store), FALSE);
+	g_return_val_if_fail (search != NULL, NULL);
+
+	/* no support */
+	if (klass->search_name == NULL) {
+		if (error != NULL)
+			*error = g_error_new (1, 0, "operation cannot be performed on this store");
+		return FALSE;
+	}
+
+	return klass->what_provides (store, search, cancellable, completion, error);
+}
+
+/**
+ * zif_store_get_packages:
+ * @store: the #ZifStore object
+ * @cancellable: a #GCancellable which is used to cancel tasks, or %NULL
+ * @completion: a #ZifCompletion to use for progress reporting
+ * @error: a #GError which is used on failure, or %NULL
+ *
+ * Return all packages in the #ZifSack's.
+ *
+ * Return value: an array of #ZifPackage's
+ **/
+GPtrArray *
+zif_store_get_packages (ZifStore *store, GCancellable *cancellable, ZifCompletion *completion, GError **error)
+{
+	ZifStoreClass *klass = ZIF_STORE_GET_CLASS (store);
+
+	g_return_val_if_fail (ZIF_IS_STORE (store), FALSE);
+
+	/* no support */
+	if (klass->get_packages == NULL) {
+		if (error != NULL)
+			*error = g_error_new (1, 0, "operation cannot be performed on this store");
+		return FALSE;
+	}
+
+	return klass->get_packages (store, cancellable, completion, error);
+}
+
+/**
+ * zif_store_get_updates:
+ * @store: the #ZifStore object
+ * @cancellable: a #GCancellable which is used to cancel tasks, or %NULL
+ * @completion: a #ZifCompletion to use for progress reporting
+ * @error: a #GError which is used on failure, or %NULL
+ *
+ * Return a list of packages that are updatable.
+ *
+ * Return value: an array of #ZifPackage's
+ **/
+GPtrArray *
+zif_store_get_updates (ZifStore *store, GCancellable *cancellable, ZifCompletion *completion, GError **error)
+{
+	ZifStoreClass *klass = ZIF_STORE_GET_CLASS (store);
+
+	g_return_val_if_fail (ZIF_IS_STORE (store), FALSE);
+
+	/* no support */
+	if (klass->get_updates == NULL) {
+		if (error != NULL)
+			*error = g_error_new (1, 0, "operation cannot be performed on this store");
+		return FALSE;
+	}
+
+	return klass->get_updates (store, cancellable, completion, error);
+}
+
+/**
+ * zif_store_find_package:
+ * @store: the #ZifStore object
+ * @package_id: the package ID which defines the package
+ * @cancellable: a #GCancellable which is used to cancel tasks, or %NULL
+ * @completion: a #ZifCompletion to use for progress reporting
+ * @error: a #GError which is used on failure, or %NULL
+ *
+ * Find a single package in the #ZifSack.
+ *
+ * Return value: A single #ZifPackage or %NULL
+ **/
+ZifPackage *
+zif_store_find_package (ZifStore *store, const gchar *package_id, GCancellable *cancellable, ZifCompletion *completion, GError **error)
+{
+	ZifStoreClass *klass = ZIF_STORE_GET_CLASS (store);
+
+	g_return_val_if_fail (ZIF_IS_STORE (store), FALSE);
+	g_return_val_if_fail (package_id != NULL, NULL);
+
+	/* no support */
+	if (klass->find_package == NULL) {
+		if (error != NULL)
+			*error = g_error_new (1, 0, "operation cannot be performed on this store");
+		return FALSE;
+	}
+
+	return klass->find_package (store, package_id, cancellable, completion, error);
+}
+
+/**
+ * zif_store_get_categories:
+ * @store: the #ZifStore object
+ * @cancellable: a #GCancellable which is used to cancel tasks, or %NULL
+ * @completion: a #ZifCompletion to use for progress reporting
+ * @error: a #GError which is used on failure, or %NULL
+ *
+ * Return a list of custom categories.
+ *
+ * Return value: an array of #PkCategory's
+ **/
+GPtrArray *
+zif_store_get_categories (ZifStore *store, GCancellable *cancellable, ZifCompletion *completion, GError **error)
+{
+	ZifStoreClass *klass = ZIF_STORE_GET_CLASS (store);
+
+	g_return_val_if_fail (ZIF_IS_STORE (store), FALSE);
+
+	/* no support */
+	if (klass->get_categories == NULL) {
+		if (error != NULL)
+			*error = g_error_new (1, 0, "operation cannot be performed on this store");
+		return FALSE;
+	}
+
+	return klass->get_categories (store, cancellable, completion, error);
+}
+
+/**
+ * zif_store_get_id:
+ * @store: the #ZifStore object
+ *
+ * Gets the id for the object.
+ *
+ * Return value: A text ID, or %NULL
+ **/
+const gchar *
+zif_store_get_id (ZifStore *store)
+{
+	ZifStoreClass *klass = ZIF_STORE_GET_CLASS (store);
+
+	g_return_val_if_fail (ZIF_IS_STORE (store), NULL);
+
+	/* no support */
+	if (klass->get_id == NULL)
+		return NULL;
+
+	return klass->get_id (store);
+}
+
+/**
+ * zif_store_print:
+ * @store: the #ZifStore object
+ *
+ * Prints all the objects in the store.
+ **/
+void
+zif_store_print (ZifStore *store)
+{
+	ZifStoreClass *klass = ZIF_STORE_GET_CLASS (store);
+
+	g_return_if_fail (ZIF_IS_STORE (store));
+
+	/* no support */
+	if (klass->print == NULL)
+		return;
+
+	klass->print (store);
+}
+
+/**
+ * zif_store_finalize:
+ **/
+static void
+zif_store_finalize (GObject *object)
+{
+	g_return_if_fail (object != NULL);
+	g_return_if_fail (ZIF_IS_STORE (object));
+
+	G_OBJECT_CLASS (zif_store_parent_class)->finalize (object);
+}
+
+/**
+ * zif_store_class_init:
+ **/
+static void
+zif_store_class_init (ZifStoreClass *klass)
+{
+	GObjectClass *object_class = G_OBJECT_CLASS (klass);
+	object_class->finalize = zif_store_finalize;
+}
+
+/**
+ * zif_store_init:
+ **/
+static void
+zif_store_init (ZifStore *store)
+{
+}
+
+/**
+ * zif_store_new:
+ *
+ * Return value: A new #ZifStore class instance.
+ **/
+ZifStore *
+zif_store_new (void)
+{
+	ZifStore *store;
+	store = g_object_new (ZIF_TYPE_STORE, NULL);
+	return ZIF_STORE (store);
+}
+
diff --git a/backends/yum/libzif/zif-store.h b/backends/yum/libzif/zif-store.h
new file mode 100644
index 0000000..c4aa869
--- /dev/null
+++ b/backends/yum/libzif/zif-store.h
@@ -0,0 +1,201 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2008 Richard Hughes <richard at hughsie.com>
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#if !defined (__ZIF_H_INSIDE__) && !defined (ZIF_COMPILATION)
+#error "Only <zif.h> can be included directly."
+#endif
+
+#ifndef __ZIF_STORE_H
+#define __ZIF_STORE_H
+
+#include <glib-object.h>
+#include <gio/gio.h>
+#include <packagekit-glib2/packagekit.h>
+
+#include "zif-package.h"
+#include "zif-completion.h"
+
+G_BEGIN_DECLS
+
+#define ZIF_TYPE_STORE		(zif_store_get_type ())
+#define ZIF_STORE(o)		(G_TYPE_CHECK_INSTANCE_CAST ((o), ZIF_TYPE_STORE, ZifStore))
+#define ZIF_STORE_CLASS(k)	(G_TYPE_CHECK_CLASS_CAST((k), ZIF_TYPE_STORE, ZifStoreClass))
+#define ZIF_IS_STORE(o)		(G_TYPE_CHECK_INSTANCE_TYPE ((o), ZIF_TYPE_STORE))
+#define ZIF_IS_STORE_CLASS(k)	(G_TYPE_CHECK_CLASS_TYPE ((k), ZIF_TYPE_STORE))
+#define ZIF_STORE_GET_CLASS(o)	(G_TYPE_INSTANCE_GET_CLASS ((o), ZIF_TYPE_STORE, ZifStoreClass))
+
+typedef struct _ZifStore	ZifStore;
+typedef struct _ZifStorePrivate	ZifStorePrivate;
+typedef struct _ZifStoreClass	ZifStoreClass;
+
+struct _ZifStore
+{
+	GObject			 parent;
+	ZifStorePrivate		*priv;
+};
+
+struct _ZifStoreClass
+{
+	GObjectClass	parent_class;
+	/* vtable */
+	gboolean	 (*load)		(ZifStore		*store,
+						 GCancellable		*cancellable,
+						 ZifCompletion		*completion,
+						 GError			**error);
+	gboolean	 (*clean)		(ZifStore		*store,
+						 GCancellable		*cancellable,
+						 ZifCompletion		*completion,
+						 GError			**error);
+	gboolean	 (*refresh)		(ZifStore		*store,
+						 gboolean		 force,
+						 GCancellable		*cancellable,
+						 ZifCompletion		*completion,
+						 GError			**error);
+	GPtrArray	*(*search_name)		(ZifStore		*store,
+						 const gchar		*search,
+						 GCancellable		*cancellable,
+						 ZifCompletion		*completion,
+						 GError			**error);
+	GPtrArray	*(*search_category)	(ZifStore		*store,
+						 const gchar		*search,
+						 GCancellable		*cancellable,
+						 ZifCompletion		*completion,
+						 GError			**error);
+	GPtrArray	*(*search_details)	(ZifStore		*store,
+						 const gchar		*search,
+						 GCancellable		*cancellable,
+						 ZifCompletion		*completion,
+						 GError			**error);
+	GPtrArray	*(*search_group)	(ZifStore		*store,
+						 const gchar		*search,
+						 GCancellable		*cancellable,
+						 ZifCompletion		*completion,
+						 GError			**error);
+	GPtrArray	*(*search_file)		(ZifStore		*store,
+						 const gchar		*search,
+						 GCancellable		*cancellable,
+						 ZifCompletion		*completion,
+						 GError			**error);
+	GPtrArray	*(*resolve)		(ZifStore		*store,
+						 const gchar		*search,
+						 GCancellable		*cancellable,
+						 ZifCompletion		*completion,
+						 GError			**error);
+	GPtrArray	*(*what_provides)	(ZifStore		*store,
+						 const gchar		*search,
+						 GCancellable		*cancellable,
+						 ZifCompletion		*completion,
+						 GError			**error);
+	GPtrArray	*(*get_packages)	(ZifStore		*store,
+						 GCancellable		*cancellable,
+						 ZifCompletion		*completion,
+						 GError			**error);
+	GPtrArray	*(*get_updates)		(ZifStore		*store,
+						 GCancellable		*cancellable,
+						 ZifCompletion		*completion,
+						 GError			**error);
+	ZifPackage	*(*find_package)	(ZifStore		*store,
+						 const gchar		*package_id,
+						 GCancellable		*cancellable,
+						 ZifCompletion		*completion,
+						 GError			**error);
+	GPtrArray	*(*get_categories)	(ZifStore		*store,
+						 GCancellable		*cancellable,
+						 ZifCompletion		*completion,
+						 GError			**error);
+	const gchar	*(*get_id)		(ZifStore		*store);
+	void		 (*print)		(ZifStore		*store);
+};
+
+GType		 zif_store_get_type		(void);
+ZifStore	*zif_store_new			(void);
+gboolean	 zif_store_load			(ZifStore		*store,
+						 GCancellable		*cancellable,
+						 ZifCompletion		*completion,
+						 GError			**error);
+gboolean	 zif_store_clean		(ZifStore		*store,
+						 GCancellable		*cancellable,
+						 ZifCompletion		*completion,
+						 GError			**error);
+gboolean	 zif_store_refresh		(ZifStore		*store,
+						 gboolean		 force,
+						 GCancellable		*cancellable,
+						 ZifCompletion		*completion,
+						 GError			**error);
+GPtrArray	*zif_store_search_name		(ZifStore		*store,
+						 const gchar		*search,
+						 GCancellable		*cancellable,
+						 ZifCompletion		*completion,
+						 GError			**error);
+GPtrArray	*zif_store_search_category	(ZifStore		*store,
+						 const gchar		*search,
+						 GCancellable		*cancellable,
+						 ZifCompletion		*completion,
+						 GError			**error);
+GPtrArray	*zif_store_search_details	(ZifStore		*store,
+						 const gchar		*search,
+						 GCancellable		*cancellable,
+						 ZifCompletion		*completion,
+						 GError			**error);
+GPtrArray	*zif_store_search_group		(ZifStore		*store,
+						 const gchar		*search,
+						 GCancellable		*cancellable,
+						 ZifCompletion		*completion,
+						 GError			**error);
+GPtrArray	*zif_store_search_file		(ZifStore		*store,
+						 const gchar		*search,
+						 GCancellable		*cancellable,
+						 ZifCompletion		*completion,
+						 GError			**error);
+GPtrArray	*zif_store_resolve		(ZifStore		*store,
+						 const gchar		*search,
+						 GCancellable		*cancellable,
+						 ZifCompletion		*completion,
+						 GError			**error);
+GPtrArray	*zif_store_what_provides	(ZifStore		*store,
+						 const gchar		*search,
+						 GCancellable		*cancellable,
+						 ZifCompletion		*completion,
+						 GError			**error);
+GPtrArray	*zif_store_get_packages		(ZifStore		*store,
+						 GCancellable		*cancellable,
+						 ZifCompletion		*completion,
+						 GError			**error);
+GPtrArray	*zif_store_get_updates		(ZifStore		*store,
+						 GCancellable		*cancellable,
+						 ZifCompletion		*completion,
+						 GError			**error);
+ZifPackage	*zif_store_find_package		(ZifStore		*store,
+						 const gchar		*package_id,
+						 GCancellable		*cancellable,
+						 ZifCompletion		*completion,
+						 GError			**error);
+GPtrArray	*zif_store_get_categories	(ZifStore		*store,
+						 GCancellable		*cancellable,
+						 ZifCompletion		*completion,
+						 GError			**error);
+const gchar	*zif_store_get_id		(ZifStore		*store);
+void		 zif_store_print		(ZifStore		*store);
+
+G_END_DECLS
+
+#endif /* __ZIF_STORE_H */
+
diff --git a/backends/yum/libzif/zif-string.c b/backends/yum/libzif/zif-string.c
new file mode 100644
index 0000000..9d429b6
--- /dev/null
+++ b/backends/yum/libzif/zif-string.c
@@ -0,0 +1,187 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2009 Richard Hughes <richard at hughsie.com>
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+/**
+ * SECTION:zif-string
+ * @short_description: Create and manage reference counted strings
+ *
+ * To avoid frequent malloc/free, we use reference counted strings to
+ * optimise many of the zif internals.
+ */
+
+#ifdef HAVE_CONFIG_H
+#  include <config.h>
+#endif
+
+#include <glib.h>
+
+#include "egg-debug.h"
+
+#include "zif-utils.h"
+#include "zif-string.h"
+
+/* private structure */
+struct ZifString {
+	gchar		*value;
+	guint		 count;
+};
+
+/**
+ * zif_string_new:
+ * @value: string to copy
+ *
+ * Creates a new referenced counted string
+ *
+ * Return value: New allocated object
+ **/
+ZifString *
+zif_string_new (const gchar *value)
+{
+	ZifString *string;
+	string = g_new0 (ZifString, 1);
+	string->count = 1;
+	string->value = g_strdup (value);
+	return string;
+}
+
+/**
+ * zif_string_new_value:
+ * @value: string to use
+ *
+ * Creates a new referenced counted string, using the allocated memory.
+ * Do not free this string as it is now owned by the #ZifString.
+ *
+ * Return value: New allocated object
+ **/
+ZifString *
+zif_string_new_value (gchar *value)
+{
+	ZifString *string;
+	string = g_new0 (ZifString, 1);
+	string->count = 1;
+	string->value = value;
+	return string;
+}
+
+/**
+ * zif_string_get_value:
+ * @string: the #ZifString object
+ *
+ * Returns the string stored in the #ZifString.
+ * This value is only valid while the #ZifString's reference count > 1.
+ *
+ * Return value: string value
+ **/
+const gchar *
+zif_string_get_value (ZifString *string)
+{
+	g_return_val_if_fail (string != NULL, NULL);
+	return string->value;
+}
+
+/**
+ * zif_string_ref:
+ * @string: the #ZifString object
+ *
+ * Increases the reference count on the object.
+ *
+ * Return value: the #ZifString object
+ **/
+ZifString *
+zif_string_ref (ZifString *string)
+{
+	g_return_val_if_fail (string != NULL, NULL);
+	string->count++;
+	return string;
+}
+
+/**
+ * zif_string_unref:
+ * @string: the #ZifString object
+ *
+ * Decreses the reference count on the object, and frees the value if
+ * it calls to zero.
+ *
+ * Return value: the #ZifString object
+ **/
+ZifString *
+zif_string_unref (ZifString *string)
+{
+	if (string == NULL)
+		zif_debug_crash ();
+
+	g_return_val_if_fail (string != NULL, NULL);
+	string->count--;
+	if (string->count == 0) {
+		g_free (string->value);
+		g_free (string);
+		string = NULL;
+	}
+	return string;
+}
+
+/***************************************************************************
+ ***                          MAKE CHECK TESTS                           ***
+ ***************************************************************************/
+#ifdef EGG_TEST
+#include "egg-test.h"
+
+void
+zif_string_test (EggTest *test)
+{
+	ZifString *string;
+	const gchar *value;
+
+	if (!egg_test_start (test, "ZifString"))
+		return;
+
+	/************************************************************/
+	egg_test_title (test, "create");
+	string = zif_string_new ("kernel");
+	if (g_strcmp0 (string->value, "kernel") == 0 && string->count == 1)
+		egg_test_success (test, NULL);
+	else
+		egg_test_failed (test, "incorrect value %s:%i", string->value, string->count);
+
+	/************************************************************/
+	egg_test_title (test, "ref");
+	zif_string_ref (string);
+	egg_test_assert (test, string->count == 2);
+
+	/************************************************************/
+	egg_test_title (test, "unref");
+	zif_string_unref (string);
+	egg_test_assert (test, string->count == 1);
+
+	/************************************************************/
+	egg_test_title (test, "get value");
+	value = zif_string_get_value (string);
+	egg_test_assert (test, (g_strcmp0 (value, "kernel") == 0));
+
+	/************************************************************/
+	egg_test_title (test, "unref");
+	string = zif_string_unref (string);
+	egg_test_assert (test, string == NULL);
+
+	egg_test_end (test);
+}
+#endif
+
diff --git a/backends/yum/libzif/zif-string.h b/backends/yum/libzif/zif-string.h
new file mode 100644
index 0000000..6205c93
--- /dev/null
+++ b/backends/yum/libzif/zif-string.h
@@ -0,0 +1,44 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2009 Richard Hughes <richard at hughsie.com>
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#if !defined (__ZIF_H_INSIDE__) && !defined (ZIF_COMPILATION)
+#error "Only <zif.h> can be included directly."
+#endif
+
+#ifndef __ZIF_STRING_H
+#define __ZIF_STRING_H
+
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+typedef struct ZifString ZifString;
+
+ZifString	*zif_string_new			(const gchar	*value);
+ZifString	*zif_string_new_value		(gchar		*value);
+ZifString	*zif_string_ref			(ZifString	*string);
+ZifString	*zif_string_unref		(ZifString	*string);
+const gchar	*zif_string_get_value		(ZifString	*string);
+
+G_END_DECLS
+
+#endif /* __ZIF_STRING_H */
+
diff --git a/backends/yum/libzif/zif-utils.c b/backends/yum/libzif/zif-utils.c
new file mode 100644
index 0000000..de2eaa7
--- /dev/null
+++ b/backends/yum/libzif/zif-utils.c
@@ -0,0 +1,761 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2008 Richard Hughes <richard at hughsie.com>
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+/**
+ * SECTION:zif-utils
+ * @short_description: Simple utility functions useful to zif
+ *
+ * Common, non-object functions are declared here.
+ */
+
+#ifdef HAVE_CONFIG_H
+#  include <config.h>
+#endif
+
+#include <glib.h>
+#include <rpm/rpmlib.h>
+#include <rpm/rpmdb.h>
+#include <archive.h>
+#include <archive_entry.h>
+#include <bzlib.h>
+#include <zlib.h>
+#include <packagekit-glib2/packagekit.h>
+
+#include "egg-debug.h"
+#include "egg-string.h"
+
+#include "zif-utils.h"
+#include "zif-package.h"
+
+#define ZIF_CRASH_DEBUG
+
+/**
+ * zif_init:
+ *
+ * This must be called before any of the zif_* functions are called.
+ *
+ * Return value: %TRUE if we initialised correctly
+ **/
+gboolean
+zif_init (void)
+{
+	gint retval;
+
+	retval = rpmReadConfigFiles (NULL, NULL);
+	if (retval != 0) {
+		egg_warning ("failed to read config files");
+		return FALSE;
+	}
+
+	return TRUE;
+}
+
+/**
+ * zif_debug_crash:
+ *
+ * Does a null dereference, useful for debugging.
+ **/
+void
+zif_debug_crash (void)
+{
+#ifdef ZIF_CRASH_DEBUG
+	GString *string = NULL;
+	string->str = NULL;
+#endif
+}
+
+/**
+ * zif_boolean_from_text:
+ * @text: the input text
+ *
+ * Convert a text boolean into it's enumerated boolean state
+ *
+ * Return value: %TRUE for positive, %FALSE for negative
+ **/
+gboolean
+zif_boolean_from_text (const gchar *text)
+{
+	g_return_val_if_fail (text != NULL, FALSE);
+	if (g_ascii_strcasecmp (text, "true") == 0 ||
+	    g_ascii_strcasecmp (text, "yes") == 0 ||
+	    g_ascii_strcasecmp (text, "1") == 0)
+		return TRUE;
+	return FALSE;
+}
+
+/**
+ * zif_list_print_array:
+ * @array: The string array to print
+ *
+ * Print an array of strings to %STDOUT.
+ **/
+void
+zif_list_print_array (GPtrArray *array)
+{
+	guint i;
+	ZifPackage *package;
+
+	for (i=0;i<array->len;i++) {
+		package = g_ptr_array_index (array, i);
+		zif_package_print (package);
+	}
+}
+
+/**
+ * zif_package_id_from_header:
+ * @name: The package name, e.g. "hal"
+ * @epoch: The package epoch, e.g. "1" or %NULL
+ * @version: The package version, e.g. "1.0.0"
+ * @release: The package release, e.g. "2"
+ * @arch: The package architecture, e.g. "i386"
+ * @data: The package data, typically the repo name, or "installed"
+ *
+ * Formats a PackageId structure from a NEVRA.
+ *
+ * Return value: The PackageId value, or %NULL if invalid
+ **/
+gchar *
+zif_package_id_from_nevra (const gchar *name, const gchar *epoch, const gchar *version, const gchar *release, const gchar *arch, const gchar *data)
+{
+	gchar *version_compound;
+	gchar *package_id;
+
+	/* do we include an epoch? */
+	if (epoch == NULL || epoch[0] == '0')
+		version_compound = g_strdup_printf ("%s-%s", version, release);
+	else
+		version_compound = g_strdup_printf ("%s:%s-%s", epoch, version, release);
+
+	package_id = pk_package_id_build (name, version_compound, arch, data);
+	g_free (version_compound);
+	return package_id;
+}
+
+/**
+ * zif_package_convert_evr:
+ *
+ * Modifies evr, so pass in copy
+ **/
+static gboolean
+zif_package_convert_evr (gchar *evr, const gchar **epoch, const gchar **version, const gchar **release)
+{
+	gchar *find;
+
+	g_return_val_if_fail (evr != NULL, FALSE);
+
+	/* set to NULL initially */
+	*version = NULL;
+
+	/* split possible epoch */
+	find = strstr (evr, ":");
+	if (find != NULL) {
+		*find = '\0';
+		*epoch = evr;
+		*version = find+1;
+	} else {
+		*epoch = NULL;
+		*version = evr;
+	}
+
+	/* split possible release */
+	find = g_strrstr (*version, "-");
+	if (find != NULL) {
+		*find = '\0';
+		*release = find+1;
+	} else {
+		*release = NULL;
+	}
+
+	return TRUE;
+}
+
+/**
+ * zif_compare_evr:
+ * @a: the first version string
+ * @b: the second version string
+ *
+ * Compare two [epoch:]version[-release] strings
+ *
+ * Return value: 1 for a>b, 0 for a==b, -1 for b>a
+ **/
+gint
+zif_compare_evr (const gchar *a, const gchar *b)
+{
+	gint val = 0;
+	gchar *ad = NULL;
+	gchar *bd = NULL;
+	const gchar *ae, *av, *ar;
+	const gchar *be, *bv, *br;
+
+	g_return_val_if_fail (a != NULL, 0);
+	g_return_val_if_fail (b != NULL, 0);
+
+	/* exactly the same, optimise */
+	if (strcmp (a, b) == 0)
+		goto out;
+
+	/* copy */
+	ad = g_strdup (a);
+	bd = g_strdup (b);
+
+	/* split */
+	zif_package_convert_evr (ad, &ae, &av, &ar);
+	zif_package_convert_evr (bd, &be, &bv, &br);
+
+	/* compare epoch */
+	if (ae != NULL && be != NULL) {
+		val = rpmvercmp (ae, be);
+		if (val != 0)
+			goto out;
+	} else if (ae != NULL && atol (ae) > 0) {
+		val = 1;
+		goto out;
+	} else if (be != NULL && atol (be) > 0) {
+		val = -1;
+		goto out;
+	}
+
+	/* compare version */
+	val = rpmvercmp (av, bv);
+	if (val != 0)
+		goto out;
+
+	/* compare release */
+	if (ar != NULL && br != NULL)
+		val = rpmvercmp (ar, br);
+
+out:
+	g_free (ad);
+	g_free (bd);
+	return val;
+}
+
+#define ZIF_BUFFER_SIZE 16384
+
+/**
+ * zif_file_decompress_zlib:
+ **/
+static gboolean
+zif_file_decompress_zlib (const gchar *in, const gchar *out, GCancellable *cancellable, ZifCompletion *completion, GError **error)
+{
+	gboolean ret = FALSE;
+	gint size;
+	gint written;
+	gzFile *f_in = NULL;
+	FILE *f_out = NULL;
+	guchar buf[ZIF_BUFFER_SIZE];
+
+	g_return_val_if_fail (in != NULL, FALSE);
+	g_return_val_if_fail (out != NULL, FALSE);
+
+	/* open file for reading */
+	f_in = gzopen (in, "rb");
+	if (f_in == NULL) {
+		if (error != NULL)
+			*error = g_error_new (1, 0, "cannot open %s for reading", in);
+		goto out;
+	}
+
+	/* open file for writing */
+	f_out = fopen (out, "w");
+	if (f_out == NULL) {
+		if (error != NULL)
+			*error = g_error_new (1, 0, "cannot open %s for writing", out);
+		goto out;
+	}
+
+	/* read in all data in chunks */
+	while (TRUE) {
+		/* read data */
+		size = gzread (f_in, buf, ZIF_BUFFER_SIZE);
+		if (size == 0)
+			break;
+
+		/* error */
+		if (size < 0) {
+			if (error != NULL)
+				*error = g_error_new (1, 0, "failed read");
+			goto out;
+		}
+
+		/* write data */
+		written = fwrite (buf, 1, size, f_out);
+		if (written != size) {
+			if (error != NULL)
+				*error = g_error_new (1, 0, "only wrote %i/%i bytes", written, size);
+			goto out;
+		}
+
+		/* is cancelled */
+		ret = !g_cancellable_is_cancelled (cancellable);
+		if (!ret) {
+			if (error != NULL)
+				*error = g_error_new (1, 0, "cancelled");
+			goto out;
+		}
+	}
+
+	/* success */
+	ret = TRUE;
+out:
+	if (f_in != NULL)
+		gzclose (f_in);
+	if (f_out != NULL)
+		fclose (f_out);
+	return ret;
+}
+
+/**
+ * zif_file_decompress_bz2:
+ **/
+static gboolean
+zif_file_decompress_bz2 (const gchar *in, const gchar *out, GCancellable *cancellable, ZifCompletion *completion, GError **error)
+{
+	gboolean ret = FALSE;
+	FILE *f_in = NULL;
+	FILE *f_out = NULL;
+	BZFILE *b = NULL;
+	gint size;
+	gint written;
+	gchar buf[ZIF_BUFFER_SIZE];
+	gint bzerror = BZ_OK;
+
+	g_return_val_if_fail (in != NULL, FALSE);
+	g_return_val_if_fail (out != NULL, FALSE);
+
+	/* open file for reading */
+	f_in = fopen (in, "r");
+	if (f_in == NULL) {
+		if (error != NULL)
+			*error = g_error_new (1, 0, "cannot open %s for reading", in);
+		goto out;
+	}
+
+	/* open file for writing */
+	f_out = fopen (out, "w");
+	if (f_out == NULL) {
+		if (error != NULL)
+			*error = g_error_new (1, 0, "cannot open %s for writing", out);
+		goto out;
+	}
+
+	/* read in file */
+	b = BZ2_bzReadOpen (&bzerror, f_in, 0, 0, NULL, 0);
+	if (bzerror != BZ_OK) {
+		if (error != NULL)
+			*error = g_error_new (1, 0, "cannot open %s for bz2 reading", in);
+		goto out;
+	}
+
+	/* read in all data in chunks */
+	while (bzerror != BZ_STREAM_END) {
+		/* read data */
+		size = BZ2_bzRead (&bzerror, b, buf, ZIF_BUFFER_SIZE);
+		if (bzerror != BZ_OK && bzerror != BZ_STREAM_END) {
+			if (error != NULL)
+				*error = g_error_new (1, 0, "failed to decompress");
+			goto out;
+		}
+
+		/* write data */
+		written = fwrite (buf, 1, size, f_out);
+		if (written != size) {
+			if (error != NULL)
+				*error = g_error_new (1, 0, "only wrote %i/%i bytes", written, size);
+			goto out;
+		}
+
+		/* is cancelled */
+		ret = !g_cancellable_is_cancelled (cancellable);
+		if (!ret) {
+			if (error != NULL)
+				*error = g_error_new (1, 0, "cancelled");
+			goto out;
+		}
+	}
+
+	/* failed to read */
+	if (bzerror != BZ_STREAM_END) {
+		if (error != NULL)
+			*error = g_error_new (1, 0, "did not decompress file: %s", in);
+		goto out;
+	}
+
+	/* success */
+	ret = TRUE;
+out:
+	if (b != NULL)
+		BZ2_bzReadClose (&bzerror, b);
+	if (f_in != NULL)
+		fclose (f_in);
+	if (f_out != NULL)
+		fclose (f_out);
+	return ret;
+}
+
+/**
+ * zif_file_decompress:
+ * @in: the filename to unpack
+ * @out: the file to create
+ * @cancellable: a #GCancellable which is used to cancel tasks, or %NULL
+ * @completion: a #ZifCompletion to use for progress reporting
+ * @error: a valid %GError
+ *
+ * Decompress files into a directory
+ *
+ * Return value: %TRUE if the file was decompressed
+ **/
+gboolean
+zif_file_decompress (const gchar *in, const gchar *out, GCancellable *cancellable, ZifCompletion *completion, GError **error)
+{
+	gboolean ret = FALSE;
+
+	g_return_val_if_fail (in != NULL, FALSE);
+	g_return_val_if_fail (out != NULL, FALSE);
+
+	/* bz2 */
+	if (g_str_has_suffix (in, "bz2")) {
+		ret = zif_file_decompress_bz2 (in, out, cancellable, completion, error);
+		goto out;
+	}
+
+	/* zlib */
+	if (g_str_has_suffix (in, "gz")) {
+		ret = zif_file_decompress_zlib (in, out, cancellable, completion, error);
+		goto out;
+	}
+
+	/* no support */
+	if (error != NULL)
+		*error = g_error_new (1, 0, "no support to decompress file: %s", in);
+out:
+	return ret;
+}
+
+/**
+ * zif_file_untar:
+ * @filename: the filename to unpack
+ * @directory: the directory to unpack into
+ * @error: a valid %GError
+ *
+ * Untar files into a directory
+ *
+ * Return value: %TRUE if the file was decompressed
+ **/
+gboolean
+zif_file_untar (const gchar *filename, const gchar *directory, GError **error)
+{
+	gboolean ret = FALSE;
+	struct archive *arch = NULL;
+	struct archive_entry *entry;
+	int r;
+	int retval;
+	gchar *retcwd;
+	gchar buf[PATH_MAX];
+
+	g_return_val_if_fail (filename != NULL, FALSE);
+	g_return_val_if_fail (directory != NULL, FALSE);
+
+	/* save the PWD as we chdir to extract */
+	retcwd = getcwd (buf, PATH_MAX);
+	if (retcwd == NULL) {
+		*error = g_error_new (1, 0, "failed to get cwd");
+		goto out;
+	}
+
+	/* we can only read tar achives */
+	arch = archive_read_new ();
+	archive_read_support_format_all (arch);
+	archive_read_support_compression_all (arch);
+
+	/* open the tar file */
+	r = archive_read_open_file (arch, filename, ZIF_BUFFER_SIZE);
+	if (r) {
+		*error = g_error_new (1, 0, "cannot open: %s", archive_error_string (arch));
+		goto out;
+	}
+
+	/* switch to our destination directory */
+	retval = chdir (directory);
+	if (retval != 0) {
+		*error = g_error_new (1, 0, "failed chdir to %s", directory);
+		goto out;
+	}
+
+	/* decompress each file */
+	for (;;) {
+		r = archive_read_next_header (arch, &entry);
+		if (r == ARCHIVE_EOF)
+			break;
+		if (r != ARCHIVE_OK) {
+			*error = g_error_new (1, 0, "cannot read header: %s", archive_error_string (arch));
+			goto out;
+		}
+		r = archive_read_extract (arch, entry, 0);
+		if (r != ARCHIVE_OK) {
+			*error = g_error_new (1, 0, "cannot extract: %s", archive_error_string (arch));
+			goto out;
+		}
+	}
+
+	/* completed all okay */
+	ret = TRUE;
+out:
+	/* close the archive */
+	if (arch != NULL) {
+		archive_read_close (arch);
+		archive_read_finish (arch);
+	}
+
+	/* switch back to PWD */
+	retval = chdir (buf);
+	if (retval != 0)
+		egg_warning ("cannot chdir back!");
+
+	return ret;
+}
+
+/**
+ * zif_file_get_uncompressed_name:
+ * @filename: the filename, e.g. /lib/dave.tar.gz
+ *
+ * Finds the uncompressed filename.
+ *
+ * Return value: the uncompressed file name, e.g. /lib/dave.tar, use g_free() to free.
+ **/
+gchar *
+zif_file_get_uncompressed_name (const gchar *filename)
+{
+	guint len;
+	gchar *tmp;
+
+	g_return_val_if_fail (filename != NULL, NULL);
+
+	/* remove compression extension */
+	tmp = g_strdup (filename);
+	len = strlen (tmp);
+	if (len > 4 && g_str_has_suffix (tmp, ".gz"))
+		tmp[len-3] = '\0';
+	else if (len > 5 && g_str_has_suffix (tmp, ".bz2"))
+		tmp[len-4] = '\0';
+
+	/* return newly allocated string */
+	return tmp;
+}
+
+/**
+ * zif_file_is_compressed_name:
+ * @filename: the filename, e.g. /lib/dave.tar.gz
+ *
+ * Finds out if the filename is compressed
+ *
+ * Return value: %TRUE if the file needs decompression
+ **/
+gboolean
+zif_file_is_compressed_name (const gchar *filename)
+{
+	g_return_val_if_fail (filename != NULL, FALSE);
+
+	if (g_str_has_suffix (filename, ".gz"))
+		return TRUE;
+	if (g_str_has_suffix (filename, ".bz2"))
+		return TRUE;
+
+	return FALSE;
+}
+
+/***************************************************************************
+ ***                          MAKE CHECK TESTS                           ***
+ ***************************************************************************/
+#ifdef EGG_TEST
+#include "egg-test.h"
+
+void
+zif_utils_test (EggTest *test)
+{
+	gchar *package_id;
+	gboolean ret;
+	gchar *evr;
+	gint val;
+	const gchar *e;
+	const gchar *v;
+	const gchar *r;
+	gchar *filename;
+	GError *error;
+	GCancellable *cancellable;
+	ZifCompletion *completion;
+
+	if (!egg_test_start (test, "ZifUtils"))
+		return;
+
+	cancellable = g_cancellable_new ();
+	completion = zif_completion_new ();
+
+	/************************************************************
+	 ****************           NEVRA          ******************
+	 ************************************************************/
+	egg_test_title (test, "no epoch");
+	package_id = zif_package_id_from_nevra ("kernel", NULL, "0.0.1", "1", "i386", "fedora");
+	if (egg_strequal (package_id, "kernel;0.0.1-1;i386;fedora"))
+		egg_test_success (test, NULL);
+	else
+		egg_test_failed (test, "incorrect package_id '%s'", package_id);
+	g_free (package_id);
+
+	/************************************************************/
+	egg_test_title (test, "epoch zero");
+	package_id = zif_package_id_from_nevra ("kernel", "0", "0.0.1", "1", "i386", "fedora");
+	if (egg_strequal (package_id, "kernel;0.0.1-1;i386;fedora"))
+		egg_test_success (test, NULL);
+	else
+		egg_test_failed (test, "incorrect package_id '%s'", package_id);
+	g_free (package_id);
+
+	/************************************************************/
+	egg_test_title (test, "epoch value");
+	package_id = zif_package_id_from_nevra ("kernel", "2", "0.0.1", "1", "i386", "fedora");
+	if (egg_strequal (package_id, "kernel;2:0.0.1-1;i386;fedora"))
+		egg_test_success (test, NULL);
+	else
+		egg_test_failed (test, "incorrect package_id '%s'", package_id);
+	g_free (package_id);
+
+	/************************************************************/
+	egg_test_title (test, "init");
+	ret = zif_init ();
+	egg_test_assert (test, ret);
+
+	/************************************************************/
+	egg_test_title (test, "bool to text true (1)");
+	ret = zif_boolean_from_text ("1");
+	egg_test_assert (test, ret);
+
+	/************************************************************/
+	egg_test_title (test, "bool to text true (2)");
+	ret = zif_boolean_from_text ("TRUE");
+	egg_test_assert (test, ret);
+
+	/************************************************************/
+	egg_test_title (test, "bool to text false");
+	ret = zif_boolean_from_text ("false");
+	egg_test_assert (test, !ret);
+
+	/************************************************************/
+	egg_test_title (test, "bool to text blank");
+	ret = zif_boolean_from_text ("");
+	egg_test_assert (test, !ret);
+
+	/************************************************************/
+	egg_test_title (test, "convert evr");
+	evr = g_strdup ("7:1.0.0-6");
+	zif_package_convert_evr (evr, &e, &v, &r);
+	if (egg_strequal (e, "7") && egg_strequal (v, "1.0.0") && egg_strequal (r, "6"))
+		egg_test_success (test, NULL);
+	else
+		egg_test_failed (test, "incorrect evr '%s','%s','%s'", e, v, r);
+	g_free (evr);
+
+	/************************************************************/
+	egg_test_title (test, "convert evr no epoch");
+	evr = g_strdup ("1.0.0-6");
+	zif_package_convert_evr (evr, &e, &v, &r);
+	if (e == NULL && egg_strequal (v, "1.0.0") && egg_strequal (r, "6"))
+		egg_test_success (test, NULL);
+	else
+		egg_test_failed (test, "incorrect evr '%s','%s','%s'", e, v, r);
+	g_free (evr);
+
+	/************************************************************/
+	egg_test_title (test, "convert evr no epoch or release");
+	evr = g_strdup ("1.0.0");
+	zif_package_convert_evr (evr, &e, &v, &r);
+	if (e == NULL && egg_strequal (v, "1.0.0") && r == NULL)
+		egg_test_success (test, NULL);
+	else
+		egg_test_failed (test, "incorrect evr '%s','%s','%s'", e, v, r);
+	g_free (evr);
+
+	/************************************************************/
+	egg_test_title (test, "compare same");
+	val = zif_compare_evr ("1:1.0.2-3", "1:1.0.2-3");
+	egg_test_assert (test, (val == 0));
+
+	/************************************************************/
+	egg_test_title (test, "compare right heavy");
+	val = zif_compare_evr ("1:1.0.2-3", "1:1.0.2-4");
+	egg_test_assert (test, (val == -1));
+
+	/************************************************************/
+	egg_test_title (test, "compare new release");
+	val = zif_compare_evr ("1:1.0.2-4", "1:1.0.2-3");
+	egg_test_assert (test, (val == 1));
+
+	/************************************************************/
+	egg_test_title (test, "compare new epoch");
+	val = zif_compare_evr ("1:0.0.1-1", "1.0.2-2");
+	egg_test_assert (test, (val == 1));
+
+	/************************************************************/
+	egg_test_title (test, "compare new version");
+	val = zif_compare_evr ("1.0.2-1", "1.0.1-1");
+	egg_test_assert (test, (val == 1));
+
+	/************************************************************/
+	egg_test_title (test, "get uncompressed name from compressed");
+	filename = zif_file_get_uncompressed_name ("/dave/moo.sqlite.gz");
+	egg_test_assert (test, (g_strcmp0 (filename, "/dave/moo.sqlite") == 0));
+	g_free (filename);
+
+	/************************************************************/
+	egg_test_title (test, "get uncompressed name from uncompressed");
+	filename = zif_file_get_uncompressed_name ("/dave/moo.sqlite");
+	egg_test_assert (test, (g_strcmp0 (filename, "/dave/moo.sqlite") == 0));
+	g_free (filename);
+
+	/************************************************************/
+	egg_test_title (test, "decompress gz");
+	ret = zif_file_decompress ("../test/cache/fedora/cf940a26805152e5f675edd695022d890241aba057a4a4a97a0b46618a51c482-comps-rawhide.xml.gz",
+				   "/tmp/comps-rawhide.xml", cancellable, completion, &error);
+	if (ret)
+		egg_test_success (test, NULL);
+	else {
+		egg_test_failed (test, "failed: %s", error->message);
+		g_error_free (error);
+	}
+
+	/************************************************************/
+	egg_test_title (test, "decompress bz2");
+	ret = zif_file_decompress ("../test/cache/fedora/35d817e2bac701525fa72cec57387a2e3457bf32642adeee1e345cc180044c86-primary.sqlite.bz2",
+				   "/tmp/moo.sqlite", cancellable, completion, &error);
+	if (ret)
+		egg_test_success (test, NULL);
+	else {
+		egg_test_failed (test, "failed: %s", error->message);
+		g_error_free (error);
+	}
+
+	g_object_unref (cancellable);
+	g_object_unref (completion);
+
+	egg_test_end (test);
+}
+#endif
+
diff --git a/backends/yum/libzif/zif-utils.h b/backends/yum/libzif/zif-utils.h
new file mode 100644
index 0000000..b33c73a
--- /dev/null
+++ b/backends/yum/libzif/zif-utils.h
@@ -0,0 +1,63 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2008 Richard Hughes <richard at hughsie.com>
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#if !defined (__ZIF_H_INSIDE__) && !defined (ZIF_COMPILATION)
+#error "Only <zif.h> can be included directly."
+#endif
+
+#ifndef __ZIF_UTILS_H
+#define __ZIF_UTILS_H
+
+#include <gio/gio.h>
+#include <glib-object.h>
+#include <packagekit-glib2/packagekit.h>
+
+#include "zif-completion.h"
+
+G_BEGIN_DECLS
+
+gboolean	 zif_init			(void);
+void		 zif_debug_crash		(void);
+void		 zif_list_print_array		(GPtrArray	*array);
+gchar		*zif_package_id_from_nevra	(const gchar	*name,
+						 const gchar	*epoch,
+						 const gchar	*version,
+						 const gchar	*release,
+						 const gchar	*arch,
+						 const gchar	*data);
+gboolean	 zif_boolean_from_text		(const gchar	*text);
+gint		 zif_compare_evr		(const gchar	*a,
+						 const gchar	*b);
+gboolean	 zif_file_untar			(const gchar	*filename,
+						 const gchar	*directory,
+						 GError		**error);
+gboolean	 zif_file_decompress		(const gchar	*in,
+						 const gchar	*out,
+						 GCancellable	*cancellable,
+						 ZifCompletion	*completion,
+						 GError		**error);
+gchar		*zif_file_get_uncompressed_name	(const gchar	*filename);
+gboolean	 zif_file_is_compressed_name	(const gchar	*filename);
+
+G_END_DECLS
+
+#endif /* __ZIF_UTILS_H */
+
diff --git a/backends/yum/libzif/zif.h b/backends/yum/libzif/zif.h
new file mode 100644
index 0000000..9f54105
--- /dev/null
+++ b/backends/yum/libzif/zif.h
@@ -0,0 +1,38 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2008 Richard Hughes <richard at hughsie.com>
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef __ZIF_H
+#define __ZIF_H
+
+#define __ZIF_H_INSIDE__
+
+#include <zif-config.h>
+#include <zif-completion.h>
+#include <zif-string.h>
+#include <zif-package.h>
+#include <zif-utils.h>
+#include <zif-download.h>
+#include <zif-lock.h>
+
+#undef __ZIF_H_INSIDE__
+
+#endif /* __ZIF_H */
+
commit a633c7b3ec6f85e06fb52e438fa48d4269efcd14
Author: Richard Hughes <richard at hughsie.com>
Date:   Mon Mar 8 15:57:17 2010 +0000

    Fix reporting distribution upgrades by setting the correct property in two places

diff --git a/lib/packagekit-glib2/pk-client.c b/lib/packagekit-glib2/pk-client.c
index 7905410..f10972f 100644
--- a/lib/packagekit-glib2/pk-client.c
+++ b/lib/packagekit-glib2/pk-client.c
@@ -1138,17 +1138,17 @@ pk_client_transaction_cb (DBusGProxy *proxy, const gchar *tid, const gchar *time
  * pk_client_distro_upgrade_cb:
  */
 static void
-pk_client_distro_upgrade_cb (DBusGProxy *proxy, const gchar *type_text, const gchar *name,
+pk_client_distro_upgrade_cb (DBusGProxy *proxy, const gchar *state_text, const gchar *name,
 			     const gchar *summary, PkClientState *state)
 {
-	PkUpdateStateEnum type_enum;
+	PkUpdateStateEnum state_enum;
 	PkDistroUpgrade *item;
-	type_enum = pk_update_state_enum_from_string (type_text);
+	state_enum = pk_update_state_enum_from_string (state_text);
 
 	/* add to results */
 	item = pk_distro_upgrade_new ();
 	g_object_set (item,
-		      "type", type_enum,
+		      "state", state_enum,
 		      "name", name,
 		      "summary", summary,
 		      "role", state->role,
diff --git a/src/pk-backend.c b/src/pk-backend.c
index b7d7093..409e4a4 100644
--- a/src/pk-backend.c
+++ b/src/pk-backend.c
@@ -1427,7 +1427,7 @@ out:
  * pk_backend_distro_upgrade:
  **/
 gboolean
-pk_backend_distro_upgrade (PkBackend *backend, PkDistroUpgradeEnum type, const gchar *name, const gchar *summary)
+pk_backend_distro_upgrade (PkBackend *backend, PkDistroUpgradeEnum state, const gchar *name, const gchar *summary)
 {
 	gboolean ret = FALSE;
 	gchar *name_safe = NULL;
@@ -1435,7 +1435,7 @@ pk_backend_distro_upgrade (PkBackend *backend, PkDistroUpgradeEnum type, const g
 	PkDistroUpgrade *item = NULL;
 
 	g_return_val_if_fail (PK_IS_BACKEND (backend), FALSE);
-	g_return_val_if_fail (type != PK_DISTRO_UPGRADE_ENUM_UNKNOWN, FALSE);
+	g_return_val_if_fail (state != PK_DISTRO_UPGRADE_ENUM_UNKNOWN, FALSE);
 	g_return_val_if_fail (name != NULL, FALSE);
 	g_return_val_if_fail (summary != NULL, FALSE);
 	g_return_val_if_fail (backend->priv->locked != FALSE, FALSE);
@@ -1453,7 +1453,7 @@ pk_backend_distro_upgrade (PkBackend *backend, PkDistroUpgradeEnum type, const g
 	/* form PkDistroUpgrade struct */
 	item = pk_distro_upgrade_new ();
 	g_object_set (item,
-		      "type", type,
+		      "state", state,
 		      "name", name_safe,
 		      "summary", summary_safe,
 		      NULL);
diff --git a/src/pk-backend.h b/src/pk-backend.h
index d55dc76..700699d 100644
--- a/src/pk-backend.h
+++ b/src/pk-backend.h
@@ -129,7 +129,7 @@ gboolean 	 pk_backend_distro_upgrade		(PkBackend 	*backend,
 							 const gchar 	*name,
 							 const gchar 	*summary);
 gboolean	 pk_backend_error_code			(PkBackend	*backend,
-							 PkErrorEnum code,
+							 PkErrorEnum	 code,
 							 const gchar	*details, ...);
 gboolean         pk_backend_repo_signature_required	(PkBackend      *backend,
 							 const gchar	*package_id,
commit 19926d4ce04e1c693c1468323c354b5cdb6da756
Author: Richard Hughes <richard at hughsie.com>
Date:   Mon Mar 8 11:25:30 2010 +0000

    When realpath fails, do not silently fail but return with an error

diff --git a/lib/packagekit-glib2/pk-client.c b/lib/packagekit-glib2/pk-client.c
index f010425..7905410 100644
--- a/lib/packagekit-glib2/pk-client.c
+++ b/lib/packagekit-glib2/pk-client.c
@@ -299,10 +299,10 @@ pk_client_real_path (const gchar *path)
 }
 
 /**
- * pk_client_real_paths:
+ * pk_client_convert_real_paths:
  **/
 static gchar **
-pk_client_real_paths (gchar **paths)
+pk_client_convert_real_paths (gchar **paths, GError **error)
 {
 	guint i;
 	guint len;
@@ -313,8 +313,17 @@ pk_client_real_paths (gchar **paths)
 	res = g_new0 (gchar *, len+1);
 
 	/* resolve each path */
-	for (i=0; i<len; i++)
+	for (i=0; i<len; i++) {
 		res[i] = pk_client_real_path (paths[i]);
+		if (res[i] == NULL) {
+			/* set an error, and abort, tearing down all our hard work */
+			g_set_error (error, PK_CLIENT_ERROR, PK_CLIENT_ERROR_INVALID_INPUT, "could not resolve: %s", paths[i]);
+			g_strfreev (res);
+			res = NULL;
+			goto out;
+		}
+	}
+out:
 	return res;
 }
 
@@ -3137,6 +3146,7 @@ pk_client_install_files_async (PkClient *client, gboolean only_trusted, gchar **
 	PkClientState *state;
 	gboolean ret;
 	guint i;
+	GError *error = NULL;
 
 	g_return_if_fail (PK_IS_CLIENT (client));
 	g_return_if_fail (callback_ready != NULL);
@@ -3154,12 +3164,19 @@ pk_client_install_files_async (PkClient *client, gboolean only_trusted, gchar **
 		state->cancellable_id = g_cancellable_connect (cancellable, G_CALLBACK (pk_client_cancellable_cancel_cb), state, NULL);
 	}
 	state->only_trusted = only_trusted;
-	state->files = pk_client_real_paths (files);
 	state->progress_callback = progress_callback;
 	state->progress_user_data = progress_user_data;
 	state->progress = pk_progress_new ();
 	pk_client_set_role (state, state->role);
 
+	/* check files are valid */
+	state->files = pk_client_convert_real_paths (files, &error);
+	if (state->files == NULL) {
+		pk_client_state_finish (state, error);
+		g_error_free (error);
+		goto out;
+	}
+
 	/* how many non-native */
 	for (i=0; state->files[i] != NULL; i++) {
 		ret = pk_client_is_file_native (state->files[i]);
@@ -3446,6 +3463,7 @@ pk_client_simulate_install_files_async (PkClient *client, gchar **files, GCancel
 	PkClientState *state;
 	gboolean ret;
 	guint i;
+	GError *error = NULL;
 
 	g_return_if_fail (PK_IS_CLIENT (client));
 	g_return_if_fail (callback_ready != NULL);
@@ -3462,13 +3480,20 @@ pk_client_simulate_install_files_async (PkClient *client, gchar **files, GCancel
 		state->cancellable = g_object_ref (cancellable);
 		state->cancellable_id = g_cancellable_connect (cancellable, G_CALLBACK (pk_client_cancellable_cancel_cb), state, NULL);
 	}
-	state->files = pk_client_real_paths (files);
 
 	state->progress_callback = progress_callback;
 	state->progress_user_data = progress_user_data;
 	state->progress = pk_progress_new ();
 	pk_client_set_role (state, state->role);
 
+	/* check files are valid */
+	state->files = pk_client_convert_real_paths (files, &error);
+	if (state->files == NULL) {
+		pk_client_state_finish (state, error);
+		g_error_free (error);
+		goto out;
+	}
+
 	/* how many non-native */
 	for (i=0; state->files[i] != NULL; i++) {
 		ret = pk_client_is_file_native (state->files[i]);
commit 59b9e5821d3332cc24a86a44ac3d4d63978f67d0
Merge: 0951895... 2f7e5c6...
Author: Scott Parkerson <scott.parkerson at gmail.com>
Date:   Sat Mar 6 21:12:19 2010 -0500

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

commit 2f7e5c6a4708b22037094426e270f5e81106ab1d
Author: Richard Hughes <richard at hughsie.com>
Date:   Thu Mar 4 13:11:40 2010 +0000

    Fix a nasty segfault if the library check-restart code tries to emit a restart-required

diff --git a/src/pk-transaction-extra.c b/src/pk-transaction-extra.c
index 3099edc..9d1b4b6 100644
--- a/src/pk-transaction-extra.c
+++ b/src/pk-transaction-extra.c
@@ -68,7 +68,6 @@ struct PkTransactionExtraPrivate
 enum {
 	PK_POST_TRANS_STATUS_CHANGED,
 	PK_POST_TRANS_PROGRESS_CHANGED,
-	PK_POST_TRANS_REQUIRE_RESTART,
 	PK_POST_TRANS_LAST_SIGNAL
 };
 
@@ -95,16 +94,6 @@ pk_transaction_extra_package_cb (PkBackend *backend, PkPackage *package, PkTrans
 }
 
 /**
- * pk_transaction_extra_set_require_restart:
- **/
-static void
-pk_transaction_extra_set_require_restart (PkTransactionExtra *extra, PkRestartEnum restart, const gchar *package_id)
-{
-	egg_debug ("emit require-restart %s, %s", pk_restart_enum_to_string (restart), package_id);
-	g_signal_emit (extra, signals [PK_POST_TRANS_REQUIRE_RESTART], 0, restart, package_id);
-}
-
-/**
  * pk_transaction_extra_set_status_changed:
  **/
 static void
@@ -871,7 +860,7 @@ pk_transaction_extra_check_library_restart (PkTransactionExtra *extra)
 			egg_debug ("failed to find package for %s", filename);
 			continue;
 		}
-		pk_transaction_extra_set_require_restart (extra, PK_RESTART_ENUM_SECURITY_SESSION, pk_package_get_id (package));
+		pk_backend_require_restart (extra->priv->backend, PK_RESTART_ENUM_SECURITY_SESSION, pk_package_get_id (package));
 	}
 
 	/* process all system restarts */
@@ -883,7 +872,7 @@ pk_transaction_extra_check_library_restart (PkTransactionExtra *extra)
 			egg_debug ("failed to find package for %s", filename);
 			continue;
 		}
-		pk_transaction_extra_set_require_restart (extra, PK_RESTART_ENUM_SECURITY_SYSTEM, pk_package_get_id (package));
+		pk_backend_require_restart (extra->priv->backend, PK_RESTART_ENUM_SECURITY_SYSTEM, pk_package_get_id (package));
 	}
 
 out:
@@ -1174,11 +1163,6 @@ pk_transaction_extra_class_init (PkTransactionExtraClass *klass)
 			      G_TYPE_FROM_CLASS (object_class), G_SIGNAL_RUN_LAST,
 			      0, NULL, NULL, pk_marshal_VOID__UINT_UINT_UINT_UINT,
 			      G_TYPE_NONE, 4, G_TYPE_UINT, G_TYPE_UINT, G_TYPE_UINT, G_TYPE_UINT);
-	signals [PK_POST_TRANS_REQUIRE_RESTART] =
-		g_signal_new ("require-restart",
-			      G_TYPE_FROM_CLASS (object_class), G_SIGNAL_RUN_LAST,
-			      0, NULL, NULL, pk_marshal_VOID__UINT_STRING,
-			      G_TYPE_NONE, 2, G_TYPE_UINT, G_TYPE_STRING);
 	g_type_class_add_private (klass, sizeof (PkTransactionExtraPrivate));
 }
 
diff --git a/src/pk-transaction.c b/src/pk-transaction.c
index 10f03b9..0a4aafa 100644
--- a/src/pk-transaction.c
+++ b/src/pk-transaction.c
@@ -5441,8 +5441,6 @@ pk_transaction_init (PkTransaction *transaction)
 			  G_CALLBACK (pk_transaction_status_changed_cb), transaction);
 	g_signal_connect (transaction->priv->transaction_extra, "progress-changed",
 			  G_CALLBACK (pk_transaction_progress_changed_cb), transaction);
-	g_signal_connect (transaction->priv->transaction_extra, "require-restart",
-			  G_CALLBACK (pk_transaction_require_restart_cb), transaction);
 
 	transaction->priv->transaction_db = pk_transaction_db_new ();
 	g_signal_connect (transaction->priv->transaction_db, "transaction",
commit 7ec02d79bc535f87932a8654bcb2ceacd6917499
Author: Fabio Erculiani <lxnay at sabayon.org>
Date:   Wed Mar 3 19:42:37 2010 +0100

    entropy: fix up the backend as the filters string is now a list, not a delimited string

diff --git a/backends/entropy/entropyBackend.py b/backends/entropy/entropyBackend.py
index 911c7cf..a89e2ea 100755
--- a/backends/entropy/entropyBackend.py
+++ b/backends/entropy/entropyBackend.py
@@ -246,13 +246,12 @@ class PackageKitEntropyMixin(object):
         Filter pkgs list given PackageKit filters.
         """
         inst_pkgs_repo_id = PackageKitEntropyMixin.INST_PKGS_REPO_ID
-        fltlist = filters.split(';')
 
-        if FILTER_INSTALLED in fltlist:
+        if FILTER_INSTALLED in filters:
             pkgs = set([x for x in pkgs if x[0] == inst_pkgs_repo_id])
-        elif FILTER_NOT_INSTALLED in fltlist:
+        elif FILTER_NOT_INSTALLED in filters:
             pkgs = set([x for x in pkgs if x[0] != inst_pkgs_repo_id])
-        if FILTER_FREE in fltlist:
+        if FILTER_FREE in filters:
             pkgs = set([x for x in pkgs if \
                 self._entropy.is_entropy_package_free(x[1], x[0])])
 
@@ -1040,8 +1039,7 @@ class PackageKitEntropyBackend(PackageKitBaseBackend, PackageKitEntropyMixin):
             devel = repo_id != default_repo
             metadata.append((repo_id, desc, enabled, devel))
 
-        fltlist = filters.split(';')
-        if FILTER_NOT_DEVELOPMENT in fltlist:
+        if FILTER_NOT_DEVELOPMENT in filters:
             metadata = [x for x in metadata if not x[3]]
 
         for repo_id, desc, enabled, devel in metadata:
commit cb35f934d693a20c318cb3e09963e42be74cfe13
Author: Anders F Bjorklund <afb at users.sourceforge.net>
Date:   Wed Mar 3 16:21:56 2010 +0100

    smart: convert filters string to array

diff --git a/backends/smart/smartBackend.py b/backends/smart/smartBackend.py
index 91c0b49..d26a1c9 100755
--- a/backends/smart/smartBackend.py
+++ b/backends/smart/smartBackend.py
@@ -1176,8 +1176,7 @@ class PackageKitSmartBackend(PackageKitBaseBackend):
 
         return packages
 
-    def _channel_passes_filters(self, channel, filters):
-        filterlist = filters.split(';')
+    def _channel_passes_filters(self, channel, filterlist):
         if FILTER_NOT_DEVELOPMENT in filterlist:
             if channel['type'] == 'rpm-md':
                 repo = channel['alias']
@@ -1222,8 +1221,7 @@ class PackageKitSmartBackend(PackageKitBaseBackend):
         else:
             return None
 
-    def _package_passes_filters(self, package, filters):
-        filterlist = filters.split(';')
+    def _package_passes_filters(self, package, filterlist):
         if FILTER_NOT_INSTALLED in filterlist and package.installed:
             return False
         elif FILTER_INSTALLED in filterlist and not package.installed:
@@ -1322,8 +1320,7 @@ class PackageKitSmartBackend(PackageKitBaseBackend):
             newest[key] = (package, status)
         return newest.values()
 
-    def _post_process_package_list(self, filters):
-        filterlist = filters.split(';')
+    def _post_process_package_list(self, filterlist):
         if FILTER_BASENAME in filterlist:
             self._package_list = self._do_basename_filtering(self._package_list)
         if FILTER_NEWEST in filterlist:
commit 8bd1638fc959a6bcf5c0de403909b6c1bb89a001
Author: Richard Hughes <richard at hughsie.com>
Date:   Wed Mar 3 14:34:58 2010 +0000

    trivial: add data about stable releases

diff --git a/docs/html/pk-download.html b/docs/html/pk-download.html
index fae650d..35e1c8e 100644
--- a/docs/html/pk-download.html
+++ b/docs/html/pk-download.html
@@ -81,6 +81,8 @@ Releases are less frequent, usually every few months.
 </p>
 <table>
 <tr><td><b>Version</b></td><td>&nbsp;&nbsp;</td><td><b>Date</b></td></tr>
+<tr><td>0.5.7</td><td></td><td>2010-03-03</td></tr>
+<tr><td>0.5.6</td><td></td><td>2010-01-05</td></tr>
 <tr><td>0.5.5</td><td></td><td>2009-12-07</td></tr>
 <tr><td>0.5.4</td><td></td><td>2009-11-02</td></tr>
 <tr><td>0.5.3</td><td></td><td>2009-10-05</td></tr>
commit 05778bf386cd90b6fac41c1317c19eb923194090
Author: Richard Hughes <richard at hughsie.com>
Date:   Wed Mar 3 14:11:01 2010 +0000

    trivial: add some compat defines for old versions of gnome-packagekit

diff --git a/lib/packagekit-glib2/pk-package-ids.h b/lib/packagekit-glib2/pk-package-ids.h
index 09b74f9..dd8816e 100644
--- a/lib/packagekit-glib2/pk-package-ids.h
+++ b/lib/packagekit-glib2/pk-package-ids.h
@@ -57,6 +57,10 @@ gchar		**pk_package_ids_add_ids		(gchar		**package_ids,
 gchar		**pk_package_ids_remove_id		(gchar		**package_ids,
 							 const gchar	*package_id);
 
+/* compat defines for old versions */
+#define pk_package_ids_from_text	pk_package_ids_from_string
+#define pk_package_ids_to_text		pk_package_ids_to_string
+
 G_END_DECLS
 
 #endif /* __PK_PACKAGE_IDS_H */
commit d3557f5c5ab96352b0b00e095ef9d5f8516f2070
Author: Richard Hughes <richard at hughsie.com>
Date:   Wed Mar 3 14:10:17 2010 +0000

    yum: fix up the backend as the filters string is now a list, not a delimited string

diff --git a/backends/yum/yumBackend.py b/backends/yum/yumBackend.py
index 5d4a540..87ed876 100755
--- a/backends/yum/yumBackend.py
+++ b/backends/yum/yumBackend.py
@@ -353,12 +353,12 @@ class PackageKitYumBackend(PackageKitBaseBackend, PackagekitPackage):
             except Exception, e:
                 self.error(ERROR_INTERNAL_ERROR, _format_str(traceback.format_exc()))
 
-    def _do_meta_package_search(self, fltlist, values):
+    def _do_meta_package_search(self, filters, values):
         grps = self.comps.get_meta_packages()
         for grpid in grps:
             for value in values:
                 if value in grpid:
-                    self._show_meta_package(grpid, fltlist)
+                    self._show_meta_package(grpid, filters)
 
     def set_locale(self, code):
         '''
@@ -374,16 +374,15 @@ class PackageKitYumBackend(PackageKitBaseBackend, PackagekitPackage):
         @param filters: package types to search (all, installed, available)
         @param values: key to seach for
         '''
-        fltlist = filters.split(';')
-        pkgfilter = YumFilter(fltlist)
+        pkgfilter = YumFilter(filters)
         package_list = []
 
         # get collection objects
-        if FILTER_NOT_COLLECTIONS not in fltlist:
-            self._do_meta_package_search(fltlist, values)
+        if FILTER_NOT_COLLECTIONS not in filters:
+            self._do_meta_package_search(filters, values)
 
         # return, as we only want collection objects
-        if FILTER_COLLECTIONS not in fltlist:
+        if FILTER_COLLECTIONS not in filters:
             installed = []
             available = []
             try:
@@ -478,12 +477,12 @@ class PackageKitYumBackend(PackageKitBaseBackend, PackagekitPackage):
             raise PkError(ERROR_INTERNAL_ERROR, _format_str(traceback.format_exc()))
         return pkgs
 
-    def _handle_newest(self, fltlist):
+    def _handle_newest(self, filters):
         """
         Handle the special newest group
         """
         self.percentage(None)
-        pkgfilter = YumFilter(fltlist)
+        pkgfilter = YumFilter(filters)
         pkgs = []
         try:
             ygl = self.yumbase.doPackageLists(pkgnarrow='recent')
@@ -514,7 +513,7 @@ class PackageKitYumBackend(PackageKitBaseBackend, PackagekitPackage):
             self._show_package_list(package_list)
             self.percentage(100)
 
-    def _handle_collections(self, fltlist):
+    def _handle_collections(self, filters):
         """
         Handle the special collection group
         """
@@ -528,16 +527,16 @@ class PackageKitYumBackend(PackageKitBaseBackend, PackagekitPackage):
         old_pct = -1
         step = (100.0 - pct) / len(collections)
         for col in collections:
-            self._show_meta_package(col, fltlist)
+            self._show_meta_package(col, filters)
             pct += step
             if int(pct) != int(old_pct):
                 self.percentage(pct)
                 old_pct = pct
         self.percentage(100)
 
-    def _show_meta_package(self, grpid, fltlist):
-        show_avail = FILTER_INSTALLED not in fltlist
-        show_inst = FILTER_NOT_INSTALLED not in fltlist
+    def _show_meta_package(self, grpid, filters):
+        show_avail = FILTER_INSTALLED not in filters
+        show_inst = FILTER_NOT_INSTALLED not in filters
         package_id = "%s;;;meta" % grpid
         try:
             grp = self.yumbase.comps.return_group(grpid)
@@ -574,13 +573,12 @@ class PackageKitYumBackend(PackageKitBaseBackend, PackagekitPackage):
         self.yumbase.conf.cache = 0 # TODO: can we just look in the cache?
         self.status(STATUS_QUERY)
         package_list = [] #we can't do emitting as found if we are post-processing
-        fltlist = filters.split(';')
-        pkgfilter = YumFilter(fltlist)
+        pkgfilter = YumFilter(filters)
 
         # handle collections
         if GROUP_COLLECTIONS in values:
             try:
-                self._handle_collections(fltlist)
+                self._handle_collections(filters)
             except PkError, e:
                 self.error(e.code, e.details, exit=False)
             return
@@ -588,7 +586,7 @@ class PackageKitYumBackend(PackageKitBaseBackend, PackagekitPackage):
         # handle newest packages
         if GROUP_NEWEST in values:
             try:
-                self._handle_newest(fltlist)
+                self._handle_newest(filters)
             except PkError, e:
                 self.error(e.code, e.details, exit=False)
             return
@@ -608,14 +606,14 @@ class PackageKitYumBackend(PackageKitBaseBackend, PackagekitPackage):
             if not all_packages:
                 continue
 
-            if FILTER_NOT_INSTALLED not in fltlist:
+            if FILTER_NOT_INSTALLED not in filters:
                 try:
                     pkgfilter.add_installed(self._get_installed_from_names(all_packages))
                 except PkError, e:
                     self.error(e.code, e.details, exit=False)
                     return
 
-            if FILTER_INSTALLED not in fltlist:
+            if FILTER_INSTALLED not in filters:
                 try:
                     pkgfilter.add_available(self._get_available_from_names(all_packages))
                 except PkError, e:
@@ -645,8 +643,7 @@ class PackageKitYumBackend(PackageKitBaseBackend, PackagekitPackage):
         self.yumbase.conf.cache = 0 # TODO: can we just look in the cache?
 
         package_list = [] #we can't do emitting as found if we are post-processing
-        fltlist = filters.split(';')
-        pkgfilter = YumFilter(fltlist)
+        pkgfilter = YumFilter(filters)
 
         # Now show installed packages.
         try:
@@ -656,7 +653,7 @@ class PackageKitYumBackend(PackageKitBaseBackend, PackagekitPackage):
         pkgfilter.add_installed(pkgs)
 
         # Now show available packages.
-        if FILTER_INSTALLED not in fltlist:
+        if FILTER_INSTALLED not in filters:
             try:
                 pkgs = self.yumbase.pkgSack
             except yum.Errors.RepoError, e:
@@ -686,11 +683,10 @@ class PackageKitYumBackend(PackageKitBaseBackend, PackagekitPackage):
         self.status(STATUS_QUERY)
 
         #self.yumbase.conf.cache = 0 # TODO: can we just look in the cache?
-        fltlist = filters.split(';')
-        pkgfilter = YumFilter(fltlist)
+        pkgfilter = YumFilter(filters)
 
         # Check installed for file
-        if not FILTER_NOT_INSTALLED in fltlist:
+        if not FILTER_NOT_INSTALLED in filters:
             for value in values:
                 try:
                     pkgs = self.yumbase.rpmdb.searchFiles(value)
@@ -699,7 +695,7 @@ class PackageKitYumBackend(PackageKitBaseBackend, PackagekitPackage):
                 pkgfilter.add_installed(pkgs)
 
         # Check available for file
-        if not FILTER_INSTALLED in fltlist:
+        if not FILTER_INSTALLED in filters:
             for value in values:
                 try:
                     # we don't need the filelists as we're not globbing
@@ -758,8 +754,7 @@ class PackageKitYumBackend(PackageKitBaseBackend, PackagekitPackage):
         self.status(STATUS_QUERY)
         values_provides = []
 
-        fltlist = filters.split(';')
-        pkgfilter = YumFilter(fltlist)
+        pkgfilter = YumFilter(filters)
 
         try:
             for value in values:
@@ -779,7 +774,7 @@ class PackageKitYumBackend(PackageKitBaseBackend, PackagekitPackage):
                 else:
                     pkgfilter.add_installed(pkgs)
 
-                    if not FILTER_INSTALLED in fltlist:
+                    if not FILTER_INSTALLED in filters:
                         # Check available packages for provide
                         try:
                             pkgs = self.yumbase.pkgSack.searchProvides(provide)
@@ -1281,7 +1276,7 @@ class PackageKitYumBackend(PackageKitBaseBackend, PackagekitPackage):
                 self.error(ERROR_INTERNAL_ERROR, _format_str(traceback.format_exc()))
         return pkgs
 
-    def _get_depends_not_installed(self, fltlist, package_ids, recursive):
+    def _get_depends_not_installed(self, filters, package_ids, recursive):
         '''
         Gets the deps that are not installed, optimisation of get_depends
         using a yum transaction
@@ -1374,14 +1369,13 @@ class PackageKitYumBackend(PackageKitBaseBackend, PackagekitPackage):
         self.allow_cancel(True)
         self.percentage(None)
         self.status(STATUS_INFO)
-        fltlist = filters.split(';')
-        pkgfilter = YumFilter(fltlist)
+        pkgfilter = YumFilter(filters)
 
         # before we do an install we do ~installed + recursive true,
         # which we can emulate quicker by doing a transaction, but not
         # executing it
-        if FILTER_NOT_INSTALLED in fltlist and recursive:
-            pkgs = self._get_depends_not_installed (fltlist, package_ids, recursive)
+        if FILTER_NOT_INSTALLED in filters and recursive:
+            pkgs = self._get_depends_not_installed (filters, package_ids, recursive)
             pkgfilter.add_available(pkgs)
             package_list = pkgfilter.post_process()
             self._show_package_list(package_list)
@@ -1592,14 +1586,13 @@ class PackageKitYumBackend(PackageKitBaseBackend, PackagekitPackage):
         self.yumbase.conf.cache = 0 # TODO: can we just look in the cache?
         self.status(STATUS_QUERY)
 
-        fltlist = filters.split(';')
-        pkgfilter = YumFilter(fltlist)
+        pkgfilter = YumFilter(filters)
         package_list = []
 
         # OR search
         for package in packages:
             # Get installed packages
-            if FILTER_NOT_INSTALLED not in fltlist:
+            if FILTER_NOT_INSTALLED not in filters:
                 try:
                     pkgs = self.yumbase.rpmdb.searchNevra(name=package)
                 except Exception, e:
@@ -1608,7 +1601,7 @@ class PackageKitYumBackend(PackageKitBaseBackend, PackagekitPackage):
                     pkgfilter.add_installed(pkgs)
 
             # Get available packages
-            if FILTER_INSTALLED not in fltlist:
+            if FILTER_INSTALLED not in filters:
                 try:
                     pkgs = self.yumbase.pkgSack.returnNewestByName(name=package)
                 except yum.Errors.PackageSackError, e:
@@ -2411,9 +2404,8 @@ class PackageKitYumBackend(PackageKitBaseBackend, PackagekitPackage):
         # clear the package sack so we can get new updates
         self.yumbase.pkgSack = None
 
-        fltlist = filters.split(';')
         package_list = []
-        pkgfilter = YumFilter(fltlist)
+        pkgfilter = YumFilter(filters)
         pkgs = []
         try:
             ygl = self.yumbase.doPackageLists(pkgnarrow='updates')
commit a7f3186db437e3409f8f72d7bd1c631abc63fedd
Author: Richard Hughes <richard at hughsie.com>
Date:   Wed Mar 3 14:06:28 2010 +0000

    Break internal python API by supplying a list of filters to the backend, not a delimited list

diff --git a/lib/python/packagekit/backend.py b/lib/python/packagekit/backend.py
index 6751559..f1bf2df 100644
--- a/lib/python/packagekit/backend.py
+++ b/lib/python/packagekit/backend.py
@@ -568,7 +568,7 @@ class PackageKitBaseBackend:
             self.download_packages(directory, package_ids)
             self.finished()
         elif cmd == 'get-depends':
-            filters = args[0]
+            filters = args[0].split(';')
             package_ids = args[1].split(PACKAGE_IDS_DELIM)
             recursive = _text_to_bool(args[2])
             self.get_depends(filters, package_ids, recursive)
@@ -582,15 +582,15 @@ class PackageKitBaseBackend:
             self.get_files(package_ids)
             self.finished()
         elif cmd == 'get-packages':
-            filters = args[0]
+            filters = args[0].split(';')
             self.get_packages(filters)
             self.finished()
         elif cmd == 'get-repo-list':
-            filters = args[0]
+            filters = args[0].split(';')
             self.get_repo_list(filters)
             self.finished()
         elif cmd == 'get-requires':
-            filters = args[0]
+            filters = args[0].split(';')
             package_ids = args[1].split(PACKAGE_IDS_DELIM)
             recursive = _text_to_bool(args[2])
             self.get_requires(filters, package_ids, recursive)
@@ -603,7 +603,7 @@ class PackageKitBaseBackend:
             self.get_distro_upgrades()
             self.finished()
         elif cmd == 'get-updates':
-            filters = args[0]
+            filters = args[0].split(';')
             self.get_updates(filters)
             self.finished()
         elif cmd == 'install-files':
@@ -644,7 +644,7 @@ class PackageKitBaseBackend:
             self.repo_set_data(repoid, para, value)
             self.finished()
         elif cmd == 'resolve':
-            filters = args[0]
+            filters = args[0].split(';')
             package_ids = args[1].split(PACKAGE_IDS_DELIM)
             self.resolve(filters, package_ids)
             self.finished()
@@ -682,7 +682,7 @@ class PackageKitBaseBackend:
             self.update_system(only_trusted)
             self.finished()
         elif cmd == 'what-provides':
-            filters = args[0]
+            filters = args[0].split(';')
             provides_type = args[1]
             values = _to_unicode(args[2]).split(PACKAGE_IDS_DELIM)
             self.what_provides(filters, provides_type, values)
commit 0951895adf46008df5713d771bad208d24f243fe
Author: Scott Parkerson <scott.parkerson at gmail.com>
Date:   Wed Mar 3 04:32:53 2010 -0500

    conary: first blush at getting conary backend to listen to simulate_*

diff --git a/backends/conary/conaryBackend.py b/backends/conary/conaryBackend.py
index a43166b..3909998 100755
--- a/backends/conary/conaryBackend.py
+++ b/backends/conary/conaryBackend.py
@@ -17,7 +17,8 @@
 #
 # Copyright (C) 2007 Ken VanDine <ken at vandine.org>
 # Copyright (C) 2008 Richard Hughes <richard at hughsie.com>
-# Copyright (C) 2008 Andres Vargas <zodman at foresightlinux.org>
+# Copyright (C) 2009-2010 Andres Vargas <zodman at foresightlinux.org>
+#                         Scott Parkerson <scott.parkerson at gmail.com>
 # }}}
 #{{{ LIBS
 import sys
@@ -271,7 +272,7 @@ class PackageKitConaryBackend(PackageKitBaseBackend):
             Cache().cacheUpdateJob(applyList, updJob)
         return updJob, suggMap
 
-    def _do_update(self, applyList):
+    def _do_update(self, applyList, simulate=False):
         log.info("========= _do_update ========")
         jobPath = Cache().checkCachedUpdateJob(applyList)
         log.info(jobPath)
@@ -285,7 +286,7 @@ class PackageKitConaryBackend(PackageKitBaseBackend):
             updJob,suggMap = self._get_update(applyList, cache=False)
         self.allow_cancel(False)
         try:
-            restartDir = self.client.applyUpdateJob(updJob)
+            restartDir = self.client.applyUpdateJob(updJob, test=simulate)
         except errors.InternalConaryError:
             self.error(ERROR_NO_PACKAGES_TO_UPDATE,"get-updates first and then update sytem")
         except trove.TroveIntegrityError: 
@@ -299,12 +300,12 @@ class PackageKitConaryBackend(PackageKitBaseBackend):
             applyList = [(name, (None, None), (version, flavor), True)]
         return self._get_update(applyList)
 
-    def _do_package_update(self, name, version, flavor):
+    def _do_package_update(self, name, version, flavor, simulate):
         if name.startswith('-'):
             applyList = [(name, (version, flavor), (None, None), False)]
         else:
             applyList = [(name, (None, None), (version, flavor), True)]
-        return self._do_update(applyList)
+        return self._do_update(applyList, simulate)
 
     def _resolve_list(self, filters):
 
@@ -574,17 +575,17 @@ class PackageKitConaryBackend(PackageKitBaseBackend):
         cache = Cache()
         cache.refresh()
 
-    def install_packages(self, only_trusted, package_ids):
+    def install_packages(self, only_trusted, package_ids, simulate=False):
         """
             alias of update_packages
         """
 
         # FIXME: use only_trusted
 
-        self.update_packages(only_trusted, package_ids)
+        self.update_packages(only_trusted, package_ids, simulate)
 
     @ExceptionHandler
-    def update_packages(self, only_trusted, package_ids):
+    def update_packages(self, only_trusted, package_ids, simulate=False):
         '''
         Implement the {backend}-{install, update}-packages functionality
         '''
@@ -609,11 +610,11 @@ class PackageKitConaryBackend(PackageKitBaseBackend):
                 log.info(">>> Prepare Update")
                 self._get_package_update(name, version, flavor)
                 log.info(">>> end Prepare Update")
-                self._do_package_update(name, version, flavor)
+                self._do_package_update(name, version, flavor, simulate)
 
         
     @ExceptionHandler
-    def remove_packages(self, allowDeps, autoremove, package_ids):
+    def remove_packages(self, allowDeps, autoremove, package_ids, simulate=False):
         '''
         Implement the {backend}-remove-packages functionality
         '''
@@ -639,7 +640,7 @@ class PackageKitConaryBackend(PackageKitBaseBackend):
                 if callback.error:
                     self.error(ERROR_DEP_RESOLUTION_FAILED,', '.join(callback.error))
                         
-                self._do_package_update(name, version, flavor)
+                self._do_package_update(name, version, flavor, simulate)
         self.client.setUpdateCallback(self.callback)
 
     def _get_metadata(self, package_id, field):
@@ -950,6 +951,24 @@ class PackageKitConaryBackend(PackageKitBaseBackend):
         '''
         pass
 
+    def simulate_install_packages(self, package_ids):
+	'''
+	Simulate an install of one or more packages.
+        '''
+	return self.install_packages(package_ids, False, simulate=True)
+
+    def simulate_update_packages(self, package_ids):
+	'''
+	Simulate an update of one or more packages.
+        '''
+	return self.update_packages(package_ids, False, simulate=True)
+
+    def simulate_remove_packages(self, package_ids):
+	'''
+	Simulate an update of one or more packages.
+        '''
+	return self.remove_packages(package_ids, False, simulate=True)
+
 from pkConaryLog import pdb
 
 def main():
diff --git a/backends/conary/pk-backend-conary.c b/backends/conary/pk-backend-conary.c
index c6f945c..2a33858 100644
--- a/backends/conary/pk-backend-conary.c
+++ b/backends/conary/pk-backend-conary.c
@@ -2,6 +2,8 @@
  *
  * Copyright (C) 2007 Richard Hughes <richard at hughsie.com>
  * Copyright (C) 2007 Ken VanDine <ken at vandine.org>
+ * Copyright (C) 2009-2010 Andres Vargas <zodman at foresightlinux.org>
+ *                         Scott Parkerson <scott.parkerson at gmail.com>
  *
  * Licensed under the GNU General Public License Version 2
  *
@@ -363,6 +365,61 @@ static void backend_get_repo_list (PkBackend *backend, PkBitfield filters)
     g_free (filters_text);
 }
 
+/**
+ * backend_simulate_install_packages:
+ */
+static void
+backend_simulate_install_packages (PkBackend *backend, gchar **package_ids)
+{
+	gchar *package_ids_temp;
+
+	/* check network state */
+	if (!pk_backend_is_online (backend)) {
+		pk_backend_error_code (backend, PK_ERROR_ENUM_NO_NETWORK, "Cannot install when offline");
+		pk_backend_finished (backend);
+		return;
+	}
+
+	/* send the complete list as stdin */
+	package_ids_temp = pk_package_ids_to_string (package_ids);
+	pk_backend_spawn_helper (spawn, "conaryBackend.py", "simulate-install-packages", package_ids_temp, NULL);
+	g_free (package_ids_temp);
+}
+
+/**
+ * backend_simulate_remove_packages:
+ */
+static void
+backend_simulate_remove_packages (PkBackend *backend, gchar **package_ids)
+{
+	gchar *package_ids_temp;
+
+	/* send the complete list as stdin */
+	package_ids_temp = pk_package_ids_to_string (package_ids);
+	pk_backend_spawn_helper (spawn, "conaryBackend.py", "simulate-remove-packages", package_ids_temp, NULL);
+	g_free (package_ids_temp);
+}
+
+/**
+ * backend_simulate_update_packages:
+ */
+static void
+backend_simulate_update_packages (PkBackend *backend, gchar **package_ids)
+{
+	gchar *package_ids_temp;
+
+	/* check network state */
+	if (!pk_backend_is_online (backend)) {
+		pk_backend_error_code (backend, PK_ERROR_ENUM_NO_NETWORK, "Cannot update when offline");
+		pk_backend_finished (backend);
+		return;
+	}
+	/* send the complete list as stdin */
+	package_ids_temp = pk_package_ids_to_string (package_ids);
+	egg_debug("Updates Packages");
+	pk_backend_spawn_helper (spawn, "conaryBackend.py", "simulate-update-packages", package_ids_temp, NULL);
+	g_free (package_ids_temp);
+}
 
 PK_BACKEND_OPTIONS (
 	"Conary with XMLCache",				/* description */
@@ -402,8 +459,8 @@ PK_BACKEND_OPTIONS (
 	backend_update_system,			/* update_system */
 	NULL,					/* what_provides */
 	NULL,					/* simulate_install_files */
-	NULL,					/* simulate_install_packages */
-	NULL,					/* simulate_remove_packages */
-	NULL				/* simulate_update_packages */
+	backend_simulate_install_packages,	/* simulate_install_packages */
+	backend_simulate_remove_packages,	/* simulate_remove_packages */
+	backend_simulate_update_packages	/* simulate_update_packages */
 );
 
commit fd3de6a4dc21eb3467f4d60b7e4fa79dcff65aff
Merge: b4976cb... c809012...
Author: Sebastian Heinlein <devel at glatzor.de>
Date:   Tue Mar 2 20:47:17 2010 +0100

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

commit c809012143dd78a86d3366ed0d75865ef40c03d5
Author: Richard Hughes <richard at hughsie.com>
Date:   Tue Mar 2 17:48:48 2010 +0000

    yum: if yum, rpm or PackageKit are available as updates, then update these packages first and surpress any other updates until the next check

diff --git a/backends/yum/yumBackend.py b/backends/yum/yumBackend.py
index 99e449e..5d4a540 100755
--- a/backends/yum/yumBackend.py
+++ b/backends/yum/yumBackend.py
@@ -2426,6 +2426,20 @@ class PackageKitYumBackend(PackageKitBaseBackend, PackagekitPackage):
             self.error(ERROR_NO_SPACE_ON_DEVICE, _to_unicode(e))
         except Exception, e:
             self.error(ERROR_INTERNAL_ERROR, _format_str(traceback.format_exc()))
+
+        # some packages should be updated before the others
+        infra_pkgs = []
+        for pkg in pkgs:
+            infra_packages = ['PackageKit', 'yum', 'rpm']
+            if pkg.name in infra_packages or pkg.name.partition('-')[0] in infra_packages:
+                infra_pkgs.append(pkg)
+        if len(infra_pkgs) > 0:
+            msg = []
+            for pkg in infra_pkgs:
+                msg.append(pkg.name)
+            self.message(MESSAGE_BACKEND_ERROR, "The packages '%s' will be updated before other packages" % msg)
+            pkgs = infra_pkgs
+
         md = self.updateMetadata
         for pkg in unique(pkgs):
             if pkgfilter.pre_process(pkg):
commit 93967983f83feaab5d8dfd872a751e9d76a873f5
Merge: 467a9c6... 975f37d...
Author: Daniel Nicoletti <dantti85-pk at yahoo.com.br>
Date:   Tue Mar 2 15:19:07 2010 -0300

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

commit 467a9c68faf1604b51e8270537333512a4cf6cb1
Author: Daniel Nicoletti <dantti85-pk at yahoo.com.br>
Date:   Tue Mar 2 15:18:40 2010 -0300

    aptcc: fix a mem leak

diff --git a/backends/aptcc/apt.cpp b/backends/aptcc/apt.cpp
index a30301c..f7505af 100644
--- a/backends/aptcc/apt.cpp
+++ b/backends/aptcc/apt.cpp
@@ -1070,6 +1070,7 @@ bool aptcc::removingEssentialPackages(pkgCacheFile &Cache)
 		}
 	}
 
+	delete [] Added;
 	if (!List.empty()) {
 		pk_backend_error_code(m_backend,
 				      PK_ERROR_ENUM_CANNOT_REMOVE_SYSTEM_PACKAGE,
commit 975f37de07c124384edd40d5c2d8ef965d6f6d86
Author: Richard Hughes <richard at hughsie.com>
Date:   Tue Mar 2 17:19:25 2010 +0000

    yum: ensure we actually do self._check_init() for RefreshCache so non-contactable repos get disabled

diff --git a/backends/yum/yumBackend.py b/backends/yum/yumBackend.py
index c8fae44..99e449e 100755
--- a/backends/yum/yumBackend.py
+++ b/backends/yum/yumBackend.py
@@ -1514,6 +1514,11 @@ class PackageKitYumBackend(PackageKitBaseBackend, PackagekitPackage):
         '''
         Implement the refresh_cache functionality
         '''
+        try:
+            self._check_init()
+        except PkError, e:
+            self.error(e.code, e.details, exit=False)
+            return
         self.allow_cancel(True)
         self.percentage(0)
         self.status(STATUS_REFRESH_CACHE)
commit 33a4cf61608bc65f907a0b7e4ca45ea971c81f6c
Author: Daniel Nicoletti <dantti85-pk at yahoo.com.br>
Date:   Tue Mar 2 12:48:57 2010 -0300

    aptcc: Don't allow essential packages to be removed

diff --git a/backends/aptcc/apt.cpp b/backends/aptcc/apt.cpp
index 143bf95..a30301c 100644
--- a/backends/aptcc/apt.cpp
+++ b/backends/aptcc/apt.cpp
@@ -1021,6 +1021,67 @@ bool aptcc::TryToInstall(pkgCache::PkgIterator Pkg,
 	return true;
 }
 
+// checks if there are Essential packages being removed
+bool aptcc::removingEssentialPackages(pkgCacheFile &Cache)
+{
+	string List;
+	bool *Added = new bool[Cache->Head().PackageCount];
+	for (unsigned int I = 0; I != Cache->Head().PackageCount; I++){
+		Added[I] = false;
+	}
+
+	for (pkgCache::PkgIterator I = Cache->PkgBegin(); ! I.end(); ++I) {
+		if ((I->Flags & pkgCache::Flag::Essential) != pkgCache::Flag::Essential &&
+		    (I->Flags & pkgCache::Flag::Important) != pkgCache::Flag::Important) {
+			continue;
+		}
+
+		if (Cache[I].Delete() == true) {
+			if (Added[I->ID] == false) {
+				Added[I->ID] = true;
+				List += string(I.Name()) + " ";
+			}
+		}
+
+		if (I->CurrentVer == 0) {
+			continue;
+		}
+
+		// Print out any essential package depenendents that are to be removed
+		for (pkgCache::DepIterator D = I.CurrentVer().DependsList(); D.end() == false; D++) {
+			// Skip everything but depends
+			if (D->Type != pkgCache::Dep::PreDepends &&
+			    D->Type != pkgCache::Dep::Depends){
+				continue;
+			}
+
+			pkgCache::PkgIterator P = D.SmartTargetPkg();
+			if (Cache[P].Delete() == true)
+			{
+				if (Added[P->ID] == true){
+				    continue;
+				}
+				Added[P->ID] = true;
+
+				char S[300];
+				snprintf(S, sizeof(S), "%s (due to %s) ", P.Name(), I.Name());
+				List += S;
+			}
+		}
+	}
+
+	if (!List.empty()) {
+		pk_backend_error_code(m_backend,
+				      PK_ERROR_ENUM_CANNOT_REMOVE_SYSTEM_PACKAGE,
+				      g_strdup_printf("WARNING: You are trying to remove the "
+						      "following essential packages: %s",
+						      List.c_str()));
+		return true;
+	}
+	
+	return false;
+}
+
 // emitChangedPackages - Show packages to newly install				/*{{{*/
 // ---------------------------------------------------------------------
 /* */
@@ -1377,7 +1438,10 @@ bool aptcc::runTransaction(vector<pair<pkgCache::PkgIterator, pkgCache::VerItera
 		return false;
 	}
 
-	// TODO check for essential packages!!!
+	// check for essential packages!!!
+	if (removingEssentialPackages(Cache)) {
+		return false;
+	}
 
 	if (simulate) {
 		// Print out a list of packages that are going to be installed extra
@@ -1387,7 +1451,7 @@ bool aptcc::runTransaction(vector<pair<pkgCache::PkgIterator, pkgCache::VerItera
 		// Store the packages that are going to change
 		// so we can emit them as we process it.
 		populateInternalPackages(Cache);
-	        return installPackages(Cache, false);
+	        return installPackages(Cache);
 	}
 }
 
@@ -1397,8 +1461,7 @@ bool aptcc::runTransaction(vector<pair<pkgCache::PkgIterator, pkgCache::VerItera
 // ---------------------------------------------------------------------
 /* This displays the informative messages describing what is going to
    happen and then calls the download routines */
-bool aptcc::installPackages(pkgCacheFile &Cache,
-			    bool Safety)
+bool aptcc::installPackages(pkgCacheFile &Cache)
 {
 	//cout << "installPackages() called" << endl;
 	if (_config->FindB("APT::Get::Purge",false) == true)
@@ -1412,20 +1475,10 @@ bool aptcc::installPackages(pkgCacheFile &Cache,
 		}
 	}
 
-//	bool Fail = false;
-	bool Essential = false;
-
-// we don't show things here
-	// Show all the various warning indicators
-// 	Fail |= !ShowHold(c1out,Cache);
-// 	if (_config->FindB("APT::Get::Show-Upgraded",true) == true)
-// 	    ShowUpgraded(c1out,Cache);
-// 	Fail |= !ShowDowngraded(c1out,Cache);
-// 	if (_config->FindB("APT::Get::Download-Only",false) == false)
-// 	    cout << "--------------fo" << endl;
-// 		Essential = !ShowEssential(c1out,Cache);
-// 	Fail |= Essential;
-// 	Stats(c1out,Cache);
+	// check for essential packages!!!
+	if (removingEssentialPackages(Cache)) {
+		return false;
+	}
 
 	// Sanity check
 	if (Cache->BrokenCount() != 0)
@@ -1442,7 +1495,7 @@ bool aptcc::installPackages(pkgCacheFile &Cache,
 	}
 
 	// No remove flag
-	if (Cache->DelCount() != 0 && _config->FindB("APT::Get::Remove",true) == false) {
+	if (Cache->DelCount() != 0 && _config->FindB("APT::Get::Remove", true) == false) {
 		pk_backend_error_code(m_backend,
 				      PK_ERROR_ENUM_PACKAGE_FAILED_TO_REMOVE,
 				      "Packages need to be removed but remove is disabled.");
@@ -1457,7 +1510,7 @@ bool aptcc::installPackages(pkgCacheFile &Cache,
 
 	// Lock the archive directory
 	FileFd Lock;
-	if (_config->FindB("Debug::NoLocking",false) == false)
+	if (_config->FindB("Debug::NoLocking", false) == false)
 	{
 		Lock.Fd(GetLock(_config->FindDir("Dir::Cache::Archives") + "lock"));
 		if (_error->PendingError() == true) {
@@ -1555,27 +1608,6 @@ cout << "How odd.. The sizes didn't match, email apt at packages.debian.org";
 		}
 	}
 
-	// Fail safe check
-// 	if (_config->FindI("quiet",0) >= 2 ||
-// 	    _config->FindB("APT::Get::Assume-Yes",false) == true)
-// 	{
-// 	    if (Fail == true && _config->FindB("APT::Get::Force-Yes",false) == false)
-// 		return _error->Error("There are problems and -y was used without --force-yes");
-// 	}
-
-	if (Essential == true && Safety == true)
-	{
-		if (_config->FindB("APT::Get::Trivial-Only",false) == true) {
-			return _error->Error("Trivial Only specified but this is not a trivial operation.");
-		}
-
-		pk_backend_error_code(m_backend,
-				      PK_ERROR_ENUM_TRANSACTION_ERROR,
-				      "You was about to do something potentially harmful.\n"
-				      "Please use aptitude or synaptic to have more information.");
-		return false;
-	}
-
 	if (!checkTrusted(fetcher, m_backend)) {
 		return false;
 	}
diff --git a/backends/aptcc/apt.h b/backends/aptcc/apt.h
index a59a0f5..a07eecd 100644
--- a/backends/aptcc/apt.h
+++ b/backends/aptcc/apt.h
@@ -120,8 +120,7 @@ public:
 	/**
 	 *  seems to install packages
 	 */
-	bool installPackages(pkgCacheFile &Cache,
-			     bool Safety = true);
+	bool installPackages(pkgCacheFile &Cache);
 
 	/**
 	 *  check if the package provides the codec
@@ -153,6 +152,7 @@ private:
 	void updateInterface(int readFd, int writeFd);
 	bool DoAutomaticRemove(pkgCacheFile &Cache);
 	void emitChangedPackages(pkgCacheFile &Cache);
+	bool removingEssentialPackages(pkgCacheFile &Cache);
 
 	vector<pair<pkgCache::PkgIterator, pkgCache::VerIterator> > m_pkgs;
 	void populateInternalPackages(pkgCacheFile &Cache);
diff --git a/backends/aptcc/pk-backend-aptcc.cpp b/backends/aptcc/pk-backend-aptcc.cpp
index 63827d9..4566b95 100644
--- a/backends/aptcc/pk-backend-aptcc.cpp
+++ b/backends/aptcc/pk-backend-aptcc.cpp
@@ -438,7 +438,7 @@ backend_get_or_update_system_thread (PkBackend *backend)
 		m_apt->emitUpdates(update, filters);
 		m_apt->emit_packages(kept, filters, PK_INFO_ENUM_BLOCKED);
 	} else {
-		res = m_apt->installPackages(Cache, true);
+		res = m_apt->installPackages(Cache);
 	}
 
 	delete m_apt;
commit 89fbc4a5faf8a478205c0789df3c56d354e0dc9b
Merge: 97c893f... db726c3...
Author: Daniel Nicoletti <dantti85-pk at yahoo.com.br>
Date:   Tue Mar 2 11:45:55 2010 -0300

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

commit 97c893fcf40084d40046642440af06160bd6b413
Author: Daniel Nicoletti <dantti85-pk at yahoo.com.br>
Date:   Tue Mar 2 11:45:06 2010 -0300

    aptcc: Fix show broken packages

diff --git a/backends/aptcc/apt.cpp b/backends/aptcc/apt.cpp
index 6b15e6e..143bf95 100644
--- a/backends/aptcc/apt.cpp
+++ b/backends/aptcc/apt.cpp
@@ -971,6 +971,12 @@ bool aptcc::TryToInstall(pkgCache::PkgIterator Pkg,
 	if (State.CandidateVer == 0 && Remove == false)
 	{
 		_error->Error("Package %s is virtual and has no installation candidate", Pkg.Name());
+
+		pk_backend_error_code(m_backend,
+				      PK_ERROR_ENUM_DEP_RESOLUTION_FAILED,
+				      g_strdup_printf("Package %s is virtual and has no "
+						      "installation candidate",
+						      Pkg.Name()));
 		return false;
 	}
 
@@ -979,7 +985,7 @@ bool aptcc::TryToInstall(pkgCache::PkgIterator Pkg,
 	if (Remove == true)
 	{
 		Fix.Remove(Pkg);
-		Cache.MarkDelete(Pkg,_config->FindB("APT::Get::Purge",false));
+		Cache.MarkDelete(Pkg,_config->FindB("APT::Get::Purge", false));
 		return true;
 	}
 
@@ -1004,7 +1010,7 @@ bool aptcc::TryToInstall(pkgCache::PkgIterator Pkg,
 		ExpectedInst++;
 	}
 
-	cout << "trytoinstall ExpectedInst " << ExpectedInst << endl;
+// 	cout << "trytoinstall ExpectedInst " << ExpectedInst << endl;
 	// Install it with autoinstalling enabled (if we not respect the minial
 	// required deps or the policy)
 	if ((State.InstBroken() == true || State.InstPolicyBroken() == true) &&
@@ -1346,26 +1352,10 @@ bool aptcc::runTransaction(vector<pair<pkgCache::PkgIterator, pkgCache::VerItera
 					 remove,
 					 BrokenFix,
 					 ExpectedInst) == false) {
-				pk_backend_error_code(m_backend,
-						      PK_ERROR_ENUM_INTERNAL_ERROR,
-						      "Could not open package cache.");
 				return false;
 			}
 		}
 
-		/* If we are in the Broken fixing mode we do not attempt to fix the
-		    problems. This is if the user invoked install without -f and gave
-		    packages */
-		// TODO this code seems to be a bit useless,
-		// if we go to the Fix.Resolve() it can fix things
-		// and if not the last if will then fail.
-// 		if (BrokenFix == true && Cache->BrokenCount() != 0)
-// 		{
-// 			_error->Error("Unmet dependencies. Try 'apt-get -f install' with no packages (or specify a solution).");
-// 			show_broken(m_backend, this);
-// 			return false;
-// 		}
-
 		// Call the scored problem resolver
 		Fix.InstallProtect();
 		if (Fix.Resolve(true) == false) {
@@ -1375,10 +1365,10 @@ bool aptcc::runTransaction(vector<pair<pkgCache::PkgIterator, pkgCache::VerItera
 		// Now we check the state of the packages,
 		if (Cache->BrokenCount() != 0)
 		{
-		    // if the problem resolver could not fix all broken things
-		    // show what is broken
-		    show_broken(m_backend, this);
-		    return false;
+			// if the problem resolver could not fix all broken things
+			// show what is broken
+			show_broken(m_backend, Cache, false);
+			return false;
 		}
 	}
 	// Try to auto-remove packages
@@ -1387,6 +1377,8 @@ bool aptcc::runTransaction(vector<pair<pkgCache::PkgIterator, pkgCache::VerItera
 		return false;
 	}
 
+	// TODO check for essential packages!!!
+
 	if (simulate) {
 		// Print out a list of packages that are going to be installed extra
 		emitChangedPackages(Cache);
@@ -1405,17 +1397,17 @@ bool aptcc::runTransaction(vector<pair<pkgCache::PkgIterator, pkgCache::VerItera
 // ---------------------------------------------------------------------
 /* This displays the informative messages describing what is going to
    happen and then calls the download routines */
-bool aptcc::installPackages(pkgDepCache &Cache,
+bool aptcc::installPackages(pkgCacheFile &Cache,
 			    bool Safety)
 {
 	//cout << "installPackages() called" << endl;
 	if (_config->FindB("APT::Get::Purge",false) == true)
 	{
-		pkgCache::PkgIterator I = Cache.PkgBegin();
+		pkgCache::PkgIterator I = Cache->PkgBegin();
 		for (; I.end() == false; I++)
 		{
 			if (I.Purge() == false && Cache[I].Mode == pkgDepCache::ModeDelete) {
-				Cache.MarkDelete(I,true);
+				Cache->MarkDelete(I,true);
 			}
 		}
 	}
@@ -1430,26 +1422,27 @@ bool aptcc::installPackages(pkgDepCache &Cache,
 // 	    ShowUpgraded(c1out,Cache);
 // 	Fail |= !ShowDowngraded(c1out,Cache);
 // 	if (_config->FindB("APT::Get::Download-Only",false) == false)
+// 	    cout << "--------------fo" << endl;
 // 		Essential = !ShowEssential(c1out,Cache);
 // 	Fail |= Essential;
 // 	Stats(c1out,Cache);
 
 	// Sanity check
-	if (Cache.BrokenCount() != 0)
+	if (Cache->BrokenCount() != 0)
 	{
 		// TODO
-		show_broken(m_backend, this);
+		show_broken(m_backend, Cache, false);
 		_error->Error("Internal error, InstallPackages was called with broken packages!");
 		return false;
 	}
 
-	if (Cache.DelCount() == 0 && Cache.InstCount() == 0 &&
-	    Cache.BadCount() == 0) {
+	if (Cache->DelCount() == 0 && Cache->InstCount() == 0 &&
+	    Cache->BadCount() == 0) {
 		return true;
 	}
 
 	// No remove flag
-	if (Cache.DelCount() != 0 && _config->FindB("APT::Get::Remove",true) == false) {
+	if (Cache->DelCount() != 0 && _config->FindB("APT::Get::Remove",true) == false) {
 		pk_backend_error_code(m_backend,
 				      PK_ERROR_ENUM_PACKAGE_FAILED_TO_REMOVE,
 				      "Packages need to be removed but remove is disabled.");
@@ -1479,14 +1472,14 @@ bool aptcc::installPackages(pkgDepCache &Cache,
 	pkgAcquire fetcher(&Stat);
 
 	// Create the package manager and prepare to download
-	SPtr<pkgPackageManager> PM= _system->CreatePM(&Cache);
+	SPtr<pkgPackageManager> PM= _system->CreatePM(Cache);
 	if (PM->GetArchives(&fetcher, packageSourceList, &Recs) == false ||
 	    _error->PendingError() == true) {
 		return false;
 	}
 
 	// Generate the list of affected packages and sort it
-	for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; I++)
+	for (pkgCache::PkgIterator I = Cache->PkgBegin(); I.end() == false; I++)
 	{
 		// Ignore no-version packages
 		if (I->VersionList == 0) {
@@ -1512,9 +1505,9 @@ bool aptcc::installPackages(pkgDepCache &Cache,
 	double FetchBytes = fetcher.FetchNeeded();
 	double FetchPBytes = fetcher.PartialPresent();
 	double DebBytes = fetcher.TotalNeeded();
-	if (DebBytes != Cache.DebSize())
+	if (DebBytes != Cache->DebSize())
 	{
- 	    cout << DebBytes << ',' << Cache.DebSize() << endl;
+ 	    cout << DebBytes << ',' << Cache->DebSize() << endl;
 cout << "How odd.. The sizes didn't match, email apt at packages.debian.org";
 		_error->Warning("How odd.. The sizes didn't match, email apt at packages.debian.org");
 	}
@@ -1528,12 +1521,12 @@ cout << "How odd.. The sizes didn't match, email apt at packages.debian.org";
 // 		    SizeToStr(DebBytes).c_str());
 
 	// Size delta
-// 	if (Cache.UsrSize() >= 0)
+// 	if (Cache->UsrSize() >= 0)
 // 	    ioprintf(c1out, "After this operation, %sB of additional disk space will be used.\n",
-// 		    SizeToStr(Cache.UsrSize()).c_str());
+// 		    SizeToStr(Cache->UsrSize()).c_str());
 // 	else
 // 	    ioprintf(c1out, "After this operation, %sB disk space will be freed.\n",
-// 		    SizeToStr(-1*Cache.UsrSize()).c_str());
+// 		    SizeToStr(-1*Cache->UsrSize()).c_str());
 
 	if (_error->PendingError() == true) {
 	    cout << "PendingError " << endl;
diff --git a/backends/aptcc/apt.h b/backends/aptcc/apt.h
index 5deb2be..a59a0f5 100644
--- a/backends/aptcc/apt.h
+++ b/backends/aptcc/apt.h
@@ -120,7 +120,7 @@ public:
 	/**
 	 *  seems to install packages
 	 */
-	bool installPackages(pkgDepCache &Cache,
+	bool installPackages(pkgCacheFile &Cache,
 			     bool Safety = true);
 
 	/**
diff --git a/backends/aptcc/aptcc_show_broken.cpp b/backends/aptcc/aptcc_show_broken.cpp
index f6375e9..8001136 100644
--- a/backends/aptcc/aptcc_show_broken.cpp
+++ b/backends/aptcc/aptcc_show_broken.cpp
@@ -1,139 +1,144 @@
 // aptcc_show_broken.cc
 //
 //   Copyright 2004 Daniel Burrows
-//   Copyright 2009 Daniel Nicoletti
+//   Copyright 2009-2010 Daniel Nicoletti
 
 #include "aptcc_show_broken.h"
 
-#include "apt.h"
-#include "apt-utils.h"
-
 #include <stdio.h>
-#include <string>
+#include <string.h>
+
 #include <sstream>
 
 using namespace std;
 
 /** Shows broken dependencies for a single package */
-static string show_broken_deps(aptcc *m_apt, pkgCache::PkgIterator pkg)
+void show_broken(PkBackend *backend, pkgCacheFile &Cache, bool Now)
 {
-	unsigned int indent=strlen(pkg.Name())+3;
-	bool is_first_dep=true;
-	stringstream output;
+	stringstream out;
+
+	out << "The following packages have unmet dependencies:" << endl;
+	for (pkgCache::PkgIterator I = Cache->PkgBegin(); ! I.end(); ++I) {
+		if (Now == true) {
+			if (Cache[I].NowBroken() == false) {
+				continue;
+			}
+		} else {
+			if (Cache[I].InstBroken() == false){
+				continue;
+			}
+		}
 
-	pkgCache::VerIterator ver;
-	ver = (*m_apt->packageDepCache)[pkg].InstVerIter(*m_apt->packageDepCache);
+		// Print out each package and the failed dependencies
+		out << "  " <<  I.Name() << ":";
+		unsigned Indent = strlen(I.Name()) + 3;
+		bool First = true;
+		pkgCache::VerIterator Ver;
 
-	output << "  " << pkg.Name() << ":";
-	for (pkgCache::DepIterator dep=ver.DependsList(); !dep.end(); ++dep)
-	{
-		pkgCache::DepIterator first=dep, prev=dep;
+		if (Now == true) {
+			Ver = I.CurrentVer();
+		} else {
+			Ver = Cache[I].InstVerIter(Cache);
+		}
 
-		while (dep->CompareOp & pkgCache::Dep::Or) {
-		    ++dep;
+		if (Ver.end() == true) {
+			out << endl;
+			continue;
 		}
 
-		// Yep, it's broken.
-		if (dep.IsCritical() &&
-		    !((*m_apt->packageDepCache)[dep]&pkgDepCache::DepGInstall))
-		{
-			bool is_first_of_or=true;
-			// Iterate over the OR group, print out the information.
-
-			do
-			{
-				if(!is_first_dep) {
-					for(unsigned int i=0; i<indent; ++i) {
-						output << " ";
-					}
+		for (pkgCache::DepIterator D = Ver.DependsList(); D.end() == false;) {
+			// Compute a single dependency element (glob or)
+			pkgCache::DepIterator Start;
+			pkgCache::DepIterator End;
+			D.GlobOr(Start,End); // advances D
+
+			if (Cache->IsImportantDep(End) == false){
+				continue;
+			}
+
+			if (Now == true) {
+				if ((Cache[End] & pkgDepCache::DepGNow) == pkgDepCache::DepGNow){
+					continue;
+				}
+			} else {
+				if ((Cache[End] & pkgDepCache::DepGInstall) == pkgDepCache::DepGInstall) {
+					continue;
 				}
+			}
 
-				is_first_dep=false;
+			bool FirstOr = true;
+			while (1) {
+				if (First == false){
+					for (unsigned J = 0; J != Indent; J++) {
+						out << ' ';
+					}
+				}
+				First = false;
 
-				if (!is_first_of_or) {
-					for(unsigned int i=0; i<strlen(dep.DepType())+3; ++i) {
-						output << " ";
+				if (FirstOr == false) {
+					for (unsigned J = 0; J != strlen(End.DepType()) + 3; J++) {
+						out << ' ';
 					}
 				} else {
-					output << " " << first.DepType() << ": ";
+					out << ' ' << End.DepType() << ": ";
 				}
+				FirstOr = false;
 
-				is_first_of_or=false;
+				out << Start.TargetPkg().Name();
 
-				if (first.TargetVer()) {
-					output << first.TargetPkg().Name() << " (" << first.CompType() << " " << first.TargetVer() << ")";
-				} else {
-					output << first.TargetPkg().Name();
+				// Show a quick summary of the version requirements
+				if (Start.TargetVer() != 0) {
+					out << " (" << Start.CompType() << " " << Start.TargetVer() << ")";
 				}
 
-				// FIXME: handle virtual packages sanely.
-				pkgCache::PkgIterator target=first.TargetPkg();
-				// Don't skip real packages which are provided.
-				if (!target.VersionList().end())
-				{
-					output << " ";
-
-					pkgCache::VerIterator ver=(*m_apt->packageDepCache)[target].InstVerIter(*m_apt->packageDepCache);
+				/* Show a summary of the target package if possible. In the case
+				of virtual packages we show nothing */
+				pkgCache::PkgIterator Targ = Start.TargetPkg();
+				if (Targ->ProvidesList == 0) {
+					out << ' ';
+					pkgCache::VerIterator Ver = Cache[Targ].InstVerIter(Cache);
+					if (Now == true) {
+						Ver = Targ.CurrentVer();
+					}
 
-					if (!ver.end()) // ok, it's installable.
+					if (Ver.end() == false)
 					{
 						char buffer[1024];
-						if ((*m_apt->packageDepCache)[target].Install()) {
-							sprintf(buffer, "but %s is to be installed.",
-							    ver.VerStr());
-						} else if ((*m_apt->packageDepCache)[target].Upgradable()) {
-							sprintf(buffer, "but %s is installed and it is kept back.",
-							    target.CurrentVer().VerStr());
+						if (Now == true) {
+							sprintf(buffer, "but %s is installed", Ver.VerStr());
 						} else {
-							sprintf(buffer, "but %s is installed.",
-							    target.CurrentVer().VerStr());
+							sprintf(buffer, "but %s is to be installed", Ver.VerStr());
 						}
-						output << buffer;
+
+						out << buffer;
 					} else {
-					    output << "but it is not installable";
+						if (Cache[Targ].CandidateVerIter(Cache).end() == true) {
+							if (Targ->ProvidesList == 0) {
+							    out << "but it is not installable";
+							} else {
+							    out << "but it is a virtual package";
+							}
+						} else {
+							if (Now) {
+							    out << "but it is not installed";
+							} else {
+							    out << "but it is not going to be installed";
+							}
+						}
 					}
-				} else {
-				    // FIXME: do something sensible here!
-				    output << " which is a virtual package.";
 				}
 
-				if (first != dep) {
-				    output << " or";
+				if (Start != End) {
+					out << " or";
 				}
+				out << endl;
 
-				output << endl;
-
-				prev=first;
-				++first;
-			} while (prev != dep);
-		}
-	}
-	return output.str();
-}
-
-bool show_broken(PkBackend *backend, aptcc *m_apt)
-{
-	pkgvector broken;
-	for (pkgCache::PkgIterator i = m_apt->packageDepCache->PkgBegin();
-	    !i.end(); ++i)
-	{
-		if((*m_apt->packageDepCache)[i].InstBroken())
-			broken.push_back(i);
-	}
-
-	if (!broken.empty())
-	    {
-		stringstream out;
-		out << "The following packages have unmet dependencies:" << endl;
-
-		for (pkgvector::iterator pkg = broken.begin(); pkg != broken.end(); ++pkg) {
-			out << show_broken_deps(m_apt, *pkg);
+				if (Start == End){
+					break;
+				}
+				Start++;
+			}
 		}
-
-		pk_backend_error_code (backend, PK_ERROR_ENUM_DEP_RESOLUTION_FAILED, out.str().c_str());
-
-		return false;
 	}
-
-	return true;
+	pk_backend_error_code (backend, PK_ERROR_ENUM_DEP_RESOLUTION_FAILED, out.str().c_str());
 }
diff --git a/backends/aptcc/aptcc_show_broken.h b/backends/aptcc/aptcc_show_broken.h
index d2c07d4..7aa5adf 100644
--- a/backends/aptcc/aptcc_show_broken.h
+++ b/backends/aptcc/aptcc_show_broken.h
@@ -1,22 +1,22 @@
 // aptcc_show_broken.h                  -*-c++-*-
 //
 //   Copyright 2004 Daniel Burrows
+//   Copyright 2009-2010 Daniel Nicoletti
 
 #ifndef APTCC_SHOW_BROKEN_H
 #define APTCC_SHOW_BROKEN_H
 
 #include <pk-backend.h>
 
-class aptcc;
+#include <apt-pkg/cachefile.h>
+
 /** \file aptcc_show_broken.h
  */
 
 /** Shows a list of all broken packages together with their
  *  dependencies.  Similar to and based on the equivalent routine in
  *  apt-get.
- *
- *  Returns \b false if some packages are broken.
  */
-bool show_broken(PkBackend *backend, aptcc *m_apt);
+void show_broken(PkBackend *backend, pkgCacheFile &cache, bool Now);
 
 #endif // APTCC_SHOW_BROKEN
diff --git a/backends/aptcc/pk-backend-aptcc.cpp b/backends/aptcc/pk-backend-aptcc.cpp
index e287b72..63827d9 100644
--- a/backends/aptcc/pk-backend-aptcc.cpp
+++ b/backends/aptcc/pk-backend-aptcc.cpp
@@ -369,7 +369,9 @@ static gboolean
 backend_get_or_update_system_thread (PkBackend *backend)
 {
 	PkBitfield filters;
+	bool getUpdates;
 	filters = (PkBitfield) pk_backend_get_uint (backend, "filters");
+	getUpdates = pk_backend_get_bool(backend, "getUpdates");
 	pk_backend_set_allow_cancel (backend, true);
 
 	aptcc *m_apt = new aptcc(backend, _cancel);
@@ -383,9 +385,29 @@ backend_get_or_update_system_thread (PkBackend *backend)
 
 	pk_backend_set_status (backend, PK_STATUS_ENUM_QUERY);
 
-	if (pkgDistUpgrade(*m_apt->packageDepCache) == false)
+	pkgCacheFile Cache;
+	OpTextProgress Prog(*_config);
+	int timeout = 10;
+	// TODO test this
+	while (Cache.Open(Prog, !getUpdates) == false) {
+		// failed to open cache, try checkDeps then..
+		// || Cache.CheckDeps(CmdL.FileSize() != 1) == false
+		if (getUpdates == true || (timeout <= 0)) {
+			pk_backend_error_code(backend,
+					      PK_ERROR_ENUM_NO_CACHE,
+					      "Could not open package cache.");
+			return false;
+		} else {
+			pk_backend_set_status (backend, PK_STATUS_ENUM_WAITING_FOR_LOCK);
+			sleep(1);
+			timeout--;
+		}
+	}
+	pk_backend_set_status (backend, PK_STATUS_ENUM_RUNNING);
+
+	if (pkgDistUpgrade(*Cache) == false)
 	{
-		show_broken(backend, m_apt);
+		show_broken(backend, Cache, false);
 		egg_debug ("Internal error, DistUpgrade broke stuff");
 		delete m_apt;
 		pk_backend_finished (backend);
@@ -393,7 +415,7 @@ backend_get_or_update_system_thread (PkBackend *backend)
 	}
 
 	bool res = true;
-	if (pk_backend_get_bool(backend, "getUpdates")) {
+	if (getUpdates) {
 		vector<pair<pkgCache::PkgIterator, pkgCache::VerIterator> > update,
 									    kept;
 
@@ -401,13 +423,13 @@ backend_get_or_update_system_thread (PkBackend *backend)
 		    !pkg.end();
 		    ++pkg)
 		{
-			if((*m_apt->packageDepCache)[pkg].Upgrade()    == true &&
-			(*m_apt->packageDepCache)[pkg].NewInstall() == false) {
+			if((*Cache)[pkg].Upgrade()    == true &&
+			(*Cache)[pkg].NewInstall() == false) {
 				update.push_back(
 					pair<pkgCache::PkgIterator, pkgCache::VerIterator>(pkg, m_apt->find_candidate_ver(pkg)));
-			} else if ((*m_apt->packageDepCache)[pkg].Upgradable() == true &&
+			} else if ((*Cache)[pkg].Upgradable() == true &&
 				pkg->CurrentVer != 0 &&
-				(*m_apt->packageDepCache)[pkg].Delete() == false) {
+				(*Cache)[pkg].Delete() == false) {
 				kept.push_back(
 					pair<pkgCache::PkgIterator, pkgCache::VerIterator>(pkg, m_apt->find_candidate_ver(pkg)));
 			}
@@ -416,7 +438,7 @@ backend_get_or_update_system_thread (PkBackend *backend)
 		m_apt->emitUpdates(update, filters);
 		m_apt->emit_packages(kept, filters, PK_INFO_ENUM_BLOCKED);
 	} else {
-		res = m_apt->installPackages(*m_apt->packageDepCache, true);
+		res = m_apt->installPackages(Cache, true);
 	}
 
 	delete m_apt;
commit db726c31a383622ccaedbcf752d40feeb6b6bbc0
Author: yurchor <yurchor at fedoraproject.org>
Date:   Tue Mar 2 12:34:39 2010 +0000

    Sending translation for Ukrainian

diff --git a/po/uk.po b/po/uk.po
index 4314a1b..bad95ac 100644
--- a/po/uk.po
+++ b/po/uk.po
@@ -2,13 +2,13 @@
 # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
 # This file is distributed under the same license as the PackageKit package.
 #
-# Yuri Chornoivan <yurchor at ukr.net>, 2009.
+# Yuri Chornoivan <yurchor at ukr.net>, 2009, 2010.
 msgid ""
 msgstr ""
 "Project-Id-Version: packagekit.master\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2009-10-03 15:49+0000\n"
-"PO-Revision-Date: 2009-10-03 19:17+0300\n"
+"POT-Creation-Date: 2010-03-02 09:15+0000\n"
+"PO-Revision-Date: 2010-03-02 14:32+0200\n"
 "Last-Translator: Yuri Chornoivan <yurchor at ukr.net>\n"
 "Language-Team: Ukrainian <translation at linux.org.ua>\n"
 "MIME-Version: 1.0\n"
@@ -16,128 +16,131 @@ msgstr ""
 "Content-Transfer-Encoding: 8bit\n"
 "Plural-Forms:  nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && "
 "n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n"
-"X-Generator: Lokalize 0.3\n"
+"X-Generator: Lokalize 1.0\n"
 
 #. TRANSLATORS: this is an atomic transaction
-#: ../client/pk-console.c:143
+#. TRANSLATORS: the role is the point of the transaction, e.g. update-system
+#: ../client/pk-console.c:175 ../client/pk-console.c:597
 msgid "Transaction"
 msgstr "Операція"
 
 #. TRANSLATORS: this is the time the transaction was started in system timezone
-#: ../client/pk-console.c:145
+#: ../client/pk-console.c:177
 msgid "System time"
 msgstr "Системний час"
 
 #. TRANSLATORS: this is if the transaction succeeded or not
-#: ../client/pk-console.c:147
+#: ../client/pk-console.c:179
 msgid "Succeeded"
 msgstr "Успішне"
 
-#: ../client/pk-console.c:147
+#: ../client/pk-console.c:179
 msgid "True"
 msgstr "Так"
 
-#: ../client/pk-console.c:147
+#: ../client/pk-console.c:179
 msgid "False"
 msgstr "Ні"
 
 #. TRANSLATORS: this is the transactions role, e.g. "update-system"
 #. TRANSLATORS: the trasaction role, e.g. update-system
-#: ../client/pk-console.c:149 ../src/pk-polkit-action-lookup.c:336
+#: ../client/pk-console.c:181 ../src/pk-polkit-action-lookup.c:332
 msgid "Role"
 msgstr "Роль"
 
 #. TRANSLATORS: this is The duration of the transaction
-#: ../client/pk-console.c:154
+#: ../client/pk-console.c:186
 msgid "Duration"
 msgstr "Тривалість"
 
-#: ../client/pk-console.c:154
+#: ../client/pk-console.c:186
 msgid "(seconds)"
 msgstr "(секунд)"
 
 #. TRANSLATORS: this is The command line used to do the action
 #. TRANSLATORS: the command line of the thing that wants the authentication
-#: ../client/pk-console.c:158 ../src/pk-polkit-action-lookup.c:350
+#: ../client/pk-console.c:190 ../src/pk-polkit-action-lookup.c:346
 msgid "Command line"
 msgstr "Командний рядок"
 
 #. TRANSLATORS: this is the user ID of the user that started the action
-#: ../client/pk-console.c:160
+#: ../client/pk-console.c:192
 msgid "User ID"
 msgstr "ІД користувача"
 
 #. TRANSLATORS: this is the username, e.g. hughsie
-#: ../client/pk-console.c:167
+#: ../client/pk-console.c:199
 msgid "Username"
 msgstr "Користувач"
 
 #. TRANSLATORS: this is the users real name, e.g. "Richard Hughes"
-#: ../client/pk-console.c:171
+#: ../client/pk-console.c:203
 msgid "Real name"
 msgstr "Справжнє ім’я"
 
-#: ../client/pk-console.c:179
+#: ../client/pk-console.c:211
 msgid "Affected packages:"
 msgstr "Задіяні пакунки:"
 
-#: ../client/pk-console.c:181
+#: ../client/pk-console.c:213
 msgid "Affected packages: None"
 msgstr "Задіяні пакунки: Немає"
 
 #. TRANSLATORS: this is the distro, e.g. Fedora 10
-#: ../client/pk-console.c:201
+#: ../client/pk-console.c:248
 msgid "Distribution"
 msgstr "Дистрибутив"
 
 #. TRANSLATORS: this is type of update, stable or testing
-#: ../client/pk-console.c:203
+#: ../client/pk-console.c:250
 msgid "Type"
 msgstr "Тип"
 
 #. TRANSLATORS: this is any summary text describing the upgrade
 #. TRANSLATORS: this is the summary of the group
-#: ../client/pk-console.c:205 ../client/pk-console.c:226
+#: ../client/pk-console.c:252 ../client/pk-console.c:291
 msgid "Summary"
 msgstr "Резюме"
 
 #. TRANSLATORS: this is the group category name
-#: ../client/pk-console.c:215
+#: ../client/pk-console.c:280
 msgid "Category"
 msgstr "Категорія"
 
 #. TRANSLATORS: this is group identifier
-#: ../client/pk-console.c:217
+#: ../client/pk-console.c:282
 msgid "ID"
 msgstr "ІД"
 
 #. TRANSLATORS: this is the parent group
-#: ../client/pk-console.c:220
+#: ../client/pk-console.c:285
 msgid "Parent"
 msgstr "Батьківська"
 
 #. TRANSLATORS: this is the name of the parent group
-#: ../client/pk-console.c:223
+#: ../client/pk-console.c:288
 msgid "Name"
 msgstr "Назва"
 
 #. TRANSLATORS: this is preferred icon for the group
-#: ../client/pk-console.c:229
+#: ../client/pk-console.c:294
 msgid "Icon"
 msgstr "Значок"
 
 #. TRANSLATORS: this is a header for the package that can be updated
-#: ../client/pk-console.c:243
+#: ../client/pk-console.c:340
 msgid "Details about the update:"
 msgstr "Подробиці щодо оновлення:"
 
 #. TRANSLATORS: details about the update, package name and version
+#. TRANSLATORS: the package that is being processed
 #. TRANSLATORS: the package that is not signed by a known key
 #. TRANSLATORS: the package name that was trying to be installed
 #. TRANSLATORS: title, the names of the packages that the method is processing
-#: ../client/pk-console.c:249 ../lib/packagekit-glib2/pk-task-text.c:107
-#: ../lib/packagekit-glib2/pk-task-text.c:174
-#: ../src/pk-polkit-action-lookup.c:361
+#: ../client/pk-console.c:346 ../client/pk-console.c:616
+#: ../lib/packagekit-glib2/pk-task-text.c:126
+#: ../lib/packagekit-glib2/pk-task-text.c:208
+#: ../src/pk-polkit-action-lookup.c:357
 msgid "Package"
 msgid_plural "Packages"
 msgstr[0] "Пакунок"
@@ -145,141 +148,161 @@ msgstr[1] "Пакунки"
 msgstr[2] "Пакунки"
 
 #. TRANSLATORS: details about the update, any packages that this update updates
-#: ../client/pk-console.c:252
+#: ../client/pk-console.c:349
 msgid "Updates"
 msgstr "Оновлює"
 
 #. TRANSLATORS: details about the update, any packages that this update obsoletes
-#: ../client/pk-console.c:256
+#: ../client/pk-console.c:353
 msgid "Obsoletes"
 msgstr "Робить застарілим"
 
 #. TRANSLATORS: details about the update, the vendor URLs
 #. TRANSLATORS: the vendor (e.g. vmware) that is providing the EULA
-#: ../client/pk-console.c:260 ../lib/packagekit-glib2/pk-task-text.c:177
+#: ../client/pk-console.c:357 ../lib/packagekit-glib2/pk-task-text.c:211
 msgid "Vendor"
 msgstr "Постачальник"
 
 #. TRANSLATORS: details about the update, the bugzilla URLs
-#: ../client/pk-console.c:264
+#: ../client/pk-console.c:361
 msgid "Bugzilla"
 msgstr "Bugzilla"
 
 #. TRANSLATORS: details about the update, the CVE URLs
-#: ../client/pk-console.c:268
+#: ../client/pk-console.c:365
 msgid "CVE"
 msgstr "CVE"
 
 #. TRANSLATORS: details about the update, if the package requires a restart
-#: ../client/pk-console.c:272
+#: ../client/pk-console.c:369
 msgid "Restart"
 msgstr "Перезапуск"
 
 #. TRANSLATORS: details about the update, any description of the update
-#: ../client/pk-console.c:276
+#: ../client/pk-console.c:373
 msgid "Update text"
 msgstr "Текст оновлення"
 
 #. TRANSLATORS: details about the update, the changelog for the package
-#: ../client/pk-console.c:280
+#: ../client/pk-console.c:377
 msgid "Changes"
 msgstr "Зміни"
 
 #. TRANSLATORS: details about the update, the ongoing state of the update
-#: ../client/pk-console.c:284
+#: ../client/pk-console.c:381
 msgid "State"
 msgstr "Стан"
 
 #. TRANSLATORS: details about the update, date the update was issued
-#: ../client/pk-console.c:289
+#: ../client/pk-console.c:385
 msgid "Issued"
 msgstr "Випущено"
 
 #. TRANSLATORS: details about the update, date the update was updated
 #. TRANSLATORS: The action of the package, in past tense
-#: ../client/pk-console.c:294 ../lib/packagekit-glib2/pk-console-shared.c:502
+#: ../client/pk-console.c:389 ../lib/packagekit-glib2/pk-console-shared.c:510
 msgid "Updated"
 msgstr "Оновлено"
 
 #. TRANSLATORS: if the repo is enabled
-#: ../client/pk-console.c:312
+#: ../client/pk-console.c:425
 msgid "Enabled"
 msgstr "Увімкнено"
 
 #. TRANSLATORS: if the repo is disabled
-#: ../client/pk-console.c:315
+#: ../client/pk-console.c:428
 msgid "Disabled"
 msgstr "Вимкнено"
 
 #. TRANSLATORS: a package requires the system to be restarted
-#: ../client/pk-console.c:337
+#: ../client/pk-console.c:460
 msgid "System restart required by:"
 msgstr "Перезавантаження системи потрібне для:"
 
 #. TRANSLATORS: a package requires the session to be restarted
-#: ../client/pk-console.c:340
+#: ../client/pk-console.c:463
 msgid "Session restart required:"
 msgstr "Перезапуск сеансу потрібен:"
 
 #. TRANSLATORS: a package requires the system to be restarted due to a security update
-#: ../client/pk-console.c:343
+#: ../client/pk-console.c:466
 msgid "System restart (security) required by:"
 msgstr "Потрібне перезавантаження системи (безпека) для:"
 
 #. TRANSLATORS: a package requires the session to be restarted due to a security update
-#: ../client/pk-console.c:346
+#: ../client/pk-console.c:469
 msgid "Session restart (security) required:"
 msgstr "Потрібен перезапуск сеансу (безпека):"
 
 #. TRANSLATORS: a package requires the application to be restarted
-#: ../client/pk-console.c:349
+#: ../client/pk-console.c:472
 msgid "Application restart required by:"
 msgstr "Потрібен перезапуск програми для:"
 
 #. TRANSLATORS: This a list of details about the package
-#: ../client/pk-console.c:366
+#: ../client/pk-console.c:507
 msgid "Package description"
 msgstr "Опис пакунка"
 
 #. TRANSLATORS: This a message (like a little note that may be of interest) from the transaction
-#: ../client/pk-console.c:384
+#: ../client/pk-console.c:538
 msgid "Message:"
 msgstr "Повідомлення:"
 
 #. TRANSLATORS: This where the package has no files
-#: ../client/pk-console.c:398
+#: ../client/pk-console.c:559
 msgid "No files"
 msgstr "Без файлів"
 
 #. TRANSLATORS: This a list files contained in the package
-#: ../client/pk-console.c:403
+#: ../client/pk-console.c:564
 msgid "Package files"
 msgstr "Файли пакунка"
 
+#. TRANSLATORS: the percentage complete of the transaction
+#: ../client/pk-console.c:632
+msgid "Percentage"
+msgstr "Відсотки"
+
+#. TRANSLATORS: the status of the transaction (e.g. downloading)
+#: ../client/pk-console.c:650
+msgid "Status"
+msgstr "Стан"
+
+#. TRANSLATORS: the results from the transaction
+#: ../client/pk-console.c:679
+msgid "Results:"
+msgstr "Результат:"
+
 #. TRANSLATORS: we failed to get any results, which is pretty fatal in my book
-#: ../client/pk-console.c:475
+#: ../client/pk-console.c:686
 msgid "Fatal error"
 msgstr "Критична помилка"
 
 #. TRANSLATORS: the transaction failed in a way we could not expect
-#: ../client/pk-console.c:484
-#: ../contrib/command-not-found/pk-command-not-found.c:426
-#: ../contrib/command-not-found/pk-command-not-found.c:593
+#: ../client/pk-console.c:695
+#: ../contrib/command-not-found/pk-command-not-found.c:432
+#: ../contrib/command-not-found/pk-command-not-found.c:603
 msgid "The transaction failed"
 msgstr "Спроба виконання операції зазнала невдачі"
 
+#. TRANSLATORS: print a message when there are no updates
+#: ../client/pk-console.c:726
+msgid "There are no updates available at this time."
+msgstr "На поточний момент оновлень не виявлено."
+
 #. TRANSLATORS: a package needs to restart their system
-#: ../client/pk-console.c:552
+#: ../client/pk-console.c:814
 msgid "Please restart the computer to complete the update."
 msgstr "Щоб завершити оновлення, перезавантажте систему."
 
 #. TRANSLATORS: a package needs to restart the session
-#: ../client/pk-console.c:555
+#: ../client/pk-console.c:817
 msgid "Please logout and login to complete the update."
 msgstr "Щоб завершити оновлення, вийдіть з облікового запису і увійдіть знову."
 
 #. TRANSLATORS: a package needs to restart their system (due to security)
-#: ../client/pk-console.c:558
+#: ../client/pk-console.c:820
 msgid ""
 "Please restart the computer to complete the update as important security "
 "updates have been installed."
@@ -287,7 +310,7 @@ msgstr ""
 "перезавантажте систему, щоб завершити встановлення важливих оновлень безпеки."
 
 #. TRANSLATORS: a package needs to restart the session (due to security)
-#: ../client/pk-console.c:561
+#: ../client/pk-console.c:823
 msgid ""
 "Please logout and login to complete the update as important security updates "
 "have been installed."
@@ -295,20 +318,30 @@ msgstr ""
 "Щоб завершити встановлення важливих оновлень безпеки вийдіть з облікового "
 "запису і увійдіть до нього знову."
 
+#. TRANSLATORS: The user used 'pkcon install dave.rpm' rather than 'pkcon install-local dave.rpm'
+#: ../client/pk-console.c:849
+#, c-format
+msgid ""
+"Extected package name, actually got file. Try using 'pkcon install-local %s' "
+"instead."
+msgstr ""
+"Мало бути передано назву пакунка, передано файл. Спробуйте скористатися "
+"командою «pkcon install-local %s»."
+
 #. TRANSLATORS: There was an error getting the list of files for the package. The detailed error follows
-#: ../client/pk-console.c:584
+#: ../client/pk-console.c:857
 #, c-format
 msgid "This tool could not find any available package: %s"
 msgstr "Програмі не вдалося знайти жодного доступного пакунка: %s"
 
 #. TRANSLATORS: There was an error getting the list of files for the package. The detailed error follows
-#: ../client/pk-console.c:612
+#: ../client/pk-console.c:885
 #, c-format
 msgid "This tool could not find the installed package: %s"
 msgstr "Програмі не вдалося знайти встановлений пакунок: %s"
 
 #. TRANSLATORS: There was an error getting the list of files for the package. The detailed error follows
-#: ../client/pk-console.c:640 ../client/pk-console.c:668
+#: ../client/pk-console.c:913 ../client/pk-console.c:941
 #, c-format
 msgid "This tool could not find the package: %s"
 msgstr "Програмі не вдалося знайти пакунок: %s"
@@ -317,194 +350,192 @@ msgstr "Програмі не вдалося знайти пакунок: %s"
 #. TRANSLATORS: There was an error getting the dependencies for the package. The detailed error follows
 #. TRANSLATORS: There was an error getting the details about the package. The detailed error follows
 #. TRANSLATORS: The package name was not found in any software sources. The detailed error follows
-#: ../client/pk-console.c:696 ../client/pk-console.c:724
-#: ../client/pk-console.c:752 ../client/pk-console.c:780
-#: ../client/pk-console.c:808
+#: ../client/pk-console.c:969 ../client/pk-console.c:997
+#: ../client/pk-console.c:1025 ../client/pk-console.c:1053
+#: ../client/pk-console.c:1081
 #, c-format
 msgid "This tool could not find all the packages: %s"
 msgstr "Програмі не вдалося знайти всі пакунки: %s"
 
 #. TRANSLATORS: This is when the daemon crashed, and we are up shit creek without a paddle
-#: ../client/pk-console.c:837
+#: ../client/pk-console.c:1110
 msgid "The daemon crashed mid-transaction!"
 msgstr "Аварійне завершення фонової служби під час операції!"
 
 #. TRANSLATORS: This is the header to the --help menu
-#: ../client/pk-console.c:871
+#: ../client/pk-console.c:1144
 msgid "PackageKit Console Interface"
 msgstr "Консольний інтерфейс PackageKit"
 
 #. these are commands we can use with pkcon
-#: ../client/pk-console.c:873
+#: ../client/pk-console.c:1146
 msgid "Subcommands:"
 msgstr "Підкоманди:"
 
 #. TRANSLATORS: we keep a database updated with the time that an action was last executed
-#: ../client/pk-console.c:952
+#: ../client/pk-console.c:1225
 msgid "Failed to get the time since this action was last completed"
 msgstr "Не вдалося визначити час, коли цю дію було виконано востаннє"
 
-#. TRANSLATORS: command line argument, if we should show debugging information
-#. TRANSLATORS: if we should show debugging data
-#: ../client/pk-console.c:989 ../client/pk-generate-pack.c:223
-#: ../client/pk-monitor.c:281
-#: ../contrib/command-not-found/pk-command-not-found.c:646
-#: ../contrib/debuginfo-install/pk-debuginfo-install.c:512
-#: ../contrib/device-rebind/pk-device-rebind.c:293 ../src/pk-main.c:211
-msgid "Show extra debugging information"
-msgstr "Показувати додаткові дані для усування вад"
-
 #. TRANSLATORS: command line argument, just show the version string
-#: ../client/pk-console.c:992 ../client/pk-monitor.c:283
+#: ../client/pk-console.c:1261 ../client/pk-monitor.c:306
 msgid "Show the program version and exit"
 msgstr "Показати версію програми і завершити роботу"
 
 #. TRANSLATORS: command line argument, use a filter to narrow down results
-#: ../client/pk-console.c:995
+#: ../client/pk-console.c:1264
 msgid "Set the filter, e.g. installed"
 msgstr "Встановити фільтр, наприклад, встановлені"
 
 #. TRANSLATORS: command line argument, work asynchronously
-#: ../client/pk-console.c:998
+#: ../client/pk-console.c:1267
 msgid "Exit without waiting for actions to complete"
 msgstr "Завершити роботу, не чекаючи на завершення дії"
 
 #. command line argument, do we ask questions
-#: ../client/pk-console.c:1001
-#: ../contrib/debuginfo-install/pk-debuginfo-install.c:524
+#: ../client/pk-console.c:1270
+#: ../contrib/debuginfo-install/pk-debuginfo-install.c:527
 msgid "Install the packages without asking for confirmation"
 msgstr "Встановити пакунки без запиту щодо підтвердження"
 
 #. TRANSLATORS: command line argument, this command is not a priority
-#: ../client/pk-console.c:1004
+#: ../client/pk-console.c:1273
 msgid "Run the command using idle network bandwidth and also using less power"
 msgstr ""
 "Виконати команду з мінімальним використанням мережевого каналу і меншою "
 "витратою ресурсів системи"
 
+#. TRANSLATORS: command line argument, just output without fancy formatting
+#: ../client/pk-console.c:1276
+msgid ""
+"Print to screen a machine readable output, rather than using animated widgets"
+msgstr ""
+"Вивести дані про поступ у простому текстовому форматі, без використання "
+"анімованих віджетів"
+
 #. TRANSLATORS: we failed to contact the daemon
-#: ../client/pk-console.c:1030
+#: ../client/pk-console.c:1298
 msgid "Failed to contact PackageKit"
 msgstr "Не вдалося зв’язатися з PackageKit"
 
 #. TRANSLATORS: The user specified an incorrect filter
-#: ../client/pk-console.c:1086
+#: ../client/pk-console.c:1356
 msgid "The filter specified was invalid"
 msgstr "Вказано некоректний фільтр"
 
 #. TRANSLATORS: a search type can be name, details, file, etc
-#: ../client/pk-console.c:1105
+#: ../client/pk-console.c:1375
 msgid "A search type is required, e.g. name"
 msgstr "Тип пошуку, якщо такий потрібен, наприклад, назва"
 
 #. TRANSLATORS: the user needs to provide a search term
-#: ../client/pk-console.c:1112 ../client/pk-console.c:1124
-#: ../client/pk-console.c:1136 ../client/pk-console.c:1148
+#: ../client/pk-console.c:1382 ../client/pk-console.c:1394
+#: ../client/pk-console.c:1406 ../client/pk-console.c:1418
 msgid "A search term is required"
 msgstr "Потрібен ключ пошуку"
 
 #. TRANSLATORS: the search type was provided, but invalid
-#: ../client/pk-console.c:1158
+#: ../client/pk-console.c:1428
 msgid "Invalid search type"
 msgstr "Некоректний тип пошуку"
 
 #. TRANSLATORS: the user did not specify what they wanted to install
-#: ../client/pk-console.c:1164
+#: ../client/pk-console.c:1434
 msgid "A package name to install is required"
 msgstr "Слід вказати назву пакунка, який слід встановити"
 
 #. TRANSLATORS: the user did not specify what they wanted to install
-#: ../client/pk-console.c:1173
+#: ../client/pk-console.c:1443
 msgid "A filename to install is required"
 msgstr "Слід вказати назву файла, який слід встановити"
 
 #. TRANSLATORS: geeky error, 99.9999% of users won't see this
-#: ../client/pk-console.c:1185
+#: ../client/pk-console.c:1455
 msgid "A type, key_id and package_id are required"
 msgstr "Слід вказати тип, ідентифікатор ключа і ідентифікатор пакунка"
 
 #. TRANSLATORS: the user did not specify what they wanted to remove
-#: ../client/pk-console.c:1196
+#: ../client/pk-console.c:1466
 msgid "A package name to remove is required"
 msgstr "Слід вказати назву пакунка, який потрібно вилучити"
 
 #. TRANSLATORS: the user did not specify anything about what to download or where
-#: ../client/pk-console.c:1205
+#: ../client/pk-console.c:1475
 msgid "A destination directory and the package names to download are required"
 msgstr ""
 "Слід вказати каталог призначення і назви пакунків, які потрібно звантажити"
 
 #. TRANSLATORS: the directory does not exist, so we can't continue
-#: ../client/pk-console.c:1212
+#: ../client/pk-console.c:1482
 msgid "Directory not found"
 msgstr "Каталог не знайдено"
 
 #. TRANSLATORS: geeky error, 99.9999% of users won't see this
-#: ../client/pk-console.c:1221
+#: ../client/pk-console.c:1491
 msgid "A licence identifier (eula-id) is required"
 msgstr "Слід вказати ідентифікатор ліцензії (eula-id)"
 
 #. TRANSLATORS: geeky error, 99.9999% of users won't see this
-#: ../client/pk-console.c:1232
+#: ../client/pk-console.c:1502
 msgid "A transaction identifier (tid) is required"
 msgstr "Слід вказати ідентифікатор операції (tid)"
 
 #. TRANSLATORS: The user did not specify a package name
-#: ../client/pk-console.c:1253
+#: ../client/pk-console.c:1523
 msgid "A package name to resolve is required"
 msgstr "Слід вказати назву пакунка для розв’язання конфлікту"
 
 #. TRANSLATORS: The user did not specify a repository (software source) name
-#: ../client/pk-console.c:1264 ../client/pk-console.c:1275
+#: ../client/pk-console.c:1534 ../client/pk-console.c:1545
 msgid "A repository name is required"
 msgstr "Слід вказати назву сховища"
 
 #. TRANSLATORS: The user didn't provide any data
-#: ../client/pk-console.c:1286
+#: ../client/pk-console.c:1556
 msgid "A repo name, parameter and value are required"
 msgstr "Слід вказати назву сховища, параметр і значення"
 
 #. TRANSLATORS: The user didn't specify what action to use
-#: ../client/pk-console.c:1303
+#: ../client/pk-console.c:1573
 msgid "An action, e.g. 'update-system' is required"
 msgstr "Слід вказати дію, наприклад «update-system»"
 
 #. TRANSLATORS: The user specified an invalid action
-#: ../client/pk-console.c:1310
+#: ../client/pk-console.c:1580
 msgid "A correct role is required"
 msgstr "Слід вказати належну роль"
 
 #. TRANSLATORS: The user did not provide a package name
 #. TRANSLATORS: This is when the user fails to supply the package name
-#: ../client/pk-console.c:1320 ../client/pk-console.c:1335
-#: ../client/pk-console.c:1344 ../client/pk-console.c:1364
-#: ../client/pk-console.c:1373 ../client/pk-generate-pack.c:287
+#: ../client/pk-console.c:1590 ../client/pk-console.c:1605
+#: ../client/pk-console.c:1614 ../client/pk-console.c:1634
+#: ../client/pk-console.c:1643 ../client/pk-generate-pack.c:316
 msgid "A package name is required"
 msgstr "Слід вказати назву пакунка"
 
 #. TRANSLATORS: each package "provides" certain things, e.g. mime(gstreamer-decoder-mp3), the user didn't specify it
-#: ../client/pk-console.c:1353
+#: ../client/pk-console.c:1623
 msgid "A package provide string is required"
 msgstr "Слід вказати рядок вмісту"
 
 #. TRANSLATORS: The user tried to use an unsupported option on the command line
-#: ../client/pk-console.c:1433
+#: ../client/pk-console.c:1703
 #, c-format
 msgid "Option '%s' is not supported"
 msgstr "Підтримки параметра «%s» не передбачено"
 
 #. TRANSLATORS: Generic failure of what they asked to do
-#: ../client/pk-console.c:1443
+#: ../client/pk-console.c:1713
 msgid "Command failed"
 msgstr "Спроба виконання команди зазнала невдачі"
 
 #. TRANSLATORS: we can exclude certain packages (glibc) when we know they'll exist on the target
-#: ../client/pk-generate-pack.c:226
+#: ../client/pk-generate-pack.c:255
 msgid "Set the file name of dependencies to be excluded"
 msgstr "Вкажіть назви файлів залежностей, які слід виключити"
 
 #. TRANSLATORS: the output location
-#: ../client/pk-generate-pack.c:229
+#: ../client/pk-generate-pack.c:258
 msgid ""
 "The output file or directory (the current directory is used if ommitted)"
 msgstr ""
@@ -512,43 +543,43 @@ msgstr ""
 "каталог)"
 
 #. TRANSLATORS: put a list of packages in the pack
-#: ../client/pk-generate-pack.c:232
+#: ../client/pk-generate-pack.c:261
 msgid "The package to be put into the service pack"
 msgstr "Пакунок, призначений для створення пакунка обслуговування"
 
 #. TRANSLATORS: put all pending updates in the pack
-#: ../client/pk-generate-pack.c:235
+#: ../client/pk-generate-pack.c:264
 msgid "Put all updates available in the service pack"
 msgstr "Додати всі можливі оновлення до пакунка з обслуговування"
 
 #. TRANSLATORS: This is when the user fails to supply the correct arguments
-#: ../client/pk-generate-pack.c:271
+#: ../client/pk-generate-pack.c:300
 msgid "Neither --package or --updates option selected."
 msgstr "Не обрано ні параметра --package, ні параметра --updates."
 
 #. TRANSLATORS: This is when the user fails to supply just one argument
-#: ../client/pk-generate-pack.c:279
+#: ../client/pk-generate-pack.c:308
 msgid "Both options selected."
 msgstr "Обрано обидва параметра."
 
 #. TRANSLATORS: This is when the user fails to supply the output
-#: ../client/pk-generate-pack.c:295
+#: ../client/pk-generate-pack.c:324
 msgid "A output directory or file name is required"
 msgstr "Слід вказати каталог або файл для виведення даних"
 
 #. TRANSLATORS: This is when the dameon is not-installed/broken and fails to startup
-#: ../client/pk-generate-pack.c:313
+#: ../client/pk-generate-pack.c:342
 msgid "The dameon failed to startup"
 msgstr "Не вдалося запустити фонову службу"
 
 #. TRANSLATORS: This is when the backend doesn't have the capability to get-depends
 #. TRANSLATORS: This is when the backend doesn't have the capability to download
-#: ../client/pk-generate-pack.c:324 ../client/pk-generate-pack.c:330
+#: ../client/pk-generate-pack.c:353 ../client/pk-generate-pack.c:359
 msgid "The package manager cannot perform this type of operation."
 msgstr "Керування пакунками не може виконувати дії цього типу."
 
 #. TRANSLATORS: This is when the distro didn't include libarchive support into PK
-#: ../client/pk-generate-pack.c:337
+#: ../client/pk-generate-pack.c:366
 msgid ""
 "Service packs cannot be created as PackageKit was not built with libarchive "
 "support."
@@ -557,213 +588,213 @@ msgstr ""
 "зібрано без підтримки libarchive."
 
 #. TRANSLATORS: the user specified an absolute path, but didn't get the extension correct
-#: ../client/pk-generate-pack.c:348
+#: ../client/pk-generate-pack.c:377
 msgid "If specifying a file, the service pack name must end with"
 msgstr "Якщо вказано файл, назва пакунка з обслуговування має завершуватися на"
 
 #. TRANSLATORS: This is when file already exists
-#: ../client/pk-generate-pack.c:364
+#: ../client/pk-generate-pack.c:393
 msgid "A pack with the same name already exists, do you want to overwrite it?"
 msgstr "Вже існує пакунок з тією самою назвою, бажаєте перезаписати його?"
 
 #. TRANSLATORS: This is when the pack was not overwritten
-#: ../client/pk-generate-pack.c:367
+#: ../client/pk-generate-pack.c:396
 msgid "The pack was not overwritten."
 msgstr "Пакунок не було перезаписано."
 
 #. TRANSLATORS: This is when the temporary directory cannot be created, the directory name follows
-#: ../client/pk-generate-pack.c:380
+#: ../client/pk-generate-pack.c:409
 msgid "Failed to create directory:"
 msgstr "Спроба створення каталогу завершилася невдало:"
 
 #. TRANSLATORS: This is when the list of packages from the remote computer cannot be opened
-#: ../client/pk-generate-pack.c:392
+#: ../client/pk-generate-pack.c:421
 msgid "Failed to open package list."
 msgstr "Не вдалося відкрити список пакунків."
 
 #. TRANSLATORS: The package name is being matched up to available packages
-#: ../client/pk-generate-pack.c:401
+#: ../client/pk-generate-pack.c:430
 msgid "Finding package name."
 msgstr "Пошук назви пакунка."
 
 #. TRANSLATORS: This is when the package cannot be found in any software source. The detailed error follows
-#: ../client/pk-generate-pack.c:405
+#: ../client/pk-generate-pack.c:434
 #, c-format
 msgid "Failed to find package '%s': %s"
 msgstr "Не вдалося знайти пакунок «%s»: %s"
 
 #. TRANSLATORS: This is telling the user we are in the process of making the pack
-#: ../client/pk-generate-pack.c:413
+#: ../client/pk-generate-pack.c:442
 msgid "Creating service pack..."
 msgstr "Створення пакунка з обслуговування..."
 
 #. TRANSLATORS: we succeeded in making the file
-#: ../client/pk-generate-pack.c:428
+#: ../client/pk-generate-pack.c:457
 #, c-format
 msgid "Service pack created '%s'"
 msgstr "Створено пакунок з обслуговування «%s»"
 
 #. TRANSLATORS: we failed to make te file
-#: ../client/pk-generate-pack.c:433
+#: ../client/pk-generate-pack.c:462
 #, c-format
 msgid "Failed to create '%s': %s"
 msgstr "Не вдалося створити «%s»: %s"
 
-#: ../client/pk-monitor.c:211
+#: ../client/pk-monitor.c:236
 msgid "Failed to get daemon state"
 msgstr "Спроба визначення стану фонової служби завершилася невдало"
 
 #. TRANSLATORS: this is a program that monitors PackageKit
-#: ../client/pk-monitor.c:299
+#: ../client/pk-monitor.c:322
 msgid "PackageKit Monitor"
 msgstr "Монітор PackageKit"
 
 #. TRANSLATORS: when we are getting data from the daemon
-#: ../contrib/browser-plugin/pk-plugin-install.c:491
+#: ../contrib/browser-plugin/pk-plugin-install.c:495
 msgid "Getting package information..."
 msgstr "Отримання даних щодо пакунка..."
 
 #. TRANSLATORS: run an applicaiton
-#: ../contrib/browser-plugin/pk-plugin-install.c:497
+#: ../contrib/browser-plugin/pk-plugin-install.c:501
 #, c-format
 msgid "Run %s"
 msgstr "Виконати %s"
 
 #. TRANSLATORS: show the installed version of a package
-#: ../contrib/browser-plugin/pk-plugin-install.c:503
+#: ../contrib/browser-plugin/pk-plugin-install.c:507
 msgid "Installed version"
 msgstr "Встановлена версія"
 
 #. TRANSLATORS: run the application now
-#: ../contrib/browser-plugin/pk-plugin-install.c:511
+#: ../contrib/browser-plugin/pk-plugin-install.c:515
 #, c-format
 msgid "Run version %s now"
 msgstr "Виконати версію %s"
 
 #. TRANSLATORS: run the application now
-#: ../contrib/browser-plugin/pk-plugin-install.c:517
+#: ../contrib/browser-plugin/pk-plugin-install.c:521
 msgid "Run now"
 msgstr "Виконати зараз"
 
 #. TRANSLATORS: update to a new version of the package
-#: ../contrib/browser-plugin/pk-plugin-install.c:523
+#: ../contrib/browser-plugin/pk-plugin-install.c:527
 #, c-format
 msgid "Update to version %s"
 msgstr "Оновити до версії %s"
 
 #. TRANSLATORS: To install a package
-#: ../contrib/browser-plugin/pk-plugin-install.c:529
+#: ../contrib/browser-plugin/pk-plugin-install.c:533
 #, c-format
 msgid "Install %s now"
 msgstr "Встановити %s"
 
 #. TRANSLATORS: the version of the package
-#: ../contrib/browser-plugin/pk-plugin-install.c:532
+#: ../contrib/browser-plugin/pk-plugin-install.c:536
 msgid "Version"
 msgstr "Версія"
 
 #. TRANSLATORS: noting found, so can't install
-#: ../contrib/browser-plugin/pk-plugin-install.c:537
+#: ../contrib/browser-plugin/pk-plugin-install.c:541
 msgid "No packages found for your system"
 msgstr "Для вашої системи пакунків не знайдено"
 
 #. TRANSLATORS: package is being installed
-#: ../contrib/browser-plugin/pk-plugin-install.c:542
+#: ../contrib/browser-plugin/pk-plugin-install.c:546
 msgid "Installing..."
 msgstr "Встановлення..."
 
 #. TRANSLATORS: downloading repo data so we can search
-#: ../contrib/command-not-found/pk-command-not-found.c:361
+#: ../contrib/command-not-found/pk-command-not-found.c:365
 msgid "Downloading details about the software sources."
 msgstr "Звантаження даних щодо джерел програмного забезпечення."
 
 #. TRANSLATORS: downloading file lists so we can search
-#: ../contrib/command-not-found/pk-command-not-found.c:365
+#: ../contrib/command-not-found/pk-command-not-found.c:369
 msgid "Downloading filelists (this may take some time to complete)."
 msgstr ""
 "Звантаження списків файлів (виконання цієї дії може бути досить тривалим)."
 
 #. TRANSLATORS: waiting for native lock
-#: ../contrib/command-not-found/pk-command-not-found.c:369
+#: ../contrib/command-not-found/pk-command-not-found.c:373
 msgid "Waiting for package manager lock."
 msgstr "Очікування на зняття блокування керування пакунками."
 
 #. TRANSLATORS: loading package cache so we can search
-#: ../contrib/command-not-found/pk-command-not-found.c:373
+#: ../contrib/command-not-found/pk-command-not-found.c:377
 msgid "Loading list of packages."
 msgstr "Завантаження списку пакунків."
 
 #. TRANSLATORS: we failed to find the package, this shouldn't happen
-#: ../contrib/command-not-found/pk-command-not-found.c:417
+#: ../contrib/command-not-found/pk-command-not-found.c:423
 msgid "Failed to search for file"
 msgstr "Не вдалося виконати пошук файла"
 
 #. TRANSLATORS: we failed to launch the executable, the error follows
-#: ../contrib/command-not-found/pk-command-not-found.c:556
+#: ../contrib/command-not-found/pk-command-not-found.c:566
 msgid "Failed to launch:"
 msgstr "Не вдалося запустити:"
 
 #. TRANSLATORS: we failed to install the package
-#: ../contrib/command-not-found/pk-command-not-found.c:584
+#: ../contrib/command-not-found/pk-command-not-found.c:594
 msgid "Failed to install packages"
 msgstr "Не вдалося встановити пакунки"
 
 #. TRANSLATORS: tool that gets called when the command is not found
-#: ../contrib/command-not-found/pk-command-not-found.c:662
+#: ../contrib/command-not-found/pk-command-not-found.c:670
 msgid "PackageKit Command Not Found"
 msgstr "Команди PackageKit не знайдено"
 
 #. TRANSLATORS: the prefix of all the output telling the user why it's not executing
-#: ../contrib/command-not-found/pk-command-not-found.c:690
+#: ../contrib/command-not-found/pk-command-not-found.c:699
 msgid "Command not found."
 msgstr "Команду не знайдено."
 
 #. TRANSLATORS: tell the user what we think the command is
-#: ../contrib/command-not-found/pk-command-not-found.c:697
+#: ../contrib/command-not-found/pk-command-not-found.c:706
 msgid "Similar command is:"
 msgstr "Подібною командою є:"
 
 #. TRANSLATORS: Ask the user if we should run the similar command
-#: ../contrib/command-not-found/pk-command-not-found.c:706
+#: ../contrib/command-not-found/pk-command-not-found.c:716
 msgid "Run similar command:"
 msgstr "Виконати подібну команду:"
 
 #. TRANSLATORS: show the user a list of commands that they could have meant
 #. TRANSLATORS: show the user a list of commands we could run
-#: ../contrib/command-not-found/pk-command-not-found.c:718
-#: ../contrib/command-not-found/pk-command-not-found.c:727
+#: ../contrib/command-not-found/pk-command-not-found.c:730
+#: ../contrib/command-not-found/pk-command-not-found.c:739
 msgid "Similar commands are:"
 msgstr "Подібними командами є:"
 
 #. TRANSLATORS: ask the user to choose a file to run
-#: ../contrib/command-not-found/pk-command-not-found.c:734
+#: ../contrib/command-not-found/pk-command-not-found.c:746
 msgid "Please choose a command to run"
 msgstr "Будь ласка, оберіть команду, яку слід виконати"
 
 #. TRANSLATORS: tell the user what package provides the command
-#: ../contrib/command-not-found/pk-command-not-found.c:750
+#: ../contrib/command-not-found/pk-command-not-found.c:764
 msgid "The package providing this file is:"
 msgstr "Пакунком, що містити цей файл є:"
 
 #. TRANSLATORS: as the user if we want to install a package to provide the command
-#: ../contrib/command-not-found/pk-command-not-found.c:755
+#: ../contrib/command-not-found/pk-command-not-found.c:769
 #, c-format
 msgid "Install package '%s' to provide command '%s'?"
 msgstr "Встановити пакунок «%s», щоб забезпечити виконання команди «%s»?"
 
 #. TRANSLATORS: Show the user a list of packages that provide this command
-#: ../contrib/command-not-found/pk-command-not-found.c:775
+#: ../contrib/command-not-found/pk-command-not-found.c:793
 msgid "Packages providing this file are:"
 msgstr "Серед пакунків, що містять цей файл:"
 
 #. TRANSLATORS: Show the user a list of packages that they can install to provide this command
-#: ../contrib/command-not-found/pk-command-not-found.c:785
+#: ../contrib/command-not-found/pk-command-not-found.c:803
 msgid "Suitable packages are:"
 msgstr "Відповідними пакунками є:"
 
 #. get selection
 #. TRANSLATORS: ask the user to choose a file to install
-#: ../contrib/command-not-found/pk-command-not-found.c:794
+#: ../contrib/command-not-found/pk-command-not-found.c:812
 msgid "Please choose a package to install"
 msgstr "Будь ласка, оберіть пакунок, який слід встановити"
 
@@ -779,271 +810,275 @@ msgid "Failed to find the package %s, or already installed: %s"
 msgstr "Не вдалося знайти пакунок %s або пакунок вже встановлено: %s"
 
 #. command line argument, simulate what would be done, but don't actually do it
-#: ../contrib/debuginfo-install/pk-debuginfo-install.c:515
+#: ../contrib/debuginfo-install/pk-debuginfo-install.c:518
 msgid ""
 "Don't actually install any packages, only simulate what would be installed"
 msgstr "Не встановлювати пакунків, лише імітувати їх встановлення"
 
 #. command line argument, do we skip packages that depend on the ones specified
-#: ../contrib/debuginfo-install/pk-debuginfo-install.c:518
+#: ../contrib/debuginfo-install/pk-debuginfo-install.c:521
 msgid "Do not install dependencies of the core packages"
 msgstr "Не встановлювати залежностей основних пакунків"
 
 #. command line argument, do we operate quietly
-#: ../contrib/debuginfo-install/pk-debuginfo-install.c:521
+#: ../contrib/debuginfo-install/pk-debuginfo-install.c:524
 msgid "Do not display information or progress"
 msgstr "Не показувати повідомлень та даних про поступ"
 
 #. TRANSLATORS: tool that gets called when the command is not found
-#: ../contrib/debuginfo-install/pk-debuginfo-install.c:539
+#: ../contrib/debuginfo-install/pk-debuginfo-install.c:542
 msgid "PackageKit Debuginfo Installer"
 msgstr "Встановлення даних для зневаджування PackageKit"
 
 #. TRANSLATORS: the use needs to specify a list of package names on the command line
-#: ../contrib/debuginfo-install/pk-debuginfo-install.c:554
+#: ../contrib/debuginfo-install/pk-debuginfo-install.c:556
 #, c-format
 msgid "ERROR: Specify package names to install."
 msgstr "ПОМИЛКА: вкажіть назви пакунків, які слід встановити."
 
 #. TRANSLATORS: we are getting the list of repositories
-#: ../contrib/debuginfo-install/pk-debuginfo-install.c:590
+#: ../contrib/debuginfo-install/pk-debuginfo-install.c:592
 #, c-format
 msgid "Getting sources list"
 msgstr "Отримання списку джерел"
 
 #. TRANSLATORS: operation was not successful
-#: ../contrib/debuginfo-install/pk-debuginfo-install.c:600
-#: ../contrib/debuginfo-install/pk-debuginfo-install.c:675
-#: ../contrib/debuginfo-install/pk-debuginfo-install.c:759
-#: ../contrib/debuginfo-install/pk-debuginfo-install.c:803
-#: ../contrib/debuginfo-install/pk-debuginfo-install.c:870
-#: ../contrib/debuginfo-install/pk-debuginfo-install.c:914
+#: ../contrib/debuginfo-install/pk-debuginfo-install.c:602
+#: ../contrib/debuginfo-install/pk-debuginfo-install.c:677
+#: ../contrib/debuginfo-install/pk-debuginfo-install.c:761
+#: ../contrib/debuginfo-install/pk-debuginfo-install.c:805
+#: ../contrib/debuginfo-install/pk-debuginfo-install.c:872
+#: ../contrib/debuginfo-install/pk-debuginfo-install.c:916
 msgid "FAILED."
 msgstr "НЕВДАЛО."
 
 #. TRANSLATORS: all completed 100%
-#: ../contrib/debuginfo-install/pk-debuginfo-install.c:615
-#: ../contrib/debuginfo-install/pk-debuginfo-install.c:655
-#: ../contrib/debuginfo-install/pk-debuginfo-install.c:690
-#: ../contrib/debuginfo-install/pk-debuginfo-install.c:774
-#: ../contrib/debuginfo-install/pk-debuginfo-install.c:818
-#: ../contrib/debuginfo-install/pk-debuginfo-install.c:885
-#: ../contrib/debuginfo-install/pk-debuginfo-install.c:929
+#: ../contrib/debuginfo-install/pk-debuginfo-install.c:617
+#: ../contrib/debuginfo-install/pk-debuginfo-install.c:657
+#: ../contrib/debuginfo-install/pk-debuginfo-install.c:692
+#: ../contrib/debuginfo-install/pk-debuginfo-install.c:776
+#: ../contrib/debuginfo-install/pk-debuginfo-install.c:820
+#: ../contrib/debuginfo-install/pk-debuginfo-install.c:887
+#: ../contrib/debuginfo-install/pk-debuginfo-install.c:931
 #, c-format
 msgid "OK."
 msgstr "Гаразд."
 
 #. TRANSLATORS: tell the user what we found
-#: ../contrib/debuginfo-install/pk-debuginfo-install.c:618
+#: ../contrib/debuginfo-install/pk-debuginfo-install.c:620
 #, c-format
 msgid "Found %i enabled and %i disabled sources."
 msgstr "Знайдено %i увімкнених і %i вимкнених джерела."
 
 #. TRANSLATORS: we're finding repositories that match out pattern
-#: ../contrib/debuginfo-install/pk-debuginfo-install.c:625
+#: ../contrib/debuginfo-install/pk-debuginfo-install.c:627
 #, c-format
 msgid "Finding debugging sources"
 msgstr "Пошук джерел даних для усування вад"
 
 #. TRANSLATORS: tell the user what we found
-#: ../contrib/debuginfo-install/pk-debuginfo-install.c:658
+#: ../contrib/debuginfo-install/pk-debuginfo-install.c:660
 #, c-format
 msgid "Found %i disabled debuginfo repos."
 msgstr "Знайдено %i вимкнених сховища даних для усування вад."
 
 #. TRANSLATORS: we're now enabling all the debug sources we found
-#: ../contrib/debuginfo-install/pk-debuginfo-install.c:665
+#: ../contrib/debuginfo-install/pk-debuginfo-install.c:667
 #, c-format
 msgid "Enabling debugging sources"
 msgstr "Вмикання джерел даних для усування вад"
 
 #. TRANSLATORS: tell the user how many we enabled
-#: ../contrib/debuginfo-install/pk-debuginfo-install.c:693
+#: ../contrib/debuginfo-install/pk-debuginfo-install.c:695
 #, c-format
 msgid "Enabled %i debugging sources."
 msgstr "Увімкнено %i джерел даних для усування вад."
 
 #. TRANSLATORS: we're now finding packages that match in all the repos
-#: ../contrib/debuginfo-install/pk-debuginfo-install.c:700
+#: ../contrib/debuginfo-install/pk-debuginfo-install.c:702
 #, c-format
 msgid "Finding debugging packages"
 msgstr "Пошук пакунків для усування вад"
 
 #. TRANSLATORS: we couldn't find the package name, non-fatal
-#: ../contrib/debuginfo-install/pk-debuginfo-install.c:712
+#: ../contrib/debuginfo-install/pk-debuginfo-install.c:714
 #, c-format
 msgid "Failed to find the package %s: %s"
 msgstr "Не вдалося знайти пакунок %s: %s"
 
 #. TRANSLATORS: we couldn't find the debuginfo package name, non-fatal
-#: ../contrib/debuginfo-install/pk-debuginfo-install.c:735
+#: ../contrib/debuginfo-install/pk-debuginfo-install.c:737
 #, c-format
 msgid "Failed to find the debuginfo package %s: %s"
 msgstr "Не вдалося знайти пакунок з даними для усування вад %s: %s"
 
 #. TRANSLATORS: no debuginfo packages could be found to be installed
-#: ../contrib/debuginfo-install/pk-debuginfo-install.c:763
+#: ../contrib/debuginfo-install/pk-debuginfo-install.c:765
 #, c-format
 msgid "Found no packages to install."
 msgstr "Не знайдено жодного пакунка для встановлення."
 
 #. TRANSLATORS: tell the user we found some packages, and then list them
-#: ../contrib/debuginfo-install/pk-debuginfo-install.c:777
+#: ../contrib/debuginfo-install/pk-debuginfo-install.c:779
 #, c-format
 msgid "Found %i packages:"
 msgstr "Знайдено %i пакунків:"
 
 #. TRANSLATORS: tell the user we are searching for deps
-#: ../contrib/debuginfo-install/pk-debuginfo-install.c:793
+#: ../contrib/debuginfo-install/pk-debuginfo-install.c:795
 #, c-format
 msgid "Finding packages that depend on these packages"
 msgstr "Пошук пакунків, які залежать від цих пакунків"
 
 #. TRANSLATORS: could not install, detailed error follows
-#: ../contrib/debuginfo-install/pk-debuginfo-install.c:806
+#: ../contrib/debuginfo-install/pk-debuginfo-install.c:808
 #, c-format
 msgid "Could not find dependant packages: %s"
 msgstr "Не вдалося знайти залежних пакунків: %s"
 
 #. TRANSLATORS: tell the user we found some more packages
-#: ../contrib/debuginfo-install/pk-debuginfo-install.c:822
+#: ../contrib/debuginfo-install/pk-debuginfo-install.c:824
 #, c-format
 msgid "Found %i extra packages."
 msgstr "Знайдено %i додаткових пакунків."
 
 #. TRANSLATORS: tell the user we found some more packages
-#: ../contrib/debuginfo-install/pk-debuginfo-install.c:826
+#: ../contrib/debuginfo-install/pk-debuginfo-install.c:828
 #, c-format
 msgid "No extra packages required."
 msgstr "Потреби у додаткових пакунках немає."
 
 #. TRANSLATORS: tell the user we found some packages (and deps), and then list them
-#: ../contrib/debuginfo-install/pk-debuginfo-install.c:835
+#: ../contrib/debuginfo-install/pk-debuginfo-install.c:837
 #, c-format
 msgid "Found %i packages to install:"
 msgstr "Знайдено %i пакунків для встановлення:"
 
 #. TRANSLATORS: simulate mode is a testing mode where we quit before the action
-#: ../contrib/debuginfo-install/pk-debuginfo-install.c:848
+#: ../contrib/debuginfo-install/pk-debuginfo-install.c:850
 #, c-format
 msgid "Not installing packages in simulate mode"
 msgstr "Не встановлювати пакунки у режимі імітації"
 
 #. TRANSLATORS: we are now installing the debuginfo packages we found earlier
 #. TRANSLATORS: transaction state, installing packages
-#: ../contrib/debuginfo-install/pk-debuginfo-install.c:860
-#: ../lib/packagekit-glib2/pk-console-shared.c:274
+#: ../contrib/debuginfo-install/pk-debuginfo-install.c:862
+#: ../lib/packagekit-glib2/pk-console-shared.c:282
 #, c-format
 msgid "Installing packages"
 msgstr "Встановлення пакунків"
 
 #. TRANSLATORS: could not install, detailed error follows
-#: ../contrib/debuginfo-install/pk-debuginfo-install.c:873
+#: ../contrib/debuginfo-install/pk-debuginfo-install.c:875
 #, c-format
 msgid "Could not install packages: %s"
 msgstr "Не вдалося встановити пакунки: %s"
 
 #. TRANSLATORS: we are now disabling all debuginfo repos we previously enabled
-#: ../contrib/debuginfo-install/pk-debuginfo-install.c:905
+#: ../contrib/debuginfo-install/pk-debuginfo-install.c:907
 #, c-format
 msgid "Disabling sources previously enabled"
 msgstr "Вимикання раніше увімкнених джерел"
 
 #. TRANSLATORS: no debuginfo packages could be found to be installed, detailed error follows
-#: ../contrib/debuginfo-install/pk-debuginfo-install.c:917
+#: ../contrib/debuginfo-install/pk-debuginfo-install.c:919
 #, c-format
 msgid "Could not disable the debugging sources: %s"
 msgstr "Не вдалося вимкнути джерела для усування вад: %s"
 
 #. TRANSLATORS: we disabled all the debugging repos that we enabled before
-#: ../contrib/debuginfo-install/pk-debuginfo-install.c:932
+#: ../contrib/debuginfo-install/pk-debuginfo-install.c:934
 #, c-format
 msgid "Disabled %i debugging sources."
 msgstr "Вимкнено %i джерел для усування вад."
 
 #. TRANSLATORS: couldn't open device to write
-#: ../contrib/device-rebind/pk-device-rebind.c:61
+#: ../contrib/device-rebind/pk-device-rebind.c:62
 msgid "Failed to open file"
 msgstr "Не вдалося відкрити файл"
 
 #. TRANSLATORS: could not write to the device
-#: ../contrib/device-rebind/pk-device-rebind.c:70
+#: ../contrib/device-rebind/pk-device-rebind.c:71
 msgid "Failed to write to the file"
 msgstr "Не вдалося виконати запис до файла"
 
 #. TRANSLATORS: we failed to release the current driver
-#: ../contrib/device-rebind/pk-device-rebind.c:110
-#: ../contrib/device-rebind/pk-device-rebind.c:147
+#: ../contrib/device-rebind/pk-device-rebind.c:111
+#: ../contrib/device-rebind/pk-device-rebind.c:148
 msgid "Failed to write to device"
 msgstr "Не вдалося виконати запис на пристрій"
 
 #. TRANSLATORS: the device could not be found in sysfs
-#: ../contrib/device-rebind/pk-device-rebind.c:175
+#: ../contrib/device-rebind/pk-device-rebind.c:176
 msgid "Device could not be found"
 msgstr "Не вдалося знайти пристрій"
 
 #. TRANSLATORS: we failed to release the current driver
-#: ../contrib/device-rebind/pk-device-rebind.c:202
+#: ../contrib/device-rebind/pk-device-rebind.c:203
 msgid "Failed to unregister driver"
 msgstr "Не вдалося скасувати реєстрацію драйвера"
 
 #. TRANSLATORS: we failed to bind the old driver
-#: ../contrib/device-rebind/pk-device-rebind.c:211
+#: ../contrib/device-rebind/pk-device-rebind.c:212
 msgid "Failed to register driver"
 msgstr "Не вдалося зареєструвати драйвер"
 
 #. TRANSLATORS: user did not specify a device sysfs path that exists
-#: ../contrib/device-rebind/pk-device-rebind.c:260
+#: ../contrib/device-rebind/pk-device-rebind.c:261
 msgid "Device path not found"
 msgstr "Не знайдено шляху до пристрою"
 
 #. TRANSLATORS: user did not specify a valid device sysfs path
-#: ../contrib/device-rebind/pk-device-rebind.c:268
+#: ../contrib/device-rebind/pk-device-rebind.c:269
 msgid "Incorrect device path specified"
 msgstr "Вказано неправильний шлях до пристрою"
 
+#: ../contrib/device-rebind/pk-device-rebind.c:294
+msgid "Show extra debugging information"
+msgstr "Показувати додаткові дані для усування вад"
+
 #. command line argument, simulate what would be done, but don't actually do it
-#: ../contrib/device-rebind/pk-device-rebind.c:296
+#: ../contrib/device-rebind/pk-device-rebind.c:297
 msgid "Don't actually touch the hardware, only simulate what would be done"
 msgstr "Не виконувати дій з обладнанням, лише імітувати їх виконання"
 
 #. TRANSLATORS: command line option: a list of files to install
-#: ../contrib/device-rebind/pk-device-rebind.c:299
+#: ../contrib/device-rebind/pk-device-rebind.c:300
 msgid "Device paths"
 msgstr "Шляхи пристроїв"
 
 #. TRANSLATORS: tool that gets called when the device needs reloading after installing firmware
-#: ../contrib/device-rebind/pk-device-rebind.c:314
+#: ../contrib/device-rebind/pk-device-rebind.c:315
 msgid "PackageKit Device Reloader"
 msgstr "Перезавантаження пристроїв PackageKit"
 
 #. TRANSLATORS: user did not specify a valid device sysfs path
-#: ../contrib/device-rebind/pk-device-rebind.c:322
+#: ../contrib/device-rebind/pk-device-rebind.c:323
 msgid "You need to specify at least one valid device path"
 msgstr "Слід вказати принаймні один коректний шлях до пристрою"
 
 #. TRANSLATORS: user did not specify a valid device sysfs path
-#: ../contrib/device-rebind/pk-device-rebind.c:332
+#: ../contrib/device-rebind/pk-device-rebind.c:333
 msgid "This script can only be used by the root user"
 msgstr "Цим скриптом можна скористатися лише від імені користувача root"
 
 #. TRANSLATORS: we're going to verify the path first
-#: ../contrib/device-rebind/pk-device-rebind.c:341
+#: ../contrib/device-rebind/pk-device-rebind.c:342
 msgid "Verifying device path"
 msgstr "Перевірка шляху до пристрою"
 
 #. TRANSLATORS: user did not specify a device sysfs path that exists
-#: ../contrib/device-rebind/pk-device-rebind.c:346
+#: ../contrib/device-rebind/pk-device-rebind.c:347
 msgid "Failed to verify device path"
 msgstr "Не вдалося перевірити шлях до пристрою"
 
 #. TRANSLATORS: we're going to try
-#: ../contrib/device-rebind/pk-device-rebind.c:360
+#: ../contrib/device-rebind/pk-device-rebind.c:361
 msgid "Attempting to rebind device"
 msgstr "Спроба повторної прив’язки пристрою"
 
 #. TRANSLATORS: we failed to release the current driver
-#: ../contrib/device-rebind/pk-device-rebind.c:365
+#: ../contrib/device-rebind/pk-device-rebind.c:366
 msgid "Failed to rebind device"
 msgstr "Повторна спроба прив’язки пристрою зазнала невдачі"
 
@@ -1065,599 +1100,599 @@ msgid "Please enter a number from 1 to %i: "
 msgstr "Будь ласка, введіть число від 1 до %i: "
 
 #. TRANSLATORS: more than one package could be found that matched, to follow is a list of possible packages
-#: ../lib/packagekit-glib2/pk-console-shared.c:181
+#: ../lib/packagekit-glib2/pk-console-shared.c:183
 msgid "More than one package matches:"
 msgstr "З ключем пошуку збігається декілька пакунків:"
 
 #. TRANSLATORS: This finds out which package in the list to use
-#: ../lib/packagekit-glib2/pk-console-shared.c:190
+#: ../lib/packagekit-glib2/pk-console-shared.c:196
 msgid "Please choose the correct package: "
 msgstr "Будь ласка, оберіть належний пакунок:"
 
 #. TRANSLATORS: This is when the transaction status is not known
-#: ../lib/packagekit-glib2/pk-console-shared.c:242
+#: ../lib/packagekit-glib2/pk-console-shared.c:250
 msgid "Unknown state"
 msgstr "Невідомий стан"
 
 #. TRANSLATORS: transaction state, the daemon is in the process of starting
-#: ../lib/packagekit-glib2/pk-console-shared.c:246
+#: ../lib/packagekit-glib2/pk-console-shared.c:254
 msgid "Starting"
 msgstr "Запуск"
 
 #. TRANSLATORS: transaction state, the transaction is waiting for another to complete
-#: ../lib/packagekit-glib2/pk-console-shared.c:250
+#: ../lib/packagekit-glib2/pk-console-shared.c:258
 msgid "Waiting in queue"
 msgstr "Очікування у черзі"
 
 #. TRANSLATORS: transaction state, just started
-#: ../lib/packagekit-glib2/pk-console-shared.c:254
+#: ../lib/packagekit-glib2/pk-console-shared.c:262
 msgid "Running"
 msgstr "Виконання"
 
 #. TRANSLATORS: transaction state, is querying data
-#: ../lib/packagekit-glib2/pk-console-shared.c:258
+#: ../lib/packagekit-glib2/pk-console-shared.c:266
 msgid "Querying"
 msgstr "Виконання запиту"
 
 #. TRANSLATORS: transaction state, getting data from a server
-#: ../lib/packagekit-glib2/pk-console-shared.c:262
+#: ../lib/packagekit-glib2/pk-console-shared.c:270
 msgid "Getting information"
 msgstr "Отримання інформації"
 
 #. TRANSLATORS: transaction state, removing packages
-#: ../lib/packagekit-glib2/pk-console-shared.c:266
+#: ../lib/packagekit-glib2/pk-console-shared.c:274
 msgid "Removing packages"
 msgstr "Вилучення пакунків"
 
 #. TRANSLATORS: transaction state, downloading package files
 #. TRANSLATORS: The role of the transaction, in present tense
-#: ../lib/packagekit-glib2/pk-console-shared.c:270
-#: ../lib/packagekit-glib2/pk-console-shared.c:648
+#: ../lib/packagekit-glib2/pk-console-shared.c:278
+#: ../lib/packagekit-glib2/pk-console-shared.c:656
 msgid "Downloading packages"
 msgstr "Звантаження пакунків"
 
 #. TRANSLATORS: transaction state, refreshing internal lists
-#: ../lib/packagekit-glib2/pk-console-shared.c:278
+#: ../lib/packagekit-glib2/pk-console-shared.c:286
 msgid "Refreshing software list"
 msgstr "Освіження списку програм"
 
 #. TRANSLATORS: transaction state, installing updates
-#: ../lib/packagekit-glib2/pk-console-shared.c:282
+#: ../lib/packagekit-glib2/pk-console-shared.c:290
 msgid "Installing updates"
 msgstr "Встановлення оновлень"
 
 #. TRANSLATORS: transaction state, removing old packages, and cleaning config files
-#: ../lib/packagekit-glib2/pk-console-shared.c:286
+#: ../lib/packagekit-glib2/pk-console-shared.c:294
 msgid "Cleaning up packages"
 msgstr "Вилучення зайвих пакунків"
 
 #. TRANSLATORS: transaction state, obsoleting old packages
-#: ../lib/packagekit-glib2/pk-console-shared.c:290
+#: ../lib/packagekit-glib2/pk-console-shared.c:298
 msgid "Obsoleting packages"
 msgstr "Вилучення застарілих пакунків"
 
 #. TRANSLATORS: transaction state, checking the transaction before we do it
-#: ../lib/packagekit-glib2/pk-console-shared.c:294
+#: ../lib/packagekit-glib2/pk-console-shared.c:302
 msgid "Resolving dependencies"
 msgstr "Розв’язання залежностей"
 
 #. TRANSLATORS: transaction state, checking if we have all the security keys for the operation
-#: ../lib/packagekit-glib2/pk-console-shared.c:298
+#: ../lib/packagekit-glib2/pk-console-shared.c:306
 msgid "Checking signatures"
 msgstr "Перевірка підписів"
 
 #. TRANSLATORS: transaction state, when we return to a previous system state
 #. TRANSLATORS: The role of the transaction, in present tense
-#: ../lib/packagekit-glib2/pk-console-shared.c:302
-#: ../lib/packagekit-glib2/pk-console-shared.c:608
+#: ../lib/packagekit-glib2/pk-console-shared.c:310
+#: ../lib/packagekit-glib2/pk-console-shared.c:616
 msgid "Rolling back"
 msgstr "Повернення до попереднього"
 
 #. TRANSLATORS: transaction state, when we're doing a test transaction
-#: ../lib/packagekit-glib2/pk-console-shared.c:306
+#: ../lib/packagekit-glib2/pk-console-shared.c:314
 msgid "Testing changes"
 msgstr "Випробування змін"
 
 #. TRANSLATORS: transaction state, when we're writing to the system package database
-#: ../lib/packagekit-glib2/pk-console-shared.c:310
+#: ../lib/packagekit-glib2/pk-console-shared.c:318
 msgid "Committing changes"
 msgstr "Застосування змін"
 
 #. TRANSLATORS: transaction state, requesting data from a server
-#: ../lib/packagekit-glib2/pk-console-shared.c:314
+#: ../lib/packagekit-glib2/pk-console-shared.c:322
 msgid "Requesting data"
 msgstr "Запит щодо даних"
 
 #. TRANSLATORS: transaction state, all done!
-#: ../lib/packagekit-glib2/pk-console-shared.c:318
+#: ../lib/packagekit-glib2/pk-console-shared.c:326
 msgid "Finished"
 msgstr "Завершено"
 
 #. TRANSLATORS: transaction state, in the process of cancelling
-#: ../lib/packagekit-glib2/pk-console-shared.c:322
+#: ../lib/packagekit-glib2/pk-console-shared.c:330
 msgid "Cancelling"
 msgstr "Скасування"
 
 #. TRANSLATORS: transaction state, downloading metadata
-#: ../lib/packagekit-glib2/pk-console-shared.c:326
+#: ../lib/packagekit-glib2/pk-console-shared.c:334
 msgid "Downloading repository information"
 msgstr "Звантаження інформації про сховище"
 
 #. TRANSLATORS: transaction state, downloading metadata
-#: ../lib/packagekit-glib2/pk-console-shared.c:330
+#: ../lib/packagekit-glib2/pk-console-shared.c:338
 msgid "Downloading list of packages"
 msgstr "Звантаження списку пакунків"
 
 #. TRANSLATORS: transaction state, downloading metadata
-#: ../lib/packagekit-glib2/pk-console-shared.c:334
+#: ../lib/packagekit-glib2/pk-console-shared.c:342
 msgid "Downloading file lists"
 msgstr "Звантаження списків файлів"
 
 #. TRANSLATORS: transaction state, downloading metadata
-#: ../lib/packagekit-glib2/pk-console-shared.c:338
+#: ../lib/packagekit-glib2/pk-console-shared.c:346
 msgid "Downloading lists of changes"
 msgstr "Звантаження списків змін"
 
 #. TRANSLATORS: transaction state, downloading metadata
-#: ../lib/packagekit-glib2/pk-console-shared.c:342
+#: ../lib/packagekit-glib2/pk-console-shared.c:350
 msgid "Downloading groups"
 msgstr "Звантаження груп"
 
 #. TRANSLATORS: transaction state, downloading metadata
-#: ../lib/packagekit-glib2/pk-console-shared.c:346
+#: ../lib/packagekit-glib2/pk-console-shared.c:354
 msgid "Downloading update information"
 msgstr "Звантаження інформації про оновлення"
 
 #. TRANSLATORS: transaction state, repackaging delta files
-#: ../lib/packagekit-glib2/pk-console-shared.c:350
+#: ../lib/packagekit-glib2/pk-console-shared.c:358
 msgid "Repackaging files"
 msgstr "Перепакування файлів"
 
 #. TRANSLATORS: transaction state, loading databases
-#: ../lib/packagekit-glib2/pk-console-shared.c:354
+#: ../lib/packagekit-glib2/pk-console-shared.c:362
 msgid "Loading cache"
 msgstr "Завантаження кешу"
 
 #. TRANSLATORS: transaction state, scanning for running processes
-#: ../lib/packagekit-glib2/pk-console-shared.c:358
+#: ../lib/packagekit-glib2/pk-console-shared.c:366
 msgid "Scanning applications"
 msgstr "Пошук програм"
 
 #. TRANSLATORS: transaction state, generating a list of packages installed on the system
-#: ../lib/packagekit-glib2/pk-console-shared.c:362
+#: ../lib/packagekit-glib2/pk-console-shared.c:370
 msgid "Generating package lists"
 msgstr "Створення списків пакунків"
 
 #. TRANSLATORS: transaction state, when we're waiting for the native tools to exit
-#: ../lib/packagekit-glib2/pk-console-shared.c:366
+#: ../lib/packagekit-glib2/pk-console-shared.c:374
 msgid "Waiting for package manager lock"
 msgstr "Очікування на зняття блокування керування пакунками"
 
 #. TRANSLATORS: transaction state, waiting for user to type in a password
-#: ../lib/packagekit-glib2/pk-console-shared.c:370
+#: ../lib/packagekit-glib2/pk-console-shared.c:378
 msgid "Waiting for authentication"
 msgstr "Очікування на завершення розпізнавання"
 
 #. TRANSLATORS: transaction state, we are updating the list of processes
-#: ../lib/packagekit-glib2/pk-console-shared.c:374
+#: ../lib/packagekit-glib2/pk-console-shared.c:382
 msgid "Updating running applications"
 msgstr "Оновлення списку запущенний програм"
 
 #. TRANSLATORS: transaction state, we are checking executable files currently in use
-#: ../lib/packagekit-glib2/pk-console-shared.c:378
+#: ../lib/packagekit-glib2/pk-console-shared.c:386
 msgid "Checking applications in use"
 msgstr "Виявлення програм, що використовуються"
 
 #. TRANSLATORS: transaction state, we are checking for libraries currently in use
-#: ../lib/packagekit-glib2/pk-console-shared.c:382
+#: ../lib/packagekit-glib2/pk-console-shared.c:390
 msgid "Checking libraries in use"
 msgstr "Виявлення бібліотек, що використовуються"
 
 #. TRANSLATORS: transaction state, we are copying package files before or after the transaction
-#: ../lib/packagekit-glib2/pk-console-shared.c:386
+#: ../lib/packagekit-glib2/pk-console-shared.c:394
 msgid "Copying files"
 msgstr "Копіювання файлів"
 
 #. TRANSLATORS: The type of update
-#: ../lib/packagekit-glib2/pk-console-shared.c:404
+#: ../lib/packagekit-glib2/pk-console-shared.c:412
 msgid "Trivial"
 msgstr "Незначне"
 
 #. TRANSLATORS: The type of update
-#: ../lib/packagekit-glib2/pk-console-shared.c:408
+#: ../lib/packagekit-glib2/pk-console-shared.c:416
 msgid "Normal"
 msgstr "Звичайне"
 
 #. TRANSLATORS: The type of update
-#: ../lib/packagekit-glib2/pk-console-shared.c:412
+#: ../lib/packagekit-glib2/pk-console-shared.c:420
 msgid "Important"
 msgstr "Важливе"
 
 #. TRANSLATORS: The type of update
-#: ../lib/packagekit-glib2/pk-console-shared.c:416
+#: ../lib/packagekit-glib2/pk-console-shared.c:424
 msgid "Security"
 msgstr "Безпека"
 
 #. TRANSLATORS: The type of update
-#: ../lib/packagekit-glib2/pk-console-shared.c:420
+#: ../lib/packagekit-glib2/pk-console-shared.c:428
 msgid "Bug fix "
 msgstr "Виправлення вад"
 
 #. TRANSLATORS: The type of update
-#: ../lib/packagekit-glib2/pk-console-shared.c:424
+#: ../lib/packagekit-glib2/pk-console-shared.c:432
 msgid "Enhancement"
 msgstr "Покращення"
 
 #. TRANSLATORS: The type of update
-#: ../lib/packagekit-glib2/pk-console-shared.c:428
+#: ../lib/packagekit-glib2/pk-console-shared.c:436
 msgid "Blocked"
 msgstr "Заблоковане"
 
 #. TRANSLATORS: The state of a package
 #. TRANSLATORS: The action of the package, in past tense
-#: ../lib/packagekit-glib2/pk-console-shared.c:433
-#: ../lib/packagekit-glib2/pk-console-shared.c:506
+#: ../lib/packagekit-glib2/pk-console-shared.c:441
+#: ../lib/packagekit-glib2/pk-console-shared.c:514
 msgid "Installed"
 msgstr "Встановлене"
 
 #. TRANSLATORS: The state of a package, i.e. not installed
-#: ../lib/packagekit-glib2/pk-console-shared.c:438
+#: ../lib/packagekit-glib2/pk-console-shared.c:446
 msgid "Available"
 msgstr "Доступний"
 
 #. TRANSLATORS: The action of the package, in present tense
-#: ../lib/packagekit-glib2/pk-console-shared.c:456
+#: ../lib/packagekit-glib2/pk-console-shared.c:464
 msgid "Downloading"
 msgstr "Звантаження"
 
 #. TRANSLATORS: The action of the package, in present tense
-#: ../lib/packagekit-glib2/pk-console-shared.c:460
+#: ../lib/packagekit-glib2/pk-console-shared.c:468
 msgid "Updating"
 msgstr "Оновлення"
 
 #. TRANSLATORS: The action of the package, in present tense
 #. TRANSLATORS: The role of the transaction, in present tense
-#: ../lib/packagekit-glib2/pk-console-shared.c:464
-#: ../lib/packagekit-glib2/pk-console-shared.c:584
+#: ../lib/packagekit-glib2/pk-console-shared.c:472
+#: ../lib/packagekit-glib2/pk-console-shared.c:592
 msgid "Installing"
 msgstr "Встановлення"
 
 #. TRANSLATORS: The action of the package, in present tense
 #. TRANSLATORS: The role of the transaction, in present tense
-#: ../lib/packagekit-glib2/pk-console-shared.c:468
-#: ../lib/packagekit-glib2/pk-console-shared.c:580
+#: ../lib/packagekit-glib2/pk-console-shared.c:476
+#: ../lib/packagekit-glib2/pk-console-shared.c:588
 msgid "Removing"
 msgstr "Вилучення"
 
 #. TRANSLATORS: The action of the package, in present tense
-#: ../lib/packagekit-glib2/pk-console-shared.c:472
+#: ../lib/packagekit-glib2/pk-console-shared.c:480
 msgid "Cleaning up"
 msgstr "Очищення"
 
 #. TRANSLATORS: The action of the package, in present tense
-#: ../lib/packagekit-glib2/pk-console-shared.c:476
+#: ../lib/packagekit-glib2/pk-console-shared.c:484
 msgid "Obsoleting"
 msgstr "Робить застарілим"
 
 #. TRANSLATORS: The action of the package, in present tense
-#: ../lib/packagekit-glib2/pk-console-shared.c:480
+#: ../lib/packagekit-glib2/pk-console-shared.c:488
 msgid "Reinstalling"
 msgstr "Перевстановлення"
 
 #. TRANSLATORS: The action of the package, in past tense
-#: ../lib/packagekit-glib2/pk-console-shared.c:498
+#: ../lib/packagekit-glib2/pk-console-shared.c:506
 msgid "Downloaded"
 msgstr "Звантажено"
 
 #. TRANSLATORS: The action of the package, in past tense
-#: ../lib/packagekit-glib2/pk-console-shared.c:510
+#: ../lib/packagekit-glib2/pk-console-shared.c:518
 msgid "Removed"
 msgstr "Вилучено"
 
 #. TRANSLATORS: The action of the package, in past tense
-#: ../lib/packagekit-glib2/pk-console-shared.c:514
+#: ../lib/packagekit-glib2/pk-console-shared.c:522
 msgid "Cleaned up"
 msgstr "Очищено"
 
 #. TRANSLATORS: The action of the package, in past tense
-#: ../lib/packagekit-glib2/pk-console-shared.c:518
+#: ../lib/packagekit-glib2/pk-console-shared.c:526
 msgid "Obsoleted"
 msgstr "Став застарілим"
 
 #. TRANSLATORS: The action of the package, in past tense
-#: ../lib/packagekit-glib2/pk-console-shared.c:522
+#: ../lib/packagekit-glib2/pk-console-shared.c:530
 msgid "Reinstalled"
 msgstr "Перевстановлено"
 
 #. TRANSLATORS: The role of the transaction, in present tense
-#: ../lib/packagekit-glib2/pk-console-shared.c:540
+#: ../lib/packagekit-glib2/pk-console-shared.c:548
 msgid "Unknown role type"
 msgstr "Невідомий тип"
 
 #. TRANSLATORS: The role of the transaction, in present tense
-#: ../lib/packagekit-glib2/pk-console-shared.c:544
+#: ../lib/packagekit-glib2/pk-console-shared.c:552
 msgid "Getting dependencies"
 msgstr "Отримання залежностей"
 
 #. TRANSLATORS: The role of the transaction, in present tense
-#: ../lib/packagekit-glib2/pk-console-shared.c:548
+#: ../lib/packagekit-glib2/pk-console-shared.c:556
 msgid "Getting update details"
 msgstr "Отримання подробиць оновлення"
 
 #. TRANSLATORS: The role of the transaction, in present tense
-#: ../lib/packagekit-glib2/pk-console-shared.c:552
+#: ../lib/packagekit-glib2/pk-console-shared.c:560
 msgid "Getting details"
 msgstr "Отримання подробиць"
 
 #. TRANSLATORS: The role of the transaction, in present tense
-#: ../lib/packagekit-glib2/pk-console-shared.c:556
+#: ../lib/packagekit-glib2/pk-console-shared.c:564
 msgid "Getting requires"
 msgstr "Отримання даних про вимоги"
 
 #. TRANSLATORS: The role of the transaction, in present tense
-#: ../lib/packagekit-glib2/pk-console-shared.c:560
+#: ../lib/packagekit-glib2/pk-console-shared.c:568
 msgid "Getting updates"
 msgstr "Отримання оновлень"
 
 #. TRANSLATORS: The role of the transaction, in present tense
-#: ../lib/packagekit-glib2/pk-console-shared.c:564
+#: ../lib/packagekit-glib2/pk-console-shared.c:572
 msgid "Searching by details"
 msgstr "Пошук за подробицями"
 
 #. TRANSLATORS: The role of the transaction, in present tense
-#: ../lib/packagekit-glib2/pk-console-shared.c:568
+#: ../lib/packagekit-glib2/pk-console-shared.c:576
 msgid "Searching by file"
 msgstr "Пошук за файлом"
 
 #. TRANSLATORS: The role of the transaction, in present tense
-#: ../lib/packagekit-glib2/pk-console-shared.c:572
+#: ../lib/packagekit-glib2/pk-console-shared.c:580
 msgid "Searching groups"
 msgstr "Пошук груп"
 
 #. TRANSLATORS: The role of the transaction, in present tense
-#: ../lib/packagekit-glib2/pk-console-shared.c:576
+#: ../lib/packagekit-glib2/pk-console-shared.c:584
 msgid "Searching by name"
 msgstr "Пошук за назвою"
 
 #. TRANSLATORS: The role of the transaction, in present tense
-#: ../lib/packagekit-glib2/pk-console-shared.c:588
+#: ../lib/packagekit-glib2/pk-console-shared.c:596
 msgid "Installing files"
 msgstr "Встановлення файлів"
 
 #. TRANSLATORS: The role of the transaction, in present tense
-#: ../lib/packagekit-glib2/pk-console-shared.c:592
+#: ../lib/packagekit-glib2/pk-console-shared.c:600
 msgid "Refreshing cache"
 msgstr "Освіження кешу"
 
 #. TRANSLATORS: The role of the transaction, in present tense
-#: ../lib/packagekit-glib2/pk-console-shared.c:596
+#: ../lib/packagekit-glib2/pk-console-shared.c:604
 msgid "Updating packages"
 msgstr "Оновлення пакунків"
 
 #. TRANSLATORS: The role of the transaction, in present tense
-#: ../lib/packagekit-glib2/pk-console-shared.c:600
+#: ../lib/packagekit-glib2/pk-console-shared.c:608
 msgid "Updating system"
 msgstr "Оновлення системи"
 
 #. TRANSLATORS: The role of the transaction, in present tense
-#: ../lib/packagekit-glib2/pk-console-shared.c:604
+#: ../lib/packagekit-glib2/pk-console-shared.c:612
 msgid "Canceling"
 msgstr "Скасування"
 
 #. TRANSLATORS: The role of the transaction, in present tense
-#: ../lib/packagekit-glib2/pk-console-shared.c:612
+#: ../lib/packagekit-glib2/pk-console-shared.c:620
 msgid "Getting repositories"
 msgstr "Отримання списку сховищ"
 
 #. TRANSLATORS: The role of the transaction, in present tense
-#: ../lib/packagekit-glib2/pk-console-shared.c:616
+#: ../lib/packagekit-glib2/pk-console-shared.c:624
 msgid "Enabling repository"
 msgstr "Увімкнення сховища"
 
 #. TRANSLATORS: The role of the transaction, in present tense
-#: ../lib/packagekit-glib2/pk-console-shared.c:620
+#: ../lib/packagekit-glib2/pk-console-shared.c:628
 msgid "Setting data"
 msgstr "Встановлення даних"
 
 #. TRANSLATORS: The role of the transaction, in present tense
-#: ../lib/packagekit-glib2/pk-console-shared.c:624
+#: ../lib/packagekit-glib2/pk-console-shared.c:632
 msgid "Resolving"
 msgstr "Розв’язання"
 
 #. TRANSLATORS: The role of the transaction, in present tense
-#: ../lib/packagekit-glib2/pk-console-shared.c:628
+#: ../lib/packagekit-glib2/pk-console-shared.c:636
 msgid "Getting file list"
 msgstr "Отримання списку файлів"
 
 #. TRANSLATORS: The role of the transaction, in present tense
-#: ../lib/packagekit-glib2/pk-console-shared.c:632
+#: ../lib/packagekit-glib2/pk-console-shared.c:640
 msgid "Getting provides"
 msgstr "Отримання даних про вміст"
 
 #. TRANSLATORS: The role of the transaction, in present tense
-#: ../lib/packagekit-glib2/pk-console-shared.c:636
+#: ../lib/packagekit-glib2/pk-console-shared.c:644
 msgid "Installing signature"
 msgstr "Встановлення підпису"
 
 #. TRANSLATORS: The role of the transaction, in present tense
-#: ../lib/packagekit-glib2/pk-console-shared.c:640
+#: ../lib/packagekit-glib2/pk-console-shared.c:648
 msgid "Getting packages"
 msgstr "Отримання списку пакунків"
 
 #. TRANSLATORS: The role of the transaction, in present tense
-#: ../lib/packagekit-glib2/pk-console-shared.c:644
+#: ../lib/packagekit-glib2/pk-console-shared.c:652
 msgid "Accepting EULA"
 msgstr "Згода з EULA"
 
 #. TRANSLATORS: The role of the transaction, in present tense
-#: ../lib/packagekit-glib2/pk-console-shared.c:652
+#: ../lib/packagekit-glib2/pk-console-shared.c:660
 msgid "Getting upgrades"
 msgstr "Отримання оновлень"
 
 #. TRANSLATORS: The role of the transaction, in present tense
-#: ../lib/packagekit-glib2/pk-console-shared.c:656
+#: ../lib/packagekit-glib2/pk-console-shared.c:664
 msgid "Getting categories"
 msgstr "Отримання категорій"
 
 #. TRANSLATORS: The role of the transaction, in present tense
-#: ../lib/packagekit-glib2/pk-console-shared.c:660
+#: ../lib/packagekit-glib2/pk-console-shared.c:668
 msgid "Getting transactions"
 msgstr "Отримання списку дій"
 
 #. TRANSLATORS: The role of the transaction, in present tense
-#: ../lib/packagekit-glib2/pk-console-shared.c:664
-#: ../lib/packagekit-glib2/pk-console-shared.c:668
+#: ../lib/packagekit-glib2/pk-console-shared.c:672
+#: ../lib/packagekit-glib2/pk-console-shared.c:676
 msgid "Simulating install"
 msgstr "Імітація встановлення"
 
 #. TRANSLATORS: The role of the transaction, in present tense
-#: ../lib/packagekit-glib2/pk-console-shared.c:672
+#: ../lib/packagekit-glib2/pk-console-shared.c:680
 msgid "Simulating remove"
 msgstr "Імітація вилучення"
 
 #. TRANSLATORS: The role of the transaction, in present tense
-#: ../lib/packagekit-glib2/pk-console-shared.c:676
+#: ../lib/packagekit-glib2/pk-console-shared.c:684
 msgid "Simulating update"
 msgstr "Імітація оновлення"
 
 #. TRANSLATORS: ask the user if they are comfortable installing insecure packages
-#: ../lib/packagekit-glib2/pk-task-text.c:66
+#: ../lib/packagekit-glib2/pk-task-text.c:69
 msgid "Do you want to allow installing of unsigned software?"
 msgstr "Бажаєте дозволити встановлення непідписаного програмного забезпечення?"
 
 #. TRANSLATORS: tell the user we've not done anything
-#: ../lib/packagekit-glib2/pk-task-text.c:71
+#: ../lib/packagekit-glib2/pk-task-text.c:74
 msgid "The unsigned software will not be installed."
 msgstr "Непідписане програмне забезпечення встановлено не буде."
 
 #. TRANSLATORS: the package repository is signed by a key that is not recognised
-#: ../lib/packagekit-glib2/pk-task-text.c:104
+#: ../lib/packagekit-glib2/pk-task-text.c:123
 msgid "Software source signature required"
 msgstr "Потрібен підпис джерела програмного забезпечення"
 
 #. TRANSLATORS: the package repository name
-#: ../lib/packagekit-glib2/pk-task-text.c:110
+#: ../lib/packagekit-glib2/pk-task-text.c:129
 msgid "Software source name"
 msgstr "Назва джерела програмного забезпечення"
 
 #. TRANSLATORS: the key URL
-#: ../lib/packagekit-glib2/pk-task-text.c:113
+#: ../lib/packagekit-glib2/pk-task-text.c:132
 msgid "Key URL"
 msgstr "Адреса URL ключа"
 
 #. TRANSLATORS: the username of the key
-#: ../lib/packagekit-glib2/pk-task-text.c:116
+#: ../lib/packagekit-glib2/pk-task-text.c:135
 msgid "Key user"
 msgstr "Користувач ключа"
 
 #. TRANSLATORS: the key ID, usually a few hex digits
-#: ../lib/packagekit-glib2/pk-task-text.c:119
+#: ../lib/packagekit-glib2/pk-task-text.c:138
 msgid "Key ID"
 msgstr "Ідентифікатор ключа"
 
 #. TRANSLATORS: the key fingerprint, again, yet more hex
-#: ../lib/packagekit-glib2/pk-task-text.c:122
+#: ../lib/packagekit-glib2/pk-task-text.c:141
 msgid "Key fingerprint"
 msgstr "Відбиток ключа"
 
 #. TRANSLATORS: the timestamp (a bit like a machine readable time)
-#: ../lib/packagekit-glib2/pk-task-text.c:125
+#: ../lib/packagekit-glib2/pk-task-text.c:144
 msgid "Key Timestamp"
 msgstr "Часова позначка ключа"
 
 #. TRANSLATORS: ask the user if they want to import
-#: ../lib/packagekit-glib2/pk-task-text.c:131
+#: ../lib/packagekit-glib2/pk-task-text.c:157
 msgid "Do you accept this signature?"
 msgstr "Чи підтверджуєте ви цей підпис?"
 
 #. TRANSLATORS: tell the user we've not done anything
-#: ../lib/packagekit-glib2/pk-task-text.c:136
+#: ../lib/packagekit-glib2/pk-task-text.c:162
 msgid "The signature was not accepted."
 msgstr "Підпис не було підтверджено."
 
 #. TRANSLATORS: this is another name for a software licence that has to be read before installing
-#: ../lib/packagekit-glib2/pk-task-text.c:171
+#: ../lib/packagekit-glib2/pk-task-text.c:205
 msgid "End user licence agreement required"
 msgstr ""
 "Потрібне підтвердження ліцензійної угоди з кінцевим користувачем (EULA)"
 
 #. TRANSLATORS: the EULA text itself (long and boring)
-#: ../lib/packagekit-glib2/pk-task-text.c:180
+#: ../lib/packagekit-glib2/pk-task-text.c:214
 msgid "Agreement"
 msgstr "Угода"
 
 #. TRANSLATORS: ask the user if they've read and accepted the EULA
-#: ../lib/packagekit-glib2/pk-task-text.c:186
+#: ../lib/packagekit-glib2/pk-task-text.c:223
 msgid "Do you accept this agreement?"
 msgstr "Чи згодвні ви дотримуватися цієї угоди?"
 
 #. TRANSLATORS: tell the user we've not done anything
-#: ../lib/packagekit-glib2/pk-task-text.c:191
+#: ../lib/packagekit-glib2/pk-task-text.c:228
 msgid "The agreement was not accepted."
 msgstr "Угоду не було підтверджено."
 
 #. TRANSLATORS: the user needs to change media inserted into the computer
-#: ../lib/packagekit-glib2/pk-task-text.c:221
+#: ../lib/packagekit-glib2/pk-task-text.c:267
 msgid "Media change required"
 msgstr "Потрібна зміна носія"
 
 #. TRANSLATORS: the type, e.g. DVD, CD, etc
-#: ../lib/packagekit-glib2/pk-task-text.c:224
+#: ../lib/packagekit-glib2/pk-task-text.c:270
 msgid "Media type"
 msgstr "Тип носія"
 
 #. TRANSLATORS: the media label, usually like 'disk-1of3'
-#: ../lib/packagekit-glib2/pk-task-text.c:227
+#: ../lib/packagekit-glib2/pk-task-text.c:273
 msgid "Media label"
 msgstr "Мітка носія"
 
 #. TRANSLATORS: the media description, usually like 'Fedora 12 disk 5'
-#: ../lib/packagekit-glib2/pk-task-text.c:230
+#: ../lib/packagekit-glib2/pk-task-text.c:276
 msgid "Text"
 msgstr "Текст"
 
 #. TRANSLATORS: ask the user to insert the media
-#: ../lib/packagekit-glib2/pk-task-text.c:234
+#: ../lib/packagekit-glib2/pk-task-text.c:282
 msgid "Please insert the correct media"
 msgstr "Будь ласка, вставте відповідний носій"
 
 #. TRANSLATORS: tell the user we've not done anything as they are lazy
-#: ../lib/packagekit-glib2/pk-task-text.c:239
+#: ../lib/packagekit-glib2/pk-task-text.c:287
 msgid "The correct media was not inserted."
 msgstr "Не було вставлено відповідного носія."
 
 #. TRANSLATORS: When processing, we might have to remove other dependencies
-#: ../lib/packagekit-glib2/pk-task-text.c:254
+#: ../lib/packagekit-glib2/pk-task-text.c:302
 msgid "The following packages have to be removed:"
 msgstr "Наведені нижче пакунки буде вилучено:"
 
 #. TRANSLATORS: When processing, we might have to install other dependencies
-#: ../lib/packagekit-glib2/pk-task-text.c:259
+#: ../lib/packagekit-glib2/pk-task-text.c:307
 msgid "The following packages have to be installed:"
 msgstr "Слід встановити такі пакунки:"
 
 #. TRANSLATORS: When processing, we might have to update other dependencies
-#: ../lib/packagekit-glib2/pk-task-text.c:264
+#: ../lib/packagekit-glib2/pk-task-text.c:312
 msgid "The following packages have to be updated:"
 msgstr "Слід оновити такі пакунки:"
 
 #. TRANSLATORS: When processing, we might have to reinstall other dependencies
-#: ../lib/packagekit-glib2/pk-task-text.c:269
+#: ../lib/packagekit-glib2/pk-task-text.c:317
 msgid "The following packages have to be reinstalled:"
 msgstr "Слід перевстановити такі пакунки:"
 
 #. TRANSLATORS: When processing, we might have to downgrade other dependencies
-#: ../lib/packagekit-glib2/pk-task-text.c:274
+#: ../lib/packagekit-glib2/pk-task-text.c:322
 msgid "The following packages have to be downgraded:"
 msgstr "Слід встановити старіші версії таких пакунків:"
 
 #. TRANSLATORS: ask the user if the proposed changes are okay
-#: ../lib/packagekit-glib2/pk-task-text.c:333
+#: ../lib/packagekit-glib2/pk-task-text.c:382
 msgid "Proceed with changes?"
 msgstr "Внести зміни:"
 
 #. TRANSLATORS: tell the user we didn't do anything
-#: ../lib/packagekit-glib2/pk-task-text.c:338
+#: ../lib/packagekit-glib2/pk-task-text.c:387
 msgid "The transaction did not proceed."
 msgstr "Операцію не було продовжено."
 
@@ -1865,47 +1900,47 @@ msgstr ""
 "У системному каталозі файл org.freedesktop.PackageKit.conf не встановлено:"
 
 #. TRANSLATORS: a backend is the system package tool, e.g. yum, apt
-#: ../src/pk-main.c:205
+#: ../src/pk-main.c:199
 msgid "Packaging backend to use, e.g. dummy"
 msgstr "Інструмент роботи з пакунками, наприклад, dummy"
 
 #. TRANSLATORS: if we should run in the background
-#: ../src/pk-main.c:208
+#: ../src/pk-main.c:202
 msgid "Daemonize and detach from the terminal"
 msgstr "Створити фонову службу і від’єднатися від термінала"
 
 #. TRANSLATORS: if we should not monitor how long we are inactive for
-#: ../src/pk-main.c:214
+#: ../src/pk-main.c:205
 msgid "Disable the idle timer"
 msgstr "Вимкнути відлік бездіяльності"
 
 #. TRANSLATORS: show version
-#: ../src/pk-main.c:217
+#: ../src/pk-main.c:208
 msgid "Show version and exit"
 msgstr "Показати версію і завершити роботу"
 
 #. TRANSLATORS: exit after we've started up, used for user profiling
-#: ../src/pk-main.c:220
+#: ../src/pk-main.c:211
 msgid "Exit after a small delay"
 msgstr "Завершити роботу з невеличкою затримкою"
 
 #. TRANSLATORS: exit straight away, used for automatic profiling
-#: ../src/pk-main.c:223
+#: ../src/pk-main.c:214
 msgid "Exit after the engine has loaded"
 msgstr "Завершити роботу після завантаження рушія"
 
 #. TRANSLATORS: describing the service that is running
-#: ../src/pk-main.c:238
+#: ../src/pk-main.c:229
 msgid "PackageKit service"
 msgstr "Служба PackageKit"
 
 #. TRANSLATORS: fatal error, dbus is not running
-#: ../src/pk-main.c:275
+#: ../src/pk-main.c:266
 msgid "Cannot connect to the system bus"
 msgstr "Не вдалося з’єднатися з системною шиною"
 
 #. TRANSLATORS: cannot register on system bus, unknown reason -- geeky error follows
-#: ../src/pk-main.c:334
+#: ../src/pk-main.c:317
 msgid "Error trying to start:"
 msgstr "Помилка під час спроби запуску:"
 
@@ -1939,32 +1974,55 @@ msgid "Do not install these packages unless you are sure it is safe to do so."
 msgstr ""
 "Не встановлюйте ці пакунки, якщо не певні, що таке встановлення є безпечним."
 
-#. TRANSLATORS: warn the user that all bets are off
-#: ../src/pk-polkit-action-lookup.c:202
-msgid "Malicious software can damage your computer or cause other harm."
-msgstr ""
-"Зловмисне програмне забезпечення може пошкодити ваш комп’ютер або завдати "
-"інших неприємностей."
-
 #. TRANSLATORS: too many packages to list each one
-#: ../src/pk-polkit-action-lookup.c:277
+#: ../src/pk-polkit-action-lookup.c:273
 msgid "Many packages"
 msgstr "Багато пакунків"
 
 #. TRANSLATORS: if the transaction is forced to install only trusted packages
-#: ../src/pk-polkit-action-lookup.c:343
+#: ../src/pk-polkit-action-lookup.c:339
 msgid "Only trusted"
 msgstr "Лише надійні"
 
+#. TRANSLATORS: turn on all debugging
+#: ../src/egg-debug.c:388
+msgid "Show debugging information for all files"
+msgstr "Показувати діагностичні дані для всіх файлів"
+
+#. TRANSLATORS: a list of modules to debug
+#: ../src/egg-debug.c:459
+msgid "Debug these specific modules"
+msgstr "Діагностика вказаних модулів"
+
+#. TRANSLATORS: a list of functions to debug
+#: ../src/egg-debug.c:462
+msgid "Debug these specific functions"
+msgstr "Діагностика вказаних функцій"
+
+#. TRANSLATORS: save to a log
+#: ../src/egg-debug.c:465
+msgid "Log debugging data to a file"
+msgstr "Записати дані діагностики до файла"
+
+#: ../src/egg-debug.c:469
+msgid "Debugging Options"
+msgstr "Параметри діагностики"
+
+#: ../src/egg-debug.c:469
+msgid "Show debugging options"
+msgstr "Показувати параметри діагностики"
+
+#~ msgid "Malicious software can damage your computer or cause other harm."
+#~ msgstr ""
+#~ "Зловмисне програмне забезпечення може пошкодити ваш комп’ютер або завдати "
+#~ "інших неприємностей."
+
 #~ msgid "Transaction failed with no error"
 #~ msgstr "Спроба виконання операції зазнала невдачі, але помилок не було"
 
 #~ msgid "Failed to get transaction list"
 #~ msgstr "Спроба отримання списку операцій завершилася невдало"
 
-#~ msgid "Percentage"
-#~ msgstr "Відсотки"
-
 #~ msgid "Please restart the application as it is being used."
 #~ msgstr "Перезапустіть програму, оскільки вона зараз використовується."
 
commit 15f883e6823c080f7f5e2b62b79e8cd64c255e52
Author: Tim Waugh <twaugh at redhat.com>
Date:   Tue Mar 2 12:15:18 2010 +0000

    bugfix: fixed packagekit.client.search_file() in Python bindings.

diff --git a/lib/python/packagekit/client.py b/lib/python/packagekit/client.py
index dabc859..5273a7e 100644
--- a/lib/python/packagekit/client.py
+++ b/lib/python/packagekit/client.py
@@ -255,7 +255,7 @@ class PackageKitClient:
 
     def search_file(self, search, filters=FILTER_NONE, exit_handler=None):
         '''Search for packages by their files'''
-        return self._run_transaction("SearchFile", [filters, search],
+        return self._run_transaction("SearchFiles", [filters, search],
                                      exit_handler)
 
     def install_packages(self, packages, only_trusted=True, exit_handler=None):
commit 4e892f7c07bd408e0b39986ee72cd50e16e3e6db
Author: Richard Hughes <richard at hughsie.com>
Date:   Mon Mar 1 10:59:22 2010 +0000

    trivial: post release version bump

diff --git a/RELEASE b/RELEASE
index 34fb471..c83e911 100644
--- a/RELEASE
+++ b/RELEASE
@@ -2,7 +2,7 @@ PackageKit Release Notes
 
 1. Write NEWS entries for PackageKit in the same format as usual.
 
-git shortlog PACKAGEKIT_0_6_1.. | grep -i -v trivial | grep -v Merge > NEWS.new
+git shortlog PACKAGEKIT_0_6_2.. | grep -i -v trivial | grep -v Merge > NEWS.new
 
 --------------------------------------------------------------------------------
 Version 0.6.x
@@ -28,8 +28,8 @@ Bugfixes:
 
 4. Commit changes in PackageKit git:
 
-git commit -a -m "Release version 0.6.2"
-git tag -s -f -m "Release 0.6.2" PACKAGEKIT_0_6_2
+git commit -a -m "Release version 0.6.3"
+git tag -s -f -m "Release 0.6.3" PACKAGEKIT_0_6_3
 <gpg password>
 git push --tags
 git push
@@ -54,9 +54,9 @@ git push
 10. Send an email to packagekit at lists.freedesktop.org
 
 =================================================
-Subject: PackageKit 0.6.1 released!
+Subject: PackageKit 0.6.3 released!
 
-Today I released PackageKit 0.6.1.
+Today I released PackageKit 0.6.3.
 
 PackageKit release notes: http://cgit.freedesktop.org/packagekit/tree/NEWS
 
diff --git a/configure.ac b/configure.ac
index 3480a6e..b65ad88 100644
--- a/configure.ac
+++ b/configure.ac
@@ -3,7 +3,7 @@ AC_PREREQ(2.65)
 
 m4_define([pk_major_version], [0])
 m4_define([pk_minor_version], [6])
-m4_define([pk_micro_version], [2])
+m4_define([pk_micro_version], [3])
 m4_define([pk_version],
           [pk_major_version.pk_minor_version.pk_micro_version])
 
commit b4976cb7ae3279a1b7a1901bb665480060fa8240
Author: Sebastian Heinlein <devel at glatzor.de>
Date:   Tue Mar 2 06:03:17 2010 +0100

    APT: Convert search-files to latest Python backend API changes. Perform
    an AND instead an OR search.

diff --git a/backends/apt/aptBackend.py b/backends/apt/aptBackend.py
index a1f4353..b238df6 100755
--- a/backends/apt/aptBackend.py
+++ b/backends/apt/aptBackend.py
@@ -73,6 +73,10 @@ else:
         pklog.debug("Use XAPIAN for the search")
         XAPIAN_SUPPORT = True
 
+STDOUT_ENCODING = sys.stdout.encoding or sys.getfilesystemencoding()
+FS_ENCODING = sys.getfilesystemencoding()
+DEFAULT_ENCODING = locale.getpreferredencoding()
+
 # SoftwareProperties is required to proivde information about repositories
 try:
     import softwareproperties.SoftwareProperties
@@ -614,11 +618,11 @@ class PackageKitAptBackend(PackageKitBaseBackend):
                 self._emit_all_visible_pkg_versions(filters,
                                                     self._cache[pkg_name])
 
-    def search_details(self, filters, search):
+    def search_details(self, filters, values):
         """
         Implement the apt2-search-details functionality
         """
-        pklog.info("Searching for package name: %s" % search)
+        pklog.info("Searching for package details: %s" % values)
         self.status(STATUS_QUERY)
         self.percentage(None)
         self._check_init(progress=False)
@@ -633,8 +637,8 @@ class PackageKitAptBackend(PackageKitBaseBackend):
             pklog.debug("Performing xapian db based search")
             db = xapian.Database(XAPIAN_DB)
             parser = xapian.QueryParser()
-            query = parser.parse_query(unicode(search),
-                                       search_flags)
+            parser.set_default_op(xapian.Query.OP_AND)
+            query = parser.parse_query(u" ".join(values), search_flags)
             enquire = xapian.Enquire(db)
             enquire.set_query(query)
             matches = enquire.get_mset(0, 1000)
@@ -643,13 +647,21 @@ class PackageKitAptBackend(PackageKitBaseBackend):
                 if pkg_name in self._cache:
                     self._emit_visible_package(filters, self._cache[pkg_name])
         else:
+            def matches(searches, text):
+                for search in searches:
+                    if not search in text:
+                        return False
+                return True
             pklog.debug("Performing apt cache based search")
-            needle = search.strip().lower()
+            values = [val.lower() for val in values]
             for pkg in self._cache:
-                if not pkg.candidate:
-                    continue
-                haystack = pkg.rawDescription.lower()
-                if needle in pkg.name or needle in haystack:
+                txt = pkg.name
+                try:
+                    txt += pkg.candidate.raw_description.lower()
+                    txt += pkg.candidate._translated_records.long_desc.lower()
+                except AttributeError:
+                    pass
+                if matches(values, unicode(txt, DEFAULT_ENCODING, "replace")):
                     self._emit_visible_package(filters, pkg)
 
     def get_distro_upgrades(self):
commit 7ff454a98f5f88d72381dfe7c8f1ae36c644d98d
Author: yeager <yeager at fedoraproject.org>
Date:   Mon Mar 1 17:26:18 2010 +0000

    Sending translation for Swedish

diff --git a/po/sv.po b/po/sv.po
index 57b9b80..b22cca8 100644
--- a/po/sv.po
+++ b/po/sv.po
@@ -1,14 +1,14 @@
 # Swedish translation for packagekit.
-# Copyright (C) 2008, 2009 Free Software Foundation, Inc.
+# Copyright (C) 2008, 2009, 2010 Free Software Foundation, Inc.
 # This file is distributed under the same license as the packagekit package.
-# Daniel Nylander <po at danielnylander.se>, 2008, 2009.
+# Daniel Nylander <po at danielnylander.se>, 2008, 2009, 2010.
 #
 msgid ""
 msgstr ""
 "Project-Id-Version: packagekit\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2009-09-21 02:44+0000\n"
-"PO-Revision-Date: 2009-09-21 09:11+0100\n"
+"POT-Creation-Date: 2010-03-01 15:24+0000\n"
+"PO-Revision-Date: 2010-03-01 18:26+0100\n"
 "Last-Translator: Daniel Nylander <po at danielnylander.se>\n"
 "Language-Team: Swedish <tp-sv at listor.tp-sv.se>\n"
 "MIME-Version: 1.0\n"
@@ -17,298 +17,325 @@ msgstr ""
 "Plural-Forms: nplurals=2; plural=n != 1;\n"
 
 #. TRANSLATORS: this is an atomic transaction
-#: ../client/pk-console.c:142
+#. TRANSLATORS: the role is the point of the transaction, e.g. update-system
+#: ../client/pk-console.c:175
+#: ../client/pk-console.c:597
 msgid "Transaction"
 msgstr "Transaktion"
 
 #. TRANSLATORS: this is the time the transaction was started in system timezone
-#: ../client/pk-console.c:144
+#: ../client/pk-console.c:177
 msgid "System time"
 msgstr "Systemtid"
 
 #. TRANSLATORS: this is if the transaction succeeded or not
-#: ../client/pk-console.c:146
+#: ../client/pk-console.c:179
 msgid "Succeeded"
 msgstr "Lyckades"
 
-#: ../client/pk-console.c:146
+#: ../client/pk-console.c:179
 msgid "True"
 msgstr "Sant"
 
-#: ../client/pk-console.c:146
+#: ../client/pk-console.c:179
 msgid "False"
 msgstr "Falskt"
 
 #. TRANSLATORS: this is the transactions role, e.g. "update-system"
 #. TRANSLATORS: the trasaction role, e.g. update-system
-#: ../client/pk-console.c:148
-#: ../src/pk-polkit-action-lookup.c:336
+#: ../client/pk-console.c:181
+#: ../src/pk-polkit-action-lookup.c:332
 msgid "Role"
 msgstr "Roll"
 
 #. TRANSLATORS: this is The duration of the transaction
-#: ../client/pk-console.c:153
+#: ../client/pk-console.c:186
 msgid "Duration"
 msgstr "Längd"
 
-#: ../client/pk-console.c:153
+#: ../client/pk-console.c:186
 msgid "(seconds)"
 msgstr "(sekunder)"
 
 #. TRANSLATORS: this is The command line used to do the action
 #. TRANSLATORS: the command line of the thing that wants the authentication
-#: ../client/pk-console.c:157
-#: ../src/pk-polkit-action-lookup.c:350
+#: ../client/pk-console.c:190
+#: ../src/pk-polkit-action-lookup.c:346
 msgid "Command line"
 msgstr "Kommandorad"
 
 #. TRANSLATORS: this is the user ID of the user that started the action
-#: ../client/pk-console.c:159
+#: ../client/pk-console.c:192
 msgid "User ID"
 msgstr "Användar-id"
 
 #. TRANSLATORS: this is the username, e.g. hughsie
-#: ../client/pk-console.c:166
+#: ../client/pk-console.c:199
 msgid "Username"
 msgstr "Användarnamn"
 
 #. TRANSLATORS: this is the users real name, e.g. "Richard Hughes"
-#: ../client/pk-console.c:170
+#: ../client/pk-console.c:203
 msgid "Real name"
 msgstr "Verkligt namn"
 
-#: ../client/pk-console.c:178
+#: ../client/pk-console.c:211
 msgid "Affected packages:"
 msgstr "PÃ¥verkade paket:"
 
-#: ../client/pk-console.c:180
+#: ../client/pk-console.c:213
 msgid "Affected packages: None"
 msgstr "PÃ¥verkade paket: Inga"
 
 #. TRANSLATORS: this is the distro, e.g. Fedora 10
-#: ../client/pk-console.c:200
+#: ../client/pk-console.c:248
 msgid "Distribution"
 msgstr "Distribution"
 
 #. TRANSLATORS: this is type of update, stable or testing
-#: ../client/pk-console.c:202
+#: ../client/pk-console.c:250
 msgid "Type"
 msgstr "Typ"
 
 #. TRANSLATORS: this is any summary text describing the upgrade
 #. TRANSLATORS: this is the summary of the group
-#: ../client/pk-console.c:204
-#: ../client/pk-console.c:225
+#: ../client/pk-console.c:252
+#: ../client/pk-console.c:291
 msgid "Summary"
 msgstr "Sammandrag"
 
 #. TRANSLATORS: this is the group category name
-#: ../client/pk-console.c:214
+#: ../client/pk-console.c:280
 msgid "Category"
 msgstr "Kategori"
 
 #. TRANSLATORS: this is group identifier
-#: ../client/pk-console.c:216
+#: ../client/pk-console.c:282
 msgid "ID"
 msgstr "ID"
 
 #. TRANSLATORS: this is the parent group
-#: ../client/pk-console.c:219
+#: ../client/pk-console.c:285
 msgid "Parent"
 msgstr "Förälder"
 
 #. TRANSLATORS: this is the name of the parent group
-#: ../client/pk-console.c:222
+#: ../client/pk-console.c:288
 msgid "Name"
 msgstr "Namn"
 
 #. TRANSLATORS: this is preferred icon for the group
-#: ../client/pk-console.c:228
+#: ../client/pk-console.c:294
 msgid "Icon"
 msgstr "Ikon"
 
 #. TRANSLATORS: this is a header for the package that can be updated
-#: ../client/pk-console.c:242
+#: ../client/pk-console.c:340
 msgid "Details about the update:"
 msgstr "Detaljer om uppdateringen:"
 
 #. TRANSLATORS: details about the update, package name and version
+#. TRANSLATORS: the package that is being processed
 #. TRANSLATORS: the package that is not signed by a known key
 #. TRANSLATORS: the package name that was trying to be installed
 #. TRANSLATORS: title, the names of the packages that the method is processing
-#: ../client/pk-console.c:248
-#: ../lib/packagekit-glib2/pk-task-text.c:105
-#: ../lib/packagekit-glib2/pk-task-text.c:172
-#: ../src/pk-polkit-action-lookup.c:361
+#: ../client/pk-console.c:346
+#: ../client/pk-console.c:616
+#: ../lib/packagekit-glib2/pk-task-text.c:126
+#: ../lib/packagekit-glib2/pk-task-text.c:208
+#: ../src/pk-polkit-action-lookup.c:357
 msgid "Package"
 msgid_plural "Packages"
 msgstr[0] "Paket"
 msgstr[1] "Paket"
 
 #. TRANSLATORS: details about the update, any packages that this update updates
-#: ../client/pk-console.c:251
+#: ../client/pk-console.c:349
 msgid "Updates"
 msgstr "Uppdaterar"
 
 #. TRANSLATORS: details about the update, any packages that this update obsoletes
-#: ../client/pk-console.c:255
+#: ../client/pk-console.c:353
 msgid "Obsoletes"
 msgstr "Föräldrar"
 
 #. TRANSLATORS: details about the update, the vendor URLs
 #. TRANSLATORS: the vendor (e.g. vmware) that is providing the EULA
-#: ../client/pk-console.c:259
-#: ../lib/packagekit-glib2/pk-task-text.c:175
+#: ../client/pk-console.c:357
+#: ../lib/packagekit-glib2/pk-task-text.c:211
 msgid "Vendor"
 msgstr "Leverantör"
 
 #. TRANSLATORS: details about the update, the bugzilla URLs
-#: ../client/pk-console.c:263
+#: ../client/pk-console.c:361
 msgid "Bugzilla"
 msgstr "Bugzilla"
 
 #. TRANSLATORS: details about the update, the CVE URLs
-#: ../client/pk-console.c:267
+#: ../client/pk-console.c:365
 msgid "CVE"
 msgstr "CVE"
 
 #. TRANSLATORS: details about the update, if the package requires a restart
-#: ../client/pk-console.c:271
+#: ../client/pk-console.c:369
 msgid "Restart"
 msgstr "Omstart"
 
 #. TRANSLATORS: details about the update, any description of the update
-#: ../client/pk-console.c:275
+#: ../client/pk-console.c:373
 msgid "Update text"
 msgstr "Uppdateringstext"
 
 #. TRANSLATORS: details about the update, the changelog for the package
-#: ../client/pk-console.c:279
+#: ../client/pk-console.c:377
 msgid "Changes"
 msgstr "Ändringar"
 
 #. TRANSLATORS: details about the update, the ongoing state of the update
-#: ../client/pk-console.c:283
+#: ../client/pk-console.c:381
 msgid "State"
 msgstr "Tillstånd"
 
 #. TRANSLATORS: details about the update, date the update was issued
-#: ../client/pk-console.c:288
+#: ../client/pk-console.c:385
 msgid "Issued"
 msgstr "Utfärdad"
 
 #. TRANSLATORS: details about the update, date the update was updated
 #. TRANSLATORS: The action of the package, in past tense
-#: ../client/pk-console.c:293
-#: ../lib/packagekit-glib2/pk-console-shared.c:494
+#: ../client/pk-console.c:389
+#: ../lib/packagekit-glib2/pk-console-shared.c:510
 msgid "Updated"
 msgstr "Uppdaterad"
 
 #. TRANSLATORS: if the repo is enabled
-#: ../client/pk-console.c:311
+#: ../client/pk-console.c:425
 msgid "Enabled"
 msgstr "Aktiverad"
 
 #. TRANSLATORS: if the repo is disabled
-#: ../client/pk-console.c:314
+#: ../client/pk-console.c:428
 msgid "Disabled"
 msgstr "Inaktiverad"
 
 #. TRANSLATORS: a package requires the system to be restarted
-#: ../client/pk-console.c:336
+#: ../client/pk-console.c:460
 msgid "System restart required by:"
 msgstr "Omstart av systemet krävs:"
 
 #. TRANSLATORS: a package requires the session to be restarted
-#: ../client/pk-console.c:339
+#: ../client/pk-console.c:463
 msgid "Session restart required:"
 msgstr "Omstart av sessionen krävs:"
 
 #. TRANSLATORS: a package requires the system to be restarted due to a security update
-#: ../client/pk-console.c:342
+#: ../client/pk-console.c:466
 msgid "System restart (security) required by:"
 msgstr "Omstart av systemet (säkerhet) krävs av:"
 
 #. TRANSLATORS: a package requires the session to be restarted due to a security update
-#: ../client/pk-console.c:345
+#: ../client/pk-console.c:469
 msgid "Session restart (security) required:"
 msgstr "Omstart av sessionen (säkerhet) krävs:"
 
 #. TRANSLATORS: a package requires the application to be restarted
-#: ../client/pk-console.c:348
+#: ../client/pk-console.c:472
 msgid "Application restart required by:"
 msgstr "Omstart av program krävs av:"
 
 #. TRANSLATORS: This a list of details about the package
-#: ../client/pk-console.c:365
+#: ../client/pk-console.c:507
 msgid "Package description"
 msgstr "Paketbeskrivning"
 
 #. TRANSLATORS: This a message (like a little note that may be of interest) from the transaction
-#: ../client/pk-console.c:383
+#: ../client/pk-console.c:538
 msgid "Message:"
 msgstr "Meddelande:"
 
 #. TRANSLATORS: This where the package has no files
-#: ../client/pk-console.c:397
+#: ../client/pk-console.c:559
 msgid "No files"
 msgstr "Inga filer"
 
 #. TRANSLATORS: This a list files contained in the package
-#: ../client/pk-console.c:402
+#: ../client/pk-console.c:564
 msgid "Package files"
 msgstr "Paketfiler"
 
+#. TRANSLATORS: the percentage complete of the transaction
+#: ../client/pk-console.c:632
+msgid "Percentage"
+msgstr "Procentandel"
+
+#. TRANSLATORS: the status of the transaction (e.g. downloading)
+#: ../client/pk-console.c:650
+msgid "Status"
+msgstr "Status"
+
+#. TRANSLATORS: the results from the transaction
+#: ../client/pk-console.c:679
+msgid "Results:"
+msgstr "Resultat:"
+
 #. TRANSLATORS: we failed to get any results, which is pretty fatal in my book
-#: ../client/pk-console.c:475
+#: ../client/pk-console.c:686
 msgid "Fatal error"
 msgstr "Ödesdigert fel"
 
-#. TRANSLATORS: we failed, but there was no error set
-#: ../client/pk-console.c:488
-msgid "Transaction failed with no error"
-msgstr "Transaktionen misslyckades utan något fel"
-
 #. TRANSLATORS: the transaction failed in a way we could not expect
-#: ../client/pk-console.c:493
+#: ../client/pk-console.c:695
+#: ../contrib/command-not-found/pk-command-not-found.c:432
+#: ../contrib/command-not-found/pk-command-not-found.c:603
 msgid "The transaction failed"
 msgstr "Transaktionen misslyckades"
 
+#. TRANSLATORS: print a message when there are no updates
+#: ../client/pk-console.c:726
+msgid "There are no updates available at this time."
+msgstr "Det finns inga uppdateringar tillgängliga just nu."
+
 #. TRANSLATORS: a package needs to restart their system
-#: ../client/pk-console.c:567
+#: ../client/pk-console.c:814
 msgid "Please restart the computer to complete the update."
 msgstr "Starta om datorn för att färdigställa uppdateringen."
 
 #. TRANSLATORS: a package needs to restart the session
-#: ../client/pk-console.c:570
+#: ../client/pk-console.c:817
 msgid "Please logout and login to complete the update."
 msgstr "Logga ut och logga in igen för att färdigställa uppdateringen."
 
 #. TRANSLATORS: a package needs to restart their system (due to security)
-#: ../client/pk-console.c:573
+#: ../client/pk-console.c:820
 msgid "Please restart the computer to complete the update as important security updates have been installed."
 msgstr "Starta om datorn för att färdigställa uppdateringen eftersom viktiga säkerhetsuppdateringar har installerats."
 
 #. TRANSLATORS: a package needs to restart the session (due to security)
-#: ../client/pk-console.c:576
+#: ../client/pk-console.c:823
 msgid "Please logout and login to complete the update as important security updates have been installed."
 msgstr "Logga ut och logga in igen för att färdigställa uppdateringen eftersom viktiga säkerhetsuppdateringar har installerats."
 
+#. TRANSLATORS: The user used 'pkcon install dave.rpm' rather than 'pkcon install-local dave.rpm'
+#: ../client/pk-console.c:849
+#, c-format
+msgid "Extected package name, actually got file. Try using 'pkcon install-local %s' instead."
+msgstr "Förväntade paketnamn men fick filen. Prova använda \"pkcon install-local %s\" istället."
+
 #. TRANSLATORS: There was an error getting the list of files for the package. The detailed error follows
-#: ../client/pk-console.c:597
+#: ../client/pk-console.c:857
 #, c-format
 msgid "This tool could not find any available package: %s"
 msgstr "Detta verktyg kunde inte hitta några tillgängliga paket: %s"
 
 #. TRANSLATORS: There was an error getting the list of files for the package. The detailed error follows
-#: ../client/pk-console.c:625
+#: ../client/pk-console.c:885
 #, c-format
 msgid "This tool could not find the installed package: %s"
 msgstr "Detta verktyg kunde inte hitta det installerade paketet: %s"
 
 #. TRANSLATORS: There was an error getting the list of files for the package. The detailed error follows
-#: ../client/pk-console.c:653
-#: ../client/pk-console.c:681
+#: ../client/pk-console.c:913
+#: ../client/pk-console.c:941
 #, c-format
 msgid "This tool could not find the package: %s"
 msgstr "Detta verktyg kunde inte hitta paketet: %s"
@@ -317,295 +344,299 @@ msgstr "Detta verktyg kunde inte hitta paketet: %s"
 #. TRANSLATORS: There was an error getting the dependencies for the package. The detailed error follows
 #. TRANSLATORS: There was an error getting the details about the package. The detailed error follows
 #. TRANSLATORS: The package name was not found in any software sources. The detailed error follows
-#: ../client/pk-console.c:709
-#: ../client/pk-console.c:737
-#: ../client/pk-console.c:765
-#: ../client/pk-console.c:793
-#: ../client/pk-console.c:821
+#: ../client/pk-console.c:969
+#: ../client/pk-console.c:997
+#: ../client/pk-console.c:1025
+#: ../client/pk-console.c:1053
+#: ../client/pk-console.c:1081
 #, c-format
 msgid "This tool could not find all the packages: %s"
 msgstr "Detta verktyg kunde inte hitta alla paketen: %s"
 
 #. TRANSLATORS: This is when the daemon crashed, and we are up shit creek without a paddle
-#: ../client/pk-console.c:850
+#: ../client/pk-console.c:1110
 msgid "The daemon crashed mid-transaction!"
 msgstr "Bakgrundsprocessen kraschade mitt under transaktionen!"
 
 #. TRANSLATORS: This is the header to the --help menu
-#: ../client/pk-console.c:884
+#: ../client/pk-console.c:1144
 msgid "PackageKit Console Interface"
 msgstr "Konsollgränssnitt för PackageKit"
 
 #. these are commands we can use with pkcon
-#: ../client/pk-console.c:886
+#: ../client/pk-console.c:1146
 msgid "Subcommands:"
 msgstr "Underkommandon:"
 
 #. TRANSLATORS: we keep a database updated with the time that an action was last executed
-#: ../client/pk-console.c:965
+#: ../client/pk-console.c:1225
 msgid "Failed to get the time since this action was last completed"
 msgstr "Misslyckades med att få tiden sedan denna åtgärd senast färdigställdes"
 
-#. TRANSLATORS: command line argument, if we should show debugging information
-#. TRANSLATORS: if we should show debugging data
-#: ../client/pk-console.c:1000
-#: ../client/pk-generate-pack.c:222
-#: ../client/pk-monitor.c:249
-#: ../contrib/command-not-found/pk-command-not-found.c:614
-#: ../contrib/debuginfo-install/pk-debuginfo-install.c:504
-#: ../contrib/device-rebind/pk-device-rebind.c:293
-#: ../src/pk-main.c:211
-msgid "Show extra debugging information"
-msgstr "Visa extra felsökningsinformation"
-
 #. TRANSLATORS: command line argument, just show the version string
-#: ../client/pk-console.c:1003
-#: ../client/pk-monitor.c:251
+#: ../client/pk-console.c:1261
+#: ../client/pk-monitor.c:306
 msgid "Show the program version and exit"
 msgstr "Visa programversion och avsluta"
 
 #. TRANSLATORS: command line argument, use a filter to narrow down results
-#: ../client/pk-console.c:1006
+#: ../client/pk-console.c:1264
 msgid "Set the filter, e.g. installed"
 msgstr "Ange filtret, t.ex. installed"
 
 #. TRANSLATORS: command line argument, work asynchronously
-#: ../client/pk-console.c:1009
+#: ../client/pk-console.c:1267
 msgid "Exit without waiting for actions to complete"
 msgstr "Avsluta utan att vänta på att åtgärder ska färdigställas"
 
+#. command line argument, do we ask questions
+#: ../client/pk-console.c:1270
+#: ../contrib/debuginfo-install/pk-debuginfo-install.c:527
+msgid "Install the packages without asking for confirmation"
+msgstr "Installera paketen utan att fråga efter bekräftelse"
+
+#. TRANSLATORS: command line argument, this command is not a priority
+#: ../client/pk-console.c:1273
+msgid "Run the command using idle network bandwidth and also using less power"
+msgstr "Kör kommandot med inaktiv nätverksbandbredd och även med mindre ström"
+
+#. TRANSLATORS: command line argument, just output without fancy formatting
+#: ../client/pk-console.c:1276
+msgid "Print to screen a machine readable output, rather than using animated widgets"
+msgstr "Skriv ut maskinläsbart utdata på skärmen istället för att använda animerade widgetar"
+
 #. TRANSLATORS: we failed to contact the daemon
-#: ../client/pk-console.c:1034
+#: ../client/pk-console.c:1298
 msgid "Failed to contact PackageKit"
 msgstr "Misslyckades med att kontakta PackageKit"
 
 #. TRANSLATORS: The user specified an incorrect filter
-#: ../client/pk-console.c:1086
+#: ../client/pk-console.c:1356
 msgid "The filter specified was invalid"
 msgstr "Angivet filter var ogiltigt"
 
 #. TRANSLATORS: a search type can be name, details, file, etc
-#: ../client/pk-console.c:1105
+#: ../client/pk-console.c:1375
 msgid "A search type is required, e.g. name"
 msgstr "En söktyp krävs, t.ex. namn"
 
 #. TRANSLATORS: the user needs to provide a search term
-#: ../client/pk-console.c:1112
-#: ../client/pk-console.c:1124
-#: ../client/pk-console.c:1136
-#: ../client/pk-console.c:1148
+#: ../client/pk-console.c:1382
+#: ../client/pk-console.c:1394
+#: ../client/pk-console.c:1406
+#: ../client/pk-console.c:1418
 msgid "A search term is required"
 msgstr "Ett sökvillkor krävs"
 
 #. TRANSLATORS: the search type was provided, but invalid
-#: ../client/pk-console.c:1158
+#: ../client/pk-console.c:1428
 msgid "Invalid search type"
 msgstr "Ogiltig söktyp"
 
 #. TRANSLATORS: the user did not specify what they wanted to install
-#: ../client/pk-console.c:1164
+#: ../client/pk-console.c:1434
 msgid "A package name to install is required"
 msgstr "Ett paketnamn att installera krävs"
 
 #. TRANSLATORS: the user did not specify what they wanted to install
-#: ../client/pk-console.c:1173
+#: ../client/pk-console.c:1443
 msgid "A filename to install is required"
 msgstr "Ett filnamn att installera krävs"
 
 #. TRANSLATORS: geeky error, 99.9999% of users won't see this
-#: ../client/pk-console.c:1185
+#: ../client/pk-console.c:1455
 msgid "A type, key_id and package_id are required"
 msgstr "En type, key_id och package_id krävs"
 
 #. TRANSLATORS: the user did not specify what they wanted to remove
-#: ../client/pk-console.c:1196
+#: ../client/pk-console.c:1466
 msgid "A package name to remove is required"
 msgstr "Ett paketnamn att ta bort krävs"
 
 #. TRANSLATORS: the user did not specify anything about what to download or where
-#: ../client/pk-console.c:1205
+#: ../client/pk-console.c:1475
 msgid "A destination directory and the package names to download are required"
 msgstr "En målkatalog och paketnamn att hämta ner krävs"
 
 #. TRANSLATORS: the directory does not exist, so we can't continue
-#: ../client/pk-console.c:1212
+#: ../client/pk-console.c:1482
 msgid "Directory not found"
 msgstr "Katalogen hittades inte"
 
 #. TRANSLATORS: geeky error, 99.9999% of users won't see this
-#: ../client/pk-console.c:1221
+#: ../client/pk-console.c:1491
 msgid "A licence identifier (eula-id) is required"
 msgstr "En licensidentifierare (eula-id) krävs"
 
 #. TRANSLATORS: geeky error, 99.9999% of users won't see this
-#: ../client/pk-console.c:1232
+#: ../client/pk-console.c:1502
 msgid "A transaction identifier (tid) is required"
 msgstr "En transaktionsidentifierare (tid) krävs"
 
 #. TRANSLATORS: The user did not specify a package name
-#: ../client/pk-console.c:1253
+#: ../client/pk-console.c:1523
 msgid "A package name to resolve is required"
 msgstr "Ett paketnamn att slå upp krävs"
 
 #. TRANSLATORS: The user did not specify a repository (software source) name
-#: ../client/pk-console.c:1264
-#: ../client/pk-console.c:1275
+#: ../client/pk-console.c:1534
+#: ../client/pk-console.c:1545
 msgid "A repository name is required"
 msgstr "Ett förrådsnamn krävs"
 
 #. TRANSLATORS: The user didn't provide any data
-#: ../client/pk-console.c:1286
+#: ../client/pk-console.c:1556
 msgid "A repo name, parameter and value are required"
 msgstr "Ett förrådsnamn, parameter och värde krävs"
 
 #. TRANSLATORS: The user didn't specify what action to use
-#: ../client/pk-console.c:1303
+#: ../client/pk-console.c:1573
 msgid "An action, e.g. 'update-system' is required"
 msgstr "En åtgärd, t.ex. \"update-system\" krävs"
 
 #. TRANSLATORS: The user specified an invalid action
-#: ../client/pk-console.c:1310
+#: ../client/pk-console.c:1580
 msgid "A correct role is required"
 msgstr "En korrekt roll krävs"
 
 #. TRANSLATORS: The user did not provide a package name
 #. TRANSLATORS: This is when the user fails to supply the package name
-#: ../client/pk-console.c:1320
-#: ../client/pk-console.c:1335
-#: ../client/pk-console.c:1344
-#: ../client/pk-console.c:1364
-#: ../client/pk-console.c:1373
-#: ../client/pk-generate-pack.c:285
+#: ../client/pk-console.c:1590
+#: ../client/pk-console.c:1605
+#: ../client/pk-console.c:1614
+#: ../client/pk-console.c:1634
+#: ../client/pk-console.c:1643
+#: ../client/pk-generate-pack.c:316
 msgid "A package name is required"
 msgstr "Ett paketnamn krävs"
 
 #. TRANSLATORS: each package "provides" certain things, e.g. mime(gstreamer-decoder-mp3), the user didn't specify it
-#: ../client/pk-console.c:1353
+#: ../client/pk-console.c:1623
 msgid "A package provide string is required"
 msgstr "En sträng för vad paketet tillhandahåller krävs"
 
 #. TRANSLATORS: The user tried to use an unsupported option on the command line
-#: ../client/pk-console.c:1433
+#: ../client/pk-console.c:1703
 #, c-format
 msgid "Option '%s' is not supported"
 msgstr "Flaggan \"%s\" stöds inte"
 
 #. TRANSLATORS: Generic failure of what they asked to do
-#: ../client/pk-console.c:1443
+#: ../client/pk-console.c:1713
 msgid "Command failed"
 msgstr "Kommandot misslyckades"
 
 #. TRANSLATORS: we can exclude certain packages (glibc) when we know they'll exist on the target
-#: ../client/pk-generate-pack.c:225
+#: ../client/pk-generate-pack.c:255
 msgid "Set the file name of dependencies to be excluded"
 msgstr "Ange filnamnet för beroenden att undanta"
 
 #. TRANSLATORS: the output location
-#: ../client/pk-generate-pack.c:228
+#: ../client/pk-generate-pack.c:258
 msgid "The output file or directory (the current directory is used if ommitted)"
 msgstr "Fil eller katalog för utdata (den aktuella katalogen används om den inte anges)"
 
 #. TRANSLATORS: put a list of packages in the pack
-#: ../client/pk-generate-pack.c:231
+#: ../client/pk-generate-pack.c:261
 msgid "The package to be put into the service pack"
 msgstr "Paket att läggas i servicepaketet"
 
 #. TRANSLATORS: put all pending updates in the pack
-#: ../client/pk-generate-pack.c:234
+#: ../client/pk-generate-pack.c:264
 msgid "Put all updates available in the service pack"
 msgstr "Lägg alla tillgängliga uppdateringar i servicepaketet"
 
 #. TRANSLATORS: This is when the user fails to supply the correct arguments
-#: ../client/pk-generate-pack.c:269
+#: ../client/pk-generate-pack.c:300
 msgid "Neither --package or --updates option selected."
 msgstr "Varken flaggan --package eller --updates angavs."
 
 #. TRANSLATORS: This is when the user fails to supply just one argument
-#: ../client/pk-generate-pack.c:277
+#: ../client/pk-generate-pack.c:308
 msgid "Both options selected."
 msgstr "BÃ¥da flaggorna angavs."
 
 #. TRANSLATORS: This is when the user fails to supply the output
-#: ../client/pk-generate-pack.c:293
+#: ../client/pk-generate-pack.c:324
 msgid "A output directory or file name is required"
 msgstr "En utmatningskatalog eller filnamn krävs"
 
 #. TRANSLATORS: This is when the dameon is not-installed/broken and fails to startup
-#: ../client/pk-generate-pack.c:311
+#: ../client/pk-generate-pack.c:342
 msgid "The dameon failed to startup"
 msgstr "Bakgrundsprocessen misslyckades att starta upp"
 
 #. TRANSLATORS: This is when the backend doesn't have the capability to get-depends
 #. TRANSLATORS: This is when the backend doesn't have the capability to download
-#: ../client/pk-generate-pack.c:322
-#: ../client/pk-generate-pack.c:328
+#: ../client/pk-generate-pack.c:353
+#: ../client/pk-generate-pack.c:359
 msgid "The package manager cannot perform this type of operation."
 msgstr "Pakethanteraren kan inte genomföra denna typ av åtgärd."
 
 #. TRANSLATORS: This is when the distro didn't include libarchive support into PK
-#: ../client/pk-generate-pack.c:335
+#: ../client/pk-generate-pack.c:366
 msgid "Service packs cannot be created as PackageKit was not built with libarchive support."
 msgstr "Servicepaket kan inte skapa eftersom PackageKit inte har byggts med stöd för libarchive."
 
 #. TRANSLATORS: the user specified an absolute path, but didn't get the extension correct
-#: ../client/pk-generate-pack.c:346
+#: ../client/pk-generate-pack.c:377
 msgid "If specifying a file, the service pack name must end with"
 msgstr "Om en fil anges måste servicepaketets namn avslutas med"
 
 #. TRANSLATORS: This is when file already exists
-#: ../client/pk-generate-pack.c:362
+#: ../client/pk-generate-pack.c:393
 msgid "A pack with the same name already exists, do you want to overwrite it?"
 msgstr "Ett paket med samma namn finns redan. Vill du skriva över det?"
 
 #. TRANSLATORS: This is when the pack was not overwritten
-#: ../client/pk-generate-pack.c:365
+#: ../client/pk-generate-pack.c:396
 msgid "The pack was not overwritten."
 msgstr "Paketet skrevs inte över."
 
 #. TRANSLATORS: This is when the temporary directory cannot be created, the directory name follows
-#: ../client/pk-generate-pack.c:378
+#: ../client/pk-generate-pack.c:409
 msgid "Failed to create directory:"
 msgstr "Misslyckades med att skapa katalog:"
 
 #. TRANSLATORS: This is when the list of packages from the remote computer cannot be opened
-#: ../client/pk-generate-pack.c:390
+#: ../client/pk-generate-pack.c:421
 msgid "Failed to open package list."
 msgstr "Misslyckades med öppna paketlistan."
 
 #. TRANSLATORS: The package name is being matched up to available packages
-#: ../client/pk-generate-pack.c:399
+#: ../client/pk-generate-pack.c:430
 msgid "Finding package name."
 msgstr "Söker efter paketnamn."
 
 #. TRANSLATORS: This is when the package cannot be found in any software source. The detailed error follows
-#: ../client/pk-generate-pack.c:403
+#: ../client/pk-generate-pack.c:434
 #, c-format
 msgid "Failed to find package '%s': %s"
 msgstr "Misslyckades med att hitta paketet \"%s\": %s"
 
 #. TRANSLATORS: This is telling the user we are in the process of making the pack
-#: ../client/pk-generate-pack.c:411
+#: ../client/pk-generate-pack.c:442
 msgid "Creating service pack..."
 msgstr "Skapar servicepaket..."
 
 #. TRANSLATORS: we succeeded in making the file
-#: ../client/pk-generate-pack.c:426
+#: ../client/pk-generate-pack.c:457
 #, c-format
 msgid "Service pack created '%s'"
 msgstr "Servicepaket skapades \"%s\""
 
 #. TRANSLATORS: we failed to make te file
-#: ../client/pk-generate-pack.c:431
+#: ../client/pk-generate-pack.c:462
 #, c-format
 msgid "Failed to create '%s': %s"
 msgstr "Misslyckades med att skapa \"%s\": %s"
 
-#: ../client/pk-monitor.c:179
+#: ../client/pk-monitor.c:236
 msgid "Failed to get daemon state"
 msgstr "Misslyckades med läsa av tillstånd för bakgrundsprocess"
 
 #. TRANSLATORS: this is a program that monitors PackageKit
-#: ../client/pk-monitor.c:266
+#: ../client/pk-monitor.c:322
 msgid "PackageKit Monitor"
 msgstr "Övervakare för PackageKit"
 
@@ -664,370 +695,379 @@ msgid "Installing..."
 msgstr "Installerar..."
 
 #. TRANSLATORS: downloading repo data so we can search
-#: ../contrib/command-not-found/pk-command-not-found.c:358
+#: ../contrib/command-not-found/pk-command-not-found.c:365
 msgid "Downloading details about the software sources."
 msgstr "Hämtar detaljer om programkällorna."
 
 #. TRANSLATORS: downloading file lists so we can search
-#: ../contrib/command-not-found/pk-command-not-found.c:362
+#: ../contrib/command-not-found/pk-command-not-found.c:369
 msgid "Downloading filelists (this may take some time to complete)."
 msgstr "Hämtar fillistor (detta kan ta lite tid att färdigställa)."
 
 #. TRANSLATORS: waiting for native lock
-#: ../contrib/command-not-found/pk-command-not-found.c:366
+#: ../contrib/command-not-found/pk-command-not-found.c:373
 msgid "Waiting for package manager lock."
 msgstr "Väntar på låset för pakethanteraren."
 
 #. TRANSLATORS: loading package cache so we can search
-#: ../contrib/command-not-found/pk-command-not-found.c:370
+#: ../contrib/command-not-found/pk-command-not-found.c:377
 msgid "Loading list of packages."
 msgstr "Läser in lista över paket."
 
 #. TRANSLATORS: we failed to find the package, this shouldn't happen
-#: ../contrib/command-not-found/pk-command-not-found.c:444
+#: ../contrib/command-not-found/pk-command-not-found.c:423
 msgid "Failed to search for file"
 msgstr "Misslyckades med att söka efter filen"
 
 #. TRANSLATORS: we failed to launch the executable, the error follows
-#: ../contrib/command-not-found/pk-command-not-found.c:570
+#: ../contrib/command-not-found/pk-command-not-found.c:566
 msgid "Failed to launch:"
 msgstr "Misslyckades med att starta:"
 
+#. TRANSLATORS: we failed to install the package
+#: ../contrib/command-not-found/pk-command-not-found.c:594
+msgid "Failed to install packages"
+msgstr "Misslyckades med att installera paket"
+
 #. TRANSLATORS: tool that gets called when the command is not found
-#: ../contrib/command-not-found/pk-command-not-found.c:630
+#: ../contrib/command-not-found/pk-command-not-found.c:670
 msgid "PackageKit Command Not Found"
 msgstr "PackageKit - Kommandot hittades inte"
 
 #. TRANSLATORS: the prefix of all the output telling the user why it's not executing
-#: ../contrib/command-not-found/pk-command-not-found.c:658
+#: ../contrib/command-not-found/pk-command-not-found.c:699
 msgid "Command not found."
 msgstr "Kommandot hittades inte."
 
 #. TRANSLATORS: tell the user what we think the command is
-#: ../contrib/command-not-found/pk-command-not-found.c:665
+#: ../contrib/command-not-found/pk-command-not-found.c:706
 msgid "Similar command is:"
 msgstr "Liknande kommando är:"
 
 #. TRANSLATORS: Ask the user if we should run the similar command
-#: ../contrib/command-not-found/pk-command-not-found.c:674
+#: ../contrib/command-not-found/pk-command-not-found.c:716
 msgid "Run similar command:"
 msgstr "Kör liknande command:"
 
 #. TRANSLATORS: show the user a list of commands that they could have meant
 #. TRANSLATORS: show the user a list of commands we could run
-#: ../contrib/command-not-found/pk-command-not-found.c:686
-#: ../contrib/command-not-found/pk-command-not-found.c:695
+#: ../contrib/command-not-found/pk-command-not-found.c:730
+#: ../contrib/command-not-found/pk-command-not-found.c:739
 msgid "Similar commands are:"
 msgstr "Liknande kommandon är:"
 
 #. TRANSLATORS: ask the user to choose a file to run
-#: ../contrib/command-not-found/pk-command-not-found.c:702
+#: ../contrib/command-not-found/pk-command-not-found.c:746
 msgid "Please choose a command to run"
 msgstr "Välj ett kommando att köra"
 
 #. TRANSLATORS: tell the user what package provides the command
-#: ../contrib/command-not-found/pk-command-not-found.c:721
+#: ../contrib/command-not-found/pk-command-not-found.c:764
 msgid "The package providing this file is:"
 msgstr "Paketet som tillhandahåller denna fil är:"
 
 #. TRANSLATORS: as the user if we want to install a package to provide the command
-#: ../contrib/command-not-found/pk-command-not-found.c:726
+#: ../contrib/command-not-found/pk-command-not-found.c:769
 #, c-format
 msgid "Install package '%s' to provide command '%s'?"
 msgstr "Installera paketet \"%s\" för att tillhandahålla kommandot \"%s\"?"
 
 #. TRANSLATORS: Show the user a list of packages that provide this command
-#: ../contrib/command-not-found/pk-command-not-found.c:747
+#: ../contrib/command-not-found/pk-command-not-found.c:793
 msgid "Packages providing this file are:"
 msgstr "Paket som tillhandahåller denna fil är:"
 
 #. TRANSLATORS: Show the user a list of packages that they can install to provide this command
-#: ../contrib/command-not-found/pk-command-not-found.c:756
+#: ../contrib/command-not-found/pk-command-not-found.c:803
 msgid "Suitable packages are:"
 msgstr "Lämpliga paket är:"
 
 #. get selection
 #. TRANSLATORS: ask the user to choose a file to install
-#: ../contrib/command-not-found/pk-command-not-found.c:764
+#: ../contrib/command-not-found/pk-command-not-found.c:812
 msgid "Please choose a package to install"
 msgstr "Välj ett paket att installera"
 
 #. TRANSLATORS: we are starting to install the packages
-#: ../contrib/debuginfo-install/pk-debuginfo-install.c:195
+#: ../contrib/debuginfo-install/pk-debuginfo-install.c:197
 msgid "Starting install"
 msgstr "Påbörjar installation"
 
 #. TRANSLATORS: we couldn't find the package name, non-fatal
-#: ../contrib/debuginfo-install/pk-debuginfo-install.c:406
+#: ../contrib/debuginfo-install/pk-debuginfo-install.c:409
 #, c-format
 msgid "Failed to find the package %s, or already installed: %s"
 msgstr "Misslyckades med att hitta paketet %s, eller så är det redan installerat: %s"
 
 #. command line argument, simulate what would be done, but don't actually do it
-#: ../contrib/debuginfo-install/pk-debuginfo-install.c:507
+#: ../contrib/debuginfo-install/pk-debuginfo-install.c:518
 msgid "Don't actually install any packages, only simulate what would be installed"
 msgstr "Installera inte några paket, simulera endast vad som ska installeras"
 
 #. command line argument, do we skip packages that depend on the ones specified
-#: ../contrib/debuginfo-install/pk-debuginfo-install.c:510
+#: ../contrib/debuginfo-install/pk-debuginfo-install.c:521
 msgid "Do not install dependencies of the core packages"
 msgstr "Installera inte några beroenden för baspaketen"
 
 #. command line argument, do we operate quietly
-#: ../contrib/debuginfo-install/pk-debuginfo-install.c:513
+#: ../contrib/debuginfo-install/pk-debuginfo-install.c:524
 msgid "Do not display information or progress"
 msgstr "Visa inte någon information eller förlopp"
 
 #. TRANSLATORS: tool that gets called when the command is not found
-#: ../contrib/debuginfo-install/pk-debuginfo-install.c:528
+#: ../contrib/debuginfo-install/pk-debuginfo-install.c:542
 msgid "PackageKit Debuginfo Installer"
 msgstr "PackageKit -Installation av debuginfo"
 
 #. TRANSLATORS: the use needs to specify a list of package names on the command line
-#: ../contrib/debuginfo-install/pk-debuginfo-install.c:540
+#: ../contrib/debuginfo-install/pk-debuginfo-install.c:556
 #, c-format
 msgid "ERROR: Specify package names to install."
 msgstr "FEL: Ange paketnamn att installera."
 
 #. TRANSLATORS: we are getting the list of repositories
-#: ../contrib/debuginfo-install/pk-debuginfo-install.c:572
+#: ../contrib/debuginfo-install/pk-debuginfo-install.c:592
 #, c-format
 msgid "Getting sources list"
 msgstr "Hämtar lista över källor"
 
 #. TRANSLATORS: operation was not successful
-#: ../contrib/debuginfo-install/pk-debuginfo-install.c:582
-#: ../contrib/debuginfo-install/pk-debuginfo-install.c:657
-#: ../contrib/debuginfo-install/pk-debuginfo-install.c:741
-#: ../contrib/debuginfo-install/pk-debuginfo-install.c:785
-#: ../contrib/debuginfo-install/pk-debuginfo-install.c:852
-#: ../contrib/debuginfo-install/pk-debuginfo-install.c:896
+#: ../contrib/debuginfo-install/pk-debuginfo-install.c:602
+#: ../contrib/debuginfo-install/pk-debuginfo-install.c:677
+#: ../contrib/debuginfo-install/pk-debuginfo-install.c:761
+#: ../contrib/debuginfo-install/pk-debuginfo-install.c:805
+#: ../contrib/debuginfo-install/pk-debuginfo-install.c:872
+#: ../contrib/debuginfo-install/pk-debuginfo-install.c:916
 msgid "FAILED."
 msgstr "MISSLYCKADES."
 
 #. TRANSLATORS: all completed 100%
-#: ../contrib/debuginfo-install/pk-debuginfo-install.c:597
-#: ../contrib/debuginfo-install/pk-debuginfo-install.c:637
-#: ../contrib/debuginfo-install/pk-debuginfo-install.c:672
-#: ../contrib/debuginfo-install/pk-debuginfo-install.c:756
-#: ../contrib/debuginfo-install/pk-debuginfo-install.c:800
-#: ../contrib/debuginfo-install/pk-debuginfo-install.c:867
-#: ../contrib/debuginfo-install/pk-debuginfo-install.c:911
+#: ../contrib/debuginfo-install/pk-debuginfo-install.c:617
+#: ../contrib/debuginfo-install/pk-debuginfo-install.c:657
+#: ../contrib/debuginfo-install/pk-debuginfo-install.c:692
+#: ../contrib/debuginfo-install/pk-debuginfo-install.c:776
+#: ../contrib/debuginfo-install/pk-debuginfo-install.c:820
+#: ../contrib/debuginfo-install/pk-debuginfo-install.c:887
+#: ../contrib/debuginfo-install/pk-debuginfo-install.c:931
 #, c-format
 msgid "OK."
 msgstr "OK."
 
 #. TRANSLATORS: tell the user what we found
-#: ../contrib/debuginfo-install/pk-debuginfo-install.c:600
+#: ../contrib/debuginfo-install/pk-debuginfo-install.c:620
 #, c-format
 msgid "Found %i enabled and %i disabled sources."
 msgstr "Hittade %i aktiverade och %i inaktiverade källor."
 
 #. TRANSLATORS: we're finding repositories that match out pattern
-#: ../contrib/debuginfo-install/pk-debuginfo-install.c:607
+#: ../contrib/debuginfo-install/pk-debuginfo-install.c:627
 #, c-format
 msgid "Finding debugging sources"
 msgstr "Söker efter källor för felsökning"
 
 #. TRANSLATORS: tell the user what we found
-#: ../contrib/debuginfo-install/pk-debuginfo-install.c:640
+#: ../contrib/debuginfo-install/pk-debuginfo-install.c:660
 #, c-format
 msgid "Found %i disabled debuginfo repos."
 msgstr "Hittade %i inaktiverade debuginfo-förråd."
 
 #. TRANSLATORS: we're now enabling all the debug sources we found
-#: ../contrib/debuginfo-install/pk-debuginfo-install.c:647
+#: ../contrib/debuginfo-install/pk-debuginfo-install.c:667
 #, c-format
 msgid "Enabling debugging sources"
 msgstr "Aktiverar källor för felsökning"
 
 #. TRANSLATORS: tell the user how many we enabled
-#: ../contrib/debuginfo-install/pk-debuginfo-install.c:675
+#: ../contrib/debuginfo-install/pk-debuginfo-install.c:695
 #, c-format
 msgid "Enabled %i debugging sources."
 msgstr "Aktiverade %i källor för felsökning."
 
 #. TRANSLATORS: we're now finding packages that match in all the repos
-#: ../contrib/debuginfo-install/pk-debuginfo-install.c:682
+#: ../contrib/debuginfo-install/pk-debuginfo-install.c:702
 #, c-format
 msgid "Finding debugging packages"
 msgstr "Söker efter paket för felsökning"
 
 #. TRANSLATORS: we couldn't find the package name, non-fatal
-#: ../contrib/debuginfo-install/pk-debuginfo-install.c:694
+#: ../contrib/debuginfo-install/pk-debuginfo-install.c:714
 #, c-format
 msgid "Failed to find the package %s: %s"
 msgstr "Misslyckades med att hitta paketet %s: %s"
 
 #. TRANSLATORS: we couldn't find the debuginfo package name, non-fatal
-#: ../contrib/debuginfo-install/pk-debuginfo-install.c:717
+#: ../contrib/debuginfo-install/pk-debuginfo-install.c:737
 #, c-format
 msgid "Failed to find the debuginfo package %s: %s"
 msgstr "Misslyckades med att hitta debuginfo-paketet %s: %s"
 
 #. TRANSLATORS: no debuginfo packages could be found to be installed
-#: ../contrib/debuginfo-install/pk-debuginfo-install.c:745
+#: ../contrib/debuginfo-install/pk-debuginfo-install.c:765
 #, c-format
 msgid "Found no packages to install."
 msgstr "Hittade inga paket att installera."
 
 #. TRANSLATORS: tell the user we found some packages, and then list them
-#: ../contrib/debuginfo-install/pk-debuginfo-install.c:759
+#: ../contrib/debuginfo-install/pk-debuginfo-install.c:779
 #, c-format
 msgid "Found %i packages:"
 msgstr "Hittade %i paket:"
 
 #. TRANSLATORS: tell the user we are searching for deps
-#: ../contrib/debuginfo-install/pk-debuginfo-install.c:775
+#: ../contrib/debuginfo-install/pk-debuginfo-install.c:795
 #, c-format
 msgid "Finding packages that depend on these packages"
 msgstr "Söker efter paket som är beroende av dessa paket"
 
 #. TRANSLATORS: could not install, detailed error follows
-#: ../contrib/debuginfo-install/pk-debuginfo-install.c:788
+#: ../contrib/debuginfo-install/pk-debuginfo-install.c:808
 #, c-format
 msgid "Could not find dependant packages: %s"
 msgstr "Kunde inte hitta paket som är beroende: %s"
 
 #. TRANSLATORS: tell the user we found some more packages
-#: ../contrib/debuginfo-install/pk-debuginfo-install.c:804
+#: ../contrib/debuginfo-install/pk-debuginfo-install.c:824
 #, c-format
 msgid "Found %i extra packages."
 msgstr "Hittade %i extra paket."
 
 #. TRANSLATORS: tell the user we found some more packages
-#: ../contrib/debuginfo-install/pk-debuginfo-install.c:808
+#: ../contrib/debuginfo-install/pk-debuginfo-install.c:828
 #, c-format
 msgid "No extra packages required."
 msgstr "Inga extra paket krävs."
 
 #. TRANSLATORS: tell the user we found some packages (and deps), and then list them
-#: ../contrib/debuginfo-install/pk-debuginfo-install.c:817
+#: ../contrib/debuginfo-install/pk-debuginfo-install.c:837
 #, c-format
 msgid "Found %i packages to install:"
 msgstr "Hittade %i paket att installera:"
 
 #. TRANSLATORS: simulate mode is a testing mode where we quit before the action
-#: ../contrib/debuginfo-install/pk-debuginfo-install.c:830
+#: ../contrib/debuginfo-install/pk-debuginfo-install.c:850
 #, c-format
 msgid "Not installing packages in simulate mode"
 msgstr "Installerar inte paket i simuleringsläget"
 
 #. TRANSLATORS: we are now installing the debuginfo packages we found earlier
 #. TRANSLATORS: transaction state, installing packages
-#: ../contrib/debuginfo-install/pk-debuginfo-install.c:842
-#: ../lib/packagekit-glib2/pk-console-shared.c:270
+#: ../contrib/debuginfo-install/pk-debuginfo-install.c:862
+#: ../lib/packagekit-glib2/pk-console-shared.c:282
 #, c-format
 msgid "Installing packages"
 msgstr "Installerar paket"
 
 #. TRANSLATORS: could not install, detailed error follows
-#: ../contrib/debuginfo-install/pk-debuginfo-install.c:855
+#: ../contrib/debuginfo-install/pk-debuginfo-install.c:875
 #, c-format
 msgid "Could not install packages: %s"
 msgstr "Kunde inte installera paket: %s"
 
 #. TRANSLATORS: we are now disabling all debuginfo repos we previously enabled
-#: ../contrib/debuginfo-install/pk-debuginfo-install.c:887
+#: ../contrib/debuginfo-install/pk-debuginfo-install.c:907
 #, c-format
 msgid "Disabling sources previously enabled"
 msgstr "Inaktiverar källor som tidigare var aktiverade"
 
 #. TRANSLATORS: no debuginfo packages could be found to be installed, detailed error follows
-#: ../contrib/debuginfo-install/pk-debuginfo-install.c:899
+#: ../contrib/debuginfo-install/pk-debuginfo-install.c:919
 #, c-format
 msgid "Could not disable the debugging sources: %s"
 msgstr "Kunde inte inaktivera källorna för felsökning: %s"
 
 #. TRANSLATORS: we disabled all the debugging repos that we enabled before
-#: ../contrib/debuginfo-install/pk-debuginfo-install.c:914
+#: ../contrib/debuginfo-install/pk-debuginfo-install.c:934
 #, c-format
 msgid "Disabled %i debugging sources."
 msgstr "Inaktiverade %i källor för felsökning."
 
 #. TRANSLATORS: couldn't open device to write
-#: ../contrib/device-rebind/pk-device-rebind.c:61
+#: ../contrib/device-rebind/pk-device-rebind.c:62
 msgid "Failed to open file"
 msgstr "Misslyckades med att öppna filen"
 
 #. TRANSLATORS: could not write to the device
-#: ../contrib/device-rebind/pk-device-rebind.c:70
+#: ../contrib/device-rebind/pk-device-rebind.c:71
 msgid "Failed to write to the file"
 msgstr "Misslyckades med att skriva till filen"
 
 #. TRANSLATORS: we failed to release the current driver
-#: ../contrib/device-rebind/pk-device-rebind.c:110
-#: ../contrib/device-rebind/pk-device-rebind.c:147
+#: ../contrib/device-rebind/pk-device-rebind.c:111
+#: ../contrib/device-rebind/pk-device-rebind.c:148
 msgid "Failed to write to device"
 msgstr "Misslyckades med att skriva till enheten"
 
 #. TRANSLATORS: the device could not be found in sysfs
-#: ../contrib/device-rebind/pk-device-rebind.c:175
+#: ../contrib/device-rebind/pk-device-rebind.c:176
 msgid "Device could not be found"
 msgstr "Enheten kunde inte hittas"
 
 #. TRANSLATORS: we failed to release the current driver
-#: ../contrib/device-rebind/pk-device-rebind.c:202
+#: ../contrib/device-rebind/pk-device-rebind.c:203
 msgid "Failed to unregister driver"
 msgstr "Misslyckades med att avregistrera drivrutinen"
 
 #. TRANSLATORS: we failed to bind the old driver
-#: ../contrib/device-rebind/pk-device-rebind.c:211
+#: ../contrib/device-rebind/pk-device-rebind.c:212
 msgid "Failed to register driver"
 msgstr "Misslyckades med att registrera drivrutinen"
 
 #. TRANSLATORS: user did not specify a device sysfs path that exists
-#: ../contrib/device-rebind/pk-device-rebind.c:260
+#: ../contrib/device-rebind/pk-device-rebind.c:261
 msgid "Device path not found"
 msgstr "Enhetssökvägen hittades inte"
 
 #. TRANSLATORS: user did not specify a valid device sysfs path
-#: ../contrib/device-rebind/pk-device-rebind.c:268
+#: ../contrib/device-rebind/pk-device-rebind.c:269
 msgid "Incorrect device path specified"
 msgstr "Felaktig enhetssökväg angiven"
 
+#: ../contrib/device-rebind/pk-device-rebind.c:294
+msgid "Show extra debugging information"
+msgstr "Visa extra felsökningsinformation"
+
 #. command line argument, simulate what would be done, but don't actually do it
-#: ../contrib/device-rebind/pk-device-rebind.c:296
+#: ../contrib/device-rebind/pk-device-rebind.c:297
 msgid "Don't actually touch the hardware, only simulate what would be done"
 msgstr "Rör inte hårdvaran, simulera endast vad som ska göras"
 
 #. TRANSLATORS: command line option: a list of files to install
-#: ../contrib/device-rebind/pk-device-rebind.c:299
+#: ../contrib/device-rebind/pk-device-rebind.c:300
 msgid "Device paths"
 msgstr "Enhetssökvägar"
 
 #. TRANSLATORS: tool that gets called when the device needs reloading after installing firmware
-#: ../contrib/device-rebind/pk-device-rebind.c:314
+#: ../contrib/device-rebind/pk-device-rebind.c:315
 msgid "PackageKit Device Reloader"
 msgstr "Enhetsuppdaterare för PackageKit"
 
 #. TRANSLATORS: user did not specify a valid device sysfs path
-#: ../contrib/device-rebind/pk-device-rebind.c:322
+#: ../contrib/device-rebind/pk-device-rebind.c:323
 msgid "You need to specify at least one valid device path"
 msgstr "Du måste ange minst en giltig enhetssökväg"
 
 #. TRANSLATORS: user did not specify a valid device sysfs path
-#: ../contrib/device-rebind/pk-device-rebind.c:332
+#: ../contrib/device-rebind/pk-device-rebind.c:333
 msgid "This script can only be used by the root user"
 msgstr "Detta skript kan endast användas av root-användaren"
 
 #. TRANSLATORS: we're going to verify the path first
-#: ../contrib/device-rebind/pk-device-rebind.c:341
+#: ../contrib/device-rebind/pk-device-rebind.c:342
 msgid "Verifying device path"
 msgstr "Verifierar enhetssökvägen"
 
 #. TRANSLATORS: user did not specify a device sysfs path that exists
-#: ../contrib/device-rebind/pk-device-rebind.c:346
+#: ../contrib/device-rebind/pk-device-rebind.c:347
 msgid "Failed to verify device path"
 msgstr "Misslyckades med att verifiera enhetssökvägen"
 
 #. TRANSLATORS: we're going to try
-#: ../contrib/device-rebind/pk-device-rebind.c:360
+#: ../contrib/device-rebind/pk-device-rebind.c:361
 msgid "Attempting to rebind device"
 msgstr "Försöker att binda om enheten"
 
 #. TRANSLATORS: we failed to release the current driver
-#: ../contrib/device-rebind/pk-device-rebind.c:365
+#: ../contrib/device-rebind/pk-device-rebind.c:366
 msgid "Failed to rebind device"
 msgstr "Misslyckades med att binda om enheten"
 
@@ -1043,599 +1083,604 @@ msgstr "Paketlista för PackageKit"
 msgid "PackageKit Service Pack"
 msgstr "Servicepaket för PackageKit"
 
-#: ../lib/packagekit-glib2/pk-console-shared.c:55
+#: ../lib/packagekit-glib2/pk-console-shared.c:59
 #, c-format
 msgid "Please enter a number from 1 to %i: "
 msgstr "Ange ett tal från 1 till %i: "
 
 #. TRANSLATORS: more than one package could be found that matched, to follow is a list of possible packages
-#: ../lib/packagekit-glib2/pk-console-shared.c:177
+#: ../lib/packagekit-glib2/pk-console-shared.c:183
 msgid "More than one package matches:"
 msgstr "Det finns fler än ett paket som matchar:"
 
 #. TRANSLATORS: This finds out which package in the list to use
-#: ../lib/packagekit-glib2/pk-console-shared.c:186
+#: ../lib/packagekit-glib2/pk-console-shared.c:196
 msgid "Please choose the correct package: "
 msgstr "Välj det korrekta paketet: "
 
 #. TRANSLATORS: This is when the transaction status is not known
-#: ../lib/packagekit-glib2/pk-console-shared.c:238
+#: ../lib/packagekit-glib2/pk-console-shared.c:250
 msgid "Unknown state"
 msgstr "Okänt tillstånd"
 
 #. TRANSLATORS: transaction state, the daemon is in the process of starting
-#: ../lib/packagekit-glib2/pk-console-shared.c:242
+#: ../lib/packagekit-glib2/pk-console-shared.c:254
 msgid "Starting"
 msgstr "Startar"
 
 #. TRANSLATORS: transaction state, the transaction is waiting for another to complete
-#: ../lib/packagekit-glib2/pk-console-shared.c:246
+#: ../lib/packagekit-glib2/pk-console-shared.c:258
 msgid "Waiting in queue"
 msgstr "Väntar i kö"
 
 #. TRANSLATORS: transaction state, just started
-#: ../lib/packagekit-glib2/pk-console-shared.c:250
+#: ../lib/packagekit-glib2/pk-console-shared.c:262
 msgid "Running"
 msgstr "Kör"
 
 #. TRANSLATORS: transaction state, is querying data
-#: ../lib/packagekit-glib2/pk-console-shared.c:254
+#: ../lib/packagekit-glib2/pk-console-shared.c:266
 msgid "Querying"
 msgstr "Frågar"
 
 #. TRANSLATORS: transaction state, getting data from a server
-#: ../lib/packagekit-glib2/pk-console-shared.c:258
+#: ../lib/packagekit-glib2/pk-console-shared.c:270
 msgid "Getting information"
 msgstr "Hämtar information"
 
 #. TRANSLATORS: transaction state, removing packages
-#: ../lib/packagekit-glib2/pk-console-shared.c:262
+#: ../lib/packagekit-glib2/pk-console-shared.c:274
 msgid "Removing packages"
 msgstr "Tar bort paket"
 
 #. TRANSLATORS: transaction state, downloading package files
 #. TRANSLATORS: The role of the transaction, in present tense
-#: ../lib/packagekit-glib2/pk-console-shared.c:266
-#: ../lib/packagekit-glib2/pk-console-shared.c:640
+#: ../lib/packagekit-glib2/pk-console-shared.c:278
+#: ../lib/packagekit-glib2/pk-console-shared.c:656
 msgid "Downloading packages"
 msgstr "Hämtar paket"
 
 #. TRANSLATORS: transaction state, refreshing internal lists
-#: ../lib/packagekit-glib2/pk-console-shared.c:274
+#: ../lib/packagekit-glib2/pk-console-shared.c:286
 msgid "Refreshing software list"
 msgstr "Uppdaterar programlista"
 
 #. TRANSLATORS: transaction state, installing updates
-#: ../lib/packagekit-glib2/pk-console-shared.c:278
+#: ../lib/packagekit-glib2/pk-console-shared.c:290
 msgid "Installing updates"
 msgstr "Installerar uppdateringar"
 
 #. TRANSLATORS: transaction state, removing old packages, and cleaning config files
-#: ../lib/packagekit-glib2/pk-console-shared.c:282
+#: ../lib/packagekit-glib2/pk-console-shared.c:294
 msgid "Cleaning up packages"
 msgstr "Rensar upp paket"
 
 #. TRANSLATORS: transaction state, obsoleting old packages
-#: ../lib/packagekit-glib2/pk-console-shared.c:286
+#: ../lib/packagekit-glib2/pk-console-shared.c:298
 msgid "Obsoleting packages"
 msgstr "Föråldrar paket"
 
 #. TRANSLATORS: transaction state, checking the transaction before we do it
-#: ../lib/packagekit-glib2/pk-console-shared.c:290
+#: ../lib/packagekit-glib2/pk-console-shared.c:302
 msgid "Resolving dependencies"
 msgstr "Löser beroenden"
 
 #. TRANSLATORS: transaction state, checking if we have all the security keys for the operation
-#: ../lib/packagekit-glib2/pk-console-shared.c:294
+#: ../lib/packagekit-glib2/pk-console-shared.c:306
 msgid "Checking signatures"
 msgstr "Kontrollerar signaturer"
 
 #. TRANSLATORS: transaction state, when we return to a previous system state
 #. TRANSLATORS: The role of the transaction, in present tense
-#: ../lib/packagekit-glib2/pk-console-shared.c:298
-#: ../lib/packagekit-glib2/pk-console-shared.c:600
+#: ../lib/packagekit-glib2/pk-console-shared.c:310
+#: ../lib/packagekit-glib2/pk-console-shared.c:616
 msgid "Rolling back"
 msgstr "Rullar tillbaka"
 
 #. TRANSLATORS: transaction state, when we're doing a test transaction
-#: ../lib/packagekit-glib2/pk-console-shared.c:302
+#: ../lib/packagekit-glib2/pk-console-shared.c:314
 msgid "Testing changes"
 msgstr "Testar ändringar"
 
 #. TRANSLATORS: transaction state, when we're writing to the system package database
-#: ../lib/packagekit-glib2/pk-console-shared.c:306
+#: ../lib/packagekit-glib2/pk-console-shared.c:318
 msgid "Committing changes"
 msgstr "Verkställer ändringar"
 
 #. TRANSLATORS: transaction state, requesting data from a server
-#: ../lib/packagekit-glib2/pk-console-shared.c:310
+#: ../lib/packagekit-glib2/pk-console-shared.c:322
 msgid "Requesting data"
 msgstr "Begär data"
 
 #. TRANSLATORS: transaction state, all done!
-#: ../lib/packagekit-glib2/pk-console-shared.c:314
+#: ../lib/packagekit-glib2/pk-console-shared.c:326
 msgid "Finished"
 msgstr "Färdigställd"
 
 #. TRANSLATORS: transaction state, in the process of cancelling
-#: ../lib/packagekit-glib2/pk-console-shared.c:318
+#: ../lib/packagekit-glib2/pk-console-shared.c:330
 msgid "Cancelling"
 msgstr "Avbryter"
 
 #. TRANSLATORS: transaction state, downloading metadata
-#: ../lib/packagekit-glib2/pk-console-shared.c:322
+#: ../lib/packagekit-glib2/pk-console-shared.c:334
 msgid "Downloading repository information"
 msgstr "Hämtar förrådsinformation"
 
 #. TRANSLATORS: transaction state, downloading metadata
-#: ../lib/packagekit-glib2/pk-console-shared.c:326
+#: ../lib/packagekit-glib2/pk-console-shared.c:338
 msgid "Downloading list of packages"
 msgstr "Hämtar lista över paket"
 
 #. TRANSLATORS: transaction state, downloading metadata
-#: ../lib/packagekit-glib2/pk-console-shared.c:330
+#: ../lib/packagekit-glib2/pk-console-shared.c:342
 msgid "Downloading file lists"
 msgstr "Hämtar fillistor"
 
 #. TRANSLATORS: transaction state, downloading metadata
-#: ../lib/packagekit-glib2/pk-console-shared.c:334
+#: ../lib/packagekit-glib2/pk-console-shared.c:346
 msgid "Downloading lists of changes"
 msgstr "Hämtar listor över ändringar"
 
 #. TRANSLATORS: transaction state, downloading metadata
-#: ../lib/packagekit-glib2/pk-console-shared.c:338
+#: ../lib/packagekit-glib2/pk-console-shared.c:350
 msgid "Downloading groups"
 msgstr "Hämtar grupper"
 
 #. TRANSLATORS: transaction state, downloading metadata
-#: ../lib/packagekit-glib2/pk-console-shared.c:342
+#: ../lib/packagekit-glib2/pk-console-shared.c:354
 msgid "Downloading update information"
 msgstr "Hämtar uppdateringsinformation"
 
 #. TRANSLATORS: transaction state, repackaging delta files
-#: ../lib/packagekit-glib2/pk-console-shared.c:346
+#: ../lib/packagekit-glib2/pk-console-shared.c:358
 msgid "Repackaging files"
 msgstr "Paketerar om filer"
 
 #. TRANSLATORS: transaction state, loading databases
-#: ../lib/packagekit-glib2/pk-console-shared.c:350
+#: ../lib/packagekit-glib2/pk-console-shared.c:362
 msgid "Loading cache"
 msgstr "Läser in cache"
 
 #. TRANSLATORS: transaction state, scanning for running processes
-#: ../lib/packagekit-glib2/pk-console-shared.c:354
+#: ../lib/packagekit-glib2/pk-console-shared.c:366
 msgid "Scanning applications"
 msgstr "Söker igenom program"
 
 #. TRANSLATORS: transaction state, generating a list of packages installed on the system
-#: ../lib/packagekit-glib2/pk-console-shared.c:358
+#: ../lib/packagekit-glib2/pk-console-shared.c:370
 msgid "Generating package lists"
 msgstr "Genererar paketlistor"
 
 #. TRANSLATORS: transaction state, when we're waiting for the native tools to exit
-#: ../lib/packagekit-glib2/pk-console-shared.c:362
+#: ../lib/packagekit-glib2/pk-console-shared.c:374
 msgid "Waiting for package manager lock"
 msgstr "Väntar på låset för pakethanteraren"
 
-#. TRANSLATORS: waiting for user to type in a password
-#: ../lib/packagekit-glib2/pk-console-shared.c:366
+#. TRANSLATORS: transaction state, waiting for user to type in a password
+#: ../lib/packagekit-glib2/pk-console-shared.c:378
 msgid "Waiting for authentication"
 msgstr "Väntar på autentisering"
 
-#. TRANSLATORS: we are updating the list of processes
-#: ../lib/packagekit-glib2/pk-console-shared.c:370
+#. TRANSLATORS: transaction state, we are updating the list of processes
+#: ../lib/packagekit-glib2/pk-console-shared.c:382
 msgid "Updating running applications"
 msgstr "Uppdaterar körande program"
 
-#. TRANSLATORS: we are checking executable files currently in use
-#: ../lib/packagekit-glib2/pk-console-shared.c:374
+#. TRANSLATORS: transaction state, we are checking executable files currently in use
+#: ../lib/packagekit-glib2/pk-console-shared.c:386
 msgid "Checking applications in use"
 msgstr "Kontrollerar använda program"
 
-#. TRANSLATORS: we are checking for libraries currently in use
-#: ../lib/packagekit-glib2/pk-console-shared.c:378
+#. TRANSLATORS: transaction state, we are checking for libraries currently in use
+#: ../lib/packagekit-glib2/pk-console-shared.c:390
 msgid "Checking libraries in use"
 msgstr "Kontrollerar använda bibliotek"
 
+#. TRANSLATORS: transaction state, we are copying package files before or after the transaction
+#: ../lib/packagekit-glib2/pk-console-shared.c:394
+msgid "Copying files"
+msgstr "Kopierar filer"
+
 #. TRANSLATORS: The type of update
-#: ../lib/packagekit-glib2/pk-console-shared.c:396
+#: ../lib/packagekit-glib2/pk-console-shared.c:412
 msgid "Trivial"
 msgstr "Enkel"
 
 #. TRANSLATORS: The type of update
-#: ../lib/packagekit-glib2/pk-console-shared.c:400
+#: ../lib/packagekit-glib2/pk-console-shared.c:416
 msgid "Normal"
 msgstr "Normal"
 
 #. TRANSLATORS: The type of update
-#: ../lib/packagekit-glib2/pk-console-shared.c:404
+#: ../lib/packagekit-glib2/pk-console-shared.c:420
 msgid "Important"
 msgstr "Viktig"
 
 #. TRANSLATORS: The type of update
-#: ../lib/packagekit-glib2/pk-console-shared.c:408
+#: ../lib/packagekit-glib2/pk-console-shared.c:424
 msgid "Security"
 msgstr "Säkerhet"
 
 #. TRANSLATORS: The type of update
-#: ../lib/packagekit-glib2/pk-console-shared.c:412
+#: ../lib/packagekit-glib2/pk-console-shared.c:428
 msgid "Bug fix "
 msgstr "Felrättning"
 
 #. TRANSLATORS: The type of update
-#: ../lib/packagekit-glib2/pk-console-shared.c:416
+#: ../lib/packagekit-glib2/pk-console-shared.c:432
 msgid "Enhancement"
 msgstr "Förbättring"
 
 #. TRANSLATORS: The type of update
-#: ../lib/packagekit-glib2/pk-console-shared.c:420
+#: ../lib/packagekit-glib2/pk-console-shared.c:436
 msgid "Blocked"
 msgstr "Blockerad"
 
 #. TRANSLATORS: The state of a package
 #. TRANSLATORS: The action of the package, in past tense
-#: ../lib/packagekit-glib2/pk-console-shared.c:425
-#: ../lib/packagekit-glib2/pk-console-shared.c:498
+#: ../lib/packagekit-glib2/pk-console-shared.c:441
+#: ../lib/packagekit-glib2/pk-console-shared.c:514
 msgid "Installed"
 msgstr "Installerade"
 
 #. TRANSLATORS: The state of a package, i.e. not installed
-#: ../lib/packagekit-glib2/pk-console-shared.c:430
+#: ../lib/packagekit-glib2/pk-console-shared.c:446
 msgid "Available"
 msgstr "Tillgänglig"
 
 #. TRANSLATORS: The action of the package, in present tense
-#: ../lib/packagekit-glib2/pk-console-shared.c:448
+#: ../lib/packagekit-glib2/pk-console-shared.c:464
 msgid "Downloading"
 msgstr "Hämtar"
 
 #. TRANSLATORS: The action of the package, in present tense
-#: ../lib/packagekit-glib2/pk-console-shared.c:452
+#: ../lib/packagekit-glib2/pk-console-shared.c:468
 msgid "Updating"
 msgstr "Uppdaterade"
 
 #. TRANSLATORS: The action of the package, in present tense
 #. TRANSLATORS: The role of the transaction, in present tense
-#: ../lib/packagekit-glib2/pk-console-shared.c:456
-#: ../lib/packagekit-glib2/pk-console-shared.c:576
+#: ../lib/packagekit-glib2/pk-console-shared.c:472
+#: ../lib/packagekit-glib2/pk-console-shared.c:592
 msgid "Installing"
 msgstr "Installerade"
 
 #. TRANSLATORS: The action of the package, in present tense
 #. TRANSLATORS: The role of the transaction, in present tense
-#: ../lib/packagekit-glib2/pk-console-shared.c:460
-#: ../lib/packagekit-glib2/pk-console-shared.c:572
+#: ../lib/packagekit-glib2/pk-console-shared.c:476
+#: ../lib/packagekit-glib2/pk-console-shared.c:588
 msgid "Removing"
 msgstr "Tar bort"
 
 #. TRANSLATORS: The action of the package, in present tense
-#: ../lib/packagekit-glib2/pk-console-shared.c:464
+#: ../lib/packagekit-glib2/pk-console-shared.c:480
 msgid "Cleaning up"
 msgstr "Rensar upp"
 
 #. TRANSLATORS: The action of the package, in present tense
-#: ../lib/packagekit-glib2/pk-console-shared.c:468
+#: ../lib/packagekit-glib2/pk-console-shared.c:484
 msgid "Obsoleting"
 msgstr "Föråldrade"
 
 #. TRANSLATORS: The action of the package, in present tense
-#: ../lib/packagekit-glib2/pk-console-shared.c:472
+#: ../lib/packagekit-glib2/pk-console-shared.c:488
 msgid "Reinstalling"
 msgstr "Installerade om"
 
 #. TRANSLATORS: The action of the package, in past tense
-#: ../lib/packagekit-glib2/pk-console-shared.c:490
+#: ../lib/packagekit-glib2/pk-console-shared.c:506
 msgid "Downloaded"
 msgstr "Hämtade"
 
 #. TRANSLATORS: The action of the package, in past tense
-#: ../lib/packagekit-glib2/pk-console-shared.c:502
+#: ../lib/packagekit-glib2/pk-console-shared.c:518
 msgid "Removed"
 msgstr "Borttagen"
 
 #. TRANSLATORS: The action of the package, in past tense
-#: ../lib/packagekit-glib2/pk-console-shared.c:506
+#: ../lib/packagekit-glib2/pk-console-shared.c:522
 msgid "Cleaned up"
 msgstr "Upprensad"
 
 #. TRANSLATORS: The action of the package, in past tense
-#: ../lib/packagekit-glib2/pk-console-shared.c:510
+#: ../lib/packagekit-glib2/pk-console-shared.c:526
 msgid "Obsoleted"
 msgstr "Föråldrade"
 
 #. TRANSLATORS: The action of the package, in past tense
-#: ../lib/packagekit-glib2/pk-console-shared.c:514
+#: ../lib/packagekit-glib2/pk-console-shared.c:530
 msgid "Reinstalled"
 msgstr "Installerade om"
 
 #. TRANSLATORS: The role of the transaction, in present tense
-#: ../lib/packagekit-glib2/pk-console-shared.c:532
+#: ../lib/packagekit-glib2/pk-console-shared.c:548
 msgid "Unknown role type"
 msgstr "Okänd rolltyp"
 
 #. TRANSLATORS: The role of the transaction, in present tense
-#: ../lib/packagekit-glib2/pk-console-shared.c:536
+#: ../lib/packagekit-glib2/pk-console-shared.c:552
 msgid "Getting dependencies"
 msgstr "Hämtar beroenden"
 
 #. TRANSLATORS: The role of the transaction, in present tense
-#: ../lib/packagekit-glib2/pk-console-shared.c:540
+#: ../lib/packagekit-glib2/pk-console-shared.c:556
 msgid "Getting update details"
 msgstr "Hämtar uppdateringsdetaljer"
 
 #. TRANSLATORS: The role of the transaction, in present tense
-#: ../lib/packagekit-glib2/pk-console-shared.c:544
+#: ../lib/packagekit-glib2/pk-console-shared.c:560
 msgid "Getting details"
 msgstr "Hämtar detaljer"
 
 #. TRANSLATORS: The role of the transaction, in present tense
-#: ../lib/packagekit-glib2/pk-console-shared.c:548
+#: ../lib/packagekit-glib2/pk-console-shared.c:564
 msgid "Getting requires"
 msgstr "Hämtar krav"
 
 #. TRANSLATORS: The role of the transaction, in present tense
-#: ../lib/packagekit-glib2/pk-console-shared.c:552
+#: ../lib/packagekit-glib2/pk-console-shared.c:568
 msgid "Getting updates"
 msgstr "Hämtar uppdateringar"
 
 #. TRANSLATORS: The role of the transaction, in present tense
-#: ../lib/packagekit-glib2/pk-console-shared.c:556
+#: ../lib/packagekit-glib2/pk-console-shared.c:572
 msgid "Searching by details"
 msgstr "Sökning efter detaljer"
 
 #. TRANSLATORS: The role of the transaction, in present tense
-#: ../lib/packagekit-glib2/pk-console-shared.c:560
+#: ../lib/packagekit-glib2/pk-console-shared.c:576
 msgid "Searching by file"
 msgstr "Sökning efter fil"
 
 #. TRANSLATORS: The role of the transaction, in present tense
-#: ../lib/packagekit-glib2/pk-console-shared.c:564
+#: ../lib/packagekit-glib2/pk-console-shared.c:580
 msgid "Searching groups"
 msgstr "Sökning i grupper"
 
 #. TRANSLATORS: The role of the transaction, in present tense
-#: ../lib/packagekit-glib2/pk-console-shared.c:568
+#: ../lib/packagekit-glib2/pk-console-shared.c:584
 msgid "Searching by name"
 msgstr "Sökning efter namn"
 
 #. TRANSLATORS: The role of the transaction, in present tense
-#: ../lib/packagekit-glib2/pk-console-shared.c:580
+#: ../lib/packagekit-glib2/pk-console-shared.c:596
 msgid "Installing files"
 msgstr "Installerade filer"
 
 #. TRANSLATORS: The role of the transaction, in present tense
-#: ../lib/packagekit-glib2/pk-console-shared.c:584
+#: ../lib/packagekit-glib2/pk-console-shared.c:600
 msgid "Refreshing cache"
 msgstr "Uppdatering av cache"
 
 #. TRANSLATORS: The role of the transaction, in present tense
-#: ../lib/packagekit-glib2/pk-console-shared.c:588
+#: ../lib/packagekit-glib2/pk-console-shared.c:604
 msgid "Updating packages"
 msgstr "Uppdaterade paket"
 
 #. TRANSLATORS: The role of the transaction, in present tense
-#: ../lib/packagekit-glib2/pk-console-shared.c:592
+#: ../lib/packagekit-glib2/pk-console-shared.c:608
 msgid "Updating system"
 msgstr "Uppdaterade systemet"
 
 #. TRANSLATORS: The role of the transaction, in present tense
-#: ../lib/packagekit-glib2/pk-console-shared.c:596
+#: ../lib/packagekit-glib2/pk-console-shared.c:612
 msgid "Canceling"
 msgstr "Avbryter"
 
 #. TRANSLATORS: The role of the transaction, in present tense
-#: ../lib/packagekit-glib2/pk-console-shared.c:604
+#: ../lib/packagekit-glib2/pk-console-shared.c:620
 msgid "Getting repositories"
 msgstr "Hämtade förråd"
 
 #. TRANSLATORS: The role of the transaction, in present tense
-#: ../lib/packagekit-glib2/pk-console-shared.c:608
+#: ../lib/packagekit-glib2/pk-console-shared.c:624
 msgid "Enabling repository"
 msgstr "Aktivering av förråd"
 
 #. TRANSLATORS: The role of the transaction, in present tense
-#: ../lib/packagekit-glib2/pk-console-shared.c:612
+#: ../lib/packagekit-glib2/pk-console-shared.c:628
 msgid "Setting data"
 msgstr "Inställning av data"
 
 #. TRANSLATORS: The role of the transaction, in present tense
-#: ../lib/packagekit-glib2/pk-console-shared.c:616
+#: ../lib/packagekit-glib2/pk-console-shared.c:632
 msgid "Resolving"
 msgstr "Löser"
 
 #. TRANSLATORS: The role of the transaction, in present tense
-#: ../lib/packagekit-glib2/pk-console-shared.c:620
+#: ../lib/packagekit-glib2/pk-console-shared.c:636
 msgid "Getting file list"
 msgstr "Hämtning av fillista"
 
 #. TRANSLATORS: The role of the transaction, in present tense
-#: ../lib/packagekit-glib2/pk-console-shared.c:624
+#: ../lib/packagekit-glib2/pk-console-shared.c:640
 msgid "Getting provides"
 msgstr "Hämtning av tillhandahåller"
 
 #. TRANSLATORS: The role of the transaction, in present tense
-#: ../lib/packagekit-glib2/pk-console-shared.c:628
+#: ../lib/packagekit-glib2/pk-console-shared.c:644
 msgid "Installing signature"
 msgstr "Installerade signatur"
 
 #. TRANSLATORS: The role of the transaction, in present tense
-#: ../lib/packagekit-glib2/pk-console-shared.c:632
+#: ../lib/packagekit-glib2/pk-console-shared.c:648
 msgid "Getting packages"
 msgstr "Hämtning av paket"
 
 #. TRANSLATORS: The role of the transaction, in present tense
-#: ../lib/packagekit-glib2/pk-console-shared.c:636
+#: ../lib/packagekit-glib2/pk-console-shared.c:652
 msgid "Accepting EULA"
 msgstr "Accepterade slutanvändaravtal"
 
 #. TRANSLATORS: The role of the transaction, in present tense
-#: ../lib/packagekit-glib2/pk-console-shared.c:644
+#: ../lib/packagekit-glib2/pk-console-shared.c:660
 msgid "Getting upgrades"
 msgstr "Hämtning av uppgraderingar"
 
 #. TRANSLATORS: The role of the transaction, in present tense
-#: ../lib/packagekit-glib2/pk-console-shared.c:648
+#: ../lib/packagekit-glib2/pk-console-shared.c:664
 msgid "Getting categories"
 msgstr "Hämtning av kategorier"
 
 #. TRANSLATORS: The role of the transaction, in present tense
-#: ../lib/packagekit-glib2/pk-console-shared.c:652
+#: ../lib/packagekit-glib2/pk-console-shared.c:668
 msgid "Getting transactions"
 msgstr "Hämtning av transaktioner"
 
 #. TRANSLATORS: The role of the transaction, in present tense
-#: ../lib/packagekit-glib2/pk-console-shared.c:656
-#: ../lib/packagekit-glib2/pk-console-shared.c:660
+#: ../lib/packagekit-glib2/pk-console-shared.c:672
+#: ../lib/packagekit-glib2/pk-console-shared.c:676
 msgid "Simulating install"
 msgstr "Simulerade installation"
 
 #. TRANSLATORS: The role of the transaction, in present tense
-#: ../lib/packagekit-glib2/pk-console-shared.c:664
+#: ../lib/packagekit-glib2/pk-console-shared.c:680
 msgid "Simulating remove"
 msgstr "Simulering av borttagning"
 
 #. TRANSLATORS: The role of the transaction, in present tense
-#: ../lib/packagekit-glib2/pk-console-shared.c:668
+#: ../lib/packagekit-glib2/pk-console-shared.c:684
 msgid "Simulating update"
 msgstr "Simulering av uppdatering"
 
 #. TRANSLATORS: ask the user if they are comfortable installing insecure packages
-#: ../lib/packagekit-glib2/pk-task-text.c:64
+#: ../lib/packagekit-glib2/pk-task-text.c:69
 msgid "Do you want to allow installing of unsigned software?"
 msgstr "Vill du tillåta installation av osignerad programvara?"
 
 #. TRANSLATORS: tell the user we've not done anything
-#: ../lib/packagekit-glib2/pk-task-text.c:69
+#: ../lib/packagekit-glib2/pk-task-text.c:74
 msgid "The unsigned software will not be installed."
 msgstr "Osignerad programvara kommer inte att installeras."
 
 #. TRANSLATORS: the package repository is signed by a key that is not recognised
-#: ../lib/packagekit-glib2/pk-task-text.c:102
+#: ../lib/packagekit-glib2/pk-task-text.c:123
 msgid "Software source signature required"
 msgstr "Signatur för programkälla krävs"
 
 #. TRANSLATORS: the package repository name
-#: ../lib/packagekit-glib2/pk-task-text.c:108
+#: ../lib/packagekit-glib2/pk-task-text.c:129
 msgid "Software source name"
 msgstr "Namn på programkälla"
 
 #. TRANSLATORS: the key URL
-#: ../lib/packagekit-glib2/pk-task-text.c:111
+#: ../lib/packagekit-glib2/pk-task-text.c:132
 msgid "Key URL"
 msgstr "Nyckelns URL"
 
 #. TRANSLATORS: the username of the key
-#: ../lib/packagekit-glib2/pk-task-text.c:114
+#: ../lib/packagekit-glib2/pk-task-text.c:135
 msgid "Key user"
 msgstr "Nyckelns användare"
 
 #. TRANSLATORS: the key ID, usually a few hex digits
-#: ../lib/packagekit-glib2/pk-task-text.c:117
+#: ../lib/packagekit-glib2/pk-task-text.c:138
 msgid "Key ID"
 msgstr "Nyckelns id"
 
 #. TRANSLATORS: the key fingerprint, again, yet more hex
-#: ../lib/packagekit-glib2/pk-task-text.c:120
+#: ../lib/packagekit-glib2/pk-task-text.c:141
 msgid "Key fingerprint"
 msgstr "Nyckelns fingeravtryck"
 
 #. TRANSLATORS: the timestamp (a bit like a machine readable time)
-#: ../lib/packagekit-glib2/pk-task-text.c:123
+#: ../lib/packagekit-glib2/pk-task-text.c:144
 msgid "Key Timestamp"
 msgstr "Nyckelns tidsstämpel"
 
 #. TRANSLATORS: ask the user if they want to import
-#: ../lib/packagekit-glib2/pk-task-text.c:129
+#: ../lib/packagekit-glib2/pk-task-text.c:157
 msgid "Do you accept this signature?"
 msgstr "Godkänner du denna signatur?"
 
 #. TRANSLATORS: tell the user we've not done anything
-#: ../lib/packagekit-glib2/pk-task-text.c:134
+#: ../lib/packagekit-glib2/pk-task-text.c:162
 msgid "The signature was not accepted."
 msgstr "Signaturen godkändes inte."
 
 #. TRANSLATORS: this is another name for a software licence that has to be read before installing
-#: ../lib/packagekit-glib2/pk-task-text.c:169
+#: ../lib/packagekit-glib2/pk-task-text.c:205
 msgid "End user licence agreement required"
 msgstr "Godkännande av slutanvändaravtal krävs"
 
 #. TRANSLATORS: the EULA text itself (long and boring)
-#: ../lib/packagekit-glib2/pk-task-text.c:178
+#: ../lib/packagekit-glib2/pk-task-text.c:214
 msgid "Agreement"
 msgstr "Användarvillkor"
 
 #. TRANSLATORS: ask the user if they've read and accepted the EULA
-#: ../lib/packagekit-glib2/pk-task-text.c:184
+#: ../lib/packagekit-glib2/pk-task-text.c:223
 msgid "Do you accept this agreement?"
 msgstr "Godkänner du dessa användarvillkor?"
 
 #. TRANSLATORS: tell the user we've not done anything
-#: ../lib/packagekit-glib2/pk-task-text.c:189
+#: ../lib/packagekit-glib2/pk-task-text.c:228
 msgid "The agreement was not accepted."
 msgstr "Användarvillkoren godkändes inte."
 
 #. TRANSLATORS: the user needs to change media inserted into the computer
-#: ../lib/packagekit-glib2/pk-task-text.c:219
+#: ../lib/packagekit-glib2/pk-task-text.c:267
 msgid "Media change required"
 msgstr "Mediabyte krävs"
 
 #. TRANSLATORS: the type, e.g. DVD, CD, etc
-#: ../lib/packagekit-glib2/pk-task-text.c:222
+#: ../lib/packagekit-glib2/pk-task-text.c:270
 msgid "Media type"
 msgstr "Mediatyp"
 
 #. TRANSLATORS: the media label, usually like 'disk-1of3'
-#: ../lib/packagekit-glib2/pk-task-text.c:225
+#: ../lib/packagekit-glib2/pk-task-text.c:273
 msgid "Media label"
 msgstr "Mediaetikett"
 
 #. TRANSLATORS: the media description, usually like 'Fedora 12 disk 5'
-#: ../lib/packagekit-glib2/pk-task-text.c:228
+#: ../lib/packagekit-glib2/pk-task-text.c:276
 msgid "Text"
 msgstr "Text"
 
 #. TRANSLATORS: ask the user to insert the media
-#: ../lib/packagekit-glib2/pk-task-text.c:232
+#: ../lib/packagekit-glib2/pk-task-text.c:282
 msgid "Please insert the correct media"
 msgstr "Mata in korrekt media"
 
 #. TRANSLATORS: tell the user we've not done anything as they are lazy
-#: ../lib/packagekit-glib2/pk-task-text.c:237
+#: ../lib/packagekit-glib2/pk-task-text.c:287
 msgid "The correct media was not inserted."
 msgstr "Korrekt media matades inte in."
 
 #. TRANSLATORS: When processing, we might have to remove other dependencies
-#: ../lib/packagekit-glib2/pk-task-text.c:252
+#: ../lib/packagekit-glib2/pk-task-text.c:302
 msgid "The following packages have to be removed:"
 msgstr "Följande paket måste tas bort:"
 
 #. TRANSLATORS: When processing, we might have to install other dependencies
-#: ../lib/packagekit-glib2/pk-task-text.c:257
+#: ../lib/packagekit-glib2/pk-task-text.c:307
 msgid "The following packages have to be installed:"
 msgstr "Följande paket måste installeras:"
 
 #. TRANSLATORS: When processing, we might have to update other dependencies
-#: ../lib/packagekit-glib2/pk-task-text.c:262
+#: ../lib/packagekit-glib2/pk-task-text.c:312
 msgid "The following packages have to be updated:"
 msgstr "Följande paket måste uppdateras:"
 
 #. TRANSLATORS: When processing, we might have to reinstall other dependencies
-#: ../lib/packagekit-glib2/pk-task-text.c:267
+#: ../lib/packagekit-glib2/pk-task-text.c:317
 msgid "The following packages have to be reinstalled:"
 msgstr "Följande paket måste installeras om:"
 
 #. TRANSLATORS: When processing, we might have to downgrade other dependencies
-#: ../lib/packagekit-glib2/pk-task-text.c:272
+#: ../lib/packagekit-glib2/pk-task-text.c:322
 msgid "The following packages have to be downgraded:"
 msgstr "Följande paket måste nedgraderas:"
 
 #. TRANSLATORS: ask the user if the proposed changes are okay
-#: ../lib/packagekit-glib2/pk-task-text.c:331
+#: ../lib/packagekit-glib2/pk-task-text.c:382
 msgid "Proceed with changes?"
 msgstr "Fortsätt med ändringar?"
 
 #. TRANSLATORS: tell the user we didn't do anything
-#: ../lib/packagekit-glib2/pk-task-text.c:336
+#: ../lib/packagekit-glib2/pk-task-text.c:387
 msgid "The transaction did not proceed."
 msgstr "Transaktionen fortsatte inte."
 
@@ -1826,47 +1871,47 @@ msgid "The org.freedesktop.PackageKit.conf file is not installed in the system d
 msgstr "Filen org.freedesktop.PackageKit.conf är inte installerad i systemkatalogen:"
 
 #. TRANSLATORS: a backend is the system package tool, e.g. yum, apt
-#: ../src/pk-main.c:205
+#: ../src/pk-main.c:199
 msgid "Packaging backend to use, e.g. dummy"
 msgstr "Paketingsbakände att använda, t.ex. dummy"
 
 #. TRANSLATORS: if we should run in the background
-#: ../src/pk-main.c:208
+#: ../src/pk-main.c:202
 msgid "Daemonize and detach from the terminal"
 msgstr "Kör som bakgrundsprocess och koppla loss från terminalen"
 
 #. TRANSLATORS: if we should not monitor how long we are inactive for
-#: ../src/pk-main.c:214
+#: ../src/pk-main.c:205
 msgid "Disable the idle timer"
 msgstr "Inaktivera tidsgräns för inaktivitet"
 
 #. TRANSLATORS: show version
-#: ../src/pk-main.c:217
+#: ../src/pk-main.c:208
 msgid "Show version and exit"
 msgstr "Visa version och avsluta"
 
 #. TRANSLATORS: exit after we've started up, used for user profiling
-#: ../src/pk-main.c:220
+#: ../src/pk-main.c:211
 msgid "Exit after a small delay"
 msgstr "Avsluta efter en mindre fördröjning"
 
 #. TRANSLATORS: exit straight away, used for automatic profiling
-#: ../src/pk-main.c:223
+#: ../src/pk-main.c:214
 msgid "Exit after the engine has loaded"
 msgstr "Avsluta efter att motorn har lästs in"
 
 #. TRANSLATORS: describing the service that is running
-#: ../src/pk-main.c:238
+#: ../src/pk-main.c:229
 msgid "PackageKit service"
 msgstr "PackageKit-tjänst"
 
 #. TRANSLATORS: fatal error, dbus is not running
-#: ../src/pk-main.c:275
+#: ../src/pk-main.c:266
 msgid "Cannot connect to the system bus"
 msgstr "Kan inte ansluta till systembussen"
 
 #. TRANSLATORS: cannot register on system bus, unknown reason -- geeky error follows
-#: ../src/pk-main.c:334
+#: ../src/pk-main.c:317
 msgid "Error trying to start:"
 msgstr "Fel vid försök att starta:"
 
@@ -1896,23 +1941,48 @@ msgstr "Installera inte detta paket såvida inte du vet att det är säkert att
 msgid "Do not install these packages unless you are sure it is safe to do so."
 msgstr "Installera inte dessa paket såvida inte du vet att det är säkert att göra så."
 
-#. TRANSLATORS: warn the user that all bets are off
-#: ../src/pk-polkit-action-lookup.c:202
-msgid "Malicious software can damage your computer or cause other harm."
-msgstr "Skadlig programvara kan skada din dator eller orsaka andra problem."
-
 #. TRANSLATORS: too many packages to list each one
-#: ../src/pk-polkit-action-lookup.c:277
+#: ../src/pk-polkit-action-lookup.c:273
 msgid "Many packages"
 msgstr "MÃ¥nga paket"
 
 #. TRANSLATORS: if the transaction is forced to install only trusted packages
-#: ../src/pk-polkit-action-lookup.c:343
+#: ../src/pk-polkit-action-lookup.c:339
 msgid "Only trusted"
 msgstr "Endast pålitliga"
 
-#~ msgid "Percentage"
-#~ msgstr "Procentandel"
+#. TRANSLATORS: turn on all debugging
+#: ../src/egg-debug.c:388
+msgid "Show debugging information for all files"
+msgstr "Visa felsökningsinformation för alla filer"
+
+#. TRANSLATORS: a list of modules to debug
+#: ../src/egg-debug.c:459
+msgid "Debug these specific modules"
+msgstr "Felsök dessa specifika moduler"
+
+#. TRANSLATORS: a list of functions to debug
+#: ../src/egg-debug.c:462
+msgid "Debug these specific functions"
+msgstr "Felsök dessa specifika funktioner"
+
+#. TRANSLATORS: save to a log
+#: ../src/egg-debug.c:465
+msgid "Log debugging data to a file"
+msgstr "Logga felsökningsdata till en fil"
+
+#: ../src/egg-debug.c:469
+msgid "Debugging Options"
+msgstr "Felsökningsflaggor"
+
+#: ../src/egg-debug.c:469
+msgid "Show debugging options"
+msgstr "Visa felsökningsflaggor"
+
+#~ msgid "Transaction failed with no error"
+#~ msgstr "Transaktionen misslyckades utan något fel"
+#~ msgid "Malicious software can damage your computer or cause other harm."
+#~ msgstr "Skadlig programvara kan skada din dator eller orsaka andra problem."
 #~ msgid "Please restart the application as it is being used."
 #~ msgstr "Starta om programmet eftersom det används för tillfället."
 #~ msgid "The package %s is already installed"


More information about the PackageKit-commit mailing list