[gnome-builder/wip/tintou/toolchain] Replace load by load_async/finish and use toolchain-added/removed signal in the provider
- From: Corentin Noël <corentinnoel src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-builder/wip/tintou/toolchain] Replace load by load_async/finish and use toolchain-added/removed signal in the provider
- Date: Fri, 13 Apr 2018 14:16:15 +0000 (UTC)
commit b5fa86fa75053cc002dd9bcb401a947d65c845ba
Author: Corentin Noël <corentin noel collabora co uk>
Date: Fri Apr 13 15:15:00 2018 +0100
Replace load by load_async/finish and use toolchain-added/removed signal in the provider
src/libide/toolchain/ide-toolchain-manager.c | 173 ++++++++++----
src/libide/toolchain/ide-toolchain-manager.h | 7 -
src/libide/toolchain/ide-toolchain-provider.c | 194 ++++++++++++++-
src/libide/toolchain/ide-toolchain-provider.h | 33 ++-
src/plugins/cmake/gbp-cmake-toolchain-provider.c | 253 ++++++++++----------
src/plugins/cmake/gbp-cmake-toolchain.c | 72 ++----
src/plugins/cmake/gbp-cmake-toolchain.h | 8 +-
src/plugins/meson/gbp-meson-toolchain-provider.c | 287 +++++++++++++++--------
8 files changed, 672 insertions(+), 355 deletions(-)
---
diff --git a/src/libide/toolchain/ide-toolchain-manager.c b/src/libide/toolchain/ide-toolchain-manager.c
index cc013a1a5..de1dafdf0 100644
--- a/src/libide/toolchain/ide-toolchain-manager.c
+++ b/src/libide/toolchain/ide-toolchain-manager.c
@@ -30,6 +30,7 @@
#include "buildsystem/ide-build-private.h"
#include "config/ide-configuration.h"
#include "devices/ide-device.h"
+#include "threading/ide-task.h"
#include "toolchain/ide-simple-toolchain.h"
#include "toolchain/ide-toolchain.h"
#include "toolchain/ide-toolchain-manager.h"
@@ -38,9 +39,10 @@
struct _IdeToolchainManager
{
IdeObject parent_instance;
+
+ GCancellable *cancellable;
PeasExtensionSet *extensions;
GPtrArray *toolchains;
- guint unloading : 1;
};
typedef struct
@@ -64,6 +66,112 @@ prepare_state_free (PrepareState *state)
g_slice_free (PrepareState, state);
}
+static void
+ide_toolchain_manager_toolchain_added (IdeToolchainManager *self,
+ IdeToolchain *toolchain,
+ IdeToolchainProvider *provider)
+{
+ guint idx;
+
+ IDE_ENTRY;
+
+ g_assert (IDE_IS_TOOLCHAIN_MANAGER (self));
+ g_assert (IDE_IS_TOOLCHAIN (toolchain));
+ g_assert (IDE_IS_TOOLCHAIN_PROVIDER (provider));
+
+ idx = self->toolchains->len;
+ g_ptr_array_add (self->toolchains, g_object_ref (toolchain));
+ g_list_model_items_changed (G_LIST_MODEL (self), idx, 0, 1);
+
+ IDE_EXIT;
+}
+
+static void
+ide_toolchain_manager_toolchain_removed (IdeToolchainManager *self,
+ IdeToolchain *toolchain,
+ IdeToolchainProvider *provider)
+{
+ IDE_ENTRY;
+
+ g_assert (IDE_IS_TOOLCHAIN_MANAGER (self));
+ g_assert (IDE_IS_TOOLCHAIN (toolchain));
+ g_assert (IDE_IS_TOOLCHAIN_PROVIDER (provider));
+
+ for (guint i = 0; i < self->toolchains->len; i++)
+ {
+ IdeToolchain *item = g_ptr_array_index (self->toolchains, i);
+
+ if (toolchain == item)
+ {
+ g_ptr_array_remove_index (self->toolchains, i);
+ g_list_model_items_changed (G_LIST_MODEL (self), i, 1, 0);
+ break;
+ }
+ }
+
+ IDE_EXIT;
+}
+
+static void
+ide_toolchain_manager_toolchain_load_cb (GObject *object,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ IdeToolchainProvider *provider = (IdeToolchainProvider *)object;
+ IdeContext *context;
+ g_autoptr(IdeToolchainManager) self = user_data;
+ g_autoptr(GError) error = NULL;
+
+ IDE_ENTRY;
+
+ g_assert (IDE_IS_TOOLCHAIN_PROVIDER (provider));
+ g_assert (IDE_IS_TOOLCHAIN_MANAGER (self));
+ g_assert (IDE_IS_TASK (result));
+
+ context = ide_object_get_context (IDE_OBJECT (self));
+
+ if (!ide_toolchain_provider_load_finish (provider, result, &error))
+ ide_context_warning (context,
+ "Failed to initialize toolchain provider: %s: %s",
+ G_OBJECT_TYPE_NAME (provider), error->message);
+
+ IDE_EXIT;
+}
+
+static void
+provider_connect (IdeToolchainManager *self,
+ IdeToolchainProvider *provider)
+{
+ g_assert (IDE_IS_TOOLCHAIN_MANAGER (self));
+ g_assert (IDE_IS_TOOLCHAIN_PROVIDER (provider));
+
+ g_signal_connect_object (provider,
+ "added",
+ G_CALLBACK (ide_toolchain_manager_toolchain_added),
+ self,
+ G_CONNECT_SWAPPED);
+ g_signal_connect_object (provider,
+ "removed",
+ G_CALLBACK (ide_toolchain_manager_toolchain_removed),
+ self,
+ G_CONNECT_SWAPPED);
+}
+
+static void
+provider_disconnect (IdeToolchainManager *self,
+ IdeToolchainProvider *provider)
+{
+ g_assert (IDE_IS_TOOLCHAIN_MANAGER (self));
+ g_assert (IDE_IS_TOOLCHAIN_PROVIDER (provider));
+
+ g_signal_handlers_disconnect_by_func (provider,
+ G_CALLBACK (ide_toolchain_manager_toolchain_added),
+ self);
+ g_signal_handlers_disconnect_by_func (provider,
+ G_CALLBACK (ide_toolchain_manager_toolchain_removed),
+ self);
+}
+
static void
ide_toolchain_manager_extension_added (PeasExtensionSet *set,
PeasPluginInfo *plugin_info,
@@ -77,7 +185,12 @@ ide_toolchain_manager_extension_added (PeasExtensionSet *set,
g_assert (plugin_info != NULL);
g_assert (IDE_IS_TOOLCHAIN_PROVIDER (provider));
- ide_toolchain_provider_load (provider, self);
+ provider_connect (self, provider);
+
+ ide_toolchain_provider_load_async (provider,
+ self->cancellable,
+ ide_toolchain_manager_toolchain_load_cb,
+ g_object_ref (self));
}
static void
@@ -93,6 +206,8 @@ ide_toolchain_manager_extension_removed (PeasExtensionSet *set,
g_assert (plugin_info != NULL);
g_assert (IDE_IS_TOOLCHAIN_PROVIDER (provider));
+ provider_disconnect (self, provider);
+
ide_toolchain_provider_unload (provider, self);
}
@@ -104,6 +219,7 @@ ide_toolchain_manager_initable_init (GInitable *initable,
IdeToolchainManager *self = (IdeToolchainManager *)initable;
IdeContext *context;
g_autoptr(IdeSimpleToolchain) default_toolchain = NULL;
+ guint idx;
g_assert (IDE_IS_TOOLCHAIN_MANAGER (self));
context = ide_object_get_context (IDE_OBJECT (self));
@@ -111,6 +227,7 @@ ide_toolchain_manager_initable_init (GInitable *initable,
self->extensions = peas_extension_set_new (peas_engine_get_default (),
IDE_TYPE_TOOLCHAIN_PROVIDER,
+ "context", context,
NULL);
g_signal_connect (self->extensions,
@@ -127,8 +244,10 @@ ide_toolchain_manager_initable_init (GInitable *initable,
ide_toolchain_manager_extension_added,
self);
+ idx = self->toolchains->len;
default_toolchain = ide_simple_toolchain_new (context, "default");
- ide_toolchain_manager_add (self, IDE_TOOLCHAIN (default_toolchain));
+ g_ptr_array_add (self->toolchains, g_object_ref (default_toolchain));
+ g_list_model_items_changed (G_LIST_MODEL (self), idx, 0, 1);
return TRUE;
}
@@ -139,22 +258,14 @@ initable_iface_init (GInitableIface *iface)
iface->init = ide_toolchain_manager_initable_init;
}
-void
-_ide_toolchain_manager_unload (IdeToolchainManager *self)
-{
- g_return_if_fail (IDE_IS_TOOLCHAIN_MANAGER (self));
-
- self->unloading = TRUE;
- g_clear_object (&self->extensions);
-}
-
static void
ide_toolchain_manager_dispose (GObject *object)
{
IdeToolchainManager *self = (IdeToolchainManager *)object;
- _ide_toolchain_manager_unload (self);
+ g_clear_object (&self->extensions);
g_clear_pointer (&self->toolchains, g_ptr_array_unref);
+ g_clear_object (&self->cancellable);
G_OBJECT_CLASS (ide_toolchain_manager_parent_class)->dispose (object);
}
@@ -170,6 +281,7 @@ ide_toolchain_manager_class_init (IdeToolchainManagerClass *klass)
static void
ide_toolchain_manager_init (IdeToolchainManager *self)
{
+ self->cancellable = g_cancellable_new ();
self->toolchains = g_ptr_array_new_with_free_func (g_object_unref);
}
@@ -209,41 +321,6 @@ list_model_iface_init (GListModelInterface *iface)
iface->get_item = ide_toolchain_manager_get_item;
}
-void
-ide_toolchain_manager_add (IdeToolchainManager *self,
- IdeToolchain *toolchain)
-{
- guint idx;
-
- g_return_if_fail (IDE_IS_TOOLCHAIN_MANAGER (self));
- g_return_if_fail (IDE_IS_TOOLCHAIN (toolchain));
-
- idx = self->toolchains->len;
- g_ptr_array_add (self->toolchains, g_object_ref (toolchain));
- g_list_model_items_changed (G_LIST_MODEL (self), idx, 0, 1);
-}
-
-void
-ide_toolchain_manager_remove (IdeToolchainManager *self,
- IdeToolchain *toolchain)
-{
- g_return_if_fail (IDE_IS_TOOLCHAIN_MANAGER (self));
- g_return_if_fail (IDE_IS_TOOLCHAIN (toolchain));
-
- for (guint i = 0; i < self->toolchains->len; i++)
- {
- IdeToolchain *item = g_ptr_array_index (self->toolchains, i);
-
- if (toolchain == item)
- {
- g_ptr_array_remove_index (self->toolchains, i);
- if (!ide_object_is_unloading (IDE_OBJECT (self)))
- g_list_model_items_changed (G_LIST_MODEL (self), i, 1, 0);
- break;
- }
- }
-}
-
/**
* ide_toolchain_manager_get_toolchain:
* @self: An #IdeToolchainManager
diff --git a/src/libide/toolchain/ide-toolchain-manager.h b/src/libide/toolchain/ide-toolchain-manager.h
index 91e782be6..f4ef26d34 100644
--- a/src/libide/toolchain/ide-toolchain-manager.h
+++ b/src/libide/toolchain/ide-toolchain-manager.h
@@ -34,11 +34,4 @@ G_DECLARE_FINAL_TYPE (IdeToolchainManager, ide_toolchain_manager, IDE, TOOLCHAIN
IDE_AVAILABLE_IN_3_30
IdeToolchain *ide_toolchain_manager_get_toolchain (IdeToolchainManager *self,
const gchar *id);
-IDE_AVAILABLE_IN_3_30
-void ide_toolchain_manager_add (IdeToolchainManager *self,
- IdeToolchain *toolchain);
-IDE_AVAILABLE_IN_3_30
-void ide_toolchain_manager_remove (IdeToolchainManager *self,
- IdeToolchain *toolchain);
-
G_END_DECLS
diff --git a/src/libide/toolchain/ide-toolchain-provider.c b/src/libide/toolchain/ide-toolchain-provider.c
index 4ef94d96d..198c64f82 100644
--- a/src/libide/toolchain/ide-toolchain-provider.c
+++ b/src/libide/toolchain/ide-toolchain-provider.c
@@ -23,24 +23,48 @@
#include "ide-debug.h"
+#include "application/ide-application.h"
#include "toolchain/ide-toolchain-provider.h"
-G_DEFINE_INTERFACE (IdeToolchainProvider, ide_toolchain_provider, G_TYPE_OBJECT)
+G_DEFINE_INTERFACE (IdeToolchainProvider, ide_toolchain_provider, IDE_TYPE_OBJECT)
+
+enum {
+ ADDED,
+ REMOVED,
+ N_SIGNALS
+};
+
+static guint signals [N_SIGNALS];
static void
-ide_toolchain_provider_default_init (IdeToolchainProviderInterface *iface)
+ide_toolchain_provider_real_load_async (IdeToolchainProvider *self,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
{
-
+ g_assert (IDE_IS_MAIN_THREAD ());
+ g_assert (IDE_IS_TOOLCHAIN_PROVIDER (self));
+ g_assert (!cancellable || G_IS_CANCELLABLE (cancellable));
+
+ g_task_report_new_error (self, callback, user_data,
+ ide_toolchain_provider_real_load_async,
+ G_IO_ERROR,
+ G_IO_ERROR_NOT_SUPPORTED,
+ "%s does not implement load_async",
+ G_OBJECT_TYPE_NAME (self));
}
-void
-ide_toolchain_provider_load (IdeToolchainProvider *self,
- IdeToolchainManager *manager)
+gboolean
+ide_toolchain_provider_real_load_finish (IdeToolchainProvider *self,
+ GAsyncResult *result,
+ GError **error)
{
- g_return_if_fail (IDE_IS_TOOLCHAIN_PROVIDER (self));
- g_return_if_fail (IDE_IS_TOOLCHAIN_MANAGER (manager));
+ g_assert (IDE_IS_MAIN_THREAD ());
+ g_assert (IDE_IS_TOOLCHAIN_PROVIDER (self));
+ g_assert (G_IS_TASK (result));
+ g_assert (g_task_is_valid (G_TASK (result), self));
- IDE_TOOLCHAIN_PROVIDER_GET_IFACE (self)->load (self, manager);
+ return g_task_propagate_boolean (G_TASK (self), error);
}
void
@@ -52,3 +76,155 @@ ide_toolchain_provider_unload (IdeToolchainProvider *self,
IDE_TOOLCHAIN_PROVIDER_GET_IFACE (self)->unload (self, manager);
}
+
+static void
+ide_toolchain_provider_real_unload (IdeToolchainProvider *self,
+ IdeToolchainManager *manager)
+{
+ g_assert (IDE_IS_MAIN_THREAD ());
+ g_assert (IDE_IS_TOOLCHAIN_PROVIDER (self));
+ g_assert (IDE_IS_TOOLCHAIN_MANAGER (manager));
+
+}
+
+static void
+ide_toolchain_provider_default_init (IdeToolchainProviderInterface *iface)
+{
+ iface->load_async = ide_toolchain_provider_real_load_async;
+ iface->load_finish = ide_toolchain_provider_real_load_finish;
+ iface->unload = ide_toolchain_provider_real_unload;
+
+ /**
+ * IdeToolchainProvider:added:
+ * @self: an #IdeToolchainProvider
+ * @toolchain: an #IdeToolchain
+ *
+ * The "added" signal is emitted when a toolchain
+ * has been added to a toolchain provider.
+ *
+ * Since: 3.30
+ */
+ signals [ADDED] =
+ g_signal_new ("added",
+ G_TYPE_FROM_INTERFACE (iface),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (IdeToolchainProviderInterface, added),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__OBJECT,
+ G_TYPE_NONE, 1, IDE_TYPE_TOOLCHAIN);
+ g_signal_set_va_marshaller (signals [ADDED],
+ G_TYPE_FROM_INTERFACE (iface),
+ g_cclosure_marshal_VOID__OBJECTv);
+
+ /**
+ * IdeToolchainProvider:removed:
+ * @self: an #IdeToolchainProvider
+ * @toolchain: an #IdeToolchain
+ *
+ * The "removed" signal is emitted when a toolchain
+ * has been removed from a toolchain provider.
+ *
+ * Since: 3.30
+ */
+ signals [REMOVED] =
+ g_signal_new ("removed",
+ G_TYPE_FROM_INTERFACE (iface),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (IdeToolchainProviderInterface, removed),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__OBJECT,
+ G_TYPE_NONE, 1, IDE_TYPE_TOOLCHAIN);
+ g_signal_set_va_marshaller (signals [REMOVED],
+ G_TYPE_FROM_INTERFACE (iface),
+ g_cclosure_marshal_VOID__OBJECTv);
+
+}
+
+/**
+ * ide_toolchain_provider_load_async:
+ * @self: a #IdeToolchainProvider
+ * @manager: a #IdeToolchainManager
+ * @cancellable: (nullable): a #GCancellable or %NULL
+ * @callback: a callback to execute upon completion
+ * @user_data: closure data for @callback
+ *
+ * This function is called to initialize the toolchain provider after
+ * the plugin instance has been created. The provider should locate any
+ * toolchain within the project and call ide_toolchain_provider_emit_added()
+ * before completing the asynchronous function so that the toolchain
+ * manager may be made aware of the toolchains.
+ *
+ * Since: 3.28
+ */
+void
+ide_toolchain_provider_load_async (IdeToolchainProvider *self,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ g_return_if_fail (IDE_IS_TOOLCHAIN_PROVIDER (self));
+
+ IDE_TOOLCHAIN_PROVIDER_GET_IFACE (self)->load_async (self, cancellable, callback, user_data);
+}
+
+/**
+ * ide_toolchain_provider_load_finish:
+ * @self: a #IdeToolchainProvider
+ * @result: a #GAsyncResult
+ * @error: a location for a #GError, or %NULL
+ *
+ * Completes an asynchronous request to ide_toolchain_provider_load_async().
+ *
+ * Returns: %TRUE if successful; otherwise %FALSE and @error is set.
+ */
+gboolean
+ide_toolchain_provider_load_finish (IdeToolchainProvider *self,
+ GAsyncResult *result,
+ GError **error)
+{
+ g_return_val_if_fail (IDE_IS_MAIN_THREAD (), FALSE);
+ g_return_val_if_fail (IDE_IS_TOOLCHAIN_PROVIDER (self), FALSE);
+ g_return_val_if_fail (G_IS_ASYNC_RESULT (result), FALSE);
+
+ return IDE_TOOLCHAIN_PROVIDER_GET_IFACE (self)->load_finish (self, result, error);
+}
+
+/**
+ * ide_toolchain_provider_emit_added:
+ * @self: an #IdeToolchainProvider
+ * @toolchain: an #IdeToolchain
+ *
+ * #IdeToolchainProvider implementations should call this function with
+ * a @toolchain when it has discovered a new toolchain.
+ *
+ * Since: 3.30
+ */
+void
+ide_toolchain_provider_emit_added (IdeToolchainProvider *self,
+ IdeToolchain *toolchain)
+{
+ g_return_if_fail (IDE_IS_TOOLCHAIN_PROVIDER (self));
+ g_return_if_fail (IDE_IS_TOOLCHAIN (toolchain));
+
+ g_signal_emit (self, signals [ADDED], 0, toolchain);
+}
+
+/**
+ * ide_toolchain_provider_emit_removed:
+ * @self: an #IdeToolchainProvider
+ * @toolchain: an #IdeToolchain
+ *
+ * #IdeToolchainProvider implementations should call this function with
+ * a @toolchain when the toolchain was removed.
+ *
+ * Since: 3.30
+ */
+void
+ide_toolchain_provider_emit_removed (IdeToolchainProvider *self,
+ IdeToolchain *toolchain)
+{
+ g_return_if_fail (IDE_IS_TOOLCHAIN_PROVIDER (self));
+ g_return_if_fail (IDE_IS_TOOLCHAIN (toolchain));
+
+ g_signal_emit (self, signals [REMOVED], 0, toolchain);
+}
diff --git a/src/libide/toolchain/ide-toolchain-provider.h b/src/libide/toolchain/ide-toolchain-provider.h
index c5c4477f1..098ee3b63 100644
--- a/src/libide/toolchain/ide-toolchain-provider.h
+++ b/src/libide/toolchain/ide-toolchain-provider.h
@@ -35,17 +35,38 @@ struct _IdeToolchainProviderInterface
{
GTypeInterface parent_iface;
- void (*load) (IdeToolchainProvider *self,
- IdeToolchainManager *manager);
+ void (*load_async) (IdeToolchainProvider *self,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+ gboolean (*load_finish) (IdeToolchainProvider *self,
+ GAsyncResult *result,
+ GError **error);
void (*unload) (IdeToolchainProvider *self,
IdeToolchainManager *manager);
+ void (*added) (IdeToolchainProvider *self,
+ IdeToolchain *toolchain);
+ void (*removed) (IdeToolchainProvider *self,
+ IdeToolchain *toolchain);
};
IDE_AVAILABLE_IN_3_30
-void ide_toolchain_provider_load (IdeToolchainProvider *self,
- IdeToolchainManager *manager);
+void ide_toolchain_provider_load_async (IdeToolchainProvider *self,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+IDE_AVAILABLE_IN_3_30
+gboolean ide_toolchain_provider_load_finish (IdeToolchainProvider *self,
+ GAsyncResult *result,
+ GError **error);
IDE_AVAILABLE_IN_3_30
-void ide_toolchain_provider_unload (IdeToolchainProvider *self,
- IdeToolchainManager *manager);
+void ide_toolchain_provider_unload (IdeToolchainProvider *self,
+ IdeToolchainManager *manager);
+IDE_AVAILABLE_IN_3_28
+void ide_toolchain_provider_emit_added (IdeToolchainProvider *self,
+ IdeToolchain *toolchain);
+IDE_AVAILABLE_IN_3_28
+void ide_toolchain_provider_emit_removed (IdeToolchainProvider *self,
+ IdeToolchain *toolchain);
G_END_DECLS
diff --git a/src/plugins/cmake/gbp-cmake-toolchain-provider.c
b/src/plugins/cmake/gbp-cmake-toolchain-provider.c
index 9db68fe62..84fd069ec 100644
--- a/src/plugins/cmake/gbp-cmake-toolchain-provider.c
+++ b/src/plugins/cmake/gbp-cmake-toolchain-provider.c
@@ -26,170 +26,168 @@
struct _GbpCMakeToolchainProvider
{
IdeObject parent_instance;
- IdeToolchainManager *manager;
- GCancellable *loading_cancellable;
+ GPtrArray *toolchains;
};
-void
-cmake_toolchain_provider_search_folder (GbpCMakeToolchainProvider *self,
- GFile *file);
-
-
static void
-gbp_cmake_toolchain_verify_async_cb (GObject *object,
- GAsyncResult *result,
- gpointer user_data)
-{
- GbpCMakeToolchain *toolchain = (GbpCMakeToolchain *)object;
- GbpCMakeToolchainProvider *provider = user_data;
- g_autoptr(GError) error = NULL;
-
- IDE_ENTRY;
-
- g_assert (GBP_IS_CMAKE_TOOLCHAIN (toolchain));
- g_assert (GBP_IS_CMAKE_TOOLCHAIN_PROVIDER (provider));
-
- if (!gbp_cmake_toolchain_verify_finish (toolchain, result, &error))
- IDE_EXIT;
-
- ide_toolchain_manager_add (provider->manager, IDE_TOOLCHAIN (toolchain));
- IDE_EXIT;
-}
-
-void
-cmake_toolchain_provider_add_crossfile (GbpCMakeToolchainProvider *self,
- GFile *file)
+gbp_cmake_toolchain_provider_load_worker (IdeTask *task,
+ gpointer source_object,
+ gpointer task_data,
+ GCancellable *cancellable)
{
+ GbpCMakeToolchainProvider *self = source_object;
+ g_autoptr(GPtrArray) toolchains = NULL;
IdeContext *context;
- g_autoptr(GbpCMakeToolchain) toolchain = NULL;
+ GPtrArray *files = task_data;
+ g_assert (IDE_IS_TASK (task));
g_assert (GBP_IS_CMAKE_TOOLCHAIN_PROVIDER (self));
- g_assert (G_IS_FILE (file));
+ g_assert (files != NULL);
+ g_assert (!cancellable || G_IS_CANCELLABLE (cancellable));
- context = ide_object_get_context (IDE_OBJECT (self->manager));
- toolchain = gbp_cmake_toolchain_new (context, file);
+ context = ide_object_get_context (IDE_OBJECT (self));
+ toolchains = g_ptr_array_new_with_free_func (g_object_unref);
- gbp_cmake_toolchain_verify_async (g_steal_pointer (&toolchain), NULL, gbp_cmake_toolchain_verify_async_cb,
self);
-}
-
-void
-cmake_toolchain_enumerate_children_cb (GObject *object,
- GAsyncResult *result,
- gpointer user_data)
-{
- GbpCMakeToolchainProvider *self = (GbpCMakeToolchainProvider *)user_data;
- GFile *dir = (GFile *)object;
- g_autoptr(GError) error = NULL;
- g_autoptr(GPtrArray) infos = NULL;
-
- g_assert (G_IS_FILE (dir));
- g_assert (G_IS_ASYNC_RESULT (result));
- g_assert (GBP_IS_CMAKE_TOOLCHAIN_PROVIDER (self));
-
- infos = ide_g_file_get_children_finish (dir, result, &error);
-
- if (infos == NULL)
- return;
-
- for (guint i = 0; i < infos->len; i++)
+ for (guint i = 0; i < files->len; i++)
{
- GFileInfo *file_info = g_ptr_array_index (infos, i);
- GFileType file_type = g_file_info_get_file_type (file_info);
+ GFile *file = g_ptr_array_index (files, i);
+ g_autofree gchar *name = NULL;
- if (file_type == G_FILE_TYPE_REGULAR)
+ g_assert (G_IS_FILE (file));
+
+ name = g_file_get_basename (file);
+ /* Cross-compilation files have .cmake extension, we have to blacklist CMakeSystem.cmake
+ * in case we are looking into a build folder */
+ if (g_strcmp0(name, "CMakeSystem.cmake") != 0)
{
- const gchar *name = g_file_info_get_name (file_info);
- /* Cross-compilation files have .cmake extension, we have to blacklist CMakeSystem.cmake
- * in case we are looking into a build folder */
- if (g_str_has_suffix (name, ".cmake") && g_strcmp0(name, "CMakeSystem.cmake") != 0)
+ g_autoptr(GError) file_error = NULL;
+ g_autofree gchar *file_path = g_file_get_path (file);
+ g_autofree gchar *file_contents = NULL;
+ gsize file_contents_len;
+
+ /* Cross-compilation files should at least define CMAKE_SYSTEM_NAME and CMAKE_SYSTEM_PROCESSOR */
+ if (g_file_get_contents (file_path,
+ &file_contents, &file_contents_len, &file_error))
{
- const gchar *content_type = g_file_info_get_content_type (file_info);
-
- if (g_content_type_is_mime_type (content_type, "text/x-cmake"))
+ const gchar *system_name = g_strstr_len (file_contents,
+ file_contents_len,
+ "CMAKE_SYSTEM_NAME");
+ if (system_name != NULL)
{
- g_autoptr(GFile) child = g_file_get_child (dir, name);
- g_autoptr(GError) file_error = NULL;
- g_autofree gchar *file_path = g_file_get_path (child);
- g_autofree gchar *file_contents = NULL;
- gsize file_contents_len;
-
- /* Cross-compilation files should at least define CMAKE_SYSTEM_NAME and
CMAKE_SYSTEM_PROCESSOR */
- if (g_file_get_contents (file_path,
- &file_contents, &file_contents_len, &file_error))
+ const gchar *processor_name = g_strstr_len (file_contents,
+ file_contents_len,
+ "CMAKE_SYSTEM_PROCESSOR");
+ if (processor_name != NULL)
{
- const gchar *system_name = g_strstr_len (file_contents,
- file_contents_len,
- "CMAKE_SYSTEM_NAME");
- if (system_name != NULL)
- {
- const gchar *processor_name = g_strstr_len (file_contents,
- file_contents_len,
- "CMAKE_SYSTEM_PROCESSOR");
- if (processor_name != NULL)
- {
- cmake_toolchain_provider_add_crossfile (self, child);
- }
- }
+ g_autoptr(GbpCMakeToolchain) toolchain = gbp_cmake_toolchain_new (context, file);
+ if (gbp_cmake_toolchain_verify (toolchain))
+ g_ptr_array_add (toolchains, g_steal_pointer (&toolchain));
}
}
- }
- }
- else if (file_type == G_FILE_TYPE_DIRECTORY)
- {
- const gchar *name = g_file_info_get_name (file_info);
- g_autoptr(GFile) child = g_file_get_child (dir, name);
-
- cmake_toolchain_provider_search_folder (self, child);
+ }
}
}
+
+ ide_task_return_pointer (task,
+ g_steal_pointer (&toolchains),
+ (GDestroyNotify)g_ptr_array_unref);
}
-void
-cmake_toolchain_provider_search_folder (GbpCMakeToolchainProvider *self,
- GFile *file)
+static void
+load_find_files_cb (GObject *object,
+ GAsyncResult *result,
+ gpointer user_data)
{
- g_assert (GBP_IS_CMAKE_TOOLCHAIN_PROVIDER (self));
+ GFile *file = (GFile *)object;
+ g_autoptr(IdeTask) task = user_data;
+ g_autoptr(GError) error = NULL;
+ g_autoptr(GPtrArray) ret = NULL;
+
g_assert (G_IS_FILE (file));
+ g_assert (G_IS_ASYNC_RESULT (result));
+ g_assert (IDE_IS_TASK (task));
+
+ ret = ide_g_file_find_finish (file, result, &error);
+ IDE_PTR_ARRAY_SET_FREE_FUNC (ret, g_object_unref);
- ide_g_file_get_children_async (file,
- G_FILE_ATTRIBUTE_STANDARD_NAME","
- G_FILE_ATTRIBUTE_STANDARD_TYPE","
- G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE,
- G_FILE_QUERY_INFO_NONE,
- G_PRIORITY_LOW,
- self->loading_cancellable,
- cmake_toolchain_enumerate_children_cb,
- self);
+ if (ret == NULL)
+ {
+ ide_task_return_error (task, g_steal_pointer (&error));
+ return;
+ }
+
+ ide_task_set_task_data (task, g_steal_pointer (&ret), (GDestroyNotify)g_ptr_array_unref);
+ ide_task_run_in_thread (task, gbp_cmake_toolchain_provider_load_worker);
}
-void
-gbp_cmake_toolchain_provider_load (IdeToolchainProvider *provider,
- IdeToolchainManager *manager)
+static void
+gbp_cmake_toolchain_provider_load_async (IdeToolchainProvider *provider,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
{
- GbpCMakeToolchainProvider *self = (GbpCMakeToolchainProvider *) provider;
+ GbpCMakeToolchainProvider *self = (GbpCMakeToolchainProvider *)provider;
+ g_autoptr(IdeTask) task = NULL;
IdeContext *context;
- g_autoptr(GFile) project_folder = NULL;
+ IdeVcs *vcs;
+ GFile *workdir;
IDE_ENTRY;
+ g_assert (IDE_IS_MAIN_THREAD ());
g_assert (GBP_IS_CMAKE_TOOLCHAIN_PROVIDER (self));
- g_assert (IDE_IS_TOOLCHAIN_MANAGER (manager));
+ g_assert (!cancellable || G_IS_CANCELLABLE (cancellable));
- self->manager = g_object_ref (manager);
+ context = ide_object_get_context (IDE_OBJECT (self));
+ vcs = ide_context_get_vcs (context);
+ workdir = ide_vcs_get_working_directory (vcs);
- context = ide_object_get_context (IDE_OBJECT (manager));
- g_return_if_fail (IDE_IS_CONTEXT (context));
- if (!GBP_IS_CMAKE_BUILD_SYSTEM (ide_context_get_build_system (context)))
- return;
+ task = ide_task_new (provider, cancellable, callback, user_data);
+ ide_task_set_source_tag (task, gbp_cmake_toolchain_provider_load_async);
+ ide_task_set_priority (task, G_PRIORITY_LOW);
- self->loading_cancellable = g_cancellable_new ();
-
- project_folder = g_file_get_parent (ide_context_get_project_file (context));
- cmake_toolchain_provider_search_folder (self, project_folder);
+ ide_g_file_find_async (workdir,
+ "*.cmake",
+ cancellable,
+ load_find_files_cb,
+ g_steal_pointer (&task));
IDE_EXIT;
}
+static gboolean
+gbp_cmake_toolchain_provider_load_finish (IdeToolchainProvider *provider,
+ GAsyncResult *result,
+ GError **error)
+{
+ GbpCMakeToolchainProvider *self = (GbpCMakeToolchainProvider *)provider;
+ g_autoptr(GPtrArray) toolchains = NULL;
+
+ g_assert (IDE_IS_MAIN_THREAD ());
+ g_assert (GBP_IS_CMAKE_TOOLCHAIN_PROVIDER (self));
+ g_assert (IDE_IS_TASK (result));
+ g_assert (ide_task_is_valid (IDE_TASK (result), provider));
+
+ toolchains = ide_task_propagate_pointer (IDE_TASK (result), error);
+
+ if (toolchains == NULL)
+ return FALSE;
+
+ g_clear_pointer (&self->toolchains, g_ptr_array_unref);
+ self->toolchains = g_ptr_array_ref (toolchains);
+
+ for (guint i = 0; i < toolchains->len; i++)
+ {
+ IdeToolchain *toolchain = g_ptr_array_index (toolchains, i);
+
+ g_assert (IDE_IS_TOOLCHAIN (toolchain));
+
+ ide_toolchain_provider_emit_added (provider, toolchain);
+ }
+
+ return TRUE;
+}
+
void
gbp_cmake_toolchain_provider_unload (IdeToolchainProvider *provider,
IdeToolchainManager *manager)
@@ -199,13 +197,14 @@ gbp_cmake_toolchain_provider_unload (IdeToolchainProvider *provider,
g_assert (GBP_IS_CMAKE_TOOLCHAIN_PROVIDER (self));
g_assert (IDE_IS_TOOLCHAIN_MANAGER (manager));
- g_clear_object (&self->manager);
+ g_clear_pointer (&self->toolchains, g_ptr_array_unref);
}
static void
toolchain_provider_iface_init (IdeToolchainProviderInterface *iface)
{
- iface->load = gbp_cmake_toolchain_provider_load;
+ iface->load_async = gbp_cmake_toolchain_provider_load_async;
+ iface->load_finish = gbp_cmake_toolchain_provider_load_finish;
iface->unload = gbp_cmake_toolchain_provider_unload;
}
diff --git a/src/plugins/cmake/gbp-cmake-toolchain.c b/src/plugins/cmake/gbp-cmake-toolchain.c
index 339ddfe04..5b13400c7 100644
--- a/src/plugins/cmake/gbp-cmake-toolchain.c
+++ b/src/plugins/cmake/gbp-cmake-toolchain.c
@@ -31,6 +31,7 @@ struct _GbpCMakeToolchain
gchar *archiver;
gchar *pkg_config;
GHashTable *compilers;
+ GCancellable *verify_cancellable;
};
G_DEFINE_TYPE (GbpCMakeToolchain, gbp_cmake_toolchain, IDE_TYPE_TOOLCHAIN)
@@ -190,13 +191,11 @@ gbp_cmake_toolchain_get_tool_for_language (IdeToolchain *toolchain,
return NULL;
}
-static void
-gbp_cmake_toolchain_verify_worker (IdeTask *task,
- gpointer source_object,
- gpointer task_data,
- GCancellable *cancellable)
+/* It is far easier and more reliable to get the variables from cmake itself,
+ * Here is a small projects that exports the content of the cross-file */
+gboolean
+gbp_cmake_toolchain_verify (GbpCMakeToolchain *self)
{
- GbpCMakeToolchain *self = source_object;
g_autoptr(GError) error = NULL;
g_autofree gchar *tmp_dir = NULL;
g_autofree gchar *toolchain_arg = NULL;
@@ -205,7 +204,10 @@ gbp_cmake_toolchain_verify_worker (IdeTask *task,
g_assert (GBP_IS_CMAKE_TOOLCHAIN (self));
- tmp_dir = _gbp_cmake_toolchain_deploy_temporary_cmake (cancellable);
+ g_clear_object (&self->verify_cancellable);
+ self->verify_cancellable = g_cancellable_new ();
+
+ tmp_dir = _gbp_cmake_toolchain_deploy_temporary_cmake (self->verify_cancellable);
toolchain_arg = g_strdup_printf ("-DCMAKE_TOOLCHAIN_FILE=%s", self->file_path);
cmake_launcher = ide_subprocess_launcher_new
(G_SUBPROCESS_FLAGS_STDOUT_SILENCE|G_SUBPROCESS_FLAGS_STDERR_SILENCE);
@@ -213,66 +215,20 @@ gbp_cmake_toolchain_verify_worker (IdeTask *task,
ide_subprocess_launcher_push_argv (cmake_launcher, ".");
ide_subprocess_launcher_push_argv (cmake_launcher, toolchain_arg);
ide_subprocess_launcher_set_cwd (cmake_launcher, tmp_dir);
- cmake_subprocess = ide_subprocess_launcher_spawn (cmake_launcher, cancellable, &error);
- if (!ide_subprocess_wait_check (cmake_subprocess, cancellable, &error))
+ cmake_subprocess = ide_subprocess_launcher_spawn (cmake_launcher, self->verify_cancellable, &error);
+ if (!ide_subprocess_wait_check (cmake_subprocess, self->verify_cancellable, &error))
{
- ide_task_return_new_error (task,
- G_IO_ERROR,
- G_IO_ERROR_INVALID_FILENAME,
- "Error Testing CMake Cross-compilation file : %s",
- self->file_path);
+ g_debug ("Error Testing CMake Cross-compilation file : %s", self->file_path);
return;
}
if (!_gbp_cmake_toolchain_parse_keyfile (self, tmp_dir))
{
- ide_task_return_new_error (task,
- G_IO_ERROR,
- G_IO_ERROR_INVALID_FILENAME,
- "Error Testing CMake Cross-compilation file : %s",
- self->file_path);
+ g_debug ("Error Testing CMake Cross-compilation file : %s", self->file_path);
return;
}
- ide_task_return_boolean (task, TRUE);
-}
-
-/* It is far easier and more reliable to get the variables from cmake itself,
- * Here is a small projects that exports the content of the cross-file */
-void
-gbp_cmake_toolchain_verify_async (GbpCMakeToolchain *self,
- GCancellable *cancellable,
- GAsyncReadyCallback callback,
- gpointer user_data)
-{
- g_autoptr(IdeTask) task = NULL;
-
- IDE_ENTRY;
-
- g_assert (GBP_IS_CMAKE_TOOLCHAIN (self));
- g_assert (!cancellable || G_IS_CANCELLABLE (cancellable));
-
- task = ide_task_new (self, cancellable, callback, user_data);
- ide_task_run_in_thread (task, gbp_cmake_toolchain_verify_worker);
-
- IDE_EXIT;
-}
-
-gboolean
-gbp_cmake_toolchain_verify_finish (GbpCMakeToolchain *self,
- GAsyncResult *result,
- GError **error)
-{
- IdeTask *task = (IdeTask *)result;
- gboolean ret;
-
- IDE_ENTRY;
-
- g_return_val_if_fail (GBP_IS_CMAKE_TOOLCHAIN (self), FALSE);
-
- ret = ide_task_propagate_boolean (task, error);
-
- IDE_RETURN (ret);
+ return TRUE;
}
static void
diff --git a/src/plugins/cmake/gbp-cmake-toolchain.h b/src/plugins/cmake/gbp-cmake-toolchain.h
index d19e9874c..f886e4c44 100644
--- a/src/plugins/cmake/gbp-cmake-toolchain.h
+++ b/src/plugins/cmake/gbp-cmake-toolchain.h
@@ -32,12 +32,6 @@ GbpCMakeToolchain *gbp_cmake_toolchain_new (IdeContext *con
const gchar *gbp_cmake_toolchain_get_file_path (GbpCMakeToolchain *self);
void gbp_cmake_toolchain_set_file_path (GbpCMakeToolchain *self,
const gchar *file_path);
-void gbp_cmake_toolchain_verify_async (GbpCMakeToolchain *self,
- GCancellable *cancellable,
- GAsyncReadyCallback callback,
- gpointer user_data);
-gboolean gbp_cmake_toolchain_verify_finish (GbpCMakeToolchain *self,
- GAsyncResult *result,
- GError **error);
+gboolean gbp_cmake_toolchain_verify (GbpCMakeToolchain *self);
G_END_DECLS
diff --git a/src/plugins/meson/gbp-meson-toolchain-provider.c
b/src/plugins/meson/gbp-meson-toolchain-provider.c
index 9be994ab0..1199faf6d 100644
--- a/src/plugins/meson/gbp-meson-toolchain-provider.c
+++ b/src/plugins/meson/gbp-meson-toolchain-provider.c
@@ -26,147 +26,247 @@
struct _GbpMesonToolchainProvider
{
IdeObject parent_instance;
- IdeToolchainManager *manager;
- GCancellable *loading_cancellable;
+ GPtrArray *toolchains;
};
-void
-meson_toolchain_provider_search_folder (GbpMesonToolchainProvider *self,
- GFile *file);
-
-void
-meson_toolchain_provider_add_crossfile (GbpMesonToolchainProvider *self,
- GFile *file)
+typedef struct
{
- IdeContext *context;
- g_autoptr(GbpMesonToolchain) toolchain = NULL;
-
- g_assert (GBP_IS_MESON_TOOLCHAIN_PROVIDER (self));
- g_assert (G_IS_FILE (file));
+ GList *folders;
+ GPtrArray *found_files;
+ IdeTask *task;
+} FileSearching;
- context = ide_object_get_context (IDE_OBJECT (self->manager));
- toolchain = gbp_meson_toolchain_new (context, file);
- ide_toolchain_manager_add (self->manager, IDE_TOOLCHAIN (toolchain));
-}
-void
-meson_toolchain_enumerate_children_cb (GObject *object,
- GAsyncResult *result,
- gpointer user_data)
+static void
+gbp_meson_toolchain_provider_load_worker (IdeTask *task,
+ gpointer source_object,
+ gpointer task_data,
+ GCancellable *cancellable)
{
- GbpMesonToolchainProvider *self = (GbpMesonToolchainProvider *)user_data;
- GFile *dir = (GFile *)object;
- g_autoptr(GError) error = NULL;
- g_autoptr(GPtrArray) infos = NULL;
+ GbpMesonToolchainProvider *self = source_object;
+ g_autoptr(GPtrArray) toolchains = NULL;
+ IdeContext *context;
+ GPtrArray *files = task_data;
- g_assert (G_IS_FILE (dir));
- g_assert (G_IS_ASYNC_RESULT (result));
+ g_assert (IDE_IS_TASK (task));
g_assert (GBP_IS_MESON_TOOLCHAIN_PROVIDER (self));
+ g_assert (files != NULL);
+ g_assert (!cancellable || G_IS_CANCELLABLE (cancellable));
- infos = ide_g_file_get_children_finish (dir, result, &error);
+ context = ide_object_get_context (IDE_OBJECT (self));
+ toolchains = g_ptr_array_new_with_free_func (g_object_unref);
- if (infos == NULL)
- return;
-
- for (guint i = 0; i < infos->len; i++)
+ for (guint i = 0; i < files->len; i++)
{
- GFileInfo *file_info = g_ptr_array_index (infos, i);
- GFileType file_type = g_file_info_get_file_type (file_info);
-
- if (file_type == G_FILE_TYPE_REGULAR)
+ GFile *file = g_ptr_array_index (files, i);
+ g_autoptr(GFileInfo) file_info = NULL;
+ g_autoptr(GError) file_error = NULL;
+ const gchar *content_type;
+
+ g_assert (G_IS_FILE (file));
+
+ file_info = g_file_query_info (file,
+ G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE,
+ G_FILE_QUERY_INFO_NONE,
+ cancellable,
+ &file_error);
+ content_type = g_file_info_get_content_type (file_info);
+ if (g_content_type_is_mime_type (content_type, "text/plain"))
{
- const gchar *content_type = g_file_info_get_content_type (file_info);
+ g_autoptr(GKeyFile) keyfile = g_key_file_new ();
+ g_autofree gchar *path = g_file_get_path (file);
+ g_autoptr(GError) keyfile_error = NULL;
- if (g_content_type_is_mime_type (content_type, "text/plain"))
+ if (g_key_file_load_from_file (keyfile, path, G_KEY_FILE_NONE, &keyfile_error))
{
- const gchar *name = g_file_info_get_name (file_info);
- g_autoptr(GFile) child = g_file_get_child (dir, name);
- g_autoptr(GKeyFile) keyfile = g_key_file_new ();
- g_autofree gchar *path = g_file_get_path (child);
- g_autoptr(GError) keyfile_error = NULL;
-
- if (g_key_file_load_from_file (keyfile, path, G_KEY_FILE_NONE, &keyfile_error))
+ if (g_key_file_has_group (keyfile, "binaries") &&
+ (g_key_file_has_group (keyfile, "host_machine") ||
+ g_key_file_has_group (keyfile, "target_machine")))
{
- if (g_key_file_has_group (keyfile, "binaries") &&
- (g_key_file_has_group (keyfile, "host_machine") ||
- g_key_file_has_group (keyfile, "target_machine")))
- meson_toolchain_provider_add_crossfile (self, child);
+ g_autoptr(GbpMesonToolchain) toolchain = gbp_meson_toolchain_new (context, file);
+ g_ptr_array_add (toolchains, g_steal_pointer (&toolchain));
}
}
}
- else if (file_type == G_FILE_TYPE_DIRECTORY)
- {
- const gchar *name = g_file_info_get_name (file_info);
- g_autoptr(GFile) child = g_file_get_child (dir, name);
+ }
- meson_toolchain_provider_search_folder (self, child);
- }
+ ide_task_return_pointer (task,
+ g_steal_pointer (&toolchains),
+ (GDestroyNotify)g_ptr_array_unref);
+}
+
+void
+meson_toolchain_provider_search_finish (FileSearching *file_searching, GError *error)
+{
+ g_autoptr(IdeTask) task = NULL;
+ g_autoptr(GPtrArray) ret = NULL;
+
+ task = file_searching->task;
+ ret = file_searching->found_files;
+ g_list_free_full (file_searching->folders, g_object_unref);
+ g_slice_free (FileSearching, file_searching);
+
+ if (error != NULL)
+ {
+ ide_task_return_error (task, error);
+ return;
}
+
+ ide_task_set_task_data (task, g_steal_pointer (&ret), (GDestroyNotify)g_ptr_array_unref);
+ ide_task_run_in_thread (task, gbp_meson_toolchain_provider_load_worker);
}
void
-meson_toolchain_provider_search_folder (GbpMesonToolchainProvider *self,
- GFile *file)
+add_all_files (GFile *array, GPtrArray *dest_array)
{
- g_assert (GBP_IS_MESON_TOOLCHAIN_PROVIDER (self));
+ g_assert (G_IS_FILE (array));
+ g_assert (dest_array != NULL);
+ g_ptr_array_add (dest_array, g_object_ref (array));
+}
+
+void
+meson_toolchain_provider_search_iterate (GObject *object,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ GFile *file = (GFile *)object;
+ g_autoptr(GError) error = NULL;
+ g_autoptr(GPtrArray) ret = NULL;
+ FileSearching *file_searching = user_data;
+
g_assert (G_IS_FILE (file));
+ g_assert (G_IS_ASYNC_RESULT (result));
+ g_assert (file_searching != NULL);
+ g_assert (IDE_IS_TASK (file_searching->task));
+
+ ret = ide_g_file_find_finish (file, result, &error);
+ IDE_PTR_ARRAY_SET_FREE_FUNC (ret, g_object_unref);
+
+ if (ret == NULL)
+ {
+ meson_toolchain_provider_search_finish (file_searching, g_steal_pointer (&error));
+ return;
+ }
- ide_g_file_get_children_async (file,
- G_FILE_ATTRIBUTE_STANDARD_NAME","
- G_FILE_ATTRIBUTE_STANDARD_TYPE","
- G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE,
- G_FILE_QUERY_INFO_NONE,
- G_PRIORITY_LOW,
- self->loading_cancellable,
- meson_toolchain_enumerate_children_cb,
- self);
+ g_ptr_array_foreach (ret, (GFunc)add_all_files, file_searching->found_files);
+ file_searching->folders = g_list_remove (file_searching->folders, file);
+ if (file_searching->folders != NULL)
+ {
+ ide_g_file_find_async (file_searching->folders->data,
+ "*",
+ ide_task_get_cancellable (file_searching->task),
+ meson_toolchain_provider_search_iterate,
+ file_searching);
+ }
+ else
+ {
+ meson_toolchain_provider_search_finish (file_searching, NULL);
+ }
}
void
-gbp_meson_toolchain_provider_load (IdeToolchainProvider *provider,
- IdeToolchainManager *manager)
+meson_toolchain_provider_search_init (GbpMesonToolchainProvider *self,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
{
- GbpMesonToolchainProvider *self = (GbpMesonToolchainProvider *) provider;
- IdeContext *context;
- const gchar * const *system_data_dirs;
+ GList *folders = NULL;
g_autoptr(GFile) project_folder = NULL;
- g_autoptr(GFile) user_folder = NULL;
+ g_autoptr (IdeTask) task = NULL;
g_autofree gchar *user_folder_path = NULL;
-
- IDE_ENTRY;
+ const gchar * const *system_data_dirs;
+ IdeContext *context;
+ FileSearching *file_searching;
g_assert (GBP_IS_MESON_TOOLCHAIN_PROVIDER (self));
- g_assert (IDE_IS_TOOLCHAIN_MANAGER (manager));
-
- self->manager = g_object_ref (manager);
-
- context = ide_object_get_context (IDE_OBJECT (manager));
- g_return_if_fail (IDE_IS_CONTEXT (context));
- if (!GBP_IS_MESON_BUILD_SYSTEM (ide_context_get_build_system (context)))
- return;
- self->loading_cancellable = g_cancellable_new ();
+ context = ide_object_get_context (IDE_OBJECT (self));
- /* Starting with version 0.44.0, Meson supported embedded cross-files */
system_data_dirs = g_get_system_data_dirs ();
for (gint i = 0; system_data_dirs[i] != NULL; i++)
{
g_autofree gchar *subfolder = g_build_filename (system_data_dirs[i], "meson", "cross", NULL);
- g_autoptr(GFile) file = g_file_new_for_path (subfolder);
- meson_toolchain_provider_search_folder (self, file);
+ folders = g_list_append (folders, g_file_new_for_path (subfolder));
}
user_folder_path = g_build_filename (g_get_user_data_dir (), "meson", "cross", NULL);
- user_folder = g_file_new_for_path (user_folder_path);
- meson_toolchain_provider_search_folder (self, user_folder);
+ folders = g_list_append (folders, g_file_new_for_path (user_folder_path));
project_folder = g_file_get_parent (ide_context_get_project_file (context));
- meson_toolchain_provider_search_folder (self, project_folder);
+ folders = g_list_append (folders, g_steal_pointer(&project_folder));
+
+ task = ide_task_new (self, cancellable, callback, user_data);
+ ide_task_set_source_tag (task, meson_toolchain_provider_search_init);
+ ide_task_set_priority (task, G_PRIORITY_LOW);
+
+ file_searching = g_slice_new0 (FileSearching);
+ file_searching->task = g_steal_pointer (&task);
+ file_searching->folders = folders;
+ file_searching->found_files = g_ptr_array_new ();
+ IDE_PTR_ARRAY_SET_FREE_FUNC (file_searching->found_files, g_object_unref);
+
+ /* Unfortunately there is no file extension for this */
+ ide_g_file_find_async (g_list_first (folders)->data,
+ "*",
+ cancellable,
+ meson_toolchain_provider_search_iterate,
+ file_searching);
+}
+
+static void
+gbp_meson_toolchain_provider_load_async (IdeToolchainProvider *provider,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ GbpMesonToolchainProvider *self = (GbpMesonToolchainProvider *)provider;
+ g_autoptr(IdeTask) task = NULL;
+
+ IDE_ENTRY;
+
+ g_assert (IDE_IS_MAIN_THREAD ());
+ g_assert (GBP_IS_MESON_TOOLCHAIN_PROVIDER (self));
+ g_assert (!cancellable || G_IS_CANCELLABLE (cancellable));
+
+ meson_toolchain_provider_search_init (self, cancellable, callback, user_data);
IDE_EXIT;
}
+static gboolean
+gbp_meson_toolchain_provider_load_finish (IdeToolchainProvider *provider,
+ GAsyncResult *result,
+ GError **error)
+{
+ GbpMesonToolchainProvider *self = (GbpMesonToolchainProvider *)provider;
+ g_autoptr(GPtrArray) toolchains = NULL;
+
+ g_assert (IDE_IS_MAIN_THREAD ());
+ g_assert (GBP_IS_MESON_TOOLCHAIN_PROVIDER (self));
+ g_assert (IDE_IS_TASK (result));
+ g_assert (ide_task_is_valid (IDE_TASK (result), provider));
+
+ toolchains = ide_task_propagate_pointer (IDE_TASK (result), error);
+
+ if (toolchains == NULL)
+ return FALSE;
+
+ g_clear_pointer (&self->toolchains, g_ptr_array_unref);
+ self->toolchains = g_ptr_array_ref (toolchains);
+
+ for (guint i = 0; i < toolchains->len; i++)
+ {
+ IdeToolchain *toolchain = g_ptr_array_index (toolchains, i);
+
+ g_assert (IDE_IS_TOOLCHAIN (toolchain));
+
+ ide_toolchain_provider_emit_added (provider, toolchain);
+ }
+
+ return TRUE;
+}
+
void
gbp_meson_toolchain_provider_unload (IdeToolchainProvider *provider,
IdeToolchainManager *manager)
@@ -176,13 +276,14 @@ gbp_meson_toolchain_provider_unload (IdeToolchainProvider *provider,
g_assert (GBP_IS_MESON_TOOLCHAIN_PROVIDER (self));
g_assert (IDE_IS_TOOLCHAIN_MANAGER (manager));
- g_clear_object (&self->manager);
+ g_clear_pointer (&self->toolchains, g_ptr_array_unref);
}
static void
toolchain_provider_iface_init (IdeToolchainProviderInterface *iface)
{
- iface->load = gbp_meson_toolchain_provider_load;
+ iface->load_async = gbp_meson_toolchain_provider_load_async;
+ iface->load_finish = gbp_meson_toolchain_provider_load_finish;
iface->unload = gbp_meson_toolchain_provider_unload;
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]