[gnome-builder] util: add helper to find files matching a pattern
- From: Christian Hergert <chergert src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-builder] util: add helper to find files matching a pattern
- Date: Tue, 30 Jan 2018 12:38:00 +0000 (UTC)
commit 840c93dab3bfce7a2354daa796ae4cbe4453d066
Author: Christian Hergert <chergert redhat com>
Date: Tue Jan 30 04:05:10 2018 -0800
util: add helper to find files matching a pattern
This can be useful since we have so much enumerate-the-tree code. It can
be used from the upcoming flatpak manifest cleanups.
src/libide/util/ide-glib.c | 151 +++++++++++++++++++++++++++++++++++++++++++++
src/libide/util/ide-glib.h | 10 +++
2 files changed, 161 insertions(+)
---
diff --git a/src/libide/util/ide-glib.c b/src/libide/util/ide-glib.c
index 8fb8768bc..d695345ae 100644
--- a/src/libide/util/ide-glib.c
+++ b/src/libide/util/ide-glib.c
@@ -23,6 +23,7 @@
#include "config.h"
#include "util/ide-glib.h"
+#include "vcs/ide-vcs.h"
typedef struct
{
@@ -401,3 +402,153 @@ ide_g_file_get_children_finish (GFile *file,
return g_task_propagate_pointer (G_TASK (result), error);
}
+
+static void
+populate_descendants_matching (GFile *file,
+ GCancellable *cancellable,
+ GPtrArray *results,
+ GPatternSpec *spec)
+{
+ g_autoptr(GFileEnumerator) enumerator = NULL;
+ g_autoptr(GPtrArray) children = NULL;
+
+ g_assert (G_IS_FILE (file));
+ g_assert (results != NULL);
+ g_assert (spec != NULL);
+
+ enumerator = g_file_enumerate_children (file,
+ G_FILE_ATTRIBUTE_STANDARD_NAME","
+ G_FILE_ATTRIBUTE_STANDARD_TYPE,
+ G_FILE_QUERY_INFO_NONE,
+ cancellable,
+ NULL);
+
+ if (enumerator == NULL)
+ return;
+
+ for (;;)
+ {
+ g_autoptr(GFileInfo) info = g_file_enumerator_next_file (enumerator, cancellable, NULL);
+ const gchar *name;
+ GFileType file_type;
+
+ if (info == NULL)
+ break;
+
+ name = g_file_info_get_name (info);
+ file_type = g_file_info_get_file_type (info);
+
+ if (g_pattern_match_string (spec, name))
+ g_ptr_array_add (results, g_file_enumerator_get_child (enumerator, info));
+
+ if (file_type == G_FILE_TYPE_DIRECTORY)
+ {
+ if (children == NULL)
+ children = g_ptr_array_new_with_free_func (g_object_unref);
+ g_ptr_array_add (children, g_file_enumerator_get_child (enumerator, info));
+ }
+ }
+
+ g_file_enumerator_close (enumerator, cancellable, NULL);
+
+ if (children != NULL)
+ {
+ for (guint i = 0; i < children->len; i++)
+ {
+ GFile *child = g_ptr_array_index (children, i);
+
+ /* Don't recurse into known bad directories */
+ if (!ide_vcs_is_ignored (NULL, child, NULL))
+ populate_descendants_matching (child, cancellable, results, spec);
+ }
+ }
+}
+
+static void
+ide_g_file_find_worker (GTask *task,
+ gpointer source_object,
+ gpointer task_data,
+ GCancellable *cancellable)
+{
+ GFile *file = source_object;
+ GPatternSpec *spec = 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 (!cancellable || G_IS_CANCELLABLE (cancellable));
+
+ ret = g_ptr_array_new_with_free_func (g_object_unref);
+ populate_descendants_matching (file, cancellable, ret, spec);
+ g_task_return_pointer (task, g_steal_pointer (&ret), (GDestroyNotify)g_ptr_array_unref);
+}
+
+/**
+ * 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)
+{
+ g_autoptr(GTask) task = NULL;
+ g_autoptr(GPatternSpec) spec = NULL;
+
+ g_return_if_fail (G_IS_FILE (file));
+ g_return_if_fail (pattern != NULL);
+ g_return_if_fail (!cancellable || G_IS_CANCELLABLE (cancellable));
+
+ 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);
+
+ if (spec == NULL)
+ {
+ g_task_return_new_error (task,
+ G_IO_ERROR,
+ G_IO_ERROR_INVAL,
+ "Invalid pattern spec: %s",
+ pattern);
+ 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_finish:
+ * @file: a #GFile
+ * @result: a result provided to callback
+ * @error: a location for a #GError or %NULL
+ *
+ * Gets the files that were found which matched the pattern.
+ *
+ * Returns: (transfer container) (element-type Gio.File): A #GPtrArray of #GFile
+ */
+GPtrArray *
+ide_g_file_find_finish (GFile *file,
+ GAsyncResult *result,
+ GError **error)
+{
+ g_return_val_if_fail (G_IS_FILE (file), NULL);
+ g_return_val_if_fail (G_IS_TASK (result), NULL);
+
+ return g_task_propagate_pointer (G_TASK (result), error);
+}
diff --git a/src/libide/util/ide-glib.h b/src/libide/util/ide-glib.h
index 03adb220c..2bf5e0ca2 100644
--- a/src/libide/util/ide-glib.h
+++ b/src/libide/util/ide-glib.h
@@ -43,6 +43,16 @@ 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_async (GFile *file,
+ const gchar *pattern,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+IDE_AVAILABLE_IN_3_28
+GPtrArray *ide_g_file_find_finish (GFile *file,
+ GAsyncResult *result,
+ GError **error);
+IDE_AVAILABLE_IN_3_28
void ide_g_file_get_children_async (GFile *file,
const gchar *attributes,
GFileQueryInfoFlags flags,
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]