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

Richard Hughes hughsient at kemper.freedesktop.org
Fri Dec 5 08:31:15 PST 2008


 backends/poldek/pk-backend-poldek.c              |   11 
 backends/yum/yumBackend.py                       |  334 +++++++++++--
 backends/yum/yumComps.py                         |    2 
 client/pk-console.c                              |  132 +++--
 client/pk-tools-common.c                         |   20 
 configure.ac                                     |    9 
 contrib/Makefile.am                              |    4 
 contrib/PackageKit.spec.in                       |   16 
 contrib/command-not-found/.gitignore             |    5 
 contrib/command-not-found/CommandNotFound.conf   |   47 +
 contrib/command-not-found/Makefile.am            |   40 +
 contrib/command-not-found/PackageKit.sh          |   12 
 contrib/command-not-found/egg-debug.c            |    1 
 contrib/command-not-found/egg-debug.h            |    1 
 contrib/command-not-found/egg-string.c           |    1 
 contrib/command-not-found/egg-string.h           |    1 
 contrib/command-not-found/pk-command-not-found.c |  578 +++++++++++++++++++++++
 contrib/command-not-found/pk-tools-common.c      |    1 
 contrib/command-not-found/pk-tools-common.h      |    1 
 docs/html/pk-help.html                           |   15 
 lib/packagekit-glib/pk-enum.c                    |    1 
 lib/packagekit-glib/pk-enum.h                    |    1 
 lib/python/packagekit/pylint.sh                  |    2 
 po/POTFILES.in                                   |    4 
 po/POTFILES.skip                                 |    2 
 tools/add-error-enum.sh                          |    2 
 26 files changed, 1110 insertions(+), 133 deletions(-)

New commits:
commit 9a85bf074a0024cf4639afc300cff1759d3009b0
Author: Richard Hughes <richard at hughsie.com>
Date:   Fri Dec 5 16:05:46 2008 +0000

    trivial: fix make check po

diff --git a/po/POTFILES.in b/po/POTFILES.in
index 4d7e879..7c24197 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -5,9 +5,11 @@ client/pk-console.c
 client/pk-generate-pack.c
 client/pk-monitor.c
 client/pk-tools-common.c
+contrib/command-not-found/pk-command-not-found.c
 contrib/packagekit-plugin/src/contents.cpp
 data/packagekit-catalog.xml.in
-data/packagekit-servicepack.xml.in
 data/packagekit-package-list.xml.in
+data/packagekit-servicepack.xml.in
 policy/org.freedesktop.packagekit.policy.in
 src/pk-main.c
+
diff --git a/po/POTFILES.skip b/po/POTFILES.skip
new file mode 100644
index 0000000..bb8a3b5
--- /dev/null
+++ b/po/POTFILES.skip
@@ -0,0 +1,2 @@
+contrib/command-not-found/pk-tools-common.c
+
commit f05c3e47c7beff6c11aba18bfc7dc34cefa56ee9
Author: Richard Hughes <richard at hughsie.com>
Date:   Fri Dec 5 16:03:45 2008 +0000

    trivial whitespace fixes

diff --git a/client/pk-tools-common.c b/client/pk-tools-common.c
index 282e70b..310a90c 100644
--- a/client/pk-tools-common.c
+++ b/client/pk-tools-common.c
@@ -152,9 +152,8 @@ pk_console_get_number (const gchar *question, guint maxnum)
 		retval = scanf("%u", &answer);
 
 		/* positive */
-		if (retval == 1 && answer > 0 && answer <= maxnum) {
+		if (retval == 1 && answer > 0 && answer <= maxnum)
 			break;
-		}
 		g_print (_("Please enter a number from 1 to %i: "), maxnum);
 	} while (TRUE);
 	return answer;
@@ -170,32 +169,27 @@ pk_console_get_prompt (const gchar *question, gboolean defaultyes)
 
 	/* pretty print */
 	g_print ("%s", question);
-	if (defaultyes) {
+	if (defaultyes)
 		g_print (" [Y/n] ");
-	} else {
+	else
 		g_print (" [N/y] ");
-	}
 
 	do {
 		/* ITS4: ignore, we are copying into the same variable, not a string */
 		answer = (gchar) getchar();
 
 		/* positive */
-		if (answer == 'y' || answer == 'Y') {
+		if (answer == 'y' || answer == 'Y')
 			return TRUE;
-		}
 		/* negative */
-		if (answer == 'n' || answer == 'N') {
+		if (answer == 'n' || answer == 'N')
 			return FALSE;
-		}
 
 		/* default choice */
-		if (answer == '\n' && defaultyes) {
+		if (answer == '\n' && defaultyes)
 			return TRUE;
-		}
-		if (answer == '\n' && defaultyes == FALSE) {
+		if (answer == '\n' && !defaultyes)
 			return FALSE;
-		}
 	} while (TRUE);
 
 	/* keep GCC happy */
commit 1c2867a91a2b3d9019d2e25a9db11b9992ab9478
Author: Richard Hughes <richard at hughsie.com>
Date:   Fri Dec 5 16:03:11 2008 +0000

    feature: use a config file to control the actions we take on command-not-found

diff --git a/contrib/command-not-found/CommandNotFound.conf b/contrib/command-not-found/CommandNotFound.conf
new file mode 100644
index 0000000..46def12
--- /dev/null
+++ b/contrib/command-not-found/CommandNotFound.conf
@@ -0,0 +1,47 @@
+# Admins can modify this file for system-wide defaults
+
+[CommandNotFound]
+
+# This policy controls what to do when a single match is found for a typo.
+# For instance, gnome-power-staatistics is matched to gnome-power-statistics
+#
+# Allowed values are 'ignore', 'run', 'ask' or 'warn'
+#
+# default=warn
+SingleMatch=warn
+
+# This policy controls what to do when multiple matches are found for a typo.
+# For instance, dmesgg is matched to mesg and dmesg
+#
+# Allowed values are 'ignore', 'ask' or 'warn'
+#
+# default=warn
+MultipleMatch=warn
+
+# This policy controls if the tool should search for packages in remote
+# software sources. This may introduce a non-trivial delay if the sources
+# have not been recently refreshed.
+#
+# Allowed values are 'ignore', 'install', 'ask' or 'warn'
+#
+# default=true
+SoftwareSourceSearch=true
+
+# This policy 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
+#
+# Allowed values are 'ignore', 'install', 'ask' or 'warn'
+#
+# default=warn
+SingleInstall=ask
+
+# This policy controls what to do when a more than one possible package
+# is found for a missing command.
+# For instance, make prompts the user to install automake-1.8 or automake-1.10.
+#
+# Allowed values are 'ignore', 'ask' or 'warn'
+#
+# default=warn
+MultipleInstall=warn
+
diff --git a/contrib/command-not-found/Makefile.am b/contrib/command-not-found/Makefile.am
index d8258e7..cf900b7 100644
--- a/contrib/command-not-found/Makefile.am
+++ b/contrib/command-not-found/Makefile.am
@@ -5,6 +5,7 @@ INCLUDES =						\
 	$(GLIB_CFLAGS)					\
 	$(DBUS_CFLAGS)					\
 	-DPACKAGE_LOCALE_DIR=\"$(localedir)\"		\
+	-DSYSCONFDIR=\""$(sysconfdir)"\" 		\
 	-DEGG_LOG_FILE=\""$(PK_LOG_DIR)/PackageKit"\"	\
 	-DEGG_VERBOSE="\"PK_VERBOSE\""			\
 	-DEGG_LOGGING="\"PK_LOGGING\""			\
@@ -18,6 +19,10 @@ libexec_PROGRAMS = pk-command-not-found
 pk_command_not_found_SOURCES =				\
 	egg-debug.c					\
 	egg-debug.h					\
+	egg-string.c					\
+	egg-string.h					\
+	pk-tools-common.c				\
+	pk-tools-common.h				\
 	pk-command-not-found.c				\
 	$(NULL)
 
@@ -30,3 +35,6 @@ pk_command_not_found_LDADD =				\
 bashprofiledir = ${SYSCONFDIR}/profile.d
 dist_bashprofile_DATA = PackageKit.sh
 
+confdir = $(PK_CONF_DIR)
+dist_conf_DATA = CommandNotFound.conf
+
diff --git a/contrib/command-not-found/egg-string.c b/contrib/command-not-found/egg-string.c
new file mode 120000
index 0000000..5f8fce4
--- /dev/null
+++ b/contrib/command-not-found/egg-string.c
@@ -0,0 +1 @@
+../../lib/packagekit-glib/egg-string.c
\ No newline at end of file
diff --git a/contrib/command-not-found/egg-string.h b/contrib/command-not-found/egg-string.h
new file mode 120000
index 0000000..620a81c
--- /dev/null
+++ b/contrib/command-not-found/egg-string.h
@@ -0,0 +1 @@
+../../lib/packagekit-glib/egg-string.h
\ No newline at end of file
diff --git a/contrib/command-not-found/pk-command-not-found.c b/contrib/command-not-found/pk-command-not-found.c
index 172f2f4..a058564 100644
--- a/contrib/command-not-found/pk-command-not-found.c
+++ b/contrib/command-not-found/pk-command-not-found.c
@@ -22,15 +22,371 @@
 #include "config.h"
 
 #include <string.h>
-#include <unistd.h>
-#include <stdlib.h>
-#include <locale.h>
-#include <glib.h>
 #include <glib/gi18n.h>
 #include <dbus/dbus-glib.h>
 #include <packagekit-glib/packagekit.h>
 
 #include "egg-debug.h"
