[packagekit] packagekit: Branch 'master' - 16 commits

Richard Hughes hughsient at kemper.freedesktop.org
Wed Nov 21 15:24:55 PST 2007


 backends/dummy/pk-backend-dummy.c |    2 
 backends/zypp/.gitignore          |   10 ++
 backends/zypp/pk-backend-zypp.cpp |  186 ++++++++++++++++++++++++--------------
 configure.ac                      |    1 
 docs/pk-introduction.xml          |   32 ++++++
 html/pk-faq.html                  |    4 
 libpackagekit/pk-client.c         |   36 +++++++
 libpackagekit/pk-common.c         |   76 +++++++++++++++
 libpackagekit/pk-common.h         |    2 
 libpackagekit/pk-enum.c           |   26 +++++
 libpackagekit/pk-enum.h           |   11 ++
 python/packagekit/frontend.py     |    4 
 src/pk-backend.c                  |   86 ++++++++++++-----
 src/pk-backend.h                  |    3 
 src/pk-engine.c                   |   38 +++++++
 src/pk-interface.xml              |    7 +
 src/pk-self-test.c                |    2 
 src/pk-transaction-db.c           |  181 +++++++++++++++++++++++++++++++++++-
 src/pk-transaction-db.h           |    4 
 19 files changed, 604 insertions(+), 107 deletions(-)

New commits:
commit f583b4e4e6fb045cf95eb1177a95a682921a686f
Author: Richard Hughes <richard at hughsie.com>
Date:   Wed Nov 21 23:21:37 2007 +0000

    add some initial code to get the action time since the last run. unconnected, but unit tested

diff --git a/src/pk-self-test.c b/src/pk-self-test.c
index 5adbac1..9f0b3fd 100644
--- a/src/pk-self-test.c
+++ b/src/pk-self-test.c
@@ -30,6 +30,7 @@ void libst_inhibit (LibSelfTest *test);
 void libst_spawn (LibSelfTest *test);
 void libst_thread_list (LibSelfTest *test);
 void libst_transaction_list (LibSelfTest *test);
+void libst_transaction_db (LibSelfTest *test);
 void libst_security (LibSelfTest *test);
 void libst_time (LibSelfTest *test);
 void libst_backend (LibSelfTest *test);
@@ -57,6 +58,7 @@ main (int argc, char **argv)
 	libst_spawn (&test);
 	libst_thread_list (&test);
 	libst_transaction_list (&test);
+	libst_transaction_db (&test);
 
 	return (libst_finish (&test));
 }
diff --git a/src/pk-transaction-db.c b/src/pk-transaction-db.c
index af3633d..e995b79 100644
--- a/src/pk-transaction-db.c
+++ b/src/pk-transaction-db.c
@@ -203,6 +203,103 @@ pk_transaction_db_sql_statement (PkTransactionDb *tdb, const gchar *sql)
 }
 
 /**
+ * pk_time_action_sqlite_callback:
+ **/
+static gint
+pk_time_action_sqlite_callback (void *data, gint argc, gchar **argv, gchar **col_name)
+{
+	gint i;
+	gchar *col;
+	gchar *value;
+	gchar **timespec = (gchar**) data;
+
+	for (i=0; i<argc; i++) {
+		col = col_name[i];
+		value = argv[i];
+		if (pk_strequal (col, "timespec") == TRUE) {
+			*timespec = g_strdup (value);
+		} else {
+			pk_warning ("%s = %s\n", col, value);
+		}
+	}
+	return 0;
+}
+
+/**
+ * pk_transaction_db_action_time_since:
+ **/
+guint
+pk_transaction_db_action_time_since (PkTransactionDb *tdb, PkRoleEnum role)
+{
+	gchar *error_msg = NULL;
+	gint rc;
+	const gchar *role_text;
+	gchar *statement;
+	gchar *timespec = NULL;
+	guint time;
+
+	g_return_val_if_fail (tdb != NULL, 0);
+	g_return_val_if_fail (PK_IS_TRANSACTION_DB (tdb), 0);
+
+	role_text = pk_role_enum_to_text (role);
+	pk_debug ("get_time_since_action=%s", role_text);
+
+	statement = g_strdup_printf ("SELECT timespec FROM last_action WHERE role = '%s'", role_text);
+	rc = sqlite3_exec (tdb->priv->db, statement, pk_time_action_sqlite_callback, &timespec, &error_msg);
+	g_free (statement);
+	if (rc != SQLITE_OK) {
+		pk_warning ("SQL error: %s\n", error_msg);
+		sqlite3_free (error_msg);
+		return 0;
+	}
+	if (timespec == NULL) {
+		pk_warning ("no response, assume zero");
+		return 0;
+	}
+
+	/* work out the difference */
+	time = pk_iso8601_difference (timespec);
+	pk_debug ("timespec=%s, difference=%i", timespec, time);
+	g_free (timespec);
+
+	return time;
+}
+
+/**
+ * pk_transaction_db_action_time_reset:
+ **/
+gboolean
+pk_transaction_db_action_time_reset (PkTransactionDb *tdb, PkRoleEnum role)
+{
+	gchar *error_msg = NULL;
+	gint rc;
+	const gchar *role_text;
+	gchar *statement;
+	gchar *timespec;
+
+	g_return_val_if_fail (tdb != NULL, FALSE);
+	g_return_val_if_fail (PK_IS_TRANSACTION_DB (tdb), FALSE);
+
+	timespec = pk_iso8601_present ();
+	role_text = pk_role_enum_to_text (role);
+	pk_debug ("reset action time=%s to %s", role_text, timespec);
+
+	statement = g_strdup_printf ("UPDATE last_action SET timespec = '%s' WHERE role = '%s'", timespec, role_text);
+	rc = sqlite3_exec (tdb->priv->db, statement, NULL, NULL, &error_msg);
+	g_free (timespec);
+	g_free (statement);
+
+	/* did we fail? */
+	if (rc != SQLITE_OK) {
+		pk_warning ("SQL error: %s\n", error_msg);
+		sqlite3_free (error_msg);
+		return FALSE;
+	}
+
+	return TRUE;
+}
+
+/**
  * pk_transaction_db_get_list:
  **/
 gboolean
@@ -232,7 +329,6 @@ pk_transaction_db_get_list (PkTransactionDb *tdb, guint limit)
 gboolean
 pk_transaction_db_add (PkTransactionDb *tdb, const gchar *tid)
 {
-	GTimeVal timeval;
 	gchar *timespec;
 	gchar *statement;
 
@@ -241,11 +337,7 @@ pk_transaction_db_add (PkTransactionDb *tdb, const gchar *tid)
 
 	pk_debug ("adding transaction %s", tid);
 
-	/* get current time */
-	g_get_current_time (&timeval);
-	timespec = g_time_val_to_iso8601 (&timeval);
-	pk_debug ("timespec=%s", timespec);
-
+	timespec = pk_iso8601_present ();
 	statement = g_strdup_printf ("INSERT INTO transactions (transaction_id, timespec) VALUES ('%s', '%s')", tid, timespec);
 	pk_transaction_db_sql_statement (tdb, statement);
 	g_free (statement);
@@ -363,6 +455,34 @@ pk_transaction_db_empty (PkTransactionDb *tdb)
 }
 
 /**
+ * pk_transaction_db_create_table_last_action:
+ **/
+static gboolean
+pk_transaction_db_create_table_last_action (PkTransactionDb *tdb)
+{
+	const gchar *role_text;
+	gchar *statement;
+	gchar *timespec;
+	guint i;
+
+	g_return_val_if_fail (tdb != NULL, FALSE);
+	g_return_val_if_fail (PK_IS_TRANSACTION_DB (tdb), FALSE);
+
+	timespec = pk_iso8601_present ();
+	statement = "CREATE TABLE last_action (role TEXT primary key, timespec TEXT);";
+	sqlite3_exec (tdb->priv->db, statement, NULL, 0, NULL);
+	for (i=0; i<PK_ROLE_ENUM_UNKNOWN; i++) {
+		role_text = pk_role_enum_to_text (i);
+		/* reset to now if the role does not exist */
+		statement = g_strdup_printf ("INSERT INTO last_action (role, timespec) VALUES ('%s', '%s')", role_text, timespec);
+		sqlite3_exec (tdb->priv->db, statement, NULL, 0, NULL);
+		g_free (statement);
+	}
+	g_free (timespec);
+	return TRUE;
+}
+
+/**
  * pk_transaction_db_init:
  **/
 static void
