[gnome-builder] gui: add ide_workbench_resolve_file_async()



commit 7f0d60ed2276f429e702cce0c36c4019e2990dcb
Author: Christian Hergert <chergert redhat com>
Date:   Thu Jan 17 21:23:43 2019 -0800

    gui: add ide_workbench_resolve_file_async()
    
    This helper can be used to locate a file by a given path. It might need to
    start scanning from the current build directory, or the source directory.
    
    If it fails, it may search for the file within the root for a file matching
    the filename.

 src/libide/gui/ide-workbench.c | 149 +++++++++++++++++++++++++++++++++++++++++
 src/libide/gui/ide-workbench.h |  10 +++
 2 files changed, 159 insertions(+)
---
diff --git a/src/libide/gui/ide-workbench.c b/src/libide/gui/ide-workbench.c
index ad836b707..de9439b6a 100644
--- a/src/libide/gui/ide-workbench.c
+++ b/src/libide/gui/ide-workbench.c
@@ -98,6 +98,12 @@ typedef struct
   gint64          present_time;
 } LoadProject;
 
+typedef struct
+{
+  GPtrArray *roots;
+  gchar     *path;
+} ResolveFile;
+
 enum {
   PROP_0,
   PROP_CONTEXT,
@@ -150,6 +156,14 @@ open_free (Open *o)
   g_slice_free (Open, o);
 }
 
