[gnome-builder/wip/gtk4-port] libide/foundry: start on new run context design
- From: Christian Hergert <chergert src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-builder/wip/gtk4-port] libide/foundry: start on new run context design
- Date: Fri, 17 Jun 2022 00:22:50 +0000 (UTC)
commit f2af388bd29c61a9dae32780ccfb86dd78e50a16
Author: Christian Hergert <chergert redhat com>
Date: Thu Jun 16 17:22:45 2022 -0700
libide/foundry: start on new run context design
This is a layered run context design where we will allow tooling at various
layers to inject things as we process the creation of the launcher.
The goal is to simplify and/or remove IdeRunner completely in favor of this
and unify how the tooling injects/processes bits at each layer.
src/libide/foundry/ide-run-context.c | 340 +++++++++++++++++++++++++++++++++++
src/libide/foundry/ide-run-context.h | 102 +++++++++++
src/libide/foundry/meson.build | 2 +
3 files changed, 444 insertions(+)
---
diff --git a/src/libide/foundry/ide-run-context.c b/src/libide/foundry/ide-run-context.c
new file mode 100644
index 000000000..5d6c05bd6
--- /dev/null
+++ b/src/libide/foundry/ide-run-context.c
@@ -0,0 +1,340 @@
+/* ide-run-context.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-run-context"
+
+#include "config.h"
+
+#include "ide-run-context.h"
+
+typedef struct
+{
+ GList qlink;
+ char *cwd;
+ GArray *argv;
+ GArray *env;
+ IdeUnixFDMap *unix_fd_map;
+ IdeRunContextHandler handler;
+ gpointer handler_data;
+ GDestroyNotify handler_data_destroy;
+} IdeRunContextLayer;
+
+struct _IdeRunContext
+{
+ GObject parent_instance;
+ GQueue layers;
+ IdeRunContextLayer root;
+ guint ended : 1;
+};
+
+G_DEFINE_FINAL_TYPE (IdeRunContext, ide_run_context, G_TYPE_OBJECT)
+
+static void
+ide_run_context_layer_clear (IdeRunContextLayer *layer)
+{
+ g_assert (layer != NULL);
+ g_assert (layer->qlink.data == layer);
+ g_assert (layer->qlink.prev == NULL);
+ g_assert (layer->qlink.next == NULL);
+
+ g_clear_pointer (&layer->cwd, g_free);
+ g_clear_pointer (&layer->argv, g_array_unref);
+ g_clear_pointer (&layer->env, g_array_unref);
+ g_clear_object (&layer->unix_fd_map);
+}
+
+static void
+ide_run_context_layer_free (IdeRunContextLayer *layer)
+{
+ ide_run_context_layer_clear (layer);
+ g_slice_free (IdeRunContextLayer, layer);
+}
+
+static IdeRunContextLayer *
+ide_run_context_current_layer (IdeRunContext *self)
+{
+ return self->layers.head->data;
+}
+
+static void
+ide_run_context_dispose (GObject *object)
+{
+ IdeRunContext *self = (IdeRunContext *)object;
+ IdeRunContextLayer *layer;
+
+ while ((layer = g_queue_peek_head (&self->layers)))
+ {
+ g_queue_unlink (&self->layers, &layer->qlink);
+ if (layer != &self->root)
+ ide_run_context_layer_free (layer);
+ }
+
+ ide_run_context_layer_clear (&self->root);
+
+ G_OBJECT_CLASS (ide_run_context_parent_class)->dispose (object);
+}
+
+static void
+ide_run_context_class_init (IdeRunContextClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->dispose = ide_run_context_dispose;
+}
+
+static void
+ide_run_context_init (IdeRunContext *self)
+{
+ self->root.qlink.data = self;
+ g_queue_push_head_link (&self->layers, &self->root.qlink);
+}
+
+static void
+strptr_free (gpointer data)
+{
+ char **strptr = data;
+ g_clear_pointer (strptr, g_free);
+}
+
+void
+ide_run_context_push (IdeRunContext *self,
+ IdeRunContextHandler handler,
+ gpointer handler_data,
+ GDestroyNotify handler_data_destroy)
+{
+ IdeRunContextLayer *layer;
+
+ g_return_if_fail (IDE_IS_RUN_CONTEXT (self));
+
+ layer = g_slice_new0 (IdeRunContextLayer);
+ layer->qlink.data = layer;
+ layer->argv = g_array_new (TRUE, FALSE, sizeof (char *));
+ layer->env = g_array_new (TRUE, FALSE, sizeof (char *));
+ layer->unix_fd_map = ide_unix_fd_map_new ();
+ layer->handler = handler;
+ layer->handler_data = handler_data;
+ layer->handler_data_destroy = handler_data_destroy;
+
+ g_array_set_clear_func (layer->argv, strptr_free);
+ g_array_set_clear_func (layer->env, strptr_free);
+
+ g_queue_push_head_link (&self->layers, &layer->qlink);
+}
+
+const char * const *
+ide_run_context_get_argv (IdeRunContext *self)
+{
+ IdeRunContextLayer *layer;
+
+ g_return_val_if_fail (IDE_IS_RUN_CONTEXT (self), NULL);
+
+ layer = ide_run_context_current_layer (self);
+
+ return (const char * const *)&g_array_index (layer->argv, char *, 0);
+}
+
+const char * const *
+ide_run_context_get_environ (IdeRunContext *self)
+{
+ IdeRunContextLayer *layer;
+
+ g_return_val_if_fail (IDE_IS_RUN_CONTEXT (self), NULL);
+
+ layer = ide_run_context_current_layer (self);
+
+ return (const char * const *)&g_array_index (layer->env, char *, 0);
+}
+
+void
+ide_run_context_set_environ (IdeRunContext *self,
+ const char * const *environ)
+{
+ IdeRunContextLayer *layer;
+
+ g_return_if_fail (IDE_IS_RUN_CONTEXT (self));
+
+ layer = ide_run_context_current_layer (self);
+
+ g_array_set_size (layer->env, 0);
+
+ if (environ != NULL)
+ {
+ char **copy = g_strdupv ((char **)environ);
+ g_array_append_vals (layer->env, copy, g_strv_length (copy));
+ }
+}
+
+const char *
+ide_run_context_get_cwd (IdeRunContext *self)
+{
+ IdeRunContextLayer *layer;
+
+ g_return_val_if_fail (IDE_IS_RUN_CONTEXT (self), NULL);
+
+ layer = ide_run_context_current_layer (self);
+
+ return layer->cwd;
+}
+
+void
+ide_run_context_set_cwd (IdeRunContext *self,
+ const char *cwd)
+{
+ IdeRunContextLayer *layer;
+
+ g_return_if_fail (IDE_IS_RUN_CONTEXT (self));
+
+ layer = ide_run_context_current_layer (self);
+
+ if (g_strcmp0 (cwd, layer->cwd) != 0)
+ {
+ g_free (layer->cwd);
+ layer->cwd = g_strdup (cwd);
+ }
+}
+
+void
+ide_run_context_prepend_argv (IdeRunContext *self,
+ const char *arg)
+{
+ IdeRunContextLayer *layer;
+ char *copy;
+
+ g_return_if_fail (IDE_IS_RUN_CONTEXT (self));
+ g_return_if_fail (arg != NULL);
+
+ layer = ide_run_context_current_layer (self);
+
+ copy = g_strdup (arg);
+ g_array_insert_val (layer->argv, 0, copy);
+}
+
+void
+ide_run_context_append_argv (IdeRunContext *self,
+ const char *arg)
+{
+ IdeRunContextLayer *layer;
+ char *copy;
+
+ g_return_if_fail (IDE_IS_RUN_CONTEXT (self));
+ g_return_if_fail (arg != NULL);
+
+ layer = ide_run_context_current_layer (self);
+
+ copy = g_strdup (arg);
+ g_array_append_val (layer->argv, copy);
+}
+
+void
+ide_run_context_append_args (IdeRunContext *self,
+ const char * const *args)
+{
+ IdeRunContextLayer *layer;
+ char **copy;
+
+ g_return_if_fail (IDE_IS_RUN_CONTEXT (self));
+ g_return_if_fail (args != NULL);
+
+ layer = ide_run_context_current_layer (self);
+
+ copy = g_strdupv ((char **)args);
+ g_array_append_vals (layer->argv, copy, g_strv_length (copy));
+}
+
+gboolean
+ide_run_context_append_args_parsed (IdeRunContext *self,
+ const char *args,
+ GError **error)
+{
+ IdeRunContextLayer *layer;
+ char **argv = NULL;
+ int argc;
+
+ g_return_val_if_fail (IDE_IS_RUN_CONTEXT (self), FALSE);
+ g_return_val_if_fail (args != NULL, FALSE);
+
+ if (!g_shell_parse_argv (args, &argc, &argv, error))
+ return FALSE;
+
+ layer = ide_run_context_current_layer (self);
+ g_array_append_vals (layer->argv, argv, argc);
+
+ return TRUE;
+}
+
+void
+ide_run_context_take_fd (IdeRunContext *self,
+ int source_fd,
+ int dest_fd)
+{
+ IdeRunContextLayer *layer;
+
+ g_return_if_fail (IDE_IS_RUN_CONTEXT (self));
+ g_return_if_fail (source_fd > -1);
+ g_return_if_fail (dest_fd > -1);
+
+ layer = ide_run_context_current_layer (self);
+
+ ide_unix_fd_map_take (layer->unix_fd_map, source_fd, dest_fd);
+}
+
+const char *
+ide_run_context_getenv (IdeRunContext *self,
+ const char *key)
+{
+ /* TODO: */
+ return NULL;
+}
+
+void
+ide_run_context_setenv (IdeRunContext *self,
+ const char *key,
+ const char *value)
+{
+ /* TODO */
+}
+
+void
+ide_run_context_unsetenv (IdeRunContext *self,
+ const char *key)
+{
+ /* TODO */
+}
+
+/**
+ * ide_run_context_end:
+ * @self: a #IdeRunContext
+ *
+ * Returns: (transfer full): an #IdeSubprocessLauncher if successful; otherwise
+ * %NULL and @error is set.
+ */
+IdeSubprocessLauncher *
+ide_run_context_end (IdeRunContext *self,
+ GError **error)
+{
+ g_return_val_if_fail (IDE_IS_RUN_CONTEXT (self), NULL);
+ g_return_val_if_fail (self->ended == FALSE, NULL);
+
+ self->ended = TRUE;
+
+ /* TODO: Process layers */
+
+ return NULL;
+}
diff --git a/src/libide/foundry/ide-run-context.h b/src/libide/foundry/ide-run-context.h
new file mode 100644
index 000000000..3fd4fd4ff
--- /dev/null
+++ b/src/libide/foundry/ide-run-context.h
@@ -0,0 +1,102 @@
+/* ide-run-context.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
+
+#if !defined (IDE_FOUNDRY_INSIDE) && !defined (IDE_FOUNDRY_COMPILATION)
+# error "Only <libide-foundry.h> can be included directly."
+#endif
+
+#include <libide-threading.h>
+
+G_BEGIN_DECLS
+
+#define IDE_TYPE_RUN_CONTEXT (ide_run_context_get_type())
+
+IDE_AVAILABLE_IN_ALL
+G_DECLARE_FINAL_TYPE (IdeRunContext, ide_run_context, IDE, RUN_CONTEXT, GObject)
+
+/**
+ * IdeRunContextHandler:
+ *
+ * Returns: %TRUE if successful; otherwise %FALSE and @error must be set.
+ */
+typedef gboolean (*IdeRunContextHandler) (IdeRunContext *self,
+ const char * const *argv,
+ const char * const *env,
+ const char *cwd,
+ IdeUnixFDMap *fd_map,
+ gpointer user_data,
+ GError **error);
+
+IDE_AVAILABLE_IN_ALL
+IdeRunContext *ide_run_context_new (void);
+IDE_AVAILABLE_IN_ALL
+void ide_run_context_push (IdeRunContext *self,
+ IdeRunContextHandler handler,
+ gpointer handler_data,
+ GDestroyNotify handler_data_destroy);
+IDE_AVAILABLE_IN_ALL
+const char * const *ide_run_context_get_argv (IdeRunContext *self);
+IDE_AVAILABLE_IN_ALL
+void ide_run_context_set_argv (IdeRunContext *self,
+ const char * const *argv);
+IDE_AVAILABLE_IN_ALL
+const char * const *ide_run_context_get_environ (IdeRunContext *self);
+IDE_AVAILABLE_IN_ALL
+void ide_run_context_set_environ (IdeRunContext *self,
+ const char * const *environ);
+IDE_AVAILABLE_IN_ALL
+const char *ide_run_context_get_cwd (IdeRunContext *self);
+IDE_AVAILABLE_IN_ALL
+void ide_run_context_set_cwd (IdeRunContext *self,
+ const char *cwd);
+IDE_AVAILABLE_IN_ALL
+void ide_run_context_take_fd (IdeRunContext *self,
+ int source_fd,
+ int dest_fd);
+IDE_AVAILABLE_IN_ALL
+void ide_run_context_prepend_argv (IdeRunContext *self,
+ const char *arg);
+IDE_AVAILABLE_IN_ALL
+void ide_run_context_append_argv (IdeRunContext *self,
+ const char *arg);
+IDE_AVAILABLE_IN_ALL
+void ide_run_context_append_args (IdeRunContext *self,
+ const char * const *args);
+IDE_AVAILABLE_IN_ALL
+gboolean ide_run_context_append_args_parsed (IdeRunContext *self,
+ const char *args,
+ GError **error);
+IDE_AVAILABLE_IN_ALL
+const char *ide_run_context_getenv (IdeRunContext *self,
+ const char *key);
+IDE_AVAILABLE_IN_ALL
+void ide_run_context_setenv (IdeRunContext *self,
+ const char *key,
+ const char *value);
+IDE_AVAILABLE_IN_ALL
+void ide_run_context_unsetenv (IdeRunContext *self,
+ const char *key);
+IDE_AVAILABLE_IN_ALL
+IdeSubprocessLauncher *ide_run_context_end (IdeRunContext *self,
+ GError **error);
+
+G_END_DECLS
diff --git a/src/libide/foundry/meson.build b/src/libide/foundry/meson.build
index ebfe90d7d..ee4d8569d 100644
--- a/src/libide/foundry/meson.build
+++ b/src/libide/foundry/meson.build
@@ -42,6 +42,7 @@ libide_foundry_public_headers = [
'ide-pipeline.h',
'ide-run-command.h',
'ide-run-command-provider.h',
+ 'ide-run-context.h',
'ide-run-manager.h',
'ide-runner-addin.h',
'ide-runner.h',
@@ -119,6 +120,7 @@ libide_foundry_public_sources = [
'ide-pipeline.c',
'ide-run-command.c',
'ide-run-command-provider.c',
+ 'ide-run-context.c',
'ide-run-manager.c',
'ide-runner-addin.c',
'ide-runner.c',
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]