@@ -399,6 +519,9 @@ pk_transaction_db_init (PkTransactionDb *tdb)
 			sqlite3_exec (tdb->priv->db, statement, NULL, 0, NULL);
 		}
 	}
+
+	/* we might be running an old database, recreate */
+	pk_transaction_db_create_table_last_action (tdb);
 }
 
 /**
@@ -432,3 +555,49 @@ pk_transaction_db_new (void)
 	tdb = g_object_new (PK_TYPE_TRANSACTION_DB, NULL);
 	return PK_TRANSACTION_DB (tdb);
 }
+
+/***************************************************************************
+ ***                          MAKE CHECK TESTS                           ***
+ ***************************************************************************/
+#ifdef PK_BUILD_TESTS
+#include <libselftest.h>
+
+void
+libst_transaction_db (LibSelfTest *test)
+{
+	PkTransactionDb *db;
+	guint value;
+	gboolean ret;
+
+	if (libst_start (test, "PkTransactionDb", CLASS_AUTO) == FALSE) {
+		return;
+	}
+
+	db = pk_transaction_db_new ();
+
+	/************************************************************/
+	libst_title (test, "set the correct time");
+	ret = pk_transaction_db_action_time_reset (db, PK_ROLE_ENUM_REFRESH_CACHE);
+	if (ret == TRUE) {
+		libst_success (test, NULL);
+	} else {
+		libst_failed (test, "failed to reset value");
+	}
+
+	g_usleep (2000000);
+
+	/************************************************************/
+	libst_title (test, "do we get the correct time");
+	value = pk_transaction_db_action_time_since (db, PK_ROLE_ENUM_REFRESH_CACHE);
+	if (value == 2) {
+		libst_success (test, "failed to get correct time");
+	} else {
+		libst_failed (test, "failed to get correct time, %i", value);
+	}
+
+	g_object_unref (db);
+
+	libst_end (test);
+}
+#endif
+
diff --git a/src/pk-transaction-db.h b/src/pk-transaction-db.h
index 6b7900a..d6cd96c 100644
--- a/src/pk-transaction-db.h
+++ b/src/pk-transaction-db.h
@@ -65,6 +65,10 @@ gboolean	 pk_transaction_db_set_data		(PkTransactionDb	*tdb,
 							 const gchar		*data);
 gboolean	 pk_transaction_db_get_list		(PkTransactionDb	*tdb,
 							 guint			 limit);
+gboolean	 pk_transaction_db_action_time_reset	(PkTransactionDb	*tdb,
+							 PkRoleEnum		 role);
+guint		 pk_transaction_db_action_time_since	(PkTransactionDb	*tdb,
+							 PkRoleEnum		 role);
 
 G_END_DECLS
 
commit 149a8bb974b767ff96bcafd1a4fd91dfd30c357b
Author: Richard Hughes <richard at hughsie.com>
Date:   Wed Nov 21 23:06:36 2007 +0000

    add two convenience functions for iso8601 date and times

diff --git a/libpackagekit/pk-common.c b/libpackagekit/pk-common.c
index a90fe6b..76f9c8c 100644
--- a/libpackagekit/pk-common.c
+++ b/libpackagekit/pk-common.c
@@ -82,6 +82,54 @@ out:
 }
 
 /**
+ * pk_iso8601_present:
+ *
+ * Return value: The current iso8601 date and time
+ **/
+gchar *
+pk_iso8601_present (void)
+{
+	GTimeVal timeval;
+	gchar *timespec;
+
+	/* get current time */
+	g_get_current_time (&timeval);
+	timespec = g_time_val_to_iso8601 (&timeval);
+	pk_debug ("timespec=%s", timespec);
+
+	return timespec;
+}
+
+/**
+ * pk_iso8601_difference:
+ * @isodate: The ISO8601 date to compare
+ *
+ * Return value: The difference in seconds between the iso8601 date and current
+ **/
+guint
+pk_iso8601_difference (const gchar *isodate)
+{
+	GTimeVal timeval_then;
+	GTimeVal timeval_now;
+	guint time;
+
+	if (pk_strzero (isodate) == TRUE) {
+		return 0;
+	}
+
+	/* convert date */
+	g_time_val_from_iso8601 (isodate, &timeval_then);
+	g_get_current_time (&timeval_now);
+
+	/* work out difference */
+	time = timeval_now.tv_sec - timeval_then.tv_sec;
+	pk_debug ("difference=%i", time);
+
+	return time;
+}
+
+
+/**
  * pk_strvalidate_char:
  * @item: A single char to test
  *
@@ -1279,6 +1327,34 @@ libst_common (LibSelfTest *test)
 		libst_failed (test, "value is %i", uvalue);
 	}
 
+	gchar *present;
+	guint seconds;
+
+	/************************************************************
+	 **************            iso8601           ****************
+	 ************************************************************/
+	libst_title (test, "get present iso8601");
+	present = pk_iso8601_present ();
+	if (present != NULL) {
+		libst_success (test, NULL);
+	} else {
+		libst_failed (test, "present is NULL");
+	}
+
+	g_usleep (2000000);
+
+	/************************************************************/
+	libst_title (test, "get difference in iso8601");
+	seconds = pk_iso8601_difference (present);
+	if (seconds == 2) {
+		libst_success (test, NULL);
+	} else {
+		libst_failed (test, "seconds is wrong, %i", seconds);
+	}
+
+	/************************************************************/
+	g_free (present);
+
 	libst_end (test);
 }
 #endif
diff --git a/libpackagekit/pk-common.h b/libpackagekit/pk-common.h
index 9302a10..6dfbb13 100644
--- a/libpackagekit/pk-common.h
+++ b/libpackagekit/pk-common.h
@@ -56,6 +56,8 @@ gboolean	 pk_strcmp_sections			(const gchar	*id1,
 							 guint		 parts,
 							 guint		 match);
 gboolean	 pk_filter_check			(const gchar	*filter);
+gchar		*pk_iso8601_present			(void);
+guint		 pk_iso8601_difference			(const gchar	*isodate);
 
 G_END_DECLS
 
commit 5b3a1a141e09af42f937156d4e93dd7e4d0ad0b6
Author: Richard Hughes <richard at hughsie.com>
Date:   Wed Nov 21 18:53:28 2007 +0000

    add a test of message in the dummy backend

diff --git a/backends/dummy/pk-backend-dummy.c b/backends/dummy/pk-backend-dummy.c
index 59109ac..ed68746 100644
--- a/backends/dummy/pk-backend-dummy.c
+++ b/backends/dummy/pk-backend-dummy.c
@@ -173,6 +173,8 @@ backend_get_updates (PkBackend *backend)
 
 	/* only find updates one in 5 times */
 	if (number != 1) {
+		pk_backend_message (backend, PK_MESSAGE_ENUM_DAEMON,
+				    "Ignoring this GetUpdate!");
 		pk_backend_finished (backend);
 		return;
 	}
