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

Richard Hughes hughsient at kemper.freedesktop.org
Wed Jun 25 06:41:55 PDT 2008


 NEWS                                      |    4 
 backends/alpm/pk-backend-alpm.c           |    1 
 backends/apt.deprecated/pk-backend-apt.c  |    1 
 backends/apt/pk-backend-apt.c             |    1 
 backends/box/pk-backend-box.c             |    1 
 backends/conary/pk-backend-conary.c       |    3 
 backends/dummy/pk-backend-dummy.c         |   81 ++++++----
 backends/opkg/pk-backend-opkg.c           |    1 
 backends/pisi/pk-backend-pisi.c           |    3 
 backends/poldek/pk-backend-poldek.c       |    1 
 backends/smart/pk-backend-smart.c         |    1 
 backends/test/pk-backend-test-dbus.c      |    1 
 backends/test/pk-backend-test-fail.c      |    1 
 backends/test/pk-backend-test-nop.c       |    1 
 backends/test/pk-backend-test-spawn.c     |    1 
 backends/test/pk-backend-test-succeed.c   |    3 
 backends/test/pk-backend-test-thread.c    |    1 
 backends/urpmi/pk-backend-urpmi.c         |   15 +
 backends/yum/helpers/download-packages.py |   20 ++
 backends/yum/helpers/get-update-detail.py |    6 
 backends/yum/helpers/yumBackend.py        |   33 ++++
 backends/yum/pk-backend-yum.c             |   15 +
 backends/yum2/pk-backend-yum2.c           |    1 
 backends/zypp/pk-backend-zypp.cpp         |    1 
 client/pk-console.c                       |   68 ++++-----
 client/pk-import-desktop.c                |    8 -
 client/pk-import-specspo.c                |    4 
 libpackagekit/Makefile.am                 |   15 +
 libpackagekit/pk-client.c                 |   70 ++++-----
 libpackagekit/pk-client.h                 |   18 --
 libpackagekit/pk-common.c                 |   88 ++++++-----
 libpackagekit/pk-common.h                 |    4 
 libpackagekit/pk-debug.c                  |    6 
 libpackagekit/pk-details-obj.c            |  146 +++++++++++++++++++
 libpackagekit/pk-details-obj.h            |   56 +++++++
 libpackagekit/pk-enum.c                   |    1 
 libpackagekit/pk-enum.h                   |    3 
 libpackagekit/pk-extra.c                  |    6 
 libpackagekit/pk-package-ids.c            |    5 
 libpackagekit/pk-package-item.c           |  189 -------------------------
 libpackagekit/pk-package-item.h           |   48 ------
 libpackagekit/pk-package-list.c           |  118 +++++++--------
 libpackagekit/pk-package-list.h           |   38 ++---
 libpackagekit/pk-package-obj.c            |  189 +++++++++++++++++++++++++
 libpackagekit/pk-package-obj.h            |   48 ++++++
 libpackagekit/pk-self-test.c              |   10 -
 libpackagekit/pk-update-detail-list.c     |  226 ++++++++++++++++++++++++++++++
 libpackagekit/pk-update-detail-list.h     |   62 ++++++++
 libpackagekit/pk-update-detail-obj.c      |  170 ++++++++++++++++++++++
 libpackagekit/pk-update-detail-obj.h      |   61 ++++++++
 python/packagekit/backend.py              |    7 
 src/pk-backend.c                          |   53 +++----
 src/pk-backend.h                          |    6 
 src/pk-engine.c                           |    4 
 src/pk-interface-transaction.xml          |   30 +++
 src/pk-spawn.c                            |   13 +
 src/pk-transaction.c                      |  175 +++++++++++++++++++----
 src/pk-transaction.h                      |    4 
 58 files changed, 1580 insertions(+), 566 deletions(-)

New commits:
commit 12afe03d38a925bbe4e4e067674c17c7e1534b87
Author: Richard Hughes <richard at hughsie.com>
Date:   Wed Jun 25 14:06:28 2008 +0100

    trivial: fix up some gtk-doc markup

diff --git a/libpackagekit/pk-client.c b/libpackagekit/pk-client.c
index 8416dbf..02fd380 100644
--- a/libpackagekit/pk-client.c
+++ b/libpackagekit/pk-client.c
@@ -454,7 +454,6 @@ pk_client_get_require_restart (PkClient *client)
 /**
  * pk_client_get_package_list:
  * @client: a valid #PkClient instance
- * @item: the item in the package buffer
  *
  * We do not provide access to the internal package list (as it could be being
  * updated) so provide a way to get access to objects here.
@@ -1416,7 +1415,7 @@ pk_client_search_file (PkClient *client, PkFilterEnum filters, const gchar *sear
  * pk_client_get_depends:
  * @client: a valid #PkClient instance
  * @filters: a %PkFilterEnum such as %PK_FILTER_ENUM_GUI | %PK_FILTER_ENUM_FREE or %PK_FILTER_ENUM_NONE
- * @package_id: a package_id structure such as "gnome-power-manager;0.0.1;i386;fedora"
+ * @package_ids: an array of package_id structures such as "gnome-power-manager;0.0.1;i386;fedora"
  * @recursive: If we should search recursively for depends
  * @error: a %GError to put the error code and message in, or %NULL
  *
@@ -1536,7 +1535,7 @@ pk_client_get_packages (PkClient *client, PkFilterEnum filters, GError **error)
  * pk_client_get_requires:
  * @client: a valid #PkClient instance
  * @filters: a %PkFilterEnum such as %PK_FILTER_ENUM_GUI | %PK_FILTER_ENUM_FREE or %PK_FILTER_ENUM_NONE
- * @package_id: a package_id structure such as "gnome-power-manager;0.0.1;i386;fedora"
+ * @package_ids: an array of package_id structures such as "gnome-power-manager;0.0.1;i386;fedora"
  * @recursive: If we should search recursively for requires
  * @error: a %GError to put the error code and message in, or %NULL
  *
@@ -1669,7 +1668,7 @@ pk_client_what_provides (PkClient *client, PkFilterEnum filters, PkProvidesEnum
 /**
  * pk_client_get_update_detail:
  * @client: a valid #PkClient instance
- * @package_id: a package_id structure such as "gnome-power-manager;0.0.1;i386;fedora"
+ * @package_ids: an array of package_id structures such as "gnome-power-manager;0.0.1;i386;fedora"
  * @error: a %GError to put the error code and message in, or %NULL
  *
  * Get details about the specific update, for instance any CVE urls and
@@ -1780,7 +1779,7 @@ pk_client_rollback (PkClient *client, const gchar *transaction_id, GError **erro
  * pk_client_resolve:
  * @client: a valid #PkClient instance
  * @filters: a %PkFilterEnum such as %PK_FILTER_ENUM_GUI | %PK_FILTER_ENUM_FREE or %PK_FILTER_ENUM_NONE
- * @package: the package name to resolve, e.g. "gnome-system-tools"
+ * @packages: an array of package names to resolve, e.g. "gnome-system-tools"
  * @error: a %GError to put the error code and message in, or %NULL
  *
  * Resolve a package name into a %package_id. This can return installed and
@@ -1836,7 +1835,7 @@ pk_client_resolve (PkClient *client, PkFilterEnum filters, gchar **packages, GEr
 /**
  * pk_client_get_details:
  * @client: a valid #PkClient instance
- * @package_id: a package_id structure such as "gnome-power-manager;0.0.1;i386;fedora"
+ * @package_ids: an array of package_id structures such as "gnome-power-manager;0.0.1;i386;fedora"
  * @error: a %GError to put the error code and message in, or %NULL
  *
  * Get details of a package, so more information can be obtained for GUI
@@ -1897,7 +1896,7 @@ pk_client_get_details (PkClient *client, gchar **package_ids, GError **error)
 /**
  * pk_client_get_files:
  * @client: a valid #PkClient instance
- * @package_id: a package_id structure such as "gnome-power-manager;0.0.1;i386;fedora"
+ * @package_ids: an array of package_id structures such as "gnome-power-manager;0.0.1;i386;fedora"
  * @error: a %GError to put the error code and message in, or %NULL
  *
  * Get the file list (i.e. a list of files installed) for the specified package.
diff --git a/libpackagekit/pk-update-detail-list.c b/libpackagekit/pk-update-detail-list.c
index 0b0562f..a18b860 100644
--- a/libpackagekit/pk-update-detail-list.c
+++ b/libpackagekit/pk-update-detail-list.c
@@ -49,6 +49,9 @@ static gpointer pk_update_detail_list_object = NULL;
 
 /**
  * pk_update_detail_list_clear:
+ * @list: a valid #PkUpdateDetailList instance
+ *
+ * Clears the package list
  **/
 gboolean
 pk_update_detail_list_clear (PkUpdateDetailList *list)
@@ -59,6 +62,10 @@ pk_update_detail_list_clear (PkUpdateDetailList *list)
 
 /**
  * pk_update_detail_list_add_obj:
+ * @list: a valid #PkUpdateDetailList instance
+ * @obj: a valid #PkUpdateDetailObj object
+ *
+ * Adds a copy of the object to the list
  **/
 gboolean
 pk_update_detail_list_add_obj (PkUpdateDetailList *list, const PkUpdateDetailObj *obj)
@@ -82,6 +89,10 @@ pk_update_detail_list_add_obj (PkUpdateDetailList *list, const PkUpdateDetailObj
 
 /**
  * pk_update_detail_list_get_obj:
+ * @list: a valid #PkUpdateDetailList instance
+ * @package_id: A %package_id such as "gnome-power-manager;0.0.1;i386;fedora"
+ *
+ * Gets an object from the list
  **/
 const PkUpdateDetailObj *
 pk_update_detail_list_get_obj (PkUpdateDetailList *list, const gchar *package_id)
@@ -106,6 +117,7 @@ pk_update_detail_list_get_obj (PkUpdateDetailList *list, const gchar *package_id
 
 /**
  * pk_update_detail_list_finalize:
+ * @object: a valid #PkUpdateDetailList instance
  **/
 static void
 pk_update_detail_list_finalize (GObject *object)
@@ -130,6 +142,7 @@ pk_update_detail_list_finalize (GObject *object)
 
 /**
  * pk_update_detail_list_class_init:
+ * @klass: a valid #PkUpdateDetailListClass instance
  **/
 static void
 pk_update_detail_list_class_init (PkUpdateDetailListClass *klass)
@@ -141,10 +154,9 @@ pk_update_detail_list_class_init (PkUpdateDetailListClass *klass)
 
 /**
  * pk_update_detail_list_init:
+ * @list: a valid #PkUpdateDetailList instance
  *
- * initializes the update_detail_list class. NOTE: We expect list objects
- * to *NOT* be removed or added during the session.
- * We only control the first list object if there are more than one.
+ * Initializes the update_detail_list class.
  **/
 static void
 pk_update_detail_list_init (PkUpdateDetailList *list)
@@ -155,6 +167,7 @@ pk_update_detail_list_init (PkUpdateDetailList *list)
 
 /**
  * pk_update_detail_list_new:
+ *
  * Return value: A new list class instance.
  **/
 PkUpdateDetailList *
commit bacb637083778a3b64dc55ec71d789c5d2bee0f1
Author: Richard Hughes <richard at hughsie.com>
Date:   Wed Jun 25 13:44:58 2008 +0100

    check all the internal and public functions with flawfinder and fix any reports

diff --git a/client/pk-console.c b/client/pk-console.c
index 1fcf4e5..5df4da2 100644
--- a/client/pk-console.c
+++ b/client/pk-console.c
@@ -685,7 +685,7 @@ pk_console_get_prompt (const gchar *question, gboolean defaultyes)
 	}
 
 	do {
-		/* get one char */
+		/* ITS4: ignore, we are copying into the same variable, not a string */
 		answer = (gchar) getchar();
 
 		/* positive */
diff --git a/client/pk-import-desktop.c b/client/pk-import-desktop.c
index b523d07..5194471 100644
--- a/client/pk-import-desktop.c
+++ b/client/pk-import-desktop.c
@@ -110,7 +110,7 @@ pk_import_get_locale (const gchar *buffer)
 		return NULL;
 	}
 	locale = g_strdup (result+1);
-	len = strlen (locale);
+	len = pk_strlen (locale, 20);
 	locale[len-1] = '\0';
 	return locale;
 }
