[PackageKit] Backport some fixes from upstream
Richard Hughes
rhughes at fedoraproject.org
Mon Sep 23 15:48:07 UTC 2013
commit 9c435a4caf54063965f4ed24b702a8b7c8c761bd
Author: Richard Hughes <richard at hughsie.com>
Date: Mon Sep 23 16:47:53 2013 +0100
Backport some fixes from upstream
PackageKit-git-fixes.patch | 990 ++++++++++++++++++++++++++++++++++++++++++++
PackageKit.spec | 10 +-
2 files changed, 997 insertions(+), 3 deletions(-)
---
diff --git a/PackageKit-git-fixes.patch b/PackageKit-git-fixes.patch
new file mode 100644
index 0000000..a1fc27c
--- /dev/null
+++ b/PackageKit-git-fixes.patch
@@ -0,0 +1,990 @@
+diff --git a/lib/packagekit-glib2/pk-common.c b/lib/packagekit-glib2/pk-common.c
+index 12f18cd..59ffc19 100644
+--- a/lib/packagekit-glib2/pk-common.c
++++ b/lib/packagekit-glib2/pk-common.c
+@@ -131,6 +131,50 @@ out:
+ }
+
+ /**
++ * pk_iso8601_to_datetime: (skip)
++ * @iso_date: The ISO8601 date to convert
++ *
++ * Return value: If valid then a new %GDateTime, else NULL
++ *
++ * Since: 0.8.11
++ **/
++GDateTime *
++pk_iso8601_to_datetime (const gchar *iso_date)
++{
++ gboolean ret = FALSE;
++ guint retval;
++ guint d = 0;
++ guint m = 0;
++ guint y = 0;
++ GTimeVal time_val;
++ GDateTime *date = NULL;
++
++ if (iso_date == NULL || iso_date[0] == '\0')
++ goto out;
++
++ /* try to parse complete ISO8601 date */
++ if (g_strstr_len (iso_date, -1, " ") != NULL)
++ ret = g_time_val_from_iso8601 (iso_date, &time_val);
++ if (ret && time_val.tv_sec != 0) {
++ g_debug ("Parsed %s %i", iso_date, ret);
++ date = g_date_time_new_from_timeval_utc (&time_val);
++ goto out;
++ }
++
++ /* g_time_val_from_iso8601() blows goats and won't
++ * accept a valid ISO8601 formatted date without a
++ * time value - try and parse this case */
++ retval = sscanf (iso_date, "%u-%u-%u", &y, &m, &d);
++ if (retval != 3)
++ goto out;
++
++ /* create valid object */
++ date = g_date_time_new_utc (y, m, d, 0, 0, 0);
++out:
++ return date;
++}
++
++/**
+ * pk_ptr_array_to_strv:
+ * @array: the GPtrArray of strings
+ *
+diff --git a/lib/packagekit-glib2/pk-common.h b/lib/packagekit-glib2/pk-common.h
+index f3d4315..379fd73 100644
+--- a/lib/packagekit-glib2/pk-common.h
++++ b/lib/packagekit-glib2/pk-common.h
+@@ -88,6 +88,7 @@ gchar *pk_iso8601_present (void)
+ G_GNUC_WARN_UNUSED_RESULT;
+ gchar *pk_iso8601_from_date (const GDate *date);
+ GDate *pk_iso8601_to_date (const gchar *iso_date);
++GDateTime *pk_iso8601_to_datetime (const gchar *iso_date);
+ gchar *pk_get_distro_id (void);
+
+ G_END_DECLS
+diff --git a/lib/packagekit-glib2/pk-control.c b/lib/packagekit-glib2/pk-control.c
+index 9477e65..e319bea 100644
+--- a/lib/packagekit-glib2/pk-control.c
++++ b/lib/packagekit-glib2/pk-control.c
+@@ -2447,6 +2447,24 @@ pk_control_name_appeared_cb (GDBusConnection *connection,
+ }
+
+ /**
++ * pk_control_proxy_destroy:
++ **/
++static void
++pk_control_proxy_destroy (PkControl *control)
++{
++ if (control->priv->proxy == NULL)
++ return;
++ g_signal_handlers_disconnect_by_func (control->priv->proxy,
++ G_CALLBACK (pk_control_properties_changed_cb),
++ control);
++ g_signal_handlers_disconnect_by_func (control->priv->proxy,
++ G_CALLBACK (pk_control_signal_cb),
++ control);
++ g_object_unref (control->priv->proxy);
++ control->priv->proxy = NULL;
++}
++
++/**
+ * pk_control_name_vanished_cb:
+ **/
+ static void
+@@ -2458,6 +2476,11 @@ pk_control_name_vanished_cb (GDBusConnection *connection,
+ control->priv->connected = FALSE;
+ g_debug ("notify::connected");
+ g_object_notify (G_OBJECT(control), "connected");
++
++ /* destroy the proxy, as even though it's "well known" we get a
++ * GDBus.Error:org.freedesktop.DBus.Error.ServiceUnknown if we try to
++ * use this after the server has restarted */
++ pk_control_proxy_destroy (control);
+ }
+
+ /**
+@@ -2497,6 +2520,9 @@ pk_control_finalize (GObject *object)
+ g_cancellable_cancel (priv->cancellable);
+ g_bus_unwatch_name (priv->watch_id);
+
++ /* disconnect proxy and destroy it */
++ pk_control_proxy_destroy (control);
++
+ /* remove pending sources */
+ if (priv->transaction_list_changed_id != 0)
+ g_source_remove (priv->transaction_list_changed_id);
+@@ -2506,15 +2532,6 @@ pk_control_finalize (GObject *object)
+ g_source_remove (priv->updates_changed_id);
+ if (priv->repo_list_changed_id != 0)
+ g_source_remove (priv->repo_list_changed_id);
+- if (priv->proxy != NULL) {
+- g_signal_handlers_disconnect_by_func (priv->proxy,
+- G_CALLBACK (pk_control_properties_changed_cb),
+- control);
+- g_signal_handlers_disconnect_by_func (priv->proxy,
+- G_CALLBACK (pk_control_signal_cb),
+- control);
+- g_object_unref (priv->proxy);
+- }
+
+ g_free (priv->backend_name);
+ g_free (priv->backend_description);
+diff --git a/lib/packagekit-glib2/pk-package.c b/lib/packagekit-glib2/pk-package.c
+index 0c9e86d..4f7deb1 100644
+--- a/lib/packagekit-glib2/pk-package.c
++++ b/lib/packagekit-glib2/pk-package.c
+@@ -196,6 +196,46 @@ out:
+ }
+
+ /**
++ * pk_package_parse:
++ * @package: a valid #PkPackage instance
++ * @data: the data describing the package
++ * @error: a %GError to put the error code and message in, or %NULL
++ *
++ * Parses the data to populate the #PkPackage.
++ *
++ * Return value: %TRUE if the data was parsed correcty
++ *
++ * Since: 0.8.11
++ **/
++gboolean
++pk_package_parse (PkPackage *package, const gchar *data, GError **error)
++{
++ gboolean ret = TRUE;
++ gchar **sections;
++
++ g_return_val_if_fail (PK_IS_PACKAGE (package), FALSE);
++ g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
++
++ /* split */
++ sections = g_strsplit (data, "\t", -1);
++ if (g_strv_length (sections) != 3) {
++ ret = FALSE;
++ g_set_error_literal (error, 1, 0, "data invalid");
++ }
++
++ /* parse object */
++ package->priv->info = pk_info_enum_from_string (sections[0]);
++ ret = pk_package_set_id (package, sections[1], error);
++ if (!ret)
++ goto out;
++ g_free (package->priv->summary);
++ package->priv->summary = g_strdup (sections[2]);
++out:
++ g_strfreev (sections);
++ return ret;
++}
++
++/**
+ * pk_package_get_info:
+ * @package: a valid #PkPackage instance
+ *
+diff --git a/lib/packagekit-glib2/pk-package.h b/lib/packagekit-glib2/pk-package.h
+index 60d0a10..8ca803b 100644
+--- a/lib/packagekit-glib2/pk-package.h
++++ b/lib/packagekit-glib2/pk-package.h
+@@ -72,6 +72,9 @@ void pk_package_test (gpointer user_data);
+ gboolean pk_package_set_id (PkPackage *package,
+ const gchar *package_id,
+ GError **error);
++gboolean pk_package_parse (PkPackage *package,
++ const gchar *data,
++ GError **error);
+ void pk_package_print (PkPackage *package);
+ gboolean pk_package_equal (PkPackage *package1,
+ PkPackage *package2);
+diff --git a/lib/packagekit-glib2/pk-transaction-past.c b/lib/packagekit-glib2/pk-transaction-past.c
+index 13c2cb4..fa91b1d 100644
+--- a/lib/packagekit-glib2/pk-transaction-past.c
++++ b/lib/packagekit-glib2/pk-transaction-past.c
+@@ -33,6 +33,7 @@
+ #include <glib-object.h>
+
+ #include <packagekit-glib2/pk-transaction-past.h>
++#include <packagekit-glib2/pk-common.h>
+ #include <packagekit-glib2/pk-enum.h>
+
+ static void pk_transaction_past_finalize (GObject *object);
+@@ -72,6 +73,187 @@ enum {
+ G_DEFINE_TYPE (PkTransactionPast, pk_transaction_past, PK_TYPE_SOURCE)
+
+ /**
++ * pk_transaction_past_get_id:
++ * @past: a valid #PkTransactionPast instance
++ *
++ * Gets the past transaction ID value;
++ *
++ * Return value: The transaction data
++ *
++ * Since: 0.8.11
++ **/
++const gchar *
++pk_transaction_past_get_id (PkTransactionPast *past)
++{
++ g_return_val_if_fail (PK_IS_TRANSACTION_PAST (past), NULL);
++ return past->priv->tid;
++}
++
++/**
++ * pk_transaction_past_get_timespec:
++ * @past: a valid #PkTransactionPast instance
++ *
++ * Gets the past transaction timespec value;
++ *
++ * Return value: The transaction data
++ *
++ * Since: 0.8.11
++ **/
++const gchar *
++pk_transaction_past_get_timespec (PkTransactionPast *past)
++{
++ g_return_val_if_fail (PK_IS_TRANSACTION_PAST (past), NULL);
++ return past->priv->timespec;
++}
++
++/**
++ * pk_transaction_past_get_datetime:
++ * @past: a valid #PkTransactionPast instance
++ *
++ * Gets the past transaction date & time value;
++ *
++ * Return value: The transaction data, or %NULL if it's not available
++ *
++ * Since: 0.8.11
++ **/
++GDateTime *
++pk_transaction_past_get_datetime (PkTransactionPast *past)
++{
++ g_return_val_if_fail (PK_IS_TRANSACTION_PAST (past), NULL);
++ if (past->priv->timespec == NULL)
++ return NULL;
++ return pk_iso8601_to_datetime (past->priv->timespec);
++}
++
++/**
++ * pk_transaction_past_get_timestamp:
++ * @past: a valid #PkTransactionPast instance
++ *
++ * Gets the past transaction timestamp
++ *
++ * Return value: The transaction data, or 0 if it's not available
++ *
++ * Since: 0.8.11
++ **/
++gint64
++pk_transaction_past_get_timestamp (PkTransactionPast *past)
++{
++ GDateTime *datetime;
++ gint64 timestamp;
++
++ g_return_val_if_fail (PK_IS_TRANSACTION_PAST (past), 0);
++
++ datetime = pk_transaction_past_get_datetime (past);
++ if (datetime == NULL)
++ return 0;
++ timestamp = g_date_time_to_unix (datetime);
++ g_date_time_unref (datetime);
++ return timestamp;
++}
++
++/**
++ * pk_transaction_past_get_succeeded:
++ * @past: a valid #PkTransactionPast instance
++ *
++ * Gets the past transaction succeeded value;
++ *
++ * Return value: The transaction data
++ *
++ * Since: 0.8.11
++ **/
++gboolean
++pk_transaction_past_get_succeeded (PkTransactionPast *past)
++{
++ g_return_val_if_fail (PK_IS_TRANSACTION_PAST (past), FALSE);
++ return past->priv->succeeded;
++}
++
++/**
++ * pk_transaction_past_get_role:
++ * @past: a valid #PkTransactionPast instance
++ *
++ * Gets the past transaction role;
++ *
++ * Return value: The transaction data
++ *
++ * Since: 0.8.11
++ **/
++PkRoleEnum
++pk_transaction_past_get_role (PkTransactionPast *past)
++{
++ g_return_val_if_fail (PK_IS_TRANSACTION_PAST (past), PK_ROLE_ENUM_UNKNOWN);
++ return past->priv->role;
++}
++
++/**
++ * pk_transaction_past_get_duration:
++ * @past: a valid #PkTransactionPast instance
++ *
++ * Gets the past transaction duration;
++ *
++ * Return value: The transaction data
++ *
++ * Since: 0.8.11
++ **/
++guint
++pk_transaction_past_get_duration (PkTransactionPast *past)
++{
++ g_return_val_if_fail (PK_IS_TRANSACTION_PAST (past), 0);
++ return past->priv->duration;
++}
++
++/**
++ * pk_transaction_past_get_data:
++ * @past: a valid #PkTransactionPast instance
++ *
++ * Gets the past transaction data;
++ *
++ * Return value: The transaction data
++ *
++ * Since: 0.8.11
++ **/
++const gchar *
++pk_transaction_past_get_data (PkTransactionPast *past)
++{
++ g_return_val_if_fail (PK_IS_TRANSACTION_PAST (past), NULL);
++ return past->priv->data;
++}
++
++/**
++ * pk_transaction_past_get_uid:
++ * @past: a valid #PkTransactionPast instance
++ *
++ * Gets the past transaction uid;
++ *
++ * Return value: The transaction data
++ *
++ * Since: 0.8.11
++ **/
++guint
++pk_transaction_past_get_uid (PkTransactionPast *past)
++{
++ g_return_val_if_fail (PK_IS_TRANSACTION_PAST (past), 0);
++ return past->priv->uid;
++}
++
++/**
++ * pk_transaction_past_get_cmdline:
++ * @past: a valid #PkTransactionPast instance
++ *
++ * Gets the past transaction cmdline value;
++ *
++ * Return value: The transaction data
++ *
++ * Since: 0.8.11
++ **/
++const gchar *
++pk_transaction_past_get_cmdline (PkTransactionPast *past)
++{
++ g_return_val_if_fail (PK_IS_TRANSACTION_PAST (past), NULL);
++ return past->priv->cmdline;
++}
++
++/**
+ * pk_transaction_past_get_property:
+ **/
+ static void
+diff --git a/lib/packagekit-glib2/pk-transaction-past.h b/lib/packagekit-glib2/pk-transaction-past.h
+index fcec8a5..5aa174b 100644
+--- a/lib/packagekit-glib2/pk-transaction-past.h
++++ b/lib/packagekit-glib2/pk-transaction-past.h
+@@ -28,6 +28,7 @@
+
+ #include <glib-object.h>
+
++#include <packagekit-glib2/pk-enum.h>
+ #include <packagekit-glib2/pk-source.h>
+
+ G_BEGIN_DECLS
+@@ -62,6 +63,16 @@ struct _PkTransactionPastClass
+
+ GType pk_transaction_past_get_type (void);
+ PkTransactionPast *pk_transaction_past_new (void);
++const gchar *pk_transaction_past_get_cmdline (PkTransactionPast *past);
++const gchar *pk_transaction_past_get_data (PkTransactionPast *past);
++const gchar *pk_transaction_past_get_id (PkTransactionPast *past);
++const gchar *pk_transaction_past_get_timespec (PkTransactionPast *past);
++GDateTime *pk_transaction_past_get_datetime (PkTransactionPast *past);
++gint64 pk_transaction_past_get_timestamp (PkTransactionPast *past);
++gboolean pk_transaction_past_get_succeeded (PkTransactionPast *past);
++guint pk_transaction_past_get_duration (PkTransactionPast *past);
++guint pk_transaction_past_get_uid (PkTransactionPast *past);
++PkRoleEnum pk_transaction_past_get_role (PkTransactionPast *past);
+
+ G_END_DECLS
+
+diff --git a/src/org.freedesktop.PackageKit.xml b/src/org.freedesktop.PackageKit.xml
+index 297cbeb..b8038ca 100644
+--- a/src/org.freedesktop.PackageKit.xml
++++ b/src/org.freedesktop.PackageKit.xml
+@@ -316,6 +316,54 @@
+ </method>
+
+ <!--*****************************************************************************************-->
++ <method name="GetPackageHistory">
++ <doc:doc>
++ <doc:description>
++ <doc:para>
++ Gets the history for a given package name.
++ This uses the internal PackageKit history database and will not
++ return transactions done outside of PackageKit using a distribution
++ native tool.
++ </doc:para>
++ </doc:description>
++ </doc:doc>
++ <arg type="as" name="names" direction="in">
++ <doc:doc>
++ <doc:summary>
++ <doc:para>
++ The package names to return history for, e.g. <doc:tt>[ colord ]</doc:tt>.
++ </doc:para>
++ </doc:summary>
++ </doc:doc>
++ </arg>
++ <arg type="u" name="count" direction="in">
++ <doc:doc>
++ <doc:summary>
++ <doc:para>
++ The maximum number of past transactions to return, or 0 for no limit.
++ </doc:para>
++ </doc:summary>
++ </doc:doc>
++ </arg>
++ <arg type="a{saa{sv}}" name="history" direction="out">
++ <doc:doc>
++ <doc:summary>
++ <doc:para>
++ The list of actions performed on this package. The array may contain
++ the following keys of types:
++ <doc:tt>info[uint]</doc:tt>,
++ <doc:tt>user-id[uint]</doc:tt>,
++ <doc:tt>version[string]</doc:tt>,
++ <doc:tt>source[string]</doc:tt>,
++ <doc:tt>timestamp[uint64]</doc:tt>.
++ Other keys and values may be added in the future.
++ </doc:para>
++ </doc:summary>
++ </doc:doc>
++ </arg>
++ </method>
++
++ <!--*****************************************************************************************-->
+ <method name="GetDaemonState">
+ <doc:doc>
+ <doc:description>
+diff --git a/src/pk-engine.c b/src/pk-engine.c
+index 338cbaa..f7265bd 100644
+--- a/src/pk-engine.c
++++ b/src/pk-engine.c
+@@ -1255,6 +1255,165 @@ out:
+ }
+
+ /**
++ * pk_engine_package_name_in_strv:
++ **/
++static gboolean
++pk_engine_package_name_in_strv (gchar **strv, PkPackage *pkg)
++{
++ guint i;
++ for (i = 0; strv[i] != NULL; i++) {
++ if (g_strcmp0 (strv[i], pk_package_get_name (pkg)) == 0)
++ return TRUE;
++ }
++ return FALSE;
++}
++
++/**
++ * pk_engine_get_package_history_pkg:
++ *
++ * Create a 'a{sv}' GVariant instance from all the PkTransactionPast data
++ **/
++static GVariant *
++pk_engine_get_package_history_pkg (PkTransactionPast *item, PkPackage *pkg)
++{
++ GVariantBuilder builder;
++ g_variant_builder_init (&builder, G_VARIANT_TYPE_ARRAY);
++ g_variant_builder_add (&builder, "{sv}", "info",
++ g_variant_new_uint32 (pk_package_get_info (pkg)));
++ g_variant_builder_add (&builder, "{sv}", "source",
++ g_variant_new_string (pk_package_get_data (pkg)));
++ g_variant_builder_add (&builder, "{sv}", "version",
++ g_variant_new_string (pk_package_get_version (pkg)));
++ g_variant_builder_add (&builder, "{sv}", "timestamp",
++ g_variant_new_uint64 (pk_transaction_past_get_timestamp (item)));
++ g_variant_builder_add (&builder, "{sv}", "user-id",
++ g_variant_new_uint32 (pk_transaction_past_get_uid (item)));
++ return g_variant_builder_end (&builder);
++}
++/**
++ * pk_engine_get_package_history:
++ **/
++static GVariant *
++pk_engine_get_package_history (PkEngine *engine,
++ gchar **package_names,
++ guint max_size,
++ GError **error)
++{
++ const gchar *data;
++ const gchar *pkgname;
++ gboolean ret;
++ gchar *key;
++ gchar **package_lines;
++ GHashTable *deduplicate_hash;
++ GHashTable *pkgname_hash;
++ gint64 timestamp;
++ GList *keys = NULL;
++ GList *l;
++ GList *list;
++ GPtrArray *array = NULL;
++ guint i;
++ GVariantBuilder builder;
++ GVariant *value = NULL;
++ PkPackage *package_tmp;
++ PkTransactionPast *item;
++
++ list = pk_transaction_db_get_list (engine->priv->transaction_db, max_size);
++
++ /* simplify the loop */
++ if (max_size == 0)
++ max_size = G_MAXUINT;
++
++ pkgname_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, (GDestroyNotify) g_ptr_array_unref);
++ deduplicate_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
++ package_tmp = pk_package_new ();
++ for (l = list; l != NULL; l = l->next) {
++ item = PK_TRANSACTION_PAST (l->data);
++
++ /* ignore anything that failed */
++ if (!pk_transaction_past_get_succeeded (item))
++ continue;
++
++ /* split up data */
++ data = pk_transaction_past_get_data (item);
++ if (data == NULL)
++ continue;
++ package_lines = g_strsplit (data, "\n", -1);
++ for (i = 0; package_lines[i] != NULL; i++) {
++ ret = pk_package_parse (package_tmp, package_lines[i], error);
++ g_assert (ret);
++
++ /* not the package we care about */
++ if (!pk_engine_package_name_in_strv (package_names, package_tmp))
++ continue;
++
++ /* not a state we care about */
++ if (pk_package_get_info (package_tmp) == PK_INFO_ENUM_CLEANUP)
++ continue;
++
++ /* transactions without a timestamp are not interesting */
++ timestamp = pk_transaction_past_get_timestamp (item);
++ if (timestamp == 0)
++ continue;
++
++ /* de-duplicate the entry, in the case of multiarch */
++ key = g_strdup_printf ("%s-%" G_GINT64_FORMAT,
++ pk_package_get_name (package_tmp),
++ timestamp);
++ if (g_hash_table_lookup (deduplicate_hash, key) != NULL) {
++ g_free (key);
++ continue;
++ }
++ g_hash_table_insert (deduplicate_hash, key, package_lines[i]);
++
++ /* get the blob for this data item */
++ value = pk_engine_get_package_history_pkg (item, package_tmp);
++ if (value == NULL)
++ continue;
++
++ /* find the array */
++ pkgname = pk_package_get_name (package_tmp);
++ array = g_hash_table_lookup (pkgname_hash, pkgname);
++ if (array == NULL) {
++ array = g_ptr_array_new ();
++ g_hash_table_insert (pkgname_hash,
++ g_strdup (pkgname),
++ array);
++ }
++ g_ptr_array_add (array, value);
++ }
++ g_strfreev (package_lines);
++ }
++
++ /* no history returns an empty array */
++ if (g_hash_table_size (pkgname_hash) == 0) {
++ value = g_variant_new_array (G_VARIANT_TYPE ("{saa{sv}}"), NULL, 0);
++ goto out;
++ }
++
++ /* we have a hash of pkgname:GPtrArray where the GPtrArray is an array
++ * of GVariants of type a{sv} */
++ g_variant_builder_init (&builder, G_VARIANT_TYPE_ARRAY);
++ keys = g_hash_table_get_keys (pkgname_hash);
++ for (l = keys; l != NULL; l = l->next) {
++ pkgname = l->data;
++ array = g_hash_table_lookup (pkgname_hash, pkgname);
++ /* create aa{sv} */
++ value = g_variant_new_array (NULL,
++ (GVariant * const *) array->pdata,
++ MIN (array->len, max_size));
++ g_variant_builder_add (&builder, "{s at aa{sv}}", pkgname, value);
++ }
++ value = g_variant_builder_end (&builder);
++out:
++ g_list_free (keys);
++ g_hash_table_unref (pkgname_hash);
++ g_hash_table_unref (deduplicate_hash);
++ g_object_unref (package_tmp);
++ g_list_free_full (list, (GDestroyNotify) g_object_unref);
++ return value;
++}
++
++/**
+ * pk_engine_daemon_method_call:
+ **/
+ static void
+@@ -1269,11 +1428,13 @@ pk_engine_daemon_method_call (GDBusConnection *connection_, const gchar *sender,
+ GError *error = NULL;
+ guint time_since;
+ GVariant *value = NULL;
++ GVariant *tuple = NULL;
+ PkAuthorizeEnum result_enum;
+ PkEngine *engine = PK_ENGINE (user_data);
+ PkRoleEnum role;
+ gchar **transaction_list;
+ gchar **array = NULL;
++ gchar **package_names;
+ guint size;
+ gboolean is_priority = TRUE;
+
+@@ -1298,6 +1459,31 @@ pk_engine_daemon_method_call (GDBusConnection *connection_, const gchar *sender,
+ goto out;
+ }
+
++ if (g_strcmp0 (method_name, "GetPackageHistory") == 0) {
++ g_variant_get (parameters, "(^a&su)", &package_names, &size);
++ if (package_names == NULL || g_strv_length (package_names) == 0) {
++ g_dbus_method_invocation_return_error (invocation,
++ PK_ENGINE_ERROR,
++ PK_ENGINE_ERROR_NOT_SUPPORTED,
++ "history for package name invalid");
++ goto out;
++ }
++ value = pk_engine_get_package_history (engine, package_names, size, &error);
++ if (value == NULL) {
++ g_dbus_method_invocation_return_error (invocation,
++ PK_ENGINE_ERROR,
++ PK_ENGINE_ERROR_NOT_SUPPORTED,
++ "history for package name %s failed: %s",
++ package_names[0],
++ error->message);
++ g_error_free (error);
++ goto out;
++ }
++ tuple = g_variant_new_tuple (&value, 1);
++ g_dbus_method_invocation_return_value (invocation, tuple);
++ goto out;
++ }
++
+ if (g_strcmp0 (method_name, "CreateTransaction") == 0) {
+
+ g_debug ("CreateTransaction method called");
+diff --git a/src/pk-transaction-db.c b/src/pk-transaction-db.c
+index 41c3807..2b20f3a 100644
+--- a/src/pk-transaction-db.c
++++ b/src/pk-transaction-db.c
+@@ -56,13 +56,6 @@ struct PkTransactionDbPrivate
+ guint database_save_id;
+ };
+
+-enum {
+- SIGNAL_TRANSACTION,
+- SIGNAL_LAST
+-};
+-
+-static guint signals [SIGNAL_LAST] = { 0 };
+-
+ G_DEFINE_TYPE (PkTransactionDb, pk_transaction_db, G_TYPE_OBJECT)
+
+ typedef struct {
+@@ -79,21 +72,21 @@ typedef struct {
+ * pk_transaction_sqlite_transaction_cb:
+ **/
+ static gint
+-pk_transaction_sqlite_transaction_cb (void *data, gint argc, gchar **argv, gchar **col_name)
++pk_transaction_db_add_transaction_cb (void *data,
++ gint argc,
++ gchar **argv,
++ gchar **col_name)
+ {
+ PkTransactionPast *item;
+- PkTransactionDb *tdb = PK_TRANSACTION_DB (data);
++ GList **list = (GList **) data;
+ gint i;
+ gchar *col;
+ gchar *value;
+ guint temp;
+ gboolean ret;
+
+- g_return_val_if_fail (tdb != NULL, 0);
+- g_return_val_if_fail (PK_IS_TRANSACTION_DB (tdb), 0);
+-
+ item = pk_transaction_past_new ();
+- for (i=0; i<argc; i++) {
++ for (i = 0; i < argc; i++) {
+ col = col_name[i];
+ value = argv[i];
+ if (g_strcmp0 (col, "succeeded") == 0) {
+@@ -137,10 +130,9 @@ pk_transaction_sqlite_transaction_cb (void *data, gint argc, gchar **argv, gchar
+ }
+ }
+
+- /* emit signal */
+- g_signal_emit (tdb, signals [SIGNAL_TRANSACTION], 0, item);
++ /* add to start of the list */
++ *list = g_list_prepend (*list, item);
+
+- g_object_unref (item);
+ return 0;
+ }
+
+@@ -156,7 +148,7 @@ pk_transaction_db_sql_statement (PkTransactionDb *tdb, const gchar *sql)
+ g_return_val_if_fail (PK_IS_TRANSACTION_DB (tdb), FALSE);
+ g_return_val_if_fail (tdb->priv->db != NULL, FALSE);
+
+- rc = sqlite3_exec (tdb->priv->db, sql, pk_transaction_sqlite_transaction_cb, tdb, &error_msg);
++ rc = sqlite3_exec (tdb->priv->db, sql, NULL, tdb, &error_msg);
+ if (rc != SQLITE_OK) {
+ g_warning ("SQL error: %s\n", error_msg);
+ sqlite3_free (error_msg);
+@@ -307,24 +299,36 @@ out:
+ /**
+ * pk_transaction_db_get_list:
+ **/
+-gboolean
++GList *
+ pk_transaction_db_get_list (PkTransactionDb *tdb, guint limit)
+ {
++ gchar *error_msg = NULL;
+ gchar *statement;
++ gint rc;
++ GList *list = NULL;
+
+- g_return_val_if_fail (PK_IS_TRANSACTION_DB (tdb), FALSE);
++ g_return_val_if_fail (PK_IS_TRANSACTION_DB (tdb), NULL);
+
+- if (limit == 0)
++ if (limit == 0) {
+ statement = g_strdup ("SELECT transaction_id, timespec, succeeded, duration, role, data, uid, cmdline "
+ "FROM transactions ORDER BY timespec DESC");
+- else
++ } else {
+ statement = g_strdup_printf ("SELECT transaction_id, timespec, succeeded, duration, role, data, uid, cmdline "
+ "FROM transactions ORDER BY timespec DESC LIMIT %i", limit);
+-
+- pk_transaction_db_sql_statement (tdb, statement);
++ }
++ rc = sqlite3_exec (tdb->priv->db,
++ statement,
++ pk_transaction_db_add_transaction_cb,
++ &list,
++ &error_msg);
++ if (rc != SQLITE_OK) {
++ g_warning ("SQL error: %s\n", error_msg);
++ sqlite3_free (error_msg);
++ goto out;
++ }
++out:
+ g_free (statement);
+-
+- return TRUE;
++ return list;
+ }
+
+ /**
+@@ -830,11 +834,6 @@ pk_transaction_db_class_init (PkTransactionDbClass *klass)
+ {
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ object_class->finalize = pk_transaction_db_finalize;
+- signals [SIGNAL_TRANSACTION] =
+- g_signal_new ("transaction",
+- G_TYPE_FROM_CLASS (object_class), G_SIGNAL_RUN_LAST,
+- 0, NULL, NULL, g_cclosure_marshal_VOID__POINTER,
+- G_TYPE_NONE, 1, G_TYPE_POINTER);
+ g_type_class_add_private (klass, sizeof (PkTransactionDbPrivate));
+ }
+
+diff --git a/src/pk-transaction-db.h b/src/pk-transaction-db.h
+index 41e9b94..4a66c62 100644
+--- a/src/pk-transaction-db.h
++++ b/src/pk-transaction-db.h
+@@ -77,7 +77,7 @@ gboolean pk_transaction_db_set_finished (PkTransactionDb *tdb,
+ gboolean pk_transaction_db_set_data (PkTransactionDb *tdb,
+ const gchar *tid,
+ const gchar *data);
+-gboolean pk_transaction_db_get_list (PkTransactionDb *tdb,
++GList *pk_transaction_db_get_list (PkTransactionDb *tdb,
+ guint limit);
+ gboolean pk_transaction_db_action_time_reset (PkTransactionDb *tdb,
+ PkRoleEnum role);
+diff --git a/src/pk-transaction.c b/src/pk-transaction.c
+index 73a6960..123ad3f 100644
+--- a/src/pk-transaction.c
++++ b/src/pk-transaction.c
+@@ -1742,67 +1742,6 @@ pk_transaction_status_changed_cb (PkBackendJob *job,
+ }
+
+ /**
+- * pk_transaction_transaction_cb:
+- **/
+-static void
+-pk_transaction_transaction_cb (PkTransactionDb *tdb,
+- PkTransactionPast *item,
+- PkTransaction *transaction)
+-{
+- gchar *tid;
+- gchar *timespec;
+- gchar *data;
+- gchar *cmdline;
+- guint duration;
+- guint uid;
+- gboolean succeeded;
+- PkRoleEnum role;
+-
+- g_return_if_fail (PK_IS_TRANSACTION (transaction));
+- g_return_if_fail (transaction->priv->tid != NULL);
+-
+- /* add to results */
+- pk_results_add_transaction (transaction->priv->results, item);
+-
+- /* get data */
+- g_object_get (item,
+- "role", &role,
+- "tid", &tid,
+- "timespec", ×pec,
+- "succeeded", &succeeded,
+- "duration", &duration,
+- "data", &data,
+- "uid", &uid,
+- "cmdline", &cmdline,
+- NULL);
+-
+- /* emit */
+- g_debug ("emitting transaction %s, %s, %i, %s, %i, %s, %i, %s",
+- tid, timespec, succeeded,
+- pk_role_enum_to_string (role),
+- duration, data, uid, cmdline);
+- g_dbus_connection_emit_signal (transaction->priv->connection,
+- NULL,
+- transaction->priv->tid,
+- PK_DBUS_INTERFACE_TRANSACTION,
+- "Transaction",
+- g_variant_new ("(osbuusus)",
+- tid,
+- timespec,
+- succeeded,
+- role,
+- duration,
+- data != NULL ? data : "",
+- uid,
+- cmdline != NULL ? cmdline : ""),
+- NULL);
+- g_free (tid);
+- g_free (timespec);
+- g_free (data);
+- g_free (cmdline);
+-}
+-
+-/**
+ * pk_transaction_update_detail_cb:
+ **/
+ static void
+@@ -3764,8 +3703,19 @@ pk_transaction_get_old_transactions (PkTransaction *transaction,
+ GVariant *params,
+ GDBusMethodInvocation *context)
+ {
++ const gchar *cmdline;
++ const gchar *data;
++ const gchar *modified;
++ const gchar *tid;
++ gboolean succeeded;
++ GList *l;
++ GList *transactions = NULL;
++ guint duration;
+ guint idle_id;
+ guint number;
++ guint uid;
++ PkRoleEnum role;
++ PkTransactionPast *item;
+
+ g_return_if_fail (PK_IS_TRANSACTION (transaction));
+ g_return_if_fail (transaction->priv->tid != NULL);
+@@ -3776,7 +3726,46 @@ pk_transaction_get_old_transactions (PkTransaction *transaction,
+ g_debug ("GetOldTransactions method called");
+
+ pk_transaction_set_role (transaction, PK_ROLE_ENUM_GET_OLD_TRANSACTIONS);
+- pk_transaction_db_get_list (transaction->priv->transaction_db, number);
++ transactions = pk_transaction_db_get_list (transaction->priv->transaction_db, number);
++ for (l = transactions; l != NULL; l = l->next) {
++ item = PK_TRANSACTION_PAST (l->data);
++
++ /* add to results */
++ pk_results_add_transaction (transaction->priv->results, item);
++
++ /* get data */
++ role = pk_transaction_past_get_role (item);
++ tid = pk_transaction_past_get_id (item);
++ modified = pk_transaction_past_get_timespec (item);
++ succeeded = pk_transaction_past_get_succeeded (item);
++ duration = pk_transaction_past_get_duration (item);
++ data = pk_transaction_past_get_data (item);
++ uid = pk_transaction_past_get_uid (item);
++ cmdline = pk_transaction_past_get_cmdline (item);
++
++ /* emit */
++ g_debug ("adding transaction %s, %s, %i, %s, %i, %s, %i, %s",
++ tid, modified, succeeded,
++ pk_role_enum_to_string (role),
++ duration, data, uid, cmdline);
++ g_dbus_connection_emit_signal (transaction->priv->connection,
++ NULL,
++ transaction->priv->tid,
++ PK_DBUS_INTERFACE_TRANSACTION,
++ "Transaction",
++ g_variant_new ("(osbuusus)",
++ tid,
++ modified,
++ succeeded,
++ role,
++ duration,
++ data != NULL ? data : "",
++ uid,
++ cmdline != NULL ? cmdline : ""),
++ NULL);
++ }
++ g_list_free_full (transactions, (GDestroyNotify) g_object_unref);
++
+ idle_id = g_idle_add ((GSourceFunc) pk_transaction_finished_idle_cb, transaction);
+ g_source_set_name_by_id (idle_id, "[PkTransaction] finished from get-old-transactions");
+
+@@ -5805,8 +5794,6 @@ pk_transaction_init (PkTransaction *transaction)
+ error->message);
+ g_error_free (error);
+ }
+- g_signal_connect (transaction->priv->transaction_db, "transaction",
+- G_CALLBACK (pk_transaction_transaction_cb), transaction);
+
+ /* load introspection from file */
+ transaction->priv->introspection = pk_load_introspection (DATADIR "/dbus-1/interfaces/"
diff --git a/PackageKit.spec b/PackageKit.spec
index 1dd8bf1..38cc618 100644
--- a/PackageKit.spec
+++ b/PackageKit.spec
@@ -6,7 +6,7 @@
Summary: Package management service
Name: PackageKit
Version: 0.8.11
-Release: 1%{?dist}
+Release: 2%{?dist}
License: GPLv2+ and LGPLv2+
URL: http://www.packagekit.org
Source0: http://www.packagekit.org/releases/%{name}-%{version}.tar.xz
@@ -21,7 +21,7 @@ Patch1: PackageKit-0.4.4-Fedora-turn-off-time.conf.patch
Patch4: PackageKit-0.7.4-xulrunner2.patch
# Upstream already
-#Patch99: PackageKit-git-fixes.patch
+Patch99: PackageKit-git-fixes.patch
Requires: %{name}-glib%{?_isa} = %{version}-%{release}
Requires: PackageKit-backend
@@ -253,7 +253,7 @@ user to restart the computer or remove and re-insert the device.
%patch0 -p1 -b .fedora
%patch1 -p1 -b .no-time
%patch4 -p1 -b .xulrunner2
-#%patch99 -p1 -b .git
+%patch99 -p1 -b .git
NOCONFIGURE=1 ./autogen.sh
@@ -455,6 +455,10 @@ update-mime-database %{_datadir}/mime &> /dev/null || :
%{_libdir}/pkgconfig/packagekit-plugin.pc
%changelog
+* Mon Sep 23 2013 Richard Hughes <rhughes at redhat.com> - 0.8.11-2
+- Backport the package history functionality from master and some other
+ related bug fixes for gnome-software.
+
* Mon Sep 02 2013 Richard Hughes <rhughes at redhat.com> - 0.8.11-1
- New upstream release
- Add a few missing subcommands to the help output
More information about the scm-commits
mailing list