[gnome-builder] runtimes: add bootstrap config helper



commit 84a665753472e4121c4f8069960fae18c8c51fc5
Author: Christian Hergert <chergert redhat com>
Date:   Mon Jan 15 20:27:51 2018 -0800

    runtimes: add bootstrap config helper
    
    This allows systems to ensure all the basic dependencies are
    installed before using a runtime. A flatpak runtime provider
    would use this to ensure that sdk-extensions are installed.
    
    Related #345

 src/libide/runtimes/ide-runtime-manager.c  | 172 +++++++++++++++++++++++++++++
 src/libide/runtimes/ide-runtime-manager.h  |  10 ++
 src/libide/runtimes/ide-runtime-provider.c | 118 ++++++++++++++++++++
 src/libide/runtimes/ide-runtime-provider.h |  18 +++
 4 files changed, 318 insertions(+)
---
diff --git a/src/libide/runtimes/ide-runtime-manager.c b/src/libide/runtimes/ide-runtime-manager.c
index fbd2cbff1..ed9b3b482 100644
--- a/src/libide/runtimes/ide-runtime-manager.c
+++ b/src/libide/runtimes/ide-runtime-manager.c
@@ -24,6 +24,7 @@
 #include "ide-context.h"
 #include "ide-debug.h"
 
+#include "buildsystem/ide-configuration.h"
 #include "runtimes/ide-runtime.h"
 #include "runtimes/ide-runtime-manager.h"
 #include "runtimes/ide-runtime-provider.h"
