[gnome-software] Load the GNOME moduleset from a file rather than hardcoding



commit 19c4b481617513860adaac74b525c28ec8a1aad4
Author: Richard Hughes <richard hughsie com>
Date:   Sat Feb 8 11:28:04 2014 +0100

    Load the GNOME moduleset from a file rather than hardcoding
    
    This allows us (or vendors) to modify this list without recompiling the
    application and will also allow us to support package-based core modulesets
    in the future.

 data/Makefile.am                                   |   13 +-
 data/moduleset-gnome-apps.xml                      |   34 +++
 src/plugins/Makefile.am                            |   16 +-
 src/plugins/gs-moduleset.c                         |  294 ++++++++++++++++++++
 src/plugins/gs-moduleset.h                         |   62 ++++
 ...ardcoded-kind.c => gs-plugin-moduleset-gnome.c} |  108 +++++---
 src/plugins/gs-self-test.c                         |   31 ++
 src/plugins/moduleset-test.xml                     |    4 +
 8 files changed, 513 insertions(+), 49 deletions(-)
---
diff --git a/data/Makefile.am b/data/Makefile.am
index b50f40f..fe35dee 100644
--- a/data/Makefile.am
+++ b/data/Makefile.am
@@ -4,19 +4,20 @@ SUBDIRS =                                             \
 
 resourcesdir = $(datadir)/gnome-software
 dist_resources_DATA =                                  \
-  featured-ardour.png \
-  featured-ardour-bg.png  \
-  featured-blender.png  \
-  featured-chess.png  \
+       featured-ardour.png                             \
+       featured-ardour-bg.png                          \
+       featured-blender.png                            \
+       featured-chess.png                              \
        featured-firefox.png                            \
        featured-gimp.png                               \
        featured-gnome-sudoku.png                       \
        featured-mypaint.png                            \
-       featured-transmission.png \
+       featured-transmission.png                       \
        featured-weather.png                            \
        featured-weather-bg.png                         \
        featured-xchat.png                              \
-       featured.ini
+       featured.ini                                    \
+       moduleset-gnome-apps.xml
 
 @GSETTINGS_RULES@
 gsettings_SCHEMAS = org.gnome.software.gschema.xml
diff --git a/data/moduleset-gnome-apps.xml b/data/moduleset-gnome-apps.xml
new file mode 100644
index 0000000..ed93766
--- /dev/null
+++ b/data/moduleset-gnome-apps.xml
@@ -0,0 +1,34 @@
+<moduleset name="gnome3">
+  <module type="application">baobab.desktop</module>
+  <module type="application">eog.desktop</module>
+  <module type="application">epiphany.desktop</module>
+  <module type="application">evince.desktop</module>
+  <module type="application">empathy.desktop</module>
+  <module type="application">gcalctool.desktop</module>
+  <module type="application">gedit.desktop</module>
+  <module type="application">gnome-bluetooth.desktop</module>
+  <module type="application">gnome-clocks.desktop</module>
+  <module type="application">gnome-contacts.desktop</module>
+  <module type="application">gnome-dictionary.desktop</module>
+  <module type="application">gnome-disks.desktop</module>
+  <module type="application">gnome-eog.desktop</module>
+  <module type="application">gnome-font-viewer.desktop</module>
+  <module type="application">gnome-gucharmap.desktop</module>
+  <module type="application">gnome-keyring.desktop</module>
+  <module type="application">gnome-menus.desktop</module>
+  <module type="application">gnome-packagekit.desktop</module>
+  <module type="application">gnome-screenshot.desktop</module>
+  <module type="application">gnome-session.desktop</module>
+  <module type="application">gnome-software.desktop</module>
+  <module type="application">gnome-system-log.desktop</module>
+  <module type="application">gnome-system-monitor.desktop</module>
+  <module type="application">gnome-terminal.desktop</module>
+  <module type="application">gnome-user-docs.desktop</module>
+  <module type="application">gnome-user-share.desktop</module>
+  <module type="application">gucharmap.desktop</module>
+  <module type="application">nautilus.desktop</module>
+  <module type="application">sushi.desktop</module>
+  <module type="application">totem.desktop</module>
+  <module type="application">vino.desktop</module>
+  <module type="application">yelp.desktop</module>
+</moduleset>
diff --git a/src/plugins/Makefile.am b/src/plugins/Makefile.am
index b74abe6..61db23d 100644
--- a/src/plugins/Makefile.am
+++ b/src/plugins/Makefile.am
@@ -31,7 +31,7 @@ plugin_LTLIBRARIES =                                  \
        libgs_plugin_datadir_filename_local.la          \
        libgs_plugin_desktopdb.la                       \
        libgs_plugin_hardcoded-featured.la              \
