[gtksourceview/wip/loader-saver: 17/31] File saving: check if the file is externally modified
- From: Sébastien Wilmet <swilmet src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtksourceview/wip/loader-saver: 17/31] File saving: check if the file is externally modified
- Date: Sun, 6 Jul 2014 13:22:44 +0000 (UTC)
commit 77a7e0ab48f43ebae7703773bace313b40db5cee
Author: Sébastien Wilmet <swilmet gnome org>
Date: Mon Jun 9 21:33:24 2014 +0200
File saving: check if the file is externally modified
Store the modification time in GtkSourceFile, and update the value on
each file loading and saving.
gtksourceview/gtksourcefile.c | 44 +++++++++++++++
gtksourceview/gtksourcefile.h | 8 +++
gtksourceview/gtksourcefileloader.c | 7 +++
gtksourceview/gtksourcefilesaver.c | 102 +++++++++++++++++++++++++++++++++-
gtksourceview/gtksourcefilesaver.h | 5 ++-
5 files changed, 162 insertions(+), 4 deletions(-)
---
diff --git a/gtksourceview/gtksourcefile.c b/gtksourceview/gtksourcefile.c
index b5fcbe8..ae3929b 100644
--- a/gtksourceview/gtksourcefile.c
+++ b/gtksourceview/gtksourcefile.c
@@ -65,6 +65,13 @@ struct _GtkSourceFilePrivate
GtkSourceMountOperationFactory mount_operation_factory;
gpointer mount_operation_userdata;
+
+ /* Last known modification time of 'location'. The value is updated on a
+ * file loading or file saving.
+ */
+ GTimeVal modification_time;
+
+ guint modification_time_set : 1;
};
G_DEFINE_TYPE_WITH_PRIVATE (GtkSourceFile, gtk_source_file, G_TYPE_OBJECT)
@@ -300,6 +307,9 @@ _gtk_source_file_set_location (GtkSourceFile *file,
g_clear_object (&file->priv->location);
file->priv->location = g_object_ref (location);
g_object_notify (G_OBJECT (file), "location");
+
+ /* The modification_time is for the old location. */
+ file->priv->modification_time_set = FALSE;
}
}
@@ -441,3 +451,37 @@ _gtk_source_file_create_mount_operation (GtkSourceFile *file)
file->priv->mount_operation_factory (file->priv->mount_operation_userdata) :
g_mount_operation_new ();
}
+
+gboolean
+_gtk_source_file_get_modification_time (GtkSourceFile *file,
+ GTimeVal *modification_time)
+{
+ g_assert (modification_time != NULL);
+
+ if (file == NULL)
+ {
+ return FALSE;
+ }
+
+ g_return_val_if_fail (GTK_SOURCE_IS_FILE (file), FALSE);
+
+ if (file->priv->modification_time_set)
+ {
+ *modification_time = file->priv->modification_time;
+ }
+
+ return file->priv->modification_time_set;
+}
+
+void
+_gtk_source_file_set_modification_time (GtkSourceFile *file,
+ GTimeVal modification_time)
+{
+ if (file != NULL)
+ {
+ g_return_if_fail (GTK_SOURCE_IS_FILE (file));
+
+ file->priv->modification_time = modification_time;
+ file->priv->modification_time_set = TRUE;
+ }
+}
diff --git a/gtksourceview/gtksourcefile.h b/gtksourceview/gtksourcefile.h
index be41162..912cf47 100644
--- a/gtksourceview/gtksourcefile.h
+++ b/gtksourceview/gtksourcefile.h
@@ -89,6 +89,14 @@ void _gtk_source_file_set_compression_type (GtkSourceFile
*file,
G_GNUC_INTERNAL
GMountOperation *_gtk_source_file_create_mount_operation (GtkSourceFile *file);
+G_GNUC_INTERNAL
+gboolean _gtk_source_file_get_modification_time (GtkSourceFile *file,
+ GTimeVal *modification_time);
+
+G_GNUC_INTERNAL
+void _gtk_source_file_set_modification_time (GtkSourceFile *file,
+ GTimeVal modification_time);
+
G_END_DECLS
#endif /* __GTK_SOURCE_FILE_H__ */
diff --git a/gtksourceview/gtksourcefileloader.c b/gtksourceview/gtksourcefileloader.c
index 98ae94e..4a41e99 100644
--- a/gtksourceview/gtksourcefileloader.c
+++ b/gtksourceview/gtksourcefileloader.c
@@ -956,6 +956,13 @@ gtk_source_file_loader_load_finish (GtkSourceFileLoader *loader,
_gtk_source_file_set_compression_type (loader->priv->file,
loader->priv->auto_detected_compression_type);
+
+ if (g_file_info_has_attribute (loader->priv->info, G_FILE_ATTRIBUTE_TIME_MODIFIED))
+ {
+ GTimeVal modification_time;
+ g_file_info_get_modification_time (loader->priv->info, &modification_time);
+ _gtk_source_file_set_modification_time (loader->priv->file, modification_time);
+ }
}
reset (loader);
diff --git a/gtksourceview/gtksourcefilesaver.c b/gtksourceview/gtksourcefilesaver.c
index 4f814c0..ae62da8 100644
--- a/gtksourceview/gtksourcefilesaver.c
+++ b/gtksourceview/gtksourcefilesaver.c
@@ -484,7 +484,6 @@ query_info_cb (GFile *file,
g_print ("Finished query info on file\n");
});
- /* TODO update mtime stored in GtkSourceFile */
g_clear_object (&saver->priv->info);
saver->priv->info = g_file_query_info_finish (file, result, &error);
@@ -793,6 +792,96 @@ begin_write (GtkSourceFileSaver *saver)
}
static void
+check_externally_modified_cb (GFile *location,
+ GAsyncResult *result,
+ GtkSourceFileSaver *saver)
+{
+ GFileInfo *info;
+ GTimeVal old_mtime;
+ GTimeVal cur_mtime;
+ GError *error = NULL;
+
+ DEBUG ({
+ g_print ("%s\n", G_STRFUNC);
+ });
+
+ info = g_file_query_info_finish (location, result, &error);
+
+ if (error != NULL)
+ {
+ if (error->domain == G_IO_ERROR &&
+ error->code == G_IO_ERROR_NOT_MOUNTED &&
+ !saver->priv->tried_mount)
+ {
+ recover_not_mounted (saver);
+ g_error_free (error);
+ return;
+ }
+
+ /* It's perfectly fine if the file doesn't exist yet. */
+ if (error->domain != G_IO_ERROR ||
+ error->code != G_IO_ERROR_NOT_FOUND)
+ {
+ DEBUG ({
+ g_print ("Check externally modified failed: %s\n", error->message);
+ });
+
+ g_task_return_error (saver->priv->task, error);
+ return;
+ }
+ else
+ {
+ g_error_free (error);
+ }
+ }
+
+ if (_gtk_source_file_get_modification_time (saver->priv->file, &old_mtime) &&
+ info != NULL &&
+ g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_TIME_MODIFIED))
+ {
+ g_file_info_get_modification_time (info, &cur_mtime);
+
+ if (old_mtime.tv_sec != cur_mtime.tv_sec ||
+ old_mtime.tv_usec != cur_mtime.tv_usec)
+ {
+ DEBUG ({
+ g_print ("The file is externally modified\n");
+ });
+
+ g_task_return_new_error (saver->priv->task,
+ GTK_SOURCE_FILE_SAVER_ERROR,
+ GTK_SOURCE_FILE_SAVER_ERROR_EXTERNALLY_MODIFIED,
+ "The file is externally modified");
+ g_object_unref (info);
+ return;
+ }
+ }
+
+ begin_write (saver);
+
+ if (info != NULL)
+ {
+ g_object_unref (info);
+ }
+}
+
+static void
+check_externally_modified (GtkSourceFileSaver *saver)
+{
+ DEBUG ({
+ g_print ("%s\n", G_STRFUNC);
+ });
+
+ g_file_query_info_async (saver->priv->location,
+ G_FILE_ATTRIBUTE_TIME_MODIFIED,
+ G_FILE_QUERY_INFO_NONE,
+ g_task_get_priority (saver->priv->task),
+ g_task_get_cancellable (saver->priv->task),
+ (GAsyncReadyCallback) check_externally_modified_cb,
+ saver);
+}
+
+static void
mount_cb (GFile *file,
GAsyncResult *result,
GtkSourceFileSaver *saver)
@@ -810,7 +899,7 @@ mount_cb (GFile *file,
g_task_return_error (saver->priv->task, error);
}
- begin_write (saver);
+ check_externally_modified (saver);
}
static void
@@ -1176,7 +1265,7 @@ gtk_source_file_saver_save_async (GtkSourceFileSaver *saver,
saver->priv->newline_type,
implicit_trailing_newline);
- begin_write (saver);
+ check_externally_modified (saver);
}
/**
@@ -1220,6 +1309,13 @@ gtk_source_file_saver_save_finish (GtkSourceFileSaver *saver,
_gtk_source_file_set_compression_type (saver->priv->file,
saver->priv->compression_type);
+
+ if (g_file_info_has_attribute (saver->priv->info, G_FILE_ATTRIBUTE_TIME_MODIFIED))
+ {
+ GTimeVal modification_time;
+ g_file_info_get_modification_time (saver->priv->info, &modification_time);
+ _gtk_source_file_set_modification_time (saver->priv->file, modification_time);
+ }
}
reset (saver);
diff --git a/gtksourceview/gtksourcefilesaver.h b/gtksourceview/gtksourcefilesaver.h
index 0a65ff5..c5afb78 100644
--- a/gtksourceview/gtksourcefilesaver.h
+++ b/gtksourceview/gtksourcefilesaver.h
@@ -47,12 +47,15 @@ typedef struct _GtkSourceFileSaverPrivate GtkSourceFileSaverPrivate;
* GtkSourceFileSaverError:
* @GTK_SOURCE_FILE_SAVER_ERROR_INVALID_CHARS: The buffer contains invalid
* characters.
+ * @GTK_SOURCE_FILE_SAVER_ERROR_EXTERNALLY_MODIFIED: The file is externally
+ * modified.
*
* An error code used with the %GTK_SOURCE_FILE_SAVER_ERROR domain.
*/
typedef enum
{
- GTK_SOURCE_FILE_SAVER_ERROR_INVALID_CHARS
+ GTK_SOURCE_FILE_SAVER_ERROR_INVALID_CHARS,
+ GTK_SOURCE_FILE_SAVER_ERROR_EXTERNALLY_MODIFIED
} GtkSourceFileSaverError;
struct _GtkSourceFileSaver
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]