[gnome-builder/gnome-builder-43] plugins/flatpak: add translate_file() helper



commit 0949b98280830a557dfe90d98380225e08e31a6d
Author: Christian Hergert <chergert redhat com>
Date:   Thu Sep 29 17:50:48 2022 -0700

    plugins/flatpak: add translate_file() helper
    
    It's simpler to have a translate_file() API on top of the SDKs so that we
    can keep the problem domain simple and specific to the underlying Flatpak
    runtime ref.

 src/plugins/flatpak/gbp-flatpak-sdk.c | 124 +++++++++++++++++++++++++++++++++-
 src/plugins/flatpak/gbp-flatpak-sdk.h |   2 +
 2 files changed, 123 insertions(+), 3 deletions(-)
---
diff --git a/src/plugins/flatpak/gbp-flatpak-sdk.c b/src/plugins/flatpak/gbp-flatpak-sdk.c
index 5e5c84508..3d2792c64 100644
--- a/src/plugins/flatpak/gbp-flatpak-sdk.c
+++ b/src/plugins/flatpak/gbp-flatpak-sdk.c
@@ -22,11 +22,16 @@
 
 #include "config.h"
 
+#include <json-glib/json-glib.h>
+
 #include "gbp-flatpak-sdk.h"
 
 struct _GbpFlatpakSdk
 {
   IdeSdk parent_instance;
+
+  GMutex mutex;
+
   char *id;
   char *name;
   char *arch;
@@ -35,13 +40,16 @@ struct _GbpFlatpakSdk
   char *sdk_branch;
   char *deploy_dir;
   char *metadata;
+  char *mount_path;
+
   guint is_sdk_extension : 1;
+  guint discovered_mount_path : 1;
 };
 
 G_DEFINE_FINAL_TYPE (GbpFlatpakSdk, gbp_flatpak_sdk, IDE_TYPE_SDK)
 
 static void
-gbp_flatpak_sdk_dispose (GObject *object)
+gbp_flatpak_sdk_finalize (GObject *object)
 {
   GbpFlatpakSdk *self = (GbpFlatpakSdk *)object;
 
@@ -53,8 +61,11 @@ gbp_flatpak_sdk_dispose (GObject *object)
   g_clear_pointer (&self->sdk_branch, g_free);
   g_clear_pointer (&self->deploy_dir, g_free);
   g_clear_pointer (&self->metadata, g_free);
+  g_clear_pointer (&self->mount_path, g_free);
+
+  g_mutex_clear (&self->mutex);
 
-  G_OBJECT_CLASS (gbp_flatpak_sdk_parent_class)->dispose (object);
+  G_OBJECT_CLASS (gbp_flatpak_sdk_parent_class)->finalize (object);
 }
 
 static void
@@ -62,12 +73,13 @@ gbp_flatpak_sdk_class_init (GbpFlatpakSdkClass *klass)
 {
   GObjectClass *object_class = G_OBJECT_CLASS (klass);
 
-  object_class->dispose = gbp_flatpak_sdk_dispose;
+  object_class->finalize = gbp_flatpak_sdk_finalize;
 }
 
 static void
 gbp_flatpak_sdk_init (GbpFlatpakSdk *self)
 {
+  g_mutex_init (&self->mutex);
 }
 
 GbpFlatpakSdk *
@@ -125,3 +137,109 @@ gbp_flatpak_sdk_get_id (GbpFlatpakSdk *self)
 
   return self->id;
 }
