[gnome-builder/gnome-builder-3-28] util: backport find with depth



commit cd7f2173631206fe749e0eacde7a4e1788f8732b
Author: Christian Hergert <chergert redhat com>
Date:   Mon Jun 25 20:41:52 2018 -0700

    util: backport find with depth
    
    This will let us to make some code have less overhead on large projects.

 src/libide/util/ide-glib.c | 85 +++++++++++++++++++++++++++++++++++++---------
 src/libide/util/ide-glib.h |  7 ++++
 2 files changed, 76 insertions(+), 16 deletions(-)
---
diff --git a/src/libide/util/ide-glib.c b/src/libide/util/ide-glib.c
index 92fb6638c..7bfc74eaf 100644
--- a/src/libide/util/ide-glib.c
+++ b/src/libide/util/ide-glib.c
@@ -18,6 +18,7 @@
 
 #define G_LOG_DOMAIN "ide-glib"
 
+#include <dazzle.h>
 #include <string.h>
 
 #include "config.h"
@@ -410,11 +411,25 @@ ide_g_file_get_children_finish (GFile         *file,
   return IDE_PTR_ARRAY_STEAL_FULL (&ret);
 }
 
+typedef struct
+{
+  GPatternSpec *spec;
+  guint         depth;
+} Find;
+
+static void
+find_free (Find *f)
+{
+  dzl_clear_pointer (&f->spec, g_pattern_spec_free);
+  g_slice_free (Find, f);
+}
+
 static void
 populate_descendants_matching (GFile        *file,
                                GCancellable *cancellable,
                                GPtrArray    *results,
-                               GPatternSpec *spec)
+                               GPatternSpec *spec,
+                               guint         depth)
 {
   g_autoptr(GFileEnumerator) enumerator = NULL;
   g_autoptr(GPtrArray) children = NULL;
@@ -423,6 +438,9 @@ populate_descendants_matching (GFile        *file,
   g_assert (results != NULL);
   g_assert (spec != NULL);
 
+  if (depth == 0)
+    return;
+
   enumerator = g_file_enumerate_children (file,
                                           G_FILE_ATTRIBUTE_STANDARD_NAME","
                                           G_FILE_ATTRIBUTE_STANDARD_IS_SYMLINK","
@@ -467,7 +485,7 @@ populate_descendants_matching (GFile        *file,
 
           /* Don't recurse into known bad directories */
           if (!ide_vcs_is_ignored (NULL, child, NULL))
-            populate_descendants_matching (child, cancellable, results, spec);
+            populate_descendants_matching (child, cancellable, results, spec, depth - 1);
         }
     }
 }
@@ -479,54 +497,66 @@ ide_g_file_find_worker (GTask        *task,
                         GCancellable *cancellable)
 {
   GFile *file = source_object;
-  GPatternSpec *spec = task_data;
+  Find *f = task_data;
   g_autoptr(GPtrArray) ret = NULL;
 
   g_assert (G_IS_TASK (task));
   g_assert (G_IS_FILE (file));
-  g_assert (spec != NULL);
+  g_assert (f != NULL);
+  g_assert (f->spec != NULL);
   g_assert (!cancellable || G_IS_CANCELLABLE (cancellable));
 
   ret = g_ptr_array_new_with_free_func (g_object_unref);
-  populate_descendants_matching (file, cancellable, ret, spec);
+  populate_descendants_matching (file, cancellable, ret, f->spec, f->depth);
   g_task_return_pointer (task, g_steal_pointer (&ret), (GDestroyNotify)g_ptr_array_unref);
 }
 
 /**
- * ide_g_file_find_async:
+ * ide_g_file_find_with_depth_async:
  * @file: a #IdeGlib
  * @pattern: the glob pattern to search for using GPatternSpec
+ * @max_depth: maximum tree depth to search
  * @cancellable: (nullable): a #GCancellable or %NULL
  * @callback: a callback to execute upon completion
  * @user_data: closure data for @callback
  *
  * Searches descendants of @file for files matching @pattern.
  *
+ * Only up to @max_depth subdirectories will be searched. However, if
+ * @max_depth is zero, then all directories will be searched.
+ *
  * You may only match on the filename, not the directory.
  *
- * Since: 3.28
+ * Since: 3.30
  */
 void
-ide_g_file_find_async (GFile               *file,
-                       const gchar         *pattern,
-                       GCancellable        *cancellable,
-                       GAsyncReadyCallback  callback,
-                       gpointer             user_data)
+ide_g_file_find_with_depth_async (GFile               *file,
+                                  const gchar         *pattern,
+                                  guint                depth,
+                                  GCancellable        *cancellable,
+                                  GAsyncReadyCallback  callback,
+                                  gpointer             user_data)
 {
   g_autoptr(GTask) task = NULL;
-  g_autoptr(GPatternSpec) spec = NULL;
+  Find *f;
 
   g_return_if_fail (G_IS_FILE (file));
   g_return_if_fail (pattern != NULL);
   g_return_if_fail (!cancellable || G_IS_CANCELLABLE (cancellable));
 
+  if (depth == 0)
+    depth = G_MAXUINT;
+
   task = g_task_new (file, cancellable, callback, user_data);
   g_task_set_source_tag (task, ide_g_file_find_async);
   g_task_set_priority (task, G_PRIORITY_LOW + 100);
 
-  spec = g_pattern_spec_new (pattern);
+  f = g_slice_new0 (Find);
+  f->spec = g_pattern_spec_new (pattern);
+  f->depth = depth;
+  g_task_set_task_data (task, f, (GDestroyNotify)find_free);
 
-  if (spec == NULL)
+  if (f->spec == NULL)
     {
       g_task_return_new_error (task,
                                G_IO_ERROR,
@@ -536,10 +566,33 @@ ide_g_file_find_async (GFile               *file,
       return;
     }
 
-  g_task_set_task_data (task, g_steal_pointer (&spec), (GDestroyNotify)g_pattern_spec_free);
   g_task_run_in_thread (task, ide_g_file_find_worker);
 }
 
+/**
+ * ide_g_file_find_async:
+ * @file: a #IdeGlib
+ * @pattern: the glob pattern to search for using GPatternSpec
+ * @cancellable: (nullable): a #GCancellable or %NULL
+ * @callback: a callback to execute upon completion
+ * @user_data: closure data for @callback
+ *
+ * Searches descendants of @file for files matching @pattern.
+ *
+ * You may only match on the filename, not the directory.
+ *
+ * Since: 3.28
+ */
+void
+ide_g_file_find_async (GFile               *file,
+                       const gchar         *pattern,
+                       GCancellable        *cancellable,
+                       GAsyncReadyCallback  callback,
+                       gpointer             user_data)
+{
+  ide_g_file_find_with_depth_async (file, pattern, G_MAXUINT, cancellable, callback, user_data);
+}
+
 /**
  * ide_g_file_find_finish:
  * @file: a #GFile
diff --git a/src/libide/util/ide-glib.h b/src/libide/util/ide-glib.h
index 147772037..ff8eeee01 100644
--- a/src/libide/util/ide-glib.h
+++ b/src/libide/util/ide-glib.h
@@ -60,6 +60,13 @@ IDE_AVAILABLE_IN_3_28
 gchar       *ide_g_file_get_uncanonical_relative_path (GFile                *file,
                                                        GFile                *other);
 IDE_AVAILABLE_IN_3_28
+void         ide_g_file_find_with_depth_async         (GFile                *file,
+                                                       const gchar          *pattern,
+                                                       guint                 max_depth,
+                                                       GCancellable         *cancellable,
+                                                       GAsyncReadyCallback   callback,
+                                                       gpointer              user_data);
+IDE_AVAILABLE_IN_3_28
 void         ide_g_file_find_async                    (GFile                *file,
                                                        const gchar          *pattern,
                                                        GCancellable         *cancellable,


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