commit 2612f7211ece4d7fe571a333cdc3bdaefa49bd4a
Author: Richard Hughes <richard at hughsie.com>
Date:   Wed Nov 21 18:14:52 2007 +0000

    add the client bits for Message

diff --git a/libpackagekit/pk-client.c b/libpackagekit/pk-client.c
index d6bace6..09ee9dc 100644
--- a/libpackagekit/pk-client.c
+++ b/libpackagekit/pk-client.c
@@ -80,6 +80,7 @@ typedef enum {
 	PK_CLIENT_PROGRESS_CHANGED,
 	PK_CLIENT_UPDATES_CHANGED,
 	PK_CLIENT_REQUIRE_RESTART,
+	PK_CLIENT_MESSAGE,
 	PK_CLIENT_TRANSACTION,
 	PK_CLIENT_TRANSACTION_STATUS_CHANGED,
 	PK_CLIENT_UPDATE_DETAIL,
@@ -710,6 +711,27 @@ pk_client_require_restart_cb (DBusGProxy  *proxy,
 	}
 }
 
+/**
+ * pk_client_message_cb:
+ */
+static void
+pk_client_message_cb (DBusGProxy  *proxy, const gchar *tid,
+		      const gchar *message_text, const gchar *details, PkClient *client)
+{
+	PkMessageEnum message;
+	g_return_if_fail (client != NULL);
+	g_return_if_fail (PK_IS_CLIENT (client));
+
+	/* not us, ignore */
+	if (pk_client_should_proxy (client, tid) == FALSE) {
+		return;
+	}
+
+	message = pk_message_enum_from_text (message_text);
+	pk_debug ("emit message %i, %s", message, details);
+	g_signal_emit (client , signals [PK_CLIENT_MESSAGE], 0, message, details);
+}
+
 /******************************************************************************
  *                    TRANSACTION ID USING METHODS
  ******************************************************************************/
@@ -2494,6 +2516,11 @@ pk_client_class_init (PkClientClass *klass)
 			      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);
