[recipes] Drop the libappstream-glib dependency again



commit cb1ec0ea3a31aa13f318a3235b899af8857c13a7
Author: Matthias Clasen <mclasen redhat com>
Date:   Mon Feb 27 18:55:26 2017 -0500

    Drop the libappstream-glib dependency again
    
    We can just as easily do this bit of xml parsing
    ourselves and save the trouble of the extra dependency.

 configure.ac     |    1 -
 meson.build      |    1 -
 src/gr-appdata.c |  210 +++++++++++++++++++++++++++++++++++++++++++++---------
 src/gr-appdata.h |    2 +-
 src/gr-window.c  |    2 +-
 5 files changed, 178 insertions(+), 38 deletions(-)
---
diff --git a/configure.ac b/configure.ac
index d7af373..5aa03cc 100644
--- a/configure.ac
+++ b/configure.ac
@@ -139,7 +139,6 @@ dnl ***********************************************************************
 PKG_CHECK_MODULES(RECIPES, [gmodule-2.0
                             gio-2.0 >= 2.42
                             gtk+-3.0 >= 3.22
-                            appstream-glib
                             $AUTOAR_DEP
                             $GSPELL_DEP
                             $CANBERRA_DEP])
diff --git a/meson.build b/meson.build
index 4de4157..e65dd1e 100644
--- a/meson.build
+++ b/meson.build
@@ -62,7 +62,6 @@ endif
 
 deps = [ dependency('gtk+-3.0', version : '>=3.22'),
          dependency('gmodule-export-2.0'),
-         dependency('appstream-glib'),
          autoar_dep,
          gspell_dep,
          canberra_dep,
diff --git a/src/gr-appdata.c b/src/gr-appdata.c
index 3f9df1b..af8b373 100644
--- a/src/gr-appdata.c
+++ b/src/gr-appdata.c
@@ -20,7 +20,8 @@
 
 #include "config.h"
 
-#include <appstream-glib.h>
+#include <string.h>
+#include <stdlib.h>
 #include <gr-appdata.h>
 
 static void
@@ -30,7 +31,7 @@ release_info_free (gpointer data)
 
         g_free (ri->version);
         g_date_time_unref (ri->date);
-        g_free (ri->news);
+        g_string_free (ri->news, TRUE);
         g_free (ri);
 }
 
@@ -72,51 +73,192 @@ version_between (const char *v,
         return version_compare (lower, v) <= 0 && version_compare (v, upper) <= 0;
 }
 
