[gnome-builder] code-index: add GbpCodeIndexPlan
- From: Christian Hergert <chergert src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-builder] code-index: add GbpCodeIndexPlan
- Date: Tue, 5 Feb 2019 06:16:01 +0000 (UTC)
commit 4d0044b670f45446174b4988ee606714345c1ebf
Author: Christian Hergert <chergert redhat com>
Date: Thu Jan 31 14:29:23 2019 -0800
code-index: add GbpCodeIndexPlan
This object can be used to help discover the plan we will take when
building our code indexes. Future code will expand on this so that we
can extract bits from the IdeCodeIndexBuilder implementation.
We should also be able to provide progress support going forward as we
will know what needs to be done. I'm also interested in seeing a plan
executor object (which is where pausability can be implemented).
src/plugins/code-index/gbp-code-index-plan.c | 622 +++++++++++++++++++++++++++
src/plugins/code-index/gbp-code-index-plan.h | 80 ++++
src/plugins/code-index/meson.build | 1 +
3 files changed, 703 insertions(+)
---
diff --git a/src/plugins/code-index/gbp-code-index-plan.c b/src/plugins/code-index/gbp-code-index-plan.c
new file mode 100644
index 000000000..13f80d298
--- /dev/null
+++ b/src/plugins/code-index/gbp-code-index-plan.c
@@ -0,0 +1,622 @@
+/* gbp-code-index-plan.c
+ *
+ * Copyright 2019 Christian Hergert <chergert redhat com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#define G_LOG_DOMAIN "gbp-code-index-plan"
+
+#include "config.h"
+
+#include <gtksourceview/gtksource.h>
+#include <libide-core.h>
+#include <libide-foundry.h>
+#include <libide-vcs.h>
+#include <libpeas/peas.h>
+
+#include "gbp-code-index-plan.h"
+#include "ide-code-index-index.h"
+
+struct _GbpCodeIndexPlan
+{
+ GObject parent_instance;
+
+ GMutex mutex;
+ GHashTable *directories;
+};
+
+typedef struct
+{
+ GFile *directory;
+ GPtrArray *plan_items;
+ GbpCodeIndexReason reason;
+} DirectoryInfo;
+
+typedef struct
+{
+ GPtrArray *indexers;
+ GFile *workdir;
+ IdeVcs *vcs;
+ IdeBuildSystem *build_system;
+} PopulateData;
+
+typedef struct
+{
+ const gchar *module_name;
+ GPtrArray *specs;
+ GPtrArray *mime_types;
+} IndexerInfo;
+
+typedef struct
+{
+ GFile *cachedir;
+ GFile *workdir;
+} CullIndexed;
+
+G_DEFINE_TYPE (GbpCodeIndexPlan, gbp_code_index_plan, G_TYPE_OBJECT)
+
+static void
+directory_info_free (DirectoryInfo *info)
+{
+ g_clear_object (&info->directory);
+ g_clear_pointer (&info->plan_items, g_ptr_array_unref);
+ g_slice_free (DirectoryInfo, info);
+}
+
+static void
+indexer_info_free (IndexerInfo *info)
+{
+ g_clear_pointer (&info->specs, g_ptr_array_unref);
+ g_clear_pointer (&info->mime_types, g_ptr_array_unref);
+ g_slice_free (IndexerInfo, info);
+}
+
+static void
+populate_data_free (PopulateData *data)
+{
+ g_clear_object (&data->workdir);
+ g_clear_object (&data->vcs);
+ g_clear_object (&data->build_system);
+ g_slice_free (PopulateData, data);
+}
+
+static void
+plan_item_free (GbpCodeIndexPlanItem *item)
+{
+ g_clear_object (&item->file_info);
+ g_clear_pointer (&item->build_flags, g_strfreev);
+ item->indexer_module_name = NULL;
+ g_slice_free (GbpCodeIndexPlanItem, item);
+}
+
+static void
+cull_indexed_free (CullIndexed *cull)
+{
+ g_clear_object (&cull->cachedir);
+ g_clear_object (&cull->workdir);
+ g_slice_free (CullIndexed, cull);
+}
+
+static void
+gbp_code_index_plan_finalize (GObject *object)
+{
+ GbpCodeIndexPlan *self = (GbpCodeIndexPlan *)object;
+
+ g_clear_pointer (&self->directories, g_hash_table_unref);
+ g_mutex_clear (&self->mutex);
+
+ G_OBJECT_CLASS (gbp_code_index_plan_parent_class)->finalize (object);
+}
+
+static void
+gbp_code_index_plan_class_init (GbpCodeIndexPlanClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->finalize = gbp_code_index_plan_finalize;
+}
+
+static void
+gbp_code_index_plan_init (GbpCodeIndexPlan *self)
+{
+ g_mutex_init (&self->mutex);
+ self->directories = g_hash_table_new_full (g_file_hash,
+ (GEqualFunc)g_file_equal,
+ NULL,
+ (GDestroyNotify)directory_info_free);
+}
+
+GbpCodeIndexPlan *
+gbp_code_index_plan_new (void)
+{
+ return g_object_new (GBP_TYPE_CODE_INDEX_PLAN, NULL);
+}
+
+static guint64
+newest_mtime (GFile *a,
+ GFile *b,
+ GCancellable *cancellable)
+{
+ g_autoptr(GFileInfo) ainfo = NULL;
+ g_autoptr(GFileInfo) binfo = NULL;
+ guint64 aval = 0;
+ guint64 bval = 0;
+
+ ainfo = g_file_query_info (a, G_FILE_ATTRIBUTE_TIME_MODIFIED, 0, cancellable, NULL);
+ binfo = g_file_query_info (b, G_FILE_ATTRIBUTE_TIME_MODIFIED, 0, cancellable, NULL);
+
+ if (ainfo)
+ aval = g_file_info_get_attribute_uint64 (ainfo, G_FILE_ATTRIBUTE_TIME_MODIFIED);
+
+ if (binfo)
+ bval = g_file_info_get_attribute_uint64 (binfo, G_FILE_ATTRIBUTE_TIME_MODIFIED);
+
+ return aval > bval ? aval : bval;
+}
+
+static void
+gbp_code_index_plan_cull_indexed_worker (IdeTask *task,
+ gpointer source_object,
+ gpointer task_data,
+ GCancellable *cancellable)
+{
+ GbpCodeIndexPlan *self = source_object;
+ CullIndexed *cull = task_data;
+ GHashTableIter iter;
+ gpointer key, value;
+
+ g_assert (IDE_IS_TASK (task));
+ g_assert (GBP_IS_CODE_INDEX_PLAN (self));
+ g_assert (G_IS_FILE (cull->cachedir));
+ g_assert (G_IS_FILE (cull->workdir));
+ g_assert (!cancellable || G_IS_CANCELLABLE (cancellable));
+
+ g_mutex_lock (&self->mutex);
+
+ g_hash_table_iter_init (&iter, self->directories);
+
+ while (g_hash_table_iter_next (&iter, &key, &value))
+ {
+ g_autofree gchar *relative = NULL;
+ g_autoptr(IdeCodeIndexIndex) index = NULL;
+ g_autoptr(GFile) indexdir = NULL;
+ g_autoptr(GFile) symbol_keys = NULL;
+ g_autoptr(GFile) symbol_names = NULL;
+ g_autoptr(DzlFuzzyIndex) fuzzy = NULL;
+ DirectoryInfo *info = value;
+ GFile *directory = key;
+ gboolean expired = FALSE;
+ guint64 mtime;
+
+ if (ide_task_return_error_if_cancelled (task))
+ break;
+
+ relative = g_file_get_relative_path (cull->workdir, directory);
+
+ if (relative == NULL)
+ indexdir = g_object_ref (cull->cachedir);
+ else
+ indexdir = g_file_get_child (cull->cachedir, relative);
+
+ symbol_keys = g_file_get_child (indexdir, "SymbolKeys");
+ symbol_names = g_file_get_child (indexdir, "SymbolNames");
+ mtime = newest_mtime (symbol_keys, symbol_names, cancellable);
+
+ /* Indexes don't yet exist, create them unless no files are available */
+ if (!g_file_query_exists (symbol_keys, cancellable) ||
+ !g_file_query_exists (symbol_names, cancellable))
+ {
+ if (ide_task_return_error_if_cancelled (task))
+ break;
+
+ if (info->plan_items->len == 0)
+ {
+ /* Nothing really to index, and no symol files, drop request */
+ g_hash_table_iter_remove (&iter);
+ continue;
+ }
+ else
+ {
+ info->reason = GBP_CODE_INDEX_REASON_INITIAL;
+ continue;
+ }
+ }
+
+ /* Indexes exist, but files no longer do. So remove them */
+ if (info->plan_items->len == 0)
+ {
+ info->reason = GBP_CODE_INDEX_REASON_REMOVE_INDEX;
+ continue;
+ }
+
+ for (guint i = 0; i < info->plan_items->len; i++)
+ {
+ GbpCodeIndexPlanItem *item = g_ptr_array_index (info->plan_items, i);
+ guint64 item_mtime = g_file_info_get_attribute_uint64 (item->file_info,
G_FILE_ATTRIBUTE_TIME_MODIFIED);
+
+ if (item_mtime > mtime)
+ {
+ expired = TRUE;
+ break;
+ }
+ }
+
+ if (expired)
+ {
+ info->reason = GBP_CODE_INDEX_REASON_EXPIRED;
+ continue;
+ }
+
+ fuzzy = dzl_fuzzy_index_new ();
+
+ if (dzl_fuzzy_index_load_file (fuzzy, symbol_names, cancellable, NULL))
+ {
+ guint32 n_files;
+
+ if (ide_task_return_error_if_cancelled (task))
+ break;
+
+ n_files = dzl_fuzzy_index_get_metadata_uint32 (fuzzy, "n_files");
+
+ if (n_files != info->plan_items->len)
+ {
+ info->reason = GBP_CODE_INDEX_REASON_CHANGES;
+ continue;
+ }
+ }
+ else
+ {
+ /* Index is bad, we need to recreate it */
+ info->reason = GBP_CODE_INDEX_REASON_INITIAL;
+ continue;
+ }
+
+ /* Everything looks fine with this entry, nothing to update */
+ g_hash_table_iter_remove (&iter);
+ }
+
+ g_mutex_unlock (&self->mutex);
+
+ ide_task_return_boolean (task, TRUE);
+}
+
+void
+gbp_code_index_plan_cull_indexed_async (GbpCodeIndexPlan *self,
+ IdeContext *context,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ g_autoptr(IdeTask) task = NULL;
+ g_autoptr(GFile) basedir = NULL;
+ CullIndexed *state;
+
+ g_return_if_fail (GBP_IS_CODE_INDEX_PLAN (self));
+ g_return_if_fail (!cancellable || G_IS_CANCELLABLE (cancellable));
+
+ state = g_slice_new0 (CullIndexed);
+ state->cachedir = ide_context_cache_file (context, "code-index", NULL);
+ state->workdir = ide_context_ref_workdir (context);
+
+ task = ide_task_new (self, cancellable, callback, user_data);
+ ide_task_set_source_tag (task, gbp_code_index_plan_cull_indexed_async);
+ ide_task_set_task_data (task, state, cull_indexed_free);
+ ide_task_run_in_thread (task, gbp_code_index_plan_cull_indexed_worker);
+}
+
+gboolean
+gbp_code_index_plan_cull_indexed_finish (GbpCodeIndexPlan *self,
+ GAsyncResult *result,
+ GError **error)
+{
+ g_return_val_if_fail (IDE_IS_MAIN_THREAD (), FALSE);
+ g_return_val_if_fail (GBP_IS_CODE_INDEX_PLAN (self), FALSE);
+ g_return_val_if_fail (IDE_IS_TASK (result), FALSE);
+
+ return ide_task_propagate_boolean (IDE_TASK (result), error);
+}
+
+void
+gbp_code_index_plan_foreach (GbpCodeIndexPlan *self,
+ GbpCodeIndexPlanForeach foreach_func,
+ gpointer foreach_data)
+{
+ GHashTableIter iter;
+ gpointer key, value;
+
+ g_return_if_fail (GBP_IS_CODE_INDEX_PLAN (self));
+ g_return_if_fail (foreach_func != NULL);
+
+ g_mutex_lock (&self->mutex);
+
+ g_hash_table_iter_init (&iter, self->directories);
+
+ while (g_hash_table_iter_next (&iter, &key, &value))
+ {
+ GFile *directory = key;
+ DirectoryInfo *info = value;
+
+ if (foreach_func (directory, info->plan_items, info->reason, foreach_data))
+ g_hash_table_iter_remove (&iter);
+ }
+
+ g_mutex_unlock (&self->mutex);
+}
+
+static GPtrArray *
+collect_indexer_info (void)
+{
+ GtkSourceLanguageManager *manager;
+ g_autoptr(GPtrArray) indexers = NULL;
+ const GList *plugins;
+ PeasEngine *engine;
+
+ g_assert (IDE_IS_MAIN_THREAD ());
+
+ manager = gtk_source_language_manager_get_default ();
+ engine = peas_engine_get_default ();
+ plugins = peas_engine_get_plugin_list (engine);
+ indexers = g_ptr_array_new_with_free_func ((GDestroyNotify)indexer_info_free);
+
+ for (; plugins != NULL; plugins = plugins->next)
+ {
+ const PeasPluginInfo *plugin_info = plugins->data;
+ const gchar *module_name;
+ g_autofree gchar *str = NULL;
+ g_auto(GStrv) split = NULL;
+ IndexerInfo *info;
+
+ if (!peas_plugin_info_is_loaded (plugin_info) ||
+ !(str = g_strdup (peas_plugin_info_get_external_data (plugin_info, "Code-Indexer-Languages"))))
+ continue;
+
+ module_name = peas_plugin_info_get_module_name (plugin_info);
+ split = g_strsplit (g_strdelimit (str, ",", ';'), ";", 0);
+
+ info = g_slice_new0 (IndexerInfo);
+ info->module_name = g_intern_string (module_name);
+ info->mime_types = g_ptr_array_new ();
+ info->specs = g_ptr_array_new_with_free_func ((GDestroyNotify)g_pattern_spec_free);
+
+ for (guint i = 0; split[i]; i++)
+ {
+ GtkSourceLanguage *lang;
+ const gchar *name = split[i];
+ g_auto(GStrv) globs = NULL;
+ g_auto(GStrv) mime_types = NULL;
+
+ if (!(lang = gtk_source_language_manager_get_language (manager, name)))
+ {
+ g_warning ("No such language \"%s\" in %s plugin description",
+ name, module_name);
+ continue;
+ }
+
+ globs = gtk_source_language_get_globs (lang);
+ mime_types = gtk_source_language_get_mime_types (lang);
+
+ for (guint j = 0; globs[j] != NULL; j++)
+ {
+ g_autoptr(GPatternSpec) spec = g_pattern_spec_new (globs[j]);
+ g_ptr_array_add (info->specs, g_steal_pointer (&spec));
+ }
+
+ for (guint j = 0; mime_types[j]; j++)
+ g_ptr_array_add (info->mime_types, (gchar *)g_intern_string (mime_types[j]));
+ }
+
+ g_ptr_array_add (indexers, g_steal_pointer (&info));
+ }
+
+ return g_steal_pointer (&indexers);
+}
+
+static gboolean
+indexer_info_matches (const IndexerInfo *info,
+ const gchar *filename,
+ const gchar *filename_reversed,
+ const gchar *mime_type)
+{
+ gsize len;
+
+ g_assert (info != NULL);
+ g_assert (filename != NULL);
+ g_assert (filename_reversed != NULL);
+
+ if (mime_type != NULL)
+ {
+ mime_type = g_intern_string (mime_type);
+
+ for (guint i = 0; i < info->mime_types->len; i++)
+ {
+ const gchar *mt = g_ptr_array_index (info->mime_types, i);
+
+ /* interned strings can-use pointer comparison */
+ if (mt == mime_type)
+ return TRUE;
+ }
+ }
+
+ len = strlen (filename);
+
+ for (guint i = 0; i < info->specs->len; i++)
+ {
+ GPatternSpec *spec = g_ptr_array_index (info->specs, i);
+
+ if (g_pattern_match (spec, len, filename, filename_reversed))
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static void
+gbp_code_index_plan_populate_cb (GFile *directory,
+ GPtrArray *file_infos,
+ gpointer user_data)
+{
+ g_autoptr(GPtrArray) items = NULL;
+ IdeTask *task = user_data;
+ GbpCodeIndexPlan *self;
+ DirectoryInfo *info;
+ PopulateData *state;
+
+ g_assert (IDE_IS_TASK (task));
+ g_assert (G_IS_FILE (directory));
+ g_assert (file_infos != NULL);
+
+ self = ide_task_get_source_object (task);
+ state = ide_task_get_task_data (task);
+
+ g_assert (GBP_IS_CODE_INDEX_PLAN (self));
+ g_assert (state != NULL);
+ g_assert (G_IS_FILE (state->workdir));
+ g_assert (state->indexers != NULL);
+
+ items = g_ptr_array_new_with_free_func ((GDestroyNotify)plan_item_free);
+
+ for (guint i = 0; i < file_infos->len; i++)
+ {
+ GFileInfo *file_info = g_ptr_array_index (file_infos, i);
+ g_autoptr(GFile) file = NULL;
+ g_autofree gchar *reversed = NULL;
+ const gchar *indexer_module_name = NULL;
+ const gchar *mime_type;
+ const gchar *name;
+ GbpCodeIndexPlanItem *item;
+
+ if (!(name = g_file_info_get_name (file_info)))
+ continue;
+
+ file = g_file_get_child (directory, name);
+
+ if (ide_vcs_is_ignored (state->vcs, file, NULL))
+ continue;
+
+ reversed = g_utf8_strreverse (name, -1);
+ mime_type = g_file_info_get_attribute_string (file_info, G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE);
+
+ for (guint j = 0; j < state->indexers->len; j++)
+ {
+ const IndexerInfo *indexer = g_ptr_array_index (state->indexers, j);
+
+ if (indexer_info_matches (indexer, name, reversed, mime_type))
+ {
+ indexer_module_name = indexer->module_name;
+ break;
+ }
+ }
+
+ if (indexer_module_name == NULL)
+ continue;
+
+ item = g_slice_new0 (GbpCodeIndexPlanItem);
+ item->file_info = g_object_ref (file_info);
+ item->build_flags = NULL;
+ item->indexer_module_name = indexer_module_name;
+
+ g_ptr_array_add (items, g_steal_pointer (&item));
+ }
+
+ info = g_slice_new0 (DirectoryInfo);
+ info->directory = g_file_dup (directory);
+ info->plan_items = g_steal_pointer (&items);
+ info->reason = GBP_CODE_INDEX_REASON_INITIAL;
+
+ g_mutex_lock (&self->mutex);
+ g_hash_table_insert (self->directories, info->directory, info);
+ g_mutex_unlock (&self->mutex);
+}
+
+static void
+gbp_code_index_plan_populate_worker (IdeTask *task,
+ gpointer source_object,
+ gpointer task_data,
+ GCancellable *cancellable)
+{
+ GbpCodeIndexPlan *self = source_object;
+ PopulateData *state = task_data;
+
+ g_assert (IDE_IS_TASK (task));
+ g_assert (GBP_IS_CODE_INDEX_PLAN (self));
+ g_assert (state != NULL);
+ g_assert (IDE_IS_BUILD_SYSTEM (state->build_system));
+ g_assert (IDE_IS_VCS (state->vcs));
+ g_assert (G_IS_FILE (state->workdir));
+
+ ide_g_file_walk (state->workdir,
+ G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE","
+ G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME","
+ G_FILE_ATTRIBUTE_STANDARD_NAME","
+ G_FILE_ATTRIBUTE_STANDARD_SIZE","
+ G_FILE_ATTRIBUTE_STANDARD_TYPE","
+ G_FILE_ATTRIBUTE_TIME_MODIFIED,
+ cancellable,
+ gbp_code_index_plan_populate_cb,
+ task);
+
+ ide_task_return_boolean (task, TRUE);
+}
+
+void
+gbp_code_index_plan_populate_async (GbpCodeIndexPlan *self,
+ IdeContext *context,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ g_autoptr(IdeTask) task = NULL;
+ g_autoptr(GFile) workdir = NULL;
+ IdeBuildSystem *build_system = NULL;
+ IdeVcs *vcs = NULL;
+ PopulateData *state;
+
+ g_return_if_fail (IDE_IS_MAIN_THREAD ());
+ g_return_if_fail (GBP_IS_CODE_INDEX_PLAN (self));
+ g_return_if_fail (IDE_IS_CONTEXT (context));
+ g_return_if_fail (!cancellable || G_IS_CANCELLABLE (cancellable));
+
+ workdir = ide_context_ref_workdir (context);
+ build_system = ide_build_system_from_context (context);
+ vcs = ide_vcs_from_context (context);
+
+ g_return_if_fail (IDE_IS_BUILD_SYSTEM (build_system));
+ g_return_if_fail (IDE_IS_VCS (vcs));
+
+ state = g_slice_new0 (PopulateData);
+ state->vcs = g_object_ref (vcs);
+ state->build_system = g_object_ref (build_system);
+ state->workdir = g_file_dup (workdir);
+ state->indexers = collect_indexer_info ();
+
+ task = ide_task_new (self, cancellable, callback, user_data);
+ ide_task_set_source_tag (task, gbp_code_index_plan_populate_async);
+ ide_task_set_task_data (task, state, populate_data_free);
+ ide_task_run_in_thread (task, gbp_code_index_plan_populate_worker);
+}
+
+gboolean
+gbp_code_index_plan_populate_finish (GbpCodeIndexPlan *self,
+ GAsyncResult *result,
+ GError **error)
+{
+ g_return_val_if_fail (IDE_IS_MAIN_THREAD (), FALSE);
+ g_return_val_if_fail (GBP_IS_CODE_INDEX_PLAN (self), FALSE);
+ g_return_val_if_fail (IDE_IS_TASK (result), FALSE);
+
+ return ide_task_propagate_boolean (IDE_TASK (result), error);
+}
diff --git a/src/plugins/code-index/gbp-code-index-plan.h b/src/plugins/code-index/gbp-code-index-plan.h
new file mode 100644
index 000000000..a754932b0
--- /dev/null
+++ b/src/plugins/code-index/gbp-code-index-plan.h
@@ -0,0 +1,80 @@
+/* gbp-code-index-plan.h
+ *
+ * Copyright 2019 Christian Hergert <chergert redhat com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#pragma once
+
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+#define GBP_TYPE_CODE_INDEX_PLAN (gbp_code_index_plan_get_type())
+
+G_DECLARE_FINAL_TYPE (GbpCodeIndexPlan, gbp_code_index_plan, GBP, CODE_INDEX_PLAN, GObject)
+
+typedef struct
+{
+ GFileInfo *file_info;
+ gchar **build_flags;
+ const gchar *indexer_module_name;
+} GbpCodeIndexPlanItem;
+
+typedef enum
+{
+ GBP_CODE_INDEX_REASON_INITIAL = 1,
+ GBP_CODE_INDEX_REASON_EXPIRED,
+ GBP_CODE_INDEX_REASON_CHANGES,
+ GBP_CODE_INDEX_REASON_REMOVE_INDEX,
+} GbpCodeIndexReason;
+
+/**
+ * GbpCodeIndexPlanForeach:
+ * @directory: the directory containing the items
+ * @plan_items: (element-type GbpCodeIndexPlanItem): array of #GbpCodeIndexPlanItem
+ * @reason: the reason for the (re)indexing
+ *
+ * Returns: %TRUE to remove item from plan
+ */
+typedef gboolean (*GbpCodeIndexPlanForeach) (GFile *directory,
+ GPtrArray *plan_items,
+ GbpCodeIndexReason reason,
+ gpointer user_data);
+
+GbpCodeIndexPlan *gbp_code_index_plan_new (void);
+void gbp_code_index_plan_populate_async (GbpCodeIndexPlan *self,
+ IdeContext *context,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+gboolean gbp_code_index_plan_populate_finish (GbpCodeIndexPlan *self,
+ GAsyncResult *result,
+ GError **error);
+void gbp_code_index_plan_cull_indexed_async (GbpCodeIndexPlan *self,
+ IdeContext *context,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+gboolean gbp_code_index_plan_cull_indexed_finish (GbpCodeIndexPlan *self,
+ GAsyncResult *result,
+ GError **error);
+void gbp_code_index_plan_foreach (GbpCodeIndexPlan *self,
+ GbpCodeIndexPlanForeach foreach_func,
+ gpointer foreach_data);
+
+G_END_DECLS
diff --git a/src/plugins/code-index/meson.build b/src/plugins/code-index/meson.build
index b24c8f2d2..dc6ae2b40 100644
--- a/src/plugins/code-index/meson.build
+++ b/src/plugins/code-index/meson.build
@@ -3,6 +3,7 @@ if get_option('plugin_code_index')
plugins_sources += files([
'code-index-plugin.c',
'gbp-code-index-application-addin.c',
+ 'gbp-code-index-plan.c',
'gbp-code-index-workbench-addin.c',
'ide-code-index-builder.c',
'ide-code-index-index.c',
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]