[gnome-software] Add a packagekit-history plugin that sets history data on applications
- From: Richard Hughes <rhughes src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-software] Add a packagekit-history plugin that sets history data on applications
- Date: Wed, 11 Sep 2013 13:15:28 +0000 (UTC)
commit a07f2772bc8970ae4cb3d9b9e1b0c59c81f1dfe4
Author: Richard Hughes <richard hughsie com>
Date: Wed Sep 11 14:13:27 2013 +0100
Add a packagekit-history plugin that sets history data on applications
This only adds 66ms to the GUI startup, and allows us to implement the
list ordering-by-date, the post-offline-updates UI and the installed details view.
You need PackageKit from git master before this will populate details.
src/gs-application.c | 1 +
src/plugins/Makefile.am | 6 +
src/plugins/gs-plugin-packagekit-history.c | 258 ++++++++++++++++++++++++++++
3 files changed, 265 insertions(+), 0 deletions(-)
---
diff --git a/src/gs-application.c b/src/gs-application.c
index 79d5e73..46ea64f 100644
--- a/src/gs-application.c
+++ b/src/gs-application.c
@@ -167,6 +167,7 @@ gs_application_startup (GApplication *application)
gs_plugin_loader_set_enabled (app->plugin_loader, "local-ratings", TRUE);
gs_plugin_loader_set_enabled (app->plugin_loader, "packagekit", TRUE);
gs_plugin_loader_set_enabled (app->plugin_loader, "packagekit-refine", TRUE);
+ gs_plugin_loader_set_enabled (app->plugin_loader, "packagekit-history", TRUE);
gs_plugin_loader_set_enabled (app->plugin_loader, "appstream", TRUE);
gs_plugin_loader_set_enabled (app->plugin_loader, "desktopdb", TRUE);
gs_plugin_loader_set_enabled (app->plugin_loader, "datadir-apps", TRUE);
diff --git a/src/plugins/Makefile.am b/src/plugins/Makefile.am
index e20b075..d575ce0 100644
--- a/src/plugins/Makefile.am
+++ b/src/plugins/Makefile.am
@@ -41,6 +41,7 @@ plugin_LTLIBRARIES = \
libgs_plugin_hardcoded-screenshots.la \
libgs_plugin_local-ratings.la \
libgs_plugin_packagekit-refine.la \
+ libgs_plugin_packagekit-history.la \
libgs_plugin_packagekit.la
libgs_plugin_dummy_la_SOURCES = gs-plugin-dummy.c
@@ -108,6 +109,11 @@ libgs_plugin_packagekit_refine_la_LIBADD = $(GS_PLUGIN_LIBS) $(PACKAGEKIT_LIBS)
libgs_plugin_packagekit_refine_la_LDFLAGS = -module -avoid-version
libgs_plugin_packagekit_refine_la_CFLAGS = $(GS_PLUGIN_CFLAGS) $(WARNINGFLAGS_C)
+libgs_plugin_packagekit_history_la_SOURCES = gs-plugin-packagekit-history.c
+libgs_plugin_packagekit_history_la_LIBADD = $(GS_PLUGIN_LIBS)
+libgs_plugin_packagekit_history_la_LDFLAGS = -module -avoid-version
+libgs_plugin_packagekit_history_la_CFLAGS = $(GS_PLUGIN_CFLAGS) $(WARNINGFLAGS_C)
+
libgs_plugin_desktopdb_la_SOURCES = gs-plugin-desktopdb.c
libgs_plugin_desktopdb_la_LIBADD = $(GS_PLUGIN_LIBS) $(PACKAGEKIT_LIBS)
libgs_plugin_desktopdb_la_LDFLAGS = -module -avoid-version
diff --git a/src/plugins/gs-plugin-packagekit-history.c b/src/plugins/gs-plugin-packagekit-history.c
new file mode 100644
index 0000000..32a5718
--- /dev/null
+++ b/src/plugins/gs-plugin-packagekit-history.c
@@ -0,0 +1,258 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2013 Richard Hughes <richard 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <config.h>
+
+#define I_KNOW_THE_PACKAGEKIT_GLIB2_API_IS_SUBJECT_TO_CHANGE
+#include <packagekit-glib2/packagekit.h>
+
+#include <gs-plugin.h>
+
+struct GsPluginPrivate {
+ GDBusProxy *proxy;
+};
+
+/**
+ * gs_plugin_get_name:
+ */
+const gchar *
+gs_plugin_get_name (void)
+{
+ return "packagekit-history";
+}
+
+/**
+ * gs_plugin_initialize:
+ */
+void
+gs_plugin_initialize (GsPlugin *plugin)
+{
+ GError *error = NULL;
+
+ /* create private area */
+ plugin->priv = GS_PLUGIN_GET_PRIVATE (GsPluginPrivate);
+ plugin->priv->proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM,
+ G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES |
+ G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS,
+ NULL,
+ "org.freedesktop.PackageKit",
+ "/org/freedesktop/PackageKit",
+ "org.freedesktop.PackageKit",
+ NULL,
+ &error);
+ if (plugin->priv->proxy == NULL) {
+ g_warning ("Failed to create proxy for PackageKit: %s", error->message);
+ g_error_free (error);
+ }
+}
+
+/**
+ * gs_plugin_get_priority:
+ */
+gdouble
+gs_plugin_get_priority (GsPlugin *plugin)
+{
+ return 200.0f;
+}
+
+/**
+ * gs_plugin_destroy:
+ */
+void
+gs_plugin_destroy (GsPlugin *plugin)
+{
+ g_object_unref (plugin->priv->proxy);
+}
+
+/**
+ * gs_plugin_packagekit_refine_add_history:
+ */
+static void
+gs_plugin_packagekit_refine_add_history (GsApp *app, GVariant *dict)
+{
+ const gchar *version;
+ gboolean ret;
+ GsApp *history;
+ guint64 timestamp;
+ PkInfoEnum info_enum;
+
+ /* create new history item with same ID as parent */
+ history = gs_app_new (gs_app_get_id (app));
+ gs_app_set_kind (history, GS_APP_KIND_PACKAGE);
+ gs_app_set_name (history, gs_app_get_name (app));
+
+ /* get the installed state */
+ ret = g_variant_lookup (dict, "info", "u", &info_enum);
+ g_assert (ret);
+ switch (info_enum) {
+ case PK_INFO_ENUM_INSTALLING:
+ gs_app_set_state (history, GS_APP_STATE_INSTALLED);
+ break;
+ case PK_INFO_ENUM_REMOVING:
+ gs_app_set_state (history, GS_APP_STATE_AVAILABLE);
+ break;
+ case PK_INFO_ENUM_UPDATING:
+ gs_app_set_state (history, GS_APP_STATE_UPDATABLE);
+ break;
+ default:
+ break;
+ }
+
+ /* set the history time and date */
+ ret = g_variant_lookup (dict, "timestamp", "t", ×tamp);
+ g_assert (ret);
+ gs_app_set_install_date (history, timestamp);
+
+ /* set the history version number */
+ ret = g_variant_lookup (dict, "version", "&s", &version);
+ g_assert (ret);
+ gs_app_set_version (history, version);
+
+ /* add the package to the main application */
+ gs_app_add_history (app, history);
+ g_object_unref (history);
+
+ /* use the last event as approximation of the package timestamp */
+ gs_app_set_install_date (app, timestamp);
+}
+
+static gboolean
+gs_plugin_packagekit_refine (GsPlugin *plugin,
+ GList *list,
+ GCancellable *cancellable,
+ GError **error)
+{
+ const gchar **package_names;
+ gboolean ret = TRUE;
+ GError *error_local = NULL;
+ GList *l;
+ GsApp *app;
+ guint i = 0;
+ GVariantIter iter;
+ GVariant *result;
+ GVariant *tuple = NULL;
+ GVariant *value;
+
+ /* get an array of package names */
+ package_names = g_new0 (const gchar *, g_list_length (list) + 1);
+ for (l = list; l != NULL; l = l->next) {
+ app = GS_APP (l->data);
+ package_names[i++] = gs_app_get_source (app);
+ }
+
+ g_debug ("getting history for %i packages", g_list_length (list));
+ result = g_dbus_proxy_call_sync (plugin->priv->proxy,
+ "GetPackageHistory",
+ g_variant_new ("(^asu)", package_names, 0),
+ G_DBUS_CALL_FLAGS_NONE,
+ 200, /* 200ms should be more than enough... */
+ cancellable,
+ &error_local);
+ if (result == NULL) {
+ if (g_error_matches (error_local,
+ G_DBUS_ERROR,
+ G_DBUS_ERROR_UNKNOWN_METHOD)) {
+ g_debug ("No history available as PackageKit is too old: %s",
+ error_local->message);
+ g_error_free (error_local);
+
+ /* just set this to something non-zero so we don't keep
+ * trying to call GetPackageHistory */
+ for (l = list; l != NULL; l = l->next) {
+ app = GS_APP (l->data);
+ gs_app_set_install_date (app, 1);
+ }
+ } else {
+ ret = FALSE;
+ g_propagate_error (error, error_local);
+ }
+ goto out;
+ }
+
+ /* get any results */
+ tuple = g_variant_get_child_value (result, 0);
+ for (l = list; l != NULL; l = l->next) {
+ app = GS_APP (l->data);
+ ret = g_variant_lookup (tuple,
+ gs_app_get_source (app),
+ "@aa{sv}",
+ &value);
+ if (!ret) {
+ g_debug ("no history for %s, setting timestamp nonzero",
+ gs_app_get_source (app));
+ gs_app_set_install_date (app, 1);
+ continue;
+ }
+
+ /* add history for application */
+ g_variant_iter_init (&iter, value);
+ while ((value = g_variant_iter_next_value (&iter))) {
+ gs_plugin_packagekit_refine_add_history (app, value);
+ g_variant_unref (value);
+ }
+ }
+
+ /* success */
+ ret = TRUE;
+out:
+ g_free (package_names);
+ if (tuple != NULL)
+ g_variant_unref (tuple);
+ if (result != NULL)
+ g_variant_unref (result);
+ return ret;
+}
+
+/**
+ * gs_plugin_refine:
+ */
+gboolean
+gs_plugin_refine (GsPlugin *plugin,
+ GList *list,
+ GCancellable *cancellable,
+ GError **error)
+{
+ gboolean ret = TRUE;
+ GList *l;
+ GList *packages = NULL;
+ GsApp *app;
+
+ /* add any missing history data */
+ for (l = list; l != NULL; l = l->next) {
+ app = GS_APP (l->data);
+ if (gs_app_get_source (app) == NULL)
+ continue;
+ if (gs_app_get_install_date (app) != 0)
+ continue;
+ packages = g_list_prepend (packages, app);
+ }
+ if (packages != NULL) {
+ ret = gs_plugin_packagekit_refine (plugin,
+ packages,
+ cancellable,
+ error);
+ if (!ret)
+ goto out;
+ }
+out:
+ g_list_free (packages);
+ return ret;
+}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]