+#include "egg-string.h"
+
+#include "pk-tools-common.h"
+
+typedef enum {
+	PK_CNF_POLICY_RUN,
+	PK_CNF_POLICY_INSTALL,
+	PK_CNF_POLICY_ASK,
+	PK_CNF_POLICY_WARN,
+	PK_CNF_POLICY_UNKNOWN
+} PkCnfPolicy;
+
+typedef struct {
+	PkCnfPolicy	 single_match;
+	PkCnfPolicy	 multiple_match;
+	PkCnfPolicy	 single_install;
+	PkCnfPolicy	 multiple_install;
+	gboolean	 software_source_search;
+} PkCnfPolicyConfig;
+
+/**
+ * pk_cnf_find_alternatives_swizzle:
+ *
+ * Swizzle ordering, e.g. amke -> make
+ **/
+static void
+pk_cnf_find_alternatives_swizzle (const gchar *cmd, guint len, GPtrArray *array)
+{
+	guint i;
+	gchar *possible;
+	gchar swap;
+
+	/*  */
+	for (i=0; i<len-1; i++) {
+		possible = g_strdup (cmd);
+		swap = possible[i];
+		possible[i] = possible[i+1];
+		possible[i+1] = swap;
+		g_ptr_array_add (array, possible);
+	}
+}
+
+/**
+ * pk_cnf_find_alternatives_replace:
+ *
+ * Replace some easily confused chars, e.g. gnome-power-managir to gnome-power-manager
+ **/
+static void
+pk_cnf_find_alternatives_replace (const gchar *cmd, guint len, GPtrArray *array)
+{
+	guint i;
+	gchar *possible;
+	gchar temp;
+
+	/* replace some easily confused chars */
+	for (i=0; i<len; i++) {
+		temp = cmd[i];
+		if (temp == 'i') {
+			possible = g_strdup (cmd);
+			possible[i] = 'e';
+			g_ptr_array_add (array, possible);
+		}
+		if (temp == 'e') {
+			possible = g_strdup (cmd);
+			possible[i] = 'i';
+			g_ptr_array_add (array, possible);
+		}
+		if (temp == 'i') {
+			possible = g_strdup (cmd);
+			possible[i] = 'o';
+			g_ptr_array_add (array, possible);
+		}
+	}
+}
+
+/**
+ * pk_cnf_find_alternatives_truncate:
+ *
+ * Truncate first and last char, so lshall -> lshal
+ **/
+static void
+pk_cnf_find_alternatives_truncate (const gchar *cmd, guint len, GPtrArray *array)
+{
+	guint i;
+	gchar *possible;
+
+	/* truncate last char */
+	possible = g_strdup (cmd);
+	possible[len-1] = '\0';
+	g_ptr_array_add (array, possible);
+
+	/* truncate first char */
+	possible = g_strdup (cmd);
+	for (i=0; i<len-1; i++)
+		possible[i] = possible[i+1];
+	possible[len-1] = '\0';
+	g_ptr_array_add (array, possible);
+}
+
+/**
+ * pk_cnf_find_alternatives_remove_double:
+ *
+ * Remove double chars, e.g. gnome-power-manaager -> gnome-power-manager
+ **/
+static void
+pk_cnf_find_alternatives_remove_double (const gchar *cmd, guint len, GPtrArray *array)
+{
+	guint i, j;
+	gchar *possible;
+
+	for (i=1; i<len; i++) {
+		if (cmd[i-1] == cmd[i]) {
+			possible = g_strdup (cmd);
+			for (j=i; j<len; j++)
+				possible[j] = possible[j+1];
+			possible[len-1] = '\0';
+			g_ptr_array_add (array, possible);
+		}
+	}
+}
+
+/**
+ * pk_cnf_find_alternatives:
+ *
+ * Generate a list of commands it might be
+ **/
+static GPtrArray *
+pk_cnf_find_alternatives (const gchar *cmd, guint len)
+{
+	GPtrArray *array;
+	GPtrArray *possible;
+	GPtrArray *unique;
+	const gchar *cmdt;
+	const gchar *cmdt2;
+	guint i, j;
+	gchar buffer_bin[1024];
+	gchar buffer_sbin[1024];
+	gboolean ret;
+
+	array = g_ptr_array_new ();
+	possible = g_ptr_array_new ();
+	unique = g_ptr_array_new ();
+	pk_cnf_find_alternatives_swizzle (cmd, len, possible);
+	pk_cnf_find_alternatives_replace (cmd, len, possible);
+	if (len > 3)
+		pk_cnf_find_alternatives_truncate (cmd, len, possible);
+	pk_cnf_find_alternatives_remove_double (cmd, len, possible);
+
+	/* remove duplicates using a helper array */
+	for (i=0; i<possible->len; i++) {
+		cmdt = g_ptr_array_index (possible, i);
+		ret = TRUE;
+		for (j=0; j<unique->len; j++) {
+			cmdt2 = g_ptr_array_index (unique, j);
+			if (strcmp (cmdt, cmdt2) == 0) {
+				ret = FALSE;
+				break;
+			}
+		}
+		/* only add if not duplicate */
+		if (ret)
+			g_ptr_array_add (unique, (gpointer) cmdt);
+	}
+
+	/* seed path, we don't want to be doing g_strdup_printf in the fast path */
+	strncpy (buffer_bin, "/usr/bin/", 1023);
+	strncpy (buffer_sbin, "/usr/sbin/", 1023);
+
+	/* remove any that exist (fast path) */
+	for (i=0; i<unique->len; i++) {
+		cmdt = g_ptr_array_index (unique, i);
+		strncpy (&buffer_bin[9], cmdt, 1023-9);
+		strncpy (&buffer_sbin[10], cmdt, 1023-10);
+
+		/* does file exist in bindir (common case) */
+		ret = g_file_test (buffer_bin, G_FILE_TEST_EXISTS | G_FILE_TEST_IS_EXECUTABLE);
+		if (ret) {
+			g_ptr_array_add (array, g_strdup (cmdt));
+			continue;
+		}
+
+		/* does file exist in sbindir */
+		ret = g_file_test (buffer_sbin, G_FILE_TEST_EXISTS | G_FILE_TEST_IS_EXECUTABLE);
+		if (ret)
+			g_ptr_array_add (array, g_strdup (cmdt));
+	}
+
+	g_ptr_array_foreach (possible, (GFunc) g_free, NULL);
+	g_ptr_array_free (possible, TRUE);
+	g_ptr_array_free (unique, TRUE);
+	return array;
+}
+
+/**
+ * pk_cnf_find_available:
+ *
+ * Find software we could install
+ **/
+static GPtrArray *
+pk_cnf_find_available (const gchar *cmd)
+{
+	PkClient *client;
+	PkControl *control;
+	GError *error = NULL;
+	PkBitfield roles;
+	gboolean ret;
+	GPtrArray *array;
+	guint i, len;
+	PkPackageList *list = NULL;
+	const PkPackageObj *obj;
+	gchar *path = NULL;
+
+	control = pk_control_new ();
+	client = pk_client_new ();
+	pk_client_set_synchronous (client, TRUE, NULL);
+	pk_client_set_use_buffer (client, TRUE, NULL);
+	roles = pk_control_get_actions (control, NULL);
+	array = g_ptr_array_new ();
+
+	/* can we search the repos */
+	if (!pk_bitfield_contain (roles, PK_ROLE_ENUM_SEARCH_FILE)) {
+		egg_warning ("cannot search file");
+		goto out;
+	}
+
+	/* do search */
+	path = g_strdup_printf ("/usr/bin/%s", cmd);
+	egg_debug ("searching for %s", path);
+	ret = pk_client_search_file (client, PK_FILTER_ENUM_NONE, path, &error);
+	if (!ret) {
+		/* TRANSLATORS: we failed to find the package, this shouldn't happen */
+		egg_warning ("%s: %s", _("Failed to search for file"), error->message);
+		g_error_free (error);
+		goto out;
+	}
+
+	/* get package list */
+	list = pk_client_get_package_list (client);
+	if (list == NULL) {
+		egg_warning ("failed to get list");
+		goto out;
+	}
+
+	/* nothing found */
+	len = PK_OBJ_LIST(list)->len;
+	if (len == 0)
+		goto out;
+
+	/* add all package names */
+	for (i=0; i<len; i++) {
+		obj = pk_package_list_get_obj (list, i);
+		g_ptr_array_add (array, g_strdup (obj->id->name));
+		egg_warning ("obj->id->name=%s", obj->id->name);
+	}
+out:
+	if (list != NULL)
+		g_object_unref (list);
+	g_object_unref (control);
+	g_object_unref (client);
+	g_free (path);
+
+	return array;
+}
+
+/**
+ * pk_cnf_get_policy_from_string:
+ **/
+static PkCnfPolicy
+pk_cnf_get_policy_from_string (const gchar *policy_text)
+{
+	if (policy_text == NULL)
+		return PK_CNF_POLICY_UNKNOWN;
+	if (strcmp (policy_text, "run") == 0)
+		return PK_CNF_POLICY_RUN;
+	if (strcmp (policy_text, "ask") == 0)
+		return PK_CNF_POLICY_ASK;
+	if (strcmp (policy_text, "warn") == 0)
+		return PK_CNF_POLICY_WARN;
+	return PK_CNF_POLICY_UNKNOWN;
+}
+
+/**
+ * pk_cnf_get_policy_from_file:
+ **/
+static PkCnfPolicy
+pk_cnf_get_policy_from_file (GKeyFile *file, const gchar *key)
+{
+	PkCnfPolicy policy;
+	gchar *policy_text;
+	GError *error = NULL;
+
+	/* get from file */
+	policy_text = g_key_file_get_string (file, "CommandNotFound", key, &error);
+	if (policy_text == NULL) {
+		egg_warning ("failed to get key %s: %s", key, error->message);
+		g_error_free (error);
+	}
+
+	/* convert to enum */
+	policy = pk_cnf_get_policy_from_string (policy_text);
+	g_free (policy_text);
+	return policy;
+}
+
+/**
+ * pk_cnf_get_config:
+ **/
+static gboolean
+pk_cnf_get_config (PkCnfPolicyConfig *config)
+{
+	GKeyFile *file;
+	gchar *path;
+	gboolean ret;
+	GError *error = NULL;
+
+	/* set defaults if the conf file is not found */
+	config->single_match = PK_CNF_POLICY_UNKNOWN;
+	config->multiple_match = PK_CNF_POLICY_UNKNOWN;
+	config->single_install = PK_CNF_POLICY_UNKNOWN;
+	config->multiple_install = PK_CNF_POLICY_UNKNOWN;
+	config->software_source_search = FALSE;
+
+	/* load file */
+	file = g_key_file_new ();
+	path = g_build_filename (SYSCONFDIR, "PackageKit", "CommandNotFound.conf", NULL);
+	ret = g_key_file_load_from_file (file, path, G_KEY_FILE_NONE, &error);
+	if (!ret) {
+		egg_warning ("failed to open policy: %s", error->message);
+		g_error_free (error);
+		goto out;
+	}
+
+	/* get data */
+	config->single_match = pk_cnf_get_policy_from_file (file, "SingleMatch");
+	config->multiple_match = pk_cnf_get_policy_from_file (file, "MultipleMatch");
+	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);
+out:
+	g_free (path);
+	g_key_file_free (file);
+	return ret;
+}
+
+/**
+ * pk_cnf_spawn_command:
+ **/
+static gboolean
+pk_cnf_spawn_command (const gchar *exec)
+{
+	gboolean ret;
+	GError *error = NULL;
+	ret = g_spawn_command_line_sync (exec, NULL, NULL, NULL, &error);
+	if (!ret) {
+		/* TRANSLATORS: we failed to launch the executable, the error follows */
+		g_print ("%s '%s': %s", _("Failed to launch:"), exec, error->message);
+		g_error_free (error);
+	}
+	return ret;
+}
 
 /**
  * main:
@@ -38,15 +394,20 @@
 int
 main (int argc, char *argv[])
 {
-	PkControl *control;
-	PkConnection *pconnection;
-	gboolean connected;
+	gboolean ret;
 	gboolean verbose = FALSE;
 	GOptionContext *context;
+	GPtrArray *array = NULL;
+	GPtrArray *available = NULL;
+	PkCnfPolicyConfig config;
+	guint i;
+	guint len;
+	gchar *text;
+	const gchar *possible;
 
 	const GOptionEntry options[] = {
 		{ "verbose", 'v', 0, G_OPTION_ARG_NONE, &verbose,
-			_("Show extra debugging information"), NULL },
+		  _("Show extra debugging information"), NULL },
 		{ NULL}
 	};
 
@@ -61,21 +422,157 @@ main (int argc, char *argv[])
 	g_type_init ();
 
 	context = g_option_context_new (NULL);
-	g_option_context_set_summary (context, _("PackageKit Monitor"));
+	/* TRANSLATORS: tool that gets called when the command is not found */
+	g_option_context_set_summary (context, _("PackageKit Command Not Found"));
 	g_option_context_add_main_entries (context, options, NULL);
 	g_option_context_parse (context, &argc, &argv, NULL);
 	g_option_context_free (context);
 
 	egg_debug_init (verbose);
 
-	pconnection = pk_connection_new ();
-	connected = pk_connection_valid (pconnection);
-	g_print ("Command not found (connected=%i)\n", connected);
+	/* no input */
+	if (argv[1] == NULL)
+		goto out;
 
-	control = pk_control_new ();
+	/* get policy config */
+	pk_cnf_get_config (&config);
 
