[gnome-software] Add fedora-distro-upgrades plugin



commit 72c62b1f454a8e985352ef10201dca6f78005db1
Author: Kalev Lember <klember redhat com>
Date:   Thu Jan 21 14:26:38 2016 +0100

    Add fedora-distro-upgrades plugin

 src/plugins/Makefile.am                        |    6 +
 src/plugins/gs-plugin-fedora-distro-upgrades.c |  271 ++++++++++++++++++++++++
 2 files changed, 277 insertions(+), 0 deletions(-)
---
diff --git a/src/plugins/Makefile.am b/src/plugins/Makefile.am
index 507c496..f4fa651 100644
--- a/src/plugins/Makefile.am
+++ b/src/plugins/Makefile.am
@@ -35,6 +35,7 @@ plugin_LTLIBRARIES =                                  \
        libgs_plugin_menu-spec-categories.la            \
        libgs_plugin_menu-spec-refine.la                \
        libgs_plugin_local-ratings.la                   \
+       libgs_plugin_fedora_distro_upgrades.la          \
        libgs_plugin_fedora_provenance.la               \
        libgs_plugin_fedora_tagger_ratings.la           \
        libgs_plugin_fedora_tagger_usage.la             \
@@ -61,6 +62,11 @@ libgs_plugin_dummy_la_LIBADD = $(GS_PLUGIN_LIBS)
 libgs_plugin_dummy_la_LDFLAGS = -module -avoid-version
 libgs_plugin_dummy_la_CFLAGS = $(GS_PLUGIN_CFLAGS) $(WARN_CFLAGS)
 
+libgs_plugin_fedora_distro_upgrades_la_SOURCES = gs-plugin-fedora-distro-upgrades.c
+libgs_plugin_fedora_distro_upgrades_la_LIBADD = $(GS_PLUGIN_LIBS) $(JSON_GLIB_LIBS) $(SOUP_LIBS)
+libgs_plugin_fedora_distro_upgrades_la_LDFLAGS = -module -avoid-version
+libgs_plugin_fedora_distro_upgrades_la_CFLAGS = $(GS_PLUGIN_CFLAGS) $(JSON_GLIB_CFLAGS) $(WARN_CFLAGS)
+
 libgs_plugin_fedora_provenance_la_SOURCES = gs-plugin-fedora-provenance.c
 libgs_plugin_fedora_provenance_la_LIBADD = $(GS_PLUGIN_LIBS) $(SOUP_LIBS) $(SQLITE_LIBS)
 libgs_plugin_fedora_provenance_la_LDFLAGS = -module -avoid-version
