[gnome-builder] vagrant: prototype a vagrant runtime
- From: Christian Hergert <chergert src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-builder] vagrant: prototype a vagrant runtime
- Date: Fri, 3 May 2019 04:02:38 +0000 (UTC)
commit 1752c11bf82ba8a04cd8d2dc36e12336e55a7cb5
Author: Christian Hergert <chergert redhat com>
Date: Thu May 2 20:56:23 2019 -0700
vagrant: prototype a vagrant runtime
This still needs work on various fronts, but it's good enough to
iterate upon now. To make some things we need fast we will need
to capture some information at load time.
For example, we expect "contains_program_in_path" to be fast, so
we will want to ls /usr/bin, /bin, etc and cache the result.
We also wont have the ability to pass FDs across the process
boundary, so we'll have to introduce new API in
IdeSubprocessLauncher for something like "can_pass_fd". That way
subsystems like GDB can use alternate strategies to spawn a
debugger.
Furthermore, we need to extend the build pipeline to sync code
to the domain. We can look at adding an IDE_BUILD_PHASE_PUSH
that happens before IDE_BUILD_PHASE_CONFIGURE. A vagrant plugin
would likely want to rsync code here.
There will be fallout for a number of other things too, such as
how do we do exports, execution with display, etc.
We might also want to add a Containers project-tree node so that
some basic management of containers can be done.
meson_options.txt | 1 +
po/POTFILES.in | 1 +
src/plugins/meson.build | 2 +
src/plugins/vagrant/gbp-vagrant-runtime-provider.c | 389 +++++++++++++++++++++
src/plugins/vagrant/gbp-vagrant-runtime-provider.h | 42 +++
src/plugins/vagrant/gbp-vagrant-runtime.c | 231 ++++++++++++
src/plugins/vagrant/gbp-vagrant-runtime.h | 39 +++
.../vagrant/gbp-vagrant-subprocess-launcher.c | 101 ++++++
.../vagrant/gbp-vagrant-subprocess-launcher.h | 34 ++
src/plugins/vagrant/gbp-vagrant-table.c | 129 +++++++
src/plugins/vagrant/gbp-vagrant-table.h | 46 +++
src/plugins/vagrant/meson.build | 19 +
src/plugins/vagrant/vagrant-plugin.c | 36 ++
src/plugins/vagrant/vagrant.gresource.xml | 6 +
src/plugins/vagrant/vagrant.plugin | 9 +
15 files changed, 1085 insertions(+)
---
diff --git a/meson_options.txt b/meson_options.txt
index 3d6fc2e40..1e2c94943 100644
--- a/meson_options.txt
+++ b/meson_options.txt
@@ -70,6 +70,7 @@ option('plugin_sysprof', type: 'boolean')
option('plugin_sysroot', type: 'boolean')
option('plugin_todo', type: 'boolean')
option('plugin_vala', type: 'boolean')
+option('plugin_vagrant', type: 'boolean', value: false)
option('plugin_valgrind', type: 'boolean')
option('plugin_waf', type: 'boolean')
option('plugin_words', type: 'boolean')
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 3e31a080d..6d2dc9600 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -362,6 +362,7 @@ src/plugins/testui/gbp-test-output-panel.ui
src/plugins/testui/gbp-test-tree-addin.c
src/plugins/todo/gbp-todo-panel.c
src/plugins/todo/gbp-todo-workspace-addin.c
+src/plugins/vagrant/gbp-vagrant-runtime-provider.c
src/plugins/vala-pack/ide-vala-completion-item.vala
src/plugins/vala-pack/ide-vala-preferences-addin.vala
src/plugins/valgrind/gtk/menus.ui
diff --git a/src/plugins/meson.build b/src/plugins/meson.build
index 5e40adc9f..17583bf9e 100644
--- a/src/plugins/meson.build
+++ b/src/plugins/meson.build
@@ -116,6 +116,7 @@ subdir('terminal')
subdir('testui')
subdir('todo')
subdir('trim-spaces')
+subdir('vagrant')
subdir('valgrind')
subdir('vcsui')
subdir('vim')
@@ -183,6 +184,7 @@ status += [
'Sysroot ............... : @0@'.format(get_option('plugin_sysroot')),
'Todo .................. : @0@'.format(get_option('plugin_todo')),
'Vala Pack ............. : @0@'.format(get_option('plugin_vala')),
+ 'Vagrant ............... : @0@'.format(get_option('plugin_vagrant')),
'Valgrind .............. : @0@'.format(get_option('plugin_valgrind')),
'Waf ................... : @0@'.format(get_option('plugin_waf')),
'Word Completion ....... : @0@'.format(get_option('plugin_words')),
diff --git a/src/plugins/vagrant/gbp-vagrant-runtime-provider.c
b/src/plugins/vagrant/gbp-vagrant-runtime-provider.c
new file mode 100644
index 000000000..4e610ea65
--- /dev/null
+++ b/src/plugins/vagrant/gbp-vagrant-runtime-provider.c
@@ -0,0 +1,389 @@
+/* gbp-vagrant-runtime-provider.c
+ *
+ * Copyright 2019 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 "gbp-vagrant-runtime-provider"
+
+#include "config.h"
+
+#include <glib/gi18n.h>
+
+#include "gbp-vagrant-runtime.h"
+#include "gbp-vagrant-runtime-provider.h"
+
+struct _GbpVagrantRuntimeProvider
+{
+ IdeObject parent_instance;
+};
+
+static const gchar *cmd_vagrant_status[] = { "vagrant", "status", NULL };
+
+static void
+gbp_vagrant_runtime_provider_add (GbpVagrantRuntimeProvider *self,
+ GbpVagrantRuntime *runtime)
+{
+ g_autofree gchar *display_name = NULL;
+ IdeRuntimeManager *runtime_manager;
+ const gchar *provider;
+ const gchar *vagrant_id;
+ IdeContext *context;
+
+ g_assert (GBP_IS_VAGRANT_RUNTIME_PROVIDER (self));
+ g_assert (GBP_IS_VAGRANT_RUNTIME (runtime));
+
+ provider = gbp_vagrant_runtime_get_provider (runtime);
+ vagrant_id = gbp_vagrant_runtime_get_vagrant_id (runtime);
+ display_name = g_strdup_printf ("%s %s (%s)", _("Vagrant"), vagrant_id, provider);
+ ide_runtime_set_display_name (IDE_RUNTIME (runtime), display_name);
+
+ context = ide_object_get_context (IDE_OBJECT (self));
+ runtime_manager = ide_runtime_manager_from_context (context);
+ ide_object_append (IDE_OBJECT (self), IDE_OBJECT (runtime));
+ ide_runtime_manager_add (runtime_manager, IDE_RUNTIME (runtime));
+}
+
+static void
+vagrant_status_cb (GbpVagrantRuntimeProvider *self,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ g_autoptr(GbpVagrantTable) table = NULL;
+ g_autoptr(GbpVagrantRuntime) runtime = NULL;
+ g_autoptr(IdeTask) task = user_data;
+ g_autoptr(GError) error = NULL;
+ GbpVagrantTableIter iter;
+
+ g_assert (GBP_IS_VAGRANT_RUNTIME_PROVIDER (self));
+ g_assert (G_IS_ASYNC_RESULT (result));
+ g_assert (IDE_IS_TASK (task));
+
+ if (!(table = gbp_vagrant_runtime_provider_command_finish (self, result, &error)))
+ {
+ ide_task_return_error (task, g_steal_pointer (&error));
+ return;
+ }
+
+ gbp_vagrant_table_iter_init (&iter, table);
+
+ while (gbp_vagrant_table_iter_next (&iter))
+ {
+ g_autofree gchar *id = NULL;
+ g_autofree gchar *key = NULL;
+ g_autofree gchar *val1 = NULL;
+
+ id = gbp_vagrant_table_iter_get_column (&iter, 1);
+ key = gbp_vagrant_table_iter_get_column (&iter, 2);
+ val1 = gbp_vagrant_table_iter_get_column (&iter, 3);
+
+ if (ide_str_empty0 (id))
+ continue;
+
+ if (runtime != NULL)
+ {
+ const gchar *prev_id = gbp_vagrant_runtime_get_vagrant_id (runtime);
+
+ if (!ide_str_equal0 (id, prev_id))
+ {
+ gbp_vagrant_runtime_provider_add (self, runtime);
+ g_clear_object (&runtime);
+ }
+ }
+ else
+ {
+ g_autofree gchar *runtime_id = g_strdup_printf ("vagrant:%s", id);
+
+ runtime = g_object_new (GBP_TYPE_VAGRANT_RUNTIME,
+ "id", runtime_id,
+ "category", _("Vagrant"),
+ "name", id,
+ "vagrant-id", id,
+ NULL);
+ }
+
+ if (ide_str_equal0 (key, "provider-name"))
+ gbp_vagrant_runtime_set_provider (runtime, val1);
+ else if (ide_str_equal0 (key, "state"))
+ gbp_vagrant_runtime_set_state (runtime, val1);
+ }
+
+ if (runtime != NULL)
+ {
+ gbp_vagrant_runtime_provider_add (self, runtime);
+ g_clear_object (&runtime);
+ }
+
+ ide_task_return_boolean (task, TRUE);
+}
+
+static void
+reload_find_in_ancestors_cb (GFile *workdir,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ g_autoptr(IdeTask) task = user_data;
+ g_autoptr(GError) error = NULL;
+ g_autoptr(GFile) vagrantfile = NULL;
+
+ g_assert (G_IS_FILE (workdir));
+ g_assert (G_IS_ASYNC_RESULT (result));
+ g_assert (IDE_IS_TASK (task));
+
+ if (!(vagrantfile = ide_g_file_find_in_ancestors_finish (result, &error)))
+ ide_task_return_error (task, g_steal_pointer (&error));
+ else
+ gbp_vagrant_runtime_provider_command_async (ide_task_get_source_object (task),
+ (const gchar * const *)cmd_vagrant_status,
+ ide_task_get_cancellable (task),
+ (GAsyncReadyCallback) vagrant_status_cb,
+ g_object_ref (task));
+
+
+}
+
+static void
+gbp_vagrant_runtime_provider_reload_async (GbpVagrantRuntimeProvider *self,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ g_autoptr(IdeTask) task = NULL;
+ g_autoptr(GFile) workdir = NULL;
+ IdeContext *context;
+
+ g_return_if_fail (GBP_IS_VAGRANT_RUNTIME_PROVIDER (self));
+ g_return_if_fail (!cancellable || G_IS_CANCELLABLE (cancellable));
+
+ task = ide_task_new (self, cancellable, callback, user_data);
+ ide_task_set_source_tag (task, gbp_vagrant_runtime_provider_reload_async);
+
+ context = ide_object_get_context (IDE_OBJECT (self));
+ workdir = ide_context_ref_workdir (context);
+
+ ide_g_file_find_in_ancestors_async (workdir,
+ "Vagrantfile",
+ ide_task_get_cancellable (task),
+ (GAsyncReadyCallback) reload_find_in_ancestors_cb,
+ g_object_ref (task));
+}
+
+static gboolean
+gbp_vagrant_runtime_provider_reload_finish (GbpVagrantRuntimeProvider *self,
+ GAsyncResult *result,
+ GError **error)
+{
+ g_return_val_if_fail (GBP_IS_VAGRANT_RUNTIME_PROVIDER (self), FALSE);
+ g_return_val_if_fail (IDE_IS_TASK (result), FALSE);
+
+ return ide_task_propagate_boolean (IDE_TASK (result), error);
+}
+
+static void
+load_reload_cb (GbpVagrantRuntimeProvider *self,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ g_autoptr(IdeTask) task = user_data;
+ g_autoptr(GError) error = NULL;
+
+ g_assert (IDE_IS_TASK (task));
+ g_assert (G_IS_ASYNC_RESULT (result));
+ g_assert (GBP_IS_VAGRANT_RUNTIME_PROVIDER (self));
+
+ if (!gbp_vagrant_runtime_provider_reload_finish (self, result, &error))
+ ide_task_return_error (task, g_steal_pointer (&error));
+ else
+ ide_task_return_boolean (task, TRUE);
+}
+
+static void
+check_vagrant_available_cb (IdeSubprocess *subprocess,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ g_autoptr(IdeTask) task = user_data;
+ g_autoptr(GError) error = NULL;
+
+ g_assert (IDE_IS_MAIN_THREAD ());
+ g_assert (G_IS_ASYNC_RESULT (result));
+ g_assert (IDE_IS_TASK (task));
+
+ if (!ide_subprocess_wait_check_finish (subprocess, result, &error))
+ ide_task_return_error (task, g_steal_pointer (&error));
+ else
+ gbp_vagrant_runtime_provider_reload_async (ide_task_get_source_object (task),
+ ide_task_get_cancellable (task),
+ (GAsyncReadyCallback) load_reload_cb,
+ g_object_ref (task));
+
+}
+
+static void
+gbp_vagrant_runtime_provider_load_async (GbpVagrantRuntimeProvider *self,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ g_autoptr(IdeSubprocessLauncher) launcher = NULL;
+ g_autoptr(IdeSubprocess) subprocess = NULL;
+ g_autoptr(IdeTask) task = NULL;
+ g_autoptr(GError) error = NULL;
+
+ g_assert (IDE_IS_MAIN_THREAD ());
+ g_assert (GBP_IS_VAGRANT_RUNTIME_PROVIDER (self));
+ g_assert (!cancellable || G_IS_CANCELLABLE (cancellable));
+
+ task = ide_task_new (self, cancellable, callback, user_data);
+ ide_task_set_source_tag (task, gbp_vagrant_runtime_provider_load_async);
+
+ launcher = ide_subprocess_launcher_new (G_SUBPROCESS_FLAGS_STDOUT_SILENCE |
+ G_SUBPROCESS_FLAGS_STDERR_SILENCE);
+ ide_subprocess_launcher_set_cwd (launcher, g_get_home_dir ());
+ ide_subprocess_launcher_set_run_on_host (launcher, TRUE);
+ ide_subprocess_launcher_push_argv (launcher, "which");
+ ide_subprocess_launcher_push_argv (launcher, "vagrant");
+
+ if (!(subprocess = ide_subprocess_launcher_spawn (launcher, cancellable, &error)))
+ ide_task_return_error (task, g_steal_pointer ((&error)));
+ else
+ ide_subprocess_wait_check_async (subprocess,
+ cancellable,
+ (GAsyncReadyCallback) check_vagrant_available_cb,
+ g_steal_pointer (&task));
+
+}
+
+static void
+gbp_vagrant_runtime_provider_load (IdeRuntimeProvider *provider,
+ IdeRuntimeManager *runtime_manager)
+{
+ g_assert (IDE_IS_MAIN_THREAD ());
+ g_assert (GBP_IS_VAGRANT_RUNTIME_PROVIDER (provider));
+ g_assert (IDE_IS_RUNTIME_MANAGER (runtime_manager));
+
+ gbp_vagrant_runtime_provider_load_async (GBP_VAGRANT_RUNTIME_PROVIDER (provider),
+ NULL, NULL, NULL);
+}
+
+static void
+runtime_provider_iface_init (IdeRuntimeProviderInterface *iface)
+{
+ iface->load = gbp_vagrant_runtime_provider_load;
+}
+
+G_DEFINE_TYPE_WITH_CODE (GbpVagrantRuntimeProvider, gbp_vagrant_runtime_provider, IDE_TYPE_OBJECT,
+ G_IMPLEMENT_INTERFACE (IDE_TYPE_RUNTIME_PROVIDER, runtime_provider_iface_init))
+
+static void
+gbp_vagrant_runtime_provider_finalize (GObject *object)
+{
+ G_OBJECT_CLASS (gbp_vagrant_runtime_provider_parent_class)->finalize (object);
+}
+
+static void
+gbp_vagrant_runtime_provider_class_init (GbpVagrantRuntimeProviderClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->finalize = gbp_vagrant_runtime_provider_finalize;
+}
+
+static void
+gbp_vagrant_runtime_provider_init (GbpVagrantRuntimeProvider *self)
+{
+}
+
+static void
+gbp_vagrant_runtime_provider_command_cb (IdeSubprocess *subprocess,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ g_autofree gchar *stdout_buf = NULL;
+ g_autoptr(IdeTask) task = user_data;
+ g_autoptr(GError) error = NULL;
+
+ g_assert (IDE_IS_SUBPROCESS (subprocess));
+ g_assert (G_IS_ASYNC_RESULT (result));
+ g_assert (IDE_IS_TASK (task));
+
+ if (!ide_subprocess_communicate_utf8_finish (subprocess, result, &stdout_buf, NULL, &error))
+ ide_task_return_error (task, g_steal_pointer (&error));
+ else
+ ide_task_return_pointer (task,
+ gbp_vagrant_table_new_take (g_steal_pointer (&stdout_buf)),
+ gbp_vagrant_table_free);
+}
+
+void
+gbp_vagrant_runtime_provider_command_async (GbpVagrantRuntimeProvider *self,
+ const gchar * const *command,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ g_autoptr(IdeSubprocessLauncher) launcher = NULL;
+ g_autoptr(IdeSubprocess) subprocess = NULL;
+ g_autoptr(IdeTask) task = NULL;
+ g_autoptr(GError) error = NULL;
+ g_autoptr(GFile) workdir = NULL;
+ IdeContext *context;
+
+ g_assert (GBP_IS_VAGRANT_RUNTIME_PROVIDER (self));
+ g_assert (command != NULL && command[0] != NULL);
+ g_assert (g_str_equal ("vagrant", command[0]));
+ g_assert (!cancellable || G_IS_CANCELLABLE (cancellable));
+
+ task = ide_task_new (self, cancellable, callback, user_data);
+ ide_task_set_source_tag (task, gbp_vagrant_runtime_provider_command_async);
+
+ context = ide_object_get_context (IDE_OBJECT (self));
+ workdir = ide_context_ref_workdir (context);
+
+ launcher = ide_subprocess_launcher_new (G_SUBPROCESS_FLAGS_STDOUT_PIPE |
+ G_SUBPROCESS_FLAGS_STDERR_SILENCE);
+ ide_subprocess_launcher_set_cwd (launcher, g_file_peek_path (workdir));
+
+ ide_subprocess_launcher_push_args (launcher, command);
+ if (!g_strv_contains (command, "--machine-readable"))
+ ide_subprocess_launcher_push_argv (launcher, "--machine-readable");
+
+ if (!(subprocess = ide_subprocess_launcher_spawn (launcher, cancellable, &error)))
+ ide_task_return_error (task, g_steal_pointer (&error));
+ else
+ ide_subprocess_communicate_utf8_async (subprocess,
+ NULL,
+ cancellable,
+ (GAsyncReadyCallback) gbp_vagrant_runtime_provider_command_cb,
+ g_steal_pointer (&task));
+}
+
+/**
+ * gbp_vagrant_runtime_provider_command_finish:
+ *
+ * Returns: (transfer full): a #GbpVagrantTable or %NULL
+ */
+GbpVagrantTable *
+gbp_vagrant_runtime_provider_command_finish (GbpVagrantRuntimeProvider *self,
+ GAsyncResult *result,
+ GError **error)
+{
+ g_return_val_if_fail (GBP_IS_VAGRANT_RUNTIME_PROVIDER (self), NULL);
+ g_return_val_if_fail (IDE_IS_TASK (result), NULL);
+
+ return ide_task_propagate_pointer (IDE_TASK (result), error);
+}
diff --git a/src/plugins/vagrant/gbp-vagrant-runtime-provider.h
b/src/plugins/vagrant/gbp-vagrant-runtime-provider.h
new file mode 100644
index 000000000..b1e2bf097
--- /dev/null
+++ b/src/plugins/vagrant/gbp-vagrant-runtime-provider.h
@@ -0,0 +1,42 @@
+/* gbp-vagrant-runtime-provider.h
+ *
+ * Copyright 2019 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 <libide-foundry.h>
+
+#include "gbp-vagrant-table.h"
+
+G_BEGIN_DECLS
+
+#define GBP_TYPE_VAGRANT_RUNTIME_PROVIDER (gbp_vagrant_runtime_provider_get_type())
+
+G_DECLARE_FINAL_TYPE (GbpVagrantRuntimeProvider, gbp_vagrant_runtime_provider, GBP,
VAGRANT_RUNTIME_PROVIDER, IdeObject)
+
+void gbp_vagrant_runtime_provider_command_async (GbpVagrantRuntimeProvider *self,
+ const gchar * const *command,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+GbpVagrantTable *gbp_vagrant_runtime_provider_command_finish (GbpVagrantRuntimeProvider *self,
+ GAsyncResult *result,
+ GError **error);
+
+G_END_DECLS
diff --git a/src/plugins/vagrant/gbp-vagrant-runtime.c b/src/plugins/vagrant/gbp-vagrant-runtime.c
new file mode 100644
index 000000000..2ace23696
--- /dev/null
+++ b/src/plugins/vagrant/gbp-vagrant-runtime.c
@@ -0,0 +1,231 @@
+/* gbp-vagrant-runtime.c
+ *
+ * Copyright 2019 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 "gbp-vagrant-runtime"
+
+#include "config.h"
+
+#include "gbp-vagrant-runtime.h"
+#include "gbp-vagrant-subprocess-launcher.h"
+
+struct _GbpVagrantRuntime
+{
+ IdeRuntime parent_instance;
+ gchar *vagrant_id;
+ gchar *provider;
+ gchar *state;
+};
+
+enum {
+ PROP_0,
+ PROP_PROVIDER,
+ PROP_STATE,
+ PROP_VAGRANT_ID,
+ N_PROPS
+};
+
+G_DEFINE_TYPE (GbpVagrantRuntime, gbp_vagrant_runtime, IDE_TYPE_RUNTIME)
+
+static GParamSpec *properties [N_PROPS];
+
+static IdeSubprocessLauncher *
+gbp_vagrant_runtime_create_launcher (IdeRuntime *runtime,
+ GError **error)
+{
+ GbpVagrantRuntime *self = (GbpVagrantRuntime *)runtime;
+ IdeSubprocessLauncher *launcher;
+ g_autoptr(GFile) workdir = NULL;
+ IdeContext *context;
+
+ g_assert (GBP_IS_VAGRANT_RUNTIME (self));
+
+ context = ide_object_get_context (IDE_OBJECT (self));
+ workdir = ide_context_ref_workdir (context);
+
+ launcher = gbp_vagrant_subprocess_launcher_new (g_file_peek_path (workdir));
+
+ ide_subprocess_launcher_set_run_on_host (launcher, TRUE);
+
+ ide_subprocess_launcher_push_argv (launcher, "vagrant");
+ ide_subprocess_launcher_push_argv (launcher, "ssh");
+ ide_subprocess_launcher_push_argv (launcher, self->vagrant_id);
+ ide_subprocess_launcher_push_argv (launcher, GBP_VAGRANT_SUBPROCESS_LAUNCHER_C_OPT);
+
+ return g_steal_pointer (&launcher);
+}
+
+static void
+gbp_vagrant_runtime_finalize (GObject *object)
+{
+ GbpVagrantRuntime *self = (GbpVagrantRuntime *)object;
+
+ g_clear_pointer (&self->provider, g_free);
+ g_clear_pointer (&self->state, g_free);
+ g_clear_pointer (&self->vagrant_id, g_free);
+
+ G_OBJECT_CLASS (gbp_vagrant_runtime_parent_class)->finalize (object);
+}
+
+static void
+gbp_vagrant_runtime_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ GbpVagrantRuntime *self = GBP_VAGRANT_RUNTIME (object);
+
+ switch (prop_id)
+ {
+ case PROP_PROVIDER:
+ g_value_set_string (value, gbp_vagrant_runtime_get_provider (self));
+ break;
+
+ case PROP_STATE:
+ g_value_set_string (value, gbp_vagrant_runtime_get_state (self));
+ break;
+
+ case PROP_VAGRANT_ID:
+ g_value_set_string (value, gbp_vagrant_runtime_get_vagrant_id (self));
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+gbp_vagrant_runtime_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ GbpVagrantRuntime *self = GBP_VAGRANT_RUNTIME (object);
+
+ switch (prop_id)
+ {
+ case PROP_PROVIDER:
+ gbp_vagrant_runtime_set_provider (self, g_value_get_string (value));
+ break;
+
+ case PROP_STATE:
+ gbp_vagrant_runtime_set_state (self, g_value_get_string (value));
+ break;
+
+ case PROP_VAGRANT_ID:
+ self->vagrant_id = g_value_dup_string (value);
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+gbp_vagrant_runtime_class_init (GbpVagrantRuntimeClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ IdeRuntimeClass *runtime_class = IDE_RUNTIME_CLASS (klass);
+
+ object_class->finalize = gbp_vagrant_runtime_finalize;
+ object_class->get_property = gbp_vagrant_runtime_get_property;
+ object_class->set_property = gbp_vagrant_runtime_set_property;
+
+ runtime_class->create_launcher = gbp_vagrant_runtime_create_launcher;
+
+ properties [PROP_PROVIDER] =
+ g_param_spec_string ("provider",
+ "Provider",
+ "Provider",
+ NULL,
+ (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+ properties [PROP_STATE] =
+ g_param_spec_string ("state",
+ "State",
+ "State",
+ NULL,
+ (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+ properties [PROP_VAGRANT_ID] =
+ g_param_spec_string ("vagrant-id",
+ "Vagrant Id",
+ "Vagrant Id",
+ NULL,
+ (G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS));
+
+ g_object_class_install_properties (object_class, N_PROPS, properties);
+}
+
+static void
+gbp_vagrant_runtime_init (GbpVagrantRuntime *self)
+{
+}
+
+const gchar *
+gbp_vagrant_runtime_get_vagrant_id (GbpVagrantRuntime *self)
+{
+ g_return_val_if_fail (GBP_IS_VAGRANT_RUNTIME (self), NULL);
+
+ return self->vagrant_id;
+}
+
+const gchar *
+gbp_vagrant_runtime_get_provider (GbpVagrantRuntime *self)
+{
+ g_return_val_if_fail (GBP_IS_VAGRANT_RUNTIME (self), NULL);
+
+ return self->provider;
+}
+
+void
+gbp_vagrant_runtime_set_provider (GbpVagrantRuntime *self,
+ const gchar *provider)
+{
+ g_return_if_fail (GBP_IS_VAGRANT_RUNTIME (self));
+
+ if (!ide_str_equal0 (provider, self->provider))
+ {
+ g_free (self->provider);
+ self->provider = g_strdup (provider);
+ g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_PROVIDER]);
+ }
+}
+
+const gchar *
+gbp_vagrant_runtime_get_state (GbpVagrantRuntime *self)
+{
+ g_return_val_if_fail (GBP_IS_VAGRANT_RUNTIME (self), NULL);
+
+ return self->state;
+}
+
+void
+gbp_vagrant_runtime_set_state (GbpVagrantRuntime *self,
+ const gchar *state)
+{
+ g_return_if_fail (GBP_IS_VAGRANT_RUNTIME (self));
+
+ if (!ide_str_equal0 (state, self->state))
+ {
+ g_free (self->state);
+ self->state = g_strdup (state);
+ g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_STATE]);
+ }
+}
diff --git a/src/plugins/vagrant/gbp-vagrant-runtime.h b/src/plugins/vagrant/gbp-vagrant-runtime.h
new file mode 100644
index 000000000..30043d7a5
--- /dev/null
+++ b/src/plugins/vagrant/gbp-vagrant-runtime.h
@@ -0,0 +1,39 @@
+/* gbp-vagrant-runtime.h
+ *
+ * Copyright 2019 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 <libide-foundry.h>
+
+G_BEGIN_DECLS
+
+#define GBP_TYPE_VAGRANT_RUNTIME (gbp_vagrant_runtime_get_type())
+
+G_DECLARE_FINAL_TYPE (GbpVagrantRuntime, gbp_vagrant_runtime, GBP, VAGRANT_RUNTIME, IdeRuntime)
+
+const gchar *gbp_vagrant_runtime_get_vagrant_id (GbpVagrantRuntime *self);
+const gchar *gbp_vagrant_runtime_get_provider (GbpVagrantRuntime *self);
+void gbp_vagrant_runtime_set_provider (GbpVagrantRuntime *self,
+ const gchar *provider);
+const gchar *gbp_vagrant_runtime_get_state (GbpVagrantRuntime *self);
+void gbp_vagrant_runtime_set_state (GbpVagrantRuntime *self,
+ const gchar *state);
+
+G_END_DECLS
diff --git a/src/plugins/vagrant/gbp-vagrant-subprocess-launcher.c
b/src/plugins/vagrant/gbp-vagrant-subprocess-launcher.c
new file mode 100644
index 000000000..da39d4460
--- /dev/null
+++ b/src/plugins/vagrant/gbp-vagrant-subprocess-launcher.c
@@ -0,0 +1,101 @@
+/* gbp-vagrant-subprocess-launcher.c
+ *
+ * Copyright 2019 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 "gbp-vagrant-subprocess-launcher"
+
+#include "config.h"
+
+#include "gbp-vagrant-subprocess-launcher.h"
+
+struct _GbpVagrantSubprocessLauncher
+{
+ GObject parent_instance;
+ gchar *dir;
+};
+
+G_DEFINE_TYPE (GbpVagrantSubprocessLauncher, gbp_vagrant_subprocess_launcher, IDE_TYPE_SUBPROCESS_LAUNCHER)
+
+static IdeSubprocess *
+gbp_vagrant_subprocess_launcher_spawn (IdeSubprocessLauncher *launcher,
+ GCancellable *cancellable,
+ GError **error)
+{
+ GbpVagrantSubprocessLauncher *self = (GbpVagrantSubprocessLauncher *)launcher;
+ const gchar * const *argv;
+ const gchar *cwd;
+
+ g_assert (GBP_IS_VAGRANT_SUBPROCESS_LAUNCHER (self));
+ g_assert (!cancellable || G_IS_CANCELLABLE (cancellable));
+
+ argv = ide_subprocess_launcher_get_argv (launcher);
+
+ for (guint i = 0; argv[i] != NULL; i++)
+ {
+ if (ide_str_equal (argv[i], GBP_VAGRANT_SUBPROCESS_LAUNCHER_C_OPT))
+ {
+ ide_subprocess_launcher_replace_argv (launcher, i, "-c");
+ ide_subprocess_launcher_join_args_for_sh_c (launcher, i + 1);
+ }
+ }
+
+ /* TODO: We have to "cd some-dir/; before our other commands */
+
+ /* Ignore any CWD, since we have to run from the project tree */
+ cwd = ide_subprocess_launcher_get_cwd (launcher);
+ if (!g_str_has_prefix (cwd, self->dir))
+ ide_subprocess_launcher_set_cwd (launcher, self->dir);
+
+ return IDE_SUBPROCESS_LAUNCHER_CLASS (gbp_vagrant_subprocess_launcher_parent_class)->spawn (launcher,
cancellable, error);
+}
+
+static void
+gbp_vagrant_subprocess_launcher_finalize (GObject *object)
+{
+ G_OBJECT_CLASS (gbp_vagrant_subprocess_launcher_parent_class)->finalize (object);
+}
+
+static void
+gbp_vagrant_subprocess_launcher_class_init (GbpVagrantSubprocessLauncherClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ IdeSubprocessLauncherClass *launcher_class = IDE_SUBPROCESS_LAUNCHER_CLASS (klass);
+
+ launcher_class->spawn = gbp_vagrant_subprocess_launcher_spawn;
+
+ object_class->finalize = gbp_vagrant_subprocess_launcher_finalize;
+}
+
+static void
+gbp_vagrant_subprocess_launcher_init (GbpVagrantSubprocessLauncher *self)
+{
+}
+
+IdeSubprocessLauncher *
+gbp_vagrant_subprocess_launcher_new (const gchar *dir)
+{
+ GbpVagrantSubprocessLauncher *self;
+
+ self = g_object_new (GBP_TYPE_VAGRANT_SUBPROCESS_LAUNCHER,
+ "cwd", dir,
+ NULL);
+ self->dir = g_strdup (dir);
+
+ return IDE_SUBPROCESS_LAUNCHER (g_steal_pointer (&self));
+}
diff --git a/src/plugins/vagrant/gbp-vagrant-subprocess-launcher.h
b/src/plugins/vagrant/gbp-vagrant-subprocess-launcher.h
new file mode 100644
index 000000000..5b524da01
--- /dev/null
+++ b/src/plugins/vagrant/gbp-vagrant-subprocess-launcher.h
@@ -0,0 +1,34 @@
+/* gbp-vagrant-subprocess-launcher.h
+ *
+ * Copyright 2019 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 <libide-foundry.h>
+
+G_BEGIN_DECLS
+
+#define GBP_TYPE_VAGRANT_SUBPROCESS_LAUNCHER (gbp_vagrant_subprocess_launcher_get_type())
+#define GBP_VAGRANT_SUBPROCESS_LAUNCHER_C_OPT "@@VAGRANT_C_OPT@@"
+
+G_DECLARE_FINAL_TYPE (GbpVagrantSubprocessLauncher, gbp_vagrant_subprocess_launcher, GBP,
VAGRANT_SUBPROCESS_LAUNCHER, IdeSubprocessLauncher)
+
+IdeSubprocessLauncher *gbp_vagrant_subprocess_launcher_new (const gchar *dir);
+
+G_END_DECLS
diff --git a/src/plugins/vagrant/gbp-vagrant-table.c b/src/plugins/vagrant/gbp-vagrant-table.c
new file mode 100644
index 000000000..353ce0677
--- /dev/null
+++ b/src/plugins/vagrant/gbp-vagrant-table.c
@@ -0,0 +1,129 @@
+/* gbp-vagrant-table.c
+ *
+ * Copyright 2019 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 "gbp-vagrant-table"
+
+#include "config.h"
+
+#include <libide-io.h>
+
+#include "gbp-vagrant-table.h"
+
+struct _GbpVagrantTable
+{
+ gchar *data;
+};
+
+GbpVagrantTable *
+gbp_vagrant_table_new_take (gchar *data)
+{
+ GbpVagrantTable *self;
+
+ self = g_slice_new0 (GbpVagrantTable);
+ self->data = data;
+
+ return g_steal_pointer (&self);
+}
+
+void
+gbp_vagrant_table_free (GbpVagrantTable *self)
+{
+ g_clear_pointer (&self->data, g_free);
+ g_slice_free (GbpVagrantTable, self);
+}
+
+void
+gbp_vagrant_table_iter_init (GbpVagrantTableIter *iter,
+ GbpVagrantTable *table)
+{
+ ide_line_reader_init (&iter->reader, table->data, -1);
+}
+
+gboolean
+gbp_vagrant_table_iter_next (GbpVagrantTableIter *iter)
+{
+ gchar *ret;
+ gsize len;
+
+ g_return_val_if_fail (iter != NULL, FALSE);
+
+ if ((ret = ide_line_reader_next (&iter->reader, &len)))
+ {
+ iter->cur = ret;
+ ret [len] = 0;
+ return TRUE;
+ }
+
+ iter->cur = NULL;
+ return FALSE;
+}
+
+static gchar *
+unescape (gchar *str)
+{
+ gchar *ptr;
+ gchar *endptr;
+
+#define COMMA "%!(VAGRANT_COMMA)"
+
+ endptr = str + strlen (str);
+
+ while ((ptr = strstr (str, COMMA)))
+ {
+ gchar *after = ptr + strlen (COMMA);
+
+ *ptr = ',';
+ memmove (ptr + 1, after, endptr - after);
+ ptr++;
+ }
+
+#undef COMMA
+
+ return str;
+}
+
+gchar *
+gbp_vagrant_table_iter_get_column (GbpVagrantTableIter *iter,
+ guint column)
+{
+ gchar *line;
+
+ g_return_val_if_fail (iter != NULL, NULL);
+ g_return_val_if_fail (iter->cur != NULL, NULL);
+
+ line = iter->cur;
+
+ while (column > 0 && line != NULL)
+ {
+ column--;
+ line = strchr (line, ',');
+ if (line != NULL)
+ line++;
+ }
+
+ if (column == 0 && line != NULL)
+ {
+ gchar *end = strchrnul (line, ',');
+ g_autofree gchar *val = g_strndup (line, end - line);
+ return unescape (g_steal_pointer (&val));
+ }
+
+ return NULL;
+}
diff --git a/src/plugins/vagrant/gbp-vagrant-table.h b/src/plugins/vagrant/gbp-vagrant-table.h
new file mode 100644
index 000000000..92c00b2e2
--- /dev/null
+++ b/src/plugins/vagrant/gbp-vagrant-table.h
@@ -0,0 +1,46 @@
+/* gbp-vagrant-table.h
+ *
+ * Copyright 2019 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 <libide-io.h>
+
+G_BEGIN_DECLS
+
+typedef struct _GbpVagrantTable GbpVagrantTable;
+
+typedef struct
+{
+ /*< private >*/
+ IdeLineReader reader;
+ gchar *cur;
+} GbpVagrantTableIter;
+
+GbpVagrantTable *gbp_vagrant_table_new_take (gchar *data);
+void gbp_vagrant_table_free (GbpVagrantTable *self);
+void gbp_vagrant_table_iter_init (GbpVagrantTableIter *iter,
+ GbpVagrantTable *self);
+gboolean gbp_vagrant_table_iter_next (GbpVagrantTableIter *iter);
+gchar *gbp_vagrant_table_iter_get_column (GbpVagrantTableIter *iter,
+ guint column);
+
+G_DEFINE_AUTOPTR_CLEANUP_FUNC (GbpVagrantTable, gbp_vagrant_table_free)
+
+G_END_DECLS
diff --git a/src/plugins/vagrant/meson.build b/src/plugins/vagrant/meson.build
new file mode 100644
index 000000000..a892b94cd
--- /dev/null
+++ b/src/plugins/vagrant/meson.build
@@ -0,0 +1,19 @@
+if get_option('plugin_vagrant')
+
+plugins_sources += files([
+ 'vagrant-plugin.c',
+ 'gbp-vagrant-runtime.c',
+ 'gbp-vagrant-runtime-provider.c',
+ 'gbp-vagrant-subprocess-launcher.c',
+ 'gbp-vagrant-table.c',
+])
+
+plugin_vagrant_resources = gnome.compile_resources(
+ 'vagrant-resources',
+ 'vagrant.gresource.xml',
+ c_name: 'gbp_vagrant'
+)
+
+plugins_sources += plugin_vagrant_resources
+
+endif
diff --git a/src/plugins/vagrant/vagrant-plugin.c b/src/plugins/vagrant/vagrant-plugin.c
new file mode 100644
index 000000000..3875f0db3
--- /dev/null
+++ b/src/plugins/vagrant/vagrant-plugin.c
@@ -0,0 +1,36 @@
+/* vagrant-plugin.c
+ *
+ * Copyright 2019 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 "vagrant-plugin"
+
+#include "config.h"
+
+#include <libpeas/peas.h>
+#include <libide-foundry.h>
+
+#include "gbp-vagrant-runtime-provider.h"
+
+_IDE_EXTERN void
+_gbp_vagrant_register_types (PeasObjectModule *module)
+{
+ peas_object_module_register_extension_type (module,
+ IDE_TYPE_RUNTIME_PROVIDER,
+ GBP_TYPE_VAGRANT_RUNTIME_PROVIDER);
+}
diff --git a/src/plugins/vagrant/vagrant.gresource.xml b/src/plugins/vagrant/vagrant.gresource.xml
new file mode 100644
index 000000000..0123b47a7
--- /dev/null
+++ b/src/plugins/vagrant/vagrant.gresource.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<gresources>
+ <gresource prefix="/plugins/vagrant">
+ <file>vagrant.plugin</file>
+ </gresource>
+</gresources>
diff --git a/src/plugins/vagrant/vagrant.plugin b/src/plugins/vagrant/vagrant.plugin
new file mode 100644
index 000000000..593bb069e
--- /dev/null
+++ b/src/plugins/vagrant/vagrant.plugin
@@ -0,0 +1,9 @@
+[Plugin]
+Authors=Christian Hergert <christian hergert me>
+Builtin=true
+Copyright=Copyright © 2019 Christian Hergert
+Depends=buildui;
+Description=Provides integration with vagrant
+Embedded=_gbp_vagrant_register_types
+Module=vagrant
+Name=Vagrant
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]