-       libgs_plugin_hardcoded-kind.la                  \
+       libgs_plugin_moduleset-gnome.la                 \
        libgs_plugin_hardcoded-categories.la            \
        libgs_plugin_hardcoded-popular.la               \
        libgs_plugin_menu-spec-categories.la            \
@@ -102,10 +102,13 @@ libgs_plugin_appdata_la_LIBADD = $(GS_PLUGIN_LIBS)
 libgs_plugin_appdata_la_LDFLAGS = -module -avoid-version
 libgs_plugin_appdata_la_CFLAGS = $(GS_PLUGIN_CFLAGS) $(WARNINGFLAGS_C)
 
-libgs_plugin_hardcoded_kind_la_SOURCES = gs-plugin-hardcoded-kind.c
-libgs_plugin_hardcoded_kind_la_LIBADD = $(GS_PLUGIN_LIBS)
-libgs_plugin_hardcoded_kind_la_LDFLAGS = -module -avoid-version
-libgs_plugin_hardcoded_kind_la_CFLAGS = $(GS_PLUGIN_CFLAGS) $(WARNINGFLAGS_C)
+libgs_plugin_moduleset_gnome_la_SOURCES =              \
+       gs-moduleset.c                                  \
+       gs-moduleset.h                                  \
+       gs-plugin-moduleset-gnome.c
+libgs_plugin_moduleset_gnome_la_LIBADD = $(GS_PLUGIN_LIBS)
+libgs_plugin_moduleset_gnome_la_LDFLAGS = -module -avoid-version
+libgs_plugin_moduleset_gnome_la_CFLAGS = $(GS_PLUGIN_CFLAGS) $(WARNINGFLAGS_C)
 
 libgs_plugin_hardcoded_popular_la_SOURCES = gs-plugin-hardcoded-popular.c
 libgs_plugin_hardcoded_popular_la_LIBADD = $(GS_PLUGIN_LIBS)
@@ -224,6 +227,7 @@ check_PROGRAMS =                                    \
 gs_self_test_SOURCES =                                 \
        appstream-common.c                              \
        appstream-markup.c                              \
+       gs-moduleset.c                                  \
        gs-self-test.c
 
 gs_self_test_LDADD =                                   \
@@ -234,4 +238,6 @@ gs_self_test_CFLAGS = $(WARNINGFLAGS_C)
 
 TESTS = gs-self-test
 
+EXTRA_DIST = moduleset-test.xml
+
 -include $(top_srcdir)/git.mk