diff --git a/src/plugins/gs-plugin-fedora-distro-upgrades.c b/src/plugins/gs-plugin-fedora-distro-upgrades.c
new file mode 100644
index 0000000..8c32318
--- /dev/null
+++ b/src/plugins/gs-plugin-fedora-distro-upgrades.c
@@ -0,0 +1,271 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2016 Kalev Lember <klember redhat 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>
+
+#include <errno.h>
+#include <json-glib/json-glib.h>
+#include <libsoup/soup.h>
+
+#include <gs-plugin.h>
+#include <gs-os-release.h>
+#include <gs-utils.h>
+
+#define FEDORA_PKGDB_COLLECTIONS_API_URI "https://admin.fedoraproject.org/pkgdb/api/collections/";
+
+#ifndef JsonParser_autoptr
+G_DEFINE_AUTOPTR_CLEANUP_FUNC(JsonParser, g_object_unref)
+#endif
+
+struct GsPluginPrivate {
+       GPtrArray       *distros;
+       SoupSession     *session;
+};
+
+/**
+ * gs_plugin_get_name:
+ */
+const gchar *
+gs_plugin_get_name (void)
+{
+       return "fedora-distro-upgrades";
+}
+
+/**
+ * gs_plugin_initialize:
+ */
+void
+gs_plugin_initialize (GsPlugin *plugin)
+{
+       plugin->priv = GS_PLUGIN_GET_PRIVATE (GsPluginPrivate);
+       plugin->priv->session = soup_session_new_with_options (SOUP_SESSION_USER_AGENT, gs_user_agent (),
+                                                              NULL);
+       /* check that we are running on Fedora */
+       if (!gs_plugin_check_distro_id (plugin, "fedora")) {
+               gs_plugin_set_enabled (plugin, FALSE);
+               g_debug ("disabling '%s' as we're not Fedora", plugin->name);
+               return;
+       }
+}
+
+/**
+ * gs_plugin_destroy:
+ */
+void
+gs_plugin_destroy (GsPlugin *plugin)
+{
+       if (plugin->priv->distros != NULL)
+               g_ptr_array_unref (plugin->priv->distros);
+       if (plugin->priv->session != NULL)
+               g_object_unref (plugin->priv->session);
+}
+
+typedef enum {
+       DISTRO_STATUS_ACTIVE,
+       DISTRO_STATUS_DEVEL,
+       DISTRO_STATUS_EOL,
+       DISTRO_STATUS_LAST
+} DistroStatus;
+
+typedef struct {
+       gchar           *name;
+       DistroStatus     status;
+       guint            version;
+} DistroInfo;
+
+static void
+distro_info_free (DistroInfo *distro_info)
+{
+       g_free (distro_info->name);
+       g_slice_free (DistroInfo, distro_info);
+}
+
+static GPtrArray *
+parse_pkgdb_collections_data (const gchar *data,
+                              gssize length,
+                              GError **error)
+{
+       g_autoptr(JsonParser) parser = NULL;
+       GPtrArray *distros = NULL;
+       JsonArray *collections;
+       JsonObject *root;
+       gboolean ret;
+       guint i;
+
+       parser = json_parser_new ();
+
+       ret = json_parser_load_from_data (parser, data, length, error);
+       if (!ret)
+               return NULL;
+
+       root = json_node_get_object (json_parser_get_root (parser));
+       if (root == NULL) {
+               g_set_error (error,
+                            GS_PLUGIN_ERROR,
+                            GS_PLUGIN_ERROR_FAILED,
+                            "no root object");
+               return NULL;
+       }
+
+       collections = json_object_get_array_member (root, "collections");
+       if (collections == NULL) {
+               g_set_error (error,
+                            GS_PLUGIN_ERROR,
+                            GS_PLUGIN_ERROR_FAILED,
+                            "no collections object");
+               return NULL;
+       }
+
+       distros = g_ptr_array_new_with_free_func ((GDestroyNotify) distro_info_free);
+       for (i = 0; i < json_array_get_length (collections); i++) {
+               DistroInfo *distro_info;
+               JsonObject *item;
+               DistroStatus status;
+               const gchar *name;
+               const gchar *status_str;
+               const gchar *version_str;
+               gchar *endptr = NULL;
+               guint64 version;
+
+               item = json_array_get_object_element (collections, i);
+               if (item == NULL)
+                       continue;
+
+               name = json_object_get_string_member (item, "name");
+               if (name == NULL)
+                       continue;
+
+               status_str = json_object_get_string_member (item, "status");
+               if (status_str == NULL)
+                       continue;
+
+               if (g_strcmp0 (status_str, "Active") == 0)
+                       status = DISTRO_STATUS_ACTIVE;
+               else if (g_strcmp0 (status_str, "Under Development") == 0)
+                       status = DISTRO_STATUS_DEVEL;
+               else if (g_strcmp0 (status_str, "EOL") == 0)
+                       status = DISTRO_STATUS_EOL;
+               else
+                       continue;
+
+               version_str = json_object_get_string_member (item, "version");
+               if (version_str == NULL)
+                       continue;
+
+               errno = 0;
+               version = g_ascii_strtoull (version_str, &endptr, 10);
+               if (errno != 0 || endptr == version_str || version > G_MAXUINT)
+                       continue;
+
+               distro_info = g_slice_new0 (DistroInfo);
+               distro_info->name = g_strdup (name);
+               distro_info->status = status;
+               distro_info->version = (guint) version;
+
+               g_ptr_array_add (distros, distro_info);
+       }
+
+       return distros;
+}
+
+/**
+ * gs_plugin_add_distro_upgrades:
+ */
+gboolean
+gs_plugin_add_distro_upgrades (GsPlugin *plugin,
+                              GList **list,
+                              GCancellable *cancellable,
+                              GError **error)
+{
+       g_autofree gchar *os_name = NULL;
+       g_autofree gchar *os_version_str = NULL;
+       g_autoptr(GPtrArray) distros = NULL;
+       g_autoptr(SoupMessage) msg = NULL;
+       gchar *endptr = NULL;
+       guint i;
+       guint status_code;
+       guint64 os_version;
+
+       os_name = gs_os_release_get_name (error);
+       if (os_name == NULL)
+               return FALSE;
+       os_version_str = gs_os_release_get_version_id (error);
+       if (os_version_str == NULL)
+               return FALSE;
+
+       errno = 0;
+       os_version = g_ascii_strtoull (os_version_str, &endptr, 10);
+       if (errno != 0 || endptr == os_version_str || os_version > G_MAXUINT) {
+               g_set_error (error,
+                            GS_PLUGIN_ERROR,
+                            GS_PLUGIN_ERROR_FAILED,
+                            "Failed parse VERSION_ID: %s", os_version_str);
+               return FALSE;
+       }
+
+       /* create the GET data */
+       msg = soup_message_new (SOUP_METHOD_GET, FEDORA_PKGDB_COLLECTIONS_API_URI);
+
+       /* set sync request */
+       status_code = soup_session_send_message (plugin->priv->session, msg);
+       if (status_code != SOUP_STATUS_OK) {
+               g_set_error (error,
+                            GS_PLUGIN_ERROR,
+                            GS_PLUGIN_ERROR_FAILED,
+                            "Failed to download distro upgrade data: %s",
+                            soup_status_get_phrase (status_code));
+               return FALSE;
+       }
+
+       g_clear_pointer (&plugin->priv->distros, g_ptr_array_unref);
+       plugin->priv->distros = parse_pkgdb_collections_data (msg->response_body->data,
+                                                             msg->response_body->length,
+                                                             error);
+       for (i = 0; i < plugin->priv->distros->len; i++) {
+               DistroInfo *distro_info = g_ptr_array_index (plugin->priv->distros, i);
+               g_autofree gchar *app_id = NULL;
+               g_autofree gchar *app_version = NULL;
+               g_autoptr(GsApp) app = NULL;
+
+               /* only interested in upgrades to the same distro */
+               if (g_strcmp0 (distro_info->name, os_name) != 0)
+                       continue;
+               /* only interested in newer versions */
+               if (distro_info->version <= os_version)
+                       continue;
+               /* only interested in non-devel distros */
+               if (distro_info->status == DISTRO_STATUS_DEVEL)
+                       continue;
+
+               app_id = g_strdup_printf ("org.fedoraproject.release-%d.upgrade", distro_info->version);
+               app_version = g_strdup_printf ("%d", distro_info->version);
+
+               /* create */
+               app = gs_app_new (app_id);
+               gs_app_set_kind (app, GS_APP_KIND_DISTRO_UPGRADE);
+               gs_app_set_state (app, AS_APP_STATE_AVAILABLE);
+               gs_app_set_name (app, GS_APP_QUALITY_LOWEST, distro_info->name);
+               gs_app_set_version (app, app_version);
+               gs_plugin_add_app (list, app);
+       }
+
+       return TRUE;
+}


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]