[gnome-builder/wip/gtk4-port: 1571/1774] libide/foundry: couple deploy strategy to pipelines
- From: Christian Hergert <chergert src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-builder/wip/gtk4-port: 1571/1774] libide/foundry: couple deploy strategy to pipelines
- Date: Mon, 11 Jul 2022 22:31:50 +0000 (UTC)
commit 8eded4156aaee98768cf7039e08929debb0f6b37
Author: Christian Hergert <chergert redhat com>
Date: Fri Jun 17 14:41:09 2022 -0700
libide/foundry: couple deploy strategy to pipelines
This also adds a new local deploy strategy so that we can always go
through a deploy strategy for running. That can simplify divergence in
how things run, even if it's just pass-through.
Once this is in place, we can start looking at replacing the whole
IdeRunner infrastructure with something simpler.
src/libide/foundry/ide-build-manager.c | 1 +
src/libide/foundry/ide-build-system.c | 1 +
src/libide/foundry/ide-deploy-strategy.c | 21 +-
src/libide/foundry/ide-deploy-strategy.h | 56 ++--
src/libide/foundry/ide-device-manager.c | 310 +++-------------------
src/libide/foundry/ide-local-deploy-strategy.c | 217 +++++++++++++++
src/libide/foundry/ide-local-deploy-strategy.h | 33 +++
src/libide/foundry/ide-pipeline.c | 136 ++++++++--
src/libide/foundry/ide-pipeline.h | 12 +-
src/libide/foundry/meson.build | 2 +
src/plugins/deviced/gbp-deviced-deploy-strategy.c | 14 +-
11 files changed, 464 insertions(+), 339 deletions(-)
---
diff --git a/src/libide/foundry/ide-build-manager.c b/src/libide/foundry/ide-build-manager.c
index e52893ef3..1c6f3405a 100644
--- a/src/libide/foundry/ide-build-manager.c
+++ b/src/libide/foundry/ide-build-manager.c
@@ -48,6 +48,7 @@
#include "ide-runtime.h"
#include "ide-toolchain-manager.h"
#include "ide-toolchain-private.h"
+#include "ide-triplet.h"
/**
* SECTION:ide-build-manager
diff --git a/src/libide/foundry/ide-build-system.c b/src/libide/foundry/ide-build-system.c
index 9c3d5b4ac..76cb20297 100644
--- a/src/libide/foundry/ide-build-system.c
+++ b/src/libide/foundry/ide-build-system.c
@@ -37,6 +37,7 @@
#include "ide-config.h"
#include "ide-device.h"
#include "ide-foundry-compat.h"
+#include "ide-runtime.h"
#include "ide-toolchain.h"
G_DEFINE_INTERFACE (IdeBuildSystem, ide_build_system, IDE_TYPE_OBJECT)
diff --git a/src/libide/foundry/ide-deploy-strategy.c b/src/libide/foundry/ide-deploy-strategy.c
index 4fde25c92..1e0bbd45d 100644
--- a/src/libide/foundry/ide-deploy-strategy.c
+++ b/src/libide/foundry/ide-deploy-strategy.c
@@ -29,7 +29,7 @@ G_DEFINE_ABSTRACT_TYPE (IdeDeployStrategy, ide_deploy_strategy, IDE_TYPE_OBJECT)
static void
ide_deploy_strategy_real_load_async (IdeDeployStrategy *self,
- IdePipeline *pipeline,
+ IdePipeline *pipeline,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data)
@@ -45,18 +45,21 @@ ide_deploy_strategy_real_load_async (IdeDeployStrategy *self,
static gboolean
ide_deploy_strategy_real_load_finish (IdeDeployStrategy *self,
GAsyncResult *result,
+ int *priority,
GError **error)
{
g_assert (IDE_IS_DEPLOY_STRATEGY (self));
g_assert (G_IS_TASK (result));
g_assert (g_task_is_valid (G_TASK (result), self));
+ *priority = G_MAXINT;
+
return g_task_propagate_boolean (G_TASK (result), error);
}
static void
ide_deploy_strategy_real_deploy_async (IdeDeployStrategy *self,
- IdePipeline *pipeline,
+ IdePipeline *pipeline,
GFileProgressCallback progress,
gpointer progress_data,
GDestroyNotify progress_data_destroy,
@@ -114,7 +117,7 @@ ide_deploy_strategy_real_create_runner_finish (IdeDeployStrategy *self,
g_assert (IDE_IS_TASK (result));
g_assert (ide_task_is_valid (G_TASK (result), self));
- return g_task_propagate_pointer (G_TASK (result), error);
+ return ide_task_propagate_pointer (IDE_TASK (result), error);
}
static void
@@ -154,7 +157,7 @@ ide_deploy_strategy_init (IdeDeployStrategy *self)
*/
void
ide_deploy_strategy_load_async (IdeDeployStrategy *self,
- IdePipeline *pipeline,
+ IdePipeline *pipeline,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data)
@@ -184,6 +187,7 @@ ide_deploy_strategy_load_async (IdeDeployStrategy *self,
gboolean
ide_deploy_strategy_load_finish (IdeDeployStrategy *self,
GAsyncResult *result,
+ int *priority,
GError **error)
{
gboolean ret;
@@ -192,8 +196,9 @@ ide_deploy_strategy_load_finish (IdeDeployStrategy *self,
g_assert (IDE_IS_DEPLOY_STRATEGY (self));
g_assert (G_IS_ASYNC_RESULT (result));
+ g_assert (priority != NULL);
- ret = IDE_DEPLOY_STRATEGY_GET_CLASS (self)->load_finish (self, result, error);
+ ret = IDE_DEPLOY_STRATEGY_GET_CLASS (self)->load_finish (self, result, priority, error);
IDE_RETURN (ret);
}
@@ -218,7 +223,7 @@ ide_deploy_strategy_load_finish (IdeDeployStrategy *self,
*/
void
ide_deploy_strategy_deploy_async (IdeDeployStrategy *self,
- IdePipeline *pipeline,
+ IdePipeline *pipeline,
GFileProgressCallback progress,
gpointer progress_data,
GDestroyNotify progress_data_destroy,
@@ -264,8 +269,8 @@ ide_deploy_strategy_deploy_finish (IdeDeployStrategy *self,
IDE_ENTRY;
- g_assert (IDE_IS_DEPLOY_STRATEGY (self));
- g_assert (G_IS_ASYNC_RESULT (result));
+ g_return_val_if_fail (IDE_IS_DEPLOY_STRATEGY (self), FALSE);
+ g_return_val_if_fail (G_IS_ASYNC_RESULT (result), FALSE);
ret = IDE_DEPLOY_STRATEGY_GET_CLASS (self)->deploy_finish (self, result, error);
diff --git a/src/libide/foundry/ide-deploy-strategy.h b/src/libide/foundry/ide-deploy-strategy.h
index 2bb4d7162..14061c544 100644
--- a/src/libide/foundry/ide-deploy-strategy.h
+++ b/src/libide/foundry/ide-deploy-strategy.h
@@ -38,33 +38,34 @@ struct _IdeDeployStrategyClass
{
IdeObjectClass parent;
- void (*load_async) (IdeDeployStrategy *self,
- IdePipeline *pipeline,
- GCancellable *cancellable,
- GAsyncReadyCallback callback,
- gpointer user_data);
- gboolean (*load_finish) (IdeDeployStrategy *self,
- GAsyncResult *result,
- GError **error);
- void (*deploy_async) (IdeDeployStrategy *self,
- IdePipeline *pipeline,
- GFileProgressCallback progress,
- gpointer progress_data,
- GDestroyNotify progress_data_destroy,
- GCancellable *cancellable,
- GAsyncReadyCallback callback,
- gpointer user_data);
- gboolean (*deploy_finish) (IdeDeployStrategy *self,
- GAsyncResult *result,
- GError **error);
- void (*create_runner_async) (IdeDeployStrategy *self,
- IdePipeline *pipeline,
- GCancellable *cancellable,
- GAsyncReadyCallback callback,
- gpointer user_data);
- IdeRunner *(*create_runner_finish) (IdeDeployStrategy *self,
- GAsyncResult *result,
- GError **error);
+ void (*load_async) (IdeDeployStrategy *self,
+ IdePipeline *pipeline,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+ gboolean (*load_finish) (IdeDeployStrategy *self,
+ GAsyncResult *result,
+ int *priority,
+ GError **error);
+ void (*deploy_async) (IdeDeployStrategy *self,
+ IdePipeline *pipeline,
+ GFileProgressCallback progress,
+ gpointer progress_data,
+ GDestroyNotify progress_data_destroy,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+ gboolean (*deploy_finish) (IdeDeployStrategy *self,
+ GAsyncResult *result,
+ GError **error);
+ void (*create_runner_async) (IdeDeployStrategy *self,
+ IdePipeline *pipeline,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+ IdeRunner *(*create_runner_finish) (IdeDeployStrategy *self,
+ GAsyncResult *result,
+ GError **error);
gpointer _reserved[16];
};
@@ -78,6 +79,7 @@ void ide_deploy_strategy_load_async (IdeDeployStrategy *self,
IDE_AVAILABLE_IN_ALL
gboolean ide_deploy_strategy_load_finish (IdeDeployStrategy *self,
GAsyncResult *result,
+ int *priority,
GError **error);
IDE_AVAILABLE_IN_ALL
void ide_deploy_strategy_deploy_async (IdeDeployStrategy *self,
diff --git a/src/libide/foundry/ide-device-manager.c b/src/libide/foundry/ide-device-manager.c
index 25ebe056d..674430c1e 100644
--- a/src/libide/foundry/ide-device-manager.c
+++ b/src/libide/foundry/ide-device-manager.c
@@ -37,6 +37,8 @@
#include "ide-device.h"
#include "ide-foundry-compat.h"
#include "ide-local-device.h"
+#include "ide-runner.h"
+#include "ide-triplet.h"
struct _IdeDeviceManager
{
@@ -76,12 +78,6 @@ struct _IdeDeviceManager
guint loading : 1;
};
-typedef struct
-{
- IdeObjectArray *strategies;
- IdePipeline *pipeline;
-} DeployState;
-
typedef struct
{
gint n_active;
@@ -93,7 +89,6 @@ static void ide_device_manager_action_device (IdeDeviceManager *self,
GVariant *param);
static void ide_device_manager_action_deploy (IdeDeviceManager *self,
GVariant *param);
-static void ide_device_manager_deploy_tick (IdeTask *task);
IDE_DEFINE_ACTION_GROUP (IdeDeviceManager, ide_device_manager, {
{ "device", ide_device_manager_action_device, "s", "'local'" },
@@ -122,14 +117,6 @@ enum {
static GParamSpec *properties [N_PROPS];
static guint signals [N_SIGNALS];
-static void
-deploy_state_free (DeployState *state)
-{
- g_clear_object (&state->pipeline);
- g_clear_pointer (&state->strategies, ide_object_array_unref);
- g_slice_free (DeployState, state);
-}
-
static void
ide_device_manager_provider_device_added_cb (IdeDeviceManager *self,
IdeDevice *device,
@@ -743,31 +730,14 @@ deploy_progress_cb (goffset current_num_bytes,
g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_PROGRESS]);
}
-static void
-collect_strategies (PeasExtensionSet *set,
- PeasPluginInfo *plugin_info,
- PeasExtension *exten,
- gpointer user_data)
-{
- IdeObjectArray *strategies = user_data;
- IdeDeployStrategy *strategy = (IdeDeployStrategy *)exten;
-
- g_assert (PEAS_IS_EXTENSION_SET (set));
- g_assert (plugin_info != NULL);
- g_assert (IDE_IS_DEPLOY_STRATEGY (strategy));
- g_assert (strategies != NULL);
-
- ide_object_array_add (strategies, strategy);
-}
-
static void
ide_device_manager_deploy_cb (GObject *object,
GAsyncResult *result,
gpointer user_data)
{
IdeDeployStrategy *strategy = (IdeDeployStrategy *)object;
- g_autoptr(GError) error = NULL;
g_autoptr(IdeTask) task = user_data;
+ g_autoptr(GError) error = NULL;
IDE_ENTRY;
@@ -783,94 +753,13 @@ ide_device_manager_deploy_cb (GObject *object,
IDE_EXIT;
}
-static void
-ide_device_manager_deploy_load_cb (GObject *object,
- GAsyncResult *result,
- gpointer user_data)
-{
- IdeDeployStrategy *strategy = (IdeDeployStrategy *)object;
- g_autoptr(GError) error = NULL;
- g_autoptr(IdeTask) task = user_data;
- IdeDeviceManager *self;
- DeployState *state;
-
- IDE_ENTRY;
-
- g_assert (IDE_IS_DEPLOY_STRATEGY (strategy));
- g_assert (G_IS_ASYNC_RESULT (result));
- g_assert (IDE_IS_TASK (task));
-
- if (!ide_deploy_strategy_load_finish (strategy, result, &error))
- {
- g_debug ("Deploy strategy failed to load: %s", error->message);
- ide_object_destroy (IDE_OBJECT (strategy));
- ide_device_manager_deploy_tick (task);
- IDE_EXIT;
- }
-
- /* Okay, we found a match. Now deploy to the device. */
-
- self = ide_task_get_source_object (task);
- state = ide_task_get_task_data (task);
-
- g_assert (IDE_IS_DEVICE_MANAGER (self));
- g_assert (state != NULL);
- g_assert (state->strategies != NULL);
- g_assert (IDE_IS_PIPELINE (state->pipeline));
-
- ide_deploy_strategy_deploy_async (strategy,
- state->pipeline,
- deploy_progress_cb,
- g_object_ref (self),
- g_object_unref,
- ide_task_get_cancellable (task),
- ide_device_manager_deploy_cb,
- g_object_ref (task));
-
- IDE_EXIT;
-}
-
-static void
-ide_device_manager_deploy_tick (IdeTask *task)
-{
- g_autoptr(IdeDeployStrategy) strategy = NULL;
- DeployState *state;
-
- IDE_ENTRY;
-
- g_assert (IDE_IS_TASK (task));
-
- state = ide_task_get_task_data (task);
-
- g_assert (state != NULL);
- g_assert (state->strategies != NULL);
- g_assert (IDE_IS_PIPELINE (state->pipeline));
-
- if (state->strategies->len == 0)
- {
- ide_task_return_new_error (task,
- G_IO_ERROR,
- G_IO_ERROR_NOT_SUPPORTED,
- "Failed to locate deployment strategy for device");
- IDE_EXIT;
- }
-
- strategy = ide_object_array_steal_index (state->strategies, 0);
-
- ide_deploy_strategy_load_async (strategy,
- state->pipeline,
- ide_task_get_cancellable (task),
- ide_device_manager_deploy_load_cb,
- g_object_ref (task));
-
- IDE_EXIT;
-}
-
static void
ide_device_manager_deploy_completed (IdeDeviceManager *self,
GParamSpec *pspec,
IdeTask *task)
{
+ IDE_ENTRY;
+
g_assert (IDE_IS_DEVICE_MANAGER (self));
g_assert (IDE_IS_TASK (task));
@@ -881,6 +770,8 @@ ide_device_manager_deploy_completed (IdeDeviceManager *self,
}
g_signal_emit (self, signals [DEPLOY_FINISHED], 0);
+
+ IDE_EXIT;
}
/**
@@ -902,10 +793,8 @@ ide_device_manager_deploy_async (IdeDeviceManager *self,
GAsyncReadyCallback callback,
gpointer user_data)
{
- g_autoptr(PeasExtensionSet) set = NULL;
g_autoptr(IdeTask) task = NULL;
- DeployState *state;
- IdeDevice *device;
+ IdeDeployStrategy *strategy;
IDE_ENTRY;
@@ -927,37 +816,20 @@ ide_device_manager_deploy_async (IdeDeviceManager *self,
self,
G_CONNECT_SWAPPED);
- if (!(device = ide_pipeline_get_device (pipeline)))
- {
- ide_task_return_new_error (task,
- G_IO_ERROR,
- G_IO_ERROR_FAILED,
- "Missing device in pipeline");
- IDE_EXIT;
- }
-
- if (IDE_IS_LOCAL_DEVICE (device))
- {
- ide_task_return_boolean (task, TRUE);
- IDE_EXIT;
- }
-
- state = g_slice_new0 (DeployState);
- state->pipeline = g_object_ref (pipeline);
- state->strategies = ide_object_array_new ();
- ide_task_set_task_data (task, state, deploy_state_free);
-
- set = peas_extension_set_new (peas_engine_get_default (),
- IDE_TYPE_DEPLOY_STRATEGY,
- NULL);
- peas_extension_set_foreach (set, collect_strategies, state->strategies);
-
- /* Root the addins as children of us so that they get context access */
- for (guint i = 0; i < state->strategies->len; i++)
- ide_object_append (IDE_OBJECT (self),
- ide_object_array_index (state->strategies, i));
-
- ide_device_manager_deploy_tick (task);
+ if (!(strategy = ide_pipeline_get_deploy_strategy (pipeline)))
+ ide_task_return_new_error (task,
+ G_IO_ERROR,
+ G_IO_ERROR_FAILED,
+ "Missing device in pipeline, cannot deploy");
+ else
+ ide_deploy_strategy_deploy_async (strategy,
+ pipeline,
+ deploy_progress_cb,
+ g_object_ref (self),
+ g_object_unref,
+ cancellable,
+ ide_device_manager_deploy_cb,
+ g_steal_pointer (&task));
IDE_EXIT;
}
@@ -996,9 +868,9 @@ ide_device_manager_create_runner_cb (GObject *object,
gpointer user_data)
{
IdeDeployStrategy *strategy = (IdeDeployStrategy *)object;
- g_autoptr(GError) error = NULL;
+ g_autoptr(IdeRunner) runner = NULL;
g_autoptr(IdeTask) task = user_data;
- IdeRunner *runner;
+ g_autoptr(GError) error = NULL;
IDE_ENTRY;
@@ -1006,94 +878,10 @@ ide_device_manager_create_runner_cb (GObject *object,
g_assert (G_IS_ASYNC_RESULT (result));
g_assert (IDE_IS_TASK (task));
- runner = ide_deploy_strategy_create_runner_finish (strategy, result, &error);
-
- if (error)
+ if (!(runner = ide_deploy_strategy_create_runner_finish (strategy, result, &error)))
ide_task_return_error (task, g_steal_pointer (&error));
else
- ide_task_return_pointer (task, runner, g_object_unref);
-
- ide_object_destroy (IDE_OBJECT (strategy));
-
- IDE_EXIT;
-}
-
-static void
-ide_device_manager_create_runner_load_cb (GObject *object,
- GAsyncResult *result,
- gpointer user_data)
-{
- IdeDeployStrategy *strategy = (IdeDeployStrategy *)object;
- g_autoptr(GError) error = NULL;
- g_autoptr(IdeTask) task = user_data;
- IdeDeviceManager *self;
- DeployState *state;
-
- IDE_ENTRY;
-
- g_assert (IDE_IS_DEPLOY_STRATEGY (strategy));
- g_assert (G_IS_ASYNC_RESULT (result));
- g_assert (IDE_IS_TASK (task));
-
- if (!ide_deploy_strategy_load_finish (strategy, result, &error))
- {
- g_debug ("Deploy strategy failed to load: %s", error->message);
- ide_object_destroy (IDE_OBJECT (strategy));
- ide_device_manager_deploy_tick (task);
- IDE_EXIT;
- }
-
- /* Okay, we found a match. Now run on the device. */
-
- self = ide_task_get_source_object (task);
- state = ide_task_get_task_data (task);
-
- g_assert (IDE_IS_DEVICE_MANAGER (self));
- g_assert (state != NULL);
- g_assert (state->strategies != NULL);
- g_assert (IDE_IS_PIPELINE (state->pipeline));
-
- ide_deploy_strategy_create_runner_async (strategy,
- state->pipeline,
- ide_task_get_cancellable (task),
- ide_device_manager_create_runner_cb,
- g_object_ref (task));
-
- IDE_EXIT;
-}
-
-static void
-ide_device_manager_create_runner_tick (IdeTask *task)
-{
- g_autoptr(IdeDeployStrategy) strategy = NULL;
- DeployState *state;
-
- IDE_ENTRY;
-
- g_assert (IDE_IS_TASK (task));
-
- state = ide_task_get_task_data (task);
-
- g_assert (state != NULL);
- g_assert (state->strategies != NULL);
- g_assert (IDE_IS_PIPELINE (state->pipeline));
-
- if (state->strategies->len == 0)
- {
- ide_task_return_new_error (task,
- G_IO_ERROR,
- G_IO_ERROR_NOT_SUPPORTED,
- "Failed to locate deployment strategy for device");
- IDE_EXIT;
- }
-
- strategy = ide_object_array_steal_index (state->strategies, 0);
-
- ide_deploy_strategy_load_async (strategy,
- state->pipeline,
- ide_task_get_cancellable (task),
- ide_device_manager_create_runner_load_cb,
- g_object_ref (task));
+ ide_task_return_pointer (task, g_steal_pointer (&runner), g_object_unref);
IDE_EXIT;
}
@@ -1116,10 +904,8 @@ ide_device_manager_create_runner_async (IdeDeviceManager *self,
GAsyncReadyCallback callback,
gpointer user_data)
{
- g_autoptr(PeasExtensionSet) set = NULL;
g_autoptr(IdeTask) task = NULL;
- DeployState *state;
- IdeDevice *device;
+ IdeDeployStrategy *strategy;
IDE_ENTRY;
@@ -1130,37 +916,17 @@ ide_device_manager_create_runner_async (IdeDeviceManager *self,
task = ide_task_new (self, cancellable, callback, user_data);
ide_task_set_source_tag (task, ide_device_manager_create_runner_async);
- if (!(device = ide_pipeline_get_device (pipeline)))
- {
- ide_task_return_new_error (task,
- G_IO_ERROR,
- G_IO_ERROR_FAILED,
- "Missing device in pipeline");
- IDE_EXIT;
- }
-
- if (IDE_IS_LOCAL_DEVICE (device))
- {
- (ide_task_return_pointer) (task, NULL, NULL);
- IDE_EXIT;
- }
-
- state = g_slice_new0 (DeployState);
- state->pipeline = g_object_ref (pipeline);
- state->strategies = ide_object_array_new ();
- ide_task_set_task_data (task, state, deploy_state_free);
-
- set = peas_extension_set_new (peas_engine_get_default (),
- IDE_TYPE_DEPLOY_STRATEGY,
- NULL);
- peas_extension_set_foreach (set, collect_strategies, state->strategies);
-
- /* Root the addins as children of us so that they get context access */
- for (guint i = 0; i < state->strategies->len; i++)
- ide_object_append (IDE_OBJECT (self),
- ide_object_array_index (state->strategies, i));
-
- ide_device_manager_create_runner_tick (task);
+ if (!(strategy = ide_pipeline_get_deploy_strategy (pipeline)))
+ ide_task_return_new_error (task,
+ G_IO_ERROR,
+ G_IO_ERROR_FAILED,
+ "Missing device in pipeline");
+ else
+ ide_deploy_strategy_create_runner_async (strategy,
+ pipeline,
+ cancellable,
+ ide_device_manager_create_runner_cb,
+ g_steal_pointer (&task));
IDE_EXIT;
}
diff --git a/src/libide/foundry/ide-local-deploy-strategy.c b/src/libide/foundry/ide-local-deploy-strategy.c
new file mode 100644
index 000000000..e947f3daf
--- /dev/null
+++ b/src/libide/foundry/ide-local-deploy-strategy.c
@@ -0,0 +1,217 @@
+/* ide-local-deploy-strategy.c
+ *
+ * Copyright 2022 Christian Hergert <chergert redhat com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#define G_LOG_DOMAIN "ide-local-deploy-strategy"
+
+#include "config.h"
+
+#include <libide-threading.h>
+
+#include "ide-local-deploy-strategy.h"
+#include "ide-local-device.h"
+#include "ide-pipeline.h"
+#include "ide-runtime.h"
+#include "ide-runner.h"
+
+struct _IdeLocalDeployStrategy
+{
+ GObject parent_instance;
+};
+
+G_DEFINE_FINAL_TYPE (IdeLocalDeployStrategy, ide_local_deploy_strategy, IDE_TYPE_DEPLOY_STRATEGY)
+
+static void
+ide_local_deploy_strategy_load_async (IdeDeployStrategy *strategy,
+ IdePipeline *pipeline,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ g_autoptr(IdeTask) task = NULL;
+ IdeDevice *device;
+
+ IDE_ENTRY;
+
+ g_assert (IDE_IS_LOCAL_DEPLOY_STRATEGY (strategy));
+ g_assert (IDE_IS_PIPELINE (pipeline));
+ g_assert (!cancellable || G_IS_CANCELLABLE (cancellable));
+
+ task = ide_task_new (strategy, cancellable, callback, user_data);
+ ide_task_set_source_tag (task, ide_local_deploy_strategy_load_async);
+
+ device = ide_pipeline_get_device (pipeline);
+
+ if (IDE_IS_LOCAL_DEVICE (device))
+ ide_task_return_boolean (task, TRUE);
+ else
+ ide_task_return_new_error (task,
+ G_IO_ERROR,
+ G_IO_ERROR_NOT_SUPPORTED,
+ "Cannot deploy to this device");
+
+ IDE_EXIT;
+}
+
+static gboolean
+ide_local_deploy_strategy_load_finish (IdeDeployStrategy *strategy,
+ GAsyncResult *result,
+ int *priority,
+ GError **error)
+{
+ gboolean ret;
+
+ IDE_ENTRY;
+
+ g_assert (IDE_IS_LOCAL_DEPLOY_STRATEGY (strategy));
+ g_assert (IDE_IS_TASK (result));
+ g_assert (priority != NULL);
+
+ *priority = 0;
+
+ ret = ide_task_propagate_boolean (IDE_TASK (result), error);
+
+ IDE_RETURN (ret);
+}
+
+static void
+ide_local_deploy_strategy_deploy_async (IdeDeployStrategy *strategy,
+ IdePipeline *pipeline,
+ GFileProgressCallback progress,
+ gpointer progress_data,
+ GDestroyNotify progress_data_destroy,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ g_autoptr(IdeTask) task = NULL;
+ IdeDevice *device;
+
+ IDE_ENTRY;
+
+ g_assert (IDE_IS_LOCAL_DEPLOY_STRATEGY (strategy));
+ g_assert (IDE_IS_PIPELINE (pipeline));
+ g_assert (!cancellable || G_IS_CANCELLABLE (cancellable));
+
+ task = ide_task_new (strategy, cancellable, callback, user_data);
+ ide_task_set_source_tag (task, ide_local_deploy_strategy_deploy_async);
+
+ device = ide_pipeline_get_device (pipeline);
+
+ if (IDE_IS_LOCAL_DEVICE (device))
+ ide_task_return_boolean (task, TRUE);
+ else
+ ide_task_return_new_error (task,
+ G_IO_ERROR,
+ G_IO_ERROR_NOT_SUPPORTED,
+ "Cannot deploy to this device: %s",
+ device ? G_OBJECT_TYPE_NAME (device) : "None");
+
+ IDE_EXIT;
+}
+
+static gboolean
+ide_local_deploy_strategy_deploy_finish (IdeDeployStrategy *strategy,
+ GAsyncResult *result,
+ GError **error)
+{
+ gboolean ret;
+
+ IDE_ENTRY;
+
+ g_assert (IDE_IS_LOCAL_DEPLOY_STRATEGY (strategy));
+ g_assert (IDE_IS_TASK (result));
+
+ ret = ide_task_propagate_boolean (IDE_TASK (result), error);
+
+ IDE_RETURN (ret);
+}
+
+static void
+ide_local_deploy_strategy_create_runner_async (IdeDeployStrategy *strategy,
+ IdePipeline *pipeline,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ g_autoptr(IdeRunner) runner = NULL;
+ g_autoptr(IdeTask) task = NULL;
+ IdeRuntime *runtime;
+
+ IDE_ENTRY;
+
+ g_return_if_fail (IDE_IS_LOCAL_DEPLOY_STRATEGY (strategy));
+ g_return_if_fail (IDE_IS_PIPELINE (pipeline));
+ g_return_if_fail (!cancellable || G_IS_CANCELLABLE (cancellable));
+
+ task = ide_task_new (strategy, cancellable, callback, user_data);
+ ide_task_set_source_tag (task, ide_local_deploy_strategy_create_runner_async);
+
+ if (!(runtime = ide_pipeline_get_runtime (pipeline)) ||
+ !(runner = ide_runtime_create_runner (runtime, NULL)))
+ ide_task_return_new_error (task,
+ G_IO_ERROR,
+ G_IO_ERROR_FAILED,
+ "Failed to create IdeRunner for pipeline");
+ else
+ ide_task_return_pointer (task, g_steal_pointer (&runner), g_object_unref);
+
+ IDE_EXIT;
+}
+
+static IdeRunner *
+ide_local_deploy_strategy_create_runner_finish (IdeDeployStrategy *strategy,
+ GAsyncResult *result,
+ GError **error)
+{
+ IdeRunner *ret;
+
+ IDE_ENTRY;
+
+ g_assert (IDE_IS_DEPLOY_STRATEGY (strategy));
+ g_assert (IDE_IS_TASK (result));
+
+ ret = ide_task_propagate_pointer (IDE_TASK (result), error);
+
+ IDE_RETURN (ret);
+}
+
+static void
+ide_local_deploy_strategy_class_init (IdeLocalDeployStrategyClass *klass)
+{
+ IdeDeployStrategyClass *deploy_strategy_class = IDE_DEPLOY_STRATEGY_CLASS (klass);
+
+ deploy_strategy_class->load_async = ide_local_deploy_strategy_load_async;
+ deploy_strategy_class->load_finish = ide_local_deploy_strategy_load_finish;
+ deploy_strategy_class->deploy_async = ide_local_deploy_strategy_deploy_async;
+ deploy_strategy_class->deploy_finish = ide_local_deploy_strategy_deploy_finish;
+ deploy_strategy_class->create_runner_async = ide_local_deploy_strategy_create_runner_async;
+ deploy_strategy_class->create_runner_finish = ide_local_deploy_strategy_create_runner_finish;
+}
+
+static void
+ide_local_deploy_strategy_init (IdeLocalDeployStrategy *self)
+{
+}
+
+IdeDeployStrategy *
+ide_local_deploy_strategy_new (void)
+{
+ return g_object_new (IDE_TYPE_LOCAL_DEPLOY_STRATEGY, NULL);
+}
diff --git a/src/libide/foundry/ide-local-deploy-strategy.h b/src/libide/foundry/ide-local-deploy-strategy.h
new file mode 100644
index 000000000..da6ed64c7
--- /dev/null
+++ b/src/libide/foundry/ide-local-deploy-strategy.h
@@ -0,0 +1,33 @@
+/* ide-local-deploy-strategy.h
+ *
+ * Copyright 2022 Christian Hergert <chergert redhat com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#pragma once
+
+#include "ide-deploy-strategy.h"
+
+G_BEGIN_DECLS
+
+#define IDE_TYPE_LOCAL_DEPLOY_STRATEGY (ide_local_deploy_strategy_get_type())
+
+G_DECLARE_FINAL_TYPE (IdeLocalDeployStrategy, ide_local_deploy_strategy, IDE, LOCAL_DEPLOY_STRATEGY,
IdeDeployStrategy)
+
+IdeDeployStrategy *ide_local_deploy_strategy_new (void);
+
+G_END_DECLS
diff --git a/src/libide/foundry/ide-pipeline.c b/src/libide/foundry/ide-pipeline.c
index 51285cc05..45f94d4f5 100644
--- a/src/libide/foundry/ide-pipeline.c
+++ b/src/libide/foundry/ide-pipeline.c
@@ -35,7 +35,8 @@
#include <libide-threading.h>
#include "ide-build-log-private.h"
-#include "ide-build-log.h"
+#include "ide-config.h"
+#include "ide-deploy-strategy.h"
#include "ide-pipeline-addin.h"
#include "ide-pipeline.h"
#include "ide-build-private.h"
@@ -47,6 +48,8 @@
#include "ide-device.h"
#include "ide-foundry-compat.h"
#include "ide-foundry-enums.h"
+#include "ide-local-deploy-strategy.h"
+#include "ide-local-device.h"
#include "ide-run-manager-private.h"
#include "ide-runtime.h"
#include "ide-toolchain-manager.h"
@@ -97,16 +100,16 @@ G_DEFINE_QUARK (ide_build_error, ide_build_error)
typedef struct
{
- guint id;
+ guint id;
IdePipelinePhase phase;
- gint priority;
+ int priority;
IdePipelineStage *stage;
} PipelineEntry;
typedef struct
{
IdePipeline *self;
- GPtrArray *addins;
+ GPtrArray *addins;
} IdleLoadState;
typedef struct
@@ -133,6 +136,15 @@ struct _IdePipeline
*/
IdeExtensionSetAdapter *addins;
+ /*
+ * Deployment stategies help discover how to make a deployment to
+ * a device which might require sending data to another system such
+ * as a phone or tablet.
+ */
+ IdeExtensionSetAdapter *deploy_strategies;
+ IdeDeployStrategy *best_strategy;
+ int best_strategy_priority;
+
/*
* This is the configuration for the build. It is a snapshot of
* the real configuration so that we do not need to synchronize
@@ -1156,6 +1168,60 @@ collect_pipeline_addins (IdeExtensionSetAdapter *set,
g_ptr_array_add (addins, g_object_ref (exten));
}
+static void
+ide_pipeline_deploy_strategy_load_cb (GObject *object,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ IdeDeployStrategy *strategy = (IdeDeployStrategy *)object;
+ g_autoptr(IdePipeline) self = user_data;
+ g_autoptr(GError) error = NULL;
+ int priority = 0;
+
+ IDE_ENTRY;
+
+ g_assert (IDE_IS_DEPLOY_STRATEGY (strategy));
+ g_assert (G_IS_ASYNC_RESULT (result));
+ g_assert (IDE_IS_PIPELINE (self));
+
+ if (ide_deploy_strategy_load_finish (strategy, result, &priority, &error))
+ {
+ if (self->best_strategy == NULL || priority < self->best_strategy_priority)
+ {
+ g_set_object (&self->best_strategy, strategy);
+ self->best_strategy_priority = priority;
+ IDE_EXIT;
+ }
+ }
+
+ IDE_EXIT;
+}
+
+static void
+ide_pipeline_deploy_strategy_added_cb (IdeExtensionSetAdapter *set,
+ PeasPluginInfo *plugin_info,
+ PeasExtension *exten,
+ gpointer user_data)
+{
+ IdePipeline *self = user_data;
+ IdeDeployStrategy *strategy = (IdeDeployStrategy *)exten;
+
+ IDE_ENTRY;
+
+ g_assert (IDE_IS_EXTENSION_SET_ADAPTER (set));
+ g_assert (plugin_info != NULL);
+ g_assert (IDE_IS_DEPLOY_STRATEGY (strategy));
+ g_assert (IDE_IS_PIPELINE (self));
+
+ ide_deploy_strategy_load_async (strategy,
+ self,
+ self->cancellable,
+ ide_pipeline_deploy_strategy_load_cb,
+ g_object_ref (self));
+
+ IDE_EXIT;
+}
+
static gboolean
ide_pipeline_load_cb (IdleLoadState *state)
{
@@ -1191,6 +1257,15 @@ ide_pipeline_load_cb (IdleLoadState *state)
return G_SOURCE_CONTINUE;
}
+ /* Now setup deployment strategies */
+ g_signal_connect (state->self->deploy_strategies,
+ "extension-added",
+ G_CALLBACK (ide_pipeline_deploy_strategy_added_cb),
+ state->self);
+ ide_extension_set_adapter_foreach (state->self->deploy_strategies,
+ ide_pipeline_deploy_strategy_added_cb,
+ state);
+
state->self->loaded = TRUE;
state->self->idle_addins_load_source = 0;
@@ -1213,7 +1288,6 @@ ide_pipeline_load_cb (IdleLoadState *state)
static void
ide_pipeline_load (IdePipeline *self)
{
- g_autoptr(GPtrArray) addins = NULL;
IdleLoadState *state;
IdeContext *context;
@@ -1229,42 +1303,39 @@ ide_pipeline_load (IdePipeline *self)
register_build_commands_stage (self, context);
register_post_install_commands_stage (self, context);
+ /* Setup pipeline addins */
self->addins = ide_extension_set_adapter_new (IDE_OBJECT (self),
peas_engine_get_default (),
IDE_TYPE_PIPELINE_ADDIN,
NULL, NULL);
-
g_signal_connect (self->addins,
"extension-added",
G_CALLBACK (ide_pipeline_extension_prepare),
self);
-
ide_extension_set_adapter_foreach (self->addins,
ide_pipeline_extension_prepare,
self);
-
g_signal_connect_after (self->addins,
"extension-added",
G_CALLBACK (ide_pipeline_extension_added),
self);
-
g_signal_connect (self->addins,
"extension-removed",
G_CALLBACK (ide_pipeline_extension_removed),
self);
- /* Collect our addins so we can incrementally load them in an
- * idle callback to reduce chances of stalling the main loop.
- */
- addins = g_ptr_array_new_with_free_func (g_object_unref);
- ide_extension_set_adapter_foreach (self->addins,
- collect_pipeline_addins,
- addins);
+ /* Create deployment strategies */
+ self->deploy_strategies = ide_extension_set_adapter_new (IDE_OBJECT (self),
+ peas_engine_get_default (),
+ IDE_TYPE_DEPLOY_STRATEGY,
+ NULL, NULL);
state = g_slice_new0 (IdleLoadState);
state->self = g_object_ref (self);
- state->addins = g_steal_pointer (&addins);
-
+ state->addins = g_ptr_array_new_with_free_func (g_object_unref);
+ ide_extension_set_adapter_foreach (self->addins,
+ collect_pipeline_addins,
+ state->addins);
self->idle_addins_load_source =
g_idle_add_full (G_PRIORITY_LOW,
(GSourceFunc) ide_pipeline_load_cb,
@@ -1347,7 +1418,10 @@ ide_pipeline_unload (IdePipeline *self)
g_assert (IDE_IS_PIPELINE (self));
+ g_clear_object (&self->best_strategy);
+
ide_clear_and_destroy_object (&self->addins);
+ ide_clear_and_destroy_object (&self->deploy_strategies);
IDE_EXIT;
}
@@ -1779,6 +1853,9 @@ ide_pipeline_init (IdePipeline *self)
self->position = -1;
self->pty_slave = -1;
+ self->best_strategy_priority = G_MAXINT;
+ self->best_strategy = ide_local_deploy_strategy_new ();
+
self->pipeline = g_array_new (FALSE, FALSE, sizeof (PipelineEntry));
g_array_set_clear_func (self->pipeline, clear_pipeline_entry);
@@ -1792,8 +1869,8 @@ ide_pipeline_init (IdePipeline *self)
static void
ide_pipeline_stage_build_cb (GObject *object,
- GAsyncResult *result,
- gpointer user_data)
+ GAsyncResult *result,
+ gpointer user_data)
{
IdePipelineStage *stage = (IdePipelineStage *)object;
IdePipeline *self;
@@ -4223,6 +4300,25 @@ ide_pipeline_contains_program_in_path (IdePipeline *self,
return FALSE;
}
+/**
+ * ide_pipeline_get_deploy_strategy:
+ * @self: a #IdePipeline
+ *
+ * Gets the best discovered deployment strategry.
+ *
+ * Returns: (transfer none) (nullable): the best deployment strategy
+ * if any are supported for the current configuration.
+ */
+IdeDeployStrategy *
+ide_pipeline_get_deploy_strategy (IdePipeline *self)
+{
+ g_return_val_if_fail (IDE_IS_PIPELINE (self), NULL);
+ g_return_val_if_fail (!self->best_strategy ||
+ IDE_IS_DEPLOY_STRATEGY (self->best_strategy), NULL);
+
+ return self->best_strategy;
+}
+
/**
* ide_pipeline_addin_find_by_module_name:
* @pipeline: an #IdePipeline
diff --git a/src/libide/foundry/ide-pipeline.h b/src/libide/foundry/ide-pipeline.h
index ba590a54a..8812cec51 100644
--- a/src/libide/foundry/ide-pipeline.h
+++ b/src/libide/foundry/ide-pipeline.h
@@ -24,19 +24,15 @@
# error "Only <libide-foundry.h> can be included directly."
#endif
+#include <vte/vte.h>
+
#include <libide-core.h>
#include <libide-code.h>
#include <libide-threading.h>
-#include <vte/vte.h>
-
-#include "ide-foundry-types.h"
#include "ide-build-log.h"
-#include "ide-config.h"
-#include "ide-pipeline-stage.h"
+#include "ide-foundry-types.h"
#include "ide-pipeline-phase.h"
-#include "ide-runtime.h"
-#include "ide-triplet.h"
G_BEGIN_DECLS
@@ -200,5 +196,7 @@ IDE_AVAILABLE_IN_ALL
gboolean ide_pipeline_contains_program_in_path (IdePipeline *self,
const gchar *name,
GCancellable *cancellable);
+IDE_AVAILABLE_IN_ALL
+IdeDeployStrategy *ide_pipeline_get_deploy_strategy (IdePipeline *self);
G_END_DECLS
diff --git a/src/libide/foundry/meson.build b/src/libide/foundry/meson.build
index ee4d8569d..6cf96bcbd 100644
--- a/src/libide/foundry/meson.build
+++ b/src/libide/foundry/meson.build
@@ -69,6 +69,7 @@ libide_foundry_private_headers = [
'ide-config-private.h',
'ide-device-private.h',
'ide-foundry-init.h',
+ 'ide-local-deploy-strategy.h',
'ide-run-manager-private.h',
'ide-runtime-private.h',
'ide-toolchain-private.h',
@@ -144,6 +145,7 @@ libide_foundry_private_sources = [
'ide-build-log.c',
'ide-build-utils.c',
'ide-foundry-init.c',
+ 'ide-local-deploy-strategy.c',
]
libide_foundry_sources += libide_foundry_public_sources
diff --git a/src/plugins/deviced/gbp-deviced-deploy-strategy.c
b/src/plugins/deviced/gbp-deviced-deploy-strategy.c
index f8877cf5a..8e9108a97 100644
--- a/src/plugins/deviced/gbp-deviced-deploy-strategy.c
+++ b/src/plugins/deviced/gbp-deviced-deploy-strategy.c
@@ -99,12 +99,16 @@ gbp_deviced_deploy_strategy_load_async (IdeDeployStrategy *strategy,
}
static gboolean
-gbp_deviced_deploy_strategy_load_finish (IdeDeployStrategy *self,
- GAsyncResult *result,
- GError **error)
+gbp_deviced_deploy_strategy_load_finish (IdeDeployStrategy *self,
+ GAsyncResult *result,
+ int *priority,
+ GError **error)
{
- g_return_val_if_fail (GBP_IS_DEVICED_DEPLOY_STRATEGY (self), FALSE);
- g_return_val_if_fail (ide_task_is_valid (result, self), FALSE);
+ g_assert (GBP_IS_DEVICED_DEPLOY_STRATEGY (self));
+ g_assert (ide_task_is_valid (result, self));
+ g_assert (priority != NULL);
+
+ *priority = -100;
return ide_task_propagate_boolean (IDE_TASK (result), error);
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]