[gnome-builder/wip/mwleeds/ide-config-provider: 86/86] WIP: Write back flatpak manifest when modified



commit 0911cb49c3da79983ed6e30fa97de811ec54c839
Author: Matthew Leeds <mleeds redhat com>
Date:   Fri Jan 13 17:50:21 2017 -0600

    WIP: Write back flatpak manifest when modified

 .../flatpak/gbp-flatpak-configuration-provider.c   |  197 +++++++++++++++++++-
 .../flatpak/gbp-flatpak-configuration-provider.h   |    8 +
 2 files changed, 204 insertions(+), 1 deletions(-)
---
diff --git a/plugins/flatpak/gbp-flatpak-configuration-provider.c 
b/plugins/flatpak/gbp-flatpak-configuration-provider.c
index c8b3a36..5f84a47 100644
--- a/plugins/flatpak/gbp-flatpak-configuration-provider.c
+++ b/plugins/flatpak/gbp-flatpak-configuration-provider.c
@@ -30,12 +30,17 @@
 #include "gbp-flatpak-configuration-provider.h"
 #include "gbp-flatpak-configuration.h"
 
+#define WRITEBACK_TIMEOUT_SECS 2
+
 struct _GbpFlatpakConfigurationProvider
 {
   GObject                  parent_instance;
   IdeConfigurationManager *manager;
   GCancellable            *cancellable;
   GPtrArray               *configurations;
+
+  gulong                   writeback_handler;
+  guint                    change_count;
 };
 
 typedef struct