-GPtrArray *
-get_release_info (const char *new_version,
-                  const char *old_version)
+typedef struct {
+        GPtrArray *result;
+        const char *old_version;
+        const char *new_version;
+        ReleaseInfo *ri;
+        gboolean collect;
+        GString *text;
+} ParserData;
+
+static const char *
+find_attribute (const char  *name,
+                const char **names,
+                const char **values)
 {
-        GPtrArray *news;
-        g_autoptr(AsApp) app = NULL;
-        GPtrArray *releases = NULL;
-        unsigned int i;
-        g_autofree char *file = NULL;
-        g_autoptr(GError) error = NULL;
+        int i;
 
-        file = g_build_filename (DATADIR, "appdata", "org.gnome.Recipes.appdata.xml", NULL);
+        for (i = 0; names[i]; i++) {
+                if (strcmp (name, names[i]) == 0)
+                        return values[i];
+        }
+
+        return NULL;
+}
+
+static void
+start_element (GMarkupParseContext  *context,
+               const char           *element_name,
+               const char          **attribute_names,
+               const char          **attribute_values,
+               gpointer              user_data,
+               GError              **error)
+{
+        ParserData *data = user_data;
+
+        if (strcmp (element_name, "release") == 0) {
+                const char *value;
+                g_auto(GStrv) dmy = NULL;
+
+                data->ri = g_new0 (ReleaseInfo, 1);
+                data->ri->news = g_string_new ("");
 
-        news = g_ptr_array_new_with_free_func (release_info_free);
+                value = find_attribute ("version", attribute_names, attribute_values);
+                data->ri->version = g_strdup (value);
 
-        app = as_app_new ();
-        if (!as_app_parse_file (app, file, 0, &error)) {
-                g_warning ("Failed to parse %s: %s", file, error->message);
-                return news;
+                value = find_attribute ("date", attribute_names, attribute_values);
+                dmy = g_strsplit (value, "-", 3);
+                if (g_strv_length (dmy) != 3) {
+                        g_message ("Failed to parse release: %s", value);
+                        data->ri->date = g_date_time_new_from_unix_utc (0);
+                }
+                else {
+                        data->ri->date = g_date_time_new_utc (atoi (dmy[0]), atoi (dmy[1]), atoi (dmy[2]), 
0, 0, 0);
+                }
+        }
+        else if (strcmp (element_name, "p") == 0 ||
+                 strcmp (element_name, "li") == 0) {
+                if (data->ri) {
+                        g_string_set_size (data->text, 0);
+                        data->collect = TRUE;
+                }
         }
+}
 
-        releases = as_app_get_releases (app);
-        for (i = 0; i < releases->len; i++) {
-                AsRelease *rel = g_ptr_array_index (releases, i);
-                ReleaseInfo *ri;
-                const char *tmp;
+static void
+string_append_normalized (GString    *s,
+                          const char *str)
+{
+        gboolean initial = TRUE;
+        gboolean in_whitespace = FALSE;
+        const char *p;
 
-                if (!version_between (as_release_get_version (rel), old_version, new_version))
+        for (p = str; *p; p = g_utf8_next_char (p)) {
+                gunichar ch = g_utf8_get_char (p);
+
+                if (g_unichar_isspace (ch)) {
+                        in_whitespace = TRUE;
                         continue;
+                }
 
-                ri = g_new0 (ReleaseInfo, 1);
-                g_ptr_array_insert (news, -1, ri);
+                if (in_whitespace && !initial)
+                        g_string_append_c (s, ' ');
 
-                ri->version = g_strdup (as_release_get_version (rel));
+                g_string_append_unichar (s, ch);
+                in_whitespace = FALSE;
+                initial = FALSE;
+        }
+}
 
-                if (as_release_get_timestamp (rel) > 0)
-                        ri->date = g_date_time_new_from_unix_utc ((gint64) as_release_get_timestamp (rel));
+static void
+end_element (GMarkupParseContext  *context,
+             const char           *element_name,
+             gpointer              user_data,
+             GError              **error)
+{
+        ParserData *data = user_data;
 
-                tmp = as_release_get_description (rel, NULL);
-                if (tmp != NULL)
-                        ri->news = as_markup_convert (tmp, AS_MARKUP_CONVERT_FORMAT_SIMPLE, NULL);
-                else {
-                        g_warning ("Failed to convert markup in %s", file);
+        if (strcmp (element_name, "release") == 0) {
+                if (!version_between (data->ri->version, data->old_version, data->new_version))
+                        release_info_free (data->ri);
+                else
+                        g_ptr_array_add (data->result, data->ri);
+                data->ri = NULL;
+        }
+        else if (strcmp (element_name, "p") == 0) {
+                if (data->collect) {
+                        data->collect = FALSE;
+                        if (data->ri->news->len > 0)
+                                g_string_append (data->ri->news, "\n");
+                        string_append_normalized (data->ri->news, data->text->str);
+                }
+        }
+        else if (strcmp (element_name, "li") == 0) {
+                if (data->collect) {
+                        data->collect = TRUE;
+                        if (data->ri->news->len > 0)
+                                g_string_append (data->ri->news, "\n");
+                        g_string_append (data->ri->news, " ∙ ");
+                        string_append_normalized (data->ri->news, data->text->str);
                 }
         }
+}
+
+static void
+text (GMarkupParseContext  *context,
+      const char           *text,
+      gsize                 text_len,
+      gpointer              user_data,
+      GError              **error)
+{
+        ParserData *data = user_data;
+
+        if (data->collect)
+                g_string_append_len (data->text, text, text_len);
+}
+
+static GMarkupParser parser = {
+        start_element,
+        end_element,
+        text,
+        NULL,
+        NULL
+};
+
+static GPtrArray *
+parse_appdata (const char *file,
+               const char *new_version,
+               const char *old_version)
+{
+        g_autoptr(GMarkupParseContext) context = NULL;
+        g_autofree char *buffer = NULL;
+        gsize length;
+        g_autoptr(GError) error = NULL;
+        ParserData data;
+
+        data.result = g_ptr_array_new_with_free_func (release_info_free);
+        data.new_version = new_version;
+        data.old_version = old_version;
+        data.ri = NULL;
+        data.collect = FALSE;
+        data.text = g_string_new ("");
+
+        if (!g_file_get_contents (file, &buffer, &length, &error)) {
+                g_message ("Failed to read %s: %s", file, error->message);
+                goto out;
+        }
+
+        context = g_markup_parse_context_new (&parser, 0, &data, NULL);
+
+        if (!g_markup_parse_context_parse (context, buffer, length, &error)) {
+                g_message ("Failed to parse %s: %s", file, error->message);
+                g_ptr_array_set_size (data.result, 0);
+        }
+
+out:
+        g_string_free (data.text, TRUE);
+
+        return data.result;
+}
+
+GPtrArray *
+get_release_info (const char *new_version,
+                  const char *old_version)
+{
+        g_autofree char *file = NULL;
+
+        file = g_build_filename (DATADIR, "appdata", "org.gnome.Recipes.appdata.xml", NULL);
 
-        return news;
+        return parse_appdata (file, new_version, old_version);
 }
diff --git a/src/gr-appdata.h b/src/gr-appdata.h
index c05f04a..d0ead8e 100644
--- a/src/gr-appdata.h
+++ b/src/gr-appdata.h
@@ -27,7 +27,7 @@ G_BEGIN_DECLS
 typedef struct {
         char *version;
         GDateTime *date;
-        char *news;
+        GString *news;
 } ReleaseInfo;
 
 GPtrArray *get_release_info (const char *new_version,
diff --git a/src/gr-window.c b/src/gr-window.c
index 41c2626..d7d3030 100644
--- a/src/gr-window.c
+++ b/src/gr-window.c
@@ -1202,7 +1202,7 @@ gr_window_show_news (GrWindow *window)
                 }
 
                 if (ri->news) {
-                        label = gtk_label_new (ri->news);
+                        label = gtk_label_new (ri->news->str);
                         gtk_label_set_xalign (GTK_LABEL (label), 0.0);
                         gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
                         gtk_label_set_max_width_chars (GTK_LABEL (label), 55);


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