-	g_object_unref (control);
-	g_object_unref (pconnection);
+	/* generate swizzles */
+	len = egg_strlen (argv[1], 1024);
+	if (len < 2)
+		goto out;
+
+	array = pk_cnf_find_alternatives (argv[1], len);
+
+	/* TRANSLATORS: the prefix of all the output telling the user why it's not executing */
+	g_print ("%s ", _("Command not found."));
+
+	/* one exact possibility */
+	if (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 */
+			g_print ("%s '%s'\n", _("Similar command is:"), possible);
+
+		/* run */
+		} else if (config.single_match == PK_CNF_POLICY_RUN) {
+			pk_cnf_spawn_command (possible);
+
+		/* ask */
+		} else if (config.single_match == PK_CNF_POLICY_ASK) {
+			/* TRANSLATORS: Ask the user if we should run the similar command */
+			text = g_strdup_printf ("%s %s", _("Run similar command:"), possible);
+			ret = pk_console_get_prompt (text, TRUE);
+			if (ret)
+				pk_cnf_spawn_command (possible);
+			g_free (text);
+		}
+		goto out;
+
+	/* multiple choice */
+	} else if (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_print ("%s:\n", _("Similar commands are:"));
+			for (i=0; i<array->len; i++) {
+				possible = g_ptr_array_index (array, i);
+				g_print ("'%s'\n", possible);
+			}
+
+		/* ask */
+		} else if (config.multiple_match == PK_CNF_POLICY_ASK) {
+			/* TRANSLATORS: show the user a list of commands we could run */
+			g_print ("%s:\n", _("Similar commands are:"));
+			for (i=0; i<array->len; i++) {
+				possible = g_ptr_array_index (array, i);
+				g_print ("%i\t'%s'\n", i+1, possible);
+			}
+
+			/* TRANSLATORS: ask the user to choose a file to run */
+			i = pk_console_get_number (_("Please choose a command to run"), array->len);
+
+			/* run command */
+			possible = g_ptr_array_index (array, i);
+			pk_cnf_spawn_command (possible);
+		}
+		goto out;
+
+	/* only search using PackageKit if configured to do so */
+	} else if (config.software_source_search) {
+		available = pk_cnf_find_available (argv[1]);
+		if (available->len == 1) {
+			possible = g_ptr_array_index (available, 0);
+			if (config.single_install == PK_CNF_POLICY_WARN) {
+				/* TRANSLATORS: tell the user what package provides the command */
+				g_print ("%s '%s'\n", _("The package providing this file is:"), possible);
+
+			/* ask */
+			} else if (config.single_install == PK_CNF_POLICY_ASK) {
+				/* TRANSLATORS: as the user if we want to install a package to provide the command */
+				text = g_strdup_printf (_("Install package '%s' to provide command '%s'?"), possible, argv[1]);
+				ret = pk_console_get_prompt (text, FALSE);
+				g_free (text);
+				if (ret) {
+					text = g_strdup_printf ("pkcon install %s", possible);
+					ret = pk_cnf_spawn_command (text);
+					if (ret)
+						pk_cnf_spawn_command (argv[1]);
+					g_free (text);
+				}
+
+			/* install */
+			} else if (config.single_install == PK_CNF_POLICY_INSTALL) {
+				text = g_strdup_printf ("pkcon install %s", possible);
+				pk_cnf_spawn_command (text);
+				g_free (text);
+			}
+			goto out;
+		} else if (available->len > 1) {
+			if (config.multiple_install == PK_CNF_POLICY_WARN) {
+				/* TRANSLATORS: Show the user a list of packages that provide this command */
+				g_print ("%s:\n", _("Packages providing this file are:"));
+				for (i=0; i<available->len; i++) {
+					possible = g_ptr_array_index (available, i);
+					g_print ("'%s'\n", possible);
+				}
+
+			/* ask */
+			} else if (config.multiple_install == PK_CNF_POLICY_ASK) {
+				/* TRANSLATORS: Show the user a list of packages that they can install to provide this command */
+				g_print ("%s:\n", _("Suitable packages are:"));
+				for (i=0; i<available->len; i++) {
+					possible = g_ptr_array_index (available, i);
+					g_print ("%i\t'%s'\n", i+1, possible);
+				}
+
+				/* get selection */
+				/* TRANSLATORS: ask the user to choose a file to install */
+				i = pk_console_get_number (_("Please choose a package to install"), available->len);
+
+				/* run command */
+				possible = g_ptr_array_index (available, i);
+				text = g_strdup_printf ("pkcon install %s", possible);
+				ret = pk_cnf_spawn_command (text);
+				if (ret)
+					pk_cnf_spawn_command (argv[1]);
+				g_free (text);
+			}
+			goto out;
+		}
+	}
+
+	g_print ("\n");
+
+out:
+	if (array != NULL) {
+		g_ptr_array_foreach (array, (GFunc) g_free, NULL);
+		g_ptr_array_free (array, TRUE);
+	}
+	if (available != NULL) {
+		g_ptr_array_foreach (available, (GFunc) g_free, NULL);
+		g_ptr_array_free (available, TRUE);
+	}
 
 	return 0;
 }
+
diff --git a/contrib/command-not-found/pk-tools-common.c b/contrib/command-not-found/pk-tools-common.c
new file mode 120000
index 0000000..4afae3b
--- /dev/null
+++ b/contrib/command-not-found/pk-tools-common.c
@@ -0,0 +1 @@
+../../client/pk-tools-common.c
\ No newline at end of file
diff --git a/contrib/command-not-found/pk-tools-common.h b/contrib/command-not-found/pk-tools-common.h
new file mode 120000
index 0000000..f3e70b0
--- /dev/null
+++ b/contrib/command-not-found/pk-tools-common.h
@@ -0,0 +1 @@
+../../client/pk-tools-common.h
\ No newline at end of file
commit 5e9ac9604708cb6fe19784bac24324fd2fd3ad17
Author: Richard Hughes <richard at hughsie.com>
Date:   Fri Dec 5 10:11:30 2008 +0000

    feature: add initial code to add command-not-found functonality to PackageKit

diff --git a/configure.ac b/configure.ac
index f1ae477..ad4c9ee 100644
--- a/configure.ac
+++ b/configure.ac
@@ -331,6 +331,13 @@ fi
 AM_CONDITIONAL(PK_BUILD_GTK_MODULE, test $build_gtk_module = "yes")
 
 dnl ---------------------------------------------------------------------------
+dnl - Able to build BASH command-not-found functionality
+dnl ---------------------------------------------------------------------------
+AC_ARG_ENABLE(command_not_found, AS_HELP_STRING([--enable-command-not-found],[Build BASH command-not-found functionality]),
+	      build_command_not_found=$enableval,build_command_not_found=yes)
+AM_CONDITIONAL(PK_BUILD_COMMAND_NOT_FOUND, test $build_command_not_found = "yes")
+
+dnl ---------------------------------------------------------------------------
 dnl - Other tests
 dnl ---------------------------------------------------------------------------
 AC_ARG_ENABLE(gcov, AS_HELP_STRING([--enable-gcov],[compile with coverage profiling instrumentation (gcc only)]),
@@ -597,6 +604,7 @@ contrib/gstreamer-plugin/Makefile
 contrib/gtk-module/Makefile
 contrib/udev/Makefile
 contrib/yum-packagekit/Makefile
+contrib/command-not-found/Makefile
 backends/Makefile
 backends/alpm/Makefile
 backends/apt/Makefile
@@ -658,6 +666,7 @@ echo "
         Browser plugin:            ${build_browser_plugin}
         GStreamer plugin:          ${build_gstreamer_plugin}
         Pango module:              ${build_gtk_module}
+        BASH Command not found:    ${build_command_not_found}
         QT library:                ${build_qt}
 
         Backends:
diff --git a/contrib/Makefile.am b/contrib/Makefile.am
index 3f21c4d..b0e7879 100644
--- a/contrib/Makefile.am
+++ b/contrib/Makefile.am
@@ -16,6 +16,10 @@ if PK_BUILD_GTK_MODULE
 SUBDIRS += gtk-module
 endif
 
+if PK_BUILD_COMMAND_NOT_FOUND
+SUBDIRS += command-not-found
+endif
+
 bashcompletiondir = ${SYSCONFDIR}/bash_completion.d
 dist_bashcompletion_DATA = pk-completion.bash
 
diff --git a/contrib/PackageKit.spec.in b/contrib/PackageKit.spec.in
index 2d84277..5c394d6 100644
--- a/contrib/PackageKit.spec.in
+++ b/contrib/PackageKit.spec.in
@@ -201,6 +201,16 @@ Requires: PackageKit-glib = %{version}-%{release}
 The PackageKit GTK+ module allows any Pango application to install
 fonts from configured repositories using PackageKit.
 
+%package command-not-found
+Summary: Ask the user to install command line programs automatically
+Group: Development/Libraries
+Requires: bash
+Requires: PackageKit-glib = %{version}-%{release}
+
+%description command-not-found
+A simple helper that offers to install new packages on the command line
+using PackageKit.
+
 %prep
 %setup -q
 
@@ -364,6 +374,12 @@ update-mime-database %{_datadir}/mime &> /dev/null || :
 %doc README AUTHORS NEWS COPYING
 %{_libdir}/gtk-2.0/modules/*.so
 
+%files command-not-found
+%defattr(-,root,root,-)
+%doc README AUTHORS NEWS COPYING
+%{_sysconfdir}/profile.d/*
+%{_libexecdir}/pk-command-not-found
+
 %files glib-devel
 %defattr(-,root,root,-)
 %doc README AUTHORS NEWS COPYING
diff --git a/contrib/command-not-found/.gitignore b/contrib/command-not-found/.gitignore
new file mode 100644
index 0000000..8aa84ae
--- /dev/null
+++ b/contrib/command-not-found/.gitignore
@@ -0,0 +1,5 @@
+.deps
+.libs
+*.o
+pk-command-not-found
+
diff --git a/contrib/command-not-found/Makefile.am b/contrib/command-not-found/Makefile.am
new file mode 100644
index 0000000..d8258e7
--- /dev/null
+++ b/contrib/command-not-found/Makefile.am
@@ -0,0 +1,32 @@
+## We require new-style dependency handling.
+AUTOMAKE_OPTIONS = 1.7
+
+INCLUDES =						\
+	$(GLIB_CFLAGS)					\
+	$(DBUS_CFLAGS)					\
+	-DPACKAGE_LOCALE_DIR=\"$(localedir)\"		\
+	-DEGG_LOG_FILE=\""$(PK_LOG_DIR)/PackageKit"\"	\
+	-DEGG_VERBOSE="\"PK_VERBOSE\""			\
+	-DEGG_LOGGING="\"PK_LOGGING\""			\
+	-DEGG_CONSOLE="\"PK_CONSOLE\""			\
+	-I$(top_srcdir)/lib
+
+PK_GLIB_LIBS = $(top_builddir)/lib/packagekit-glib/libpackagekit-glib.la
+
+libexec_PROGRAMS = pk-command-not-found
+
+pk_command_not_found_SOURCES =				\
+	egg-debug.c					\
+	egg-debug.h					\
+	pk-command-not-found.c				\
+	$(NULL)
+
+pk_command_not_found_LDADD =				\
+	$(GLIB_LIBS)					\
+	$(DBUS_LIBS)					\
+	$(PK_GLIB_LIBS)					\
+	$(NULL)
+
+bashprofiledir = ${SYSCONFDIR}/profile.d
+dist_bashprofile_DATA = PackageKit.sh
+
diff --git a/contrib/command-not-found/PackageKit.sh b/contrib/command-not-found/PackageKit.sh
new file mode 100644
index 0000000..95d85e3
--- /dev/null
+++ b/contrib/command-not-found/PackageKit.sh
@@ -0,0 +1,12 @@
+# 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.
+
+command_not_found_handler () {
+	/usr/libexec/pk-command-not-found $1 || return 127
+}
+
diff --git a/contrib/command-not-found/egg-debug.c b/contrib/command-not-found/egg-debug.c
new file mode 120000
index 0000000..cc37e68
--- /dev/null
+++ b/contrib/command-not-found/egg-debug.c
@@ -0,0 +1 @@
+../../lib/packagekit-glib/egg-debug.c
\ No newline at end of file
diff --git a/contrib/command-not-found/egg-debug.h b/contrib/command-not-found/egg-debug.h
new file mode 120000
index 0000000..ccc6364
--- /dev/null
+++ b/contrib/command-not-found/egg-debug.h
@@ -0,0 +1 @@
+../../lib/packagekit-glib/egg-debug.h
\ No newline at end of file
diff --git a/contrib/command-not-found/pk-command-not-found.c b/contrib/command-not-found/pk-command-not-found.c
new file mode 100644
index 0000000..172f2f4
--- /dev/null
+++ b/contrib/command-not-found/pk-command-not-found.c
@@ -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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include "config.h"
+
+#include <string.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <locale.h>
+#include <glib.h>
+#include <glib/gi18n.h>
+#include <dbus/dbus-glib.h>
+#include <packagekit-glib/packagekit.h>
+
+#include "egg-debug.h"
+
+/**
+ * main:
+ **/
+int
+main (int argc, char *argv[])
+{
+	PkControl *control;
+	PkConnection *pconnection;
+	gboolean connected;
+	gboolean verbose = FALSE;
+	GOptionContext *context;
+
+	const GOptionEntry options[] = {
+		{ "verbose", 'v', 0, G_OPTION_ARG_NONE, &verbose,
+			_("Show extra debugging information"), NULL },
+		{ NULL}
+	};
+
+	setlocale (LC_ALL, "");
+	bindtextdomain (GETTEXT_PACKAGE, PACKAGE_LOCALE_DIR);
+	bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
+	textdomain (GETTEXT_PACKAGE);
+
+	if (! g_thread_supported ())
+		g_thread_init (NULL);
+	dbus_g_thread_init ();
+	g_type_init ();
+
+	context = g_option_context_new (NULL);
+	g_option_context_set_summary (context, _("PackageKit Monitor"));
+	g_option_context_add_main_entries (context, options, NULL);
+	g_option_context_parse (context, &argc, &argv, NULL);
+	g_option_context_free (context);
+
+	egg_debug_init (verbose);
+
+	pconnection = pk_connection_new ();
+	connected = pk_connection_valid (pconnection);
+	g_print ("Command not found (connected=%i)\n", connected);
+
+	control = pk_control_new ();
+
+	g_object_unref (control);
+	g_object_unref (pconnection);
+
+	return 0;
+}
commit 35acc3337ac5032649932edb7cb4bcb9813970ca
Author: Richard Hughes <richard at hughsie.com>
Date:   Fri Dec 5 09:50:05 2008 +0000

    yum: check if a package has the correct architecture, and if not exit with an error. Fixes rh#474740

diff --git a/backends/yum/yumBackend.py b/backends/yum/yumBackend.py
index 03c02b4..8504639 100755
--- a/backends/yum/yumBackend.py
+++ b/backends/yum/yumBackend.py
@@ -1576,10 +1576,18 @@ class PackageKitYumBackend(PackageKitBaseBackend, PackagekitPackage):
             self.error(ERROR_INTERNAL_ERROR, _to_unicode(e))
             return False
 
+        # check if wrong arch
+        suitable_archs = rpmUtils.arch.getArchList()
+        if po.arch not in suitable_archs:
+            self.error(ERROR_INCOMPATIBLE_ARCHITECTURE, "Package %s has incompatible architecture %s. Valid architectures are %s" % (pkg, po.arch, suitable_archs))
+            return False
+
+        # check already installed
         if self._is_inst_arch(po):
             self.error(ERROR_PACKAGE_ALREADY_INSTALLED, "The package %s is already installed" % str(po))
             return False
 
+        # check if excluded
         if len(self.yumbase.conf.exclude) > 0:
             exactmatch, matched, unmatched = parsePackages([po], self.yumbase.conf.exclude, casematch=1)
             if po in exactmatch + matched:
commit 8fedc5df068b9395cc0ee7a406e7da0393c4b810
Author: Richard Hughes <richard at hughsie.com>
Date:   Fri Dec 5 09:46:15 2008 +0000

    trivial: add another error enum for incompatible architectures

diff --git a/lib/packagekit-glib/pk-enum.c b/lib/packagekit-glib/pk-enum.c
index 52a4528..474bdfe 100644
--- a/lib/packagekit-glib/pk-enum.c
+++ b/lib/packagekit-glib/pk-enum.c
@@ -167,6 +167,7 @@ static const PkEnumMatch enum_error[] = {
 	{PK_ERROR_ENUM_FILE_NOT_FOUND,		"file-not-found"},
 	{PK_ERROR_ENUM_NO_MORE_MIRRORS_TO_TRY,	"no-more-mirrors-to-try"},
 	{PK_ERROR_ENUM_NO_DISTRO_UPGRADE_DATA,	"no-distro-upgrade-data"},
+	{PK_ERROR_ENUM_INCOMPATIBLE_ARCHITECTURE,	"incompatible-architecture"},
 	{0, NULL}
 };
 
diff --git a/lib/packagekit-glib/pk-enum.h b/lib/packagekit-glib/pk-enum.h
index e610985..c569d63 100644
--- a/lib/packagekit-glib/pk-enum.h
+++ b/lib/packagekit-glib/pk-enum.h
@@ -279,6 +279,7 @@ typedef enum {
 	PK_ERROR_ENUM_FILE_NOT_FOUND,
 	PK_ERROR_ENUM_NO_MORE_MIRRORS_TO_TRY,
 	PK_ERROR_ENUM_NO_DISTRO_UPGRADE_DATA,
+	PK_ERROR_ENUM_INCOMPATIBLE_ARCHITECTURE,
 	PK_ERROR_ENUM_UNKNOWN
 } PkErrorCodeEnum;
 
commit e05f7353577688f0334cbdaabeb1a05580e53d98
Author: Richard Hughes <richard at hughsie.com>
Date:   Fri Dec 5 09:45:22 2008 +0000

    trivial: fix up the library path in the error helper

diff --git a/tools/add-error-enum.sh b/tools/add-error-enum.sh
index 2ae43b9..1d35e6a 100755
--- a/tools/add-error-enum.sh
+++ b/tools/add-error-enum.sh
@@ -7,5 +7,5 @@
 # the Free Software Foundation; either version 2 of the License, or
 # (at your option) any later version.
 
-$EDITOR docs/api/spec/pk-concepts.xml libpackagekit/pk-enum.h libpackagekit/pk-enum.c ../gnome-packagekit/src/gpk-enum.c ../gnome-packagekit/src/gpk-common.c
+$EDITOR docs/api/spec/pk-concepts.xml lib/packagekit-glib/pk-enum.h lib/packagekit-glib/pk-enum.c ../gnome-packagekit/src/gpk-enum.c ../gnome-packagekit/src/gpk-common.c
 
commit 6825ae2f69bae523f55a69f367b18f7230e0daf9
Author: Marcin Banasiak <megabajt at pld-linux.org>
Date:   Thu Dec 4 22:00:40 2008 +0100

    poldek: implement backend_get_mime_types

diff --git a/backends/poldek/pk-backend-poldek.c b/backends/poldek/pk-backend-poldek.c
index 80fb984..e9b3f88 100644
--- a/backends/poldek/pk-backend-poldek.c
+++ b/backends/poldek/pk-backend-poldek.c
@@ -2039,6 +2039,15 @@ backend_get_filters (PkBackend *backend)
 }
 
 /**
+ * backend_get_mime_types:
+ */
+static gchar *
+backend_get_mime_types (PkBackend *backend)
+{
+	return g_strdup ("application/x-rpm");
+}
+
+/**
  * backend_get_cancel:
  **/
 static void