+	signals [PK_CLIENT_MESSAGE] =
+		g_signal_new ("message",
+			      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);
 	signals [PK_CLIENT_LOCKED] =
 		g_signal_new ("locked",
 			      G_TYPE_FROM_CLASS (object_class), G_SIGNAL_RUN_LAST,
@@ -2600,7 +2627,7 @@ pk_client_init (PkClient *client)
 	dbus_g_object_register_marshaller (pk_marshal_VOID__STRING_STRING_UINT,
 					   G_TYPE_NONE, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_UINT, G_TYPE_INVALID);
 
-	/* ErrorCode, RequireRestart */
+	/* ErrorCode, RequireRestart, Message */
 	dbus_g_object_register_marshaller (pk_marshal_VOID__STRING_STRING_STRING,
 					   G_TYPE_NONE, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_INVALID);
 
@@ -2712,6 +2739,11 @@ pk_client_init (PkClient *client)
 	dbus_g_proxy_connect_signal (proxy, "RequireRestart",
 				     G_CALLBACK (pk_client_require_restart_cb), client, NULL);
 
+	dbus_g_proxy_add_signal (proxy, "Message",
+				 G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_INVALID);
+	dbus_g_proxy_connect_signal (proxy, "Message",
+				     G_CALLBACK (pk_client_message_cb), client, NULL);
+
 	dbus_g_proxy_add_signal (proxy, "CallerActiveChanged",
 				 G_TYPE_STRING, G_TYPE_BOOLEAN, G_TYPE_INVALID);
 	dbus_g_proxy_connect_signal (proxy, "CallerActiveChanged",
@@ -2765,6 +2797,8 @@ pk_client_finalize (GObject *object)
 				        G_CALLBACK (pk_client_error_code_cb), client);
 	dbus_g_proxy_disconnect_signal (client->priv->proxy, "RequireRestart",
 				        G_CALLBACK (pk_client_require_restart_cb), client);
+	dbus_g_proxy_disconnect_signal (client->priv->proxy, "Message",
+				        G_CALLBACK (pk_client_message_cb), client);
 	dbus_g_proxy_disconnect_signal (client->priv->proxy, "CallerActiveChanged",
 					G_CALLBACK (pk_client_caller_active_changed_cb), client);
 	dbus_g_proxy_disconnect_signal (client->priv->proxy, "Locked",
commit 71dbb3b9589be383ea83011b955f4d94059bcb59
Author: Richard Hughes <richard at hughsie.com>
Date:   Wed Nov 21 18:10:00 2007 +0000

    add the message dbus daemon bits

diff --git a/libpackagekit/pk-enum.h b/libpackagekit/pk-enum.h
index 0af6ef6..b1091c5 100644
--- a/libpackagekit/pk-enum.h
+++ b/libpackagekit/pk-enum.h
@@ -251,6 +251,9 @@ const gchar	*pk_error_enum_to_text			(PkErrorCodeEnum code);
 PkRestartEnum	 pk_restart_enum_from_text		(const gchar	*restart);
 const gchar	*pk_restart_enum_to_text		(PkRestartEnum	 restart);
 
+PkMessageEnum	 pk_message_enum_from_text		(const gchar	*message);
+const gchar	*pk_message_enum_to_text		(PkMessageEnum	 message);
+
 PkGroupEnum	 pk_group_enum_from_text		(const gchar	*group);
 const gchar	*pk_group_enum_to_text			(PkGroupEnum	 group);
 
diff --git a/src/pk-backend.c b/src/pk-backend.c
index c5e4142..1d87787 100644
--- a/src/pk-backend.c
+++ b/src/pk-backend.c
@@ -107,6 +107,7 @@ enum {
 	PK_BACKEND_UPDATES_CHANGED,
 	PK_BACKEND_REPO_SIGNATURE_REQUIRED,
 	PK_BACKEND_REQUIRE_RESTART,
+	PK_BACKEND_MESSAGE,
 	PK_BACKEND_CHANGE_TRANSACTION_DATA,
 	PK_BACKEND_FINISHED,
 	PK_BACKEND_ALLOW_INTERRUPT,
@@ -372,6 +373,7 @@ pk_backend_parse_common_error (PkBackend *backend, const gchar *line)
 	gchar *command;
 	PkErrorCodeEnum error_enum;
 	PkStatusEnum status_enum;
+	PkMessageEnum message_enum;
 	PkRestartEnum restart_enum;
 	gboolean ret = TRUE;
 
@@ -432,6 +434,14 @@ pk_backend_parse_common_error (PkBackend *backend, const gchar *line)
 		}
 		restart_enum = pk_restart_enum_from_text (sections[1]);
 		pk_backend_require_restart (backend, restart_enum, sections[2]);
+	} else if (pk_strequal (command, "message") == TRUE) {
+		if (size != 3) {
+			g_warning ("invalid command '%s'", command);
+			ret = FALSE;
+			goto out;
+		}
+		message_enum = pk_message_enum_from_text (sections[1]);
+		pk_backend_message (backend, message_enum, sections[2]);
 	} else if (pk_strequal (command, "change-transaction-data") == TRUE) {
 		if (size != 2) {
 			g_warning ("invalid command '%s'", command);
@@ -886,6 +896,21 @@ pk_backend_require_restart (PkBackend *backend, PkRestartEnum restart, const gch
 }
 
 /**
+ * pk_backend_message:
+ **/
+gboolean
+pk_backend_message (PkBackend *backend, PkMessageEnum message, const gchar *details)
+{
+	g_return_val_if_fail (backend != NULL, FALSE);
+	g_return_val_if_fail (PK_IS_BACKEND (backend), FALSE);
+
+	pk_debug ("emit message %i, %s", message, details);
+	g_signal_emit (backend, signals [PK_BACKEND_MESSAGE], 0, message, details);
+
+	return TRUE;
+}
+
+/**
  * pk_backend_change_transaction_data:
  **/
 gboolean
@@ -1084,44 +1109,48 @@ pk_backend_finished (PkBackend *backend)
 
 	/* are we trying to finish in init? */
 	if (backend->priv->during_initialize == TRUE) {
-		g_print ("You can't call pk_backend_finished in backend_initialize!\n");
-		pk_error ("Internal error, cannot continue!");
+		pk_backend_message (backend, PK_MESSAGE_ENUM_DAEMON,
+				    "You can't call pk_backend_finished in backend_initialize!");
+		return FALSE;
 	}
 
 	/* check we have no threads running */
 	if (pk_thread_list_number_running (backend->priv->thread_list) != 0) {
-		g_print ("There are threads running and the task has been asked to finish!\n");
-		g_print ("If you are using :\n");
-		g_print ("* pk_backend_thread_helper\n");
-		g_print ("   - You should _not_ use pk_backend_finished directly");
-		g_print ("   - Return from the function like normal\n");
-		g_print ("* pk_thread_list_create:\n");
-		g_print ("   -  If used internally you _have_ to use pk_thread_list_wait\n");
-		pk_error ("Internal error, cannot continue!");
+		pk_backend_message (backend, PK_MESSAGE_ENUM_DAEMON,
+				    "There are threads running and the task has been asked to finish!\n"
+				    "If you are using :\n"
+				    "* pk_backend_thread_helper\n"
+				    "   - You should _not_ use pk_backend_finished directly"
+				    "   - Return from the function like normal\n"
+				    "* pk_thread_list_create:\n"
+				    "   -  If used internally you _have_ to use pk_thread_list_wait");
+		return FALSE;
 	}
 
 	/* check we have not already finished */
 	if (backend->priv->finished == TRUE) {
-		g_print ("Backends cannot request Finished more than once!\n");
-		g_print ("If you are using:\n");
-		g_print ("* pk_backend_thread_helper\n");
-		g_print ("   - You should _not_ use pk_backend_finished directly");
-		g_print ("   - Return from the function like normal\n");
-		pk_error ("Internal error, cannot continue!");
+		pk_backend_message (backend, PK_MESSAGE_ENUM_DAEMON,
+				    "Backends cannot request Finished more than once!\n"
+				    "If you are using:\n"
+				    "* pk_backend_thread_helper\n"
+				    "   - You should _not_ use pk_backend_finished directly"
+				    "   - Return from the function like normal");
+		return FALSE;
 	}
 
 	/* check we sent at least one status calls */
 	if (backend->priv->status == PK_STATUS_ENUM_SETUP) {
-		g_print ("Backends should send status <value> signals to update the UI!\n");
-		g_print ("If you are:\n");
-		g_print ("* Calling out to external tools, the compiled backend "
-			 "should call pk_backend_change_status() manually.\n");
-		g_print ("* Using a scripted backend with dumb commands then "
-			 "this should be set at the start of the runtime call\n");
-		g_print ("   - see helpers/yumBackend.py:self.status()\n");
-		g_print ("* Using a scripted backend with clever commands then a "
-			 "  callback should use map values into status enums\n");
-		g_print ("   - see helpers/yumBackend.py:self.state_actions\n");
+		pk_backend_message (backend, PK_MESSAGE_ENUM_DAEMON,
+				    "Backends should send status <value> signals to update the UI!\n"
+				    "If you are:\n"
+				    "* Calling out to external tools, the compiled backend "
+				    "should call pk_backend_change_status() manually.\n"
+				    "* Using a scripted backend with dumb commands then "
+				    "this should be set at the start of the runtime call\n"
+				    "   - see helpers/yumBackend.py:self.status()\n"
+				    "* Using a scripted backend with clever commands then a "
+				    "  callback should use map values into status enums\n"
+				    "   - see helpers/yumBackend.py:self.state_actions");
 		pk_warning ("GUI will remain unchanged!");
 	}
 
@@ -1955,6 +1984,11 @@ pk_backend_class_init (PkBackendClass *klass)
 			      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);
+	signals [PK_BACKEND_MESSAGE] =
+		g_signal_new ("message",
+			      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);
 	signals [PK_BACKEND_CHANGE_TRANSACTION_DATA] =
 		g_signal_new ("change-transaction-data",
 			      G_TYPE_FROM_CLASS (object_class), G_SIGNAL_RUN_LAST,
diff --git a/src/pk-backend.h b/src/pk-backend.h
index d1e99ca..c54b3ac 100644
--- a/src/pk-backend.h
+++ b/src/pk-backend.h
@@ -60,6 +60,9 @@ gboolean	 pk_backend_update_detail		(PkBackend	*backend,
 gboolean	 pk_backend_require_restart		(PkBackend	*backend,
 							 PkRestartEnum	 restart,
 							 const gchar	*details);
+gboolean	 pk_backend_message			(PkBackend	*backend,
+							 PkMessageEnum	 message,
+							 const gchar	*details);
 gboolean	 pk_backend_description			(PkBackend	*backend,
 							 const gchar	*package_id,
 							 const gchar	*licence,
diff --git a/src/pk-engine.c b/src/pk-engine.c
index 2f803c8..91f339f 100644
--- a/src/pk-engine.c
+++ b/src/pk-engine.c
@@ -84,6 +84,7 @@ enum {
 	PK_ENGINE_TRANSACTION,
 	PK_ENGINE_ERROR_CODE,
 	PK_ENGINE_REQUIRE_RESTART,
+	PK_ENGINE_MESSAGE,
 	PK_ENGINE_UPDATES_CHANGED,
 	PK_ENGINE_REPO_SIGNATURE_REQUIRED,
 	PK_ENGINE_FINISHED,
@@ -298,8 +299,9 @@ pk_engine_package_cb (PkBackend *backend, PkInfoEnum info, const gchar *package_
 	    role == PK_ROLE_ENUM_INSTALL_PACKAGE ||
 	    role == PK_ROLE_ENUM_UPDATE_PACKAGE) {
 		if (info == PK_INFO_ENUM_INSTALLED) {
-			pk_warning ("backend emitted 'installed' rather than 'installing' "
-				    "- you need to do the package *before* you do the action");
+			pk_backend_message (item->backend, PK_MESSAGE_ENUM_DAEMON,
+					    "backend emitted 'installed' rather than 'installing' "
+					    "- you need to do the package *before* you do the action");
 			return;
 		}
 	}
@@ -430,6 +432,29 @@ pk_engine_require_restart_cb (PkBackend *backend, PkRestartEnum restart, const g
 }
 
 /**
+ * pk_engine_message_cb:
+ **/
+static void
+pk_engine_message_cb (PkBackend *backend, PkMessageEnum restart, const gchar *details, PkEngine *engine)
+{
+	PkTransactionItem *item;
+	const gchar *message_text;
+
+	g_return_if_fail (engine != NULL);
+	g_return_if_fail (PK_IS_ENGINE (engine));
+
+	item = pk_transaction_list_get_from_backend (engine->priv->transaction_list, backend);
+	if (item == NULL) {
+		pk_warning ("could not find backend");
+		return;
+	}
+	message_text = pk_message_enum_to_text (restart);
+	pk_debug ("emitting message tid:%s %s, '%s'", item->tid, message_text, details);
+	g_signal_emit (engine, signals [PK_ENGINE_MESSAGE], 0, item->tid, message_text, details);
+	pk_engine_reset_timer (engine);
+}
+
+/**
  * pk_engine_description_cb:
  **/
 static void
@@ -732,6 +757,8 @@ pk_engine_backend_new (PkEngine *engine)
 			  G_CALLBACK (pk_engine_repo_signature_required_cb), engine);
 	g_signal_connect (backend, "require-restart",
 			  G_CALLBACK (pk_engine_require_restart_cb), engine);
+	g_signal_connect (backend, "message",
+			  G_CALLBACK (pk_engine_message_cb), engine);
 	g_signal_connect (backend, "finished",
 			  G_CALLBACK (pk_engine_finished_cb), engine);
 	g_signal_connect (backend, "description",
@@ -967,7 +994,7 @@ pk_engine_get_updates (PkEngine *engine, const gchar *tid, DBusGMethodInvocation
 		guint length;
 
 		length = pk_package_list_get_size (engine->priv->updates_cache);
-		pk_warning ("we have cached data (%i) we could use!", length);
+		pk_debug ("we have cached data (%i) we could use!", length);
 
 		/* emulate the backend */
 		pk_backend_set_role (item->backend, PK_ROLE_ENUM_GET_UPDATES);
@@ -2732,6 +2759,11 @@ pk_engine_class_init (PkEngineClass *klass)
 			      G_TYPE_FROM_CLASS (object_class), G_SIGNAL_RUN_LAST,
 			      0, NULL, NULL, pk_marshal_VOID__STRING_STRING_STRING,
 			      G_TYPE_NONE, 3, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING);
+	signals [PK_ENGINE_MESSAGE] =
+		g_signal_new ("message",
+			      G_TYPE_FROM_CLASS (object_class), G_SIGNAL_RUN_LAST,
+			      0, NULL, NULL, pk_marshal_VOID__STRING_STRING_STRING,
+			      G_TYPE_NONE, 3, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING);
 	signals [PK_ENGINE_UPDATES_CHANGED] =
 		g_signal_new ("updates-changed",
 			      G_TYPE_FROM_CLASS (object_class), G_SIGNAL_RUN_LAST,
diff --git a/src/pk-interface.xml b/src/pk-interface.xml
index fb86a02..97128a1 100644
--- a/src/pk-interface.xml
+++ b/src/pk-interface.xml
@@ -160,7 +160,12 @@
     </signal>
     <signal name="RequireRestart">
       <arg type="s" name="tid" direction="out"/>
-      <arg type="s" name="type" direction="out"/> <!-- system,application,session -->
+      <arg type="s" name="type" direction="out"/>
+      <arg type="s" name="details" direction="out"/> <!-- non-localized detail -->
+    </signal>
+    <signal name="Message">
+      <arg type="s" name="tid" direction="out"/>
+      <arg type="s" name="message" direction="out"/>
       <arg type="s" name="details" direction="out"/> <!-- non-localized detail -->
     </signal>
     <signal name="UpdatesChanged">
commit 300cf8d3f13c5d896f06040b7be66118259163ea
Author: Richard Hughes <richard at hughsie.com>
Date:   Wed Nov 21 17:39:15 2007 +0000

    add the message enumerated types

diff --git a/docs/pk-introduction.xml b/docs/pk-introduction.xml
index d1fc50d..ec6acad 100644
--- a/docs/pk-introduction.xml
+++ b/docs/pk-introduction.xml
@@ -1485,6 +1485,38 @@
       </informaltable>
     </sect2>
 
+    <sect2 id="api-message">
+      <title>Message</title>
+      <para>
+        This allows the backend to queue up a message to be shown after the
+        transaction has completed.
+      </para>
+      <informaltable>
+        <tgroup cols="2">
+          <thead>
+            <row>
+              <entry>Option</entry>
+              <entry>Description</entry>
+            </row>
+          </thead>
+          <tbody>
+            <row>
+              <entry><literal>type</literal></entry>
+              <entry>
+                One of "<literal>warning</literal>",
+                "<literal>notice</literal>",
+                "<literal>daemon</literal>".
+              </entry>
+            </row>
+            <row>
+              <entry><literal>detail</literal></entry>
+              <entry>Required details about the message, non localised</entry>
+            </row>
+          </tbody>
+        </tgroup>
+      </informaltable>
+    </sect2>
+
     <sect2 id="backends-spawn-package">
       <title>Package</title>
       <para>
diff --git a/libpackagekit/pk-enum.c b/libpackagekit/pk-enum.c
index 8ec731e..ab7da25 100644
--- a/libpackagekit/pk-enum.c
+++ b/libpackagekit/pk-enum.c
@@ -124,6 +124,14 @@ static PkEnumMatch enum_restart[] = {
 	{0, NULL},
 };
 
+static PkEnumMatch enum_message[] = {
+	{PK_MESSAGE_ENUM_UNKNOWN,		"unknown"},	/* fall though value */
+	{PK_MESSAGE_ENUM_NOTICE,		"notice"},
+	{PK_MESSAGE_ENUM_WARNING,		"warning"},
+	{PK_MESSAGE_ENUM_DAEMON,		"daemon"},
+	{0, NULL},
+};
+
 static PkEnumMatch enum_filter[] = {
 	{PK_FILTER_ENUM_UNKNOWN,		"unknown"},	/* fall though value */
 	{PK_FILTER_ENUM_NONE,			"none"},
@@ -394,6 +402,24 @@ pk_restart_enum_to_text (PkRestartEnum restart)
 }
 
 /**
+ * pk_message_enum_from_text:
+ **/
+PkMessageEnum
+pk_message_enum_from_text (const gchar *message)
+{
+	return pk_enum_find_value (enum_message, message);
+}
+
+/**
+ * pk_message_enum_to_text:
+ **/
+const gchar *
+pk_message_enum_to_text (PkMessageEnum message)
+{
+	return pk_enum_find_string (enum_message, message);
+}
+
+/**
  * pk_group_enum_from_text:
  **/
 PkGroupEnum
diff --git a/libpackagekit/pk-enum.h b/libpackagekit/pk-enum.h
index 07cec3a..0af6ef6 100644
--- a/libpackagekit/pk-enum.h
+++ b/libpackagekit/pk-enum.h
@@ -116,6 +116,14 @@ typedef enum {
 	PK_RESTART_ENUM_UNKNOWN
 } PkRestartEnum;
 
+/* what message type we need to show */
+typedef enum {
+	PK_MESSAGE_ENUM_NOTICE,
+	PK_MESSAGE_ENUM_WARNING,
+	PK_MESSAGE_ENUM_DAEMON,
+	PK_MESSAGE_ENUM_UNKNOWN
+} PkMessageEnum;
+
 typedef enum {
 	PK_ERROR_ENUM_OOM,
 	PK_ERROR_ENUM_NO_NETWORK,
commit 6165834b3fa58d7939354ab8d69656a8a99c6154
Author: S.Çağlar Onur <caglar at pardus.org.tr>
Date:   Wed Nov 21 16:20:21 2007 +0200

    Fix "configure.ac:491: required file `backends/box/helpers/Makefile.in' not found" error

diff --git a/configure.ac b/configure.ac
index e9ae52f..e194601 100755
--- a/configure.ac
+++ b/configure.ac
@@ -464,7 +464,6 @@ backends/alpm/Makefile
 backends/apt/Makefile
 backends/apt/helpers/Makefile
 backends/box/Makefile
-backends/box/helpers/Makefile
 backends/conary/Makefile
 backends/conary/helpers/Makefile
 backends/dummy/Makefile
commit fc905fc53ca91b81bf2ad8ce0c12925d0acfba64
Author: S.Çağlar Onur <caglar at pardus.org.tr>
Date:   Wed Nov 21 16:15:17 2007 +0200

    Correct Resolve method

diff --git a/python/packagekit/frontend.py b/python/packagekit/frontend.py
index 93c30fd..2647fd7 100644
--- a/python/packagekit/frontend.py
+++ b/python/packagekit/frontend.py
@@ -241,12 +241,12 @@ class PackageKit:
 
 	@dbusException
 	@job_id
-	def Resolve(self,package_name):
+	def Resolve(self,package_name,filter="none"):
 		"""
 		Finds a package with the given name, and gives back a Package that matches that name exactly
 		(not yet supported in yum backend, and maybe others)
 		"""
-		return self.pk_iface.Resolve(self.tid(),package_id)
+		return self.pk_iface.Resolve(self.tid(),filter,package_name)
 
 	@dbusException
 	@job_id
commit f4583b802688f1392bff44f356a7e1f9a4d2dd15
Author: S.Çağlar Onur <caglar at bankai.(none)>
Date:   Wed Nov 21 16:10:43 2007 +0200

    Add .gitignore to zypp backend

diff --git a/backends/zypp/.gitignore b/backends/zypp/.gitignore
new file mode 100644
index 0000000..c851833
--- /dev/null
+++ b/backends/zypp/.gitignore
@@ -0,0 +1,10 @@
+.deps
+.libs
+Makefile
+Makefile.in
+*.la
+*.lo
+*.loT
+*.o
+*~
+
commit 758c1d17915bc5f84f9adfc348d009e03877bcd4
Author: Boyd Timothy <boyd at boyd-timothys-macbook.local>
Date:   Tue Nov 20 20:20:28 2007 -0700

    Updated the pk-faq.html to add resolve and install-package for zypp.

diff --git a/html/pk-faq.html b/html/pk-faq.html
index 88cabc4..a3f585c 100644
--- a/html/pk-faq.html
+++ b/html/pk-faq.html
@@ -22,7 +22,7 @@
 <pre>
                   | conary | yum | apt | box | alpm | smart | pisi | zypp |
 ---------------------------------------------------------------------------
-resolve           |   X    |  X  |     |  X  |      |   X   |   X  |      |
+resolve           |   X    |  X  |     |  X  |      |   X   |   X  |   X  |
 refresh-cache     |   X    |  X  |  X  |  X  |      |   X   |   X  |      |
   \--force        |        |     |     |     |      |       |      |      |
 get-updates       |   X    |  X  |     |  X  |      |   X   |   X  |      |
@@ -31,7 +31,7 @@ search-name       |   X    |  X  |  X  |  X  |  X   |   X   |   X  |      |
 search-details    |        |  X  |  X  |  X  |      |   X   |   X  |      |
 search-file       |        |  X  |     |  X  |      |       |   X  |      |
 search-group      |        |  X  |     |     |      |       |   X  |      |
-install-package   |   X    |  X  |     |  X  |  X   |   X   |   X  |      |
+install-package   |   X    |  X  |     |  X  |  X   |   X   |   X  |   X  |
 install-file      |        |  X  |     |  X  |      |   X   |   X  |      |
 remove-package    |   X    |  X  |     |  X  |  X   |   X   |   X  |      |
 update-package    |   X    |  X  |     |  X  |      |   X   |   X  |      |
commit 657f157cfd7b575eba5edfc16921569d0286b93e
Author: Boyd Timothy <btimothy at gmail.com>
Date:   Fri Nov 16 14:09:05 2007 -0700

    Fix whitespace in zypp backend.

diff --git a/backends/zypp/pk-backend-zypp.cpp b/backends/zypp/pk-backend-zypp.cpp
index 43dc603..2fc410d 100644
--- a/backends/zypp/pk-backend-zypp.cpp
+++ b/backends/zypp/pk-backend-zypp.cpp
@@ -696,7 +696,7 @@ extern "C" PK_BACKEND_OPTIONS (
 	NULL,					/* install_file */
 	NULL,//backend_refresh_cache,			/* refresh_cache */
 	NULL,					/* remove_package */
-	backend_resolve,		/* resolve */
+	backend_resolve,			/* resolve */
 	NULL,					/* rollback */
 	NULL,					/* search_details */
 	NULL,					/* search_file */
commit 4b802692fb4f67c2f6815082bbb531afd48c69b5
Author: Scott Reeves <sreeves at novell.com>
Date:   Tue Nov 20 16:50:54 2007 -0700

    dump out real backend error

diff --git a/backends/zypp/pk-backend-zypp.cpp b/backends/zypp/pk-backend-zypp.cpp
index b075185..43dc603 100644
--- a/backends/zypp/pk-backend-zypp.cpp
+++ b/backends/zypp/pk-backend-zypp.cpp
@@ -287,7 +287,8 @@ printf ("Finished the installation.\n");
 		pk_package_id_free (pi);
 		return FALSE;
 	} catch (const zypp::Exception &ex) {
-		pk_backend_error_code (backend, PK_ERROR_ENUM_INTERNAL_ERROR, "Error enumerating repositories");
+		//pk_backend_error_code (backend, PK_ERROR_ENUM_INTERNAL_ERROR, "Error enumerating repositories");
+		pk_backend_error_code (backend, PK_ERROR_ENUM_INTERNAL_ERROR, ex.asUserString().c_str() );
 		g_free (package_id);
 		pk_package_id_free (pi);
 		return FALSE;
commit 7ae49fbd87ef8787f26f0078f97f4f00b7e4a8fb
Author: Scott Reeves <sreeves at novell.com>
Date:   Tue Nov 20 15:24:28 2007 -0700

    close database, remove debug prints

diff --git a/backends/zypp/pk-backend-zypp.cpp b/backends/zypp/pk-backend-zypp.cpp
index ea59ba2..b075185 100644
--- a/backends/zypp/pk-backend-zypp.cpp
+++ b/backends/zypp/pk-backend-zypp.cpp
@@ -314,14 +314,14 @@ backend_install_package (PkBackend *backend, const gchar *package_id)
 static int
 select_callback (void* data,int argc ,char** argv, char** cl_name)
 {
-	printf ("Enter select_callback\n");
+	// printf ("Enter select_callback\n");
 
 	SQLData *sql_data = (SQLData *) data;
 	/* FIXME - for now we prefer later versions, i586 */
 	if (sql_data->name == NULL ||
 			(g_ascii_strcasecmp (argv[SQL_VERSION], sql_data->version) > 0) ||
 			!g_ascii_strcasecmp ("i586", argv[SQL_ARCH]) ) {
-		printf ("Adding to data struct\n");
+		//printf ("Adding to data struct\n");
 		g_free (sql_data->name);
 		g_free (sql_data->version);
 		g_free (sql_data->release);
@@ -333,11 +333,11 @@ select_callback (void* data,int argc ,char** argv, char** cl_name)
 		sql_data->repo = g_strdup (argv[SQL_REPO]);
 		sql_data->arch = g_strdup (argv[SQL_ARCH]);
 	}
-	// /*
+	/*
 	for (int i = 0; i < argc; i++) {
 		printf ("%s=%s\n", cl_name[i], argv[i] ? argv[i] : "null");
 	}
-	// */
+	*/
 	return 0;
 }
 
@@ -353,7 +353,7 @@ backend_resolve_thread (PkBackend *backend, gpointer data)
 							  
 	pk_backend_change_status (backend, PK_STATUS_ENUM_QUERY);
 
-	printf("\n\nEnter backend_resolve_thread\n");
+	// printf("\n\nEnter backend_resolve_thread\n");
 	ResolveData *rdata = (ResolveData*) data;
 
 	sqlite3 *db;
@@ -364,6 +364,7 @@ backend_resolve_thread (PkBackend *backend, gpointer data)
 
 	select_statement = g_strdup_printf (select_statement_template, rdata->name);
 	sqlite3_exec (db, select_statement, select_callback, sql_data, &error_string);
+	sqlite3_close (db);
 
 	if (sql_data->name == NULL) {
 		//did not get any matches
commit 9df2ef9374c9bdb2eab9ee984a3c841aa8d54733
Author: Boyd Timothy <btimothy at gmail.com>
Date:   Fri Nov 16 13:30:02 2007 -0700

    Added a few TODO items and emit status lines to zypp backend.

diff --git a/backends/zypp/pk-backend-zypp.cpp b/backends/zypp/pk-backend-zypp.cpp
index a8d59d7..ea59ba2 100644
--- a/backends/zypp/pk-backend-zypp.cpp
+++ b/backends/zypp/pk-backend-zypp.cpp
@@ -216,6 +216,8 @@ backend_install_package_thread (PkBackend *backend, gpointer data)
 	try
 	{
 		// TODO: Split the code up so it's not all just in one bit try/catch
+
+		// TODO: Fix up this code so we only iterate through enabled repositories
 		repos = manager.knownRepositories();
 		for (std::list <zypp::RepoInfo>::iterator it = repos.begin(); it != repos.end(); it++) {
 			zypp::Repository repository = manager.createFromCache (*it);
@@ -246,6 +248,7 @@ backend_install_package_thread (PkBackend *backend, gpointer data)
 printf ("WOOT!  Marking the package to be installed!\n");
 					// this is the one, mark it to be installed
 					selectable->set_status (zypp::ui::S_Install);
+					break; // Found it, get out of the for loop
 				}
 			}
 		}
@@ -274,6 +277,8 @@ printf ("Performing installation...\n");
 printf ("Finished the installation.\n");
 
 		// TODO: Check result for success
+		// TODO: Loop through the installed packages and let
+		// packagekit know we installed them and not just the top-level package
 		pk_backend_package (backend, PK_INFO_ENUM_INSTALLED, package_id, "TODO: Put the package summary here");
 	} catch (const zypp::repo::RepoNotFoundException &ex) {
 		// TODO: make sure this dumps out the right sring.
@@ -346,6 +351,7 @@ backend_resolve_thread (PkBackend *backend, gpointer data)
 	gchar *full_version;
 	SQLData *sql_data = g_new0(SQLData, 1);
 							  
+	pk_backend_change_status (backend, PK_STATUS_ENUM_QUERY);
 
 	printf("\n\nEnter backend_resolve_thread\n");
 	ResolveData *rdata = (ResolveData*) data;
commit a075e07e9026e4be934884bae518f6379fbdbc8e
Author: Boyd Timothy <btimothy at gmail.com>
Date:   Fri Nov 16 13:23:49 2007 -0700

    We have a working package install for zypp now.  Still needs LOTS of cleanup.

diff --git a/backends/zypp/pk-backend-zypp.cpp b/backends/zypp/pk-backend-zypp.cpp
index 005f511..a8d59d7 100644
--- a/backends/zypp/pk-backend-zypp.cpp
+++ b/backends/zypp/pk-backend-zypp.cpp
@@ -188,6 +188,17 @@ static gboolean
 backend_install_package_thread (PkBackend *backend, gpointer data)
 {
 	gchar *package_id = (gchar *)data;
+
+	pk_backend_change_status (backend, PK_STATUS_ENUM_QUERY);
+
+	PkPackageId *pi = pk_package_id_new_from_string (package_id);
+        if (pi == NULL) {
+                pk_backend_error_code (backend, PK_ERROR_ENUM_PACKAGE_ID_INVALID, "invalid package id");
+                g_free (package_id);
+
+                return FALSE;
+        }
+
 	zypp::Target_Ptr target;
 
 	zypp::ZYpp::Ptr zypp;
@@ -199,6 +210,7 @@ backend_install_package_thread (PkBackend *backend, gpointer data)
 	zypp->addResolvables (target->resolvables(), TRUE);
 
 	// Load resolvables from all the enabled repositories
+	pk_backend_change_status (backend, PK_STATUS_ENUM_WAIT);
 	zypp::RepoManager manager;
 	std::list <zypp::RepoInfo> repos;
 	try
@@ -215,20 +227,69 @@ backend_install_package_thread (PkBackend *backend, gpointer data)
 		for (zypp::ResPoolProxy::const_iterator it = zypp->poolProxy().byKindBegin <zypp::Package>();
 				it != zypp->poolProxy().byKindEnd <zypp::Package>(); it++) {
 			zypp::ui::Selectable::Ptr selectable = *it;
-			
+			if (strcmp (selectable->name().c_str(), pi->name) == 0) {
+				switch (selectable->status ()) {
+					case zypp::ui::S_Update:	// Have installedObj
+					case zypp::ui::S_NoInst:	// No installedObj
+						break;
+					default:
+						continue;
+						break;
+				}
+
+				// This package matches the name we're looking for and
+				// is available for update/install.
+				zypp::ResObject::constPtr installable = selectable->candidateObj();
+				const char *edition_str = installable->edition().asString().c_str();
+
+				if (strcmp (edition_str, pi->version) == 0) {
+printf ("WOOT!  Marking the package to be installed!\n");
+					// this is the one, mark it to be installed
+					selectable->set_status (zypp::ui::S_Install);
+				}
+			}
+		}
+
+printf ("Resolving dependencies...\n");
+		// Gather up any dependencies
+		pk_backend_change_status (backend, PK_STATUS_ENUM_DEP_RESOLVE);
+		if (zypp->resolver ()->resolvePool () == FALSE) {
+			// Manual intervention required to resolve dependencies
+			// TODO: Figure out what we need to do with PackageKit
+			// to pull off interactive problem solving.
+			pk_backend_error_code (backend, PK_ERROR_ENUM_DEP_RESOLUTION_FAILED, "Couldn't resolve the package dependencies.");
+			g_free (package_id);
+			pk_package_id_free (pi);
+			return FALSE;
 		}
+
+printf ("Performing installation...\n");
+		// Perform the installation
+		pk_backend_change_status (backend, PK_STATUS_ENUM_COMMIT);
+		// TODO: If this were an update, you should use PK_INFO_ENUM_UPDATING instead
+		pk_backend_package (backend, PK_INFO_ENUM_INSTALLING, package_id, "TODO: Put the package summary here");
+		zypp::ZYppCommitPolicy policy;
+		policy.restrictToMedia (0);	// 0 - install all packages regardless to media
+		zypp::ZYppCommitResult result = zypp->commit (policy);
+printf ("Finished the installation.\n");
+
+		// TODO: Check result for success
+		pk_backend_package (backend, PK_INFO_ENUM_INSTALLED, package_id, "TODO: Put the package summary here");
 	} catch (const zypp::repo::RepoNotFoundException &ex) {
 		// TODO: make sure this dumps out the right sring.
 		pk_backend_error_code (backend, PK_ERROR_ENUM_REPO_NOT_FOUND, ex.asUserString().c_str() );
 		g_free (package_id);
+		pk_package_id_free (pi);
 		return FALSE;
 	} catch (const zypp::Exception &ex) {
 		pk_backend_error_code (backend, PK_ERROR_ENUM_INTERNAL_ERROR, "Error enumerating repositories");
 		g_free (package_id);
+		pk_package_id_free (pi);
 		return FALSE;
 	}
 
 	g_free (package_id);
+	pk_package_id_free (pi);
 	return TRUE;
 }
 
@@ -243,24 +304,6 @@ backend_install_package (PkBackend *backend, const gchar *package_id)
 	printf("package_id is %s\n", package_id);
 	gchar *package_to_install = g_strdup (package_id);
 	pk_backend_thread_helper (backend, backend_install_package_thread, package_to_install);
-
-	/*
-	if(strcmp(package_id,"signedpackage;1.0-1.fc8;i386;fedora") == 0) {
-		pk_backend_repo_signature_required(backend, "updates", "http://example.com/gpgkey",
-						   "Test Key (Fedora) fedora at example.com", "BB7576AC",
-						   "D8CC 06C2 77EC 9C53 372F  C199 B1EE 1799 F24F 1B08",
-						   "2007-10-04", PK_SIGTYPE_ENUM_GPG);
-		pk_backend_error_code (backend, PK_ERROR_ENUM_GPG_FAILURE,
-				       "GPG signed package could not be verified");
-		pk_backend_finished (backend);
-	}
-
-	progress_percentage = 0;
-	pk_backend_package (backend, PK_INFO_ENUM_DOWNLOADING,
-			    "gtkhtml2;2.19.1-4.fc8;i386;fedora",
-			    "An HTML widget for GTK+ 2.0");
-	g_timeout_add (1000, backend_install_timeout, backend);
-	*/
 }
 
 static int
commit e2071d1f1a708fbd8632d58c7a655ea92aaa3887
Author: Scott Reeves <sreeves at novell.com>
Date:   Tue Nov 20 14:31:44 2007 -0700

    query slq database to resolve names

diff --git a/backends/zypp/pk-backend-zypp.cpp b/backends/zypp/pk-backend-zypp.cpp
index dbd2854..005f511 100644
--- a/backends/zypp/pk-backend-zypp.cpp
+++ b/backends/zypp/pk-backend-zypp.cpp
@@ -62,9 +62,21 @@ typedef struct {
 	gchar *filter;
 } ResolveData;
 
+/* make sure and keep the struct in sync with the enum */
+enum SqlQuerySchema {
+	SQL_NAME = 0,
+	SQL_VERSION,
+	SQL_RELEASE,
+	SQL_REPO,
+	SQL_ARCH
+};
+
 typedef struct {
 	gchar *name;
-	gchar *filter;
+	gchar *version;
+	gchar *release;
+	gchar *repo;
+	gchar *arch;
 } SQLData;
 
 typedef struct {
@@ -252,12 +264,32 @@ backend_install_package (PkBackend *backend, const gchar *package_id)
 }
 
 static int
-select_callback (void* sql_data,int argc ,char** argv, char** cl_name)
+select_callback (void* data,int argc ,char** argv, char** cl_name)
 {
-	printf("\n\nEnter select_callback\n");
+	printf ("Enter select_callback\n");
+
+	SQLData *sql_data = (SQLData *) data;
+	/* FIXME - for now we prefer later versions, i586 */
+	if (sql_data->name == NULL ||
+			(g_ascii_strcasecmp (argv[SQL_VERSION], sql_data->version) > 0) ||
+			!g_ascii_strcasecmp ("i586", argv[SQL_ARCH]) ) {
+		printf ("Adding to data struct\n");
+		g_free (sql_data->name);
+		g_free (sql_data->version);
+		g_free (sql_data->release);
+		g_free (sql_data->repo);
+		g_free (sql_data->arch);
+		sql_data->name = g_strdup (argv[SQL_NAME]);
+		sql_data->version = g_strdup (argv[SQL_VERSION]);
+		sql_data->release = g_strdup (argv[SQL_RELEASE]);
+		sql_data->repo = g_strdup (argv[SQL_REPO]);
+		sql_data->arch = g_strdup (argv[SQL_ARCH]);
+	}
+	// /*
 	for (int i = 0; i < argc; i++) {
 		printf ("%s=%s\n", cl_name[i], argv[i] ? argv[i] : "null");
 	}
+	// */
 	return 0;
 }
 
@@ -265,8 +297,10 @@ static gboolean
 backend_resolve_thread (PkBackend *backend, gpointer data)
 {
 	char * error_string;
-	const char * select_statement_template = "SELECT p.name,p.version,p.release,t.name FROM resolvables p JOIN types t ON p.arch = t.id WHERE p.name LIKE \"%s\"";
+	const char * select_statement_template = "SELECT p.name,p.version,p.release,r.alias,t.name FROM resolvables p JOIN repositories r ON p.repository_id = r.id JOIN types t ON p.arch = t.id WHERE p.name LIKE \"%s\"";
 	gchar *select_statement;
+	gchar *package_id;
+	gchar *full_version;
 	SQLData *sql_data = g_new0(SQLData, 1);
 							  
 
@@ -281,53 +315,24 @@ backend_resolve_thread (PkBackend *backend, gpointer data)
 
 	select_statement = g_strdup_printf (select_statement_template, rdata->name);
 	sqlite3_exec (db, select_statement, select_callback, sql_data, &error_string);
-	/*
-	zypp::Target_Ptr target;
-	zypp::ZYpp::Ptr zypp;
-	zypp = get_zypp ();
-
-	target = zypp->target ();
 
-	// Load all the local system "resolvables" (packages)
-	zypp->addResolvables (target->resolvables(), TRUE);
-
-	// Load resolvables from all the enabled repositories
-	zypp::RepoManager manager;
-	std::list <zypp::RepoInfo> repos;
-	try
-	{
-		// TODO: Split the code up so it's not all just in one bit try/catch
-		repos = manager.knownRepositories();
-		for (std::list <zypp::RepoInfo>::iterator it = repos.begin(); it != repos.end(); it++) {
-			zypp::Repository repository = manager.createFromCache (*it);
-			zypp->addResolvables (repository.resolvables ());
-		}
-
-		// Iterate over the resolvables and mark the ones we want to install
-		//zypp->start ();
-		for (zypp::ResPoolProxy::const_iterator it = zypp->poolProxy().byKindBegin <zypp::Package>();
-				it != zypp->poolProxy().byKindEnd <zypp::Package>(); it++) {
-			zypp::ui::Selectable::Ptr selectable = *it;
-
-		}
-	} catch (const zypp::repo::RepoNotFoundException &ex) {
-		// TODO: make sure this dumps out the right sring.
-		pk_backend_error_code (backend, PK_ERROR_ENUM_REPO_NOT_FOUND, ex.asUserString().c_str() );
-		g_free (package_id);
-		return FALSE;
-	} catch (const zypp::Exception &ex) {
-		pk_backend_error_code (backend, PK_ERROR_ENUM_INTERNAL_ERROR, "Error enumerating repositories");
-		g_free (package_id);
+	if (sql_data->name == NULL) {
+		//did not get any matches
 		return FALSE;
 	}
-	*/
+	full_version = g_strconcat (sql_data->version, "-", sql_data->release, NULL);
+	package_id = pk_package_id_build(sql_data->name, full_version, sql_data->arch, sql_data->repo);
+	printf("about to return package_id of:%s\n", package_id);
+	//FIXME - return real PK_INFO_ENUM_*
+	pk_backend_package (backend, PK_INFO_ENUM_AVAILABLE,
+				package_id, "description generated by zypp backend");
 
 	g_free (rdata->name);
 	g_free (rdata->filter);
 	g_free (rdata);
+	g_free (full_version);
+	g_free (package_id);
 	g_free (select_statement);
-	pk_backend_package (backend, PK_INFO_ENUM_INSTALLED,
-			    "glib2;2.14.0;i386;fedora", "The GLib library");
 	return TRUE;
 }
 



More information about the PackageKit mailing list