@@ -230,7 +230,7 @@ pk_desktop_process_directory (const gchar *directory)
 	pattern = g_pattern_spec_new ("*.desktop");
 	name = g_dir_read_name (dir);
 	while (name != NULL) {
-		/* ITS4: ignore, not used for allocation */
+		/* ITS4: ignore, not used for allocation and has to be NULL terminated */
 		match = g_pattern_match (pattern, strlen (name), name, NULL);
 		if (match) {
 			filename = g_build_filename (directory, name, NULL);
diff --git a/libpackagekit/pk-client.c b/libpackagekit/pk-client.c
index 37a6189..8416dbf 100644
--- a/libpackagekit/pk-client.c
+++ b/libpackagekit/pk-client.c
@@ -2477,6 +2477,7 @@ pk_resolve_local_path (const gchar *rel_path)
 		return NULL;
 	}
 
+	/* ITS4: ignore, glibc allocates us a buffer to try and fix some brain damage */
 	temp = realpath (rel_path, NULL);
 	if (temp != NULL) {
 		real = g_strdup (temp);
diff --git a/libpackagekit/pk-common.c b/libpackagekit/pk-common.c
index 83da6fd..b537fdd 100644
--- a/libpackagekit/pk-common.c
+++ b/libpackagekit/pk-common.c
@@ -324,13 +324,14 @@ pk_strnumber (const gchar *text)
 		return FALSE;
 	}
 
-	/* ITS4: ignore, not used for allocation and checked for oversize */
-	length = strlen (text);
+	/* max length is 10 */
+	length = pk_strlen (text, 10);
+	if (length == 10) {
+		pk_debug ("input too long!");
+		return FALSE;
+	}
+
 	for (i=0; i<length; i++) {
-		if (i > 10) {
-			pk_debug ("input too long!");
-			return FALSE;
-		}
 		if (i == 0 && text[i] == '-') {
 			/* negative sign */
 		} else if (g_ascii_isdigit (text[i]) == FALSE) {
@@ -413,26 +414,30 @@ pk_strzero (const gchar *text)
 /**
  * pk_strlen:
  * @text: The text to check
- * @max_length: The maximum length of the string
+ * @len: The maximum length of the string
  *
  * This function is a much safer way of doing strlen as it checks for NULL and
  * a stupidly long string.
- * This also modifies the string in place if it is over-range by inserting
- * a NULL at the max_length.
  *
- * Return value: the length of the string, or max_length.
+ * Return value: the length of the string, or len if the string is too long.
  **/
 guint
-pk_strlen (gchar *text, guint max_length)
+pk_strlen (const gchar *text, guint len)
 {
-	guint length;
-	/* ITS4: ignore, not used for allocation and checked */
-	length = strlen (text);
-	if (length > max_length) {
-		text[max_length] = '\0';
-		return max_length;
+	guint i;
+
+	/* common case */
+	if (text == NULL || text[0] == '\0') {
+		return 0;
+	}
+
+	/* only count up to len */
+	for (i=1; i<len; i++) {
+		if (text[i] == '\0') {
+			break;
+		}
 	}
-	return length;
+	return i;
 }
 
 /**
@@ -449,13 +454,14 @@ pk_strvalidate (const gchar *text)
 	guint i;
 	guint length;
 
-	/* ITS4: ignore, not used for allocation and checked for oversize */
-	length = strlen (text);
+	/* maximum size is 1024 */
+	length = pk_strlen (text, 1024);
+	if (length > 1024) {
+		pk_debug ("input too long!");
+		return FALSE;
+	}
+
 	for (i=0; i<length; i++) {
-		if (i > 1024) {
-			pk_debug ("input too long!");
-			return FALSE;
-		}
 		if (pk_strvalidate_char (text[i]) == FALSE) {
 			pk_debug ("invalid char '%c' in text!", text[i]);
 			return FALSE;
@@ -492,9 +498,8 @@ pk_strsplit (const gchar *id, guint parts)
 		goto out;
 	}
 
-	/* ITS4: ignore, not used for allocation */
+	/* name has to be valid */
 	if (pk_strzero (sections[0])) {
-		/* name has to be valid */
 		pk_warning ("ident first section is empty");
 		goto out;
 	}
@@ -606,6 +611,7 @@ gchar *
 pk_strpad (const gchar *data, guint length)
 {
 	gint size;
+	guint data_len;
 	gchar *text;
 	gchar *padding;
 
@@ -614,7 +620,10 @@ pk_strpad (const gchar *data, guint length)
 	}
 
 	/* ITS4: ignore, only used for formatting */
-	size = (length - strlen(data));
+	data_len = strlen (data);
+
+	/* calculate */
+	size = (length - data_len);
 	if (size <= 0) {
 		return g_strdup (data);
 	}
@@ -1308,25 +1317,30 @@ libst_common (LibSelfTest *test)
 	 ****************          strlen          ******************
 	 ************************************************************/
 	libst_title (test, "strlen bigger");
-	text_safe = g_strdup ("123456789");
-	length = pk_strlen (text_safe, 20);
-	if (length == 9 && pk_strequal (text_safe, "123456789")) {
+	length = pk_strlen ("123456789", 20);
+	if (length == 9) {
 		libst_success (test, NULL);
 	} else {
-		libst_failed (test, "failed the strlen %i,'%s'", length, text_safe);
+		libst_failed (test, "failed the strlen %i", length);
 	}
-	g_free (text_safe);
 
 	/************************************************************/
 	libst_title (test, "strlen smaller");
-	text_safe = g_strdup ("123456789");
-	length = pk_strlen (text_safe, 5);
-	if (length == 5 && pk_strequal (text_safe, "12345")) {
+	length = pk_strlen ("123456789", 5);
+	if (length == 5) {
 		libst_success (test, NULL);
 	} else {
-		libst_failed (test, "failed the strlen %i,'%s'", length, text_safe);
+		libst_failed (test, "failed the strlen %i", length);
+	}
+
+	/************************************************************/
+	libst_title (test, "strlen correct");
+	length = pk_strlen ("123456789", 9);
+	if (length == 9) {
+		libst_success (test, NULL);
+	} else {
+		libst_failed (test, "failed the strlen %i", length);
 	}
-	g_free (text_safe);
 
 	/************************************************************
 	 ****************         Padding          ******************
diff --git a/libpackagekit/pk-common.h b/libpackagekit/pk-common.h
index f5b2aba..e02a67d 100644
--- a/libpackagekit/pk-common.h
+++ b/libpackagekit/pk-common.h
@@ -54,8 +54,8 @@ G_BEGIN_DECLS
  */
 #define	PK_DBUS_INTERFACE_TRANSACTION	"org.freedesktop.PackageKit.Transaction"
 
-guint		 pk_strlen				(gchar		*text,
-							 guint		 max_length)
+guint		 pk_strlen				(const gchar	*text,
+							 guint		 len)
 							 G_GNUC_WARN_UNUSED_RESULT;
 gboolean	 pk_strzero				(const gchar	*text)
 							 G_GNUC_WARN_UNUSED_RESULT;
diff --git a/libpackagekit/pk-debug.c b/libpackagekit/pk-debug.c
index 2f632b5..0b8c142 100644
--- a/libpackagekit/pk-debug.c
+++ b/libpackagekit/pk-debug.c
@@ -84,7 +84,7 @@ pk_set_console_mode (guint console_code)
 		return;
 	}
 	/* Command is the control command to the terminal */
-	sprintf (command, "%c[%dm", 0x1B, console_code);
+	g_snprintf (command, 13, "%c[%dm", 0x1B, console_code);
 	printf ("%s", command);
 }
 
@@ -98,12 +98,14 @@ pk_log_line (const gchar *buffer)
 	/* open a file */
 	if (fd == -1) {
 		mkdir (PK_LOG_DIR, 0777);
+		/* ITS4: ignore, /var/log/PackageKit is owned by root, and this is just debug text */
 		fd = open (PK_LOG_FILE, O_WRONLY|O_APPEND|O_CREAT, 0777);
 		if (fd == -1) {
 			g_error ("could not open log: '%s'", PK_LOG_FILE);
 		}
 	}
-	/* whole line */
+
+	/* ITS4: ignore, debug text always NULL terminated */
 	count = write (fd, buffer, strlen (buffer));
 	if (count == -1) {
 		g_warning ("could not write %s", buffer);
diff --git a/libpackagekit/pk-extra.c b/libpackagekit/pk-extra.c
index d0f0776..ce1ec02 100644
--- a/libpackagekit/pk-extra.c
+++ b/libpackagekit/pk-extra.c
@@ -280,11 +280,7 @@ pk_extra_set_locale (PkExtra *extra, const gchar *locale)
 	extra->priv->locale_base = g_strdup (locale);
 
 	/* we only want the first section to compare */
-	len = strlen (locale);
-	if (len > 10) {
-		pk_warning ("locale really long (%i), truncating to 10", len);
-		len = 10;
-	}
+	len = pk_strlen (locale, 10);
 	for (i=0; i<len; i++) {
 		if (extra->priv->locale_base[i] == '_') {
 			extra->priv->locale_base[i] = '\0';
diff --git a/libpackagekit/pk-package-ids.c b/libpackagekit/pk-package-ids.c
index ad6f232..3bf7acd 100644
--- a/libpackagekit/pk-package-ids.c
+++ b/libpackagekit/pk-package-ids.c
@@ -193,8 +193,11 @@ pk_package_ids_to_text (gchar **package_ids, const gchar *delimiter)
 		g_string_append (string, package_ids[i]);
 		g_string_append (string, delimiter);
 	}
-	/* remove trailing delimiter */
+
+	/* ITS4: ignore, we check this for validity */
 	size = strlen (delimiter);
+
+	/* remove trailing delimiter */
 	if (string->len > size) {
 		g_string_set_size (string, string->len-size);
 	}
diff --git a/src/pk-spawn.c b/src/pk-spawn.c
index 7d45eaa..c794078 100644
--- a/src/pk-spawn.c
+++ b/src/pk-spawn.c
@@ -106,7 +106,7 @@ pk_spawn_emit_whole_lines (PkSpawn *spawn, GString *string)
 	gchar **lines;
 	guint bytes_processed;
 
-	/* ITS4: ignore, GString is always NULL terminated */
+	/* if nothing then don't emit */
 	if (pk_strzero (string->str)) {
 		return FALSE;
 	}
diff --git a/src/pk-transaction.c b/src/pk-transaction.c
index 62c6146..88c0455 100644
--- a/src/pk-transaction.c
+++ b/src/pk-transaction.c
@@ -967,8 +967,8 @@ pk_transaction_search_check (const gchar *search, GError **error)
 	guint size;
 	gboolean ret;
 
-	/* ITS4: ignore, not used for allocation, and checked */
-	size = strlen (search);
+	/* limit to a 1k chunk */
+	size = pk_strlen (search, 1024);
 
 	if (search == NULL) {
 		*error = g_error_new (PK_TRANSACTION_ERROR, PK_TRANSACTION_ERROR_SEARCH_INVALID,
@@ -985,7 +985,7 @@ pk_transaction_search_check (const gchar *search, GError **error)
 				     "The search string length is too small");
 		return FALSE;
 	}
-	if (size > 1024) {
+	if (size == 1024) {
 		*error = g_error_new (PK_TRANSACTION_ERROR, PK_TRANSACTION_ERROR_SEARCH_INVALID,
 				     "The search string length is too large");
 		return FALSE;
commit 5f44e795f10d9c24129a8b7651c0724a19b13f1c
Author: Richard Hughes <richard at hughsie.com>
Date:   Wed Jun 25 13:02:36 2008 +0100

    trivial: fix the struct size on the other backends so they can still compile

diff --git a/backends/alpm/pk-backend-alpm.c b/backends/alpm/pk-backend-alpm.c
index c6767ed..49fc22d 100644
--- a/backends/alpm/pk-backend-alpm.c
+++ b/backends/alpm/pk-backend-alpm.c
@@ -1547,6 +1547,7 @@ PK_BACKEND_OPTIONS (
 		backend_get_groups,				/* get_groups */
 		backend_get_filters,				/* get_filters */
 		backend_get_cancel,				/* cancel */
+		NULL,						/* download_packages */
 		backend_get_depends,				/* get_depends */
 		backend_get_details,				/* get_details */
 		backend_get_files,				/* get_files */
diff --git a/backends/apt.deprecated/pk-backend-apt.c b/backends/apt.deprecated/pk-backend-apt.c
index 2d8addd..a8a9389 100644
--- a/backends/apt.deprecated/pk-backend-apt.c
+++ b/backends/apt.deprecated/pk-backend-apt.c
@@ -240,6 +240,7 @@ PK_BACKEND_OPTIONS (
 	backend_get_groups,			/* get_groups */
 	backend_get_filters,			/* get_filters */
 	NULL,					/* cancel */
+	NULL,					/* download_packages */
 	backend_get_depends,			/* get_depends */
 	backend_get_details,			/* get_details */
 	NULL,					/* get_files */
diff --git a/backends/apt/pk-backend-apt.c b/backends/apt/pk-backend-apt.c
index 0c5f176..759e636 100644
--- a/backends/apt/pk-backend-apt.c
+++ b/backends/apt/pk-backend-apt.c
@@ -195,6 +195,7 @@ PK_BACKEND_OPTIONS (
 	backend_get_groups,			/* get_groups */
 	backend_get_filters,			/* get_filters */
 	backend_cancel,				/* cancel */
+	NULL,					/* download_packages */
 	NULL,					/* get_depends */
 	backend_get_details,			/* get_details */
 	NULL,					/* get_files */
diff --git a/backends/box/pk-backend-box.c b/backends/box/pk-backend-box.c
index e22d7b1..6d417cf 100644
--- a/backends/box/pk-backend-box.c
+++ b/backends/box/pk-backend-box.c
@@ -666,6 +666,7 @@ PK_BACKEND_OPTIONS (
 	NULL,					/* get_groups */
 	backend_get_filters,			/* get_filters */
 	NULL,					/* cancel */
+	NULL,					/* download_packages */
 	backend_get_depends,			/* get_depends */
 	backend_get_details,			/* get_details */
 	backend_get_files,			/* get_files */
diff --git a/backends/conary/pk-backend-conary.c b/backends/conary/pk-backend-conary.c
index b8da8a9..54c6405 100644
--- a/backends/conary/pk-backend-conary.c
+++ b/backends/conary/pk-backend-conary.c
@@ -268,8 +268,9 @@ PK_BACKEND_OPTIONS (
 	backend_get_groups,			/* get_groups */
 	backend_get_filters,			/* get_filters */
 	backend_cancel,				/* cancel */
+	NULL,					/* download_packages */
 	NULL,					/* get_depends */
-	backend_get_details,		/* get_details */
+	backend_get_details,			/* get_details */
 	backend_get_files,			/* get_files */
 	NULL,					/* get_packages */
 	NULL,					/* get_repo_list */
diff --git a/backends/opkg/pk-backend-opkg.c b/backends/opkg/pk-backend-opkg.c
index 0050d0e..cf6cb3c 100644
--- a/backends/opkg/pk-backend-opkg.c
+++ b/backends/opkg/pk-backend-opkg.c
@@ -713,6 +713,7 @@ PK_BACKEND_OPTIONS (
 	backend_get_groups,			/* get_groups */
 	backend_get_filters,			/* get_filters */
 	NULL,					/* cancel */
+	NULL,					/* download_packages */
 	NULL,					/* get_depends */
 	backend_get_details,			/* get_details */
 	NULL,					/* get_files */
diff --git a/backends/pisi/pk-backend-pisi.c b/backends/pisi/pk-backend-pisi.c
index 0b792bc..dc4f7fc 100644
--- a/backends/pisi/pk-backend-pisi.c
+++ b/backends/pisi/pk-backend-pisi.c
@@ -348,8 +348,9 @@ PK_BACKEND_OPTIONS (
 	backend_get_groups,			/* get_groups */
 	backend_get_filters,			/* get_filters */
 	backend_cancel,				/* cancel */
+	NULL,					/* download_packages */
 	backend_get_depends,			/* get_depends */
-	backend_get_details,		/* get_details */
+	backend_get_details,			/* get_details */
 	backend_get_files,			/* get_files */
 	NULL,					/* get_packages */
 	backend_get_repo_list,			/* get_repo_list */
diff --git a/backends/poldek/pk-backend-poldek.c b/backends/poldek/pk-backend-poldek.c
index afdfb21..27528a1 100644
--- a/backends/poldek/pk-backend-poldek.c
+++ b/backends/poldek/pk-backend-poldek.c
@@ -2643,6 +2643,7 @@ PK_BACKEND_OPTIONS (
 	backend_get_groups,				/* get_groups */
 	backend_get_filters,				/* get_filters */
 	backend_get_cancel,				/* cancel */
+	NULL,						/* download_packages */
 	backend_get_depends,				/* get_depends */
 	backend_get_details,				/* get_details */
 	backend_get_files,				/* get_files */
diff --git a/backends/smart/pk-backend-smart.c b/backends/smart/pk-backend-smart.c
index 762ee93..73f83a0 100644
--- a/backends/smart/pk-backend-smart.c
+++ b/backends/smart/pk-backend-smart.c
@@ -271,6 +271,7 @@ PK_BACKEND_OPTIONS (
 	NULL,						/* get_groups */
 	NULL,						/* get_filters */
 	NULL,						/* cancel */
+	NULL,						/* download_packages */
 	backend_get_depends,				/* get_depends */
 	backend_get_details,				/* get_details */
 	backend_get_files,				/* get_files */
diff --git a/backends/test/pk-backend-test-dbus.c b/backends/test/pk-backend-test-dbus.c
index 76686dc..28e2969 100644
--- a/backends/test/pk-backend-test-dbus.c
+++ b/backends/test/pk-backend-test-dbus.c
@@ -81,6 +81,7 @@ PK_BACKEND_OPTIONS (
 	NULL,					/* get_groups */
 	NULL,					/* get_filters */
 	backend_cancel,				/* cancel */
+	NULL,					/* download_packages */
 	NULL,					/* get_depends */
 	NULL,					/* get_details */
 	NULL,					/* get_files */
diff --git a/backends/test/pk-backend-test-fail.c b/backends/test/pk-backend-test-fail.c
index 2dbeb00..0f343ce 100644
--- a/backends/test/pk-backend-test-fail.c
+++ b/backends/test/pk-backend-test-fail.c
@@ -251,6 +251,7 @@ PK_BACKEND_OPTIONS (
 	backend_get_groups,			/* get_groups */
 	backend_get_filters,			/* get_filters */
 	backend_cancel,				/* cancel */
+	NULL,					/* download_packages */
 	backend_get_depends,			/* get_depends */
 	backend_get_details,			/* get_details */
 	backend_get_files,			/* get_files */
diff --git a/backends/test/pk-backend-test-nop.c b/backends/test/pk-backend-test-nop.c
index 3526fa5..4d484d9 100644
--- a/backends/test/pk-backend-test-nop.c
+++ b/backends/test/pk-backend-test-nop.c
@@ -31,6 +31,7 @@ PK_BACKEND_OPTIONS (
 	NULL,					/* get_groups */
 	NULL,					/* get_filters */
 	NULL,					/* cancel */
+	NULL,					/* download_packages */
 	NULL,					/* get_depends */
 	NULL,					/* get_details */
 	NULL,					/* get_files */
diff --git a/backends/test/pk-backend-test-spawn.c b/backends/test/pk-backend-test-spawn.c
index 584f44c..fd4cc0b 100644
--- a/backends/test/pk-backend-test-spawn.c
+++ b/backends/test/pk-backend-test-spawn.c
@@ -72,6 +72,7 @@ PK_BACKEND_OPTIONS (
 	NULL,					/* get_groups */
 	NULL,					/* get_filters */
 	NULL,					/* cancel */
+	NULL,					/* download_packages */
 	NULL,					/* get_depends */
 	NULL,					/* get_details */
 	NULL,					/* get_files */
diff --git a/backends/test/pk-backend-test-succeed.c b/backends/test/pk-backend-test-succeed.c
index 168f8be..86335a4 100644
--- a/backends/test/pk-backend-test-succeed.c
+++ b/backends/test/pk-backend-test-succeed.c
@@ -320,8 +320,9 @@ PK_BACKEND_OPTIONS (
 	backend_get_groups,			/* get_groups */
 	backend_get_filters,			/* get_filters */
 	backend_cancel,				/* cancel */
+	NULL,					/* download_packages */
 	backend_get_depends,			/* get_depends */
-	backend_get_details,		/* get_details */
+	backend_get_details,			/* get_details */
 	backend_get_files,			/* get_files */
 	backend_get_packages,			/* get_packages */
 	backend_get_repo_list,			/* get_repo_list */
diff --git a/backends/test/pk-backend-test-thread.c b/backends/test/pk-backend-test-thread.c
index 46ee862..9442313 100644
--- a/backends/test/pk-backend-test-thread.c
+++ b/backends/test/pk-backend-test-thread.c
@@ -144,6 +144,7 @@ PK_BACKEND_OPTIONS (
 	NULL,					/* get_groups */
 	NULL,					/* get_filters */
 	backend_cancel,				/* cancel */
+	NULL,					/* download_packages */
 	NULL,					/* get_depends */
 	NULL,					/* get_details */
 	NULL,					/* get_files */
diff --git a/backends/urpmi/pk-backend-urpmi.c b/backends/urpmi/pk-backend-urpmi.c
index 2a78f72..8698555 100644
--- a/backends/urpmi/pk-backend-urpmi.c
+++ b/backends/urpmi/pk-backend-urpmi.c
@@ -334,22 +334,23 @@ PK_BACKEND_OPTIONS (
 	backend_destroy,			/* destroy */
 	backend_get_groups,			/* get_groups */
 	backend_get_filters,			/* get_filters */
-	NULL,				/* cancel */
+	NULL,					/* cancel */
+	NULL,					/* download_packages */
 	backend_get_depends,			/* get_depends */
 	backend_get_details,			/* get_details */
 	backend_get_files,			/* get_files */
 	backend_get_packages,			/* get_packages */
-	NULL,			/* get_repo_list */
+	NULL,					/* get_repo_list */
 	backend_get_requires,			/* get_requires */
 	backend_get_update_detail,		/* get_update_detail */
 	backend_get_updates,			/* get_updates */
-	NULL,			/* install_files */
+	NULL,					/* install_files */
 	backend_install_packages,		/* install_packages */
-	NULL,		/* install_signature */
+	NULL,					/* install_signature */
 	backend_refresh_cache,			/* refresh_cache */
 	backend_remove_packages,		/* remove_packages */
-	NULL,			/* repo_enable */
-	NULL,			/* repo_set_data */
+	NULL,					/* repo_enable */
+	NULL,					/* repo_set_data */
 	backend_resolve,			/* resolve */
 	NULL,					/* rollback */
 	backend_search_details,			/* search_details */
@@ -359,6 +360,6 @@ PK_BACKEND_OPTIONS (
 	NULL,					/* service_pack */
 	backend_update_packages,		/* update_packages */
 	backend_update_system,			/* update_system */
-	NULL			/* what_provides */
+	NULL					/* what_provides */
 );
 
diff --git a/backends/yum2/pk-backend-yum2.c b/backends/yum2/pk-backend-yum2.c
index 01a317d..82af287 100644
--- a/backends/yum2/pk-backend-yum2.c
+++ b/backends/yum2/pk-backend-yum2.c
@@ -317,6 +317,7 @@ PK_BACKEND_OPTIONS (
 	backend_get_groups,			/* get_groups */
 	backend_get_filters,			/* get_filters */
 	backend_cancel,				/* cancel */
+	NULL,					/* download_packages */
 	backend_get_depends,			/* get_depends */
 	backend_get_details,			/* get_details */
 	backend_get_files,			/* get_files */
diff --git a/backends/zypp/pk-backend-zypp.cpp b/backends/zypp/pk-backend-zypp.cpp
index d292bb5..fb08591 100644
--- a/backends/zypp/pk-backend-zypp.cpp
+++ b/backends/zypp/pk-backend-zypp.cpp
@@ -1703,6 +1703,7 @@ extern "C" PK_BACKEND_OPTIONS (
 	backend_get_groups,			/* get_groups */
 	backend_get_filters,			/* get_filters */
 	NULL,					/* cancel */
+	NULL,					/* download_packages */
 	backend_get_depends,			/* get_depends */
 	backend_get_details,			/* get_details */
 	backend_get_files,			/* get_files */
commit 3423751b5a2da21ef7ebdf5fa5eade4e043db932
Author: Shishir Goyal <crazyontheedge at gmail.com>
Date:   Wed Jun 25 12:58:19 2008 +0100

    add a new method DownloadPackages() to be able to create ServicePacks

diff --git a/backends/dummy/pk-backend-dummy.c b/backends/dummy/pk-backend-dummy.c
index 219a923..0aa4314 100644
--- a/backends/dummy/pk-backend-dummy.c
+++ b/backends/dummy/pk-backend-dummy.c
@@ -795,6 +795,20 @@ backend_get_packages (PkBackend *backend, PkFilterEnum filters)
 	pk_backend_finished (backend);
 }
 
+/**
+ * backend_download_packages:
+ */
+static void
+backend_download_packages (PkBackend *backend, gchar **package_ids, const gchar *directory)
+{
+	pk_backend_set_status (backend, PK_STATUS_ENUM_DOWNLOAD);
+	pk_backend_package (backend, PK_INFO_ENUM_DOWNLOADING,
+			    "powertop;1.8-1.fc8;i386;fedora", "Power consumption monitor");
+	pk_backend_package (backend, PK_INFO_ENUM_DOWNLOADING,
+			    "gtk2;gtk2-2.11.6-6.fc8;i386;fedora", "GTK+ Libraries for GIMP");
+	pk_backend_finished (backend);
+}
+
 PK_BACKEND_OPTIONS (
 	"Dummy",				/* description */
 	"Richard Hughes <richard at hughsie.com>",	/* author */
@@ -803,6 +817,7 @@ PK_BACKEND_OPTIONS (
 	backend_get_groups,			/* get_groups */
 	backend_get_filters,			/* get_filters */
 	backend_cancel,				/* cancel */
+	backend_download_packages,		/* download_packages */
 	backend_get_depends,			/* get_depends */
 	backend_get_details,			/* get_details */
 	backend_get_files,			/* get_files */
diff --git a/backends/yum/helpers/download-packages.py b/backends/yum/helpers/download-packages.py
new file mode 100644
index 0000000..512bc6a
--- /dev/null
+++ b/backends/yum/helpers/download-packages.py
@@ -0,0 +1,20 @@
+#!/usr/bin/python
+#
+#
+# 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.
+
+import sys
+
+from yumBackend import PackageKitYumBackend
+directory = sys.argv[1]
+packages = sys.argv[2:]
+
+backend = PackageKitYumBackend(sys.argv[1:])
+backend.download_packages(directory, packages)
+sys.exit(0)
+
diff --git a/backends/yum/helpers/yumBackend.py b/backends/yum/helpers/yumBackend.py
index cbcb90d..1e519fe 100644
--- a/backends/yum/helpers/yumBackend.py
+++ b/backends/yum/helpers/yumBackend.py
@@ -629,6 +629,39 @@ class PackageKitYumBackend(PackageKitBaseBackend):
                         self._show_package(pkg,INFO_AVAILABLE)
                         found[str(pkg)] = 1
 
+    @handle_repo_error
+    def download_packages(self,packages,directory)
+	'''
+	Implement the {backend}-download-packages functionality
+	'''
+	self._check_init()
+	self.allow_cancel(True)
+	self.percentage(0)
+	self.status(STATUS_DOWNLOAD)
+	for package in packages:
+	    pkg,inst = self._findPackage(package)
+	    for pkg in packages:
+	        n,a,e,v,r = pkg.pkgtup
+	        packs = self.pkgSack.searchNevra(n,e,v,r,a)
+	        for download in packs:
+	            repo = self.repos.getRepo(download.repoid)
+	            remote = download.returnSimple('relativepath')
+	            local = os.path.basename(remote)
+	            if not os.path.exists(directory):
+	                self.error(ERROR_PACKAGE_DOWNLOAD_FAILED,"No destination directory exists")
+	            local = os.path.join(directory,local)
+	            if(os.path.exists(local) and os.path.getsize(local) == int(download.returnSimple('packagesize'))):
+	                self.error(ERROR_PACKAGE_DOWNLOAD_FAILED,"Package already exists")
+	                continue
+	            # Disable cache otherwise things won't download
+	            repo.cache = 0
+	            download.localpath = local #Hack:To set the localpath we want
+	            try:
+	                path = repo.getPackage(download)
+	            except IOError, e:
+	                self.error(ERROR_WRITE_ERROR,"Cannot write to file")
+	                continue
+
     def _getEVR(self,idver):
         '''
         get the e,v,r from the package id version
diff --git a/backends/yum/pk-backend-yum.c b/backends/yum/pk-backend-yum.c
index 21350ec..1acdbad 100644
--- a/backends/yum/pk-backend-yum.c
+++ b/backends/yum/pk-backend-yum.c
@@ -113,6 +113,20 @@ backend_cancel (PkBackend *backend)
 }
 
 /**
+ * backend_download_packages:
+ */
+static void
+backend_download_packages (PkBackend *backend, gchar **package_ids, const gchar *directory)
+{
+	gchar *package_ids_temp;
+
+	/* send the complete list as stdin */
+	package_ids_temp = pk_package_ids_to_text (package_ids, "|");
+	pk_backend_spawn_helper (spawn, "download-packages.py", directory, package_ids_temp, NULL);
+	g_free (package_ids_temp);
+}
+
+/**
  * backend_get_depends:
  */
 static void
@@ -429,6 +443,7 @@ PK_BACKEND_OPTIONS (
 	backend_get_groups,			/* get_groups */
 	backend_get_filters,			/* get_filters */
 	backend_cancel,				/* cancel */
+	backend_download_packages,		/* download_packages */
 	backend_get_depends,			/* get_depends */
 	backend_get_details,			/* get_details */
 	backend_get_files,			/* get_files */
diff --git a/libpackagekit/pk-enum.c b/libpackagekit/pk-enum.c
index 6a79fbb..d96bd9f 100644
--- a/libpackagekit/pk-enum.c
+++ b/libpackagekit/pk-enum.c
@@ -110,6 +110,7 @@ static PkEnumMatch enum_role[] = {
 	{PK_ROLE_ENUM_UPDATE_SYSTEM,		"update-system"},
 	{PK_ROLE_ENUM_WHAT_PROVIDES,		"what-provides"},
 	{PK_ROLE_ENUM_ACCEPT_EULA,		"accept-eula"},
+	{PK_ROLE_ENUM_DOWNLOAD_PACKAGES,	"download-packages"},
 	{0, NULL}
 };
 
diff --git a/libpackagekit/pk-enum.h b/libpackagekit/pk-enum.h
index 9481d44..c64c559 100644
--- a/libpackagekit/pk-enum.h
+++ b/libpackagekit/pk-enum.h
@@ -78,7 +78,8 @@ typedef enum {
 	PK_ROLE_ENUM_UPDATE_SYSTEM		= 1 << 24,
 	PK_ROLE_ENUM_WHAT_PROVIDES		= 1 << 25,
 	PK_ROLE_ENUM_ACCEPT_EULA		= 1 << 26,
-	PK_ROLE_ENUM_UNKNOWN			= 1 << 27
+	PK_ROLE_ENUM_DOWNLOAD_PACKAGES		= 1 << 27,
+	PK_ROLE_ENUM_UNKNOWN			= 1 << 28
 } PkRoleEnum;
 
 /**
diff --git a/python/packagekit/backend.py b/python/packagekit/backend.py
index 96cd50d..c46d977 100644
--- a/python/packagekit/backend.py
+++ b/python/packagekit/backend.py
@@ -446,6 +446,13 @@ class PackageKitBaseBackend:
         '''
         self.error(ERROR_NOT_SUPPORTED,"This function is not implemented in this backend")
 
+    def download_packages(self,directory,packages):
+	'''
+	Implement the {backend}-download-packages functionality
+	Needed to be implemented in a sub class
+	'''
+	self.error(ERROR_NOT_SUPPORTED,"This function is not implemented in this backend")
+
     def customTracebackHandler(self,tb):
         '''
         Custom Traceback Handler
diff --git a/src/pk-backend.h b/src/pk-backend.h
index 0cfac0e..336b88a 100644
--- a/src/pk-backend.h
+++ b/src/pk-backend.h
@@ -189,6 +189,9 @@ typedef struct {
 	PkGroupEnum	(*get_groups)			(PkBackend	*backend);
 	PkFilterEnum	(*get_filters)			(PkBackend	*backend);
 	void		(*cancel)			(PkBackend	*backend);
+	void		(*download_packages)		(PkBackend	*backend,
+							 gchar		**package_ids,
+							 const gchar	*directory);
 	void		(*get_depends)			(PkBackend	*backend,
 							 PkFilterEnum	 filters,
 							 gchar		**package_ids,
@@ -261,7 +264,7 @@ typedef struct {
 	gpointer	padding[10];
 } PkBackendDesc;
 
-#define PK_BACKEND_OPTIONS(description, author, initialize, destroy, get_filters, get_groups, cancel,	\
+#define PK_BACKEND_OPTIONS(description, author, initialize, destroy, get_filters, get_groups, cancel, download_packages, \
 			   get_depends, get_details, get_files, get_packages, get_repo_list, get_requires,	\
 			   get_update_detail, get_updates, install_files, install_packages,		\
 			   install_signature, refresh_cache, remove_packages, repo_enable,		\
@@ -275,6 +278,7 @@ typedef struct {
 		get_filters,		\
 		get_groups,		\
 		cancel,			\
+		download_packages,	\
 		get_depends,		\
 		get_details,		\
 		get_files,		\
diff --git a/src/pk-interface-transaction.xml b/src/pk-interface-transaction.xml
index e72d9a4..6ba188d 100644
--- a/src/pk-interface-transaction.xml
+++ b/src/pk-interface-transaction.xml
@@ -47,6 +47,36 @@
     </method>
 
     <!--*****************************************************************************************-->
+    <method name="DownloadPackages">
+      <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
+      <doc:doc>
+        <doc:description>
+          <doc:para>
+            This method downloads packages into a specified directory.
+          </doc:para>
+        </doc:description>
+      </doc:doc>
+      <arg type="as" name="package_ids" direction="in">
+        <doc:doc>
+          <doc:summary>
+            <doc:para>
+              An array of package IDs.
+            </doc:para>
+          </doc:summary>
+        </doc:doc>
+      </arg>
+      <arg type="s" name="directory" direction="in">
+        <doc:doc>
+          <doc:summary>
+            <doc:para>
+              The directory to install the packages into.
+            </doc:para>
+          </doc:summary>
+        </doc:doc>
+      </arg>
+    </method>
+
+    <!--*****************************************************************************************-->
     <method name="GetAllowCancel">
       <doc:doc>
         <doc:description>
diff --git a/src/pk-transaction.c b/src/pk-transaction.c
index 992997d..62c6146 100644
--- a/src/pk-transaction.c
+++ b/src/pk-transaction.c
@@ -111,6 +111,7 @@ struct PkTransactionPrivate
 	gchar			*cached_key_id;
 	gchar			*cached_parameter;
 	gchar			*cached_value;
+	gchar			*cached_directory;
 	PkProvidesEnum		 cached_provides;
 
 	guint			 signal_allow_cancel;
@@ -830,6 +831,8 @@ pk_transaction_set_running (PkTransaction *transaction)
 		desc->resolve (priv->backend, priv->cached_filters, priv->cached_package_ids);
 	} else if (priv->role == PK_ROLE_ENUM_ROLLBACK) {
 		desc->rollback (priv->backend, priv->cached_transaction_id);
+	} else if (priv->role == PK_ROLE_ENUM_DOWNLOAD_PACKAGES) {
+		desc->download_packages (priv->backend, priv->cached_package_ids, priv->cached_directory);
 	} else if (priv->role == PK_ROLE_ENUM_GET_DETAILS) {
 		desc->get_details (priv->backend, priv->cached_package_ids);
 	} else if (priv->role == PK_ROLE_ENUM_GET_FILES) {
@@ -1201,6 +1204,74 @@ pk_transaction_cancel (PkTransaction *transaction, GError **error)
 }
 
 /**
+ * pk_transaction_download_packages:
+ **/
+void
+pk_transaction_download_packages (PkTransaction *transaction, gchar **package_ids,
+				  const gchar *directory, DBusGMethodInvocation *context)
+{
+	gboolean ret;
+	GError *error;
+	gchar *sender;
+	gchar *package_ids_temp;
+
+	g_return_if_fail (PK_IS_TRANSACTION (transaction));
+	g_return_if_fail (transaction->priv->tid != NULL);
+
+	pk_debug ("DownloadPackages method called: %s, %s", package_ids[0], directory);
+
+	/* not implemented yet */
+	if (transaction->priv->backend->desc->download_packages == NULL) {
+	        error = g_error_new (PK_TRANSACTION_ERROR, PK_TRANSACTION_ERROR_NOT_SUPPORTED,
+	                             "Operation not yet supported by backend");
+	        pk_transaction_list_remove (transaction->priv->transaction_list, transaction);
+	        dbus_g_method_return_error (context, error);
+	        return;
+	}
+
+	/* check package_ids */
+	ret = pk_package_ids_check (package_ids);
+	if (ret == FALSE) {
+	        package_ids_temp = pk_package_ids_to_text (package_ids, ", ");
+	        error = g_error_new (PK_TRANSACTION_ERROR, PK_TRANSACTION_ERROR_PACKAGE_ID_INVALID,
+	                             "The package id's '%s' are not valid", package_ids_temp);
+	        g_free (package_ids_temp);
+	        dbus_g_method_return_error (context, error);
+	        return;
+	}
+
+	/* check if the action is allowed from this client - if not, set an error */
+	sender = dbus_g_method_get_sender (context);
+	ret = pk_transaction_action_is_allowed (transaction, sender, FALSE, PK_ROLE_ENUM_DOWNLOAD_PACKAGES, &error);
+	g_free (sender);
+	if  (!ret) {
+	        dbus_g_method_return_error (context, error);
+	        return;
+	}
+
+	/* set the dbus name, so we can get the disconnect */
+	pk_transaction_set_dbus_name (transaction, dbus_g_method_get_sender (context));
+
+	/* save so we can run later */
+	transaction->priv->cached_package_ids = g_strdupv (package_ids);
+	transaction->priv->cached_directory = g_strdup (directory);
+	transaction->priv->status = PK_STATUS_ENUM_WAIT;
+	pk_transaction_set_role (transaction, PK_ROLE_ENUM_DOWNLOAD_PACKAGES);
+
+	/* try to commit this */
+	ret = pk_transaction_commit (transaction);
+	if (!ret) {
+	        error = g_error_new (PK_TRANSACTION_ERROR, PK_TRANSACTION_ERROR_COMMIT_FAILED,
+	                             "Could not commit to a transaction object");
+	        pk_transaction_list_remove (transaction->priv->transaction_list, transaction);
+	        dbus_g_method_return_error (context, error);
+	        return;
+	}
+
+	dbus_g_method_return (context);
+}
+
+/**
  * pk_transaction_get_allow_cancel:
  **/
 gboolean
@@ -3106,6 +3177,7 @@ pk_transaction_finalize (GObject *object)
 	g_free (transaction->priv->cached_key_id);
 	g_strfreev (transaction->priv->cached_package_ids);
 	g_free (transaction->priv->cached_transaction_id);
+	g_free (transaction->priv->cached_directory);
 	g_free (transaction->priv->cached_search);
 	g_free (transaction->priv->cached_repo_id);
 	g_free (transaction->priv->cached_parameter);
diff --git a/src/pk-transaction.h b/src/pk-transaction.h
index e718f73..316d057 100644
--- a/src/pk-transaction.h
+++ b/src/pk-transaction.h
@@ -100,6 +100,10 @@ void		 pk_transaction_accept_eula		(PkTransaction	*transaction,
 							 DBusGMethodInvocation *context);
 gboolean	 pk_transaction_cancel			(PkTransaction	*transaction,
 							 GError		**error);
+void		 pk_transaction_download_packages	(PkTransaction  *transaction,
+							 gchar		**package_ids,
+							 const gchar	*directory,
+							 DBusGMethodInvocation *context);
 gboolean	 pk_transaction_get_allow_cancel	(PkTransaction	*transaction,
 							 gboolean	*allow_cancel,
 							 GError		**error);
commit b2e7378fa3718cc7887dcf9769d4d0cfd2afcae1
Author: Richard Hughes <richard at hughsie.com>
Date:   Wed Jun 25 12:35:15 2008 +0100

    abi: rename some source files and be more militant with const

diff --git a/NEWS b/NEWS
index ba896d2..5d89b82 100644
--- a/NEWS
+++ b/NEWS
@@ -73,9 +73,9 @@ Released: 2008-06-05
  - Updated Polish translation (Piotr DrÄ…g)
 
 * New features:
- - Add pk_package_item_copy() and allow freeing a NULL PkPackageItem without going boom (Richard Hughes)
+ - Add pk_package_obj_copy() and allow freeing a NULL PkPackageObj without going boom (Richard Hughes)
  - Allow setting 101 for backends for sub-percentages (Richard Hughes)
- - Add pk_package_list_add_item() and pk_package_list_contains_item() (Richard Hughes)
+ - Add pk_package_list_add_obj() and pk_package_list_contains_obj() (Richard Hughes)
  - Allow passing environment parameters to pk_spawn_argv (Richard Hughes)
  - Add support for http and ftp proxy servers in the daemon (Richard Hughes)
  - Allow adding and removing multiple packages at one time with pkcon (Richard Hughes)
diff --git a/client/pk-console.c b/client/pk-console.c
index fe672e8..1fcf4e5 100644
--- a/client/pk-console.c
+++ b/client/pk-console.c
@@ -38,7 +38,7 @@
 #include <pk-package-id.h>
 #include <pk-common.h>
 #include <pk-connection.h>
-#include <pk-update-detail.h>
+#include <pk-update-detail-obj.h>
 
 #define PROGRESS_BAR_SIZE 15
 
@@ -213,7 +213,7 @@ pk_console_transaction_cb (PkClient *client, const gchar *tid, const gchar *time
  * pk_console_update_detail_cb:
  **/
 static void
-pk_console_update_detail_cb (PkClient *client, const PkUpdateDetail *detail, gpointer data)
+pk_console_update_detail_cb (PkClient *client, const PkUpdateDetailObj *detail, gpointer data)
 {
 	if (awaiting_space) {
 		g_print ("\n");
@@ -483,7 +483,7 @@ pk_console_perhaps_resolve (PkClient *client, PkFilterEnum filter, const gchar *
 	gboolean valid;
 	guint i;
 	guint length;
-	PkPackageItem *item;
+	const PkPackageObj *item;
 	PkPackageList *list;
 	gchar **packages;
 
@@ -537,7 +537,7 @@ pk_console_perhaps_resolve (PkClient *client, PkFilterEnum filter, const gchar *
 
 	/* only found one, great! */
 	if (length == 1) {
-		item = pk_package_list_get_item (list, 0);
+		item = pk_package_list_get_obj (list, 0);
 		return g_strdup (item->package_id);
 	}
 
@@ -547,13 +547,13 @@ pk_console_perhaps_resolve (PkClient *client, PkFilterEnum filter, const gchar *
 	}
 	g_print ("%s\n", _("There are multiple package matches"));
 	for (i=0; i<length; i++) {
-		item = pk_package_list_get_item (list, i);
+		item = pk_package_list_get_obj (list, i);
 		g_print ("%i. %s\n", i+1, item->package_id);
 	}
 
 	/* find out what package the user wants to use */
 	i = pk_console_get_number (_("Please enter the package number: "), length);
-	item = pk_package_list_get_item (list, i-1);
+	item = pk_package_list_get_obj (list, i-1);
 	pk_debug ("package_id = %s", item->package_id);
 	g_object_unref (list);
 
@@ -718,7 +718,7 @@ pk_console_remove_packages (PkClient *client, gchar **packages, GError **error)
 {
 	gchar *package_id;
 	gboolean ret = TRUE;
-	PkPackageItem *item;
+	const PkPackageObj *item;
 	PkPackageId *ident;
 	guint i;
 	guint length;
@@ -797,7 +797,7 @@ pk_console_remove_packages (PkClient *client, gchar **packages, GError **error)
 	}
 	g_print ("%s:\n", _("The following packages have to be removed"));
 	for (i=0; i<length; i++) {
-		item = pk_package_list_get_item (list, i);
+		item = pk_package_list_get_obj (list, i);
 		ident = pk_package_id_new_from_string (item->package_id);
 		g_print ("%i\t%s-%s\n", i, ident->name, ident->version);
 		pk_package_id_free (ident);
@@ -996,7 +996,7 @@ pk_console_error_code_cb (PkClient *client, PkErrorCodeEnum error_code, const gc
  * pk_console_details_cb:
  **/
 static void
-pk_console_details_cb (PkClient *client, const PkDetails *details, gpointer data)
+pk_console_details_cb (PkClient *client, const PkDetailsObj *details, gpointer data)
 {
 	/* if on console, clear the progress bar line */
 	if (awaiting_space) {
diff --git a/client/pk-import-desktop.c b/client/pk-import-desktop.c
index bfe364f..b523d07 100644
--- a/client/pk-import-desktop.c
+++ b/client/pk-import-desktop.c
@@ -45,7 +45,7 @@ pk_desktop_get_name_for_file (const gchar *filename)
 {
 	guint size;
 	gchar *name = NULL;
-	PkPackageItem *item;
+	const PkPackageObj *item;
 	PkPackageId *pid;
 	gboolean ret;
 	GError *error = NULL;
@@ -75,7 +75,7 @@ pk_desktop_get_name_for_file (const gchar *filename)
 	}
 
 	/* get the item */
-	item = pk_package_list_get_item (list, 0);
+	item = pk_package_list_get_obj (list, 0);
 	if (item == NULL) {
 		pk_error ("cannot get item");
 		goto out;
diff --git a/client/pk-import-specspo.c b/client/pk-import-specspo.c
index bc010ee..c38374d 100644
--- a/client/pk-import-specspo.c
+++ b/client/pk-import-specspo.c
@@ -55,7 +55,7 @@ pk_import_specspo_get_summary (const gchar *name)
 {
 	guint size;
 	gboolean ret;
-	PkPackageItem *item;
+	const PkPackageObj *item;
 	GError *error = NULL;
 	PkPackageList *list;
 	gchar **names;
@@ -87,7 +87,7 @@ pk_import_specspo_get_summary (const gchar *name)
 	}
 
 	/* get the item */
-	item = pk_package_list_get_item (list, 0);
+	item = pk_package_list_get_obj (list, 0);
 	if (item == NULL) {
 		pk_error ("cannot get item");
 		g_object_unref (list);
diff --git a/libpackagekit/Makefile.am b/libpackagekit/Makefile.am
index f63c9b5..dfa24e0 100644
--- a/libpackagekit/Makefile.am
+++ b/libpackagekit/Makefile.am
@@ -38,10 +38,11 @@ libpackagekit_include_HEADERS =					\
 	pk-connection.h						\
 	pk-package-id.h						\
 	pk-package-ids.h					\
-	pk-package-item.h					\
+	pk-package-obj.h					\
 	pk-package-list.h					\
-	pk-update-detail.h					\
-	pk-details.h						\
+	pk-update-detail-obj.h					\
+	pk-update-detail-list.h					\
+	pk-details-obj.h					\
 	pk-enum.h						\
 	pk-common.h						\
 	pk-client.h						\
@@ -63,14 +64,16 @@ libpackagekit_la_SOURCES =					\
 	pk-package-id.h						\
 	pk-package-ids.c					\
 	pk-package-ids.h					\
-	pk-package-item.c					\
-	pk-package-item.h					\
+	pk-package-obj.c					\
+	pk-package-obj.h					\
 	pk-package-list.c					\
 	pk-package-list.h					\
-	pk-update-detail.c					\
-	pk-update-detail.h					\
-	pk-details.c						\
-	pk-details.h						\
+	pk-update-detail-obj.c					\
+	pk-update-detail-obj.h					\
+	pk-update-detail-list.c					\
+	pk-update-detail-list.h					\
+	pk-details-obj.c					\
+	pk-details-obj.h					\
 	pk-enum.h						\
 	pk-enum.c						\
 	pk-common.c						\
diff --git a/libpackagekit/pk-client.c b/libpackagekit/pk-client.c
index 4e3060f..37a6189 100644
--- a/libpackagekit/pk-client.c
+++ b/libpackagekit/pk-client.c
@@ -56,8 +56,8 @@
 #include "pk-marshal.h"
 #include "pk-common.h"
 #include "pk-control.h"
-#include "pk-update-detail.h"
-#include "pk-details.h"
+#include "pk-update-detail-obj.h"
+#include "pk-details-obj.h"
 
 static void     pk_client_class_init	(PkClientClass *klass);
 static void     pk_client_init		(PkClient      *client);
@@ -459,7 +459,7 @@ pk_client_get_require_restart (PkClient *client)
  * We do not provide access to the internal package list (as it could be being
  * updated) so provide a way to get access to objects here.
  *
- * Return value: The #PkPackageItem or %NULL if not found or invalid
+ * Return value: The #PkPackageObj or %NULL if not found or invalid
  **/
 PkPackageList *
 pk_client_get_package_list (PkClient *client)
@@ -595,7 +595,7 @@ pk_client_update_detail_cb (DBusGProxy  *proxy, const gchar *package_id, const g
 			    const gchar *cve_url, const gchar *restart_text, const gchar *update_text, PkClient *client)
 {
 	PkRestartEnum restart;
-	PkUpdateDetail *detail;
+	PkUpdateDetailObj *detail;
 
 	g_return_if_fail (PK_IS_CLIENT (client));
 
@@ -603,10 +603,10 @@ pk_client_update_detail_cb (DBusGProxy  *proxy, const gchar *package_id, const g
 		  package_id, updates, obsoletes, vendor_url, bugzilla_url, cve_url, restart_text, update_text);
 	restart = pk_restart_enum_from_text (restart_text);
 
-	detail = pk_update_detail_new_from_data (package_id, updates, obsoletes, vendor_url,
+	detail = pk_update_detail_obj_new_from_data (package_id, updates, obsoletes, vendor_url,
 						 bugzilla_url, cve_url, restart, update_text);
 	g_signal_emit (client, signals [PK_CLIENT_UPDATE_DETAIL], 0, detail);
-	pk_update_detail_free (detail);
+	pk_update_detail_obj_free (detail);
 }
 
 /**
@@ -618,7 +618,7 @@ pk_client_details_cb (DBusGProxy *proxy, const gchar *package_id, const gchar *l
 		      guint64 size, PkClient *client)
 {
 	PkGroupEnum group;
-	PkDetails *details;
+	PkDetailsObj *details;
 	g_return_if_fail (PK_IS_CLIENT (client));
 
 	group = pk_group_enum_from_text (group_text);
@@ -626,9 +626,9 @@ pk_client_details_cb (DBusGProxy *proxy, const gchar *package_id, const gchar *l
 	pk_debug ("emit details %s, %s, %s, %s, %s, %ld",
 		  package_id, license, pk_group_enum_to_text (group), description, url, (long int) size);
 
-	details = pk_details_new_from_data (package_id, license, group, description, url, size);
+	details = pk_details_obj_new_from_data (package_id, license, group, description, url, size);
 	g_signal_emit (client, signals [PK_CLIENT_DETAILS], 0, details);
-	pk_details_free (details);
+	pk_details_obj_free (details);
 }
 
 /**
diff --git a/libpackagekit/pk-client.h b/libpackagekit/pk-client.h
index 636ab8f..61c7b09 100644
--- a/libpackagekit/pk-client.h
+++ b/libpackagekit/pk-client.h
@@ -25,8 +25,8 @@
 #include <glib-object.h>
 #include "pk-enum.h"
 #include "pk-package-list.h"
-#include "pk-update-detail.h"
-#include "pk-details.h"
+#include "pk-update-detail-obj.h"
+#include "pk-details-obj.h"
 
 G_BEGIN_DECLS
 
@@ -99,9 +99,9 @@ struct _PkClientClass
 							 guint		 duration,
 							 const gchar	*data);
 	void		(* update_detail)		(PkClient	*client,
-							 PkUpdateDetail	*update_detail);
+							 PkUpdateDetailObj	*update_detail);
 	void		(* details)			(PkClient	*client,
-							 PkDetails	*package_detail);
+							 PkDetailsObj	*package_detail);
 	void		(* files)			(PkClient	*client,
 							 const gchar	*package_id,
 							 const gchar	*filelist);
diff --git a/libpackagekit/pk-details-obj.c b/libpackagekit/pk-details-obj.c
new file mode 100644
index 0000000..619c9c8
--- /dev/null
+++ b/libpackagekit/pk-details-obj.c
@@ -0,0 +1,146 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2007-2008 Richard Hughes <richard at hughsie.com>
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+/**
+ * SECTION:pk-details-obj
+ * @short_description: Functionality to create a details struct
+ */
+
+#include "config.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/types.h>
+#include <glib/gi18n.h>
+
+#include <pk-enum.h>
+#include "pk-debug.h"
+#include "pk-common.h"
+#include "pk-details-obj.h"
+
+/**
+ * pk_details_obj_new:
+ *
+ * Creates a new #PkDetailsObj object with default values
+ *
+ * Return value: a new #PkDetailsObj object
+ **/
+PkDetailsObj *
+pk_details_obj_new (void)
+{
+	PkDetailsObj *detail;
+	detail = g_new0 (PkDetailsObj, 1);
+	detail->package_id = NULL;
+	detail->license = NULL;
+	detail->group = 0;
+	detail->description = NULL;
+	detail->url = NULL;
+	detail->size = 0;
+
+	return detail;
+}
+
+/**
+ * pk_details_obj_new_from_data:
+ *
+ * Creates a new #PkDetailsObj object with values.
+ *
+ * Return value: a new #PkDetailsObj object
+ **/
+PkDetailsObj *
+pk_details_obj_new_from_data (const gchar *package_id, const gchar *license, PkGroupEnum group,
+			      const gchar *description, const gchar *url, guint64 size)
+{
+	PkDetailsObj *detail = NULL;
+
+	/* create new object */
+	detail = pk_details_obj_new ();
+	detail->package_id = g_strdup (package_id);
+	detail->license = g_strdup (license);
+	detail->group = group;
+	detail->description = g_strdup (description);
+	detail->url = g_strdup (url);
+	detail->size = size;
+
+	return detail;
+}
+
+/**
+ * pk_details_obj_free:
+ * @detail: the #PkDetailsObj object
+ *
+ * Return value: %TRUE if the #PkDetailsObj object was freed.
+ **/
+gboolean
+pk_details_obj_free (PkDetailsObj *detail)
+{
+	if (detail == NULL) {
+		return FALSE;
+	}
+	g_free (detail->package_id);
+	g_free (detail->license);
+	g_free (detail->description);
+	g_free (detail->url);
+	g_free (detail);
+	return TRUE;
+}
+
+/***************************************************************************
+ ***                          MAKE CHECK TESTS                           ***
+ ***************************************************************************/
+#ifdef PK_BUILD_TESTS
+#include <libselftest.h>
+
+void
+libst_details (LibSelfTest *test)
+{
+	gboolean ret;
+	PkDetailsObj *detail;
+
+	if (libst_start (test, "PkDetailsObj", CLASS_AUTO) == FALSE) {
+		return;
+	}
+
+	/************************************************************/
+	libst_title (test, "get an details object");
+	detail = pk_details_obj_new ();
+	if (detail != NULL) {
+		libst_success (test, NULL);
+	} else {
+		libst_failed (test, NULL);
+	}
+
+	/************************************************************/
+	libst_title (test, "test details");
+	ret = pk_details_obj_free (detail);
+	if (ret) {
+		libst_success (test, NULL);
+	} else {
+		libst_failed (test, NULL);
+	}
+
+	pk_details_obj_free (detail);
+
+	libst_end (test);
+}
+#endif
+
diff --git a/libpackagekit/pk-details-obj.h b/libpackagekit/pk-details-obj.h
new file mode 100644
index 0000000..854fddc
--- /dev/null
+++ b/libpackagekit/pk-details-obj.h
@@ -0,0 +1,56 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2007-2008 Richard Hughes <richard at hughsie.com>
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __PK_DETAILS_H
+#define __PK_DETAILS_H
+
+#include <glib-object.h>
+#include <pk-enum.h>
+
+G_BEGIN_DECLS
+
+/**
+ * PkDetailsObj:
+ *
+ * Cached object to represent details about the package.
+ **/
+typedef struct
+{
+	gchar				*package_id;
+	gchar				*license;
+	PkGroupEnum			 group;
+	gchar				*description;
+	gchar				*url;
+	guint64				 size;
+} PkDetailsObj;
+
+PkDetailsObj	*pk_details_obj_new			(void);
+PkDetailsObj	*pk_details_obj_new_from_data		(const gchar	*package_id,
+							 const gchar	*license,
+							 PkGroupEnum	 group,
+							 const gchar	*description,
+							 const gchar	*url,
+							 guint64	 size);
+gboolean	 pk_details_obj_free			(PkDetailsObj	*detail);
+
+G_END_DECLS
+
+#endif /* __PK_DETAILS_H */
diff --git a/libpackagekit/pk-details.c b/libpackagekit/pk-details.c
deleted file mode 100644
index 50cb742..0000000
--- a/libpackagekit/pk-details.c
+++ /dev/null
@@ -1,146 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
- *
- * Copyright (C) 2007-2008 Richard Hughes <richard at hughsie.com>
- *
- * Licensed under the GNU General Public License Version 2
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-/**
- * SECTION:pk-details
- * @short_description: Functionality to create a details struct
- */
-
-#include "config.h"
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <sys/types.h>
-#include <glib/gi18n.h>
-
-#include <pk-enum.h>
-#include "pk-debug.h"
-#include "pk-common.h"
-#include "pk-details.h"
-
-/**
- * pk_details_new:
- *
- * Creates a new #PkDetails object with default values
- *
- * Return value: a new #PkDetails object
- **/
-PkDetails *
-pk_details_new (void)
-{
-	PkDetails *detail;
-	detail = g_new0 (PkDetails, 1);
-	detail->package_id = NULL;
-	detail->license = NULL;
-	detail->group = 0;
-	detail->description = NULL;
-	detail->url = NULL;
-	detail->size = 0;
-
-	return detail;
-}
-
-/**
- * pk_details_new_from_data:
- *
- * Creates a new #PkDetails object with values.
- *
- * Return value: a new #PkDetails object
- **/
-PkDetails *
-pk_details_new_from_data (const gchar *package_id, const gchar *license, PkGroupEnum group,
-			  const gchar *description, const gchar *url, guint64 size)
-{
-	PkDetails *detail = NULL;
-
-	/* create new object */
-	detail = pk_details_new ();
-	detail->package_id = g_strdup (package_id);
-	detail->license = g_strdup (license);
-	detail->group = group;
-	detail->description = g_strdup (description);
-	detail->url = g_strdup (url);
-	detail->size = size;
-
-	return detail;
-}
-
-/**
- * pk_details_free:
- * @detail: the #PkDetails object
- *
- * Return value: %TRUE if the #PkDetails object was freed.
- **/
-gboolean
-pk_details_free (PkDetails *detail)
-{
-	if (detail == NULL) {
-		return FALSE;
-	}
-	g_free (detail->package_id);
-	g_free (detail->license);
-	g_free (detail->description);
-	g_free (detail->url);
-	g_free (detail);
-	return TRUE;
-}
-
-/***************************************************************************
- ***                          MAKE CHECK TESTS                           ***
- ***************************************************************************/
-#ifdef PK_BUILD_TESTS
-#include <libselftest.h>
-
-void
-libst_details (LibSelfTest *test)
-{
-	gboolean ret;
-	PkDetails *detail;
-
-	if (libst_start (test, "PkDetails", CLASS_AUTO) == FALSE) {
-		return;
-	}
-
-	/************************************************************/
-	libst_title (test, "get an details object");
-	detail = pk_details_new ();
-	if (detail != NULL) {
-		libst_success (test, NULL);
-	} else {
-		libst_failed (test, NULL);
-	}
-
-	/************************************************************/
-	libst_title (test, "test details");
-	ret = pk_details_free (detail);
-	if (ret) {
-		libst_success (test, NULL);
-	} else {
-		libst_failed (test, NULL);
-	}
-
-	pk_details_free (detail);
-
-	libst_end (test);
-}
-#endif
-
diff --git a/libpackagekit/pk-details.h b/libpackagekit/pk-details.h
deleted file mode 100644
index b485a37..0000000
--- a/libpackagekit/pk-details.h
+++ /dev/null
@@ -1,56 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
- *
- * Copyright (C) 2007-2008 Richard Hughes <richard at hughsie.com>
- *
- * Licensed under the GNU General Public License Version 2
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-#ifndef __PK_DETAILS_H
-#define __PK_DETAILS_H
-
-#include <glib-object.h>
-#include <pk-enum.h>
-
-G_BEGIN_DECLS
-
-/**
- * PkDetails:
- *
- * Cached object to represent details about the package.
- **/
-typedef struct
-{
-	gchar				*package_id;
-	gchar				*license;
-	PkGroupEnum			 group;
-	gchar				*description;
-	gchar				*url;
-	guint64				 size;
-} PkDetails;
-
-PkDetails	*pk_details_new				(void);
-PkDetails	*pk_details_new_from_data		(const gchar	*package_id,
-							 const gchar	*license,
-							 PkGroupEnum	 group,
-							 const gchar	*description,
-							 const gchar	*url,
-							 guint64	 size);
-gboolean	 pk_details_free			(PkDetails	*detail);
-
-G_END_DECLS
-
-#endif /* __PK_DETAILS_H */
diff --git a/libpackagekit/pk-package-item.c b/libpackagekit/pk-package-item.c
deleted file mode 100644
index ff4bd4e..0000000
--- a/libpackagekit/pk-package-item.c
+++ /dev/null
@@ -1,189 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
- *
- * Copyright (C) 2007-2008 Richard Hughes <richard at hughsie.com>
- *
- * Licensed under the GNU General Public License Version 2
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-/**
- * SECTION:pk-package-item
- * @short_description: A cached Package structure
- *
- * These provide a way to query and store a single package.
- */
-
-#include "config.h"
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <time.h>
-#include <errno.h>
-
-#include <string.h>
-#include <sys/time.h>
-#include <sys/types.h>
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif /* HAVE_UNISTD_H */
-
-#include <glib/gi18n.h>
-
-#include "pk-debug.h"
-#include "pk-common.h"
-#include "pk-package-item.h"
-
-/**
- * pk_package_item_new:
- **/
-PkPackageItem *
-pk_package_item_new (PkInfoEnum info, const gchar *package_id, const gchar *summary)
-{
-	PkPackageItem *item;
-
-	g_return_val_if_fail (package_id != NULL, FALSE);
-
-	item = g_new0 (PkPackageItem, 1);
-	item->info = info;
-	item->package_id = g_strdup (package_id);
-	item->summary = g_strdup (summary);
-	return item;
-}
-
-/**
- * pk_package_item_free:
- **/
-gboolean
-pk_package_item_free (PkPackageItem *item)
-{
-	if (item == NULL) {
-		return FALSE;
-	}
-	g_free (item->package_id);
-	g_free (item->summary);
-	g_free (item);
-	return TRUE;
-}
-
-/**
- * pk_package_item_equal:
- *
- * Only compares the package_id's and the info enum
- **/
-gboolean
-pk_package_item_equal (PkPackageItem *item1, PkPackageItem *item2)
-{
-	if (item1 == NULL || item2 == NULL) {
-		return FALSE;
-	}
-	return (item1->info == item2->info &&
-		pk_strequal (item1->package_id, item2->package_id));
-}
-
-/**
- * pk_package_item_copy:
- *
- * Copy a PkPackageItem
- **/
-PkPackageItem *
-pk_package_item_copy (PkPackageItem *item)
-{
-	g_return_val_if_fail (item != NULL, NULL);
-	return pk_package_item_new (item->info, item->package_id, item->summary);
-}
-
-/***************************************************************************
- ***                          MAKE CHECK TESTS                           ***
- ***************************************************************************/
-#ifdef PK_BUILD_TESTS
-#include <libselftest.h>
-
-void
-libst_package_item (LibSelfTest *test)
-{
-	PkPackageItem *item1;
-	PkPackageItem *item2;
-	PkPackageItem *item3;
-	gboolean ret;
-
-	if (libst_start (test, "PkPackageItem", CLASS_AUTO) == FALSE) {
-		return;
-	}
-
-	/************************************************************/
-	libst_title (test, "add entry");
-	item1 = pk_package_item_new (PK_INFO_ENUM_INSTALLED, "gnome;1.23;i386;data", "GNOME!");
-	if (item1 != NULL) {
-		libst_success (test, NULL);
-	} else {
-		libst_failed (test, NULL);
-	}
-
-	/************************************************************/
-	libst_title (test, "add entry");
-	item2 = pk_package_item_new (PK_INFO_ENUM_INSTALLED, "gnome;1.23;i386;data", "GNOME foo!");
-	if (item2 != NULL) {
-		libst_success (test, NULL);
-	} else {
-		libst_failed (test, NULL);
-	}
-
-	/************************************************************/
-	libst_title (test, "copy entry");
-	item3 = pk_package_item_copy (item2);
-	if (item3 != NULL) {
-		libst_success (test, NULL);
-	} else {
-		libst_failed (test, NULL);
-	}
-
-	/************************************************************/
-	libst_title (test, "check equal");
-	ret = pk_package_item_equal (item1, item3);
-	if (ret) {
-		libst_success (test, NULL);
-	} else {
-		libst_failed (test, NULL);
-	}
-
-	pk_package_item_free (item2);
-	pk_package_item_free (item3);
-
-	/************************************************************/
-	libst_title (test, "add entry");
-	item2 = pk_package_item_new (PK_INFO_ENUM_INSTALLED, "gnome-do;1.23;i386;data", "GNOME doo!");
-	if (item2 != NULL) {
-		libst_success (test, NULL);
-	} else {
-		libst_failed (test, NULL);
-	}
-
-	/************************************************************/
-	libst_title (test, "check !equal");
-	ret = pk_package_item_equal (item1, item2);
-	if (!ret) {
-		libst_success (test, NULL);
-	} else {
-		libst_failed (test, NULL);
-	}
-
-	pk_package_item_free (item1);
-	pk_package_item_free (item2);
-
-	libst_end (test);
-}
-#endif
-
diff --git a/libpackagekit/pk-package-item.h b/libpackagekit/pk-package-item.h
deleted file mode 100644
index c41a6ea..0000000
--- a/libpackagekit/pk-package-item.h
+++ /dev/null
@@ -1,48 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
- *
- * Copyright (C) 2008 Richard Hughes <richard at hughsie.com>
- *
- * Licensed under the GNU General Public License Version 2
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-#ifndef __PK_PACKAGE_ITEM_H
-#define __PK_PACKAGE_ITEM_H
-
-#include <glib-object.h>
-#include <pk-enum.h>
-
-/**
- * PkPackageItem:
- *
- * A cached store for the complete Package object
- */
-typedef struct {
-	PkInfoEnum		 info;
-	gchar			*package_id;
-	gchar			*summary;
-} PkPackageItem;
-
-PkPackageItem	*pk_package_item_new			(PkInfoEnum		 info,
-							 const gchar		*package_id,
-							 const gchar		*summary);
-gboolean	 pk_package_item_free			(PkPackageItem		*item);
-PkPackageItem	*pk_package_item_copy			(PkPackageItem		*item);
-gboolean	 pk_package_item_equal			(PkPackageItem		*item1,
-							 PkPackageItem		*item2);
-
-#endif /* __PK_PACKAGE_ITEM_H */
-
diff --git a/libpackagekit/pk-package-list.c b/libpackagekit/pk-package-list.c
index fee5ea8..34c7a72 100644
--- a/libpackagekit/pk-package-list.c
+++ b/libpackagekit/pk-package-list.c
@@ -45,7 +45,7 @@
 #include "pk-debug.h"
 #include "pk-common.h"
 #include "pk-package-id.h"
-#include "pk-package-item.h"
+#include "pk-package-obj.h"
 #include "pk-package-list.h"
 
 static void     pk_package_list_class_init	(PkPackageListClass *klass);
@@ -72,39 +72,39 @@ G_DEFINE_TYPE (PkPackageList, pk_package_list, G_TYPE_OBJECT)
 gboolean
 pk_package_list_add (PkPackageList *plist, PkInfoEnum info, const gchar *package_id, const gchar *summary)
 {
-	PkPackageItem *item;
+	PkPackageObj *obj;
 
 	g_return_val_if_fail (PK_IS_PACKAGE_LIST (plist), FALSE);
 	g_return_val_if_fail (package_id != NULL, FALSE);
 
-	item = pk_package_item_new (info, package_id, summary);
-	g_ptr_array_add (plist->priv->array, item);
+	obj = pk_package_obj_new (info, package_id, summary);
+	g_ptr_array_add (plist->priv->array, obj);
 
 	return TRUE;
 }
 
 /**
- * pk_package_list_add_item:
+ * pk_package_list_add_obj:
  *
  * Makes a deep copy, and adds to the array
  **/
 gboolean
-pk_package_list_add_item (PkPackageList *plist, PkPackageItem *item)
+pk_package_list_add_obj (PkPackageList *plist, const PkPackageObj *obj)
 {
 	gboolean ret;
-	PkPackageItem *item_new;
+	PkPackageObj *obj_new;
 
 	g_return_val_if_fail (PK_IS_PACKAGE_LIST (plist), FALSE);
-	g_return_val_if_fail (item != NULL, FALSE);
+	g_return_val_if_fail (obj != NULL, FALSE);
 
-	ret = pk_package_list_contains_item (plist, item);
+	ret = pk_package_list_contains_obj (plist, obj);
 	if (ret) {
-		pk_debug ("already added item");
+		pk_debug ("already added obj");
 		return FALSE;
 	}
 
-	item_new = pk_package_item_copy (item);
-	g_ptr_array_add (plist->priv->array, item_new);
+	obj_new = pk_package_obj_copy (obj);
+	g_ptr_array_add (plist->priv->array, obj_new);
 
 	return TRUE;
 }
@@ -119,7 +119,7 @@ pk_package_list_add_list (PkPackageList *plist, PkPackageList *list)
 {
 	guint i;
 	guint len;
-	PkPackageItem *item;
+	const PkPackageObj *obj;
 
 	g_return_val_if_fail (PK_IS_PACKAGE_LIST (plist), FALSE);
 	g_return_val_if_fail (PK_IS_PACKAGE_LIST (list), FALSE);
@@ -127,8 +127,8 @@ pk_package_list_add_list (PkPackageList *plist, PkPackageList *list)
 	/* add list to plist */
 	len = pk_package_list_get_size (list);
 	for (i=0; i<len; i++) {
-		item = pk_package_list_get_item (list, i);
-		pk_package_list_add_item (plist, item);
+		obj = pk_package_list_get_obj (list, i);
+		pk_package_list_add_obj (plist, obj);
 	}
 	return TRUE;
 }
@@ -139,7 +139,7 @@ pk_package_list_add_list (PkPackageList *plist, PkPackageList *list)
 gchar *
 pk_package_list_to_string (PkPackageList *plist)
 {
-	PkPackageItem *item;
+	PkPackageObj *obj;
 	guint i;
 	guint length;
 	const gchar *info_text;
@@ -150,9 +150,9 @@ pk_package_list_to_string (PkPackageList *plist)
 	package_cache = g_string_new ("");
 	length = plist->priv->array->len;
 	for (i=0; i<length; i++) {
-		item = g_ptr_array_index (plist->priv->array, i);
-		info_text = pk_info_enum_to_text (item->info);
-		g_string_append_printf (package_cache, "%s\t%s\t%s\n", info_text, item->package_id, item->summary);
+		obj = g_ptr_array_index (plist->priv->array, i);
+		info_text = pk_info_enum_to_text (obj->info);
+		g_string_append_printf (package_cache, "%s\t%s\t%s\n", info_text, obj->package_id, obj->summary);
 	}
 
 	/* remove trailing newline */
@@ -169,7 +169,7 @@ pk_package_list_to_string (PkPackageList *plist)
 gchar **
 pk_package_list_to_argv (PkPackageList *plist)
 {
-	PkPackageItem *item;
+	PkPackageObj *obj;
 	GPtrArray *array;
 	gchar **package_ids;
 	guint length;
@@ -178,8 +178,8 @@ pk_package_list_to_argv (PkPackageList *plist)
 	array = g_ptr_array_new ();
 	length = plist->priv->array->len;
 	for (i=0; i<length; i++) {
-		item = g_ptr_array_index (plist->priv->array, i);
-		g_ptr_array_add (array, item->package_id);
+		obj = g_ptr_array_index (plist->priv->array, i);
+		g_ptr_array_add (array, obj->package_id);
 	}
 
 	/* convert to argv */
@@ -203,7 +203,7 @@ pk_package_list_get_size (PkPackageList *plist)
  * pk_package_list_sort_compare_package_id_func:
  **/
 static gint
-pk_package_list_sort_compare_package_id_func (PkPackageItem **a, PkPackageItem **b)
+pk_package_list_sort_compare_package_id_func (PkPackageObj **a, PkPackageObj **b)
 {
 	return strcmp ((*a)->package_id, (*b)->package_id);
 }
@@ -212,7 +212,7 @@ pk_package_list_sort_compare_package_id_func (PkPackageItem **a, PkPackageItem *
  * pk_package_list_sort_compare_summary_func:
  **/
 static gint
-pk_package_list_sort_compare_summary_func (PkPackageItem **a, PkPackageItem **b)
+pk_package_list_sort_compare_summary_func (PkPackageObj **a, PkPackageObj **b)
 {
 	if ((*a)->summary == NULL && (*b)->summary == NULL) {
 		return 0;
@@ -228,7 +228,7 @@ pk_package_list_sort_compare_summary_func (PkPackageItem **a, PkPackageItem **b)
  * pk_package_list_sort_compare_info_func:
  **/
 static gint
-pk_package_list_sort_compare_info_func (PkPackageItem **a, PkPackageItem **b)
+pk_package_list_sort_compare_info_func (PkPackageObj **a, PkPackageObj **b)
 {
 	if ((*a)->info == (*b)->info) {
 		return 0;
@@ -278,10 +278,10 @@ pk_package_list_sort_info (PkPackageList *plist)
 }
 
 /**
- * pk_package_list_get_item:
+ * pk_package_list_get_obj:
  **/
-PkPackageItem *
-pk_package_list_get_item (PkPackageList *plist, guint item)
+const PkPackageObj *
+pk_package_list_get_obj (PkPackageList *plist, guint item)
 {
 	g_return_val_if_fail (PK_IS_PACKAGE_LIST (plist), NULL);
 	if (item >= plist->priv->array->len) {
@@ -297,13 +297,13 @@ pk_package_list_get_item (PkPackageList *plist, guint item)
 gboolean
 pk_package_list_clear (PkPackageList *plist)
 {
-	PkPackageItem *item;
+	PkPackageObj *obj;
 
 	g_return_val_if_fail (PK_IS_PACKAGE_LIST (plist), FALSE);
 
 	while (plist->priv->array->len > 0) {
-		item = g_ptr_array_index (plist->priv->array, 0);
-		pk_package_item_free (item);
+		obj = g_ptr_array_index (plist->priv->array, 0);
+		pk_package_obj_free (obj);
 		g_ptr_array_remove_index_fast (plist->priv->array, 0);
 	}
 	return TRUE;
@@ -315,7 +315,7 @@ pk_package_list_clear (PkPackageList *plist)
 gboolean
 pk_package_list_contains (PkPackageList *plist, const gchar *package_id)
 {
-	PkPackageItem *item;
+	PkPackageObj *obj;
 	guint i;
 	guint length;
 	gboolean ret = FALSE;
@@ -325,8 +325,8 @@ pk_package_list_contains (PkPackageList *plist, const gchar *package_id)
 
 	length = plist->priv->array->len;
 	for (i=0; i<length; i++) {
-		item = g_ptr_array_index (plist->priv->array, i);
-		ret = pk_package_id_equal (item->package_id, package_id);
+		obj = g_ptr_array_index (plist->priv->array, i);
+		ret = pk_package_id_equal (obj->package_id, package_id);
 		if (ret) {
 			break;
 		}
@@ -340,7 +340,7 @@ pk_package_list_contains (PkPackageList *plist, const gchar *package_id)
 gboolean
 pk_package_list_remove (PkPackageList *plist, const gchar *package_id)
 {
-	PkPackageItem *item;
+	PkPackageObj *obj;
 	guint i;
 	guint length;
 	gboolean ret = FALSE;
@@ -350,10 +350,10 @@ pk_package_list_remove (PkPackageList *plist, const gchar *package_id)
 
 	length = plist->priv->array->len;
 	for (i=0; i<length; i++) {
-		item = g_ptr_array_index (plist->priv->array, i);
-		ret = pk_package_id_equal (item->package_id, package_id);
+		obj = g_ptr_array_index (plist->priv->array, i);
+		ret = pk_package_id_equal (obj->package_id, package_id);
 		if (ret) {
-			pk_package_item_free (item);
+			pk_package_obj_free (obj);
 			g_ptr_array_remove_index (plist->priv->array, i);
 			break;
 		}
@@ -362,23 +362,23 @@ pk_package_list_remove (PkPackageList *plist, const gchar *package_id)
 }
 
 /**
- * pk_package_list_contains_item:
+ * pk_package_list_contains_obj:
  **/
 gboolean
-pk_package_list_contains_item (PkPackageList *plist, PkPackageItem *item)
+pk_package_list_contains_obj (PkPackageList *plist, const PkPackageObj *obj)
 {
-	PkPackageItem *item_temp;
+	PkPackageObj *obj_temp;
 	guint i;
 	guint length;
 	gboolean ret = FALSE;
 
 	g_return_val_if_fail (PK_IS_PACKAGE_LIST (plist), FALSE);
-	g_return_val_if_fail (item != NULL, FALSE);
+	g_return_val_if_fail (obj != NULL, FALSE);
 
 	length = plist->priv->array->len;
 	for (i=0; i<length; i++) {
-		item_temp = g_ptr_array_index (plist->priv->array, i);
-		ret = pk_package_item_equal (item_temp, item);
+		obj_temp = g_ptr_array_index (plist->priv->array, i);
+		ret = pk_package_obj_equal (obj_temp, obj);
 		if (ret) {
 			break;
 		}
@@ -456,9 +456,9 @@ libst_package_list (LibSelfTest *test)
 	PkPackageList *plist;
 	gchar *text;
 	gboolean ret;
-	PkPackageItem *r0;
-	PkPackageItem *r1;
-	PkPackageItem *r2;
+	const PkPackageObj *r0;
+	const PkPackageObj *r1;
+	const PkPackageObj *r2;
 
 	if (libst_start (test, "PkPackageList", CLASS_AUTO) == FALSE) {
 		return;
@@ -550,9 +550,9 @@ libst_package_list (LibSelfTest *test)
 	/************************************************************/
 	libst_title (test, "sort by package_id");
 	ret = pk_package_list_sort (plist);
-	r0 = pk_package_list_get_item (plist, 0);
-	r1 = pk_package_list_get_item (plist, 1);
-	r2 = pk_package_list_get_item (plist, 2);
+	r0 = pk_package_list_get_obj (plist, 0);
+	r1 = pk_package_list_get_obj (plist, 1);
+	r2 = pk_package_list_get_obj (plist, 2);
 	if (pk_strequal (r0->package_id, "abc;1.23;i386;data") &&
 	    pk_strequal (r1->package_id, "def;1.23;i386;data") &&
 	    pk_strequal (r2->package_id, "ghi;1.23;i386;data")) {
@@ -564,9 +564,9 @@ libst_package_list (LibSelfTest *test)
 	/************************************************************/
 	libst_title (test, "sort by summary");
 	ret = pk_package_list_sort_summary (plist);
-	r0 = pk_package_list_get_item (plist, 0);
-	r1 = pk_package_list_get_item (plist, 1);
-	r2 = pk_package_list_get_item (plist, 2);
+	r0 = pk_package_list_get_obj (plist, 0);
+	r1 = pk_package_list_get_obj (plist, 1);
+	r2 = pk_package_list_get_obj (plist, 2);
 	if (pk_strequal (r0->summary, "aed") &&
 	    pk_strequal (r1->summary, "fed") &&
 	    pk_strequal (r2->summary, "zed")) {
@@ -578,9 +578,9 @@ libst_package_list (LibSelfTest *test)
 	/************************************************************/
 	libst_title (test, "sort by severity");
 	ret = pk_package_list_sort_info (plist);
-	r0 = pk_package_list_get_item (plist, 0);
-	r1 = pk_package_list_get_item (plist, 1);
-	r2 = pk_package_list_get_item (plist, 2);
+	r0 = pk_package_list_get_obj (plist, 0);
+	r1 = pk_package_list_get_obj (plist, 1);
+	r2 = pk_package_list_get_obj (plist, 2);
 	if (r0->info == PK_INFO_ENUM_SECURITY &&
 	    r1->info == PK_INFO_ENUM_BUGFIX &&
 	    r2->info == PK_INFO_ENUM_ENHANCEMENT) {
@@ -601,9 +601,9 @@ libst_package_list (LibSelfTest *test)
 	libst_title (test, "sort by package_id then priority (should not mess up previous sort)");
 	pk_package_list_sort (plist);
 	pk_package_list_sort_info (plist);
-	r0 = pk_package_list_get_item (plist, 0);
-	r1 = pk_package_list_get_item (plist, 1);
-	r2 = pk_package_list_get_item (plist, 2);
+	r0 = pk_package_list_get_obj (plist, 0);
+	r1 = pk_package_list_get_obj (plist, 1);
+	r2 = pk_package_list_get_obj (plist, 2);
 	if (pk_strequal (r0->package_id, "abc;1.23;i386;data") &&
 	    pk_strequal (r1->package_id, "def;1.23;i386;data") &&
 	    pk_strequal (r2->package_id, "ghi;1.23;i386;data")) {
diff --git a/libpackagekit/pk-package-list.h b/libpackagekit/pk-package-list.h
index 38251b5..314a5db 100644
--- a/libpackagekit/pk-package-list.h
+++ b/libpackagekit/pk-package-list.h
@@ -25,7 +25,7 @@
 #include <glib-object.h>
 #include <pk-enum.h>
 
-#include "pk-package-item.h"
+#include "pk-package-obj.h"
 
 G_BEGIN_DECLS
 
@@ -51,33 +51,33 @@ struct _PkPackageListClass
 	GObjectClass	parent_class;
 };
 
-GType		 pk_package_list_get_type		(void) G_GNUC_CONST;
-PkPackageList	*pk_package_list_new			(void);
-gboolean	 pk_package_list_add			(PkPackageList		*plist,
+GType			 pk_package_list_get_type	(void) G_GNUC_CONST;
+PkPackageList		*pk_package_list_new		(void);
+gboolean		 pk_package_list_add		(PkPackageList		*plist,
 							 PkInfoEnum		 info,
 							 const gchar		*package_id,
 							 const gchar		*summary);
-gboolean	 pk_package_list_add_item		(PkPackageList		*plist,
-							 PkPackageItem		*item);
-gboolean	 pk_package_list_add_list		(PkPackageList		*plist,
+gboolean		 pk_package_list_add_obj	(PkPackageList		*plist,
+							 const PkPackageObj	*obj);
+gboolean		 pk_package_list_add_list	(PkPackageList		*plist,
 							 PkPackageList		*list);
-gboolean	 pk_package_list_contains		(PkPackageList		*plist,
+gboolean		 pk_package_list_contains	(PkPackageList		*plist,
 							 const gchar		*package_id);
-gboolean	 pk_package_list_remove			(PkPackageList		*plist,
+gboolean		 pk_package_list_remove		(PkPackageList		*plist,
 							 const gchar		*package_id);
-gboolean	 pk_package_list_contains_item		(PkPackageList		*plist,
-							 PkPackageItem		*item);
-gchar		*pk_package_list_to_string		(PkPackageList		*plist)
+gboolean		 pk_package_list_contains_obj	(PkPackageList		*plist,
+							 const PkPackageObj	*obj);
+gchar			*pk_package_list_to_string	(PkPackageList		*plist)
 							 G_GNUC_WARN_UNUSED_RESULT;
-gchar		**pk_package_list_to_argv		(PkPackageList		*plist)
+gchar			**pk_package_list_to_argv	(PkPackageList		*plist)
 							 G_GNUC_WARN_UNUSED_RESULT;
-guint		 pk_package_list_get_size		(PkPackageList		*plist);
-gboolean	 pk_package_list_sort			(PkPackageList		*plist);
-gboolean	 pk_package_list_sort_info		(PkPackageList		*plist);
-gboolean	 pk_package_list_sort_summary		(PkPackageList		*plist);
-PkPackageItem	*pk_package_list_get_item		(PkPackageList		*plist,
+guint			 pk_package_list_get_size	(PkPackageList		*plist);
+gboolean		 pk_package_list_sort		(PkPackageList		*plist);
+gboolean		 pk_package_list_sort_info	(PkPackageList		*plist);
+gboolean		 pk_package_list_sort_summary	(PkPackageList		*plist);
+const PkPackageObj	*pk_package_list_get_obj	(PkPackageList		*plist,
 							 guint			 item);
-gboolean	 pk_package_list_clear			(PkPackageList		*plist);
+gboolean		 pk_package_list_clear		(PkPackageList		*plist);
 
 G_END_DECLS
 
diff --git a/libpackagekit/pk-package-obj.c b/libpackagekit/pk-package-obj.c
new file mode 100644
index 0000000..519e93d
--- /dev/null
+++ b/libpackagekit/pk-package-obj.c
@@ -0,0 +1,189 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2007-2008 Richard Hughes <richard at hughsie.com>
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+/**
+ * SECTION:pk-package-obj
+ * @short_description: A cached Package structure
+ *
+ * These provide a way to query and store a single package.
+ */
+
+#include "config.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <time.h>
+#include <errno.h>
+
+#include <string.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif /* HAVE_UNISTD_H */
+
+#include <glib/gi18n.h>
+
+#include "pk-debug.h"
+#include "pk-common.h"
+#include "pk-package-obj.h"
+
+/**
+ * pk_package_obj_new:
+ **/
+PkPackageObj *
+pk_package_obj_new (PkInfoEnum info, const gchar *package_id, const gchar *summary)
+{
+	PkPackageObj *obj;
+
+	g_return_val_if_fail (package_id != NULL, FALSE);
+
+	obj = g_new0 (PkPackageObj, 1);
+	obj->info = info;
+	obj->package_id = g_strdup (package_id);
+	obj->summary = g_strdup (summary);
+	return obj;
+}
+
+/**
+ * pk_package_obj_free:
+ **/
+gboolean
+pk_package_obj_free (PkPackageObj *obj)
+{
+	if (obj == NULL) {
+		return FALSE;
+	}
+	g_free (obj->package_id);
+	g_free (obj->summary);
+	g_free (obj);
+	return TRUE;
+}
+
+/**
+ * pk_package_obj_equal:
+ *
+ * Only compares the package_id's and the info enum
+ **/
+gboolean
+pk_package_obj_equal (const PkPackageObj *obj1, const PkPackageObj *obj2)
+{
+	if (obj1 == NULL || obj2 == NULL) {
+		return FALSE;
+	}
+	return (obj1->info == obj2->info &&
+		pk_strequal (obj1->package_id, obj2->package_id));
+}
+
+/**
+ * pk_package_obj_copy:
+ *
+ * Copy a PkPackageObj
+ **/
+PkPackageObj *
+pk_package_obj_copy (const PkPackageObj *obj)
+{
+	g_return_val_if_fail (obj != NULL, NULL);
+	return pk_package_obj_new (obj->info, obj->package_id, obj->summary);
+}
+
+/***************************************************************************
+ ***                          MAKE CHECK TESTS                           ***
+ ***************************************************************************/
+#ifdef PK_BUILD_TESTS
+#include <libselftest.h>
+
+void
+libst_package_obj (LibSelfTest *test)
+{
+	PkPackageObj *obj1;
+	PkPackageObj *obj2;
+	PkPackageObj *obj3;
+	gboolean ret;
+
+	if (libst_start (test, "PkPackageObj", CLASS_AUTO) == FALSE) {
+		return;
+	}
+
+	/************************************************************/
+	libst_title (test, "add entry");
+	obj1 = pk_package_obj_new (PK_INFO_ENUM_INSTALLED, "gnome;1.23;i386;data", "GNOME!");
+	if (obj1 != NULL) {
+		libst_success (test, NULL);
+	} else {
+		libst_failed (test, NULL);
+	}
+
+	/************************************************************/
+	libst_title (test, "add entry");
+	obj2 = pk_package_obj_new (PK_INFO_ENUM_INSTALLED, "gnome;1.23;i386;data", "GNOME foo!");
+	if (obj2 != NULL) {
+		libst_success (test, NULL);
+	} else {
+		libst_failed (test, NULL);
+	}
+
+	/************************************************************/
+	libst_title (test, "copy entry");
+	obj3 = pk_package_obj_copy (obj2);
+	if (obj3 != NULL) {
+		libst_success (test, NULL);
+	} else {
+		libst_failed (test, NULL);
+	}
+
+	/************************************************************/
+	libst_title (test, "check equal");
+	ret = pk_package_obj_equal (obj1, obj3);
+	if (ret) {
+		libst_success (test, NULL);
+	} else {
+		libst_failed (test, NULL);
+	}
+
+	pk_package_obj_free (obj2);
+	pk_package_obj_free (obj3);
+
+	/************************************************************/
+	libst_title (test, "add entry");
+	obj2 = pk_package_obj_new (PK_INFO_ENUM_INSTALLED, "gnome-do;1.23;i386;data", "GNOME doo!");
+	if (obj2 != NULL) {
+		libst_success (test, NULL);
+	} else {
+		libst_failed (test, NULL);
+	}
+
+	/************************************************************/
+	libst_title (test, "check !equal");
+	ret = pk_package_obj_equal (obj1, obj2);
+	if (!ret) {
+		libst_success (test, NULL);
+	} else {
+		libst_failed (test, NULL);
+	}
+
+	pk_package_obj_free (obj1);
+	pk_package_obj_free (obj2);
+
+	libst_end (test);
+}
+#endif
+
diff --git a/libpackagekit/pk-package-obj.h b/libpackagekit/pk-package-obj.h
new file mode 100644
index 0000000..5b4d097
--- /dev/null
+++ b/libpackagekit/pk-package-obj.h
@@ -0,0 +1,48 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2008 Richard Hughes <richard at hughsie.com>
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __PK_PACKAGE_OBJ_H
+#define __PK_PACKAGE_OBJ_H
+
+#include <glib-object.h>
+#include <pk-enum.h>
+
+/**
+ * PkPackageObj:
+ *
+ * A cached store for the complete Package object
+ */
+typedef struct {
+	PkInfoEnum		 info;
+	gchar			*package_id;
+	gchar			*summary;
+} PkPackageObj;
+
+PkPackageObj	*pk_package_obj_new			(PkInfoEnum		 info,
+							 const gchar		*package_id,
+							 const gchar		*summary);
+gboolean	 pk_package_obj_free			(PkPackageObj		*obj);
+PkPackageObj	*pk_package_obj_copy			(const PkPackageObj	*obj);
+gboolean	 pk_package_obj_equal			(const PkPackageObj	*obj1,
+							 const PkPackageObj	*obj2);
+
+#endif /* __PK_PACKAGE_OBJ_H */
+
diff --git a/libpackagekit/pk-self-test.c b/libpackagekit/pk-self-test.c
index caa5284..70fc642 100644
--- a/libpackagekit/pk-self-test.c
+++ b/libpackagekit/pk-self-test.c
@@ -29,7 +29,7 @@
 /* prototypes */
 void libst_package_id (LibSelfTest *test);
 void libst_package_ids (LibSelfTest *test);
-void libst_package_item (LibSelfTest *test);
+void libst_package_obj (LibSelfTest *test);
 void libst_package_list (LibSelfTest *test);
 void libst_enum (LibSelfTest *test);
 void libst_common (LibSelfTest *test);
@@ -55,7 +55,7 @@ main (int argc, char **argv)
 	libst_common (&test);
 	libst_package_id (&test);
 	libst_package_ids (&test);
-	libst_package_item (&test);
+	libst_package_obj (&test);
 	libst_package_list (&test);
 	libst_enum (&test);
 	libst_extra (&test);
diff --git a/libpackagekit/pk-update-detail-list.c b/libpackagekit/pk-update-detail-list.c
new file mode 100644
index 0000000..0b0562f
--- /dev/null
+++ b/libpackagekit/pk-update-detail-list.c
@@ -0,0 +1,213 @@
+/* -*- 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.
+ */
+
+#ifdef CONFIG_H
+#  include <config.h>
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/time.h>
+#include <sys/types.h>
+
+#include <glib/gi18n.h>
+#include <glib.h>
+
+#include "pk-debug.h"
+#include "pk-common.h"
+#include "pk-update-detail-obj.h"
+#include "pk-update-detail-list.h"
+
+#define PK_UPDATE_DETAIL_LIST_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), PK_TYPE_UPDATE_DETAIL_LIST, PkUpdateDetailListPrivate))
+
+struct PkUpdateDetailListPrivate
+{
+	GPtrArray		*array;
+};
+
+G_DEFINE_TYPE (PkUpdateDetailList, pk_update_detail_list, G_TYPE_OBJECT)
+static gpointer pk_update_detail_list_object = NULL;
+
+/**
+ * pk_update_detail_list_clear:
+ **/
+gboolean
+pk_update_detail_list_clear (PkUpdateDetailList *list)
+{
+	g_return_val_if_fail (PK_IS_UPDATE_DETAIL_LIST (list), FALSE);
+	return TRUE;
+}
+
+/**
+ * pk_update_detail_list_add_obj:
+ **/
+gboolean
+pk_update_detail_list_add_obj (PkUpdateDetailList *list, const PkUpdateDetailObj *obj)
+{
+	PkUpdateDetailObj *obj_new;
+	const PkUpdateDetailObj *obj_found;
+	g_return_val_if_fail (PK_IS_UPDATE_DETAIL_LIST (list), FALSE);
+	g_return_val_if_fail (obj != NULL, FALSE);
+
+	/* are we already in the cache? */
+	obj_found = pk_update_detail_list_get_obj (list, obj->package_id);
+	if (obj_found != NULL) {
+		pk_debug ("already in list: %s", obj->package_id);
+		return FALSE;
+	}
+
+	obj_new = pk_update_detail_obj_copy (obj);
+	g_ptr_array_add (list->priv->array, obj_new);
+	return TRUE;
+}
+
+/**
+ * pk_update_detail_list_get_obj:
+ **/
+const PkUpdateDetailObj *
+pk_update_detail_list_get_obj (PkUpdateDetailList *list, const gchar *package_id)
+{
+	guint i;
+	guint len;
+	PkUpdateDetailObj *obj;
+
+	g_return_val_if_fail (PK_IS_UPDATE_DETAIL_LIST (list), NULL);
+	g_return_val_if_fail (package_id != NULL, NULL);
+
+	len = list->priv->array->len;
+	for (i=0; i<len; i++) {
+		obj = (PkUpdateDetailObj *) g_ptr_array_index (list->priv->array, i);
+		if (pk_strequal (package_id, obj->package_id)) {
+			return obj;
+		}
+	}
+	/* bahh, found nothing */
+	return NULL;
+}
+
+/**
+ * pk_update_detail_list_finalize:
+ **/
+static void
+pk_update_detail_list_finalize (GObject *object)
+{
+	guint i;
+	guint len;
+	PkUpdateDetailObj *obj;
+	PkUpdateDetailList *list;
+	g_return_if_fail (PK_IS_UPDATE_DETAIL_LIST (object));
+	list = PK_UPDATE_DETAIL_LIST (object);
+
+	//TODO: FREE!
+	len = list->priv->array->len;
+	for (i=0; i<len; i++) {
+		obj = (PkUpdateDetailObj *) g_ptr_array_index (list->priv->array, i);
+		pk_update_detail_obj_free (obj);
+	}
+	g_ptr_array_free (list->priv->array, FALSE);
+
+	G_OBJECT_CLASS (pk_update_detail_list_parent_class)->finalize (object);
+}
+
+/**
+ * pk_update_detail_list_class_init:
+ **/
+static void
+pk_update_detail_list_class_init (PkUpdateDetailListClass *klass)
+{
+	GObjectClass *object_class = G_OBJECT_CLASS (klass);
+	object_class->finalize = pk_update_detail_list_finalize;
+	g_type_class_add_private (klass, sizeof (PkUpdateDetailListPrivate));
+}
+
+/**
+ * pk_update_detail_list_init:
+ *
+ * initializes the update_detail_list class. NOTE: We expect list objects
+ * to *NOT* be removed or added during the session.
+ * We only control the first list object if there are more than one.
+ **/
+static void
+pk_update_detail_list_init (PkUpdateDetailList *list)
+{
+	list->priv = PK_UPDATE_DETAIL_LIST_GET_PRIVATE (list);
+	list->priv->array = g_ptr_array_new ();
+}
+
+/**
+ * pk_update_detail_list_new:
+ * Return value: A new list class instance.
+ **/
+PkUpdateDetailList *
+pk_update_detail_list_new (void)
+{
+	if (pk_update_detail_list_object != NULL) {
+		g_object_ref (pk_update_detail_list_object);
+	} else {
+		pk_update_detail_list_object = g_object_new (PK_TYPE_UPDATE_DETAIL_LIST, NULL);
+		g_object_add_weak_pointer (pk_update_detail_list_object, &pk_update_detail_list_object);
+	}
+	return PK_UPDATE_DETAIL_LIST (pk_update_detail_list_object);
+}
+
+/***************************************************************************
+ ***                          MAKE CHECK TESTS                           ***
+ ***************************************************************************/
+#ifdef PK_BUILD_TESTS
+#include <libselftest.h>
+
+void
+libst_update_detail_list (LibSelfTest *test)
+{
+	PkUpdateDetailList *list;
+	gchar *text;
+	gint value;
+
+	if (libst_start (test, "PkUpdateDetailList", CLASS_AUTO) == FALSE) {
+		return;
+	}
+
+	/************************************************************/
+	libst_title (test, "get an instance");
+	list = pk_update_detail_list_new ();
+	if (list != NULL) {
+		libst_success (test, NULL);
+	} else {
+		libst_failed (test, NULL);
+	}
+
+	/************************************************************/
+	libst_title (test, "get the default backend");
+	text = pk_update_detail_list_get_string (list, "DefaultBackend");
+	if (text != PK_UPDATE_DETAIL_LIST_VALUE_STRING_MISSING) {
+		libst_success (test, "got default backend '%s'", text);
+	} else {
+		libst_failed (test, "got NULL!");
+	}
+	g_free (text);
+
+	g_object_unref (list);
+
+	libst_end (test);
+}
+#endif
+
diff --git a/libpackagekit/pk-update-detail-list.h b/libpackagekit/pk-update-detail-list.h
new file mode 100644
index 0000000..41ac877
--- /dev/null
+++ b/libpackagekit/pk-update-detail-list.h
@@ -0,0 +1,62 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2008 Richard Hughes <richard at hughsie.com>
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __PK_UPDATE_DETAIL_LIST_H
+#define __PK_UPDATE_DETAIL_LIST_H
+
+#include <glib-object.h>
+#include <pk-update-detail-obj.h>
+
+G_BEGIN_DECLS
+
+#define PK_TYPE_UPDATE_DETAIL_LIST		(pk_update_detail_list_get_type ())
+#define PK_UPDATE_DETAIL_LIST(o)		(G_TYPE_CHECK_INSTANCE_CAST ((o), PK_TYPE_UPDATE_DETAIL_LIST, PkUpdateDetailList))
+#define PK_UPDATE_DETAIL_LIST_CLASS(k)		(G_TYPE_CHECK_CLASS_CAST((k), PK_TYPE_UPDATE_DETAIL_LIST, PkUpdateDetailListClass))
+#define PK_IS_UPDATE_DETAIL_LIST(o)		(G_TYPE_CHECK_INSTANCE_TYPE ((o), PK_TYPE_UPDATE_DETAIL_LIST))
+#define PK_IS_UPDATE_DETAIL_LIST_CLASS(k)	(G_TYPE_CHECK_CLASS_TYPE ((k), PK_TYPE_UPDATE_DETAIL_LIST))
+#define PK_UPDATE_DETAIL_LIST_GET_CLASS(o)	(G_TYPE_INSTANCE_GET_CLASS ((o), PK_TYPE_UPDATE_DETAIL_LIST, PkUpdateDetailListClass))
+
+typedef struct PkUpdateDetailListPrivate PkUpdateDetailListPrivate;
+
+typedef struct
+{
+	GObject		     		 parent;
+	PkUpdateDetailListPrivate	*priv;
+} PkUpdateDetailList;
+
+typedef struct
+{
+	GObjectClass			 parent_class;
+} PkUpdateDetailListClass;
+
+GType			 pk_update_detail_list_get_type		(void) G_GNUC_CONST;
+PkUpdateDetailList	 *pk_update_detail_list_new		(void);
+
+gboolean		 pk_update_detail_list_clear		(PkUpdateDetailList	*list);
+gboolean		 pk_update_detail_list_add_obj 		(PkUpdateDetailList	*list,
+								 const PkUpdateDetailObj *obj);
+const PkUpdateDetailObj	*pk_update_detail_list_get_obj 		(PkUpdateDetailList	*list,
+								 const gchar		*package_id);
+
+
+G_END_DECLS
+
+#endif /* __PK_UPDATE_DETAIL_LIST_H */
diff --git a/libpackagekit/pk-update-detail-obj.c b/libpackagekit/pk-update-detail-obj.c
new file mode 100644
index 0000000..1723add
--- /dev/null
+++ b/libpackagekit/pk-update-detail-obj.c
@@ -0,0 +1,170 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2007-2008 Richard Hughes <richard at hughsie.com>
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+/**
+ * SECTION:pk-update-detail-obj
+ * @short_description: Functionality to create an update detail struct
+ */
+
+#include "config.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/types.h>
+#include <glib/gi18n.h>
+
+#include <pk-enum.h>
+#include "pk-debug.h"
+#include "pk-common.h"
+#include "pk-update-detail-obj.h"
+
+/**
+ * pk_update_detail_obj_new:
+ *
+ * Creates a new #PkUpdateDetailObj object with default values
+ *
+ * Return value: a new #PkUpdateDetailObj object
+ **/
+PkUpdateDetailObj *
+pk_update_detail_obj_new (void)
+{
+	PkUpdateDetailObj *detail;
+	detail = g_new0 (PkUpdateDetailObj, 1);
+	detail->updates = NULL;
+	detail->obsoletes = NULL;
+	detail->vendor_url = NULL;
+	detail->bugzilla_url = NULL;
+	detail->cve_url = NULL;
+	detail->restart = 0;
+	detail->update_text = NULL;
+
+	return detail;
+}
+
+/**
+ * pk_update_detail_obj_new_from_data:
+ *
+ * Creates a new #PkUpdateDetailObj object with values.
+ *
+ * Return value: a new #PkUpdateDetailObj object
+ **/
+PkUpdateDetailObj *
+pk_update_detail_obj_new_from_data (const gchar *package_id, const gchar *updates, const gchar *obsoletes,
+				    const gchar *vendor_url, const gchar *bugzilla_url, const gchar *cve_url,
+				    PkRestartEnum restart, const gchar *update_text)
+{
+	PkUpdateDetailObj *detail = NULL;
+
+	/* create new object */
+	detail = pk_update_detail_obj_new ();
+	detail->package_id = g_strdup (package_id);
+	detail->updates = g_strdup (updates);
+	detail->obsoletes = g_strdup (obsoletes);
+	detail->vendor_url = g_strdup (vendor_url);
+	detail->bugzilla_url = g_strdup (bugzilla_url);
+	detail->cve_url = g_strdup (cve_url);
+	detail->restart = restart;
+	detail->update_text = g_strdup (update_text);
+
+	return detail;
+}
+
+/**
+ * pk_update_detail_obj_copy:
+ *
+ * Return value: a new #PkUpdateDetailObj object
+ **/
+PkUpdateDetailObj *
+pk_update_detail_obj_copy (const PkUpdateDetailObj *detail)
+{
+	g_return_val_if_fail (detail != NULL, NULL);
+	return pk_update_detail_obj_new_from_data (detail->package_id, detail->updates, detail->obsoletes,
+						   detail->vendor_url, detail->bugzilla_url, detail->cve_url,
+						   detail->restart, detail->update_text);
+}
+
+/**
+ * pk_update_detail_obj_free:
+ * @detail: the #PkUpdateDetailObj object
+ *
+ * Return value: %TRUE if the #PkUpdateDetailObj object was freed.
+ **/
+gboolean
+pk_update_detail_obj_free (PkUpdateDetailObj *detail)
+{
+	if (detail == NULL) {
+		return FALSE;
+	}
+	g_free (detail->updates);
+	g_free (detail->obsoletes);
+	g_free (detail->vendor_url);
+	g_free (detail->bugzilla_url);
+	g_free (detail->cve_url);
+	g_free (detail->update_text);
+	g_free (detail);
+	return TRUE;
+}
+
+/***************************************************************************
+ ***                          MAKE CHECK TESTS                           ***
+ ***************************************************************************/
+#ifdef PK_BUILD_TESTS
+#include <libselftest.h>
+
+void
+libst_update_detail (LibSelfTest *test)
+{
+	gboolean ret;
+	PkUpdateDetailObj *detail;
+
+	if (libst_start (test, "PkUpdateDetailObj", CLASS_AUTO) == FALSE) {
+		return;
+	}
+
+	/************************************************************
+	 ****************          IDENT           ******************
+	 ************************************************************/
+
+	/************************************************************/
+	libst_title (test, "get an detail object");
+	detail = pk_update_detail_obj_new ();
+	if (detail != NULL) {
+		libst_success (test, NULL);
+	} else {
+		libst_failed (test, NULL);
+	}
+
+	/************************************************************/
+	libst_title (test, "test detail");
+	ret = pk_update_detail_obj_free (detail);
+	if (ret) {
+		libst_success (test, NULL);
+	} else {
+		libst_failed (test, NULL);
+	}
+
+	pk_update_detail_obj_free (detail);
+
+	libst_end (test);
+}
+#endif
+
diff --git a/libpackagekit/pk-update-detail-obj.h b/libpackagekit/pk-update-detail-obj.h
new file mode 100644
index 0000000..caa0569
--- /dev/null
+++ b/libpackagekit/pk-update-detail-obj.h
@@ -0,0 +1,61 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2007-2008 Richard Hughes <richard at hughsie.com>
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __PK_UPDATE_DETAIL_H
+#define __PK_UPDATE_DETAIL_H
+
+#include <glib-object.h>
+#include <pk-enum.h>
+
+G_BEGIN_DECLS
+
+/**
+ * PkUpdateDetailObj:
+ *
+ * Cached object to represent details about the update.
+ **/
+typedef struct
+{
+	gchar				*package_id;
+	gchar				*updates;
+	gchar				*obsoletes;
+	gchar				*vendor_url;
+	gchar				*bugzilla_url;
+	gchar				*cve_url;
+	PkRestartEnum			 restart;
+	gchar				*update_text;
+} PkUpdateDetailObj;
+
+PkUpdateDetailObj	*pk_update_detail_obj_new		(void);
+PkUpdateDetailObj	*pk_update_detail_obj_copy		(const PkUpdateDetailObj *detail);
+PkUpdateDetailObj	*pk_update_detail_obj_new_from_data	(const gchar		*package_id,
+								 const gchar		*updates,
+								 const gchar		*obsoletes,
+								 const gchar		*vendor_url,
+								 const gchar		*bugzilla_url,
+								 const gchar		*cve_url,
+								 PkRestartEnum		 restart,
+								 const gchar		*update_text);
+gboolean		 pk_update_detail_obj_free		(PkUpdateDetailObj	*detail);
+
+G_END_DECLS
+
+#endif /* __PK_UPDATE_DETAIL_H */
diff --git a/libpackagekit/pk-update-detail.c b/libpackagekit/pk-update-detail.c
deleted file mode 100644
index bfe754d..0000000
--- a/libpackagekit/pk-update-detail.c
+++ /dev/null
@@ -1,170 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
- *
- * Copyright (C) 2007-2008 Richard Hughes <richard at hughsie.com>
- *
- * Licensed under the GNU General Public License Version 2
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-/**
- * SECTION:pk-update-detail
- * @short_description: Functionality to create an update detail struct
- */
-
-#include "config.h"
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <sys/types.h>
-#include <glib/gi18n.h>
-
-#include <pk-enum.h>
-#include "pk-debug.h"
-#include "pk-common.h"
-#include "pk-update-detail.h"
-
-/**
- * pk_update_detail_new:
- *
- * Creates a new #PkUpdateDetail object with default values
- *
- * Return value: a new #PkUpdateDetail object
- **/
-PkUpdateDetail *
-pk_update_detail_new (void)
-{
-	PkUpdateDetail *detail;
-	detail = g_new0 (PkUpdateDetail, 1);
-	detail->updates = NULL;
-	detail->obsoletes = NULL;
-	detail->vendor_url = NULL;
-	detail->bugzilla_url = NULL;
-	detail->cve_url = NULL;
-	detail->restart = 0;
-	detail->update_text = NULL;
-
-	return detail;
-}
-
-/**
- * pk_update_detail_new_from_data:
- *
- * Creates a new #PkUpdateDetail object with values.
- *
- * Return value: a new #PkUpdateDetail object
- **/
-PkUpdateDetail *
-pk_update_detail_new_from_data (const gchar *package_id, const gchar *updates, const gchar *obsoletes,
-				const gchar *vendor_url, const gchar *bugzilla_url, const gchar *cve_url,
-				PkRestartEnum restart, const gchar *update_text)
-{
-	PkUpdateDetail *detail = NULL;
-
-	/* create new object */
-	detail = pk_update_detail_new ();
-	detail->package_id = g_strdup (package_id);
-	detail->updates = g_strdup (updates);
-	detail->obsoletes = g_strdup (obsoletes);
-	detail->vendor_url = g_strdup (vendor_url);
-	detail->bugzilla_url = g_strdup (bugzilla_url);
-	detail->cve_url = g_strdup (cve_url);
-	detail->restart = restart;
-	detail->update_text = g_strdup (update_text);
-
-	return detail;
-}
-
-/**
- * pk_update_detail_copy:
- *
- * Return value: a new #PkUpdateDetail object
- **/
-PkUpdateDetail *
-pk_update_detail_copy (const PkUpdateDetail *detail)
-{
-	g_return_val_if_fail (detail != NULL, NULL);
-	return pk_update_detail_new_from_data (detail->package_id, detail->updates, detail->obsoletes,
-					       detail->vendor_url, detail->bugzilla_url, detail->cve_url,
-					       detail->restart, detail->update_text);
-}
-
-/**
- * pk_update_detail_free:
- * @detail: the #PkUpdateDetail object
- *
- * Return value: %TRUE if the #PkUpdateDetail object was freed.
- **/
-gboolean
-pk_update_detail_free (PkUpdateDetail *detail)
-{
-	if (detail == NULL) {
-		return FALSE;
-	}
-	g_free (detail->updates);
-	g_free (detail->obsoletes);
-	g_free (detail->vendor_url);
-	g_free (detail->bugzilla_url);
-	g_free (detail->cve_url);
-	g_free (detail->update_text);
-	g_free (detail);
-	return TRUE;
-}
-
-/***************************************************************************
- ***                          MAKE CHECK TESTS                           ***
- ***************************************************************************/
-#ifdef PK_BUILD_TESTS
-#include <libselftest.h>
-
-void
-libst_update_detail (LibSelfTest *test)
-{
-	gboolean ret;
-	PkUpdateDetail *detail;
-
-	if (libst_start (test, "PkUpdateDetail", CLASS_AUTO) == FALSE) {
-		return;
-	}
-
-	/************************************************************
-	 ****************          IDENT           ******************
-	 ************************************************************/
-
-	/************************************************************/
-	libst_title (test, "get an detail object");
-	detail = pk_update_detail_new ();
-	if (detail != NULL) {
-		libst_success (test, NULL);
-	} else {
-		libst_failed (test, NULL);
-	}
-
-	/************************************************************/
-	libst_title (test, "test detail");
-	ret = pk_update_detail_free (detail);
-	if (ret) {
-		libst_success (test, NULL);
-	} else {
-		libst_failed (test, NULL);
-	}
-
-	pk_update_detail_free (detail);
-
-	libst_end (test);
-}
-#endif
-
diff --git a/libpackagekit/pk-update-detail.h b/libpackagekit/pk-update-detail.h
deleted file mode 100644
index 479d48a..0000000
--- a/libpackagekit/pk-update-detail.h
+++ /dev/null
@@ -1,61 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
- *
- * Copyright (C) 2007-2008 Richard Hughes <richard at hughsie.com>
- *
- * Licensed under the GNU General Public License Version 2
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-#ifndef __PK_UPDATE_DETAIL_H
-#define __PK_UPDATE_DETAIL_H
-
-#include <glib-object.h>
-#include <pk-enum.h>
-
-G_BEGIN_DECLS
-
-/**
- * PkUpdateDetail:
- *
- * Cached object to represent details about the update.
- **/
-typedef struct
-{
-	gchar				*package_id;
-	gchar				*updates;
-	gchar				*obsoletes;
-	gchar				*vendor_url;
-	gchar				*bugzilla_url;
-	gchar				*cve_url;
-	PkRestartEnum			 restart;
-	gchar				*update_text;
-} PkUpdateDetail;
-
-PkUpdateDetail	*pk_update_detail_new			(void);
-PkUpdateDetail	*pk_update_detail_copy			(const PkUpdateDetail	*detail);
-PkUpdateDetail	*pk_update_detail_new_from_data		(const gchar	*package_id,
-							 const gchar	*updates,
-							 const gchar	*obsoletes,
-							 const gchar	*vendor_url,
-							 const gchar	*bugzilla_url,
-							 const gchar	*cve_url,
-							 PkRestartEnum	 restart,
-							 const gchar	*update_text);
-gboolean	 pk_update_detail_free			(PkUpdateDetail	*detail);
-
-G_END_DECLS
-
-#endif /* __PK_UPDATE_DETAIL_H */
diff --git a/src/Makefile.am b/src/Makefile.am
index ea6e9b1..fb7a7ec 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -45,8 +45,6 @@ shared_SOURCES =					\
 	pk-marshal.h					\
 	pk-transaction.c				\
 	pk-transaction.h				\
-	pk-update-detail-cache.c			\
-	pk-update-detail-cache.h			\
 	pk-backend.c					\
 	pk-backend.h					\
 	pk-backend-internal.h				\
diff --git a/src/pk-backend.c b/src/pk-backend.c
index c27fe42..b6b5281 100644
--- a/src/pk-backend.c
+++ b/src/pk-backend.c
@@ -33,7 +33,7 @@
 #include <glib/gprintf.h>
 #include <pk-network.h>
 
-#include "pk-package-item.h"
+#include "pk-package-obj.h"
 #include "pk-debug.h"
 #include "pk-common.h"
 #include "pk-marshal.h"
@@ -41,8 +41,8 @@
 #include "pk-backend.h"
 #include "pk-time.h"
 #include "pk-file-monitor.h"
-#include "pk-update-detail.h"
-#include "pk-details.h"
+#include "pk-update-detail-obj.h"
+#include "pk-details-obj.h"
 
 #define PK_BACKEND_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), PK_TYPE_BACKEND, PkBackendPrivate))
 
@@ -88,7 +88,7 @@ struct _PkBackendPrivate
 	gboolean		 set_eula;
 	gboolean		 has_sent_package;
 	PkNetwork		*network;
-	PkPackageItem		*last_package;
+	PkPackageObj		*last_package;
 	PkRoleEnum		 role; /* this never changes for the lifetime of a transaction */
 	PkStatusEnum		 status; /* this changes */
 	PkExitEnum		 exit;
@@ -909,7 +909,7 @@ gboolean
 pk_backend_package (PkBackend *backend, PkInfoEnum info, const gchar *package_id, const gchar *summary)
 {
 	gchar *summary_safe;
-	PkPackageItem *item;
+	PkPackageObj *item;
 	gboolean ret;
 
 	g_return_val_if_fail (PK_IS_BACKEND (backend), FALSE);
@@ -917,17 +917,17 @@ pk_backend_package (PkBackend *backend, PkInfoEnum info, const gchar *package_id
 	g_return_val_if_fail (backend->priv->locked != FALSE, FALSE);
 
 	/* check against the old one */
-	item = pk_package_item_new (info, package_id, summary);
-	ret = pk_package_item_equal (item, backend->priv->last_package);
+	item = pk_package_obj_new (info, package_id, summary);
+	ret = pk_package_obj_equal (item, backend->priv->last_package);
 	if (ret) {
-		pk_package_item_free (item);
+		pk_package_obj_free (item);
 		pk_debug ("skipping duplicate %s", package_id);
 		return FALSE;
 	}
 	/* update the 'last' package */
-	pk_package_item_free (backend->priv->last_package);
-	backend->priv->last_package = pk_package_item_copy (item);
-	pk_package_item_free (item);
+	pk_package_obj_free (backend->priv->last_package);
+	backend->priv->last_package = pk_package_obj_copy (item);
+	pk_package_obj_free (item);
 
 	/* have we already set an error? */
 	if (backend->priv->set_error) {
@@ -973,7 +973,7 @@ pk_backend_update_detail (PkBackend *backend, const gchar *package_id,
 			  const gchar *update_text)
 {
 	gchar *update_text_safe;
-	PkUpdateDetail *detail;
+	PkUpdateDetailObj *detail;
 
 	g_return_val_if_fail (PK_IS_BACKEND (backend), FALSE);
 	g_return_val_if_fail (package_id != NULL, FALSE);
@@ -988,11 +988,11 @@ pk_backend_update_detail (PkBackend *backend, const gchar *package_id,
 	/* replace unsafe chars */
 	update_text_safe = pk_strsafe (update_text);
 
-	/* form PkUpdateDetail struct */
-	detail = pk_update_detail_new_from_data (package_id, updates, obsoletes, vendor_url, bugzilla_url, cve_url, restart, update_text_safe);
+	/* form PkUpdateDetailObj struct */
+	detail = pk_update_detail_obj_new_from_data (package_id, updates, obsoletes, vendor_url, bugzilla_url, cve_url, restart, update_text_safe);
 	g_signal_emit (backend, signals [PK_BACKEND_UPDATE_DETAIL], 0, detail);
 
-	pk_update_detail_free (detail);
+	pk_update_detail_obj_free (detail);
 	g_free (update_text_safe);
 	return TRUE;
 }
@@ -1098,7 +1098,7 @@ pk_backend_details (PkBackend *backend, const gchar *package_id,
 		    const gchar *description, const gchar *url, gulong size)
 {
 	gchar *description_safe;
-	PkDetails *details;
+	PkDetailsObj *details;
 
 	g_return_val_if_fail (PK_IS_BACKEND (backend), FALSE);
 	g_return_val_if_fail (package_id != NULL, FALSE);
@@ -1113,10 +1113,10 @@ pk_backend_details (PkBackend *backend, const gchar *package_id,
 	/* replace unsafe chars */
 	description_safe = pk_strsafe (description);
 
-	details = pk_details_new_from_data (package_id, license, group, description_safe, url, size);
+	details = pk_details_obj_new_from_data (package_id, license, group, description_safe, url, size);
 	g_signal_emit (backend, signals [PK_BACKEND_DETAILS], 0, details);
 
-	pk_details_free (details);
+	pk_details_obj_free (details);
 	g_free (description_safe);
 	return TRUE;
 }
@@ -1841,7 +1841,7 @@ pk_backend_reset (PkBackend *backend)
 
 	/* TODO: need to wait for Finished() if running */
 
-	pk_package_item_free (backend->priv->last_package);
+	pk_package_obj_free (backend->priv->last_package);
 	backend->priv->set_error = FALSE;
 	backend->priv->set_signature = FALSE;
 	backend->priv->set_eula = FALSE;
diff --git a/src/pk-engine.c b/src/pk-engine.c
index 1cdb08a..fc7235c 100644
--- a/src/pk-engine.c
+++ b/src/pk-engine.c
@@ -47,7 +47,7 @@
 #include <pk-enum.h>
 
 #include "pk-cache.h"
-#include "pk-update-detail-cache.h"
+#include "pk-update-detail-list.h"
 #include "pk-backend.h"
 #include "pk-backend-internal.h"
 #include "pk-engine.h"
@@ -97,7 +97,7 @@ struct PkEnginePrivate
 	PkTransactionList	*transaction_list;
 	PkTransactionDb		*transaction_db;
 	PkCache			*cache;
-	PkUpdateDetailCache	*update_detail_cache;
+	PkUpdateDetailList	*update_detail_cache;
 	PkBackend		*backend;
 	PkInhibit		*inhibit;
 	PkNetwork		*network;
@@ -662,7 +662,7 @@ pk_engine_init (PkEngine *engine)
 
 	/* we save a cache of the latest update lists sowe can do cached responses */
 	engine->priv->cache = pk_cache_new ();
-	engine->priv->update_detail_cache = pk_update_detail_cache_new ();
+	engine->priv->update_detail_cache = pk_update_detail_list_new ();
 
 	/* we need to be able to clear this */
 	engine->priv->signal_state_priority_timeout = 0;
diff --git a/src/pk-transaction.c b/src/pk-transaction.c
index 4a70524..992997d 100644
--- a/src/pk-transaction.c
+++ b/src/pk-transaction.c
@@ -46,8 +46,8 @@
 #include <pk-enum.h>
 #include <pk-debug.h>
 #include <pk-package-list.h>
-#include <pk-update-detail.h>
-#include <pk-details.h>
+#include <pk-update-detail-obj.h>
+#include <pk-details-obj.h>
 
 #include "pk-transaction.h"
 #include "pk-transaction-list.h"
@@ -56,7 +56,7 @@
 #include "pk-backend.h"
 #include "pk-backend-internal.h"
 #include "pk-inhibit.h"
-#include "pk-update-detail-cache.h"
+#include "pk-update-detail-list.h"
 #include "pk-cache.h"
 #include "pk-notify.h"
 #include "pk-security.h"
@@ -82,7 +82,7 @@ struct PkTransactionPrivate
 	PkBackend		*backend;
 	PkInhibit		*inhibit;
 	PkCache			*cache;
-	PkUpdateDetailCache	*update_detail_cache;
+	PkUpdateDetailList	*update_detail_list;
 	PkNotify		*notify;
 	PkSecurity		*security;
 
@@ -361,7 +361,7 @@ pk_transaction_caller_active_changed_cb (LibGBus *libgbus, gboolean is_active, P
  * pk_transaction_details_cb:
  **/
 static void
-pk_transaction_details_cb (PkBackend *backend, PkDetails *details, PkTransaction *transaction)
+pk_transaction_details_cb (PkBackend *backend, PkDetailsObj *details, PkTransaction *transaction)
 {
 	const gchar *group_text;
 
@@ -711,20 +711,15 @@ pk_transaction_transaction_cb (PkTransactionDb *tdb, const gchar *old_tid, const
  * pk_transaction_update_detail_cb:
  **/
 static void
-pk_transaction_update_detail_cb (PkBackend *backend, const PkUpdateDetail *detail, PkTransaction *transaction)
+pk_transaction_update_detail_cb (PkBackend *backend, const PkUpdateDetailObj *detail, PkTransaction *transaction)
 {
 	const gchar *restart_text;
-	PkUpdateDetail *detail_new;
 
 	g_return_if_fail (PK_IS_TRANSACTION (transaction));
 	g_return_if_fail (transaction->priv->tid != NULL);
 
-	/* are we already in the cache? */
-	detail_new = pk_update_detail_cache_get_item (transaction->priv->update_detail_cache, detail->package_id);
-	if (detail_new == NULL) {
-		detail_new = pk_update_detail_copy (detail);
-		pk_update_detail_cache_add_item (transaction->priv->update_detail_cache, detail_new);
-	}
+	/* add, if not already added? */
+	pk_update_detail_list_add_obj (transaction->priv->update_detail_list, detail);
 
 	restart_text = pk_restart_enum_to_text (detail->restart);
 	g_signal_emit (transaction, signals [PK_TRANSACTION_UPDATE_DETAIL], 0,
@@ -1691,7 +1686,7 @@ pk_transaction_get_update_detail (PkTransaction *transaction, gchar **package_id
 	GError *error;
 	gchar *package_ids_temp;
 	gchar **package_ids_new;
-	PkUpdateDetail *detail;
+	const PkUpdateDetailObj *detail;
 	GPtrArray *array;
 	guint i;
 	guint len;
@@ -1737,7 +1732,7 @@ pk_transaction_get_update_detail (PkTransaction *transaction, gchar **package_id
 	/* try and reuse cache */
 	len = g_strv_length (package_ids);
 	for (i=0; i<len; i++) {
-		detail = pk_update_detail_cache_get_item (transaction->priv->update_detail_cache, package_ids[i]);
+		detail = pk_update_detail_list_get_obj (transaction->priv->update_detail_list, package_ids[i]);
 		if (detail != NULL) {
 			pk_warning ("got %s", package_ids[i]);
 			/* emulate the backend */
@@ -1825,7 +1820,7 @@ pk_transaction_get_updates (PkTransaction *transaction, const gchar *filter, DBu
 	/* try and reuse cache */
 	updates_cache = pk_cache_get_updates (transaction->priv->cache);
 	if (updates_cache != NULL) {
-		PkPackageItem *package;
+		const PkPackageObj *package;
 		const gchar *info_text;
 		const gchar *exit_text;
 		guint i;
@@ -1836,7 +1831,7 @@ pk_transaction_get_updates (PkTransaction *transaction, const gchar *filter, DBu
 
 		/* emulate the backend */
 		for (i=0; i<length; i++) {
-			package = pk_package_list_get_item (updates_cache, i);
+			package = pk_package_list_get_obj (updates_cache, i);
 			info_text = pk_info_enum_to_text (package->info);
 			g_signal_emit (transaction, signals [PK_TRANSACTION_PACKAGE], 0,
 				       info_text, package->package_id, package->summary);
@@ -3077,7 +3072,7 @@ pk_transaction_init (PkTransaction *transaction)
 	transaction->priv->backend = pk_backend_new ();
 	transaction->priv->security = pk_security_new ();
 	transaction->priv->cache = pk_cache_new ();
-	transaction->priv->update_detail_cache = pk_update_detail_cache_new ();
+	transaction->priv->update_detail_list = pk_update_detail_list_new ();
 	transaction->priv->notify = pk_notify_new ();
 	transaction->priv->inhibit = pk_inhibit_new ();
 	transaction->priv->package_list = pk_package_list_new ();
@@ -3120,7 +3115,7 @@ pk_transaction_finalize (GObject *object)
 	/* remove any inhibit, it's okay to call this function when it's not needed */
 	pk_inhibit_remove (transaction->priv->inhibit, transaction);
 	g_object_unref (transaction->priv->cache);
-	g_object_unref (transaction->priv->update_detail_cache);
+	g_object_unref (transaction->priv->update_detail_list);
 	g_object_unref (transaction->priv->inhibit);
 	g_object_unref (transaction->priv->backend);
 	g_object_unref (transaction->priv->libgbus);
diff --git a/src/pk-update-detail-cache.c b/src/pk-update-detail-cache.c
deleted file mode 100644
index 86b23c2..0000000
--- a/src/pk-update-detail-cache.c
+++ /dev/null
@@ -1,203 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
- *
- * Copyright (C) 2008 Richard Hughes <richard at hughsie.com>
- *
- * Licensed under the GNU General Public License Version 2
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-#ifdef CONFIG_H
-#  include <config.h>
-#endif
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <sys/time.h>
-#include <sys/types.h>
-
-#include <glib/gi18n.h>
-#include <glib.h>
-
-#include "pk-debug.h"
-#include "pk-common.h"
-#include "pk-update-detail.h"
-#include "pk-update-detail-cache.h"
-
-#define PK_UPDATE_DETAIL_CACHE_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), PK_TYPE_UPDATE_DETAIL_CACHE, PkUpdateDetailCachePrivate))
-
-struct PkUpdateDetailCachePrivate
-{
-	GPtrArray		*array;
-};
-
-G_DEFINE_TYPE (PkUpdateDetailCache, pk_update_detail_cache, G_TYPE_OBJECT)
-static gpointer pk_update_detail_cache_object = NULL;
-
-/**
- * pk_update_detail_cache_invalidate:
- **/
-gboolean
-pk_update_detail_cache_invalidate (PkUpdateDetailCache *cache)
-{
-	g_return_val_if_fail (PK_IS_UPDATE_DETAIL_CACHE (cache), FALSE);
-	return TRUE;
-}
-
-/**
- * pk_update_detail_cache_add_item:
- **/
-gboolean
-pk_update_detail_cache_add_item (PkUpdateDetailCache *cache, PkUpdateDetail *detail)
-{
-	g_return_val_if_fail (PK_IS_UPDATE_DETAIL_CACHE (cache), FALSE);
-	g_return_val_if_fail (detail != NULL, FALSE);
-
-	g_ptr_array_add (cache->priv->array, detail);
-	return TRUE;
-}
-
-/**
- * pk_update_detail_cache_get_item:
- **/
-PkUpdateDetail *
-pk_update_detail_cache_get_item (PkUpdateDetailCache *cache, const gchar *package_id)
-{
-	guint i;
-	guint len;
-	PkUpdateDetail *detail;
-
-	g_return_val_if_fail (PK_IS_UPDATE_DETAIL_CACHE (cache), NULL);
-	g_return_val_if_fail (package_id != NULL, NULL);
-
-	len = cache->priv->array->len;
-	for (i=0; i<len; i++) {
-		detail = (PkUpdateDetail *) g_ptr_array_index (cache->priv->array, i);
-		if (pk_strequal (package_id, detail->package_id)) {
-			return detail;
-		}
-	}
-	/* bahh, found nothing */
-	return NULL;
-}
-
-/**
- * pk_update_detail_cache_finalize:
- **/
-static void
-pk_update_detail_cache_finalize (GObject *object)
-{
-	guint i;
-	guint len;
-	PkUpdateDetail *detail;
-	PkUpdateDetailCache *cache;
-	g_return_if_fail (PK_IS_UPDATE_DETAIL_CACHE (object));
-	cache = PK_UPDATE_DETAIL_CACHE (object);
-
-	//TODO: FREE!
-	len = cache->priv->array->len;
-	for (i=0; i<len; i++) {
-		detail = (PkUpdateDetail *) g_ptr_array_index (cache->priv->array, i);
-		pk_update_detail_free (detail);
-	}
-	g_ptr_array_free (cache->priv->array, FALSE);
-
-	G_OBJECT_CLASS (pk_update_detail_cache_parent_class)->finalize (object);
-}
-
-/**
- * pk_update_detail_cache_class_init:
- **/
-static void
-pk_update_detail_cache_class_init (PkUpdateDetailCacheClass *klass)
-{
-	GObjectClass *object_class = G_OBJECT_CLASS (klass);
-	object_class->finalize = pk_update_detail_cache_finalize;
-	g_type_class_add_private (klass, sizeof (PkUpdateDetailCachePrivate));
-}
-
-/**
- * pk_update_detail_cache_init:
- *
- * initializes the update_detail_cache class. NOTE: We expect cache objects
- * to *NOT* be removed or added during the session.
- * We only control the first cache object if there are more than one.
- **/
-static void
-pk_update_detail_cache_init (PkUpdateDetailCache *cache)
-{
-	cache->priv = PK_UPDATE_DETAIL_CACHE_GET_PRIVATE (cache);
-	cache->priv->array = g_ptr_array_new ();
-}
-
-/**
- * pk_update_detail_cache_new:
- * Return value: A new cache class instance.
- **/
-PkUpdateDetailCache *
-pk_update_detail_cache_new (void)
-{
-	if (pk_update_detail_cache_object != NULL) {
-		g_object_ref (pk_update_detail_cache_object);
-	} else {
-		pk_update_detail_cache_object = g_object_new (PK_TYPE_UPDATE_DETAIL_CACHE, NULL);
-		g_object_add_weak_pointer (pk_update_detail_cache_object, &pk_update_detail_cache_object);
-	}
-	return PK_UPDATE_DETAIL_CACHE (pk_update_detail_cache_object);
-}
-
-/***************************************************************************
- ***                          MAKE CHECK TESTS                           ***
- ***************************************************************************/
-#ifdef PK_BUILD_TESTS
-#include <libselftest.h>
-
-void
-libst_update_detail_cache (LibSelfTest *test)
-{
-	PkUpdateDetailCache *cache;
-	gchar *text;
-	gint value;
-
-	if (libst_start (test, "PkUpdateDetailCache", CLASS_AUTO) == FALSE) {
-		return;
-	}
-
-	/************************************************************/
-	libst_title (test, "get an instance");
-	cache = pk_update_detail_cache_new ();
-	if (cache != NULL) {
-		libst_success (test, NULL);
-	} else {
-		libst_failed (test, NULL);
-	}
-
-	/************************************************************/
-	libst_title (test, "get the default backend");
-	text = pk_update_detail_cache_get_string (cache, "DefaultBackend");
-	if (text != PK_UPDATE_DETAIL_CACHE_VALUE_STRING_MISSING) {
-		libst_success (test, "got default backend '%s'", text);
-	} else {
-		libst_failed (test, "got NULL!");
-	}
-	g_free (text);
-
-	g_object_unref (cache);
-
-	libst_end (test);
-}
-#endif
-
diff --git a/src/pk-update-detail-cache.h b/src/pk-update-detail-cache.h
deleted file mode 100644
index 9ded0d2..0000000
--- a/src/pk-update-detail-cache.h
+++ /dev/null
@@ -1,62 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
- *
- * Copyright (C) 2008 Richard Hughes <richard at hughsie.com>
- *
- * Licensed under the GNU General Public License Version 2
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-#ifndef __PK_UPDATE_DETAIL_CACHE_H
-#define __PK_UPDATE_DETAIL_CACHE_H
-
-#include <glib-object.h>
-#include <pk-update-detail.h>
-
-G_BEGIN_DECLS
-
-#define PK_TYPE_UPDATE_DETAIL_CACHE		(pk_update_detail_cache_get_type ())
-#define PK_UPDATE_DETAIL_CACHE(o)		(G_TYPE_CHECK_INSTANCE_CAST ((o), PK_TYPE_UPDATE_DETAIL_CACHE, PkUpdateDetailCache))
-#define PK_UPDATE_DETAIL_CACHE_CLASS(k)		(G_TYPE_CHECK_CLASS_CAST((k), PK_TYPE_UPDATE_DETAIL_CACHE, PkUpdateDetailCacheClass))
-#define PK_IS_UPDATE_DETAIL_CACHE(o)		(G_TYPE_CHECK_INSTANCE_TYPE ((o), PK_TYPE_UPDATE_DETAIL_CACHE))
-#define PK_IS_UPDATE_DETAIL_CACHE_CLASS(k)	(G_TYPE_CHECK_CLASS_TYPE ((k), PK_TYPE_UPDATE_DETAIL_CACHE))
-#define PK_UPDATE_DETAIL_CACHE_GET_CLASS(o)	(G_TYPE_INSTANCE_GET_CLASS ((o), PK_TYPE_UPDATE_DETAIL_CACHE, PkUpdateDetailCacheClass))
-
-typedef struct PkUpdateDetailCachePrivate PkUpdateDetailCachePrivate;
-
-typedef struct
-{
-	GObject		     		 parent;
-	PkUpdateDetailCachePrivate	*priv;
-} PkUpdateDetailCache;
-
-typedef struct
-{
-	GObjectClass			 parent_class;
-} PkUpdateDetailCacheClass;
-
-GType		 pk_update_detail_cache_get_type	(void) G_GNUC_CONST;
-PkUpdateDetailCache *pk_update_detail_cache_new		(void);
-
-gboolean	 pk_update_detail_cache_invalidate	(PkUpdateDetailCache	*cache);
-gboolean	 pk_update_detail_cache_add_item 	(PkUpdateDetailCache	*cache,
-							 PkUpdateDetail		*detail);
-PkUpdateDetail	*pk_update_detail_cache_get_item 	(PkUpdateDetailCache	*cache,
-							 const gchar		*package_id);
-
-
-G_END_DECLS
-
-#endif /* __PK_UPDATE_DETAIL_CACHE_H */
commit 4c835804883ec8ab29694358ec61992a8212dc53
Author: Richard Hughes <richard at hughsie.com>
Date:   Wed Jun 25 11:05:28 2008 +0100

    trivial: code cleanup - more to come

diff --git a/client/pk-console.c b/client/pk-console.c
index 017fe9d..fe672e8 100644
--- a/client/pk-console.c
+++ b/client/pk-console.c
@@ -213,7 +213,7 @@ pk_console_transaction_cb (PkClient *client, const gchar *tid, const gchar *time
  * pk_console_update_detail_cb:
  **/
 static void
-pk_console_update_detail_cb (PkClient *client, PkUpdateDetail *detail, gpointer data)
+pk_console_update_detail_cb (PkClient *client, const PkUpdateDetail *detail, gpointer data)
 {
 	if (awaiting_space) {
 		g_print ("\n");
@@ -996,7 +996,7 @@ pk_console_error_code_cb (PkClient *client, PkErrorCodeEnum error_code, const gc
  * pk_console_details_cb:
  **/
 static void
-pk_console_details_cb (PkClient *client, PkDetails *details, gpointer data)
+pk_console_details_cb (PkClient *client, const PkDetails *details, gpointer data)
 {
 	/* if on console, clear the progress bar line */
 	if (awaiting_space) {
diff --git a/libpackagekit/pk-update-detail.c b/libpackagekit/pk-update-detail.c
index d344f38..bfe754d 100644
--- a/libpackagekit/pk-update-detail.c
+++ b/libpackagekit/pk-update-detail.c
@@ -89,6 +89,20 @@ pk_update_detail_new_from_data (const gchar *package_id, const gchar *updates, c
 }
 
 /**
+ * pk_update_detail_copy:
+ *
+ * Return value: a new #PkUpdateDetail object
+ **/
+PkUpdateDetail *
+pk_update_detail_copy (const PkUpdateDetail *detail)
+{
+	g_return_val_if_fail (detail != NULL, NULL);
+	return pk_update_detail_new_from_data (detail->package_id, detail->updates, detail->obsoletes,
+					       detail->vendor_url, detail->bugzilla_url, detail->cve_url,
+					       detail->restart, detail->update_text);
+}
+
+/**
  * pk_update_detail_free:
  * @detail: the #PkUpdateDetail object
  *
diff --git a/libpackagekit/pk-update-detail.h b/libpackagekit/pk-update-detail.h
index 39c4d19..479d48a 100644
--- a/libpackagekit/pk-update-detail.h
+++ b/libpackagekit/pk-update-detail.h
@@ -45,6 +45,7 @@ typedef struct
 } PkUpdateDetail;
 
 PkUpdateDetail	*pk_update_detail_new			(void);
+PkUpdateDetail	*pk_update_detail_copy			(const PkUpdateDetail	*detail);
 PkUpdateDetail	*pk_update_detail_new_from_data		(const gchar	*package_id,
 							 const gchar	*updates,
 							 const gchar	*obsoletes,
diff --git a/src/pk-backend.c b/src/pk-backend.c
index 6efa55e..c27fe42 100644
--- a/src/pk-backend.c
+++ b/src/pk-backend.c
@@ -41,6 +41,8 @@
 #include "pk-backend.h"
 #include "pk-time.h"
 #include "pk-file-monitor.h"
+#include "pk-update-detail.h"
+#include "pk-details.h"
 
 #define PK_BACKEND_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), PK_TYPE_BACKEND, PkBackendPrivate))
 
@@ -971,6 +973,7 @@ pk_backend_update_detail (PkBackend *backend, const gchar *package_id,
 			  const gchar *update_text)
 {
 	gchar *update_text_safe;
+	PkUpdateDetail *detail;
 
 	g_return_val_if_fail (PK_IS_BACKEND (backend), FALSE);
 	g_return_val_if_fail (package_id != NULL, FALSE);
@@ -985,10 +988,11 @@ pk_backend_update_detail (PkBackend *backend, const gchar *package_id,
 	/* replace unsafe chars */
 	update_text_safe = pk_strsafe (update_text);
 
-	pk_debug ("emit update-detail %s, %s, %s, %s, %s, %s, %i, %s",
-		  package_id, updates, obsoletes, vendor_url, bugzilla_url, cve_url, restart, update_text_safe);
-	g_signal_emit (backend, signals [PK_BACKEND_UPDATE_DETAIL], 0,
-		       package_id, updates, obsoletes, vendor_url, bugzilla_url, cve_url, restart, update_text_safe);
+	/* form PkUpdateDetail struct */
+	detail = pk_update_detail_new_from_data (package_id, updates, obsoletes, vendor_url, bugzilla_url, cve_url, restart, update_text_safe);
+	g_signal_emit (backend, signals [PK_BACKEND_UPDATE_DETAIL], 0, detail);
+
+	pk_update_detail_free (detail);
 	g_free (update_text_safe);
 	return TRUE;
 }
@@ -1094,6 +1098,7 @@ pk_backend_details (PkBackend *backend, const gchar *package_id,
 		    const gchar *description, const gchar *url, gulong size)
 {
 	gchar *description_safe;
+	PkDetails *details;
 
 	g_return_val_if_fail (PK_IS_BACKEND (backend), FALSE);
 	g_return_val_if_fail (package_id != NULL, FALSE);
@@ -1108,12 +1113,10 @@ pk_backend_details (PkBackend *backend, const gchar *package_id,
 	/* replace unsafe chars */
 	description_safe = pk_strsafe (description);
 
-	pk_debug ("emit details %s, %s, %i, %s, %s, %ld",
-		  package_id, license, group, description_safe, url,
-		  size);
-	g_signal_emit (backend, signals [PK_BACKEND_DETAILS], 0,
-		       package_id, license, group, description_safe, url,
-		       size);
+	details = pk_details_new_from_data (package_id, license, group, description_safe, url, size);
+	g_signal_emit (backend, signals [PK_BACKEND_DETAILS], 0, details);
+
+	pk_details_free (details);
 	g_free (description_safe);
 	return TRUE;
 }
@@ -1754,9 +1757,8 @@ pk_backend_class_init (PkBackendClass *klass)
 	signals [PK_BACKEND_UPDATE_DETAIL] =
 		g_signal_new ("update-detail",
 			      G_TYPE_FROM_CLASS (object_class), G_SIGNAL_RUN_LAST,
-			      0, NULL, NULL, pk_marshal_VOID__STRING_STRING_STRING_STRING_STRING_STRING_UINT_STRING,
-			      G_TYPE_NONE, 8, G_TYPE_STRING, G_TYPE_STRING,
-			      G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_UINT, G_TYPE_STRING);
+			      0, NULL, NULL, g_cclosure_marshal_VOID__POINTER,
+			      G_TYPE_NONE, 1, G_TYPE_POINTER);
 	signals [PK_BACKEND_REQUIRE_RESTART] =
 		g_signal_new ("require-restart",
 			      G_TYPE_FROM_CLASS (object_class), G_SIGNAL_RUN_LAST,
@@ -1775,9 +1777,8 @@ pk_backend_class_init (PkBackendClass *klass)
 	signals [PK_BACKEND_DETAILS] =
 		g_signal_new ("details",
 			      G_TYPE_FROM_CLASS (object_class), G_SIGNAL_RUN_LAST,
-			      0, NULL, NULL, pk_marshal_VOID__STRING_STRING_UINT_STRING_STRING_UINT64,
-			      G_TYPE_NONE, 6, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_UINT, G_TYPE_STRING, G_TYPE_STRING,
-			      G_TYPE_UINT64);
+			      0, NULL, NULL, g_cclosure_marshal_VOID__POINTER,
+			      G_TYPE_NONE, 1, G_TYPE_POINTER);
 	signals [PK_BACKEND_FILES] =
 		g_signal_new ("files",
 			      G_TYPE_FROM_CLASS (object_class), G_SIGNAL_RUN_LAST,
diff --git a/src/pk-transaction.c b/src/pk-transaction.c
index f070239..4a70524 100644
--- a/src/pk-transaction.c
+++ b/src/pk-transaction.c
@@ -46,6 +46,8 @@
 #include <pk-enum.h>
 #include <pk-debug.h>
 #include <pk-package-list.h>
+#include <pk-update-detail.h>
+#include <pk-details.h>
 
 #include "pk-transaction.h"
 #include "pk-transaction-list.h"
@@ -359,20 +361,17 @@ pk_transaction_caller_active_changed_cb (LibGBus *libgbus, gboolean is_active, P
  * pk_transaction_details_cb:
  **/
 static void
-pk_transaction_details_cb (PkBackend *backend, const gchar *package_id, const gchar *license, PkGroupEnum group,
-			   const gchar *detail, const gchar *url, guint64 size, PkTransaction *transaction)
+pk_transaction_details_cb (PkBackend *backend, PkDetails *details, PkTransaction *transaction)
 {
 	const gchar *group_text;
 
 	g_return_if_fail (PK_IS_TRANSACTION (transaction));
 	g_return_if_fail (transaction->priv->tid != NULL);
 
-	group_text = pk_group_enum_to_text (group);
-
-	pk_debug ("emitting details %s, %s, %i, %s, %s, %ld",
-		  package_id, license, group, detail, url, (long int) size);
+	group_text = pk_group_enum_to_text (details->group);
 	g_signal_emit (transaction, signals [PK_TRANSACTION_DETAILS], 0,
-		       package_id, license, group_text, detail, url, size);
+		       details->package_id, details->license, group_text, details->description,
+		       details->url, details->size);
 }
 
 /**
@@ -712,31 +711,25 @@ pk_transaction_transaction_cb (PkTransactionDb *tdb, const gchar *old_tid, const
  * pk_transaction_update_detail_cb:
  **/
 static void
-pk_transaction_update_detail_cb (PkBackend *backend, const gchar *package_id,
-				 const gchar *updates, const gchar *obsoletes,
-				 const gchar *vendor_url, const gchar *bugzilla_url,
-				 const gchar *cve_url, PkRestartEnum restart,
-				 const gchar *update_text, PkTransaction *transaction)
+pk_transaction_update_detail_cb (PkBackend *backend, const PkUpdateDetail *detail, PkTransaction *transaction)
 {
 	const gchar *restart_text;
-	PkUpdateDetail *detail;
+	PkUpdateDetail *detail_new;
 
 	g_return_if_fail (PK_IS_TRANSACTION (transaction));
 	g_return_if_fail (transaction->priv->tid != NULL);
 
 	/* are we already in the cache? */
-	detail = pk_update_detail_cache_get_item (transaction->priv->update_detail_cache, package_id);
-	if (detail == NULL) {
-		detail = pk_update_detail_new_from_data (package_id, updates, obsoletes, vendor_url,
-							 bugzilla_url, cve_url, restart, update_text);
-		pk_update_detail_cache_add_item (transaction->priv->update_detail_cache, detail);
+	detail_new = pk_update_detail_cache_get_item (transaction->priv->update_detail_cache, detail->package_id);
+	if (detail_new == NULL) {
+		detail_new = pk_update_detail_copy (detail);
+		pk_update_detail_cache_add_item (transaction->priv->update_detail_cache, detail_new);
 	}
 
-	restart_text = pk_restart_enum_to_text (restart);
-	pk_debug ("emitting UpdateDetail value=%s, %s, %s, %s, %s, %s, %s, %s",
-		  package_id, updates, obsoletes, vendor_url, bugzilla_url, cve_url, restart_text, update_text);
+	restart_text = pk_restart_enum_to_text (detail->restart);
 	g_signal_emit (transaction, signals [PK_TRANSACTION_UPDATE_DETAIL], 0,
-		       package_id, updates, obsoletes, vendor_url, bugzilla_url, cve_url, restart_text, update_text);
+		       detail->package_id, detail->updates, detail->obsoletes, detail->vendor_url,
+		       detail->bugzilla_url, detail->cve_url, restart_text, detail->update_text);
 }
 
 
commit d97a549d7d0cb8846bbfd81dbb9f65f2f04c5d10
Author: Richard Hughes <richard at hughsie.com>
Date:   Tue Jun 24 21:54:56 2008 +0100

    Add the two files so we can cache the update detail

diff --git a/src/pk-update-detail-cache.c b/src/pk-update-detail-cache.c
new file mode 100644
index 0000000..86b23c2
--- /dev/null
+++ b/src/pk-update-detail-cache.c
@@ -0,0 +1,203 @@
+/* -*- 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.
+ */
+
+#ifdef CONFIG_H
+#  include <config.h>
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/time.h>
+#include <sys/types.h>
+
+#include <glib/gi18n.h>
+#include <glib.h>
+
+#include "pk-debug.h"
+#include "pk-common.h"
+#include "pk-update-detail.h"
+#include "pk-update-detail-cache.h"
+
+#define PK_UPDATE_DETAIL_CACHE_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), PK_TYPE_UPDATE_DETAIL_CACHE, PkUpdateDetailCachePrivate))
+
+struct PkUpdateDetailCachePrivate
+{
+	GPtrArray		*array;
+};
+
+G_DEFINE_TYPE (PkUpdateDetailCache, pk_update_detail_cache, G_TYPE_OBJECT)
+static gpointer pk_update_detail_cache_object = NULL;
+
+/**
+ * pk_update_detail_cache_invalidate:
+ **/
+gboolean
+pk_update_detail_cache_invalidate (PkUpdateDetailCache *cache)
+{
+	g_return_val_if_fail (PK_IS_UPDATE_DETAIL_CACHE (cache), FALSE);
+	return TRUE;
+}
+
+/**
+ * pk_update_detail_cache_add_item:
+ **/
+gboolean
+pk_update_detail_cache_add_item (PkUpdateDetailCache *cache, PkUpdateDetail *detail)
+{
+	g_return_val_if_fail (PK_IS_UPDATE_DETAIL_CACHE (cache), FALSE);
+	g_return_val_if_fail (detail != NULL, FALSE);
+
+	g_ptr_array_add (cache->priv->array, detail);
+	return TRUE;
+}
+
+/**
+ * pk_update_detail_cache_get_item:
+ **/
+PkUpdateDetail *
+pk_update_detail_cache_get_item (PkUpdateDetailCache *cache, const gchar *package_id)
+{
+	guint i;
+	guint len;
+	PkUpdateDetail *detail;
+
+	g_return_val_if_fail (PK_IS_UPDATE_DETAIL_CACHE (cache), NULL);
+	g_return_val_if_fail (package_id != NULL, NULL);
+
+	len = cache->priv->array->len;
+	for (i=0; i<len; i++) {
+		detail = (PkUpdateDetail *) g_ptr_array_index (cache->priv->array, i);
+		if (pk_strequal (package_id, detail->package_id)) {
+			return detail;
+		}
+	}
+	/* bahh, found nothing */
+	return NULL;
+}
+
+/**
+ * pk_update_detail_cache_finalize:
+ **/
+static void
+pk_update_detail_cache_finalize (GObject *object)
+{
+	guint i;
+	guint len;
+	PkUpdateDetail *detail;
+	PkUpdateDetailCache *cache;
+	g_return_if_fail (PK_IS_UPDATE_DETAIL_CACHE (object));
+	cache = PK_UPDATE_DETAIL_CACHE (object);
+
+	//TODO: FREE!
+	len = cache->priv->array->len;
+	for (i=0; i<len; i++) {
+		detail = (PkUpdateDetail *) g_ptr_array_index (cache->priv->array, i);
+		pk_update_detail_free (detail);
+	}
+	g_ptr_array_free (cache->priv->array, FALSE);
+
+	G_OBJECT_CLASS (pk_update_detail_cache_parent_class)->finalize (object);
+}
+
+/**
+ * pk_update_detail_cache_class_init:
+ **/
+static void
+pk_update_detail_cache_class_init (PkUpdateDetailCacheClass *klass)
+{
+	GObjectClass *object_class = G_OBJECT_CLASS (klass);
+	object_class->finalize = pk_update_detail_cache_finalize;
+	g_type_class_add_private (klass, sizeof (PkUpdateDetailCachePrivate));
+}
+
+/**
+ * pk_update_detail_cache_init:
+ *
+ * initializes the update_detail_cache class. NOTE: We expect cache objects
+ * to *NOT* be removed or added during the session.
+ * We only control the first cache object if there are more than one.
+ **/
+static void
+pk_update_detail_cache_init (PkUpdateDetailCache *cache)
+{
+	cache->priv = PK_UPDATE_DETAIL_CACHE_GET_PRIVATE (cache);
+	cache->priv->array = g_ptr_array_new ();
+}
+
+/**
+ * pk_update_detail_cache_new:
+ * Return value: A new cache class instance.
+ **/
+PkUpdateDetailCache *
+pk_update_detail_cache_new (void)
+{
+	if (pk_update_detail_cache_object != NULL) {
+		g_object_ref (pk_update_detail_cache_object);
+	} else {
+		pk_update_detail_cache_object = g_object_new (PK_TYPE_UPDATE_DETAIL_CACHE, NULL);
+		g_object_add_weak_pointer (pk_update_detail_cache_object, &pk_update_detail_cache_object);
+	}
+	return PK_UPDATE_DETAIL_CACHE (pk_update_detail_cache_object);
+}
+
+/***************************************************************************
+ ***                          MAKE CHECK TESTS                           ***
+ ***************************************************************************/
+#ifdef PK_BUILD_TESTS
+#include <libselftest.h>
+
+void
+libst_update_detail_cache (LibSelfTest *test)
+{
+	PkUpdateDetailCache *cache;
+	gchar *text;
+	gint value;
+
+	if (libst_start (test, "PkUpdateDetailCache", CLASS_AUTO) == FALSE) {
+		return;
+	}
+
+	/************************************************************/
+	libst_title (test, "get an instance");
+	cache = pk_update_detail_cache_new ();
+	if (cache != NULL) {
+		libst_success (test, NULL);
+	} else {
+		libst_failed (test, NULL);
+	}
+
+	/************************************************************/
+	libst_title (test, "get the default backend");
+	text = pk_update_detail_cache_get_string (cache, "DefaultBackend");
+	if (text != PK_UPDATE_DETAIL_CACHE_VALUE_STRING_MISSING) {
+		libst_success (test, "got default backend '%s'", text);
+	} else {
+		libst_failed (test, "got NULL!");
+	}
+	g_free (text);
+
+	g_object_unref (cache);
+
+	libst_end (test);
+}
+#endif
+
diff --git a/src/pk-update-detail-cache.h b/src/pk-update-detail-cache.h
new file mode 100644
index 0000000..9ded0d2
--- /dev/null
+++ b/src/pk-update-detail-cache.h
@@ -0,0 +1,62 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2008 Richard Hughes <richard at hughsie.com>
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __PK_UPDATE_DETAIL_CACHE_H
+#define __PK_UPDATE_DETAIL_CACHE_H
+
+#include <glib-object.h>
+#include <pk-update-detail.h>
+
+G_BEGIN_DECLS
+
+#define PK_TYPE_UPDATE_DETAIL_CACHE		(pk_update_detail_cache_get_type ())
+#define PK_UPDATE_DETAIL_CACHE(o)		(G_TYPE_CHECK_INSTANCE_CAST ((o), PK_TYPE_UPDATE_DETAIL_CACHE, PkUpdateDetailCache))
+#define PK_UPDATE_DETAIL_CACHE_CLASS(k)		(G_TYPE_CHECK_CLASS_CAST((k), PK_TYPE_UPDATE_DETAIL_CACHE, PkUpdateDetailCacheClass))
+#define PK_IS_UPDATE_DETAIL_CACHE(o)		(G_TYPE_CHECK_INSTANCE_TYPE ((o), PK_TYPE_UPDATE_DETAIL_CACHE))
+#define PK_IS_UPDATE_DETAIL_CACHE_CLASS(k)	(G_TYPE_CHECK_CLASS_TYPE ((k), PK_TYPE_UPDATE_DETAIL_CACHE))
+#define PK_UPDATE_DETAIL_CACHE_GET_CLASS(o)	(G_TYPE_INSTANCE_GET_CLASS ((o), PK_TYPE_UPDATE_DETAIL_CACHE, PkUpdateDetailCacheClass))
+
+typedef struct PkUpdateDetailCachePrivate PkUpdateDetailCachePrivate;
+
+typedef struct
+{
+	GObject		     		 parent;
+	PkUpdateDetailCachePrivate	*priv;
+} PkUpdateDetailCache;
+
+typedef struct
+{
+	GObjectClass			 parent_class;
+} PkUpdateDetailCacheClass;
+
+GType		 pk_update_detail_cache_get_type	(void) G_GNUC_CONST;
+PkUpdateDetailCache *pk_update_detail_cache_new		(void);
+
+gboolean	 pk_update_detail_cache_invalidate	(PkUpdateDetailCache	*cache);
+gboolean	 pk_update_detail_cache_add_item 	(PkUpdateDetailCache	*cache,
+							 PkUpdateDetail		*detail);
+PkUpdateDetail	*pk_update_detail_cache_get_item 	(PkUpdateDetailCache	*cache,
+							 const gchar		*package_id);
+
+
+G_END_DECLS
+
+#endif /* __PK_UPDATE_DETAIL_CACHE_H */
commit 52faf07249215b7da028944526aaf127b91ea52a
Author: Richard Hughes <richard at hughsie.com>
Date:   Tue Jun 24 21:40:40 2008 +0100

    convert to using the PkUpdateDetail and PkDetails in the pk-client callbacks so we can add struct members in the future

diff --git a/client/pk-console.c b/client/pk-console.c
index bef0ce9..017fe9d 100644
--- a/client/pk-console.c
+++ b/client/pk-console.c
@@ -38,6 +38,7 @@
 #include <pk-package-id.h>
 #include <pk-common.h>
 #include <pk-connection.h>
+#include <pk-update-detail.h>
 
 #define PROGRESS_BAR_SIZE 15
 
@@ -212,37 +213,33 @@ pk_console_transaction_cb (PkClient *client, const gchar *tid, const gchar *time
  * pk_console_update_detail_cb:
  **/
 static void
-pk_console_update_detail_cb (PkClient *client, const gchar *package_id,
-			     const gchar *updates, const gchar *obsoletes,
-			     const gchar *vendor_url, const gchar *bugzilla_url,
-			     const gchar *cve_url, PkRestartEnum restart,
-			     const gchar *update_text, gpointer data)
+pk_console_update_detail_cb (PkClient *client, PkUpdateDetail *detail, gpointer data)
 {
 	if (awaiting_space) {
 		g_print ("\n");
 	}
 	g_print ("%s\n", _("Update detail"));
-	g_print ("  package:    '%s'\n", package_id);
-	if (pk_strzero (updates) == FALSE) {
-		g_print ("  updates:    '%s'\n", updates);
+	g_print ("  package:    '%s'\n", detail->package_id);
+	if (pk_strzero (detail->updates) == FALSE) {
+		g_print ("  updates:    '%s'\n", detail->updates);
 	}
-	if (pk_strzero (obsoletes) == FALSE) {
-		g_print ("  obsoletes:  '%s'\n", obsoletes);
+	if (pk_strzero (detail->obsoletes) == FALSE) {
+		g_print ("  obsoletes:  '%s'\n", detail->obsoletes);
 	}
-	if (pk_strzero (vendor_url) == FALSE) {
-		g_print ("  vendor URL: '%s'\n", vendor_url);
+	if (pk_strzero (detail->vendor_url) == FALSE) {
+		g_print ("  vendor URL: '%s'\n", detail->vendor_url);
 	}
-	if (pk_strzero (bugzilla_url) == FALSE) {
-		g_print ("  bug URL:    '%s'\n", bugzilla_url);
+	if (pk_strzero (detail->bugzilla_url) == FALSE) {
+		g_print ("  bug URL:    '%s'\n", detail->bugzilla_url);
 	}
-	if (pk_strzero (cve_url) == FALSE) {
-		g_print ("  cve URL:    '%s'\n", cve_url);
+	if (pk_strzero (detail->cve_url) == FALSE) {
+		g_print ("  cve URL:    '%s'\n", detail->cve_url);
 	}
-	if (restart != PK_RESTART_ENUM_NONE) {
-		g_print ("  restart:    '%s'\n", pk_restart_enum_to_text (restart));
+	if (detail->restart != PK_RESTART_ENUM_NONE) {
+		g_print ("  restart:    '%s'\n", pk_restart_enum_to_text (detail->restart));
 	}
-	if (pk_strzero (update_text) == FALSE) {
-		g_print ("  update_text:'%s'\n", update_text);
+	if (pk_strzero (detail->update_text) == FALSE) {
+		g_print ("  update_text:'%s'\n", detail->update_text);
 	}
 }
 
@@ -999,22 +996,19 @@ pk_console_error_code_cb (PkClient *client, PkErrorCodeEnum error_code, const gc
  * pk_console_details_cb:
  **/
 static void
-pk_console_details_cb (PkClient *client, const gchar *package_id,
-			   const gchar *license, PkGroupEnum group,
-			   const gchar *description, const gchar *url,
-			   gulong size, gpointer data)
+pk_console_details_cb (PkClient *client, PkDetails *details, gpointer data)
 {
 	/* if on console, clear the progress bar line */
 	if (awaiting_space) {
 		g_print ("\n");
 	}
 	g_print ("%s\n", _("Package description"));
-	g_print ("  package:     '%s'\n", package_id);
-	g_print ("  license:     '%s'\n", license);
-	g_print ("  group:       '%s'\n", pk_group_enum_to_text (group));
-	g_print ("  description: '%s'\n", description);
-	g_print ("  size:        '%ld' bytes\n", size);
-	g_print ("  url:         '%s'\n", url);
+	g_print ("  package:     '%s'\n", details->package_id);
+	g_print ("  license:     '%s'\n", details->license);
+	g_print ("  group:       '%s'\n", pk_group_enum_to_text (details->group));
+	g_print ("  description: '%s'\n", details->description);
+	g_print ("  size:        '%lu' bytes\n", (long unsigned int) details->size);
+	g_print ("  url:         '%s'\n", details->url);
 }
 
 /**
diff --git a/libpackagekit/pk-client.c b/libpackagekit/pk-client.c
index f525e43..4e3060f 100644
--- a/libpackagekit/pk-client.c
+++ b/libpackagekit/pk-client.c
@@ -56,6 +56,8 @@
 #include "pk-marshal.h"
 #include "pk-common.h"
 #include "pk-control.h"
+#include "pk-update-detail.h"
+#include "pk-details.h"
 
 static void     pk_client_class_init	(PkClientClass *klass);
 static void     pk_client_init		(PkClient      *client);
@@ -588,48 +590,45 @@ pk_client_transaction_cb (DBusGProxy *proxy, const gchar *old_tid, const gchar *
  * pk_client_update_detail_cb:
  */
 static void
-pk_client_update_detail_cb (DBusGProxy  *proxy,
-			    const gchar *package_id,
-			    const gchar *updates,
-			    const gchar *obsoletes,
-			    const gchar *vendor_url,
-			    const gchar *bugzilla_url,
-			    const gchar *cve_url,
-			    const gchar *restart_text,
-			    const gchar *update_text,
-			    PkClient    *client)
+pk_client_update_detail_cb (DBusGProxy  *proxy, const gchar *package_id, const gchar *updates,
+			    const gchar *obsoletes, const gchar *vendor_url, const gchar *bugzilla_url,
+			    const gchar *cve_url, const gchar *restart_text, const gchar *update_text, PkClient *client)
 {
 	PkRestartEnum restart;
+	PkUpdateDetail *detail;
+
 	g_return_if_fail (PK_IS_CLIENT (client));
 
 	pk_debug ("emit update-detail %s, %s, %s, %s, %s, %s, %s, %s",
 		  package_id, updates, obsoletes, vendor_url, bugzilla_url, cve_url, restart_text, update_text);
 	restart = pk_restart_enum_from_text (restart_text);
-	g_signal_emit (client , signals [PK_CLIENT_UPDATE_DETAIL], 0,
-		       package_id, updates, obsoletes, vendor_url, bugzilla_url, cve_url, restart, update_text);
+
+	detail = pk_update_detail_new_from_data (package_id, updates, obsoletes, vendor_url,
+						 bugzilla_url, cve_url, restart, update_text);
+	g_signal_emit (client, signals [PK_CLIENT_UPDATE_DETAIL], 0, detail);
+	pk_update_detail_free (detail);
 }
 
 /**
  * pk_client_details_cb:
  */
 static void
-pk_client_details_cb (DBusGProxy  *proxy,
-		      const gchar *package_id,
-		      const gchar *license,
-		      const gchar *group_text,
-		      const gchar *description,
-		      const gchar *url,
-		      guint64      size,
-		      PkClient    *client)
+pk_client_details_cb (DBusGProxy *proxy, const gchar *package_id, const gchar *license,
+		      const gchar *group_text, const gchar *description, const gchar *url,
+		      guint64 size, PkClient *client)
 {
 	PkGroupEnum group;
+	PkDetails *details;
 	g_return_if_fail (PK_IS_CLIENT (client));
 
 	group = pk_group_enum_from_text (group_text);
+
 	pk_debug ("emit details %s, %s, %s, %s, %s, %ld",
 		  package_id, license, pk_group_enum_to_text (group), description, url, (long int) size);
-	g_signal_emit (client , signals [PK_CLIENT_DETAILS], 0,
-		       package_id, license, group, description, url, size);
+
+	details = pk_details_new_from_data (package_id, license, group, description, url, size);
+	g_signal_emit (client, signals [PK_CLIENT_DETAILS], 0, details);
+	pk_details_free (details);
 }
 
 /**
@@ -3241,10 +3240,8 @@ pk_client_class_init (PkClientClass *klass)
 		g_signal_new ("update-detail",
 			      G_TYPE_FROM_CLASS (object_class), G_SIGNAL_RUN_LAST,
 			      G_STRUCT_OFFSET (PkClientClass, update_detail),
-			      NULL, NULL, pk_marshal_VOID__STRING_STRING_STRING_STRING_STRING_STRING_STRING_STRING,
-			      G_TYPE_NONE, 8, G_TYPE_STRING, G_TYPE_STRING,
-			      G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING,
-			      G_TYPE_STRING, G_TYPE_UINT, G_TYPE_STRING);
+			      NULL, NULL, g_cclosure_marshal_VOID__POINTER,
+			      G_TYPE_NONE, 1, G_TYPE_POINTER);
 	/**
 	 * PkClient::details:
 	 * @client: the #PkClient instance that emitted the signal
@@ -3261,9 +3258,8 @@ pk_client_class_init (PkClientClass *klass)
 		g_signal_new ("details",
 			      G_TYPE_FROM_CLASS (object_class), G_SIGNAL_RUN_LAST,
 			      G_STRUCT_OFFSET (PkClientClass, details),
-			      NULL, NULL, pk_marshal_VOID__STRING_STRING_UINT_STRING_STRING_UINT64,
-			      G_TYPE_NONE, 6, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_UINT, G_TYPE_STRING,
-			      G_TYPE_STRING, G_TYPE_UINT64);
+			      NULL, NULL, g_cclosure_marshal_VOID__POINTER,
+			      G_TYPE_NONE, 1, G_TYPE_POINTER);
 	/**
 	 * PkClient::files:
 	 * @package_id: the package_id of the package
diff --git a/libpackagekit/pk-client.h b/libpackagekit/pk-client.h
index 1582488..636ab8f 100644
--- a/libpackagekit/pk-client.h
+++ b/libpackagekit/pk-client.h
@@ -25,6 +25,8 @@
 #include <glib-object.h>
 #include "pk-enum.h"
 #include "pk-package-list.h"
+#include "pk-update-detail.h"
+#include "pk-details.h"
 
 G_BEGIN_DECLS
 
@@ -97,21 +99,9 @@ struct _PkClientClass
 							 guint		 duration,
 							 const gchar	*data);
 	void		(* update_detail)		(PkClient	*client,
-							 const gchar	*package_id,
-							 const gchar	*updates,
-							 const gchar	*obsoletes,
-							 const gchar	*vendor_url,
-							 const gchar	*bugzilla_url,
-							 const gchar	*cve_url,
-							 PkRestartEnum	 restart,
-							 const gchar	*update_text);
+							 PkUpdateDetail	*update_detail);
 	void		(* details)			(PkClient	*client,
-							 const gchar	*package_id,
-							 const gchar	*license,
-							 PkGroupEnum	 group,
-							 const gchar	*description,
-							 const gchar	*url,
-							 gulong		 size);
+							 PkDetails	*package_detail);
 	void		(* files)			(PkClient	*client,
 							 const gchar	*package_id,
 							 const gchar	*filelist);
diff --git a/src/Makefile.am b/src/Makefile.am
index fb7a7ec..ea6e9b1 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -45,6 +45,8 @@ shared_SOURCES =					\
 	pk-marshal.h					\
 	pk-transaction.c				\
 	pk-transaction.h				\
+	pk-update-detail-cache.c			\
+	pk-update-detail-cache.h			\
 	pk-backend.c					\
 	pk-backend.h					\
 	pk-backend-internal.h				\
diff --git a/src/pk-engine.c b/src/pk-engine.c
index 14ecf41..1cdb08a 100644
--- a/src/pk-engine.c
+++ b/src/pk-engine.c
@@ -47,6 +47,7 @@
 #include <pk-enum.h>
 
 #include "pk-cache.h"
+#include "pk-update-detail-cache.h"
 #include "pk-backend.h"
 #include "pk-backend-internal.h"
 #include "pk-engine.h"
@@ -96,6 +97,7 @@ struct PkEnginePrivate
 	PkTransactionList	*transaction_list;
 	PkTransactionDb		*transaction_db;
 	PkCache			*cache;
+	PkUpdateDetailCache	*update_detail_cache;
 	PkBackend		*backend;
 	PkInhibit		*inhibit;
 	PkNetwork		*network;
@@ -660,6 +662,7 @@ pk_engine_init (PkEngine *engine)
 
 	/* we save a cache of the latest update lists sowe can do cached responses */
 	engine->priv->cache = pk_cache_new ();
+	engine->priv->update_detail_cache = pk_update_detail_cache_new ();
 
 	/* we need to be able to clear this */
 	engine->priv->signal_state_priority_timeout = 0;
@@ -752,6 +755,7 @@ pk_engine_finalize (GObject *object)
 	g_object_unref (engine->priv->notify);
 	g_object_unref (engine->priv->backend);
 	g_object_unref (engine->priv->cache);
+	g_object_unref (engine->priv->update_detail_cache);
 	g_object_unref (engine->priv->conf);
 
 	G_OBJECT_CLASS (pk_engine_parent_class)->finalize (object);
diff --git a/src/pk-transaction.c b/src/pk-transaction.c
index e95281c..f070239 100644
--- a/src/pk-transaction.c
+++ b/src/pk-transaction.c
@@ -54,6 +54,7 @@
 #include "pk-backend.h"
 #include "pk-backend-internal.h"
 #include "pk-inhibit.h"
+#include "pk-update-detail-cache.h"
 #include "pk-cache.h"
 #include "pk-notify.h"
 #include "pk-security.h"
@@ -79,6 +80,7 @@ struct PkTransactionPrivate
 	PkBackend		*backend;
 	PkInhibit		*inhibit;
 	PkCache			*cache;
+	PkUpdateDetailCache	*update_detail_cache;
 	PkNotify		*notify;
 	PkSecurity		*security;
 
@@ -358,8 +360,7 @@ pk_transaction_caller_active_changed_cb (LibGBus *libgbus, gboolean is_active, P
  **/
 static void
 pk_transaction_details_cb (PkBackend *backend, const gchar *package_id, const gchar *license, PkGroupEnum group,
-			       const gchar *detail, const gchar *url,
-			       guint64 size, PkTransaction *transaction)
+			   const gchar *detail, const gchar *url, guint64 size, PkTransaction *transaction)
 {
 	const gchar *group_text;
 
@@ -368,8 +369,8 @@ pk_transaction_details_cb (PkBackend *backend, const gchar *package_id, const gc
 
 	group_text = pk_group_enum_to_text (group);
 
-	pk_debug ("emitting details %s, %s, %s, %s, %s, %ld",
-		  package_id, license, group_text, detail, url, (long int) size);
+	pk_debug ("emitting details %s, %s, %i, %s, %s, %ld",
+		  package_id, license, group, detail, url, (long int) size);
 	g_signal_emit (transaction, signals [PK_TRANSACTION_DETAILS], 0,
 		       package_id, license, group_text, detail, url, size);
 }
@@ -718,12 +719,21 @@ pk_transaction_update_detail_cb (PkBackend *backend, const gchar *package_id,
 				 const gchar *update_text, PkTransaction *transaction)
 {
 	const gchar *restart_text;
+	PkUpdateDetail *detail;
 
 	g_return_if_fail (PK_IS_TRANSACTION (transaction));
 	g_return_if_fail (transaction->priv->tid != NULL);
 
+	/* are we already in the cache? */
+	detail = pk_update_detail_cache_get_item (transaction->priv->update_detail_cache, package_id);
+	if (detail == NULL) {
+		detail = pk_update_detail_new_from_data (package_id, updates, obsoletes, vendor_url,
+							 bugzilla_url, cve_url, restart, update_text);
+		pk_update_detail_cache_add_item (transaction->priv->update_detail_cache, detail);
+	}
+
 	restart_text = pk_restart_enum_to_text (restart);
-	pk_debug ("emitting package value=%s, %s, %s, %s, %s, %s, %s, %s",
+	pk_debug ("emitting UpdateDetail value=%s, %s, %s, %s, %s, %s, %s, %s",
 		  package_id, updates, obsoletes, vendor_url, bugzilla_url, cve_url, restart_text, update_text);
 	g_signal_emit (transaction, signals [PK_TRANSACTION_UPDATE_DETAIL], 0,
 		       package_id, updates, obsoletes, vendor_url, bugzilla_url, cve_url, restart_text, update_text);
@@ -1687,6 +1697,11 @@ pk_transaction_get_update_detail (PkTransaction *transaction, gchar **package_id
 	gboolean ret;
 	GError *error;
 	gchar *package_ids_temp;
+	gchar **package_ids_new;
+	PkUpdateDetail *detail;
+	GPtrArray *array;
+	guint i;
+	guint len;
 
 	g_return_if_fail (PK_IS_TRANSACTION (transaction));
 	g_return_if_fail (transaction->priv->tid != NULL);
@@ -1695,6 +1710,9 @@ pk_transaction_get_update_detail (PkTransaction *transaction, gchar **package_id
 	pk_debug ("GetUpdateDetail method called: %s", package_ids_temp);
 	g_free (package_ids_temp);
 
+	/* need to split the package_ids into new and cached */
+	array = g_ptr_array_new ();
+
 	/* not implemented yet */
 	if (transaction->priv->backend->desc->get_update_detail == NULL) {
 		pk_debug ("Not implemented yet: GetUpdateDetail");
@@ -1723,6 +1741,40 @@ pk_transaction_get_update_detail (PkTransaction *transaction, gchar **package_id
 	transaction->priv->status = PK_STATUS_ENUM_WAIT;
 	pk_transaction_set_role (transaction, PK_ROLE_ENUM_GET_UPDATE_DETAIL);
 
+	/* try and reuse cache */
+	len = g_strv_length (package_ids);
+	for (i=0; i<len; i++) {
+		detail = pk_update_detail_cache_get_item (transaction->priv->update_detail_cache, package_ids[i]);
+		if (detail != NULL) {
+			pk_warning ("got %s", package_ids[i]);
+			/* emulate the backend */
+			g_signal_emit (transaction, signals [PK_TRANSACTION_UPDATE_DETAIL], 0,
+				       detail->package_id, detail->updates, detail->obsoletes,
+				       detail->vendor_url, detail->bugzilla_url, detail->cve_url,
+				       pk_restart_enum_to_text (detail->restart), detail->update_text);
+		} else {
+			pk_warning ("not got %s", package_ids[i]);
+			g_ptr_array_add (array, g_strdup (package_ids[i]));
+		}
+	}
+
+	/* if we have nothing to do, i.e. everything was in the cache */
+	if (array->len == 0) {
+		const gchar *exit_text;
+		exit_text = pk_exit_enum_to_text (PK_EXIT_ENUM_SUCCESS);
+		pk_debug ("emitting finished '%s' as no more to process", exit_text);
+		g_signal_emit (transaction, signals [PK_TRANSACTION_FINISHED], 0, exit_text, 0);
+		goto out;
+	}
+
+	/* get the new list */
+	pk_debug ("%i more to process", array->len);
+	package_ids_new = pk_ptr_array_to_argv (array);
+
+	/* alter list */
+	g_strfreev (transaction->priv->cached_package_ids);
+	transaction->priv->cached_package_ids = g_strdupv (package_ids_new);
+
 	/* try to commit this */
 	ret = pk_transaction_commit (transaction);
 	if (!ret) {
@@ -1733,6 +1785,8 @@ pk_transaction_get_update_detail (PkTransaction *transaction, gchar **package_id
 		return;
 	}
 
+out:
+	g_ptr_array_free (array, TRUE);
 	dbus_g_method_return (context);
 }
 
@@ -1770,6 +1824,11 @@ pk_transaction_get_updates (PkTransaction *transaction, const gchar *filter, DBu
 	/* set the dbus name, so we can get the disconnect */
 	pk_transaction_set_dbus_name (transaction, dbus_g_method_get_sender (context));
 
+	/* save so we can run later */
+	transaction->priv->cached_filters = pk_filter_enums_from_text (filter);
+	transaction->priv->status = PK_STATUS_ENUM_WAIT;
+	pk_transaction_set_role (transaction, PK_ROLE_ENUM_GET_UPDATES);
+
 	/* try and reuse cache */
 	updates_cache = pk_cache_get_updates (transaction->priv->cache);
 	if (updates_cache != NULL) {
@@ -1783,7 +1842,6 @@ pk_transaction_get_updates (PkTransaction *transaction, const gchar *filter, DBu
 		pk_debug ("we have cached data (%i) we should use!", length);
 
 		/* emulate the backend */
-		pk_transaction_set_role (transaction, PK_ROLE_ENUM_GET_UPDATES);
 		for (i=0; i<length; i++) {
 			package = pk_package_list_get_item (updates_cache, i);
 			info_text = pk_info_enum_to_text (package->info);
@@ -1800,11 +1858,6 @@ pk_transaction_get_updates (PkTransaction *transaction, const gchar *filter, DBu
 		return;
 	}
 
-	/* save so we can run later */
-	transaction->priv->cached_filters = pk_filter_enums_from_text (filter);
-	transaction->priv->status = PK_STATUS_ENUM_WAIT;
-	pk_transaction_set_role (transaction, PK_ROLE_ENUM_GET_UPDATES);
-
 	/* try to commit this */
 	ret = pk_transaction_commit (transaction);
 	if (!ret) {
@@ -2721,7 +2774,9 @@ pk_transaction_update_packages (PkTransaction *transaction, gchar **package_ids,
 	g_return_if_fail (PK_IS_TRANSACTION (transaction));
 	g_return_if_fail (transaction->priv->tid != NULL);
 
-	pk_debug ("UpdatePackages method called: %s", package_ids[0]);
+	package_ids_temp = pk_package_ids_to_text (package_ids, ", ");
+	pk_debug ("UpdatePackages method called: %s", package_ids_temp);
+	g_free (package_ids_temp);
 
 	/* not implemented yet */
 	if (transaction->priv->backend->desc->update_packages == NULL) {
@@ -3029,6 +3084,7 @@ pk_transaction_init (PkTransaction *transaction)
 	transaction->priv->backend = pk_backend_new ();
 	transaction->priv->security = pk_security_new ();
 	transaction->priv->cache = pk_cache_new ();
+	transaction->priv->update_detail_cache = pk_update_detail_cache_new ();
 	transaction->priv->notify = pk_notify_new ();
 	transaction->priv->inhibit = pk_inhibit_new ();
 	transaction->priv->package_list = pk_package_list_new ();
@@ -3071,6 +3127,7 @@ pk_transaction_finalize (GObject *object)
 	/* remove any inhibit, it's okay to call this function when it's not needed */
 	pk_inhibit_remove (transaction->priv->inhibit, transaction);
 	g_object_unref (transaction->priv->cache);
+	g_object_unref (transaction->priv->update_detail_cache);
 	g_object_unref (transaction->priv->inhibit);
 	g_object_unref (transaction->priv->backend);
 	g_object_unref (transaction->priv->libgbus);
commit 8ca5ca9b58da43a68eab0b918448e8a7eb47e817
Author: Richard Hughes <richard at hughsie.com>
Date:   Tue Jun 24 16:57:48 2008 +0100

    add functionality to pass around some PkDetails objects

diff --git a/libpackagekit/Makefile.am b/libpackagekit/Makefile.am
index 1c11a39..f63c9b5 100644
--- a/libpackagekit/Makefile.am
+++ b/libpackagekit/Makefile.am
@@ -41,6 +41,7 @@ libpackagekit_include_HEADERS =					\
 	pk-package-item.h					\
 	pk-package-list.h					\
 	pk-update-detail.h					\
+	pk-details.h						\
 	pk-enum.h						\
 	pk-common.h						\
 	pk-client.h						\
@@ -68,6 +69,8 @@ libpackagekit_la_SOURCES =					\
 	pk-package-list.h					\
 	pk-update-detail.c					\
 	pk-update-detail.h					\
+	pk-details.c						\
+	pk-details.h						\
 	pk-enum.h						\
 	pk-enum.c						\
 	pk-common.c						\
diff --git a/libpackagekit/pk-details.c b/libpackagekit/pk-details.c
new file mode 100644
index 0000000..50cb742
--- /dev/null
+++ b/libpackagekit/pk-details.c
@@ -0,0 +1,146 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2007-2008 Richard Hughes <richard at hughsie.com>
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+/**
+ * SECTION:pk-details
+ * @short_description: Functionality to create a details struct
+ */
+
+#include "config.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/types.h>
+#include <glib/gi18n.h>
+
+#include <pk-enum.h>
+#include "pk-debug.h"
+#include "pk-common.h"
+#include "pk-details.h"
+
+/**
+ * pk_details_new:
+ *
+ * Creates a new #PkDetails object with default values
+ *
+ * Return value: a new #PkDetails object
+ **/
+PkDetails *
+pk_details_new (void)
+{
+	PkDetails *detail;
+	detail = g_new0 (PkDetails, 1);
+	detail->package_id = NULL;
+	detail->license = NULL;
+	detail->group = 0;
+	detail->description = NULL;
+	detail->url = NULL;
+	detail->size = 0;
+
+	return detail;
+}
+
+/**
+ * pk_details_new_from_data:
+ *
+ * Creates a new #PkDetails object with values.
+ *
+ * Return value: a new #PkDetails object
+ **/
+PkDetails *
+pk_details_new_from_data (const gchar *package_id, const gchar *license, PkGroupEnum group,
+			  const gchar *description, const gchar *url, guint64 size)
+{
+	PkDetails *detail = NULL;
+
+	/* create new object */
+	detail = pk_details_new ();
+	detail->package_id = g_strdup (package_id);
+	detail->license = g_strdup (license);
+	detail->group = group;
+	detail->description = g_strdup (description);
+	detail->url = g_strdup (url);
+	detail->size = size;
+
+	return detail;
+}
+
+/**
+ * pk_details_free:
+ * @detail: the #PkDetails object
+ *
+ * Return value: %TRUE if the #PkDetails object was freed.
+ **/
+gboolean
+pk_details_free (PkDetails *detail)
+{
+	if (detail == NULL) {
+		return FALSE;
+	}
+	g_free (detail->package_id);
+	g_free (detail->license);
+	g_free (detail->description);
+	g_free (detail->url);
+	g_free (detail);
+	return TRUE;
+}
+
+/***************************************************************************
+ ***                          MAKE CHECK TESTS                           ***
+ ***************************************************************************/
+#ifdef PK_BUILD_TESTS
+#include <libselftest.h>
+
+void
+libst_details (LibSelfTest *test)
+{
+	gboolean ret;
+	PkDetails *detail;
+
+	if (libst_start (test, "PkDetails", CLASS_AUTO) == FALSE) {
+		return;
+	}
+
+	/************************************************************/
+	libst_title (test, "get an details object");
+	detail = pk_details_new ();
+	if (detail != NULL) {
+		libst_success (test, NULL);
+	} else {
+		libst_failed (test, NULL);
+	}
+
+	/************************************************************/
+	libst_title (test, "test details");
+	ret = pk_details_free (detail);
+	if (ret) {
+		libst_success (test, NULL);
+	} else {
+		libst_failed (test, NULL);
+	}
+
+	pk_details_free (detail);
+
+	libst_end (test);
+}
+#endif
+
diff --git a/libpackagekit/pk-details.h b/libpackagekit/pk-details.h
new file mode 100644
index 0000000..b485a37
--- /dev/null
+++ b/libpackagekit/pk-details.h
@@ -0,0 +1,56 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2007-2008 Richard Hughes <richard at hughsie.com>
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __PK_DETAILS_H
+#define __PK_DETAILS_H
+
+#include <glib-object.h>
+#include <pk-enum.h>
+
+G_BEGIN_DECLS
+
+/**
+ * PkDetails:
+ *
+ * Cached object to represent details about the package.
+ **/
+typedef struct
+{
+	gchar				*package_id;
+	gchar				*license;
+	PkGroupEnum			 group;
+	gchar				*description;
+	gchar				*url;
+	guint64				 size;
+} PkDetails;
+
+PkDetails	*pk_details_new				(void);
+PkDetails	*pk_details_new_from_data		(const gchar	*package_id,
+							 const gchar	*license,
+							 PkGroupEnum	 group,
+							 const gchar	*description,
+							 const gchar	*url,
+							 guint64	 size);
+gboolean	 pk_details_free			(PkDetails	*detail);
+
+G_END_DECLS
+
+#endif /* __PK_DETAILS_H */
diff --git a/libpackagekit/pk-self-test.c b/libpackagekit/pk-self-test.c
index 81b9b5e..caa5284 100644
--- a/libpackagekit/pk-self-test.c
+++ b/libpackagekit/pk-self-test.c
@@ -40,6 +40,7 @@ void libst_control (LibSelfTest *test);
 void libst_task_list (LibSelfTest *test);
 void libst_catalog (LibSelfTest *test);
 void libst_update_detail (LibSelfTest *test);
+void libst_details (LibSelfTest *test);
 
 int
 main (int argc, char **argv)
@@ -63,6 +64,7 @@ main (int argc, char **argv)
 	libst_control (&test);
 	libst_task_list (&test);
 	libst_update_detail (&test);
+	libst_details (&test);
 
 	return (libst_finish (&test));
 }
commit a4d6cabdc91b1dc54104ad7e21e55dc6e9b185cb
Author: Richard Hughes <richard at hughsie.com>
Date:   Tue Jun 24 16:56:42 2008 +0100

    trivial: comment fix

diff --git a/libpackagekit/pk-update-detail.c b/libpackagekit/pk-update-detail.c
index 077430e..d344f38 100644
--- a/libpackagekit/pk-update-detail.c
+++ b/libpackagekit/pk-update-detail.c
@@ -20,10 +20,8 @@
  */
 
 /**
- * SECTION:pk-package-id
- * @short_description: Functionality to modify a PackageID
- *
- * PackageId's are difficult to read and create.
+ * SECTION:pk-update-detail
+ * @short_description: Functionality to create an update detail struct
  */
 
 #include "config.h"
@@ -86,6 +84,7 @@ pk_update_detail_new_from_data (const gchar *package_id, const gchar *updates, c
 	detail->cve_url = g_strdup (cve_url);
 	detail->restart = restart;
 	detail->update_text = g_strdup (update_text);
+
 	return detail;
 }
 
commit 6784da925c899e64defba3113a7df02717313854
Author: Richard Hughes <richard at hughsie.com>
Date:   Tue Jun 24 15:43:28 2008 +0100

    add functionality to create PkUpdateDetail structures

diff --git a/libpackagekit/Makefile.am b/libpackagekit/Makefile.am
index fa5bb6a..1c11a39 100644
--- a/libpackagekit/Makefile.am
+++ b/libpackagekit/Makefile.am
@@ -40,6 +40,7 @@ libpackagekit_include_HEADERS =					\
 	pk-package-ids.h					\
 	pk-package-item.h					\
 	pk-package-list.h					\
+	pk-update-detail.h					\
 	pk-enum.h						\
 	pk-common.h						\
 	pk-client.h						\
@@ -65,6 +66,8 @@ libpackagekit_la_SOURCES =					\
 	pk-package-item.h					\
 	pk-package-list.c					\
 	pk-package-list.h					\
+	pk-update-detail.c					\
+	pk-update-detail.h					\
 	pk-enum.h						\
 	pk-enum.c						\
 	pk-common.c						\
diff --git a/libpackagekit/pk-self-test.c b/libpackagekit/pk-self-test.c
index b03dfd2..81b9b5e 100644
--- a/libpackagekit/pk-self-test.c
+++ b/libpackagekit/pk-self-test.c
@@ -1,6 +1,6 @@
 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
  *
- * Copyright (C) 2007 Richard Hughes <richard at hughsie.com>
+ * Copyright (C) 2007-2008 Richard Hughes <richard at hughsie.com>
  *
  * Licensed under the GNU General Public License Version 2
  *
@@ -39,6 +39,7 @@ void libst_client (LibSelfTest *test);
 void libst_control (LibSelfTest *test);
 void libst_task_list (LibSelfTest *test);
 void libst_catalog (LibSelfTest *test);
+void libst_update_detail (LibSelfTest *test);
 
 int
 main (int argc, char **argv)
@@ -61,6 +62,7 @@ main (int argc, char **argv)
 	libst_catalog (&test);
 	libst_control (&test);
 	libst_task_list (&test);
+	libst_update_detail (&test);
 
 	return (libst_finish (&test));
 }
diff --git a/libpackagekit/pk-update-detail.c b/libpackagekit/pk-update-detail.c
new file mode 100644
index 0000000..077430e
--- /dev/null
+++ b/libpackagekit/pk-update-detail.c
@@ -0,0 +1,157 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2007-2008 Richard Hughes <richard at hughsie.com>
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+/**
+ * SECTION:pk-package-id
+ * @short_description: Functionality to modify a PackageID
+ *
+ * PackageId's are difficult to read and create.
+ */
+
+#include "config.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/types.h>
+#include <glib/gi18n.h>
+
+#include <pk-enum.h>
+#include "pk-debug.h"
+#include "pk-common.h"
+#include "pk-update-detail.h"
+
+/**
+ * pk_update_detail_new:
+ *
+ * Creates a new #PkUpdateDetail object with default values
+ *
+ * Return value: a new #PkUpdateDetail object
+ **/
+PkUpdateDetail *
+pk_update_detail_new (void)
+{
+	PkUpdateDetail *detail;
+	detail = g_new0 (PkUpdateDetail, 1);
+	detail->updates = NULL;
+	detail->obsoletes = NULL;
+	detail->vendor_url = NULL;
+	detail->bugzilla_url = NULL;
+	detail->cve_url = NULL;
+	detail->restart = 0;
+	detail->update_text = NULL;
+
+	return detail;
+}
+
+/**
+ * pk_update_detail_new_from_data:
+ *
+ * Creates a new #PkUpdateDetail object with values.
+ *
+ * Return value: a new #PkUpdateDetail object
+ **/
+PkUpdateDetail *
+pk_update_detail_new_from_data (const gchar *package_id, const gchar *updates, const gchar *obsoletes,
+				const gchar *vendor_url, const gchar *bugzilla_url, const gchar *cve_url,
+				PkRestartEnum restart, const gchar *update_text)
+{
+	PkUpdateDetail *detail = NULL;
+
+	/* create new object */
+	detail = pk_update_detail_new ();
+	detail->package_id = g_strdup (package_id);
+	detail->updates = g_strdup (updates);
+	detail->obsoletes = g_strdup (obsoletes);
+	detail->vendor_url = g_strdup (vendor_url);
+	detail->bugzilla_url = g_strdup (bugzilla_url);
+	detail->cve_url = g_strdup (cve_url);
+	detail->restart = restart;
+	detail->update_text = g_strdup (update_text);
+	return detail;
+}
+
+/**
+ * pk_update_detail_free:
+ * @detail: the #PkUpdateDetail object
+ *
+ * Return value: %TRUE if the #PkUpdateDetail object was freed.
+ **/
+gboolean
+pk_update_detail_free (PkUpdateDetail *detail)
+{
+	if (detail == NULL) {
+		return FALSE;
+	}
+	g_free (detail->updates);
+	g_free (detail->obsoletes);
+	g_free (detail->vendor_url);
+	g_free (detail->bugzilla_url);
+	g_free (detail->cve_url);
+	g_free (detail->update_text);
+	g_free (detail);
+	return TRUE;
+}
+
+/***************************************************************************
+ ***                          MAKE CHECK TESTS                           ***
+ ***************************************************************************/
+#ifdef PK_BUILD_TESTS
+#include <libselftest.h>
+
+void
+libst_update_detail (LibSelfTest *test)
+{
+	gboolean ret;
+	PkUpdateDetail *detail;
+
+	if (libst_start (test, "PkUpdateDetail", CLASS_AUTO) == FALSE) {
+		return;
+	}
+
+	/************************************************************
+	 ****************          IDENT           ******************
+	 ************************************************************/
+
+	/************************************************************/
+	libst_title (test, "get an detail object");
+	detail = pk_update_detail_new ();
+	if (detail != NULL) {
+		libst_success (test, NULL);
+	} else {
+		libst_failed (test, NULL);
+	}
+
+	/************************************************************/
+	libst_title (test, "test detail");
+	ret = pk_update_detail_free (detail);
+	if (ret) {
+		libst_success (test, NULL);
+	} else {
+		libst_failed (test, NULL);
+	}
+
+	pk_update_detail_free (detail);
+
+	libst_end (test);
+}
+#endif
+
diff --git a/libpackagekit/pk-update-detail.h b/libpackagekit/pk-update-detail.h
new file mode 100644
index 0000000..39c4d19
--- /dev/null
+++ b/libpackagekit/pk-update-detail.h
@@ -0,0 +1,60 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2007-2008 Richard Hughes <richard at hughsie.com>
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __PK_UPDATE_DETAIL_H
+#define __PK_UPDATE_DETAIL_H
+
+#include <glib-object.h>
+#include <pk-enum.h>
+
+G_BEGIN_DECLS
+
+/**
+ * PkUpdateDetail:
+ *
+ * Cached object to represent details about the update.
+ **/
+typedef struct
+{
+	gchar				*package_id;
+	gchar				*updates;
+	gchar				*obsoletes;
+	gchar				*vendor_url;
+	gchar				*bugzilla_url;
+	gchar				*cve_url;
+	PkRestartEnum			 restart;
+	gchar				*update_text;
+} PkUpdateDetail;
+
+PkUpdateDetail	*pk_update_detail_new			(void);
+PkUpdateDetail	*pk_update_detail_new_from_data		(const gchar	*package_id,
+							 const gchar	*updates,
+							 const gchar	*obsoletes,
+							 const gchar	*vendor_url,
+							 const gchar	*bugzilla_url,
+							 const gchar	*cve_url,
+							 PkRestartEnum	 restart,
+							 const gchar	*update_text);
+gboolean	 pk_update_detail_free			(PkUpdateDetail	*detail);
+
+G_END_DECLS
+
+#endif /* __PK_UPDATE_DETAIL_H */
commit e1af76753fab255bb2ec83c7759750a248ae566f
Author: Richard Hughes <richard at hughsie.com>
Date:   Tue Jun 24 14:27:59 2008 +0100

    trivial: print out more of the argv for debugging

diff --git a/src/pk-spawn.c b/src/pk-spawn.c
index 7c23af7..7d45eaa 100644
--- a/src/pk-spawn.c
+++ b/src/pk-spawn.c
@@ -268,11 +268,20 @@ gboolean
 pk_spawn_argv (PkSpawn *spawn, gchar **argv, gchar **envp)
 {
 	gboolean ret;
+	guint i;
+	guint len;
 
 	g_return_val_if_fail (PK_IS_SPAWN (spawn), FALSE);
 	g_return_val_if_fail (argv != NULL, FALSE);
 
-	pk_debug ("argv[0] '%s'", argv[0]);
+	len = g_strv_length (argv);
+	if (len > 5) {
+		pk_debug ("limiting debugging to 5 entries");
+		len = 5;
+	}
+	for (i=0; i<len; i++) {
+		pk_debug ("argv[%i] '%s'", i, argv[i]);
+	}
 	spawn->priv->finished = FALSE;
 
 	/* create spawned object for tracking */
commit c00f06fbab1bad20a103ccef805b27efa53c7e2b
Author: Richard Hughes <richard at hughsie.com>
Date:   Tue Jun 24 13:49:57 2008 +0100

    yum: support passing more than one package_id to GetUpdateDetail

diff --git a/backends/yum/helpers/get-update-detail.py b/backends/yum/helpers/get-update-detail.py
index 8fbc484..ac9424e 100755
--- a/backends/yum/helpers/get-update-detail.py
+++ b/backends/yum/helpers/get-update-detail.py
@@ -12,8 +12,8 @@
 import sys
 
 from yumBackend import PackageKitYumBackend
-package=sys.argv[1]
-backend = PackageKitYumBackend(sys.argv[2:])
-backend.get_update_detail(package.split('|'))
+packages=sys.argv[1:]
+backend = PackageKitYumBackend(sys.argv[1:])
+backend.get_update_detail(packages)
 backend.unLock()
 sys.exit(0)
commit 47599b78c816f9628300e5d442bd2d61541f15b2
Author: Richard Hughes <richard at hughsie.com>
Date:   Tue Jun 24 13:49:14 2008 +0100

    dummy: properly emulate package_ids for get_update_detail

diff --git a/backends/dummy/pk-backend-dummy.c b/backends/dummy/pk-backend-dummy.c
index ffccab5..219a923 100644
--- a/backends/dummy/pk-backend-dummy.c
+++ b/backends/dummy/pk-backend-dummy.c
@@ -29,7 +29,6 @@
 /* static bodges */
 static guint _progress_percentage = 0;
 static gulong _signal_timeout = 0;
-static const gchar *_package_id;
 static gchar **_package_ids;
 static guint _package_current = 0;
 static gboolean _has_service_pack = FALSE;
@@ -177,36 +176,43 @@ backend_get_requires (PkBackend *backend, PkFilterEnum filters, gchar **package_
 static gboolean
 backend_get_update_detail_timeout (gpointer data)
 {
+	guint i;
+	guint len;
+	const gchar *package_id;
 	PkBackend *backend = (PkBackend *) data;
+
 	/* each one has a different detail for testing */
-	if (pk_strequal (_package_id, "powertop;1.8-1.fc8;i386;fedora")) {
-		pk_backend_update_detail (backend, "powertop;1.8-1.fc8;i386;available",
-					  "powertop;1.7-1.fc8;i386;installed", "",
-					  "http://www.distro-update.org/page?moo;Bugfix release for powertop",
-					  "http://bgzilla.fd.org/result.php?#12344;Freedesktop Bugzilla #12344",
-					  "", PK_RESTART_ENUM_NONE, "Update to newest upstream source");
-	} else if (pk_strequal (_package_id, "kernel;2.6.23-0.115.rc3.git1.fc8;i386;installed")) {
-		pk_backend_update_detail (backend, "kernel;2.6.23-0.115.rc3.git1.fc8;i386;available",
-					  "kernel;2.6.22-0.104.rc3.git6.fc8;i386;installed^"
-					  "kernel;2.6.22-0.105.rc3.git7.fc8;i386;installed", "",
-					  "http://www.distro-update.org/page?moo;Bugfix release for kernel",
-					  "http://bgzilla.fd.org/result.php?#12344;Freedesktop Bugzilla #12344;"
-					  "http://bgzilla.gnome.org/result.php?#9876;GNOME Bugzilla #9876",
-					  "http://nvd.nist.gov/nvd.cfm?cvename=CVE-2007-3381;CVE-2007-3381",
-					  PK_RESTART_ENUM_SYSTEM, "Update to newest version");
-	} else if (pk_strequal (_package_id, "gtkhtml2;2.19.1-4.fc8;i386;fedora")) {
-		pk_backend_update_detail (backend, "gtkhtml2;2.19.1-4.fc8;i386;fedora",
-					  "gtkhtml2;2.18.1-22.fc8;i386;installed", "",
-					  "http://www.distro-update.org/page?moo;Bugfix release for gtkhtml",
-					  "http://bgzilla.gnome.org/result.php?#9876;GNOME Bugzilla #9876",
-					  NULL,
-					  PK_RESTART_ENUM_SESSION,
-					  "Update to latest whizz bang version\n"
-					  "* support this new thing\n"
-					  "* something else\n"
-					  "- and that new thing");
-	} else {
-		pk_backend_message (backend, PK_MESSAGE_ENUM_DAEMON, "Got unexpected package_id '%s'", _package_id);
+	len = g_strv_length (_package_ids);
+	for (i=0; i<len; i++) {
+		package_id = _package_ids[i];
+		if (pk_strequal (package_id, "powertop;1.8-1.fc8;i386;fedora")) {
+			pk_backend_update_detail (backend, package_id,
+						  "powertop;1.7-1.fc8;i386;installed", "",
+						  "http://www.distro-update.org/page?moo;Bugfix release for powertop",
+						  "http://bgzilla.fd.org/result.php?#12344;Freedesktop Bugzilla #12344",
+						  "", PK_RESTART_ENUM_NONE, "Update to newest upstream source");
+		}
+		if (pk_strequal (package_id, "kernel;2.6.23-0.115.rc3.git1.fc8;i386;installed")) {
+			pk_backend_update_detail (backend, package_id,
+						  "kernel;2.6.22-0.104.rc3.git6.fc8;i386;installed^"
+						  "kernel;2.6.22-0.105.rc3.git7.fc8;i386;installed", "",
+						  "http://www.distro-update.org/page?moo;Bugfix release for kernel",
+						  "http://bgzilla.fd.org/result.php?#12344;Freedesktop Bugzilla #12344;"
+						  "http://bgzilla.gnome.org/result.php?#9876;GNOME Bugzilla #9876",
+						  "http://nvd.nist.gov/nvd.cfm?cvename=CVE-2007-3381;CVE-2007-3381",
+						  PK_RESTART_ENUM_SYSTEM, "Update to newest version");
+		}
+		if (pk_strequal (package_id, "gtkhtml2;2.19.1-4.fc8;i386;fedora")) {
+			pk_backend_update_detail (backend, package_id,
+						  "gtkhtml2;2.18.1-22.fc8;i386;installed", "",
+						  "http://www.distro-update.org/page?moo;Bugfix release for gtkhtml",
+						  "http://bgzilla.gnome.org/result.php?#9876;GNOME Bugzilla #9876",
+						  NULL, PK_RESTART_ENUM_SESSION,
+						  "Update to latest whizz bang version\n"
+						  "* support this new thing\n"
+						  "* something else\n"
+						  "- and that new thing");
+		}
 	}
 	pk_backend_finished (backend);
 	_signal_timeout = 0;
@@ -220,7 +226,7 @@ static void
 backend_get_update_detail (PkBackend *backend, gchar **package_ids)
 {
 	pk_backend_set_status (backend, PK_STATUS_ENUM_QUERY);
-	_package_id = package_ids[0];
+	_package_ids = package_ids;
 	_signal_timeout = g_timeout_add (500, backend_get_update_detail_timeout, backend);
 }
 


More information about the PackageKit-commit mailing list