[gnome-builder] flatpak: implement basic bootstrapping for new runtime provider
- From: Christian Hergert <chergert src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-builder] flatpak: implement basic bootstrapping for new runtime provider
- Date: Wed, 5 May 2021 04:10:29 +0000 (UTC)
commit 3c173ec3087d11c826f25f526ad6061b9b1d9c48
Author: Christian Hergert <chergert redhat com>
Date: Tue May 4 09:24:30 2021 -0700
flatpak: implement basic bootstrapping for new runtime provider
We still need to do a bit more here so that we show the dialog again.
However, that will get done via callbacks from the IpcFlatpakTransfer
object in an upcoming commit.
.../flatpak/daemon/ipc-flatpak-service-impl.c | 133 +++++++--
.../daemon/org.gnome.Builder.Flatpak.Service.xml | 11 +-
src/plugins/flatpak/daemon/test-flatpak.c | 7 +
src/plugins/flatpak/daemon/test-install.c | 11 +-
src/plugins/flatpak/gbp-flatpak-manifest.c | 73 +++--
src/plugins/flatpak/gbp-flatpak-manifest.h | 1 +
src/plugins/flatpak/gbp-flatpak-runtime-provider.c | 331 +++++++++++++++++++++
7 files changed, 519 insertions(+), 48 deletions(-)
---
diff --git a/src/plugins/flatpak/daemon/ipc-flatpak-service-impl.c
b/src/plugins/flatpak/daemon/ipc-flatpak-service-impl.c
index 46f776ebd..55a2fc167 100644
--- a/src/plugins/flatpak/daemon/ipc-flatpak-service-impl.c
+++ b/src/plugins/flatpak/daemon/ipc-flatpak-service-impl.c
@@ -593,14 +593,19 @@ ipc_flatpak_service_impl_install_changed_cb (IpcFlatpakServiceImpl *self,
}
}
+typedef struct
+{
+ char *ref;
+ char *remote;
+} InstallRef;
+
typedef struct
{
FlatpakInstallation *installation;
GDBusMethodInvocation *invocation;
IpcFlatpakTransfer *transfer;
- char *remote;
- char *ref;
char *parent_window;
+ GArray *refs;
} InstallState;
static void
@@ -609,8 +614,7 @@ install_state_free (InstallState *state)
g_clear_object (&state->installation);
g_clear_object (&state->invocation);
g_clear_object (&state->transfer);
- g_clear_pointer (&state->remote, g_free);
- g_clear_pointer (&state->ref, g_free);
+ g_clear_pointer (&state->refs, g_array_unref);
g_clear_pointer (&state->parent_window, g_free);
g_slice_free (InstallState, state);
}
@@ -664,6 +668,22 @@ connect_signals (FlatpakTransaction *transaction,
return TRUE;
}
+static gboolean
+add_refs_to_transaction (FlatpakTransaction *transaction,
+ GArray *refs,
+ GError **error)
+{
+ for (guint i = 0; i < refs->len; i++)
+ {
+ const InstallRef *ref = &g_array_index (refs, InstallRef, i);
+
+ if (!flatpak_transaction_add_install (transaction, ref->remote, ref->ref, NULL, error))
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
static void
install_worker (GTask *task,
gpointer source_object,
@@ -677,7 +697,7 @@ install_worker (GTask *task,
g_assert (G_IS_TASK (task));
g_assert (IPC_IS_FLATPAK_SERVICE_IMPL (source_object));
g_assert (state != NULL);
- g_assert (state->remote != NULL);
+ g_assert (state->refs != NULL);
g_assert (G_IS_DBUS_METHOD_INVOCATION (state->invocation));
g_assert (IPC_IS_FLATPAK_TRANSFER (state->transfer));
g_assert (FLATPAK_IS_INSTALLATION (state->installation));
@@ -686,7 +706,7 @@ install_worker (GTask *task,
ipc_flatpak_transfer_set_message (state->transfer, "");
if (!(transaction = flatpak_transaction_new_for_installation (state->installation, NULL, &error)) ||
- !flatpak_transaction_add_install (transaction, state->remote, state->ref, NULL, &error) ||
+ !add_refs_to_transaction (transaction, state->refs, &error) ||
!connect_signals (transaction, state->transfer, &error) ||
!flatpak_transaction_run (transaction, cancellable, &error))
{
@@ -759,53 +779,78 @@ find_remote_for_ref (IpcFlatpakServiceImpl *self,
return NULL;
}
+static void
+clear_install_ref (gpointer data)
+{
+ InstallRef *r = data;
+
+ g_free (r->ref);
+ g_free (r->remote);
+}
+
static gboolean
ipc_flatpak_service_impl_install (IpcFlatpakService *service,
GDBusMethodInvocation *invocation,
- const char *full_ref_name,
+ const char * const *full_ref_names,
const char *transfer_path,
const char *parent_window)
{
IpcFlatpakServiceImpl *self = (IpcFlatpakServiceImpl *)service;
g_autoptr(IpcFlatpakTransfer) transfer = NULL;
- g_autoptr(FlatpakRef) ref = NULL;
+ g_autoptr(GArray) refs = NULL;
g_autoptr(GError) error = NULL;
g_autoptr(GTask) task = NULL;
- g_autofree char *remote = NULL;
GDBusConnection *connection;
InstallState *state;
g_assert (IPC_IS_FLATPAK_SERVICE_IMPL (self));
g_assert (G_IS_DBUS_METHOD_INVOCATION (invocation));
- g_assert (full_ref_name != NULL);
+ g_assert (full_ref_names != NULL);
g_assert (transfer_path != NULL);
g_assert (parent_window != NULL);
- if (!(ref = flatpak_ref_parse (full_ref_name, &error)))
- return complete_wrapped_error (invocation, error);
+ refs = g_array_new (FALSE, FALSE, sizeof (InstallRef));
+ g_array_set_clear_func (refs, clear_install_ref);
connection = g_dbus_method_invocation_get_connection (invocation);
- remote = find_remote_for_ref (self, ref);
transfer = ipc_flatpak_transfer_proxy_new_sync (connection,
G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES,
NULL,
transfer_path,
NULL, NULL);
- if (remote == NULL)
+ if (full_ref_names[0] == NULL)
{
g_dbus_method_invocation_return_error (g_steal_pointer (&invocation),
G_DBUS_ERROR,
G_DBUS_ERROR_FAILED,
- "No configured remote contains ref");
+ "No refs to install");
return TRUE;
}
+ for (guint i = 0; full_ref_names[i]; i++)
+ {
+ g_autoptr(FlatpakRef) ref = flatpak_ref_parse (full_ref_names[i], NULL);
+ InstallRef iref = {0};
+
+ if (ref == NULL ||
+ !(iref.remote = find_remote_for_ref (self, ref)))
+ {
+ g_dbus_method_invocation_return_error (g_steal_pointer (&invocation),
+ G_DBUS_ERROR,
+ G_DBUS_ERROR_FAILED,
+ "No configured remote contains ref");
+ return TRUE;
+ }
+
+ iref.ref = g_strdup (full_ref_names[i]);
+ g_array_append_val (refs, iref);
+ }
+
state = g_slice_new0 (InstallState);
state->installation = ipc_flatpak_service_impl_ref_user_installation (self);
state->invocation = g_steal_pointer (&invocation);
- state->ref = g_strdup (full_ref_name);
- state->remote = g_steal_pointer (&remote);
+ state->refs = g_array_ref (refs);
state->parent_window = parent_window[0] ? g_strdup (parent_window) : NULL;
state->transfer = g_object_ref (transfer);
@@ -1105,6 +1150,59 @@ ipc_flatpak_service_impl_resolve_extension (IpcFlatpakService *service,
return TRUE;
}
+static gboolean
+ipc_flatpak_service_impl_get_runtime (IpcFlatpakService *service,
+ GDBusMethodInvocation *invocation,
+ const char *runtime_id)
+{
+ IpcFlatpakServiceImpl *self = (IpcFlatpakServiceImpl *)service;
+ g_autoptr(FlatpakRef) ref = NULL;
+ g_autofree char *full_name = NULL;
+
+ g_assert (IPC_IS_FLATPAK_SERVICE_IMPL (self));
+ g_assert (G_IS_DBUS_METHOD_INVOCATION (invocation));
+ g_assert (runtime_id != NULL);
+
+ /* Homogenize names into runtime/name/arch/branch */
+ if (g_str_has_prefix (runtime_id, "runtime/"))
+ runtime_id += strlen ("runtime/");
+ full_name = g_strdup_printf ("runtime/%s", runtime_id);
+
+ if (!(ref = flatpak_ref_parse (full_name, NULL)))
+ {
+ g_dbus_method_invocation_return_error (g_steal_pointer (&invocation),
+ G_DBUS_ERROR,
+ G_DBUS_ERROR_FAILED,
+ "Invalid runtime id %s",
+ full_name);
+ return TRUE;
+ }
+
+ for (guint i = 0; i < self->runtimes->len; i++)
+ {
+ const Runtime *runtime = g_ptr_array_index (self->runtimes, i);
+
+ if (str_equal0 (flatpak_ref_get_name (ref), runtime->name) &&
+ str_equal0 (flatpak_ref_get_arch (ref), runtime->arch) &&
+ str_equal0 (flatpak_ref_get_branch (ref), runtime->branch))
+ {
+ g_autoptr(GVariant) ret = runtime_to_variant (runtime);
+ ipc_flatpak_service_complete_get_runtime (service,
+ g_steal_pointer (&invocation),
+ ret);
+ return TRUE;
+ }
+ }
+
+ g_dbus_method_invocation_return_error (g_steal_pointer (&invocation),
+ G_DBUS_ERROR,
+ G_DBUS_ERROR_FAILED,
+ "No such runtime %s",
+ full_name);
+
+ return TRUE;
+}
+
static void
service_iface_init (IpcFlatpakServiceIface *iface)
{
@@ -1112,6 +1210,7 @@ service_iface_init (IpcFlatpakServiceIface *iface)
iface->handle_list_runtimes = ipc_flatpak_service_impl_list_runtimes;
iface->handle_runtime_is_known = ipc_flatpak_service_impl_runtime_is_known;
iface->handle_install = ipc_flatpak_service_impl_install;
+ iface->handle_get_runtime = ipc_flatpak_service_impl_get_runtime;
iface->handle_resolve_extension = ipc_flatpak_service_impl_resolve_extension;
}
diff --git a/src/plugins/flatpak/daemon/org.gnome.Builder.Flatpak.Service.xml
b/src/plugins/flatpak/daemon/org.gnome.Builder.Flatpak.Service.xml
index 49d3ff505..df1b7d7bc 100644
--- a/src/plugins/flatpak/daemon/org.gnome.Builder.Flatpak.Service.xml
+++ b/src/plugins/flatpak/daemon/org.gnome.Builder.Flatpak.Service.xml
@@ -50,6 +50,13 @@
<method name="ListRuntimes">
<arg name="runtimes" direction="out" type="a(sssssssb)"/>
</method>
+ <!--
+ Get information on the runtime.
+ -->
+ <method name="GetRuntime">
+ <arg name="id" direction="in" type="s"/>
+ <arg name="runtime" direction="out" type="(sssssssb)"/>
+ </method>
<!--
RuntimeIsKnown:
@name: a runtime name to lookup in form name/arch/branch
@@ -63,14 +70,14 @@
</method>
<!--
Install:
- @full_ref_name: the full name of the target to install such as "runtime/org.gnome.Sdk/x86_64/master"
+ @full_ref_names: the full name of the targets to install such as "runtime/org.gnome.Sdk/x86_64/master"
@transfer: the path of an org.gnome.Builder.Flatpak.Transfer object on the caller side
Begins the installation of a ref from a configured remote. The operation will not
complete until the installation has completed.
-->
<method name="Install">
- <arg name="full_ref_name" direction="in" type="s"/>
+ <arg name="full_ref_name" direction="in" type="as"/>
<arg name="transfer" direction="in" type="o"/>
<arg name="parent_window" direction="in" type="s"/>
</method>
diff --git a/src/plugins/flatpak/daemon/test-flatpak.c b/src/plugins/flatpak/daemon/test-flatpak.c
index f6a047672..aa911bb34 100644
--- a/src/plugins/flatpak/daemon/test-flatpak.c
+++ b/src/plugins/flatpak/daemon/test-flatpak.c
@@ -66,6 +66,7 @@ add_install_cb (GObject *object,
g_autofree gchar *resolved = NULL;
g_autoptr(GMainLoop) main_loop = user_data;
g_autoptr(GVariant) runtimes = NULL;
+ g_autoptr(GVariant) info = NULL;
g_autoptr(GError) error = NULL;
GVariantIter iter;
gboolean is_known = TRUE;
@@ -119,6 +120,12 @@ add_install_cb (GObject *object,
sizestr = g_format_size (download_size);
g_message (" Found, Download Size: <=%s", sizestr);
+ g_message ("Getting runtime info for known runtime");
+ ret = ipc_flatpak_service_call_get_runtime_sync (service, "org.gnome.Sdk/x86_64/master", &info, NULL,
&error);
+ g_assert_no_error (error);
+ g_assert_true (ret);
+ g_message (" Found");
+
g_message ("Resolving org.freedesktop.Sdk.Extension.rust-stable for org.gnome.Sdk/x86_64/master");
ret = ipc_flatpak_service_call_resolve_extension_sync (service, "org.gnome.Sdk/x86_64/master",
"org.freedesktop.Sdk.Extension.rust-stable", &resolved, NULL, &error);
g_assert_no_error (error);
diff --git a/src/plugins/flatpak/daemon/test-install.c b/src/plugins/flatpak/daemon/test-install.c
index 33fd386dd..687e4c7de 100644
--- a/src/plugins/flatpak/daemon/test-install.c
+++ b/src/plugins/flatpak/daemon/test-install.c
@@ -71,15 +71,20 @@ main (gint argc,
g_autoptr(GSubprocessLauncher) launcher = NULL;
g_autoptr(IpcFlatpakService) service = NULL;
g_autoptr(IpcFlatpakTransfer) transfer = NULL;
+ g_autoptr(GPtrArray) all = g_ptr_array_new ();
GMainLoop *main_loop;
gboolean ret;
- if (argc != 2)
+ if (argc < 2)
{
- g_printerr ("usage: %s REF\n", argv[0]);
+ g_printerr ("usage: %s REF [REF..]\n", argv[0]);
return EXIT_FAILURE;
}
+ for (guint i = 1; i < argc; i++)
+ g_ptr_array_add (all, argv[i]);
+ g_ptr_array_add (all, NULL);
+
launcher = g_subprocess_launcher_new (G_SUBPROCESS_FLAGS_STDIN_PIPE | G_SUBPROCESS_FLAGS_STDOUT_PIPE);
subprocess = g_subprocess_launcher_spawn (launcher, &error,
#if 0
@@ -122,7 +127,7 @@ main (gint argc,
g_message ("Installing %s\n", argv[1]);
ipc_flatpak_service_call_install (service,
- argv[1],
+ (const char * const *)all->pdata,
transfer_path,
"",
NULL,
diff --git a/src/plugins/flatpak/gbp-flatpak-manifest.c b/src/plugins/flatpak/gbp-flatpak-manifest.c
index 28a339b21..af686141a 100644
--- a/src/plugins/flatpak/gbp-flatpak-manifest.c
+++ b/src/plugins/flatpak/gbp-flatpak-manifest.c
@@ -30,7 +30,8 @@
#include "gbp-flatpak-runtime.h"
#include "gbp-flatpak-util.h"
-#include "ipc-flatpak-service.h"
+#include "daemon/ipc-flatpak-service.h"
+#include "daemon/ipc-flatpak-util.h"
struct _GbpFlatpakManifest
{
@@ -551,43 +552,51 @@ gbp_flatpak_manifest_set_file (GbpFlatpakManifest *self,
static IdeRuntime *
find_extension (GbpFlatpakManifest *self,
- const gchar *name)
+ const gchar *runtime_id)
{
- g_autoptr(FlatpakInstalledRef) ref = NULL;
g_autoptr(IpcFlatpakService) service = NULL;
- g_autofree char *resolved = NULL;
- GbpFlatpakApplicationAddin *addin;
- GbpFlatpakRuntime *ret = NULL;
+ g_autoptr(GVariant) info = NULL;
GbpFlatpakClient *client;
IdeContext *context;
- g_autoptr(GBytes) bytes = NULL;
g_assert (GBP_IS_FLATPAK_MANIFEST (self));
- g_assert (name != NULL);
+ g_assert (runtime_id != NULL);
context = ide_object_get_context (IDE_OBJECT (self));
-#if 0
if ((client = gbp_flatpak_client_from_context (context)) &&
(service = gbp_flatpak_client_get_service (client, NULL, NULL)) &&
- ipc_flatpak_service_call_resolve_extension_sync (service, self->sdk, name, &resolved, NULL, NULL))
+ ipc_flatpak_service_call_get_runtime_sync (service, runtime_id, &info, NULL, NULL))
{
-
- addin = gbp_flatpak_application_addin_get_default ();
- ref = gbp_flatpak_application_addin_find_extension (addin, self->sdk, name);
- if (ref != NULL)
- ret = gbp_flatpak_runtime_new (flatpak_ref_get_name (FLATPAK_REF (ref)),
- flatpak_ref_get_arch (FLATPAK_REF (ref)),
- flatpak_ref_get_branch (FLATPAK_REF (ref)),
- (bytes = flatpak_installed_ref_load_metadata (ref, NULL, NULL)),
- flatpak_installed_ref_get_deploy_dir (ref),
- TRUE, NULL, NULL);
+ GbpFlatpakRuntime *ret = NULL;
+ const gchar *name;
+ const gchar *arch;
+ const gchar *branch;
+ const gchar *sdk_name;
+ const gchar *sdk_branch;
+ const gchar *deploy_dir;
+ const gchar *metadata;
+ gboolean is_extension;
+
+ if (runtime_variant_parse (info,
+ &name, &arch, &branch,
+ &sdk_name, &sdk_branch,
+ &deploy_dir,
+ &metadata,
+ &is_extension))
+ ret = gbp_flatpak_runtime_new (name,
+ arch,
+ branch,
+ sdk_name,
+ sdk_branch,
+ deploy_dir,
+ metadata,
+ is_extension);
+
+ return IDE_RUNTIME (g_steal_pointer (&ret));
}
-#endif
-
- g_printerr ("TODO: fix find_extension()\n");
- return IDE_RUNTIME (g_steal_pointer (&ret));
+ IDE_RETURN (NULL);
}
static GPtrArray *
@@ -928,7 +937,6 @@ apply_changes_to_tree (GbpFlatpakManifest *self)
}
}
-
}
static void
@@ -1098,7 +1106,12 @@ gbp_flatpak_manifest_get_runtimes (GbpFlatpakManifest *self,
if (self->sdk_extensions != NULL)
{
for (guint i = 0; self->sdk_extensions[i]; i++)
- g_ptr_array_add (ar, g_strdup_printf ("%s/%s/", self->sdk_extensions[i], for_arch));
+ {
+ if (strchr (self->sdk_extensions[i], '/') != NULL)
+ g_ptr_array_add (ar, g_strdup (self->sdk_extensions[i]));
+ else
+ g_ptr_array_add (ar, g_strdup_printf ("%s/%s/", self->sdk_extensions[i], for_arch));
+ }
}
g_ptr_array_add (ar, NULL);
@@ -1155,3 +1168,11 @@ gbp_flatpak_manifest_resolve_extensions (GbpFlatpakManifest *self,
}
}
}
+
+const char *
+gbp_flatpak_manifest_get_branch (GbpFlatpakManifest *self)
+{
+ g_return_val_if_fail (GBP_IS_FLATPAK_MANIFEST (self), NULL);
+
+ return self->runtime_version;
+}
diff --git a/src/plugins/flatpak/gbp-flatpak-manifest.h b/src/plugins/flatpak/gbp-flatpak-manifest.h
index fbda0e2e2..320bb1816 100644
--- a/src/plugins/flatpak/gbp-flatpak-manifest.h
+++ b/src/plugins/flatpak/gbp-flatpak-manifest.h
@@ -44,6 +44,7 @@ const gchar *gbp_flatpak_manifest_get_sdk (GbpFlatpakManifest
const gchar *gbp_flatpak_manifest_get_platform (GbpFlatpakManifest *self);
gchar **gbp_flatpak_manifest_get_runtimes (GbpFlatpakManifest *self,
const gchar *for_arch);
+const char *gbp_flatpak_manifest_get_branch (GbpFlatpakManifest *self);
void gbp_flatpak_manifest_save_async (GbpFlatpakManifest *self,
GCancellable *cancellable,
GAsyncReadyCallback callback,
diff --git a/src/plugins/flatpak/gbp-flatpak-runtime-provider.c
b/src/plugins/flatpak/gbp-flatpak-runtime-provider.c
index bbe920687..df6f4c202 100644
--- a/src/plugins/flatpak/gbp-flatpak-runtime-provider.c
+++ b/src/plugins/flatpak/gbp-flatpak-runtime-provider.c
@@ -22,13 +22,17 @@
#include "config.h"
+#include <glib/gi18n.h>
#include <libide-foundry.h>
#include "gbp-flatpak-client.h"
+#include "gbp-flatpak-manifest.h"
#include "gbp-flatpak-runtime.h"
#include "gbp-flatpak-runtime-provider.h"
+#include "gbp-flatpak-util.h"
#include "daemon/ipc-flatpak-service.h"
+#include "daemon/ipc-flatpak-transfer.h"
#include "daemon/ipc-flatpak-util.h"
struct _GbpFlatpakRuntimeProvider
@@ -193,9 +197,336 @@ gbp_flatpak_runtime_provider_unload (IdeRuntimeProvider *provider,
g_ptr_array_remove_range (self->runtimes, 0, self->runtimes->len);
}
+typedef struct
+{
+ char *runtime_id;
+ char *transfer_path;
+ GPtrArray *to_install;
+ IpcFlatpakTransfer *transfer;
+ IpcFlatpakService *service;
+ IdeNotification *notif;
+} Bootstrap;
+
+static void
+bootstrap_free (Bootstrap *b)
+{
+ g_clear_pointer (&b->runtime_id, g_free);
+ g_clear_pointer (&b->transfer_path, g_free);
+ g_clear_object (&b->notif);
+ g_clear_object (&b->service);
+ g_clear_object (&b->transfer);
+ g_clear_pointer (&b->to_install, g_ptr_array_unref);
+ g_slice_free (Bootstrap, b);
+}
+
+static IdeRuntime *
+find_runtime (GbpFlatpakRuntimeProvider *self,
+ const char *runtime_id)
+{
+ IdeRuntimeManager *manager;
+ IdeContext *context;
+ IdeRuntime *runtime;
+
+ g_assert (GBP_IS_FLATPAK_RUNTIME_PROVIDER (self));
+ g_assert (runtime_id != NULL);
+
+ context = ide_object_get_context (IDE_OBJECT (self));
+ manager = ide_runtime_manager_from_context (context);
+ runtime = ide_runtime_manager_get_runtime (manager, runtime_id);
+
+ return runtime ? g_object_ref (runtime) : NULL;
+}
+
+static void
+gbp_flatpak_runtime_provider_bootstrap_install_cb (GObject *object,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ GbpFlatpakRuntimeProvider *self;
+ IpcFlatpakService *service = (IpcFlatpakService *)object;
+ g_autoptr(IdeRuntime) runtime = NULL;
+ g_autoptr(IdeTask) task = user_data;
+ g_autoptr(GError) error = NULL;
+ Bootstrap *state;
+
+ IDE_ENTRY;
+
+ g_assert (IPC_IS_FLATPAK_SERVICE (service));
+ g_assert (G_IS_ASYNC_RESULT (result));
+ g_assert (IDE_IS_TASK (task));
+
+ state = ide_task_get_task_data (task);
+ self = ide_task_get_source_object (task);
+
+ g_assert (GBP_IS_FLATPAK_RUNTIME_PROVIDER (self));
+ g_assert (state != NULL);
+ g_assert (IDE_IS_NOTIFICATION (state->notif));
+
+ if (!ipc_flatpak_service_call_install_finish (service, result, &error))
+ ide_task_return_error (task, g_steal_pointer (&error));
+ else if (!(runtime = find_runtime (self, state->runtime_id)))
+ ide_task_return_new_error (task,
+ G_IO_ERROR,
+ G_IO_ERROR_CANCELLED,
+ "Operation was cancelled");
+ else
+ ide_task_return_pointer (task, g_steal_pointer (&runtime), g_object_unref);
+
+ ide_notification_withdraw (state->notif);
+
+ IDE_EXIT;
+}
+
+static gboolean
+gbp_flatpak_runtime_provider_bootstrap_complete (gpointer data)
+{
+ GbpFlatpakRuntimeProvider *self;
+ g_autoptr(IdeRuntime) runtime = NULL;
+ IdeTask *task = data;
+ Bootstrap *state;
+
+ IDE_ENTRY;
+
+ g_assert (IDE_IS_TASK (task));
+
+ self = ide_task_get_source_object (task);
+ state = ide_task_get_task_data (task);
+
+ g_assert (GBP_IS_FLATPAK_RUNTIME_PROVIDER (self));
+ g_assert (state->to_install != NULL);
+ g_assert (IPC_IS_FLATPAK_SERVICE (state->service));
+ g_assert (state->transfer_path != NULL);
+ g_assert (IDE_IS_NOTIFICATION (state->notif));
+
+ ide_notification_attach (state->notif, IDE_OBJECT (self));
+
+ ipc_flatpak_service_call_install (state->service,
+ (const char * const *)state->to_install->pdata,
+ state->transfer_path,
+ "",
+ ide_task_get_cancellable (task),
+ gbp_flatpak_runtime_provider_bootstrap_install_cb,
+ g_object_ref (task));
+
+ IDE_RETURN (G_SOURCE_REMOVE);
+}
+
+static void
+gbp_flatpak_runtime_provider_bootstrap (IdeTask *task,
+ gpointer source_object,
+ gpointer task_data,
+ GCancellable *cancellable)
+{
+ g_autoptr(IdeContext) context = NULL;
+ g_autoptr(GbpFlatpakClient) client = NULL;
+ g_autoptr(IpcFlatpakService) service = NULL;
+ g_autoptr(IpcFlatpakTransfer) transfer = NULL;
+ g_autoptr(IdeNotification) notif = NULL;
+ Bootstrap *state = task_data;
+
+ IDE_ENTRY;
+
+ g_assert (IDE_IS_TASK (task));
+ g_assert (GBP_IS_FLATPAK_RUNTIME_PROVIDER (source_object));
+ g_assert (state != NULL);
+ g_assert (state->to_install != NULL);
+ g_assert (state->to_install->len > 0);
+
+ if (!(context = ide_object_ref_context (source_object)) ||
+ !(client = gbp_flatpak_client_ensure (context)) ||
+ !(service = gbp_flatpak_client_get_service (client, NULL, NULL)))
+ {
+ ide_task_return_new_error (task,
+ G_IO_ERROR,
+ G_IO_ERROR_CANCELLED,
+ "Operation was cancelled");
+ IDE_GOTO (failure);
+ }
+
+ /* Filter out anything we can't find or is already installed */
+ for (guint i = state->to_install->len; i > 0; i--)
+ {
+ const char *id = g_ptr_array_index (state->to_install, i-1);
+ gboolean is_known = FALSE;
+ gint64 size = 0;
+
+ if (!ipc_flatpak_service_call_runtime_is_known_sync (service, id, &is_known, &size, NULL, NULL) ||
+ is_known == TRUE)
+ g_ptr_array_remove_index (state->to_install, i-1);
+ }
+
+ /* Now create a transfer to install the rest */
+ if (state->to_install->len > 0)
+ {
+ g_autofree char *guid = g_dbus_generate_guid ();
+ g_autofree char *transfer_path = g_strdup_printf ("/org/gnome/Builder/Flatpak/Transfer/%s", guid);
+ g_autoptr(GError) error = NULL;
+
+ notif = ide_notification_new ();
+ ide_notification_set_icon_name (notif, "system-software-install");
+ ide_notification_set_title (notif, _("Installing Necessary SDKs"));
+ ide_notification_set_body (notif, _("Builder is installing Software Development Kits necessary for
building your application."));
+ ide_notification_set_has_progress (notif, TRUE);
+ ide_notification_set_progress_is_imprecise (notif, FALSE);
+
+ transfer = ipc_flatpak_transfer_skeleton_new ();
+ g_dbus_interface_skeleton_export (G_DBUS_INTERFACE_SKELETON (transfer),
+ g_dbus_proxy_get_connection (G_DBUS_PROXY (service)),
+ transfer_path,
+ NULL);
+
+ g_object_bind_property (transfer, "fraction", notif, "progress", G_BINDING_SYNC_CREATE);
+ g_object_bind_property (transfer, "message", notif, "body", G_BINDING_DEFAULT);
+
+ state->service = g_object_ref (service);
+ state->notif = g_object_ref (notif);
+ state->transfer_path = g_strdup (transfer_path);
+
+ g_ptr_array_add (state->to_install, NULL);
+ }
+
+ g_timeout_add_full (G_PRIORITY_DEFAULT,
+ 0,
+ gbp_flatpak_runtime_provider_bootstrap_complete,
+ g_object_ref (task),
+ g_object_unref);
+
+failure:
+
+ if (transfer != NULL)
+ g_dbus_interface_skeleton_unexport (G_DBUS_INTERFACE_SKELETON (transfer));
+
+ IDE_EXIT;
+}
+
+static void
+gbp_flatpak_runtime_provider_bootstrap_async (IdeRuntimeProvider *provider,
+ IdePipeline *pipeline,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ GbpFlatpakRuntimeProvider *self = (GbpFlatpakRuntimeProvider *)provider;
+ g_autoptr(IdeTask) task = NULL;
+ g_autofree char *full_sdk = NULL;
+ g_autofree char *full_platform = NULL;
+ const char *arch;
+ Bootstrap *state;
+ IdeConfig *config;
+
+ IDE_ENTRY;
+
+ g_assert (GBP_IS_FLATPAK_RUNTIME_PROVIDER (self));
+ g_assert (IDE_IS_PIPELINE (pipeline));
+ g_assert (!cancellable || G_IS_CANCELLABLE (cancellable));
+
+ arch = ide_pipeline_get_arch (pipeline);
+ config = ide_pipeline_get_config (pipeline);
+
+ state = g_slice_new0 (Bootstrap);
+ state->runtime_id = g_strdup (ide_config_get_runtime_id (config));
+ state->to_install = g_ptr_array_new_with_free_func (g_free);
+
+ task = ide_task_new (self, cancellable, callback, user_data);
+ ide_task_set_source_tag (task, gbp_flatpak_runtime_provider_bootstrap_async);
+ ide_task_set_task_data (task, state, bootstrap_free);
+
+ /* Collect all of the runtimes that could be needed */
+ if (GBP_IS_FLATPAK_MANIFEST (config))
+ {
+ const char *sdk = gbp_flatpak_manifest_get_sdk (GBP_FLATPAK_MANIFEST (config));
+ const char *platform = gbp_flatpak_manifest_get_platform (GBP_FLATPAK_MANIFEST (config));
+ const char *branch = gbp_flatpak_manifest_get_branch (GBP_FLATPAK_MANIFEST (config));
+ const char * const *extensions = gbp_flatpak_manifest_get_sdk_extensions (GBP_FLATPAK_MANIFEST
(config));
+
+ if (sdk == NULL)
+ sdk = platform;
+
+ if (branch == NULL)
+ branch = "master";
+
+ full_sdk = g_strdup_printf ("runtime/%s/%s/%s", sdk, arch, branch);
+ full_platform = g_strdup_printf ("runtime/%s/%s/%s", platform, arch, branch);
+
+ g_ptr_array_add (state->to_install, g_strdup (full_sdk));
+ if (g_strcmp0 (full_sdk, full_platform) != 0)
+ g_ptr_array_add (state->to_install, g_strdup (full_platform));
+
+ if (extensions != NULL)
+ {
+ for (guint i = 0; extensions[i]; i++)
+ g_ptr_array_add (state->to_install, g_strdup_printf ("runtime/%s", extensions[i]));
+ }
+ }
+ else
+ {
+ const char *runtime_id = ide_config_get_runtime_id (config);
+
+ if (g_str_has_prefix (runtime_id, "flatpak:"))
+ {
+ g_autofree char *resolved_id = NULL;
+ g_autofree char *resolved_arch = NULL;
+ g_autofree char *resolved_branch = NULL;
+
+ if (gbp_flatpak_split_id (runtime_id + strlen ("flatpak:"),
+ &resolved_id,
+ &resolved_arch,
+ &resolved_branch))
+ {
+ full_sdk = g_strdup_printf ("runtime/%s/%s/%s",
+ resolved_id,
+ arch,
+ resolved_branch ?: "master");
+ g_ptr_array_add (state->to_install, g_strdup (full_sdk));
+ }
+ }
+ }
+
+ if (state->to_install->len == 0)
+ {
+ ide_task_return_new_error (task,
+ G_IO_ERROR,
+ G_IO_ERROR_NOT_SUPPORTED,
+ "No runtime provided to bootstrap");
+ g_warn_if_reached ();
+ IDE_EXIT;
+ }
+
+ ide_task_run_in_thread (task, gbp_flatpak_runtime_provider_bootstrap);
+
+ IDE_EXIT;
+}
+
+static IdeRuntime *
+gbp_flatpak_runtime_provider_bootstrap_finish (IdeRuntimeProvider *provider,
+ GAsyncResult *result,
+ GError **error)
+{
+ IdeRuntime *ret;
+
+ IDE_ENTRY;
+
+ g_return_val_if_fail (GBP_IS_FLATPAK_RUNTIME_PROVIDER (provider), NULL);
+ g_return_val_if_fail (IDE_IS_TASK (result), NULL);
+
+ ret = ide_task_propagate_pointer (IDE_TASK (result), error);
+
+ IDE_RETURN (ret);
+}
+
+static gboolean
+gbp_flatpak_runtime_provider_provides (IdeRuntimeProvider *provider,
+ const char *runtime_id)
+{
+ return g_str_has_prefix (runtime_id, "flatpak:");
+}
+
static void
runtime_provider_iface_init (IdeRuntimeProviderInterface *iface)
{
iface->load = gbp_flatpak_runtime_provider_load;
iface->unload = gbp_flatpak_runtime_provider_unload;
+ iface->bootstrap_async = gbp_flatpak_runtime_provider_bootstrap_async;
+ iface->bootstrap_finish = gbp_flatpak_runtime_provider_bootstrap_finish;
+ iface->provides = gbp_flatpak_runtime_provider_provides;
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]