@@ -2847,7 +2856,7 @@ PK_BACKEND_OPTIONS (
 	backend_destroy,				/* destroy */
 	backend_get_groups,				/* get_groups */
 	backend_get_filters,				/* get_filters */
-	NULL,						/* get_mime_types */
+	backend_get_mime_types,				/* get_mime_types */
 	backend_get_cancel,				/* cancel */
 	backend_download_packages,			/* download_packages */
 	NULL,						/* get_categories */
commit 167543051fb9e3a54a2cb199cc59b62a693ddfda
Author: Richard Hughes <richard at hughsie.com>
Date:   Thu Dec 4 14:23:41 2008 +0000

    bugfix: make a lot of new string translatable in pkcon

diff --git a/client/pk-console.c b/client/pk-console.c
index 1a007a9..9768e83 100644
--- a/client/pk-console.c
+++ b/client/pk-console.c
@@ -218,27 +218,64 @@ pk_console_transaction_cb (PkClient *client, const PkTransactionObj *obj, gpoint
 {
 	struct passwd *pw;
 	const gchar *role_text;
+	gchar **lines;
+	gchar **parts;
+	guint i, lines_len;
+	PkPackageId *id;
 
 	role_text = pk_role_enum_to_text (obj->role);
 	if (awaiting_space)
 		g_print ("\n");
-	g_print ("Transaction  : %s\n", obj->tid);
-	g_print (" timespec    : %s\n", obj->timespec);
-	g_print (" succeeded   : %i\n", obj->succeeded);
-	g_print (" role        : %s\n", role_text);
-	g_print (" duration    : %i (seconds)\n", obj->duration);
-	g_print (" data        : %s\n", obj->data);
-	g_print (" cmdline     : %s\n", obj->cmdline);
-	g_print (" uid         : %i\n", obj->uid);
+	/* TRANSLATORS: this is an atomic transaction */
+	g_print ("%s: %s\n", _("Transaction"), obj->tid);
+	/* TRANSLATORS: this is the time the transaction was started in system timezone */
+	g_print (" %s: %s\n", _("System time"), obj->timespec);
+	/* TRANSLATORS: this is if the transaction succeeded or not */
+	g_print (" %s: %s\n", _("Succeeded"), obj->timespec ? _("True") : _("False"));
+	/* TRANSLATORS: this is the transactions role, e.g. "update-system" */
+	g_print (" %s: %s\n", _("Role"), role_text);
+
+	/* only print if not null */
+	if (obj->duration > 0) {
+		/* TRANSLATORS: this is The duration of the transaction */
+		g_print (" %s: %i %s\n", _("Duration"), obj->duration, _("(seconds)"));
+	}
+
+	/* TRANSLATORS: this is The command line used to do the action */
+	g_print (" %s: %s\n", _("Command line"), obj->cmdline);
+	/* TRANSLATORS: this is the user ID of the user that started the action */
+	g_print (" %s: %i\n", _("User ID"), obj->uid);
 
 	/* query real name */
 	pw = getpwuid(obj->uid);
 	if (pw != NULL) {
-		if (pw->pw_name != NULL)
-			g_print (" user name   : %s\n", pw->pw_name);
-		if (pw->pw_gecos != NULL)
-			g_print (" real name   : %s\n", pw->pw_gecos);
+		if (pw->pw_name != NULL) {
+			/* TRANSLATORS: this is the username, e.g. hughsie */
+			g_print (" %s: %s\n", _("Username"), pw->pw_name);
+		}
+		if (pw->pw_gecos != NULL) {
+			/* TRANSLATORS: this is the users real name, e.g. "Richard Hughes" */
+			g_print (" %s: %s\n", _("Real name"), pw->pw_gecos);
+		}
+	}
+
+	/* TRANSLATORS: these are packages touched by the transaction */
+	g_print (" %s:\n", _("Affected packages"));
+	lines = g_strsplit (obj->data, "\n", -1);
+	lines_len = g_strv_length (lines);
+	for (i=0; i<lines_len; i++) {
+		parts = g_strsplit (lines[i], "\t", 3);
+		id = pk_package_id_new_from_string (parts[1]);
+		g_print (" - %s %s", parts[0], id->name);
+		if (!egg_strzero (id->version))
+			g_print ("-%s", id->version);
+		if (!egg_strzero (id->arch))
+			g_print (".%s", id->arch);
+		g_print ("\n");
+		pk_package_id_free (id);
+		g_strfreev (parts);
 	}
+	g_strfreev (lines);
 }
 
 /**
@@ -249,9 +286,12 @@ pk_console_distro_upgrade_cb (PkClient *client, const PkDistroUpgradeObj *obj, g
 {
 	if (awaiting_space)
 		g_print ("\n");
-	g_print ("Distro       : %s\n", obj->name);
-	g_print (" type        : %s\n", pk_update_state_enum_to_text (obj->state));
-	g_print (" summary     : %s\n", obj->summary);
+	/* TRANSLATORS: this is the distro, e.g. Fedora 10 */
+	g_print ("%s: %s\n", _("Distribution"), obj->name);
+	/* TRANSLATORS: this is type of update, stable or testing */
+	g_print (" %s: %s\n", _("Type"), pk_update_state_enum_to_text (obj->state));
+	/* TRANSLATORS: this is any summary text describing the upgrade */
+	g_print (" %s: %s\n", _("Summary"), obj->summary);
 }
 
 /**
@@ -262,14 +302,21 @@ pk_console_category_cb (PkClient *client, const PkCategoryObj *obj, gpointer use
 {
 	if (awaiting_space)
 		g_print ("\n");
-	g_print ("Category  : %s\n", obj->name);
-	g_print (" cat_id   : %s\n", obj->cat_id);
-	if (!egg_strzero (obj->parent_id))
-		g_print (" parent   : %s\n", obj->parent_id);
-	g_print (" name     : %s\n", obj->name);
-	if (!egg_strzero (obj->summary))
-		g_print (" summary  : %s\n", obj->summary);
-	g_print (" icon     : %s\n", obj->icon);
+	/* TRANSLATORS: this is the group category name */
+	g_print ("%s: %s\n", _("Category"), obj->name);
+	/* TRANSLATORS: this is group identifier */
+	g_print (" %s: %s\n", _("ID"), obj->cat_id);
+	if (!egg_strzero (obj->parent_id)) {
+		/* TRANSLATORS: this is the parent group */
+		g_print (" %s: %s\n", _("Parent"), obj->parent_id);
+	}
+	g_print (" %s: %s\n", _("Name"), obj->name);
+	if (!egg_strzero (obj->summary)) {
+		/* TRANSLATORS: this is the summary of the group */
+		g_print (" %s: %s\n", _("Summary"), obj->summary);
+	}
+	/* TRANSLATORS: this is preferred icon for the group */
+	g_print (" %s: %s\n", _("Icon"), obj->icon);
 }
 
 /**
@@ -285,31 +332,31 @@ pk_console_update_detail_cb (PkClient *client, const PkUpdateDetailObj *detail,
 		g_print ("\n");
 	/* TRANSLATORS: this is a header for the package that can be updated */
 	g_print ("%s\n", _("Details about the update:"));
