[gnome-builder] code: settle buffer before saving
- From: Christian Hergert <chergert src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-builder] code: settle buffer before saving
- Date: Mon, 18 Feb 2019 19:38:09 +0000 (UTC)
commit 648c3ff7b073ad970e651fe58a7e8e75cb6f6333
Author: Christian Hergert <chergert redhat com>
Date: Mon Feb 18 11:10:01 2019 -0800
code: settle buffer before saving
This will query all buffer addins to request that they settle any in-flight
changes before the save_file vfunc is called. Doing so allows plugins to
ensure that things like change flags are available for changes that have
raced with the save operation.
src/libide/code/ide-buffer.c | 181 ++++++++++++++++++++++++++++++++++++++-----
1 file changed, 163 insertions(+), 18 deletions(-)
---
diff --git a/src/libide/code/ide-buffer.c b/src/libide/code/ide-buffer.c
index a4c2682e3..033330f79 100644
--- a/src/libide/code/ide-buffer.c
+++ b/src/libide/code/ide-buffer.c
@@ -106,6 +106,7 @@ typedef struct
{
GFile *file;
IdeNotification *notif;
+ GtkSourceFile *source_file;
} SaveState;
typedef struct
@@ -221,6 +222,13 @@ static gboolean ide_buffer_can_do_newline_hack (IdeBuffer *self
guint len);
static void ide_buffer_guess_language (IdeBuffer *self);
static void ide_buffer_real_loaded (IdeBuffer *self);
+static void settle_async (IdeBuffer *self,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+static gboolean settle_finish (IdeBuffer *self,
+ GAsyncResult *result,
+ GError **error);
static void
load_state_free (LoadState *state)
@@ -241,6 +249,7 @@ save_state_free (SaveState *state)
g_clear_object (&state->notif);
g_clear_object (&state->file);
+ g_clear_object (&state->source_file);
g_slice_free (SaveState, state);
}
@@ -1413,6 +1422,50 @@ ide_buffer_save_file_cb (GObject *object,
IDE_EXIT;
}
+static void
+ide_buffer_save_file_settle_cb (GObject *object,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ IdeBuffer *self = (IdeBuffer *)object;
+ g_autoptr(IdeTask) task = user_data;
+ g_autoptr(GtkSourceFileSaver) saver = NULL;
+ SaveState *state;
+
+ g_assert (IDE_IS_MAIN_THREAD ());
+ g_assert (IDE_IS_BUFFER (self));
+ g_assert (G_IS_ASYNC_RESULT (result));
+ g_assert (IDE_IS_TASK (task));
+
+ settle_finish (self, result, NULL);
+
+ state = ide_task_get_task_data (task);
+
+ g_assert (state != NULL);
+ g_assert (G_IS_FILE (state->file));
+ g_assert (IDE_IS_NOTIFICATION (state->notif));
+ g_assert (GTK_SOURCE_IS_FILE (state->source_file));
+
+ if (self->addins != NULL)
+ {
+ IdeBufferFileSave closure = { self, state->file };
+ ide_extension_set_adapter_foreach (self->addins,
+ _ide_buffer_addin_save_file_cb,
+ &closure);
+ }
+
+ saver = gtk_source_file_saver_new (GTK_SOURCE_BUFFER (self), state->source_file);
+ gtk_source_file_saver_save_async (saver,
+ G_PRIORITY_DEFAULT,
+ ide_task_get_cancellable (task),
+ ide_buffer_progress_cb,
+ g_object_ref (state->notif),
+ g_object_unref,
+ ide_buffer_save_file_cb,
+ g_object_ref (task));
+
+}
+
/**
* ide_buffer_save_file_async:
* @self: an #IdeBuffer
@@ -1443,7 +1496,6 @@ ide_buffer_save_file_async (IdeBuffer *self,
{
g_autoptr(IdeTask) task = NULL;
g_autoptr(GtkSourceFile) alternate = NULL;
- g_autoptr(GtkSourceFileSaver) saver = NULL;
g_autoptr(IdeNotification) local_notif = NULL;
GtkSourceFile *source_file;
SaveState *state;
@@ -1507,6 +1559,8 @@ ide_buffer_save_file_async (IdeBuffer *self,
source_file = alternate;
}
+ state->source_file = g_object_ref (source_file);
+
/* Possibly avoid any writing if we can detect a no-change state */
if (file == NULL || g_file_equal (file, ide_buffer_get_file (self)))
{
@@ -1519,24 +1573,12 @@ ide_buffer_save_file_async (IdeBuffer *self,
}
}
- if (self->addins != NULL)
- {
- IdeBufferFileSave closure = { self, file };
- ide_extension_set_adapter_foreach (self->addins,
- _ide_buffer_addin_save_file_cb,
- &closure);
- }
-
- saver = gtk_source_file_saver_new (GTK_SOURCE_BUFFER (self), source_file);
ide_buffer_set_state (self, IDE_BUFFER_STATE_SAVING);
- gtk_source_file_saver_save_async (saver,
- G_PRIORITY_DEFAULT,
- cancellable,
- ide_buffer_progress_cb,
- g_object_ref (local_notif),
- g_object_unref,
- ide_buffer_save_file_cb,
- g_steal_pointer (&task));
+
+ settle_async (self,
+ cancellable,
+ ide_buffer_save_file_settle_cb,
+ g_steal_pointer (&task));
set_out_param:
if (notif != NULL)
@@ -3625,3 +3667,106 @@ ide_buffer_has_symbol_resolvers (IdeBuffer *self)
return self->symbol_resolvers != NULL &&
ide_extension_set_adapter_get_n_extensions (self->symbol_resolvers) > 0;
}
+
+static void
+settle_cb (GObject *object,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ IdeBufferAddin *addin = (IdeBufferAddin *)object;
+ g_autoptr(IdeTask) task = user_data;
+ g_autoptr(GError) error = NULL;
+ gint *n_active;
+
+ g_assert (IDE_IS_MAIN_THREAD ());
+ g_assert (IDE_IS_BUFFER_ADDIN (addin));
+ g_assert (G_IS_ASYNC_RESULT (result));
+ g_assert (IDE_IS_TASK (task));
+
+ n_active = ide_task_get_task_data (task);
+
+ if (!ide_buffer_addin_settle_finish (addin, result, &error))
+ g_warning ("Buffer addin \"%s\" failed to settle: %s",
+ G_OBJECT_TYPE_NAME (addin),
+ error->message);
+
+ (*n_active)--;
+
+ if (*n_active == 0)
+ ide_task_return_boolean (task, TRUE);
+}
+
+static void
+settle_foreach_cb (IdeExtensionSetAdapter *set,
+ PeasPluginInfo *plugin_info,
+ PeasExtension *exten,
+ gpointer user_data)
+{
+ IdeBufferAddin *addin = (IdeBufferAddin *)exten;
+ IdeTask *task = user_data;
+ gint *n_active;
+
+ g_assert (IDE_IS_EXTENSION_SET_ADAPTER (set));
+ g_assert (plugin_info != NULL);
+ g_assert (IDE_IS_BUFFER_ADDIN (addin));
+ g_assert (IDE_IS_TASK (task));
+
+ n_active = ide_task_get_task_data (task);
+
+ (*n_active)++;
+
+ ide_buffer_addin_settle_async (addin,
+ ide_task_get_cancellable (task),
+ settle_cb,
+ g_object_ref (task));
+}
+
+static void
+settle_async (IdeBuffer *self,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ g_autoptr(IdeTask) task = NULL;
+ gint *n_active;
+
+ IDE_ENTRY;
+
+ g_assert (IDE_IS_MAIN_THREAD ());
+ g_assert (IDE_IS_BUFFER (self));
+ g_assert (!cancellable || G_IS_CANCELLABLE (cancellable));
+
+ n_active = g_new0 (gint, 1);
+
+ task = ide_task_new (self, cancellable, callback, user_data);
+ ide_task_set_source_tag (task, settle_async);
+ ide_task_set_task_data (task, n_active, g_free);
+
+ if (self->addins != NULL)
+ ide_extension_set_adapter_foreach (self->addins,
+ settle_foreach_cb,
+ task);
+
+ if (*n_active == 0)
+ ide_task_return_boolean (task, TRUE);
+
+ IDE_EXIT;
+}
+
+static gboolean
+settle_finish (IdeBuffer *self,
+ GAsyncResult *result,
+ GError **error)
+{
+ gboolean ret;
+
+ IDE_ENTRY;
+
+ g_assert (IDE_IS_MAIN_THREAD ());
+ g_assert (IDE_IS_BUFFER (self));
+ g_assert (IDE_IS_TASK (result));
+
+ ret = ide_task_propagate_boolean (IDE_TASK (result), error);
+
+ IDE_RETURN (ret);
+}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]