@@ -58,6 +63,188 @@ G_DEFINE_TYPE_EXTENDED (GbpFlatpakConfigurationProvider, gbp_flatpak_configurati
 static void gbp_flatpak_configuration_provider_load (IdeConfigurationProvider *provider, 
IdeConfigurationManager *manager);
 static void gbp_flatpak_configuration_provider_unload (IdeConfigurationProvider *provider, 
IdeConfigurationManager *manager);
 
+static void
+gbp_flatpak_configuration_provider_save_cb (GObject      *object,
+                                            GAsyncResult *result,
+                                            gpointer      user_data)
+{
+  g_autoptr(GTask) task = user_data;
+  GError *error = NULL;
+  GFile *file = (GFile *)object;
+
+  g_assert (G_IS_FILE (file));
+  g_assert (G_IS_ASYNC_RESULT (result));
+
+  if (!g_file_replace_contents_finish (file, result, NULL, &error))
+    g_task_return_error (task, error);
+  else
+    g_task_return_boolean (task, TRUE);
+}
+
+void
+gbp_flatpak_configuration_provider_save_async (GbpFlatpakConfigurationProvider *self,
+                                               GCancellable                    *cancellable,
+                                               GAsyncReadyCallback              callback,
+                                               gpointer                         user_data)
+{
+  g_autoptr(GTask) task = NULL;
+
+  IDE_ENTRY;
+
+  g_assert (GBP_IS_FLATPAK_CONFIGURATION_PROVIDER (self));
+  g_assert (!cancellable || G_IS_CANCELLABLE (cancellable));
+
+  task = g_task_new (self, cancellable, callback, user_data);
+
+  if (self->change_count == 0)
+    {
+      g_task_return_boolean (task, TRUE);
+      return;
+    }
+
+  self->change_count = 0;
+
+  if (self->configurations != NULL)
+    {
+      for (guint i = 0; i < self->configurations->len; i++)
+        {
+          g_autoptr(GError) local_error = NULL;
+          g_autoptr(GFileInputStream) file_stream = NULL;
+          g_autoptr(GDataInputStream) data_stream = NULL;
+          g_autoptr(GRegex) runtime_regex = NULL;
+          g_autoptr(GPtrArray) new_lines = NULL;
+          gchar *json_string = NULL;
+          GBytes *bytes = NULL;
+          const gchar *new_runtime_id;
+          gchar *new_runtime_name;
+          GFile *manifest;
+
+          GbpFlatpakConfiguration *configuration = (GbpFlatpakConfiguration *)g_ptr_array_index 
(self->configurations, i);
+
+          manifest = gbp_flatpak_configuration_get_manifest (configuration);
+          if (manifest == NULL)
+            continue;
+
+          file_stream = g_file_read (manifest, NULL, &local_error);
+          if (file_stream == NULL)
+            continue;
+
+          data_stream = g_data_input_stream_new (G_INPUT_STREAM (file_stream));
+
+          runtime_regex = g_regex_new ("^\\s*\"runtime\"\\s*:\\s*\"(?<id>.+)\",$", 0, 0, NULL);
+
+          new_runtime_id = ide_configuration_get_runtime_id (IDE_CONFIGURATION (configuration));
+          if (g_str_has_prefix (new_runtime_id, "flatpak:"))
+            {
+              gchar **parts;
+              parts = g_strsplit (new_runtime_id + 8, "/", 3);
+              if (parts[0] != NULL)
+                new_runtime_name = parts[0];
+            }
+
+          new_lines = g_ptr_array_new_with_free_func (g_free);
+          for (;;)
+            {
+              g_autoptr(GMatchInfo) match_info = NULL;
+              gchar *line;
+
+              line = g_data_input_stream_read_line_utf8 (data_stream, NULL, NULL, &local_error);
+              if (local_error != NULL || line == NULL)
+                break;
+
+              /* Replace the runtime with the user-chosen one */
+              if (!ide_str_empty0 (new_runtime_name))
+                {
+                  g_regex_match (runtime_regex, line, 0, &match_info);
+                  if (g_match_info_matches (match_info))
+                    {
+                      gchar *old_runtime_ptr;
+                      old_runtime_ptr = g_strstr_len (line, -1, g_match_info_fetch_named (match_info, "id"));
+                      *old_runtime_ptr = NULL;
+                      //TODO memory leak here?
+                      line = g_strdup_printf ("%s%s\",", line, new_runtime_name);
+                    }
+                }
+
+              //TODO deal with other things the user might have changed
+
+              g_ptr_array_add (new_lines, line);
+            }
+
+          g_ptr_array_add (new_lines, NULL);
+          json_string = g_strjoinv ("\n", (gchar **)new_lines->pdata);
+          bytes = g_bytes_new_take (json_string, strlen (json_string));
+
+          g_file_replace_contents_bytes_async (manifest,
+                                               bytes,
+                                               NULL,
+                                               FALSE,
+                                               G_FILE_CREATE_NONE,
+                                               cancellable,
+                                               gbp_flatpak_configuration_provider_save_cb,
+                                               g_object_ref (task));
+        }
+    }
+
+  //TODO write all the manifests not just one
+
+  IDE_EXIT;
+}
+
+gboolean
+gbp_flatpak_configuration_provider_save_finish (GbpFlatpakConfigurationProvider  *self,
+                                                GAsyncResult                         *result,
+                                                GError                              **error)
+{
+  g_return_val_if_fail (GBP_IS_FLATPAK_CONFIGURATION_PROVIDER (self), FALSE);
+  g_return_val_if_fail (G_IS_TASK (result), FALSE);
+
+  return g_task_propagate_boolean (G_TASK (result), error);
+}
+
+static gboolean
+gbp_flatpak_configuration_provider_do_writeback (gpointer data)
+{
+  GbpFlatpakConfigurationProvider *self = data;
+
+  g_assert (GBP_IS_FLATPAK_CONFIGURATION_PROVIDER (self));
+
+  self->writeback_handler = 0;
+
+  gbp_flatpak_configuration_provider_save_async (self, NULL, NULL, NULL);
+
+  return G_SOURCE_REMOVE;
+}
+
+static void
+gbp_flatpak_configuration_provider_queue_writeback (GbpFlatpakConfigurationProvider *self)
+{
+  g_assert (GBP_IS_FLATPAK_CONFIGURATION_PROVIDER (self));
+
+  IDE_ENTRY;
+
+  if (self->writeback_handler != 0)
+    g_source_remove (self->writeback_handler);
+
+  self->writeback_handler = g_timeout_add_seconds (WRITEBACK_TIMEOUT_SECS,
+                                                   gbp_flatpak_configuration_provider_do_writeback,
+                                                   self);
+
+  IDE_EXIT;
+}
+
+static void
+gbp_flatpak_configuration_provider_changed (GbpFlatpakConfigurationProvider *self,
+                                            IdeConfiguration *configuration)
+{
+  g_assert (GBP_IS_FLATPAK_CONFIGURATION_PROVIDER (self));
+  g_assert (IDE_IS_CONFIGURATION (configuration));
+
+  self->change_count++;
+
+  gbp_flatpak_configuration_provider_queue_writeback (self);
+}
+
 static gboolean
 contains_id (GPtrArray   *ar,
              const gchar *id)
@@ -450,6 +637,12 @@ gbp_flatpak_configuration_provider_load_manifests (GbpFlatpakConfigurationProvid
       if (manifest->config_opts != NULL)
         ide_configuration_set_config_opts (IDE_CONFIGURATION (configuration), manifest->config_opts);
 
+      g_signal_connect_object (configuration,
+                               "changed",
+                               G_CALLBACK (gbp_flatpak_configuration_provider_changed),
+                               self,
+                               G_CONNECT_SWAPPED);
+
       g_ptr_array_add (configurations, configuration);
     }
 
@@ -555,9 +748,11 @@ gbp_flatpak_configuration_provider_unload (IdeConfigurationProvider *provider,
   g_assert (GBP_IS_FLATPAK_CONFIGURATION_PROVIDER (self));
   g_assert (IDE_IS_CONFIGURATION_MANAGER (manager));
 
+  ide_clear_source (&self->writeback_handler);
+
   if (self->configurations != NULL)
     {
-      for (guint i= 0; i < self->configurations->len; i++)
+      for (guint i = 0; i < self->configurations->len; i++)
         {
           IdeConfiguration *configuration = g_ptr_array_index (self->configurations, i);
 
diff --git a/plugins/flatpak/gbp-flatpak-configuration-provider.h 
b/plugins/flatpak/gbp-flatpak-configuration-provider.h
index 7a262b7..dfc7905 100644
--- a/plugins/flatpak/gbp-flatpak-configuration-provider.h
+++ b/plugins/flatpak/gbp-flatpak-configuration-provider.h
@@ -27,6 +27,14 @@ G_BEGIN_DECLS
 
 G_DECLARE_FINAL_TYPE (GbpFlatpakConfigurationProvider, gbp_flatpak_configuration_provider, GBP, 
FLATPAK_CONFIGURATION_PROVIDER, GObject)
 
+void gbp_flatpak_configuration_provider_save_async      (GbpFlatpakConfigurationProvider *self,
+                                                         GCancellable                    *cancellable,
+                                                         GAsyncReadyCallback              callback,
+                                                         gpointer                         user_data);
+gboolean gbp_flatpak_configuration_provider_save_finish (GbpFlatpakConfigurationProvider  *self,
+                                                         GAsyncResult                     *result,
+                                                         GError                          **error);
+
 G_END_DECLS
 
 #endif /* GBP_FLATPAK_CONFIGURATION_PROVIDER_H */


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