[gnome-software/667-show-changelogs-for-rpm-ostree-updates] rpm-ostree: Show Changelog entries for updated packages



commit 30ed326b88bb18e5551a093c890584c100158092
Author: Milan Crha <mcrha redhat com>
Date:   Mon Oct 17 14:14:26 2022 +0200

    rpm-ostree: Show Changelog entries for updated packages
    
    Use `rpm-ostree` command to get Changelog entries for updated
    packages and show it to the user, if available. Hide packager's
    email addresses in the output, no need to expose them in the UI.
    
    Closes https://gitlab.gnome.org/GNOME/gnome-software/-/issues/667

 plugins/rpm-ostree/gs-plugin-rpm-ostree.c | 146 ++++++++++++++++++++++++++++++
 1 file changed, 146 insertions(+)
---
diff --git a/plugins/rpm-ostree/gs-plugin-rpm-ostree.c b/plugins/rpm-ostree/gs-plugin-rpm-ostree.c
index 1b4f758da..5d9377c6c 100644
--- a/plugins/rpm-ostree/gs-plugin-rpm-ostree.c
+++ b/plugins/rpm-ostree/gs-plugin-rpm-ostree.c
@@ -2840,6 +2840,152 @@ gs_plugin_rpm_ostree_disable_repository_finish (GsPlugin      *plugin,
        return g_task_propagate_boolean (G_TASK (result), error);
 }
 
+static const gchar *
+find_char_on_line (const gchar *txt,
+                  gchar chr)
+{
+       while (*txt != '\n' && *txt != '\0' && *txt != chr)
+               txt++;
+       return *txt == chr ? txt : NULL;
+}
+
+static void
+sanitize_update_history_text (gchar *text)
+{
+       gchar *read_pos = text, *write_pos = text;
+
+       #define skip_after(_chr) G_STMT_START { \
+               while (*read_pos != '\0' && *read_pos != '\n' && *read_pos != (_chr)) { \
+                       if (read_pos != write_pos) \
+                               *write_pos = *read_pos; \
+                       read_pos++; \
+                       write_pos++; \
+               } \
+               if (*read_pos == (_chr)) { \
+                       if (read_pos != write_pos) \
+                               *write_pos = *read_pos; \
+                       read_pos++; \
+                       write_pos++; \
+               } \
+       } G_STMT_END
+       #define skip_whitespace() G_STMT_START { \
+               while (*read_pos != '\0' && *read_pos != '\n' && g_ascii_isspace (*read_pos)) { \
+                       if (read_pos != write_pos) \
+                               *write_pos = *read_pos; \
+                       read_pos++; \
+                       write_pos++; \
+               } \
+       } G_STMT_END
+
+       /* The first two lines begin with "ostree diff commit from/to:" - skip them. */
+       if (g_ascii_strncasecmp (read_pos, "ostree diff", 11) == 0)
+               skip_after ('\n');
+       if (g_ascii_strncasecmp (read_pos, "ostree diff", 11) == 0)
+               skip_after ('\n');
+       write_pos = text;
+
+       while (*read_pos != '\0') {
+               skip_whitespace ();
+
+               /* Hide email addresses */
+               if (*read_pos == '*') {
+                       const gchar *start, *end;
+
+                       start = find_char_on_line (read_pos, '<');
+                       if (start != NULL) {
+                               end = find_char_on_line (start, '>');
+                               if (end != NULL) {
+                                       while (read_pos < start) {
+                                               if (read_pos != write_pos)
+                                                       *write_pos = *read_pos;
+                                               read_pos++;
+                                               write_pos++;
+                                       }
+                                       read_pos += end - read_pos;
+                                       if (*read_pos == '>' && g_ascii_isspace (read_pos[1]))
+                                               read_pos += 2;
+                               }
+                       }
+               }
+
+               skip_after ('\n');
+       }
+
+       #undef skip_until
+       #undef skip_whitespace
+
+       if (read_pos != write_pos)
+               *write_pos = '\0';
+}
+
+gboolean
+gs_plugin_add_updates_historical (GsPlugin *plugin,
+                                 GsAppList *list,
+                                 GCancellable *cancellable,
+                                 GError **error)
+{
+       g_autoptr(GSubprocess) subprocess = NULL;
+       GInputStream *input_stream;
+
+       subprocess = g_subprocess_new (G_SUBPROCESS_FLAGS_STDOUT_PIPE, error,
+                                      "rpm-ostree",
+                                      "db",
+                                      "diff",
+                                      "--changelogs",
+                                      "--format=block",
+                                      NULL);
+       if (subprocess == NULL)
+               return FALSE;
+       if (!g_subprocess_wait (subprocess, cancellable, error))
+               return FALSE;
+       input_stream = g_subprocess_get_stdout_pipe (subprocess);
+       if (input_stream != NULL) {
+               g_autoptr(GByteArray) array = g_byte_array_new ();
+               gchar buffer[4096];
+               gsize nread = 0;
+               gboolean success;
+
+               while (success = g_input_stream_read_all (input_stream, buffer, sizeof (buffer), &nread, 
cancellable, error), success && nread > 0) {
+                       g_byte_array_append (array, (const guint8 *) buffer, nread);
+               }
+
+               if (success && array->len > 0) {
+                       g_autoptr(GsApp) app = NULL;
+                       g_autoptr(GIcon) ic = NULL;
+
+                       /* NUL-terminated the array, to use it as a string */
+                       g_byte_array_append (array, (const guint8 *) "", 1);
+
+                       sanitize_update_history_text ((gchar *) array->data);
+
+                       /* create new */
+                       app = gs_app_new ("org.gnome.Software.RpmostreeUpdate");
+                       gs_app_set_management_plugin (app, plugin);
+                       gs_app_set_state (app, GS_APP_STATE_INSTALLED);
+                       gs_app_set_name (app,
+                                        GS_APP_QUALITY_NORMAL,
+                                        /* TRANSLATORS: this is a group of updates that are not
+                                         * packages and are not shown in the main list */
+                                        _("System Updates"));
+                       gs_app_set_summary (app,
+                                           GS_APP_QUALITY_NORMAL,
+                                           /* TRANSLATORS: this is a longer description of the
+                                            * "System Updates" string */
+                                           _("General system updates, such as security or bug fixes, and 
performance improvements."));
+                       gs_app_set_description (app,
+                                               GS_APP_QUALITY_NORMAL,
+                                               gs_app_get_summary (app));
+                       gs_app_set_update_details_text (app, (const gchar *) array->data);
+                       ic = g_themed_icon_new ("system-component-os-updates");
+                       gs_app_add_icon (app, ic);
+
+                       gs_app_list_add (list, app);
+               }
+       }
+
+       return input_stream != NULL;
+}
+
 static void
 gs_plugin_rpm_ostree_class_init (GsPluginRpmOstreeClass *klass)
 {


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