-	g_print ("  package:    '%s-%s.%s'\n", detail->id->name, detail->id->version, detail->id->arch);
+	g_print (" %s: '%s-%s.%s'\n", _("Package"), detail->id->name, detail->id->version, detail->id->arch);
 	if (!egg_strzero (detail->updates))
-		g_print ("  updates:    %s\n", detail->updates);
+		g_print (" %s: %s\n", _("Updates"), detail->updates);
 	if (!egg_strzero (detail->obsoletes))
-		g_print ("  obsoletes:  %s\n", detail->obsoletes);
+		g_print (" %s: %s\n", _("Obsoletes"), detail->obsoletes);
 	if (!egg_strzero (detail->vendor_url))
-		g_print ("  vendor URL: %s\n", detail->vendor_url);
+		g_print (" %s: %s\n", _("Vendor"), detail->vendor_url);
 	if (!egg_strzero (detail->bugzilla_url))
-		g_print ("  bug URL:    %s\n", detail->bugzilla_url);
+		g_print (" %s: %s\n", _("Bugzilla"), detail->bugzilla_url);
 	if (!egg_strzero (detail->cve_url))
-		g_print ("  cve URL:    %s\n", detail->cve_url);
+		g_print (" %s: %s\n", _("CVE"), detail->cve_url);
 	if (detail->restart != PK_RESTART_ENUM_NONE)
-		g_print ("  restart:    %s\n", pk_restart_enum_to_text (detail->restart));
+		g_print (" %s: %s\n", _("Restart"), pk_restart_enum_to_text (detail->restart));
 	if (!egg_strzero (detail->update_text))
-		g_print ("  update_text:%s\n", detail->update_text);
+		g_print (" %s: %s\n", _("Update text"), detail->update_text);
 	if (!egg_strzero (detail->changelog))
-		g_print ("  changelog:  %s\n", detail->changelog);
+		g_print (" %s: %s\n", _("Changes"), detail->changelog);
 	if (detail->state != PK_UPDATE_STATE_ENUM_UNKNOWN)
-		g_print ("  state:      %s\n", pk_update_state_enum_to_text (detail->state));
+		g_print (" %s: %s\n", _("State"), pk_update_state_enum_to_text (detail->state));
 	issued = pk_iso8601_from_date (detail->issued);
 	if (!egg_strzero (issued))
-		g_print ("  issued:     %s\n", issued);
+		g_print (" %s: %s\n", _("Issued"), issued);
 	updated = pk_iso8601_from_date (detail->updated);
 	if (!egg_strzero (updated))
-		g_print ("  updated:    %s\n", updated);
+		g_print (" %s: %s\n", _("Updated"), updated);
 	g_free (issued);
 	g_free (updated);
 }
@@ -321,15 +368,10 @@ static void
 pk_console_repo_detail_cb (PkClient *client, const gchar *repo_id,
 			   const gchar *description, gboolean enabled, gpointer data)
 {
-	gchar *repo;
-	repo = pk_strpad (repo_id, 28);
 	if (awaiting_space)
 		g_print ("\n");
-	if (enabled)
-		g_print ("  enabled   %s %s\n", repo, description);
-	else
-		g_print ("  disabled  %s %s\n", repo, description);
-	g_free (repo);
+	/* TRANSLATORS: if the repo is enabled */
+	g_print (" %s\t%s\t%s\n", enabled ? _("True") : _("False"), repo_id, description);
 }
 
 /**
@@ -400,9 +442,9 @@ pk_console_progress_changed_cb (PkClient *client, guint percentage, guint subper
 {
 	if (!is_console) {
 		if (percentage != PK_CLIENT_PERCENTAGE_INVALID)
-			g_print ("percentage: %i%%\n", percentage);
+			g_print ("%s: %i%%\n", _("Percentage"), percentage);
 		else
-			g_print ("percentage: unknown\n");
+			g_print ("%s: %s\n", _("Percentage"), _("Unknown"));
 		return;
 	}
 	percentage_last = percentage;
@@ -1344,7 +1386,7 @@ pk_console_error_code_cb (PkClient *client, PkErrorCodeEnum error_code, const gc
 	if (awaiting_space)
 		g_print ("\n");
 	/* TRANSLATORS: This was an unhandled error, and we don't have _any_ context */