diff --git a/src/plugins/gs-moduleset.c b/src/plugins/gs-moduleset.c
new file mode 100644
index 0000000..a3c88f5
--- /dev/null
+++ b/src/plugins/gs-moduleset.c
@@ -0,0 +1,294 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2014 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"
+
+#include <string.h>
+#include <glib.h>
+
+#include "gs-moduleset.h"
+
+typedef struct {
+       GsModulesetModuleKind    module_kind;
+       gchar                   *id;
+} GsModulesetEntry;
+
+typedef enum {
+       GS_MODULESET_PARSER_SECTION_UNKNOWN,
+       GS_MODULESET_PARSER_SECTION_MODULESET,
+       GS_MODULESET_PARSER_SECTION_MODULE,
+       GS_MODULESET_PARSER_SECTION_LAST
+} GsModulesetParserSection;
+
+typedef struct {
+       gchar                   *name;
+       GPtrArray               *array;
+       GsModulesetEntry        *entry_tmp;
+       GsModulesetParserSection section;
+} GsModulesetPrivate;
+
+G_DEFINE_TYPE_WITH_PRIVATE (GsModuleset, gs_moduleset, G_TYPE_OBJECT)
+
+/**
+ * gs_moduleset_get_name:
+ **/
+const gchar *
+gs_moduleset_get_name (GsModuleset *moduleset)
+{
+       GsModulesetPrivate *priv = gs_moduleset_get_instance_private (moduleset);
+       return priv->name;
+}
+
+/**
+ * gs_moduleset_get_by_kind:
+ **/
+gchar **
+gs_moduleset_get_by_kind (GsModuleset *moduleset, GsModulesetModuleKind module_kind)
+{
+       GsModulesetPrivate *priv = gs_moduleset_get_instance_private (moduleset);
+       GsModulesetEntry *entry;
+       gchar **data;
+       guint i;
+       guint idx = 0;
+
+       g_return_val_if_fail (GS_IS_MODULESET (moduleset), NULL);
+
+       /* return results that match */
+       data = g_new0 (gchar *, priv->array->len);
+       for (i = 0; i < priv->array->len; i++) {
+               entry = g_ptr_array_index (priv->array, i);
+               if (entry->module_kind == module_kind)
+                       data[idx++] = g_strdup (entry->id);
+       }
+
+       return data;
+}
+
+/**
+ * gs_moduleset_section_from_string:
+ **/
+static GsModulesetParserSection
+gs_moduleset_section_from_string (const gchar *element_name)
+{
+       if (g_strcmp0 (element_name, "moduleset") == 0)
+               return GS_MODULESET_PARSER_SECTION_MODULESET;
+       if (g_strcmp0 (element_name, "module") == 0)
+               return GS_MODULESET_PARSER_SECTION_MODULE;
+       return GS_MODULESET_PARSER_SECTION_UNKNOWN;
+}
+
+/**
+ * gs_moduleset_module_kind_from_string:
+ **/
+static GsModulesetModuleKind
+gs_moduleset_module_kind_from_string (const gchar *str)
+{
+       if (g_strcmp0 (str, "pkgname") == 0)
+               return GS_MODULESET_MODULE_KIND_PACKAGE;
+       if (g_strcmp0 (str, "application") == 0)
+               return GS_MODULESET_MODULE_KIND_APPLICATION;
+       return GS_MODULESET_MODULE_KIND_UNKNOWN;
+}
+
+/**
+ * gs_moduleset_parser_start_element:
+ **/
+static void
+gs_moduleset_parser_start_element (GMarkupParseContext *context,
+                                  const gchar *element_name,
+                                  const gchar **attribute_names,
+                                  const gchar **attribute_values,
+                                  gpointer user_data,
+                                  GError **error)
+{
+       GsModuleset *moduleset = GS_MODULESET (user_data);
+       GsModulesetPrivate *priv = gs_moduleset_get_instance_private (moduleset);
+       GsModulesetParserSection section_new;
+       GsModulesetModuleKind kind = GS_MODULESET_MODULE_KIND_UNKNOWN;
+       guint i;
+
+       section_new = gs_moduleset_section_from_string (element_name);
+       if (section_new == GS_MODULESET_PARSER_SECTION_UNKNOWN)
+               return;
+
+       switch (priv->section) {
+       case GS_MODULESET_PARSER_SECTION_UNKNOWN:
+               if (section_new == GS_MODULESET_PARSER_SECTION_MODULESET) {
+                       for (i = 0; attribute_names[i] != NULL; i++) {
+                               if (g_strcmp0 (attribute_names[i], "name") == 0) {
+                                       g_free (priv->name);
+                                       priv->name = g_strdup (attribute_values[i]);
+                               }
+                       }
+                       priv->section = section_new;
+                       return;
+               }
+               g_warning ("unknown->%s", element_name);
+               break;
+       case GS_MODULESET_PARSER_SECTION_MODULESET:
+               if (section_new == GS_MODULESET_PARSER_SECTION_MODULE) {
+                       priv->section = section_new;
+                       priv->entry_tmp = g_slice_new0 (GsModulesetEntry);
+                       for (i = 0; attribute_names[i] != NULL; i++) {
+                               if (g_strcmp0 (attribute_names[i], "type") == 0) {
+                                       kind = gs_moduleset_module_kind_from_string (attribute_values[i]);
+                               }
+                       }
+                       priv->entry_tmp->module_kind = kind;
+                       return;
+               }
+               g_warning ("moduleset->%s", element_name);
+               break;
+       default:
+               g_warning ("->%s", element_name);
+               break;
+       }
+}
+
+/**
+ * gs_moduleset_parser_end_element:
+ **/
+static void
+gs_moduleset_parser_end_element (GMarkupParseContext *context,
+                                const gchar *element_name,
+                                gpointer user_data,
+                                GError **error)
+{
+       GsModuleset *moduleset = GS_MODULESET (user_data);
+       GsModulesetPrivate *priv = gs_moduleset_get_instance_private (moduleset);
+
+       switch (priv->section) {
+       case GS_MODULESET_PARSER_SECTION_MODULESET:
+               priv->section = GS_MODULESET_PARSER_SECTION_UNKNOWN;
+               break;
+       case GS_MODULESET_PARSER_SECTION_MODULE:
+               priv->section = GS_MODULESET_PARSER_SECTION_MODULESET;
+               g_ptr_array_add (priv->array, priv->entry_tmp);
+               priv->entry_tmp = NULL;
+               break;
+       default:
+               g_warning ("<-%s", element_name);
+               break;
+       }
+}
+
+/**
+ * gs_moduleset_parser_text:
+ **/
+static void
+gs_moduleset_parser_text (GMarkupParseContext *context,
+                         const gchar *text,
+                         gsize text_len,
+                         gpointer user_data,
+                         GError **error)
+{
+       GsModuleset *moduleset = GS_MODULESET (user_data);
+       GsModulesetPrivate *priv = gs_moduleset_get_instance_private (moduleset);
+       switch (priv->section) {
+       case GS_MODULESET_PARSER_SECTION_MODULESET:
+               break;
+       case GS_MODULESET_PARSER_SECTION_MODULE:
+               priv->entry_tmp->id = g_strndup (text, text_len);
+               break;
+       default:
+               break;
+       }
+}
+
+/**
+ * gs_moduleset_parse_filename:
+ **/
+gboolean
+gs_moduleset_parse_filename (GsModuleset *moduleset, const gchar *filename, GError **error)
+{
+       const GMarkupParser parser = {
+               gs_moduleset_parser_start_element,
+               gs_moduleset_parser_end_element,
+               gs_moduleset_parser_text,
+               NULL,
+               NULL };
+       GMarkupParseContext *ctx;
+       gboolean ret;
+       gchar *data = NULL;
+       gsize data_len;
+
+       g_return_val_if_fail (GS_IS_MODULESET (moduleset), FALSE);
+
+       /* parse */
+       ctx = g_markup_parse_context_new (&parser,
+                                         G_MARKUP_PREFIX_ERROR_POSITION,
+                                         moduleset, NULL);
+       ret = g_file_get_contents (filename, &data, &data_len, error);
+       if (!ret)
+               goto out;
+       ret = g_markup_parse_context_parse (ctx, data, data_len, error);
+       if (!ret)
+               goto out;
+out:
+       g_markup_parse_context_free (ctx);
+       g_free (data);
+       return ret;
+}
+
+static void
+gs_moduleset_entry_free (GsModulesetEntry *entry)
+{
+       g_free (entry->id);
+       g_slice_free (GsModulesetEntry, entry);
+}
+
+static void
+gs_moduleset_finalize (GObject *object)
+{
+       GsModuleset *moduleset;
+       GsModulesetPrivate *priv;
+
+       g_return_if_fail (GS_IS_MODULESET (object));
+
+       moduleset = GS_MODULESET (object);
+       priv = gs_moduleset_get_instance_private (moduleset);
+       g_ptr_array_unref (priv->array);
+       g_free (priv->name);
+
+       G_OBJECT_CLASS (gs_moduleset_parent_class)->finalize (object);
+}
+
+static void
+gs_moduleset_class_init (GsModulesetClass *klass)
+{
+       GObjectClass *object_class = G_OBJECT_CLASS (klass);
+       object_class->finalize = gs_moduleset_finalize;
+}
+
+static void
+gs_moduleset_init (GsModuleset *moduleset)
+{
+       GsModulesetPrivate *priv = gs_moduleset_get_instance_private (moduleset);
+       priv->array = g_ptr_array_new_with_free_func ((GDestroyNotify) gs_moduleset_entry_free);
+}
+
+GsModuleset *
+gs_moduleset_new (void)
+{
+       GsModuleset *moduleset;
+       moduleset = g_object_new (GS_TYPE_MODULESET, NULL);
+       return GS_MODULESET (moduleset);
+}
diff --git a/src/plugins/gs-moduleset.h b/src/plugins/gs-moduleset.h
new file mode 100644
index 0000000..069c26a
--- /dev/null
+++ b/src/plugins/gs-moduleset.h
@@ -0,0 +1,62 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2014 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.
+ */
+
+#ifndef __GS_MODULESET_H
+#define __GS_MODULESET_H
+
+#include <glib-object.h>
+
+typedef struct _GsModuleset            GsModuleset;
+typedef struct _GsModulesetClass       GsModulesetClass;
+
+#define GS_TYPE_MODULESET      (gs_moduleset_get_type ())
+#define GS_MODULESET(o)                (G_TYPE_CHECK_INSTANCE_CAST ((o), GS_TYPE_MODULESET, GsModuleset))
+#define GS_IS_MODULESET(o)     (G_TYPE_CHECK_INSTANCE_TYPE ((o), GS_TYPE_MODULESET))
+
+struct _GsModuleset {
+       GObject          parent_instance;
+};
+
+struct _GsModulesetClass {
+       GObjectClass     parent_class;
+};
+
+typedef enum {
+       GS_MODULESET_MODULE_KIND_UNKNOWN,
+       GS_MODULESET_MODULE_KIND_APPLICATION,
+       GS_MODULESET_MODULE_KIND_PACKAGE,
+       GS_MODULESET_MODULE_KIND_LAST
+} GsModulesetModuleKind;
+
+GType           gs_moduleset_get_type                  (void);
+GsModuleset    *gs_moduleset_new                       (void);
+
+const gchar    *gs_moduleset_get_name                  (GsModuleset            *moduleset);
+gchar          **gs_moduleset_get_by_kind              (GsModuleset            *moduleset,
+                                                        GsModulesetModuleKind   module_kind);
+gboolean        gs_moduleset_parse_filename            (GsModuleset            *moduleset,
+                                                        const gchar            *filename,
+                                                        GError                 **error);
+
+G_END_DECLS
+
+#endif /* __GS_MODULESET_H */
+
diff --git a/src/plugins/gs-plugin-hardcoded-kind.c b/src/plugins/gs-plugin-moduleset-gnome.c
similarity index 50%
rename from src/plugins/gs-plugin-hardcoded-kind.c
rename to src/plugins/gs-plugin-moduleset-gnome.c
index fdfde29..2a28ab5 100644
--- a/src/plugins/gs-plugin-hardcoded-kind.c
+++ b/src/plugins/gs-plugin-moduleset-gnome.c
@@ -1,6 +1,6 @@
 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
  *
