[gnome-builder] vcs: add clone helper for threads



commit e15a8a5946adca9f770e1d309356cdc8559b8b75
Author: Christian Hergert <chergert redhat com>
Date:   Wed Apr 10 21:24:46 2019 -0700

    vcs: add clone helper for threads
    
    This adds a simple clone API that can be called from a thread, and block
    while the main loop async/finish pairs complete. It's not ideal, but it
    allows for straightforward ports of threaded code.

 src/libide/vcs/ide-vcs-cloner.c | 166 ++++++++++++++++++++++++++++++++++++++++
 src/libide/vcs/ide-vcs-cloner.h |   9 +++
 2 files changed, 175 insertions(+)
---
diff --git a/src/libide/vcs/ide-vcs-cloner.c b/src/libide/vcs/ide-vcs-cloner.c
index cf6d76c84..f5ecce56c 100644
--- a/src/libide/vcs/ide-vcs-cloner.c
+++ b/src/libide/vcs/ide-vcs-cloner.c
@@ -22,7 +22,10 @@
 
 #include "config.h"
 
+#include <gdk/gdk.h>
+
 #include <libide-threading.h>
+#include <libpeas/peas.h>
 
 #include "ide-vcs-cloner.h"
 
@@ -146,3 +149,166 @@ ide_vcs_cloner_get_title (IdeVcsCloner *self)
 
   return NULL;
 }
