[gnome-builder/wip/chergert/code-index-revamp: 6/16] io: add ide_g_file_walk()



commit 68cf7e00711cd581f9b43805da614abf333a1bf8
Author: Christian Hergert <chergert redhat com>
Date:   Thu Jan 31 14:25:42 2019 -0800

    io: add ide_g_file_walk()
    
    This is a helper function that can be used in threads to walk a file-system
    starting from a given directory. Crawlers can use this, such as the code
    indexer.

 src/libide/io/ide-gfile.c | 95 +++++++++++++++++++++++++++++++++++++++++++++++
 src/libide/io/ide-gfile.h | 18 +++++++++
 2 files changed, 113 insertions(+)
---
diff --git a/src/libide/io/ide-gfile.c b/src/libide/io/ide-gfile.c
index 6cd4fbd6d..b66feba7e 100644
--- a/src/libide/io/ide-gfile.c
+++ b/src/libide/io/ide-gfile.c
@@ -727,3 +727,98 @@ ide_g_host_file_get_contents (const gchar  *path,
 
   return TRUE;
 }
+
+/**
+ * ide_g_file_walk:
+ * @directory: a #GFile that is a directory
+ * @attributes: attributes to include in #GFileInfo
+ * @cancellable: (nullable): an optional cancellable
+ * @callback: (scope call): a callback for each directory starting from @directory
+ * @callback_data: closure data for @callback
+ *
+ * Calls @callback for every directory starting from @directory.
+ *
+ * All of the fileinfo for the directory will be provided to the callback for
+ * each directory.
+ *
+ * Since: 3.32
+ */
+void
+ide_g_file_walk (GFile               *directory,
+                 const gchar         *attributes,
+                 GCancellable        *cancellable,
+                 IdeFileWalkCallback  callback,
+                 gpointer             callback_data)
+{
+  g_autoptr(GFileEnumerator) enumerator = NULL;
+  g_autoptr(GPtrArray) directories = NULL;
+  g_autoptr(GPtrArray) file_infos = NULL;
+  g_autoptr(GString) str = NULL;
+  g_autoptr(GError) error = NULL;
+  GFileType directory_type;
+  gpointer infoptr;
+  static const gchar *required[] = {
+    G_FILE_ATTRIBUTE_STANDARD_NAME,
+    G_FILE_ATTRIBUTE_STANDARD_TYPE,
+    NULL
+  };
+
+  g_return_if_fail (G_IS_FILE (directory));
+  g_return_if_fail (!cancellable || G_IS_CANCELLABLE (cancellable));
+
+  if (g_cancellable_is_cancelled (cancellable))
+    return;
+
+  directory_type = g_file_query_file_type (directory,
+                                           G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
+                                           cancellable);
+
+  if (directory_type != G_FILE_TYPE_DIRECTORY)
+    return;
+
+  str = g_string_new (attributes);
+
+  for (guint i = 0; required[i]; i++)
+    {
+      if (!strstr (str->str, required[i]))
+        g_string_append_printf (str, ",%s", required[i]);
+    }
+
+  directories = g_ptr_array_new_with_free_func (g_object_unref);
+  file_infos = g_ptr_array_new_with_free_func (g_object_unref);
+
+  enumerator = g_file_enumerate_children (directory,
+                                          str->str,
+                                          G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
+                                          cancellable,
+                                          NULL);
+
+  if (enumerator == NULL)
+    return;
+
+  while ((infoptr = g_file_enumerator_next_file (enumerator, cancellable, &error)))
+    {
+      g_autoptr(GFileInfo) info = infoptr;
+      g_autoptr(GFile) child = g_file_enumerator_get_child (enumerator, info);
+
+      if (ide_g_file_is_ignored (child))
+        continue;
+
+      if (g_file_info_get_file_type (info) == G_FILE_TYPE_DIRECTORY)
+        g_ptr_array_add (directories, g_steal_pointer (&child));
+
+      g_ptr_array_add (file_infos, g_steal_pointer (&info));
+    }
+
+  callback (directory, file_infos, callback_data);
+
+  for (guint i = 0; i < directories->len; i++)
+    {
+      GFile *child = g_ptr_array_index (directories, i);
+
+      if (g_cancellable_is_cancelled (cancellable))
+        break;
+
+      ide_g_file_walk (child, attributes, cancellable, callback, callback_data);
+    }
+}
diff --git a/src/libide/io/ide-gfile.h b/src/libide/io/ide-gfile.h
index f5f5f46a2..e728b5db4 100644
--- a/src/libide/io/ide-gfile.h
+++ b/src/libide/io/ide-gfile.h
@@ -26,6 +26,18 @@
 
 #include <libide-core.h>
 
+/**
+ * IdeFileWalkCallback:
+ * @directory: a #GFile of the directory
+ * @file_infos: (element-type GFileInfo): array of #GFileInfo children
+ *   of @directory
+ * @user_data: user data for callback
+ *
+ */
+typedef void (*IdeFileWalkCallback) (GFile     *directory,
+                                     GPtrArray *file_infos,
+                                     gpointer   user_data);
+
 G_BEGIN_DECLS
 
 IDE_AVAILABLE_IN_3_32
@@ -76,5 +88,11 @@ gboolean   ide_g_host_file_get_contents             (const gchar          *path,
                                                      gchar               **contents,
                                                      gsize                *len,
                                                      GError              **error);
+IDE_AVAILABLE_IN_3_32
+void       ide_g_file_walk                          (GFile                *directory,
+                                                     const gchar          *attributes,
+                                                     GCancellable         *cancellable,
+                                                     IdeFileWalkCallback   callback,
+                                                     gpointer              callback_data);
 
 G_END_DECLS


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