+
+static const char *
+gbp_flatpak_sdk_get_mount_path (GbpFlatpakSdk *self)
+{
+  g_assert (GBP_IS_FLATPAK_SDK (self));
+
+  if (!self->discovered_mount_path)
+    {
+      g_mutex_lock (&self->mutex);
+
+      if (!self->discovered_mount_path)
+        {
+          g_autofree char *json_path = g_build_filename (self->deploy_dir, "files", "manifest.json", NULL);
+          g_autoptr(JsonParser) parser = json_parser_new ();
+
+          if (json_parser_load_from_mapped_file (parser, json_path, NULL))
+            {
+              JsonObject *obj;
+              JsonNode *node;
+
+              if ((node = json_parser_get_root (parser)) &&
+                  JSON_NODE_HOLDS_OBJECT (node) &&
+                  (obj = json_node_get_object (node)) &&
+                  json_object_has_member (obj, "build-options") &&
+                  (node = json_object_get_member (obj, "build-options")) &&
+                  JSON_NODE_HOLDS_OBJECT (node) &&
+                  (obj = json_node_get_object (node)) &&
+                  json_object_has_member (obj, "prefix") &&
+                  (node = json_object_get_member (obj, "prefix")) &&
+                  JSON_NODE_HOLDS_VALUE (node))
+                self->mount_path = json_node_dup_string (node);
+            }
+
+          /* If we're a .Debug, then assume we're at /usr/lib/debug */
+          if (self->mount_path == NULL && g_str_has_suffix (self->name, ".Debug"))
+            self->mount_path = g_strdup ("/usr/lib/debug");
+
+          self->discovered_mount_path = TRUE;
+        }
+
+      g_mutex_unlock (&self->mutex);
+    }
+
+  return self->mount_path ? self->mount_path : "/usr";
+}
+
+GFile *
+gbp_flatpak_sdk_translate_file (GbpFlatpakSdk *self,
+                                GFile         *file)
+{
+  g_autofree char *deploy_dir_files = NULL;
+  const char *path;
+  const char *mount_path;
+
+  g_assert (GBP_IS_FLATPAK_SDK (self));
+  g_assert (G_IS_FILE (file));
+
+  /* We only support native files as UNIX paths */
+  if (!g_file_is_native (file) || !(path = g_file_peek_path (file)))
+    return NULL;
+
+  /* This should be handled by gbp_flatpak_manifest_translate_file() */
+  if (g_str_equal (path, "/app") || g_str_has_prefix (path, "/app/"))
+    return NULL;
+
+  deploy_dir_files = g_build_filename (self->deploy_dir, "files", NULL);
+
+  /* Get the mount path (default is /usr) but things like "id".Debug will
+   * be mounted at /usr/lib/debug (unless specified by a manifest.json).
+   */
+  if ((mount_path = gbp_flatpak_sdk_get_mount_path (self)))
+    {
+      gsize len = strlen (mount_path);
+
+      if (strncmp (path, mount_path, len) == 0)
+        {
+          if (path[len] == 0 || !(path = g_path_skip_root (path + len)) || path[0] == 0)
+            path = NULL;
+
+          return g_file_new_build_filename (deploy_dir_files, path, NULL);
+        }
+    }
+
+  /* Sometimes we'll be trying to resovle a path to sources when debugging,
+   * usually extracted with readelf/DWARF data from the likes of GDB. This
+   * is generally only provided by the .Debug runtimes, so we can short-circuit
+   * based on our id.
+   */
+  if (g_str_has_suffix (self->name, ".Debug") &&
+      g_str_has_suffix (path, "/run/build-runtime/"))
+    {
+      g_autoptr(GFile) translated = g_file_new_build_filename (deploy_dir_files,
+                                                               "sources",
+                                                               path + strlen ("/run/build-runtime/"),
+                                                               NULL);
+
+      /* Just to be sure this is within our .Debug. While not currently in use,
+       * I don't see any reason why we can't have multiple .Debug runtimes in
+       * play providing sources access at different subdirectories.
+       */
+      if (g_file_query_exists (translated, NULL))
+        return g_steal_pointer (&translated);
+    }
+
+  return NULL;
+}
diff --git a/src/plugins/flatpak/gbp-flatpak-sdk.h b/src/plugins/flatpak/gbp-flatpak-sdk.h
index 5550095c9..e7ca3e588 100644
--- a/src/plugins/flatpak/gbp-flatpak-sdk.h
+++ b/src/plugins/flatpak/gbp-flatpak-sdk.h
@@ -30,5 +30,7 @@ G_DECLARE_FINAL_TYPE (GbpFlatpakSdk, gbp_flatpak_sdk, GBP, FLATPAK_SDK, IdeSdk)
 
 GbpFlatpakSdk *gbp_flatpak_sdk_new_from_variant (GVariant      *variant);
 const char    *gbp_flatpak_sdk_get_id           (GbpFlatpakSdk *self);
+GFile         *gbp_flatpak_sdk_translate_file   (GbpFlatpakSdk *self,
+                                                 GFile         *file);
 
 G_END_DECLS


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]