-	g_print ("%s %s : %s\n", _("Error:"), pk_error_enum_to_text (error_code), details);
+	g_print ("%s %s: %s\n", _("Error:"), pk_error_enum_to_text (error_code), details);
 }
 
 /**
commit 02b36f20b3b1d0fc5ba9f1016dcb1b879a6bedda
Author: Richard Hughes <richard at hughsie.com>
Date:   Thu Dec 4 13:43:36 2008 +0000

    trivial: remove planned features section, it's obsolete

diff --git a/docs/html/pk-help.html b/docs/html/pk-help.html
index 6cace7c..318b48b 100644
--- a/docs/html/pk-help.html
+++ b/docs/html/pk-help.html
@@ -61,21 +61,6 @@ existing backends as a template for what you are trying to do.
 </tr>
 </table>
 
-<hr>
-<h3><a name="timeline">What are the planned features?</a></h3>
-<p>
-There is a rough timeline for new features - we can't do everything at once...
-If you want to work on a feature and bring it forward, please just jump on the mailing list and
-as for instructions!
-</p>
-<p>
-<b>0.3.2</b> - To be released September 2008
-</p>
-<ul>
-<li>Category support (install/remove whole categories of applications)<i>(0%)</i></li>
-<li>NetworkManager integration so we can detect GPRS (and modem) connections. <i>(10%)</i></li>
-</ul>
-
 <p>Back to the <a href="index.html">main page</a></p>
 
 <p class="footer">
commit bc30cd1adfd00cad4260757291cc5ebddcabe6d7
Author: Richard Hughes <richard at hughsie.com>
Date:   Thu Dec 4 10:13:33 2008 +0000

    yum: as we can't treat yum like a usual python module, hand-hold it by wrapping all calls in 'except Exception' and throwing an internal error. This sucks.

diff --git a/backends/yum/yumBackend.py b/backends/yum/yumBackend.py
index 657cdcd..03c02b4 100755
--- a/backends/yum/yumBackend.py
+++ b/backends/yum/yumBackend.py
@@ -268,8 +268,11 @@ class PackageKitYumBackend(PackageKitBaseBackend, PackagekitPackage):
         ''' Unlock Yum'''
         if self.isLocked():
             PackageKitBaseBackend.unLock(self)
-            self.yumbase.closeRpmDB()
-            self.yumbase.doUnlock(YUM_PID_FILE)
+            try:
+                self.yumbase.closeRpmDB()
+                self.yumbase.doUnlock(YUM_PID_FILE)
+            except Exception, e:
+                self.error(ERROR_INTERNAL_ERROR, _to_unicode(e))
 
     def _do_meta_package_search(self, fltlist, key):
         grps = self.comps.get_meta_packages()
@@ -312,6 +315,8 @@ class PackageKitYumBackend(PackageKitBaseBackend, PackagekitPackage):
                         available.append(pkg)
             except yum.Errors.RepoError, e:
                 self.error(ERROR_NO_CACHE, _to_unicode(e))
+            except Exception, e:
+                self.error(ERROR_INTERNAL_ERROR, _to_unicode(e))
             else:
                 pkgfilter.add_installed(installed)
                 pkgfilter.add_available(available)
@@ -335,7 +340,10 @@ class PackageKitYumBackend(PackageKitBaseBackend, PackagekitPackage):
 
         searchlist = ['name']
         self.status(STATUS_QUERY)
-        self.yumbase.doConfigSetup(errorlevel=0, debuglevel=0)# Setup Yum Config
+        try:
+            self.yumbase.doConfigSetup(errorlevel=0, debuglevel=0)# Setup Yum Config
+        except Exception, e:
+            self.error(ERROR_INTERNAL_ERROR, _to_unicode(e))
         self._do_search(searchlist, filters, key)
 
     def search_details(self, filters, key):
@@ -343,7 +351,10 @@ class PackageKitYumBackend(PackageKitBaseBackend, PackagekitPackage):
         Implement the {backend}-search-details functionality
         '''
         self._check_init(lazy_cache=True)
-        self.yumbase.doConfigSetup(errorlevel=0, debuglevel=0)# Setup Yum Config
+        try:
+            self.yumbase.doConfigSetup(errorlevel=0, debuglevel=0)# Setup Yum Config
+        except Exception, e:
+            self.error(ERROR_INTERNAL_ERROR, _to_unicode(e))
         self.yumbase.conf.cache = 0 # Allow new files
         self.allow_cancel(True)
         self.percentage(None)
@@ -355,7 +366,10 @@ class PackageKitYumBackend(PackageKitBaseBackend, PackagekitPackage):
     def _get_installed_from_names(self, name_list):
         found = []
         for package in name_list:
-            pkgs = self.yumbase.rpmdb.searchNevra(name=package)
+            try:
+                pkgs = self.yumbase.rpmdb.searchNevra(name=package)
+            except Exception, e:
+                self.error(ERROR_INTERNAL_ERROR, _to_unicode(e))
             found.extend(pkgs)
         return found
 
@@ -365,6 +379,8 @@ class PackageKitYumBackend(PackageKitBaseBackend, PackagekitPackage):
             pkgs = self.yumbase.pkgSack.searchNames(names=name_list)
         except yum.Errors.RepoError, e:
             self.error(ERROR_NO_CACHE, _to_unicode(e))
+        except Exception, e:
+            self.error(ERROR_INTERNAL_ERROR, _to_unicode(e))
         return pkgs
 
     def _handle_newest(self, fltlist):
@@ -379,11 +395,16 @@ class PackageKitYumBackend(PackageKitBaseBackend, PackagekitPackage):
             pkgs.extend(ygl.recent)
         except yum.Errors.RepoError, e:
             self.error(ERROR_REPO_NOT_AVAILABLE, _to_unicode(e))
+        except Exception, e:
+            self.error(ERROR_INTERNAL_ERROR, _to_unicode(e))
 
         installed = []
         available = []
         for pkg in pkgs:
-            instpo = self.yumbase.rpmdb.searchNevra(name=pkg.name, epoch=pkg.epoch, ver=pkg.ver, rel=pkg.rel, arch=pkg.arch)
+            try:
+                instpo = self.yumbase.rpmdb.searchNevra(name=pkg.name, epoch=pkg.epoch, ver=pkg.ver, rel=pkg.rel, arch=pkg.arch)
+            except Exception, e:
+                self.error(ERROR_INTERNAL_ERROR, _to_unicode(e))
             if len(instpo) > 0:
                 installed.append(instpo[0])
             else:
@@ -425,6 +446,8 @@ class PackageKitYumBackend(PackageKitBaseBackend, PackagekitPackage):
             grp = self.yumbase.comps.return_group(grpid)
         except yum.Errors.RepoError, e:
             self.error(ERROR_NO_CACHE, _to_unicode(e))
+        except Exception, e:
+            self.error(ERROR_INTERNAL_ERROR, _to_unicode(e))
         else:
             if grp:
                 name = grp.nameByLang(self.lang)
@@ -441,7 +464,10 @@ class PackageKitYumBackend(PackageKitBaseBackend, PackagekitPackage):
         '''
         self._check_init(lazy_cache=True)
         self.allow_cancel(True)
-        self.yumbase.doConfigSetup(errorlevel=0, debuglevel=0)# Setup Yum Config
+        try:
+            self.yumbase.doConfigSetup(errorlevel=0, debuglevel=0)# Setup Yum Config
+        except Exception, e:
+            self.error(ERROR_INTERNAL_ERROR, _to_unicode(e))
         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
@@ -497,7 +523,10 @@ class PackageKitYumBackend(PackageKitBaseBackend, PackagekitPackage):
         '''
         self.status(STATUS_QUERY)
         self.allow_cancel(True)
-        self.yumbase.doConfigSetup(errorlevel=0, debuglevel=0)# Setup Yum Config
+        try:
+            self.yumbase.doConfigSetup(errorlevel=0, debuglevel=0)# Setup Yum Config
+        except Exception, e:
+            self.error(ERROR_INTERNAL_ERROR, _to_unicode(e))
         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
@@ -505,7 +534,10 @@ class PackageKitYumBackend(PackageKitBaseBackend, PackagekitPackage):
         pkgfilter = YumFilter(fltlist)
 
         # Now show installed packages.
-        pkgs = self.yumbase.rpmdb
+        try:
+            pkgs = self.yumbase.rpmdb
+        except Exception, e:
+            self.error(ERROR_INTERNAL_ERROR, _to_unicode(e))
         pkgfilter.add_installed(pkgs)
 
         # Now show available packages.
@@ -514,6 +546,8 @@ class PackageKitYumBackend(PackageKitBaseBackend, PackagekitPackage):
                 pkgs = self.yumbase.pkgSack
             except yum.Errors.RepoError, e:
                 self.error(ERROR_NO_CACHE, _to_unicode(e))
+            except Exception, e:
+                self.error(ERROR_INTERNAL_ERROR, _to_unicode(e))
             else:
                 pkgfilter.add_available(pkgs)
 
@@ -536,7 +570,10 @@ class PackageKitYumBackend(PackageKitBaseBackend, PackagekitPackage):
         pkgfilter = YumFilter(fltlist)
 
         # Check installed for file
-        pkgs = self.yumbase.rpmdb.searchFiles(key)
+        try:
+            pkgs = self.yumbase.rpmdb.searchFiles(key)
+        except Exception, e:
+            self.error(ERROR_INTERNAL_ERROR, _to_unicode(e))
         pkgfilter.add_installed(pkgs)
 
         # Check available for file
@@ -547,6 +584,8 @@ class PackageKitYumBackend(PackageKitBaseBackend, PackagekitPackage):
                 pkgs = self.yumbase.pkgSack.searchFiles(key)
             except yum.Errors.RepoError, e:
                 self.error(ERROR_NO_CACHE, _to_unicode(e))
+            except Exception, e:
+                self.error(ERROR_INTERNAL_ERROR, _to_unicode(e))
             else:
                 pkgfilter.add_available(pkgs)
 
@@ -568,7 +607,10 @@ class PackageKitYumBackend(PackageKitBaseBackend, PackagekitPackage):
         pkgfilter = YumFilter(fltlist)
 
         # Check installed for file
-        pkgs = self.yumbase.rpmdb.searchProvides(search)
+        try:
+            pkgs = self.yumbase.rpmdb.searchProvides(search)
+        except Exception, e:
+            self.error(ERROR_INTERNAL_ERROR, _to_unicode(e))
         pkgfilter.add_installed(pkgs)
 
         if not FILTER_INSTALLED in fltlist:
@@ -577,6 +619,8 @@ class PackageKitYumBackend(PackageKitBaseBackend, PackagekitPackage):
                 pkgs = self.yumbase.pkgSack.searchProvides(search)
             except yum.Errors.RepoError, e:
                 self.error(ERROR_NO_CACHE, _to_unicode(e))
+            except Exception, e:
+                self.error(ERROR_INTERNAL_ERROR, _to_unicode(e))
             else:
                 pkgfilter.add_available(pkgs)
 
@@ -595,6 +639,9 @@ class PackageKitYumBackend(PackageKitBaseBackend, PackagekitPackage):
             cats = self.yumbase.comps.categories
         except yum.Errors.RepoError, e:
             self.error(ERROR_NO_CACHE, _to_unicode(e))
+        except Exception, e:
+            self.error(ERROR_INTERNAL_ERROR, _to_unicode(e))
+
         if len(cats) == 0:
             self.error(ERROR_GROUP_LIST_INVALID, "no comps categories")
         for cat in cats:
@@ -625,7 +672,10 @@ class PackageKitYumBackend(PackageKitBaseBackend, PackagekitPackage):
         for cat in cats:
             grps = []
             for grp_id in self.comps.get_groups(cat):
-                grp = self.yumbase.comps.return_group(grp_id)
+                try:
+                    grp = self.yumbase.comps.return_group(grp_id)
+                except Exception, e:
+                    self.error(ERROR_INTERNAL_ERROR, _to_unicode(e))
                 if grp:
                     grps.append(grp)
             for grp in sorted(grps):
@@ -669,6 +719,8 @@ class PackageKitYumBackend(PackageKitBaseBackend, PackagekitPackage):
                 packs = self.yumbase.pkgSack.searchNevra(n, e, v, r, a)
             except yum.Errors.RepoError, e:
                 self.error(ERROR_NO_CACHE, _to_unicode(e))
+            except Exception, e:
+                self.error(ERROR_INTERNAL_ERROR, _to_unicode(e))
 
             # if we couldn't map package_id -> pkg
             if len(packs) == 0:
@@ -678,7 +730,10 @@ class PackageKitYumBackend(PackageKitBaseBackend, PackagekitPackage):
             # should have only one...
             for pkg_download in packs:
                 self._show_package(pkg_download, INFO_DOWNLOADING)
-                repo = self.yumbase.repos.getRepo(pkg_download.repoid)
+                try:
+                    repo = self.yumbase.repos.getRepo(pkg_download.repoid)
+                except Exception, e:
+                    self.error(ERROR_INTERNAL_ERROR, _to_unicode(e))
                 remote = pkg_download.returnSimple('relativepath')
                 local = os.path.basename(remote)
                 if not os.path.exists(directory):
@@ -712,10 +767,16 @@ class PackageKitYumBackend(PackageKitBaseBackend, PackagekitPackage):
             (name, idver, a, repo) = self.get_package_from_id(package_id)
             isGroup = False
             if repo == 'meta':
-                grp = self.yumbase.comps.return_group(name)
+                try:
+                    grp = self.yumbase.comps.return_group(name)
+                except Exception, e:
+                    self.error(ERROR_INTERNAL_ERROR, _to_unicode(e))
                 isGroup = True
             elif name[0] == '@':
-                grp = self.yumbase.comps.return_group(name[1:])
+                try:
+                    grp = self.yumbase.comps.return_group(name[1:])
+                except Exception, e:
+                    self.error(ERROR_INTERNAL_ERROR, _to_unicode(e))
                 isGroup = True
             if isGroup and not grp:
                 self.error(ERROR_PACKAGE_NOT_FOUND, "The Group %s dont exist" % name)
@@ -739,7 +800,10 @@ class PackageKitYumBackend(PackageKitBaseBackend, PackagekitPackage):
             n = package_id
             e = v = r = a = d = None
         # search the rpmdb for the nevra
-        pkgs = self.yumbase.rpmdb.searchNevra(name=n, epoch=e, ver=v, rel=r, arch=a)
+        try:
+            pkgs = self.yumbase.rpmdb.searchNevra(name=n, epoch=e, ver=v, rel=r, arch=a)
+        except Exception, e:
+            self.error(ERROR_INTERNAL_ERROR, _to_unicode(e))
         # if the package is found, then return it (do not have to match the repo_id)
         if len(pkgs) != 0:
             return pkgs[0], True
@@ -748,6 +812,9 @@ class PackageKitYumBackend(PackageKitBaseBackend, PackagekitPackage):
             pkgs = self.yumbase.pkgSack.searchNevra(name=n, epoch=e, ver=v, rel=r, arch=a)
         except yum.Errors.RepoError, e:
             self.error(ERROR_REPO_NOT_AVAILABLE, _to_unicode(e))
+        except Exception, e:
+            self.error(ERROR_INTERNAL_ERROR, _to_unicode(e))
+
         # nothing found
         if len(pkgs) == 0:
             return None, False
@@ -784,7 +851,10 @@ class PackageKitYumBackend(PackageKitBaseBackend, PackagekitPackage):
                 if not grp.installed:
                     self.error(ERROR_PACKAGE_NOT_INSTALLED, "The Group %s is not installed" % grp.groupid)
                 else:
-                    txmbrs = self.yumbase.groupRemove(grp.groupid)
+                    try:
+                        txmbrs = self.yumbase.groupRemove(grp.groupid)
+                    except Exception, e:
+                        self.error(ERROR_INTERNAL_ERROR, _to_unicode(e))
                     for txmbr in self.yumbase.tsInfo:
                         deps_list.append(txmbr.po)
             else:
@@ -792,12 +862,18 @@ class PackageKitYumBackend(PackageKitBaseBackend, PackagekitPackage):
                 # This simulates the removal of the package
                 if inst and pkg:
                     resolve_list.append(pkg)
-                    txmbrs = self.yumbase.remove(po=pkg)
+                    try:
+                        txmbrs = self.yumbase.remove(po=pkg)
+                    except Exception, e:
+                        self.error(ERROR_INTERNAL_ERROR, _to_unicode(e))
             percentage += bump
 
         # do the depsolve to pull in deps
         if len(self.yumbase.tsInfo) > 0  and recursive:
-            rc, msgs =  self.yumbase.buildTransaction()
+            try:
+                rc, msgs =  self.yumbase.buildTransaction()
+            except Exception, e:
+                self.error(ERROR_INTERNAL_ERROR, _to_unicode(e))
             if rc != 2:
                 self.error(ERROR_DEP_RESOLUTION_FAILED, _format_msgs(msgs))
             else:
@@ -818,7 +894,11 @@ class PackageKitYumBackend(PackageKitBaseBackend, PackagekitPackage):
 
     def _is_inst(self, pkg):
         # search only for requested arch
-        return self.yumbase.rpmdb.installed(po=pkg)
+        try:
+            ret = self.yumbase.rpmdb.installed(po=pkg)
+        except Exception, e:
+            self.error(ERROR_INTERNAL_ERROR, _to_unicode(e))
+        return ret
 
     def _is_inst_arch(self, pkg):
         # search for a requested arch first
@@ -837,7 +917,10 @@ class PackageKitYumBackend(PackageKitBaseBackend, PackagekitPackage):
 
         """check if the package is reasonably installable, true/false"""
 
-        exactarchlist = self.yumbase.conf.exactarchlist
+        try:
+            exactarchlist = self.yumbase.conf.exactarchlist
+        except Exception, e:
+            self.error(ERROR_INTERNAL_ERROR, _to_unicode(e))
         # we look through each returned possibility and rule out the
         # ones that we obviously can't use
 
@@ -845,7 +928,10 @@ class PackageKitYumBackend(PackageKitBaseBackend, PackagekitPackage):
             return False
 
         # everything installed that matches the name
-        installedByKey = self.yumbase.rpmdb.searchNevra(name=pkg.name, arch=pkg.arch)
+        try:
+            installedByKey = self.yumbase.rpmdb.searchNevra(name=pkg.name, arch=pkg.arch)
+        except Exception, e:
+            self.error(ERROR_INTERNAL_ERROR, _to_unicode(e))
         comparable = []
         for instpo in installedByKey:
             if rpmUtils.arch.isMultiLibArch(instpo.arch) == rpmUtils.arch.isMultiLibArch(pkg.arch):
@@ -872,8 +958,13 @@ class PackageKitYumBackend(PackageKitBaseBackend, PackagekitPackage):
                                    # this is where we could handle setting
                                    # it to be an 'oldpackage' revert.
 
-                    if ematch and self.yumbase.allowedMultipleInstalls(pkg):
-                        return True
+                    if ematch:
+                        try:
+                            ret = self.yumbase.allowedMultipleInstalls(pkg)
+                        except Exception, e:
+                            self.error(ERROR_INTERNAL_ERROR, _to_unicode(e))
+                        if ret:
+                            return True
 
         else: # we've not got any installed that match n or n+a
             return True
@@ -889,7 +980,10 @@ class PackageKitYumBackend(PackageKitBaseBackend, PackagekitPackage):
         # first try and find the highest EVR package that is already installed
         for pkgi in pkglist:
             n, a, e, v, r = pkgi.pkgtup
-            pkgs = self.yumbase.rpmdb.searchNevra(name=n, epoch=e, ver=v, arch=a)
+            try:
+                pkgs = self.yumbase.rpmdb.searchNevra(name=n, epoch=e, ver=v, arch=a)
+            except Exception, e:
+                self.error(ERROR_INTERNAL_ERROR, _to_unicode(e))
             for pkg in pkgs:
                 if best:
                     if pkg.EVR > best.EVR:
@@ -916,7 +1010,10 @@ class PackageKitYumBackend(PackageKitBaseBackend, PackagekitPackage):
         deps_list = []
 
         # get the dep list
-        results = self.yumbase.findDeps(pkgs)
+        try:
+            results = self.yumbase.findDeps(pkgs)
+        except Exception, e:
+            self.error(ERROR_INTERNAL_ERROR, _to_unicode(e))
         require_list = []
         recursive_list = []
 
@@ -952,16 +1049,28 @@ class PackageKitYumBackend(PackageKitBaseBackend, PackagekitPackage):
         is installed
         '''
         if not grp.installed:
-            txmbrs = self.yumbase.selectGroup(grp.groupid)
+            try:
+                txmbrs = self.yumbase.selectGroup(grp.groupid)
+            except Exception, e:
+                self.error(ERROR_INTERNAL_ERROR, _to_unicode(e))
         else:
-            txmbrs = self.yumbase.groupRemove(grp.groupid)
+            try:
+                txmbrs = self.yumbase.groupRemove(grp.groupid)
+            except Exception, e:
+                self.error(ERROR_INTERNAL_ERROR, _to_unicode(e))
         pkgs = []
         for t in txmbrs:
             pkgs.append(t.po)
         if not grp.installed:
-            self.yumbase.deselectGroup(grp.groupid)
+            try:
+                self.yumbase.deselectGroup(grp.groupid)
+            except Exception, e:
+                self.error(ERROR_INTERNAL_ERROR, _to_unicode(e))
         else:
-            self.yumbase.groupUnremove(grp.groupid)
+            try:
+                self.yumbase.groupUnremove(grp.groupid)
+            except Exception, e:
+                self.error(ERROR_INTERNAL_ERROR, _to_unicode(e))
         return pkgs
 
     def _get_depends_not_installed(self, fltlist, package_ids, recursive):
@@ -982,7 +1091,10 @@ class PackageKitYumBackend(PackageKitBaseBackend, PackagekitPackage):
                 if grp.installed:
                     self.error(ERROR_PACKAGE_ALREADY_INSTALLED, "The Group %s is already installed" % grp.groupid)
                 else:
-                    txmbrs = self.yumbase.selectGroup(grp.groupid)
+                    try:
+                        txmbrs = self.yumbase.selectGroup(grp.groupid)
+                    except Exception, e:
+                        self.error(ERROR_INTERNAL_ERROR, _to_unicode(e))
                     for txmbr in self.yumbase.tsInfo:
                         deps_list.append(txmbr.po)
             else:
@@ -990,11 +1102,17 @@ class PackageKitYumBackend(PackageKitBaseBackend, PackagekitPackage):
                 # This simulates the addition of the package
                 if not inst and pkg:
                     resolve_list.append(pkg)
-                    txmbrs = self.yumbase.install(po=pkg)
+                    try:
+                        txmbrs = self.yumbase.install(po=pkg)
+                    except Exception, e:
+                        self.error(ERROR_INTERNAL_ERROR, _to_unicode(e))
             percentage += bump
 
         if len(self.yumbase.tsInfo) > 0 and recursive:
-            rc, msgs =  self.yumbase.buildTransaction()
+            try:
+                rc, msgs =  self.yumbase.buildTransaction()
+            except Exception, e:
+                self.error(ERROR_INTERNAL_ERROR, _to_unicode(e))
             if rc != 2:
                 self.error(ERROR_DEP_RESOLUTION_FAILED, _format_msgs(msgs))
             else:
@@ -1105,6 +1223,8 @@ class PackageKitYumBackend(PackageKitBaseBackend, PackagekitPackage):
             txmbr = self.yumbase.update() # Add all updates to Transaction
         except yum.Errors.RepoError, e:
             self.error(ERROR_REPO_NOT_AVAILABLE, _to_unicode(e))
+        except Exception, e:
+            self.error(ERROR_INTERNAL_ERROR, _to_unicode(e))
         if txmbr:
             self._runYumTransaction(allow_skip_broken=True)
         else:
@@ -1144,7 +1264,10 @@ class PackageKitYumBackend(PackageKitBaseBackend, PackagekitPackage):
 
             self.percentage(95)
             # Setup categories/groups
-            self.yumbase.doGroupSetup()
+            try:
+                self.yumbase.doGroupSetup()
+            except Exception, e:
+                self.error(ERROR_INTERNAL_ERROR, _to_unicode(e))
             #we might have a rounding error
             self.percentage(100)
 
@@ -1156,6 +1279,8 @@ class PackageKitYumBackend(PackageKitBaseBackend, PackagekitPackage):
                 self.error(ERROR_REPO_CONFIGURATION_ERROR, message)
         except yum.Errors.YumBaseError, e:
             self.error(ERROR_UNKNOWN, "cannot refresh cache: %s" % _to_unicode(e))
+        except Exception, e:
+            self.error(ERROR_INTERNAL_ERROR, _to_unicode(e))
 
         # update the comps groups too
         self.comps.refresh()
@@ -1167,14 +1292,20 @@ class PackageKitYumBackend(PackageKitBaseBackend, PackagekitPackage):
         self._check_init(lazy_cache=True)
         self.allow_cancel(True)
         self.percentage(None)
-        self.yumbase.doConfigSetup(errorlevel=0, debuglevel=0)# Setup Yum Config
+        try:
+            self.yumbase.doConfigSetup(errorlevel=0, debuglevel=0)# Setup Yum Config
+        except Exception, e:
+            self.error(ERROR_INTERNAL_ERROR, _to_unicode(e))
         self.yumbase.conf.cache = 0 # TODO: can we just look in the cache?
         self.status(STATUS_QUERY)
 
         fltlist = filters.split(';')
         for package in packages:
             # Get installed packages
-            installedByKey = self.yumbase.rpmdb.searchNevra(name=package)
+            try:
+                installedByKey = self.yumbase.rpmdb.searchNevra(name=package)
+            except Exception, e:
+                self.error(ERROR_INTERNAL_ERROR, _to_unicode(e))
             if FILTER_NOT_INSTALLED not in fltlist:
                 for pkg in installedByKey:
                     self._show_package(pkg, INFO_INSTALLED)
@@ -1184,6 +1315,8 @@ class PackageKitYumBackend(PackageKitBaseBackend, PackagekitPackage):
                     pkgs = self.yumbase.pkgSack.returnNewestByNameArch()
                 except yum.Errors.RepoError, e:
                     self.error(ERROR_NO_CACHE, _to_unicode(e))
+                except Exception, e:
+                    self.error(ERROR_INTERNAL_ERROR, _to_unicode(e))
                 else:
                     for pkg in pkgs:
                         if pkg.name == package:
@@ -1212,9 +1345,15 @@ class PackageKitYumBackend(PackageKitBaseBackend, PackagekitPackage):
             if grp:
                 if grp.installed:
                     self.error(ERROR_PACKAGE_ALREADY_INSTALLED, "This Group %s is already installed" % grp.groupid)
-                txmbr = self.yumbase.selectGroup(grp.groupid)
+                try:
+                    txmbr = self.yumbase.selectGroup(grp.groupid)
+                except Exception, e:
+                    self.error(ERROR_INTERNAL_ERROR, _to_unicode(e))
                 for t in txmbr:
-                    repo = self.yumbase.repos.getRepo(t.po.repoid)
+                    try:
+                        repo = self.yumbase.repos.getRepo(t.po.repoid)
+                    except Exception, e:
+                        self.error(ERROR_INTERNAL_ERROR, _to_unicode(e))
                     if not already_warned and not repo.gpgcheck:
                         self.message(MESSAGE_UNTRUSTED_PACKAGE, "The untrusted package %s will be installed from %s." % (t.po.name, repo))
                         already_warned = True
@@ -1237,7 +1376,10 @@ class PackageKitYumBackend(PackageKitBaseBackend, PackagekitPackage):
             self.error(ERROR_PACKAGE_ALREADY_INSTALLED, "The packages failed to be installed")
 
     def _checkForNewer(self, po):
-        pkgs = self.yumbase.pkgSack.returnNewestByName(name=po.name)
+        try:
+            pkgs = self.yumbase.pkgSack.returnNewestByName(name=po.name)
+        except Exception, e:
+            self.error(ERROR_INTERNAL_ERROR, _to_unicode(e))
         if pkgs:
             newest = pkgs[0]
             if newest.EVR > po.EVR:
@@ -1357,10 +1499,14 @@ class PackageKitYumBackend(PackageKitBaseBackend, PackagekitPackage):
                     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)
+                except Exception, e:
+                    self.error(ERROR_INTERNAL_ERROR, _to_unicode(e))
                 try:
                     self.yumbase._checkSignatures([po], None)
                 except yum.Errors.YumGPGCheckError, e:
                     self.error(ERROR_MISSING_GPG_SIGNATURE, _to_unicode(e))
+                except Exception, e:
+                    self.error(ERROR_INTERNAL_ERROR, _to_unicode(e))
         else:
             self.yumbase.conf.gpgcheck = 0
 
@@ -1372,7 +1518,10 @@ class PackageKitYumBackend(PackageKitBaseBackend, PackagekitPackage):
         txmbrs = []
         try:
             for inst_file in inst_files:
-                txmbr = self.yumbase.installLocal(inst_file)
+                try:
+                    txmbr = self.yumbase.installLocal(inst_file)
+                except Exception, e:
+                    self.error(ERROR_INTERNAL_ERROR, _to_unicode(e))
                 if txmbr:
                     txmbrs.extend(txmbr)
                     self._checkForNewer(txmbr[0].po)
@@ -1394,7 +1543,10 @@ class PackageKitYumBackend(PackageKitBaseBackend, PackagekitPackage):
                     repo.disable()
 
                 for inst_file in inst_files:
-                    txmbr = self.yumbase.installLocal(inst_file)
+                    try:
+                        txmbr = self.yumbase.installLocal(inst_file)
+                    except Exception, e:
+                        self.error(ERROR_INTERNAL_ERROR, _to_unicode(e))
                     if txmbr:
                         txmbrs.extend(txmbr)
                         if len(self.yumbase.tsInfo) > 0:
@@ -1405,6 +1557,8 @@ class PackageKitYumBackend(PackageKitBaseBackend, PackagekitPackage):
                         self.error(ERROR_LOCAL_INSTALL_FAILED, "Can't install %s" % inst_file)
             except yum.Errors.InstallError, e:
                 self.error(ERROR_LOCAL_INSTALL_FAILED, _to_unicode(e))
+            except Exception, e:
+                self.error(ERROR_INTERNAL_ERROR, _to_unicode(e))
         shutil.rmtree(tempdir)
 
     def _check_local_file(self, pkg):
@@ -1418,6 +1572,9 @@ class PackageKitYumBackend(PackageKitBaseBackend, PackagekitPackage):
         except yum.Errors.MiscError:
             self.error(ERROR_INVALID_PACKAGE_FILE, "%s does not appear to be a valid package." % pkg)
             return False
+        except Exception, e:
+            self.error(ERROR_INTERNAL_ERROR, _to_unicode(e))
+            return False
 
         if self._is_inst_arch(po):
             self.error(ERROR_PACKAGE_ALREADY_INSTALLED, "The package %s is already installed" % str(po))
@@ -1446,10 +1603,15 @@ class PackageKitYumBackend(PackageKitBaseBackend, PackagekitPackage):
             for package in package_ids:
                 pkg, inst = self._findPackage(package)
                 if pkg:
-                    txmbr = self.yumbase.update(po=pkg)
+                    try:
+                        txmbr = self.yumbase.update(po=pkg)
+                    except Exception, e:
+                        self.error(ERROR_INTERNAL_ERROR, _to_unicode(e))
                     txmbrs.extend(txmbr)
         except yum.Errors.RepoError, e:
             self.error(ERROR_REPO_NOT_AVAILABLE, _to_unicode(e))
+        except Exception, e:
+            self.error(ERROR_INTERNAL_ERROR, _to_unicode(e))
         if txmbrs:
             self._runYumTransaction(allow_skip_broken=True)
         else:
@@ -1566,12 +1728,18 @@ class PackageKitYumBackend(PackageKitBaseBackend, PackagekitPackage):
             if grp:
                 if not grp.installed:
                     self.error(ERROR_PACKAGE_NOT_INSTALLED, "This Group %s is not installed" % grp.groupid)
-                txmbr = self.yumbase.groupRemove(grp.groupid)
+                try:
+                    txmbr = self.yumbase.groupRemove(grp.groupid)
+                except Exception, e:
+                    self.error(ERROR_INTERNAL_ERROR, _to_unicode(e))
                 txmbrs.extend(txmbr)
             else:
                 pkg, inst = self._findPackage(package)
                 if pkg and inst:
-                    txmbr = self.yumbase.remove(po=pkg)
+                    try:
+                        txmbr = self.yumbase.remove(po=pkg)
+                    except Exception, e:
+                        self.error(ERROR_INTERNAL_ERROR, _to_unicode(e))
                     txmbrs.extend(txmbr)
                 if pkg and not inst:
                     self.error(ERROR_PACKAGE_NOT_INSTALLED, "The package %s is not installed" % pkg.name)
@@ -1669,7 +1837,10 @@ class PackageKitYumBackend(PackageKitBaseBackend, PackagekitPackage):
         self.status(STATUS_QUERY)
 
         # is preupgrade installed?
-        pkgs = self.yumbase.rpmdb.searchNevra(name='preupgrade')
+        try:
+            pkgs = self.yumbase.rpmdb.searchNevra(name='preupgrade')
+        except Exception, e:
+            self.error(ERROR_INTERNAL_ERROR, _to_unicode(e))
         if len(pkgs) == 0:
 
             # find preupgrade, which may not exist
@@ -1678,6 +1849,9 @@ class PackageKitYumBackend(PackageKitBaseBackend, PackagekitPackage):
             except yum.Errors.PackageSackError, e:
                 self.error(ERROR_NO_DISTRO_UPGRADE_DATA, "Could not find preupgrade package in any enabled repos")
                 return
+            except Exception, e:
+                self.error(ERROR_INTERNAL_ERROR, _to_unicode(e))
+                return
 
             # shouldn't happen
             if len(pkgs) == 0:
@@ -1687,7 +1861,10 @@ class PackageKitYumBackend(PackageKitBaseBackend, PackagekitPackage):
             # we can have more than one result if the package is in multiple repos, for example
             # a machine with i386 _and_ x86_64 configured.
             # in this case, just pick the first entry as they are both noarch
-            txmbr = self.yumbase.install(po=pkgs[0])
+            try:
+                txmbr = self.yumbase.install(po=pkgs[0])
+            except Exception, e:
+                self.error(ERROR_INTERNAL_ERROR, _to_unicode(e))
             if txmbr:
                 self._runYumTransaction()
             else:
@@ -1702,13 +1879,18 @@ class PackageKitYumBackend(PackageKitBaseBackend, PackagekitPackage):
                 pkgs = self.yumbase.pkgSack.returnNewestByName(name='preupgrade')
             except yum.Errors.PackageSackError, e:
                 # could not find upgraded preupgrade package in any enabled repos
-                pass;
+                pass
+            except Exception, e:
+                self.error(ERROR_INTERNAL_ERROR, _to_unicode(e))
             else:
                 if pkgs:
                     newest = pkgs[0]
                     if newest.EVR > po.EVR:
                         # need to update preupgrade package
-                        txmbr = self.yumbase.update(po=pkgs[0])
+                        try:
+                            txmbr = self.yumbase.update(po=pkgs[0])
+                        except Exception, e:
+                            self.error(ERROR_INTERNAL_ERROR, _to_unicode(e))
                         if txmbr:
                             self._runYumTransaction()
         else:
@@ -1734,7 +1916,10 @@ class PackageKitYumBackend(PackageKitBaseBackend, PackagekitPackage):
             self.error(ERROR_FAILED_CONFIG_PARSING, "could not get latest distro data")
 
         # are we already on the latest version
-        present_version = self.yumbase.conf.yumvar['releasever']
+        try:
+            present_version = self.yumbase.conf.yumvar['releasever']
+        except Exception, e:
+            self.error(ERROR_INTERNAL_ERROR, _to_unicode(e))
         if (present_version >= last_version):
             return
 
@@ -1768,6 +1953,8 @@ class PackageKitYumBackend(PackageKitBaseBackend, PackagekitPackage):
             pkgs.extend(ygl.obsoletes)
         except yum.Errors.RepoError, e:
             self.error(ERROR_REPO_NOT_AVAILABLE, _to_unicode(e))
+        except Exception, e:
+            self.error(ERROR_INTERNAL_ERROR, _to_unicode(e))
         md = self.updateMetadata
         for pkg in pkgs:
             if pkgfilter.pre_process(pkg):
@@ -1800,6 +1987,8 @@ class PackageKitYumBackend(PackageKitBaseBackend, PackagekitPackage):
 
         except yum.Errors.RepoError, e:
             self.error(ERROR_REPO_NOT_FOUND, _to_unicode(e))
+        except Exception, e:
+            self.error(ERROR_INTERNAL_ERROR, _to_unicode(e))
 
     def get_repo_list(self, filters):
         '''
@@ -1809,7 +1998,12 @@ class PackageKitYumBackend(PackageKitBaseBackend, PackagekitPackage):
         self.yumbase.conf.cache = 0 # Allow new files
         self.status(STATUS_INFO)
 
-        for repo in self.yumbase.repos.repos.values():
+        try:
+            repos = self.yumbase.repos.repos.values()
+        except Exception, e:
+            self.error(ERROR_INTERNAL_ERROR, _to_unicode(e))
+            return
+        for repo in repos:
             if filters != FILTER_NOT_DEVELOPMENT or not _is_development_repo(repo.id):
                 if repo.isEnabled():
                     self.repo_detail(repo.id, repo.name, 'true')
@@ -1825,12 +2019,15 @@ class PackageKitYumBackend(PackageKitBaseBackend, PackagekitPackage):
                 if obsoleting[0] == name:
                     pkg =  self.yumbase.rpmdb.searchPkgTuple(installed)[0]
                     return self._pkg_to_id(pkg)
-        except:
+        except Exception, e:
             pass # no obsolete data - fd#17528
         return ""
 
     def _get_updated(self, pkg):
-        pkgs = self.yumbase.rpmdb.searchNevra(name=pkg.name, arch=pkg.arch)
+        try:
+            pkgs = self.yumbase.rpmdb.searchNevra(name=pkg.name, arch=pkg.arch)
+        except Exception, e:
+            self.error(ERROR_INTERNAL_ERROR, _to_unicode(e))
         if pkgs:
             return self._pkg_to_id(pkgs[0])
         else:
@@ -1842,7 +2039,7 @@ class PackageKitYumBackend(PackageKitBaseBackend, PackagekitPackage):
             for repo in self.yumbase.repos.listEnabled():
                 try:
                     self._updateMetadata.add(repo)
-                except:
+                except Exception, e:
                     pass # No updateinfo.xml.gz in repo
         return self._updateMetadata
 
@@ -1920,7 +2117,10 @@ class PackageKitYumBackend(PackageKitBaseBackend, PackagekitPackage):
         self._check_init()
         self.yumbase.conf.cache = 0 # Allow new files
         # Get the repo
-        repo = self.yumbase.repos.getRepo(repoid)
+        try:
+            repo = self.yumbase.repos.getRepo(repoid)
+        except Exception, e:
+            self.error(ERROR_INTERNAL_ERROR, _to_unicode(e))
         if repo:
             repo.cfg.set(repoid, parameter, value)
             try:
@@ -1954,6 +2154,8 @@ class PackageKitYumBackend(PackageKitBaseBackend, PackagekitPackage):
                     self.yumbase.getKeyForPackage(pkg, askcb = lambda x, y, z: True)
                 except yum.Errors.YumBaseError, e:
                     self.error(ERROR_UNKNOWN, "cannot install signature: %s" % str(e))
+                except Exception, e:
+                    self.error(ERROR_INTERNAL_ERROR, _to_unicode(e))
                 except:
                     self.error(ERROR_GPG_FAILURE, "Error importing GPG Key for %s" % pkg)
 
@@ -1985,12 +2187,17 @@ class PackageKitYumBackend(PackageKitBaseBackend, PackagekitPackage):
                 self.yumbase.repos.doSetup()
             except yum.Errors.RepoError, e:
                 self.error(ERROR_NO_CACHE, _to_unicode(e))
+            except Exception, e:
+                self.error(ERROR_INTERNAL_ERROR, _to_unicode(e))
 
     def _refresh_yum_cache(self):
         self.status(STATUS_REFRESH_CACHE)
         old_cache_setting = self.yumbase.conf.cache
         self.yumbase.conf.cache = 0
-        self.yumbase.repos.setCache(0)
+        try:
+            self.yumbase.repos.setCache(0)
+        except Exception, e:
+            self.error(ERROR_INTERNAL_ERROR, _to_unicode(e))
 
         try:
             self.yumbase.repos.populateSack(mdtype='metadata', cacheonly=1)
@@ -1998,9 +2205,14 @@ class PackageKitYumBackend(PackageKitBaseBackend, PackagekitPackage):
             self.yumbase.repos.populateSack(mdtype='otherdata', cacheonly=1)
         except yum.Errors.RepoError, e:
             self.error(ERROR_REPO_NOT_AVAILABLE, _to_unicode(e))
+        except Exception, e:
+            self.error(ERROR_INTERNAL_ERROR, _to_unicode(e))
 
         self.yumbase.conf.cache = old_cache_setting
-        self.yumbase.repos.setCache(old_cache_setting)
+        try:
+            self.yumbase.repos.setCache(old_cache_setting)
+        except Exception, e:
+            self.error(ERROR_INTERNAL_ERROR, _to_unicode(e))
 
     def _setup_yum(self):
         try:
diff --git a/backends/yum/yumComps.py b/backends/yum/yumComps.py
index fedc171..9c77785 100755
--- a/backends/yum/yumComps.py
+++ b/backends/yum/yumComps.py
@@ -259,6 +259,8 @@ class yumComps:
             cats = self.yumbase.comps.categories
         except yum.Errors.RepoError, e:
             return False
+        except Exception, e:
+            return False
         if self.yumbase.comps.compscount == 0:
             return False
 
commit f82515bba8bae30174143f25c59cddf783a7a3eb
Author: Richard Hughes <richard at hughsie.com>
Date:   Thu Dec 4 09:55:03 2008 +0000

    trivial: add another ignore type to pylint

diff --git a/lib/python/packagekit/pylint.sh b/lib/python/packagekit/pylint.sh
index 95b6d61..8c4e52f 100755
--- a/lib/python/packagekit/pylint.sh
+++ b/lib/python/packagekit/pylint.sh
@@ -1 +1 @@
-pylint --disable-msg=W0614,C0301,C0103,W0613,C0111,R0913,R0904,R0903,C0302,W0401,R0912,R0914,R0911,R0915,R0902,W0612 $1
+pylint --disable-msg=W0614,C0301,C0103,W0613,C0111,R0913,R0904,R0903,C0302,W0401,R0912,R0914,R0911,R0915,R0902,W0612,W0703 $1
commit ddcd689d34ac397fb8b879e890d045dd87ccc291
Author: Richard Hughes <richard at hughsie.com>
Date:   Tue Dec 2 16:21:24 2008 +0000

    yum: make sure we call doObsoletes explicitly when we get the ObsoletesTuples

diff --git a/backends/yum/yumBackend.py b/backends/yum/yumBackend.py
index 04424b7..657cdcd 100755
--- a/backends/yum/yumBackend.py
+++ b/backends/yum/yumBackend.py
@@ -1818,6 +1818,8 @@ class PackageKitYumBackend(PackageKitBaseBackend, PackagekitPackage):
 
     def _get_obsoleted(self, name):
         try:
+            # make sure yum doesn't explode in some internal fit of rage
+            self.yumbase.up.doObsoletes()
             obsoletes = self.yumbase.up.getObsoletesTuples(newest=1)
             for (obsoleting, installed) in obsoletes:
                 if obsoleting[0] == name:


More information about the PackageKit-commit mailing list