@@ -396,6 +397,11 @@ ide_runtime_manager_ensure_async (IdeRuntimeManager   *self,
 
 /**
  * ide_runtime_manager_ensure_finish:
+ * @self: an #IdeRuntimeManager
+ * @result: a #GAsyncResult
+ * @error: a location for a #GError or %NULL
+ *
+ * Completes an asynchronous request to ide_runtime_manager_ensure_async()
  *
  * Returns: (transfer full): An #IdeRuntime or %NULL.
  */
@@ -429,3 +435,169 @@ ide_runtime_manager_ensure_finish (IdeRuntimeManager  *self,
 
   return ret;
 }
+
+static void
+ide_runtime_manager_ensure_config_cb (GObject      *object,
+                                      GAsyncResult *result,
+                                      gpointer      user_data)
+{
+  IdeRuntimeProvider *provider = (IdeRuntimeProvider *)object;
+  g_autoptr(GTask) task = user_data;
+  g_autoptr(GError) error = NULL;
+  IdeRuntimeManager *self;
+  const gchar *runtime_id;
+  IdeRuntime *runtime;
+
+  IDE_ENTRY;
+
+  g_assert (IDE_IS_RUNTIME_PROVIDER (provider));
+  g_assert (G_IS_ASYNC_RESULT (result));
+  g_assert (G_IS_TASK (task));
+
+  if (!ide_runtime_provider_bootstrap_finish (provider, result, &error))
+    {
+      g_task_return_error (task, g_steal_pointer (&error));
+      IDE_EXIT;
+    }
+
+  self = g_task_get_source_object (task);
+  g_assert (IDE_IS_RUNTIME_MANAGER (self));
+
+  runtime_id = g_task_get_task_data (task);
+  g_assert (runtime_id != NULL);
+
+  runtime = ide_runtime_manager_get_runtime (self, runtime_id);
+
+  if (runtime == NULL)
+    {
+      g_task_return_new_error (task,
+                               G_IO_ERROR,
+                               G_IO_ERROR_FAILED,
+                               "Runtime failed to register runtime \"%s\"",
+                               runtime_id);
+      IDE_EXIT;
+    }
+
+  g_task_return_pointer (task, g_object_ref (runtime), g_object_unref);
+
+  IDE_EXIT;
+}
+
+/**
+ * ide_runtime_manager_ensure_config_async:
+ * @self: a #IdeRuntimeManager
+ * @configuration: an #IdeConfiguration
+ * @cancellable: (nullable): a #GCancellable or %NULL
+ * @callback: a #GAsyncReadyCallback to execute upon completion
+ * @user_data: closure data for @callback
+ *
+ * Ensures that the runtime or multiple runtimes that may be necessary to
+ * build the configuration are installed.
+ *
+ * Since: 3.28
+ */
+void
+ide_runtime_manager_ensure_config_async (IdeRuntimeManager   *self,
+                                         IdeConfiguration    *configuration,
+                                         GCancellable        *cancellable,
+                                         GAsyncReadyCallback  callback,
+                                         gpointer             user_data)
+{
+  g_autoptr(GTask) task = NULL;
+  const gchar *runtime_id;
+  InstallLookup lookup = { 0 };
+
+  IDE_ENTRY;
+
+  g_return_if_fail (IDE_IS_RUNTIME_MANAGER (self));
+  g_return_if_fail (IDE_IS_CONFIGURATION (configuration));
+  g_return_if_fail (!cancellable || G_IS_CANCELLABLE (cancellable));
+
+  runtime_id = ide_configuration_get_runtime_id (configuration);
+
+  task = g_task_new (self, cancellable, callback, user_data);
+  g_task_set_source_tag (task, ide_runtime_manager_ensure_config_async);
+  g_task_set_priority (task, G_PRIORITY_LOW);
+  g_task_set_task_data (task, g_strdup (runtime_id), g_free);
+
+  if (runtime_id == NULL)
+    {
+      g_task_return_new_error (task,
+                               G_IO_ERROR,
+                               G_IO_ERROR_FAILED,
+                               "Configuration does not have specified runtime");
+      return;
+    }
+
+  /*
+   * It would be tempting to just return early here if we could locate
+   * the runtime as already registered. But that isn't enough since we
+   * might need to also install an SDK.
+   */
+
+  lookup.runtime_id = runtime_id;
+  peas_extension_set_foreach (self->extensions,
+                              (PeasExtensionSetForeachFunc) install_lookup_cb,
+                              &lookup);
+
+  if (lookup.provider == NULL)
+    {
+      g_task_return_new_error (task,
+                               G_IO_ERROR,
+                               G_IO_ERROR_NOT_SUPPORTED,
+                               "Failed to locate provider for runtime: %s",
+                               runtime_id);
+      IDE_EXIT;
+    }
+
+  ide_runtime_provider_bootstrap_async (lookup.provider,
+                                        configuration,
+                                        cancellable,
+                                        ide_runtime_manager_ensure_config_cb,
+                                        g_steal_pointer (&task));
+
+  IDE_EXIT;
+}
+
+/**
+ * ide_runtime_manager_ensure_config_finish:
+ * @self: a #IdeRuntimeManager
+ * @result: a #GAsyncResult provided to callback
+ * @error: a location for a #GError or %NULL
+ *
+ * Completes an asynchronous request to ide_runtime_manager_ensure_config_async().
+ *
+ * Returns: (transfer full): an #IdeRuntime
+ *
+ * Since: 3.28
+ */
+IdeRuntime *
+ide_runtime_manager_ensure_config_finish (IdeRuntimeManager  *self,
+                                          GAsyncResult       *result,
+                                          GError            **error)
+{
+  g_autoptr(GError) local_error = NULL;
+  IdeRuntime *ret;
+
+  g_return_val_if_fail (IDE_IS_RUNTIME_MANAGER (self), NULL);
+  g_return_val_if_fail (G_IS_TASK (result), NULL);
+
+  ret = g_task_propagate_pointer (G_TASK (result), &local_error);
+
+  /*
+   * If we got NOT_SUPPORTED error, and the runtime already exists,
+   * then we can synthesize a successful result to the caller.
+   */
+  if (g_error_matches (local_error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED))
+    {
+      const gchar *runtime_id = g_task_get_task_data (G_TASK (result));
+      ret = ide_runtime_manager_get_runtime (self, runtime_id);
+      if (ret != NULL)
+        return ret;
+    }
+
+  if (error != NULL)
+    *error = g_steal_pointer (&local_error);
+
+  return ret;
+}
diff --git a/src/libide/runtimes/ide-runtime-manager.h b/src/libide/runtimes/ide-runtime-manager.h
index 6808b8401..7bfc881f9 100644
--- a/src/libide/runtimes/ide-runtime-manager.h
+++ b/src/libide/runtimes/ide-runtime-manager.h
@@ -48,5 +48,15 @@ IDE_AVAILABLE_IN_ALL
 IdeRuntime *ide_runtime_manager_ensure_finish        (IdeRuntimeManager    *self,
                                                       GAsyncResult         *result,
                                                       GError              **error);
+IDE_AVAILABLE_IN_3_28
+void        ide_runtime_manager_ensure_config_async  (IdeRuntimeManager    *self,
+                                                      IdeConfiguration     *configuration,
+                                                      GCancellable         *cancellable,
+                                                      GAsyncReadyCallback   callback,
+                                                      gpointer              user_data);
+IDE_AVAILABLE_IN_3_28
+IdeRuntime *ide_runtime_manager_ensure_config_finish (IdeRuntimeManager    *self,
+                                                      GAsyncResult         *result,
+                                                      GError              **error);
 
 G_END_DECLS
diff --git a/src/libide/runtimes/ide-runtime-provider.c b/src/libide/runtimes/ide-runtime-provider.c
index d04ac29a1..38d31fe50 100644
--- a/src/libide/runtimes/ide-runtime-provider.c
+++ b/src/libide/runtimes/ide-runtime-provider.c
@@ -16,6 +16,9 @@
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
+#define G_LOG_DOMAIN "ide-runtime-provider"
+
+#include "buildsystem/ide-configuration.h"
 #include "runtimes/ide-runtime-manager.h"
 #include "runtimes/ide-runtime-provider.h"
 
@@ -63,6 +66,63 @@ ide_runtime_provider_real_install_finish (IdeRuntimeProvider  *self,
   return g_task_propagate_boolean (G_TASK (result), error);
 }
 
+static void
+ide_runtime_provider_real_bootstrap_cb (GObject      *object,
+                                        GAsyncResult *result,
+                                        gpointer      user_data)
+{
+  IdeRuntimeProvider *self = (IdeRuntimeProvider *)object;
+  g_autoptr(GError) error = NULL;
+  g_autoptr(GTask) task = user_data;
+
+  g_assert (IDE_IS_RUNTIME_PROVIDER (self));
+  g_assert (G_IS_ASYNC_RESULT (result));
+  g_assert (G_IS_TASK (task));
+
+  if (!ide_runtime_provider_install_finish (self, result, &error))
+    g_task_return_error (task, g_steal_pointer (&error));
+  else
+    g_task_return_boolean (task, TRUE);
+}
+
+void
+ide_runtime_provider_real_bootstrap_async (IdeRuntimeProvider  *self,
+                                           IdeConfiguration    *configuration,
+                                           GCancellable        *cancellable,
+                                           GAsyncReadyCallback  callback,
+                                           gpointer             user_data)
+{
+  g_autoptr(GTask) task = NULL;
+  const gchar *runtime_id;
+
+  g_assert (IDE_IS_RUNTIME_PROVIDER (self));
+  g_assert (IDE_IS_CONFIGURATION (configuration));
+  g_assert (!cancellable || IDE_IS_CONFIGURATION (configuration));
+
+  task = g_task_new (self, cancellable, callback, user_data);
+  g_task_set_source_tag (task, ide_runtime_provider_real_bootstrap_async);
+  g_task_set_priority (task, G_PRIORITY_LOW);
+
+  runtime_id = ide_configuration_get_runtime_id (configuration);
+
+  if (runtime_id == NULL)
+    g_task_return_boolean (task, TRUE);
+  else
+    ide_runtime_provider_install_async (self,
+                                        runtime_id,
+                                        cancellable,
+                                        ide_runtime_provider_real_bootstrap_cb,
+                                        g_steal_pointer (&task));
+}
+
+gboolean
+ide_runtime_provider_real_bootstrap_finish (IdeRuntimeProvider  *self,
+                                          GAsyncResult        *result,
+                                          GError             **error)
+{
+  return g_task_propagate_boolean (G_TASK (result), error);
+}
+
 static void
 ide_runtime_provider_default_init (IdeRuntimeProviderInterface *iface)
 {
@@ -71,6 +131,8 @@ ide_runtime_provider_default_init (IdeRuntimeProviderInterface *iface)
   iface->can_install = ide_runtime_provider_real_can_install;
   iface->install_async = ide_runtime_provider_real_install_async;
   iface->install_finish = ide_runtime_provider_real_install_finish;
+  iface->bootstrap_async = ide_runtime_provider_real_bootstrap_async;
+  iface->bootstrap_finish = ide_runtime_provider_real_bootstrap_finish;
 }
 
 void
@@ -127,3 +189,59 @@ ide_runtime_provider_install_finish (IdeRuntimeProvider  *self,
 
   return IDE_RUNTIME_PROVIDER_GET_IFACE (self)->install_finish (self, result, error);
 }
+
+/**
+ * ide_runtime_provider_bootstrap_async:
+ * @self: a #IdeRuntimeProvider
+ * @configuration: an #IdeConfiguration
+ * @cancellable: (nullable): a #GCancellable or %NULL
+ * @callback: a #GAsyncReadyCallback or %NULL
+ * @user_data: closure data for @callback
+ *
+ * This function allows to the runtime provider to install dependent runtimes
+ * similar to ide_runtime_provider_install_async(), but with the added benefit
+ * that it can access the configuration for additional information.
+ *
+ * Some runtime providers like Flatpak might use this to locate SDK extensions
+ * and install those too.
+ *
+ * This function should be used instead of ide_runtime_provider_install_async().
+ *
+ * Since: 3.28
+ */
+void
+ide_runtime_provider_bootstrap_async (IdeRuntimeProvider  *self,
+                                      IdeConfiguration    *configuration,
+                                      GCancellable        *cancellable,
+                                      GAsyncReadyCallback  callback,
+                                      gpointer             user_data)
+{
+  g_return_if_fail (IDE_IS_RUNTIME_PROVIDER (self));
+  g_return_if_fail (IDE_IS_CONFIGURATION (configuration));
+  g_return_if_fail (!cancellable || G_IS_CANCELLABLE (cancellable));
+
+  IDE_RUNTIME_PROVIDER_GET_IFACE (self)->bootstrap_async (self, configuration, cancellable, callback, 
user_data);
+}
+
+/**
+ * ide_runtime_provider_bootstrap_finish:
+ * @self: a #IdeRuntimeProvider
+ * @result: a #GAsyncResult provided to callback
+ * @error: a location for a #GError, or %NULL
+ *
+ * Completes the asynchronous request to bootstrap.
+ *
+ * Returns: %TRUE if successful; otherwise %FALSE and @error is set.
+ *
+ * Since: 3.28
+ */
+gboolean
+ide_runtime_provider_bootstrap_finish (IdeRuntimeProvider  *self,
+                                       GAsyncResult        *result,
+                                       GError             **error)
+{
+  g_return_val_if_fail (IDE_IS_RUNTIME_PROVIDER (self), FALSE);
+  g_return_val_if_fail (G_IS_ASYNC_RESULT (result), FALSE);
+
+  return IDE_RUNTIME_PROVIDER_GET_IFACE (self)->bootstrap_finish (self, result, error);
+}
diff --git a/src/libide/runtimes/ide-runtime-provider.h b/src/libide/runtimes/ide-runtime-provider.h
index ca0ce195d..fa2d366f3 100644
--- a/src/libide/runtimes/ide-runtime-provider.h
+++ b/src/libide/runtimes/ide-runtime-provider.h
@@ -48,6 +48,14 @@ struct _IdeRuntimeProviderInterface
   gboolean (*install_finish)   (IdeRuntimeProvider   *self,
                                 GAsyncResult         *result,
                                 GError              **error);
+  void     (*bootstrap_async)  (IdeRuntimeProvider   *self,
+                                IdeConfiguration     *configuration,
+                                GCancellable         *cancellable,
+                                GAsyncReadyCallback   callback,
+                                gpointer              user_data);
+  gboolean (*bootstrap_finish) (IdeRuntimeProvider   *self,
+                                GAsyncResult         *result,
+                                GError              **error);
 };
 
 IDE_AVAILABLE_IN_ALL
@@ -69,5 +77,15 @@ IDE_AVAILABLE_IN_ALL
 gboolean ide_runtime_provider_install_finish   (IdeRuntimeProvider   *self,
                                                 GAsyncResult         *result,
                                                 GError              **error);
+IDE_AVAILABLE_IN_3_28
+void     ide_runtime_provider_bootstrap_async  (IdeRuntimeProvider   *self,
+                                                IdeConfiguration     *configuration,
+                                                GCancellable         *cancellable,
+                                                GAsyncReadyCallback   callback,
+                                                gpointer              user_data);
+IDE_AVAILABLE_IN_3_28
+gboolean ide_runtime_provider_bootstrap_finish (IdeRuntimeProvider   *self,
+                                                GAsyncResult         *result,
+                                                GError              **error);
 
 G_END_DECLS


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