- * Copyright (C) 2013 Richard Hughes <richard hughsie com>
+ * Copyright (C) 2013-2014 Richard Hughes <richard hughsie com>
  *
  * Licensed under the GNU General Public License Version 2
  *
@@ -23,13 +23,39 @@
 
 #include <gs-plugin.h>
 
+#include "gs-moduleset.h"
+
+struct GsPluginPrivate {
+       GsModuleset             *moduleset;
+       gsize                    done_init;
+};
+
 /**
  * gs_plugin_get_name:
  */
 const gchar *
 gs_plugin_get_name (void)
 {
-       return "hardcoded-kind";
+       return "moduleset-gnome";
+}
+
+/**
+ * gs_plugin_initialize:
+ */
+void
+gs_plugin_initialize (GsPlugin *plugin)
+{
+       plugin->priv = GS_PLUGIN_GET_PRIVATE (GsPluginPrivate);
+       plugin->priv->moduleset = gs_moduleset_new ();
+}
+
+/**
+ * gs_plugin_destroy:
+ */
+void
+gs_plugin_destroy (GsPlugin *plugin)
+{
+       g_object_unref (plugin->priv->moduleset);
 }
 
 /**
@@ -45,6 +71,32 @@ gs_plugin_get_deps (GsPlugin *plugin)
 }
 
 /**
+ * gs_plugin_startup:
+ */
+static gboolean
+gs_plugin_startup (GsPlugin *plugin, GCancellable *cancellable, GError **error)
+{
+       gboolean ret;
+       gchar *filename;
+
+       /* Parse the XML */
+       gs_profile_start (plugin->profile, "moduleset-gnome::startup");
+       filename = g_build_filename (DATADIR,
+                                    "gnome-software",
+                                    "moduleset-gnome-apps.xml",
+                                    NULL);
+       ret = gs_moduleset_parse_filename (plugin->priv->moduleset,
+                                          filename,
+                                          error);
+       if (!ret)
+               goto out;
+out:
+       g_free (filename);
+       gs_profile_stop (plugin->profile, "moduleset-gnome::startup");
+       return ret;
+}
+
+/**
  * gs_plugin_refine:
  */
 gboolean
