[gnome-builder/wip/gtk4-port: 1157/1774] plugins/cargo: port Cargo build system plugin to C
- From: Christian Hergert <chergert src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-builder/wip/gtk4-port: 1157/1774] plugins/cargo: port Cargo build system plugin to C
- Date: Mon, 11 Jul 2022 22:31:36 +0000 (UTC)
commit cac436f5b43cd472c45c69777fd916a157f819a2
Author: Christian Hergert <chergert redhat com>
Date: Wed May 25 13:59:42 2022 -0700
plugins/cargo: port Cargo build system plugin to C
This is an incremental step on our path in #1670 to remove PyGObject
plugins or port them to C.
src/plugins/cargo/cargo-plugin.c | 55 +++++
src/plugins/cargo/cargo.gresource.xml | 6 +
src/plugins/cargo/cargo.plugin | 10 +-
src/plugins/cargo/cargo_plugin.py | 257 ---------------------
.../cargo/gbp-cargo-build-system-discovery.c | 47 ++++
.../cargo/gbp-cargo-build-system-discovery.h | 31 +++
src/plugins/cargo/gbp-cargo-build-system.c | 252 ++++++++++++++++++++
src/plugins/cargo/gbp-cargo-build-system.h | 37 +++
src/plugins/cargo/gbp-cargo-dependency-updater.c | 168 ++++++++++++++
src/plugins/cargo/gbp-cargo-dependency-updater.h | 31 +++
src/plugins/cargo/gbp-cargo-pipeline-addin.c | 178 ++++++++++++++
src/plugins/cargo/gbp-cargo-pipeline-addin.h | 31 +++
src/plugins/cargo/gbp-cargo-run-command-provider.c | 123 ++++++++++
src/plugins/cargo/gbp-cargo-run-command-provider.h | 31 +++
src/plugins/cargo/meson.build | 23 +-
15 files changed, 1009 insertions(+), 271 deletions(-)
---
diff --git a/src/plugins/cargo/cargo-plugin.c b/src/plugins/cargo/cargo-plugin.c
new file mode 100644
index 000000000..9f049e878
--- /dev/null
+++ b/src/plugins/cargo/cargo-plugin.c
@@ -0,0 +1,55 @@
+/* cargo-plugin.c
+ *
+ * Copyright 2016-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 "cargo-plugin"
+
+#include "config.h"
+
+#include <libpeas/peas.h>
+
+#include <libide-editor.h>
+#include <libide-gui.h>
+#include <libide-tree.h>
+
+#include "gbp-cargo-build-system.h"
+#include "gbp-cargo-build-system-discovery.h"
+#include "gbp-cargo-dependency-updater.h"
+#include "gbp-cargo-pipeline-addin.h"
+#include "gbp-cargo-run-command-provider.h"
+
+_IDE_EXTERN void
+_gbp_cargo_register_types (PeasObjectModule *module)
+{
+ peas_object_module_register_extension_type (module,
+ IDE_TYPE_BUILD_SYSTEM,
+ GBP_TYPE_CARGO_BUILD_SYSTEM);
+ peas_object_module_register_extension_type (module,
+ IDE_TYPE_BUILD_SYSTEM_DISCOVERY,
+ GBP_TYPE_CARGO_BUILD_SYSTEM_DISCOVERY);
+ peas_object_module_register_extension_type (module,
+ IDE_TYPE_DEPENDENCY_UPDATER,
+ GBP_TYPE_CARGO_DEPENDENCY_UPDATER);
+ peas_object_module_register_extension_type (module,
+ IDE_TYPE_PIPELINE_ADDIN,
+ GBP_TYPE_CARGO_PIPELINE_ADDIN);
+ peas_object_module_register_extension_type (module,
+ IDE_TYPE_RUN_COMMAND_PROVIDER,
+ GBP_TYPE_CARGO_RUN_COMMAND_PROVIDER);
+}
diff --git a/src/plugins/cargo/cargo.gresource.xml b/src/plugins/cargo/cargo.gresource.xml
new file mode 100644
index 000000000..7270ec40e
--- /dev/null
+++ b/src/plugins/cargo/cargo.gresource.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<gresources>
+ <gresource prefix="/plugins/cargo">
+ <file>cargo.plugin</file>
+ </gresource>
+</gresources>
diff --git a/src/plugins/cargo/cargo.plugin b/src/plugins/cargo/cargo.plugin
index 14d8a9f34..cfb0e8a27 100644
--- a/src/plugins/cargo/cargo.plugin
+++ b/src/plugins/cargo/cargo.plugin
@@ -1,12 +1,10 @@
[Plugin]
Authors=Christian Hergert <christian hergert me>
Builtin=true
-Copyright=Copyright © 2016 Christian Hergert
+Copyright=Copyright © 2016-2022 Christian Hergert
Description=Provides integration with the Cargo build system
-Hidden=true
-Loader=python3
-Module=cargo_plugin
-Name=Cargo
+Embedded=_gbp_cargo_register_types
+Module=cargo
+Name=Cargo Build System
X-Project-File-Filter-Name=Cargo (Cargo.toml)
X-Project-File-Filter-Pattern=Cargo.toml
-X-Builder-ABI=@PACKAGE_ABI@
diff --git a/src/plugins/cargo/gbp-cargo-build-system-discovery.c
b/src/plugins/cargo/gbp-cargo-build-system-discovery.c
new file mode 100644
index 000000000..98a133348
--- /dev/null
+++ b/src/plugins/cargo/gbp-cargo-build-system-discovery.c
@@ -0,0 +1,47 @@
+/* gbp-cargo-build-system-discovery.c
+ *
+ * Copyright 2016-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 "gbp-cargo-build-system-discovery"
+
+#include "config.h"
+
+#include "gbp-cargo-build-system-discovery.h"
+
+struct _GbpCargoBuildSystemDiscovery
+{
+ IdeSimpleBuildSystemDiscovery parent_instance;
+};
+
+G_DEFINE_FINAL_TYPE (GbpCargoBuildSystemDiscovery, gbp_cargo_build_system_discovery,
IDE_TYPE_SIMPLE_BUILD_SYSTEM_DISCOVERY)
+
+static void
+gbp_cargo_build_system_discovery_class_init (GbpCargoBuildSystemDiscoveryClass *klass)
+{
+}
+
+static void
+gbp_cargo_build_system_discovery_init (GbpCargoBuildSystemDiscovery *self)
+{
+ g_object_set (self,
+ "glob", "Cargo.toml",
+ "hint", "cargo",
+ "priority", -200,
+ NULL);
+}
diff --git a/src/plugins/cargo/gbp-cargo-build-system-discovery.h
b/src/plugins/cargo/gbp-cargo-build-system-discovery.h
new file mode 100644
index 000000000..15d278eea
--- /dev/null
+++ b/src/plugins/cargo/gbp-cargo-build-system-discovery.h
@@ -0,0 +1,31 @@
+/* gbp-cargo-build-system-discovery.h
+ *
+ * Copyright 2016-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 <libide-foundry.h>
+
+G_BEGIN_DECLS
+
+#define GBP_TYPE_CARGO_BUILD_SYSTEM_DISCOVERY (gbp_cargo_build_system_discovery_get_type())
+
+G_DECLARE_FINAL_TYPE (GbpCargoBuildSystemDiscovery, gbp_cargo_build_system_discovery, GBP,
CARGO_BUILD_SYSTEM_DISCOVERY, IdeSimpleBuildSystemDiscovery)
+
+G_END_DECLS
diff --git a/src/plugins/cargo/gbp-cargo-build-system.c b/src/plugins/cargo/gbp-cargo-build-system.c
new file mode 100644
index 000000000..b281306c4
--- /dev/null
+++ b/src/plugins/cargo/gbp-cargo-build-system.c
@@ -0,0 +1,252 @@
+/* gbp-cargo-build-system.c
+ *
+ * Copyright 2016-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 "gbp-cargo-build-system"
+#define CARGO "cargo"
+
+#include "config.h"
+
+#include "gbp-cargo-build-system.h"
+
+struct _GbpCargoBuildSystem
+{
+ IdeObject parent_instance;
+ GFile *project_file;
+};
+
+enum {
+ PROP_0,
+ PROP_PROJECT_FILE,
+ N_PROPS
+};
+
+static char *
+gbp_cargo_build_system_get_id (IdeBuildSystem *build_system)
+{
+ return g_strdup (CARGO);
+}
+
+static char *
+gbp_cargo_build_system_get_display_name (IdeBuildSystem *build_system)
+{
+ return g_strdup ("Cargo");
+}
+
+static int
+gbp_cargo_build_system_get_priority (IdeBuildSystem *build_system)
+{
+ return -200;
+}
+
+static gboolean
+gbp_cargo_build_system_supports_language (IdeBuildSystem *build_system,
+ const char *language)
+{
+ return g_strv_contains (IDE_STRV_INIT ("rust", "c", "cpp"), language);
+}
+
+static void
+build_system_iface_init (IdeBuildSystemInterface *iface)
+{
+ iface->get_id = gbp_cargo_build_system_get_id;
+ iface->get_display_name = gbp_cargo_build_system_get_display_name;
+ iface->get_priority = gbp_cargo_build_system_get_priority;
+ iface->supports_language = gbp_cargo_build_system_supports_language;
+}
+
+G_DEFINE_FINAL_TYPE_WITH_CODE (GbpCargoBuildSystem, gbp_cargo_build_system, IDE_TYPE_OBJECT,
+ G_IMPLEMENT_INTERFACE (IDE_TYPE_BUILD_SYSTEM, build_system_iface_init))
+
+static GParamSpec *properties [N_PROPS];
+
+static void
+gbp_cargo_build_system_dispose (GObject *object)
+{
+ GbpCargoBuildSystem *self = (GbpCargoBuildSystem *)object;
+
+ g_clear_object (&self->project_file);
+
+ G_OBJECT_CLASS (gbp_cargo_build_system_parent_class)->dispose (object);
+}
+
+static void
+gbp_cargo_build_system_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ GbpCargoBuildSystem *self = GBP_CARGO_BUILD_SYSTEM (object);
+
+ switch (prop_id)
+ {
+ case PROP_PROJECT_FILE:
+ g_value_set_object (value, self->project_file);
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+gbp_cargo_build_system_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ GbpCargoBuildSystem *self = GBP_CARGO_BUILD_SYSTEM (object);
+
+ switch (prop_id)
+ {
+ case PROP_PROJECT_FILE:
+ g_set_object (&self->project_file, g_value_get_object (value));
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+gbp_cargo_build_system_class_init (GbpCargoBuildSystemClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->dispose = gbp_cargo_build_system_dispose;
+ object_class->get_property = gbp_cargo_build_system_get_property;
+ object_class->set_property = gbp_cargo_build_system_set_property;
+
+ properties [PROP_PROJECT_FILE] =
+ g_param_spec_object ("project-file",
+ "Project File",
+ "The project file (Cargo.toml)",
+ G_TYPE_FILE,
+ (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+ g_object_class_install_properties (object_class, N_PROPS, properties);
+}
+
+static void
+gbp_cargo_build_system_init (GbpCargoBuildSystem *self)
+{
+}
+
+char *
+gbp_cargo_build_system_get_project_dir (GbpCargoBuildSystem *self)
+{
+ g_autoptr(GFile) workdir = NULL;
+ g_autofree char *base = NULL;
+ IdeContext *context;
+
+ g_return_val_if_fail (GBP_IS_CARGO_BUILD_SYSTEM (self), NULL);
+
+ context = ide_object_get_context (IDE_OBJECT (self));
+ workdir = ide_context_ref_workdir (context);
+
+ if (self->project_file == NULL)
+ return g_strdup (g_file_peek_path (workdir));
+
+ base = g_file_get_basename (self->project_file);
+
+ if (strcasecmp (base, "Cargo.toml") != 0)
+ {
+ g_autoptr(GFile) parent = g_file_get_parent (self->project_file);
+ return g_file_get_path (parent);
+ }
+
+ return g_file_get_path (self->project_file);
+}
+
+char *
+gbp_cargo_build_system_get_cargo_toml_path (GbpCargoBuildSystem *self)
+{
+ g_autofree char *base = NULL;
+ g_autoptr(GFile) child = NULL;
+
+ g_return_val_if_fail (GBP_IS_CARGO_BUILD_SYSTEM (self), NULL);
+
+ base = g_file_get_basename (self->project_file);
+ if (strcasecmp (base, "Cargo.toml") == 0)
+ return g_file_get_path (self->project_file);
+
+ child = g_file_get_child (self->project_file, "Cargo.toml");
+ return g_file_get_path (child);
+}
+
+/**
+ * gbp_cargo_build_system_locate_cargo:
+ * @self: (nullable): a #GbpCargoBuildSystem or %NULL
+ * @pipeline: (nullable): an #IdePipeline or %NULL
+ * @config: (nullable): an #IdeConfig or %NULL
+ *
+ * Currently, @self may be %NULL but is kept around so that in
+ * the future we may have other fallbacks which could take use
+ * of the build system.
+ *
+ * This function will first check for "CARGO" in @config's environment
+ * variables. If specified, that will be used.
+ *
+ * Then the config's runtime+sdk-extensions will be checked and if it
+ * contains "cargo" in the pipeline's $PATH, that will be used.
+ *
+ * Then if ~/.cargo/bin/cargo exists, that will be used.
+ *
+ * Lastly, nothing was found, so "cargo" will be used with the hope
+ * that something, somewhere, will find it when executing.
+ *
+ * Returns: (transfer full) (not nullable): a path to a cargo program
+ * or "cargo" in the case that a specific path was not found.
+ */
+char *
+gbp_cargo_build_system_locate_cargo (GbpCargoBuildSystem *self,
+ IdePipeline *pipeline,
+ IdeConfig *config)
+{
+ g_autofree char *cargo_in_home = NULL;
+ IdeRuntime *runtime = NULL;
+ const char *envvar;
+
+ g_return_val_if_fail (!self || GBP_IS_CARGO_BUILD_SYSTEM (self), NULL);
+ g_return_val_if_fail (!pipeline || IDE_IS_PIPELINE (pipeline), NULL);
+ g_return_val_if_fail (!config || IDE_IS_CONFIG (config), NULL);
+
+ /* First check CARGO=path override in IdeConfig */
+ if (config != NULL)
+ {
+ if ((envvar = ide_config_getenv (config, "CARGO")))
+ return g_strdup (envvar);
+ }
+
+ /* Next see if the pipeline or one of it's extensions has Cargo */
+ if (pipeline != NULL)
+ {
+ if (ide_pipeline_contains_program_in_path (pipeline, CARGO, NULL))
+ return g_strdup (CARGO);
+ }
+
+ /* Now see if the user has cargo installed in ~/.cargo/bin */
+ cargo_in_home = g_build_filename (g_get_home_dir (), "bin", CARGO, NULL);
+ if (g_file_test (cargo_in_home, G_FILE_TEST_IS_EXECUTABLE))
+ return g_steal_pointer (&cargo_in_home);
+
+ /* Fallback to "cargo" and hope for the best */
+ return g_strdup (CARGO);
+}
+
diff --git a/src/plugins/cargo/gbp-cargo-build-system.h b/src/plugins/cargo/gbp-cargo-build-system.h
new file mode 100644
index 000000000..143b89857
--- /dev/null
+++ b/src/plugins/cargo/gbp-cargo-build-system.h
@@ -0,0 +1,37 @@
+/* gbp-cargo-build-system.h
+ *
+ * Copyright 2016-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 <libide-foundry.h>
+
+G_BEGIN_DECLS
+
+#define GBP_TYPE_CARGO_BUILD_SYSTEM (gbp_cargo_build_system_get_type())
+
+G_DECLARE_FINAL_TYPE (GbpCargoBuildSystem, gbp_cargo_build_system, GBP, CARGO_BUILD_SYSTEM, IdeObject)
+
+char *gbp_cargo_build_system_get_cargo_toml_path (GbpCargoBuildSystem *self);
+char *gbp_cargo_build_system_get_project_dir (GbpCargoBuildSystem *self);
+char *gbp_cargo_build_system_locate_cargo (GbpCargoBuildSystem *self,
+ IdePipeline *pipeline,
+ IdeConfig *config);
+
+G_END_DECLS
diff --git a/src/plugins/cargo/gbp-cargo-dependency-updater.c
b/src/plugins/cargo/gbp-cargo-dependency-updater.c
new file mode 100644
index 000000000..48efb6adc
--- /dev/null
+++ b/src/plugins/cargo/gbp-cargo-dependency-updater.c
@@ -0,0 +1,168 @@
+/* gbp-cargo-dependency-updater.c
+ *
+ * Copyright 2016-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 "gbp-cargo-dependency-updater"
+
+#include "config.h"
+
+#include <libide-foundry.h>
+#include <libide-threading.h>
+
+#include "gbp-cargo-build-system.h"
+#include "gbp-cargo-dependency-updater.h"
+
+struct _GbpCargoDependencyUpdater
+{
+ IdeObject parent_instance;
+};
+
+static void
+gbp_cargo_dependency_updater_wait_check_cb (GObject *object,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ IdeSubprocess *subprocess = (IdeSubprocess *)object;
+ g_autoptr(IdeTask) task = user_data;
+ g_autoptr(GError) error = NULL;
+
+ IDE_ENTRY;
+
+ g_assert (IDE_IS_SUBPROCESS (subprocess));
+ 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
+ ide_task_return_boolean (task, TRUE);
+
+ IDE_EXIT;
+}
+
+static void
+gbp_cargo_dependency_updater_update_async (IdeDependencyUpdater *updater,
+ 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_autofree char *cargo_toml = NULL;
+ g_autofree char *cargo = NULL;
+ IdeBuildManager *build_manager;
+ IdeBuildSystem *build_system;
+ IdePipeline *pipeline;
+ IdeContext *context;
+ const char *builddir;
+ IdeConfig *config;
+
+ IDE_ENTRY;
+
+ g_assert (GBP_IS_CARGO_DEPENDENCY_UPDATER (updater));
+ g_assert (!cancellable || G_IS_CANCELLABLE (cancellable));
+
+ task = ide_task_new (updater, cancellable, callback, user_data);
+ ide_task_set_source_tag (task, gbp_cargo_dependency_updater_update_async);
+
+ context = ide_object_get_context (IDE_OBJECT (updater));
+ build_system = ide_build_system_from_context (context);
+
+ if (!GBP_IS_CARGO_BUILD_SYSTEM (build_system))
+ {
+ ide_task_return_unsupported_error (task);
+ IDE_EXIT;
+ }
+
+ build_manager = ide_build_manager_from_context (context);
+ pipeline = ide_build_manager_get_pipeline (build_manager);
+
+ if (pipeline == NULL)
+ {
+ ide_task_return_new_error (task,
+ G_IO_ERROR,
+ G_IO_ERROR_NOT_INITIALIZED,
+ "Cannot update cargo dependencies. Build pipeline is not initialized.");
+ IDE_EXIT;
+ }
+
+ config = ide_pipeline_get_config (pipeline);
+ cargo = gbp_cargo_build_system_locate_cargo (GBP_CARGO_BUILD_SYSTEM (build_system), pipeline, config);
+ cargo_toml = gbp_cargo_build_system_get_cargo_toml_path (GBP_CARGO_BUILD_SYSTEM (build_system));
+
+ launcher = ide_pipeline_create_launcher (pipeline, NULL);
+ builddir = ide_pipeline_get_builddir (pipeline);
+ ide_subprocess_launcher_setenv (launcher, "CARGO_TARGET_DIR", builddir, TRUE);
+ ide_subprocess_launcher_push_argv (launcher, cargo);
+ ide_subprocess_launcher_push_argv (launcher, "update");
+ ide_subprocess_launcher_push_argv (launcher, "--manifest-path");
+ ide_subprocess_launcher_push_argv (launcher, cargo_toml);
+ ide_pipeline_attach_pty (pipeline, launcher);
+
+ if (!(subprocess = ide_subprocess_launcher_spawn (launcher, cancellable, NULL)))
+ {
+ ide_task_return_error (task, g_steal_pointer (&error));
+ IDE_EXIT;
+ }
+
+ ide_subprocess_wait_check_async (subprocess,
+ cancellable,
+ gbp_cargo_dependency_updater_wait_check_cb,
+ g_steal_pointer (&task));
+
+ IDE_EXIT;
+}
+
+static gboolean
+gbp_cargo_dependency_updater_update_finish (IdeDependencyUpdater *updater,
+ GAsyncResult *result,
+ GError **error)
+{
+ gboolean ret;
+
+ IDE_ENTRY;
+
+ g_assert (GBP_IS_CARGO_BUILD_SYSTEM (updater));
+ g_assert (IDE_IS_TASK (result));
+
+ ret = ide_task_propagate_boolean (IDE_TASK (result), error);
+
+ IDE_RETURN (ret);
+}
+
+static void
+dependency_updater_iface_init (IdeDependencyUpdaterInterface *iface)
+{
+ iface->update_async = gbp_cargo_dependency_updater_update_async;
+ iface->update_finish = gbp_cargo_dependency_updater_update_finish;
+}
+
+G_DEFINE_FINAL_TYPE_WITH_CODE (GbpCargoDependencyUpdater, gbp_cargo_dependency_updater, IDE_TYPE_OBJECT,
+ G_IMPLEMENT_INTERFACE (IDE_TYPE_DEPENDENCY_UPDATER,
dependency_updater_iface_init))
+static void
+gbp_cargo_dependency_updater_class_init (GbpCargoDependencyUpdaterClass *klass)
+{
+}
+
+static void
+gbp_cargo_dependency_updater_init (GbpCargoDependencyUpdater *self)
+{
+}
diff --git a/src/plugins/cargo/gbp-cargo-dependency-updater.h
b/src/plugins/cargo/gbp-cargo-dependency-updater.h
new file mode 100644
index 000000000..044846358
--- /dev/null
+++ b/src/plugins/cargo/gbp-cargo-dependency-updater.h
@@ -0,0 +1,31 @@
+/* gbp-cargo-dependency-updater.h
+ *
+ * Copyright 2016-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 <libide-core.h>
+
+G_BEGIN_DECLS
+
+#define GBP_TYPE_CARGO_DEPENDENCY_UPDATER (gbp_cargo_dependency_updater_get_type())
+
+G_DECLARE_FINAL_TYPE (GbpCargoDependencyUpdater, gbp_cargo_dependency_updater, GBP,
CARGO_DEPENDENCY_UPDATER, IdeObject)
+
+G_END_DECLS
diff --git a/src/plugins/cargo/gbp-cargo-pipeline-addin.c b/src/plugins/cargo/gbp-cargo-pipeline-addin.c
new file mode 100644
index 000000000..ad0123289
--- /dev/null
+++ b/src/plugins/cargo/gbp-cargo-pipeline-addin.c
@@ -0,0 +1,178 @@
+/* gbp-cargo-pipeline-addin.c
+ *
+ * Copyright 2016-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 "gbp-cargo-pipeline-addin"
+
+#include "config.h"
+
+#include <glib/gi18n.h>
+
+#include <libide-foundry.h>
+
+#include "gbp-cargo-build-system.h"
+#include "gbp-cargo-pipeline-addin.h"
+
+struct _GbpCargoPipelineAddin
+{
+ IdeObject parent_instance;
+};
+
+static IdeSubprocessLauncher *
+create_launcher (IdePipeline *pipeline,
+ const char *project_dir,
+ const char *cargo)
+{
+ IdeSubprocessLauncher *ret;
+ const char *builddir;
+
+ g_assert (IDE_IS_PIPELINE (pipeline));
+
+ if (!(ret = ide_pipeline_create_launcher (pipeline, NULL)))
+ return NULL;
+
+ builddir = ide_pipeline_get_builddir (pipeline);
+ ide_subprocess_launcher_setenv (ret, "CARGO_TARGET_DIR", builddir, TRUE);
+ ide_subprocess_launcher_set_cwd (ret, project_dir);
+ ide_subprocess_launcher_push_argv (ret, cargo);
+
+ return ret;
+}
+
+static void
+query_cb (IdePipelineStage *stage,
+ IdePipeline *pipeline,
+ GPtrArray *targets,
+ GCancellable *cancellable,
+ gpointer user_data)
+{
+ g_assert (IDE_IS_PIPELINE_STAGE (stage));
+ g_assert (IDE_IS_PIPELINE (pipeline));
+ g_assert (!cancellable || G_IS_CANCELLABLE (cancellable));
+
+ /* Always defer to cargo to check if build is needed */
+ ide_pipeline_stage_set_completed (stage, FALSE);
+}
+
+static void
+gbp_cargo_pipeline_addin_load (IdePipelineAddin *addin,
+ IdePipeline *pipeline)
+{
+ g_autoptr(IdeSubprocessLauncher) fetch_launcher = NULL;
+ g_autoptr(IdeSubprocessLauncher) build_launcher = NULL;
+ g_autoptr(IdeSubprocessLauncher) clean_launcher = NULL;
+ IdePipelineStage *stage;
+ g_autofree char *project_dir = NULL;
+ g_autofree char *cargo = NULL;
+ IdeBuildSystem *build_system;
+ const char *config_opts;
+ IdeContext *context;
+ IdeConfig *config;
+ guint id;
+
+ IDE_ENTRY;
+
+ g_assert (GBP_IS_CARGO_PIPELINE_ADDIN (addin));
+ g_assert (IDE_IS_PIPELINE (pipeline));
+
+ context = ide_object_get_context (IDE_OBJECT (addin));
+ build_system = ide_build_system_from_context (context);
+
+ if (!GBP_IS_CARGO_BUILD_SYSTEM (build_system))
+ IDE_EXIT;
+
+ project_dir = gbp_cargo_build_system_get_project_dir (GBP_CARGO_BUILD_SYSTEM (build_system));
+ config = ide_pipeline_get_config (pipeline);
+ config_opts = ide_config_get_config_opts (config);
+ cargo = gbp_cargo_build_system_locate_cargo (GBP_CARGO_BUILD_SYSTEM (build_system), pipeline, config);
+
+ g_assert (project_dir != NULL);
+ g_assert (IDE_IS_CONFIG (config));
+ g_assert (cargo != NULL);
+
+ fetch_launcher = create_launcher (pipeline, project_dir, cargo);
+ ide_subprocess_launcher_push_argv (fetch_launcher, "fetch");
+ id = ide_pipeline_attach_launcher (pipeline, IDE_PIPELINE_PHASE_DOWNLOADS, 0, fetch_launcher);
+ ide_pipeline_addin_track (addin, id);
+
+ build_launcher = create_launcher (pipeline, project_dir, cargo);
+ ide_subprocess_launcher_push_argv (build_launcher, "build");
+ ide_subprocess_launcher_push_argv (build_launcher, "--message-format");
+ ide_subprocess_launcher_push_argv (build_launcher, "human");
+
+ if (!ide_pipeline_is_native (pipeline))
+ {
+ IdeTriplet *triplet = ide_pipeline_get_host_triplet (pipeline);
+
+ ide_subprocess_launcher_push_argv (build_launcher, "--target");
+ ide_subprocess_launcher_push_argv (build_launcher, ide_triplet_get_full_name (triplet));
+ }
+
+ if (ide_config_get_parallelism (config) > 0)
+ {
+ int j = ide_config_get_parallelism (config);
+ ide_subprocess_launcher_push_argv_format (build_launcher, "-j%d", j);
+ }
+
+ if (!ide_config_get_debug (config))
+ ide_subprocess_launcher_push_argv (build_launcher, "--release");
+
+ /* Configure Options get passed to "cargo build" because there is no
+ * equivalent "configure stage" for cargo.
+ */
+ if (!ide_str_empty0 (config_opts))
+ {
+ g_auto(GStrv) args = NULL;
+ int argc;
+
+ if (g_shell_parse_argv (config_opts, &argc, &args, NULL))
+ ide_subprocess_launcher_push_args (build_launcher, (const char * const *)args);
+ }
+
+ clean_launcher = create_launcher (pipeline, project_dir, cargo);
+ ide_subprocess_launcher_push_argv (clean_launcher, "clean");
+
+ stage = ide_pipeline_stage_launcher_new (context, build_launcher);
+ ide_pipeline_stage_set_name (stage, _("Building project"));
+ ide_pipeline_stage_launcher_set_clean_launcher (IDE_PIPELINE_STAGE_LAUNCHER (stage), clean_launcher);
+ g_signal_connect (stage, "query", G_CALLBACK (query_cb), NULL);
+ id = ide_pipeline_attach (pipeline, IDE_PIPELINE_PHASE_BUILD, 0, stage);
+ ide_pipeline_addin_track (addin, id);
+
+ IDE_EXIT;
+}
+
+static void
+pipeline_addin_iface_init (IdePipelineAddinInterface *iface)
+{
+ iface->load = gbp_cargo_pipeline_addin_load;
+}
+
+G_DEFINE_FINAL_TYPE_WITH_CODE (GbpCargoPipelineAddin, gbp_cargo_pipeline_addin, IDE_TYPE_OBJECT,
+ G_IMPLEMENT_INTERFACE (IDE_TYPE_PIPELINE_ADDIN, pipeline_addin_iface_init))
+
+static void
+gbp_cargo_pipeline_addin_class_init (GbpCargoPipelineAddinClass *klass)
+{
+}
+
+static void
+gbp_cargo_pipeline_addin_init (GbpCargoPipelineAddin *self)
+{
+}
diff --git a/src/plugins/cargo/gbp-cargo-pipeline-addin.h b/src/plugins/cargo/gbp-cargo-pipeline-addin.h
new file mode 100644
index 000000000..cdb864b2a
--- /dev/null
+++ b/src/plugins/cargo/gbp-cargo-pipeline-addin.h
@@ -0,0 +1,31 @@
+/* gbp-cargo-pipeline-addin.h
+ *
+ * Copyright 2016-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 <libide-core.h>
+
+G_BEGIN_DECLS
+
+#define GBP_TYPE_CARGO_PIPELINE_ADDIN (gbp_cargo_pipeline_addin_get_type())
+
+G_DECLARE_FINAL_TYPE (GbpCargoPipelineAddin, gbp_cargo_pipeline_addin, GBP, CARGO_PIPELINE_ADDIN, IdeObject)
+
+G_END_DECLS
diff --git a/src/plugins/cargo/gbp-cargo-run-command-provider.c
b/src/plugins/cargo/gbp-cargo-run-command-provider.c
new file mode 100644
index 000000000..1132db582
--- /dev/null
+++ b/src/plugins/cargo/gbp-cargo-run-command-provider.c
@@ -0,0 +1,123 @@
+/* gbp-cargo-run-command-provider.c
+ *
+ * Copyright 2016-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 "gbp-cargo-run-command-provider"
+
+#include "config.h"
+
+#include <glib/gi18n.h>
+
+#include <libide-foundry.h>
+#include <libide-threading.h>
+
+#include "gbp-cargo-build-system.h"
+#include "gbp-cargo-run-command-provider.h"
+
+struct _GbpCargoRunCommandProvider
+{
+ IdeObject parent_instance;
+};
+
+static void
+gbp_cargo_run_command_provider_list_commands_async (IdeRunCommandProvider *provider,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ GbpCargoRunCommandProvider *self = (GbpCargoRunCommandProvider *)provider;
+ g_autoptr(IdeRunCommand) run_command = NULL;
+ g_autoptr(GListStore) store = NULL;
+ g_autoptr(IdeTask) task = NULL;
+ g_autofree char *cargo_toml = NULL;
+ IdeBuildSystem *build_system;
+ IdeContext *context;
+
+ IDE_ENTRY;
+
+ g_assert (GBP_IS_CARGO_RUN_COMMAND_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_cargo_run_command_provider_list_commands_async);
+
+ context = ide_object_get_context (IDE_OBJECT (self));
+ build_system = ide_build_system_from_context (context);
+
+ if (!GBP_IS_CARGO_BUILD_SYSTEM (build_system))
+ {
+ ide_task_return_new_error (task,
+ G_IO_ERROR,
+ G_IO_ERROR_NOT_SUPPORTED,
+ "Not a cargo build system");
+ IDE_EXIT;
+ }
+
+ cargo_toml = gbp_cargo_build_system_get_cargo_toml_path (GBP_CARGO_BUILD_SYSTEM (build_system));
+
+ run_command = ide_run_command_new ();
+ ide_run_command_set_id (run_command, "cargo:run");
+ ide_run_command_set_priority (run_command, -500);
+ ide_run_command_set_display_name (run_command, _("Cargo Run"));
+ /* Pass Cargo.toml path so we are CWD independent */
+ ide_run_command_set_argv (run_command, IDE_STRV_INIT ("cargo", "run", "--manifest-path", cargo_toml));
+
+ store = g_list_store_new (IDE_TYPE_RUN_COMMAND);
+ g_list_store_append (store, run_command);
+ ide_task_return_pointer (task, g_steal_pointer (&store), g_object_unref);
+
+ IDE_EXIT;
+}
+
+static GListModel *
+gbp_cargo_run_command_provider_list_commands_finish (IdeRunCommandProvider *provider,
+ GAsyncResult *result,
+ GError **error)
+{
+ GListModel *ret;
+
+ IDE_ENTRY;
+
+ g_assert (GBP_IS_CARGO_RUN_COMMAND_PROVIDER (provider));
+ g_assert (IDE_IS_TASK (result));
+
+ ret = ide_task_propagate_pointer (IDE_TASK (result), error);
+
+ IDE_RETURN (ret);
+}
+
+static void
+run_command_provider_iface_init (IdeRunCommandProviderInterface *iface)
+{
+ iface->list_commands_async = gbp_cargo_run_command_provider_list_commands_async;
+ iface->list_commands_finish = gbp_cargo_run_command_provider_list_commands_finish;
+}
+
+G_DEFINE_FINAL_TYPE_WITH_CODE (GbpCargoRunCommandProvider, gbp_cargo_run_command_provider, IDE_TYPE_OBJECT,
+ G_IMPLEMENT_INTERFACE (IDE_TYPE_RUN_COMMAND_PROVIDER,
run_command_provider_iface_init))
+
+static void
+gbp_cargo_run_command_provider_class_init (GbpCargoRunCommandProviderClass *klass)
+{
+}
+
+static void
+gbp_cargo_run_command_provider_init (GbpCargoRunCommandProvider *self)
+{
+}
diff --git a/src/plugins/cargo/gbp-cargo-run-command-provider.h
b/src/plugins/cargo/gbp-cargo-run-command-provider.h
new file mode 100644
index 000000000..337936c57
--- /dev/null
+++ b/src/plugins/cargo/gbp-cargo-run-command-provider.h
@@ -0,0 +1,31 @@
+/* gbp-cargo-run-command-provider.h
+ *
+ * Copyright 2016-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 <libide-core.h>
+
+G_BEGIN_DECLS
+
+#define GBP_TYPE_CARGO_RUN_COMMAND_PROVIDER (gbp_cargo_run_command_provider_get_type())
+
+G_DECLARE_FINAL_TYPE (GbpCargoRunCommandProvider, gbp_cargo_run_command_provider, GBP,
CARGO_RUN_COMMAND_PROVIDER, IdeObject)
+
+G_END_DECLS
diff --git a/src/plugins/cargo/meson.build b/src/plugins/cargo/meson.build
index 4b975cbea..f979a49d7 100644
--- a/src/plugins/cargo/meson.build
+++ b/src/plugins/cargo/meson.build
@@ -1,13 +1,20 @@
if get_option('plugin_cargo')
-install_data('cargo_plugin.py', install_dir: plugindir)
-
-configure_file(
- input: 'cargo.plugin',
- output: 'cargo.plugin',
- configuration: config_h,
- install: true,
- install_dir: plugindir,
+plugins_sources += files([
+ 'cargo-plugin.c',
+ 'gbp-cargo-build-system-discovery.c',
+ 'gbp-cargo-build-system.c',
+ 'gbp-cargo-dependency-updater.c',
+ 'gbp-cargo-pipeline-addin.c',
+ 'gbp-cargo-run-command-provider.c',
+])
+
+plugin_cargo_resources = gnome.compile_resources(
+ 'cargo-resources',
+ 'cargo.gresource.xml',
+ c_name: 'gbp_cargo',
)
+plugins_sources += plugin_cargo_resources
+
endif
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]