From 9c435a4caf54063965f4ed24b702a8b7c8c761bd Mon Sep 17 00:00:00 2001 From: Richard Hughes Date: Sep 23 2013 15:47:53 +0000 Subject: Backport some fixes from upstream --- 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 + + #include ++#include + #include + + 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 + ++#include + #include + + 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 @@ + + + ++ ++ ++ ++ ++ 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. ++ ++ ++ ++ ++ ++ ++ ++ The package names to return history for, e.g. [ colord ]. ++ ++ ++ ++ ++ ++ ++ ++ ++ The maximum number of past transactions to return, or 0 for no limit. ++ ++ ++ ++ ++ ++ ++ ++ ++ The list of actions performed on this package. The array may contain ++ the following keys of types: ++ info[uint], ++ user-id[uint], ++ version[string], ++ source[string], ++ timestamp[uint64]. ++ Other keys and values may be added in the future. ++ ++ ++ ++ ++ ++ ++ + + + +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@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; ipriv->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 - 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 - 0.8.11-1 - New upstream release - Add a few missing subcommands to the help output