@@ -56,51 +108,31 @@ gs_plugin_refine (GsPlugin *plugin,
 {
        GList *l;
        GsApp *app;
+       gboolean ret = TRUE;
+       gchar **apps = NULL;
        guint i;
-       const gchar *apps[] = {
-               "baobab",
-               "eog",
-               "epiphany",
-               "evince",
-               "empathy",
-               "gcalctool",
-               "gedit",
-               "gnome-bluetooth",
-               "gnome-clocks",
-               "gnome-contacts",
-               "gnome-dictionary",
-               "gnome-disks",
-               "gnome-eog",
-               "gnome-font-viewer",
-               "gnome-gucharmap",
-               "gnome-keyring",
-               "gnome-menus",
-               "gnome-packagekit",
-               "gnome-screenshot",
-               "gnome-session",
-               "gnome-software",
-               "gnome-system-log",
-               "gnome-system-monitor",
-               "gnome-terminal",
-               "gnome-user-docs",
-               "gnome-user-share",
-               "gucharmap",
-               "nautilus",
-               "sushi",
-               "totem",
-               "vino",
-               "yelp",
-               NULL };
+
+       /* load XML files */
+       if (g_once_init_enter (&plugin->priv->done_init)) {
+               ret = gs_plugin_startup (plugin, cancellable, error);
+               g_once_init_leave (&plugin->priv->done_init, TRUE);
+               if (!ret)
+                       goto out;
+       }
 
        /* just mark each one as core */
+       apps = gs_moduleset_get_by_kind (plugin->priv->moduleset,
+                                        GS_MODULESET_MODULE_KIND_APPLICATION);
        for (l = *list; l != NULL; l = l->next) {
                app = GS_APP (l->data);
                for (i = 0; apps[i] != NULL; i++) {
-                       if (g_strcmp0 (apps[i], gs_app_get_id (app)) == 0) {
+                       if (g_strcmp0 (apps[i], gs_app_get_id_full (app)) == 0) {
                                gs_app_set_kind (app, GS_APP_KIND_SYSTEM);
                                break;
                        }
                }
        }
-       return TRUE;
+out:
+       g_strfreev (apps);
+       return ret;
 }
diff --git a/src/plugins/gs-self-test.c b/src/plugins/gs-self-test.c
index c86fa3c..f14072f 100644
--- a/src/plugins/gs-self-test.c
+++ b/src/plugins/gs-self-test.c
@@ -29,6 +29,8 @@
 #include "appstream-common.h"
 #include "appstream-markup.h"
 
+#include "gs-moduleset.h"
+
 static void
 appstream_common_func (void)
 {
@@ -138,6 +140,34 @@ appstream_markup_locale_func (void)
        appstream_markup_free (markup);
 }
 
+static void
+moduleset_func (void)
+{
+       gboolean ret;
+       gchar **data;
+       GError *error = NULL;
+       GsModuleset *ms;
+
+       ms = gs_moduleset_new ();
+       ret = gs_moduleset_parse_filename (ms, "./moduleset-test.xml", &error);
+       g_assert_no_error (error);
+       g_assert (ret);
+
+       data = gs_moduleset_get_by_kind (ms, GS_MODULESET_MODULE_KIND_PACKAGE);
+       g_assert (data != NULL);
+       g_assert_cmpint (g_strv_length (data), ==, 1);
+       g_assert_cmpstr (data[0], ==, "kernel");
+       g_assert_cmpstr (data[1], ==, NULL);
+
+       data = gs_moduleset_get_by_kind (ms, GS_MODULESET_MODULE_KIND_APPLICATION);
+       g_assert (data != NULL);
+       g_assert_cmpint (g_strv_length (data), ==, 1);
+       g_assert_cmpstr (data[0], ==, "gnome-shell.desktop");
+       g_assert_cmpstr (data[1], ==, NULL);
+
+       g_object_unref (ms);
+}
+
 int
 main (int argc, char **argv)
 {
@@ -149,6 +179,7 @@ main (int argc, char **argv)
        g_log_set_fatal_mask (NULL, G_LOG_LEVEL_ERROR | G_LOG_LEVEL_CRITICAL);
 
        /* tests go here */
+       g_test_add_func ("/moduleset", moduleset_func);
        g_test_add_func ("/appstream-common", appstream_common_func);
        g_test_add_func ("/appstream-markup{plain}", appstream_markup_plain_func);
        g_test_add_func ("/appstream-markup{tags}", appstream_markup_tags_func);
diff --git a/src/plugins/moduleset-test.xml b/src/plugins/moduleset-test.xml
new file mode 100644
index 0000000..af3eeea
--- /dev/null
+++ b/src/plugins/moduleset-test.xml
@@ -0,0 +1,4 @@
+<moduleset name="gnome3">
+  <module type="pkgname">kernel</module>
+  <module type="application">gnome-shell.desktop</module>
+</moduleset>


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