+static void
+resolve_file_free (ResolveFile *rf)
+{
+  g_clear_pointer (&rf->roots, g_ptr_array_unref);
+  g_clear_pointer (&rf->path, g_free);
+  g_slice_free (ResolveFile, rf);
+}
+
 static gboolean
 ignore_error (GError *error)
 {
@@ -2342,3 +2356,138 @@ ide_workbench_addin_find_by_module_name (IdeWorkbench *workbench,
 
   return IDE_WORKBENCH_ADDIN (ret);
 }
+
+static void
+ide_workbench_resolve_file_worker (IdeTask      *task,
+                                   gpointer      source_object,
+                                   gpointer      task_data,
+                                   GCancellable *cancellable)
+{
+  ResolveFile *rf = task_data;
+  g_autofree gchar *basename = NULL;
+
+  g_assert (IDE_IS_TASK (task));
+  g_assert (IDE_IS_WORKBENCH (source_object));
+  g_assert (rf != NULL);
+  g_assert (rf->roots != NULL);
+  g_assert (!cancellable || G_IS_CANCELLABLE (cancellable));
+
+  basename = g_path_get_basename (rf->path);
+
+  for (guint i = 0; i < rf->roots->len; i++)
+    {
+      GFile *root = g_ptr_array_index (rf->roots, i);
+      g_autoptr(GFile) child = g_file_get_child (root, rf->path);
+      g_autoptr(GPtrArray) found = NULL;
+
+      if (g_file_query_exists (child, cancellable))
+        {
+          ide_task_return_pointer (task, g_steal_pointer (&child), g_object_unref);
+          return;
+        }
+
+      found = ide_g_file_find_with_depth (root, basename, 0, cancellable);
+      IDE_PTR_ARRAY_SET_FREE_FUNC (found, g_object_unref);
+
+      if (found != NULL && found->len > 0)
+        {
+          GFile *match = g_ptr_array_index (found, 0);
+          ide_task_return_pointer (task, g_object_ref (match), g_object_unref);
+          return;
+        }
+    }
+
+  ide_task_return_new_error (task,
+                             G_IO_ERROR,
+                             G_IO_ERROR_NOT_FOUND,
+                             "Failed to locate file %s",
+                             basename);
+}
+
+/**
+ * ide_workbench_resolve_file_async:
+ * @self: a #IdeWorkbench
+ * @filename: the filename to discover
+ *
+ * This function will try to locate a given file based on the filename,
+ * possibly resolving it from a build directory, or source directory.
+ *
+ * If no file was discovered, some attempt will be made to locate a file
+ * that matches appropriately.
+ *
+ * Since: 3.32
+ */
+void
+ide_workbench_resolve_file_async (IdeWorkbench        *self,
+                                  const gchar         *filename,
+                                  GCancellable        *cancellable,
+                                  GAsyncReadyCallback  callback,
+                                  gpointer             user_data)
+{
+  g_autofree gchar *srcpath = NULL;
+  g_autoptr(IdeTask) task = NULL;
+  ResolveFile *rf;
+
+  IDE_ENTRY;
+
+  g_return_if_fail (IDE_IS_MAIN_THREAD ());
+  g_return_if_fail (IDE_IS_WORKBENCH (self));
+  g_return_if_fail (filename != NULL);
+
+  task = ide_task_new (self, cancellable, callback, user_data);
+  ide_task_set_source_tag (task, ide_workbench_resolve_file_async);
+
+  rf = g_slice_new0 (ResolveFile);
+  rf->roots = g_ptr_array_new_with_free_func (g_object_unref);
+  rf->path = g_strdup (filename);
+
+  g_ptr_array_add (rf->roots, ide_context_ref_workdir (self->context));
+
+  if (ide_workbench_has_project (self))
+    {
+      IdeBuildManager *build_manager = ide_build_manager_from_context (self->context);
+      IdePipeline *pipeline = ide_build_manager_get_pipeline (build_manager);
+
+      if (pipeline != NULL)
+        {
+          const gchar *builddir = ide_pipeline_get_builddir (pipeline);
+
+          g_ptr_array_add (rf->roots, g_file_new_for_path (builddir));
+        }
+    }
+
+  ide_task_set_task_data (task, rf, resolve_file_free);
+  ide_task_run_in_thread (task, ide_workbench_resolve_file_worker);
+
+  IDE_EXIT;
+}
+
+/**
+ * ide_workbench_resolve_file_finish:
+ * @self: a #IdeWorkbench
+ * @result: a #GAsyncResult
+ * @error: a location for a #GError
+ *
+ * Completes an asynchronous request to ide_workbench_resolve_file_async().
+ *
+ * Returns: (transfer full): a #GFile, or %NULL and @error is set
+ *
+ * Since: 3.32
+ */
+GFile *
+ide_workbench_resolve_file_finish (IdeWorkbench  *self,
+                                   GAsyncResult  *result,
+                                   GError       **error)
+{
+  GFile *ret;
+
+  IDE_ENTRY;
+
+  g_return_val_if_fail (IDE_IS_MAIN_THREAD (), NULL);
+  g_return_val_if_fail (IDE_IS_WORKBENCH (self), NULL);
+  g_return_val_if_fail (IDE_IS_TASK (result), NULL);
+
+  ret = ide_task_propagate_pointer (IDE_TASK (result), error);
+
+  IDE_RETURN (g_steal_pointer (&ret));
+}
diff --git a/src/libide/gui/ide-workbench.h b/src/libide/gui/ide-workbench.h
index b3a0ae7cd..f27d3e0cf 100644
--- a/src/libide/gui/ide-workbench.h
+++ b/src/libide/gui/ide-workbench.h
@@ -139,6 +139,16 @@ IdeBuildSystem  *ide_workbench_get_build_system      (IdeWorkbench         *self
 IDE_AVAILABLE_IN_3_32
 void             ide_workbench_set_build_system      (IdeWorkbench         *self,
                                                       IdeBuildSystem       *build_system);
+IDE_AVAILABLE_IN_3_32
+void             ide_workbench_resolve_file_async    (IdeWorkbench         *self,
+                                                      const gchar          *filename,
+                                                      GCancellable         *cancellable,
+                                                      GAsyncReadyCallback   callback,
+                                                      gpointer              user_data);
+IDE_AVAILABLE_IN_3_32
+GFile           *ide_workbench_resolve_file_finish   (IdeWorkbench         *self,
+                                                      GAsyncResult         *result,
+                                                      GError              **error);
 
 
 G_END_DECLS


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