+
+typedef struct
+{
+  GMutex           mutex;
+  GCond            cond;
+  IdeContext      *context;
+  const gchar     *module_name;
+  const gchar     *url;
+  const gchar     *branch;
+  const gchar     *destination;
+  IdeNotification *notif;
+  GCancellable    *cancellable;
+  GError          *error;
+} CloneSimple;
+
+static void
+ide_vcs_cloner_clone_simple_clone_cb (GObject      *object,
+                                      GAsyncResult *result,
+                                      gpointer      user_data)
+{
+  IdeVcsCloner *cloner = (IdeVcsCloner *)object;
+  g_autoptr(GError) error = NULL;
+  CloneSimple *state = user_data;
+
+  g_assert (IDE_IS_VCS_CLONER (cloner));
+  g_assert (G_IS_ASYNC_RESULT (result));
+  g_assert (state->module_name != NULL);
+  g_assert (state->url != NULL);
+  g_assert (state->destination != NULL);
+  g_assert (!state->notif || IDE_IS_NOTIFICATION (state->notif));
+  g_assert (!state->cancellable || IDE_IS_NOTIFICATION (state->cancellable));
+  g_assert (state->error == NULL);
+
+  ide_vcs_cloner_clone_finish (cloner, result, &state->error);
+
+  g_mutex_lock (&state->mutex);
+  g_cond_signal (&state->cond);
+  g_mutex_unlock (&state->mutex);
+}
+
+static gboolean
+ide_vcs_cloner_clone_simple_idle_cb (CloneSimple *state)
+{
+  g_autoptr(PeasExtension) exten = NULL;
+  g_autoptr(GVariant) options = NULL;
+  PeasPluginInfo *plugin_info;
+  PeasEngine *engine;
+  GVariantDict dict;
+
+  g_assert (state != NULL);
+  g_assert (IDE_IS_CONTEXT (state->context));
+  g_assert (state->module_name != NULL);
+  g_assert (state->url != NULL);
+  g_assert (state->destination != NULL);
+  g_assert (!state->notif || IDE_IS_NOTIFICATION (state->notif));
+  g_assert (!state->cancellable || IDE_IS_NOTIFICATION (state->cancellable));
+  g_assert (state->error == NULL);
+
+  engine = peas_engine_get_default ();
+
+  if (!(plugin_info = peas_engine_get_plugin_info (engine, state->module_name)))
+    {
+      g_set_error (&state->error,
+                   G_IO_ERROR,
+                   G_IO_ERROR_NOT_FOUND,
+                   "No such module %s",
+                   state->module_name);
+      goto notify;
+    }
+
+  exten = peas_engine_create_extension (engine,
+                                        plugin_info,
+                                        IDE_TYPE_VCS_CLONER,
+                                        "parent", state->context,
+                                        NULL);
+
+  if (exten == NULL)
+    {
+      g_set_error (&state->error,
+                   G_IO_ERROR,
+                   G_IO_ERROR_NOT_FOUND,
+                   "Failed to create IdeVcsCloner from module %s",
+                   state->module_name);
+      goto notify;
+    }
+
+  g_variant_dict_init (&dict, NULL);
+  if (state->branch != NULL)
+    g_variant_dict_insert (&dict, "branch", "s", state->branch);
+  options = g_variant_take_ref (g_variant_dict_end (&dict));
+
+  ide_vcs_cloner_clone_async (IDE_VCS_CLONER (exten),
+                              state->url,
+                              state->destination,
+                              options,
+                              state->notif,
+                              state->cancellable,
+                              ide_vcs_cloner_clone_simple_clone_cb,
+                              state);
+
+  return G_SOURCE_REMOVE;
+
+notify:
+
+  g_mutex_lock (&state->mutex);
+  g_cond_signal (&state->cond);
+  g_mutex_unlock (&state->mutex);
+
+  return G_SOURCE_REMOVE;
+}
+
+gboolean
+ide_vcs_cloner_clone_simple (IdeContext       *context,
+                             const gchar      *module_name,
+                             const gchar      *url,
+                             const gchar      *branch,
+                             const gchar      *destination,
+                             IdeNotification  *notif,
+                             GCancellable     *cancellable,
+                             GError          **error)
+{
+  CloneSimple state = {0};
+
+  g_return_val_if_fail (!IDE_IS_MAIN_THREAD (), FALSE);
+  g_return_val_if_fail (IDE_IS_CONTEXT (context), FALSE);
+  g_return_val_if_fail (module_name != NULL, FALSE);
+  g_return_val_if_fail (url != NULL, FALSE);
+  g_return_val_if_fail (destination != NULL, FALSE);
+  g_return_val_if_fail (!notif || IDE_IS_NOTIFICATION (notif), FALSE);
+  g_return_val_if_fail (!cancellable || G_IS_CANCELLABLE (cancellable), FALSE);
+
+  state.context = context;
+  state.module_name = module_name;
+  state.url = url;
+  state.branch = branch;
+  state.destination = destination;
+  state.notif = notif;
+  state.cancellable = cancellable;
+  state.error = NULL;
+
+  g_mutex_init (&state.mutex);
+  g_cond_init (&state.cond);
+
+  g_mutex_lock (&state.mutex);
+
+  gdk_threads_add_idle_full (G_PRIORITY_HIGH,
+                             (GSourceFunc) ide_vcs_cloner_clone_simple_idle_cb,
+                             &state, NULL);
+
+  g_cond_wait (&state.cond, &state.mutex);
+  g_mutex_unlock (&state.mutex);
+  g_cond_clear (&state.cond);
+  g_mutex_clear (&state.mutex);
+
+  if (state.error != NULL)
+    {
+      g_propagate_error (error, g_steal_pointer (&state.error));
+      return FALSE;
+    }
+
+  return TRUE;
+}
+
diff --git a/src/libide/vcs/ide-vcs-cloner.h b/src/libide/vcs/ide-vcs-cloner.h
index adf1d35f2..d143010f8 100644
--- a/src/libide/vcs/ide-vcs-cloner.h
+++ b/src/libide/vcs/ide-vcs-cloner.h
@@ -69,5 +69,14 @@ IDE_AVAILABLE_IN_3_32
 gboolean  ide_vcs_cloner_validate_uri (IdeVcsCloner         *self,
                                        const gchar          *uri,
                                        gchar               **errmsg);
+IDE_AVAILABLE_IN_3_34
+gboolean  ide_vcs_cloner_clone_simple (IdeContext           *context,
+                                       const gchar          *module_name,
+                                       const gchar          *url,
+                                       const gchar          *branch,
+                                       const gchar          *destination,
+                                       IdeNotification      *notif,
+                                       GCancellable         *cancellable,
+                                       GError              **error);
 
 G_END_DECLS


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