[tepl] Dumb FileSaver: remove all the implementation, UTF-8 only!
- From: Sébastien Wilmet <swilmet src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [tepl] Dumb FileSaver: remove all the implementation, UTF-8 only!
- Date: Tue, 12 May 2020 13:50:42 +0000 (UTC)
commit 58b9a5da064d41f877fdee443bf0af36ee843b42
Author: Sébastien Wilmet <swilmet gnome org>
Date: Mon May 11 20:06:41 2020 +0200
Dumb FileSaver: remove all the implementation, UTF-8 only!
The FileSaver will be made smarter again later, it is planned to use the
libicu. First make it dumb, then it will be easier to re-add what is
missing differently.
Keep most of the TeplFileSaver API and docs, but remove all the
implementation.
docs/reference/tepl-sections.txt | 2 -
po/POTFILES.in | 1 -
tepl/meson.build | 2 -
tepl/tepl-buffer-input-stream.c | 498 --------------------
tepl/tepl-buffer-input-stream.h | 54 ---
tepl/tepl-file-saver.c | 877 ++++-------------------------------
tepl/tepl-file-saver.h | 14 +-
testsuite/meson.build | 4 +-
testsuite/test-buffer-input-stream.c | 135 ------
testsuite/test-file-saver.c | 801 --------------------------------
10 files changed, 92 insertions(+), 2296 deletions(-)
---
diff --git a/docs/reference/tepl-sections.txt b/docs/reference/tepl-sections.txt
index 104bcbb..8a6860b 100644
--- a/docs/reference/tepl-sections.txt
+++ b/docs/reference/tepl-sections.txt
@@ -190,8 +190,6 @@ tepl_file_saver_new_with_target
tepl_file_saver_get_buffer
tepl_file_saver_get_file
tepl_file_saver_get_location
-tepl_file_saver_set_encoding
-tepl_file_saver_get_encoding
tepl_file_saver_set_newline_type
tepl_file_saver_get_newline_type
tepl_file_saver_set_compression_type
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 5f13874..f339668 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -3,7 +3,6 @@ tepl/tepl-abstract-factory.c
tepl/tepl-application.c
tepl/tepl-application-window.c
tepl/tepl-buffer.c
-tepl/tepl-buffer-input-stream.c
tepl/tepl-close-confirm-dialog-single.c
tepl/tepl-encoding.c
tepl/tepl-encoding-converter.c
diff --git a/tepl/meson.build b/tepl/meson.build
index 998a588..f3ef0a4 100644
--- a/tepl/meson.build
+++ b/tepl/meson.build
@@ -61,7 +61,6 @@ tepl_public_c_files = [
]
TEPL_PRIVATE_HEADERS = [
- 'tepl-buffer-input-stream.h',
'tepl-close-confirm-dialog-single.h',
'tepl-encoding-converter.h',
'tepl-encoding-private.h',
@@ -79,7 +78,6 @@ TEPL_PRIVATE_HEADERS = [
]
tepl_private_c_files = [
- 'tepl-buffer-input-stream.c',
'tepl-close-confirm-dialog-single.c',
'tepl-encoding-converter.c',
'tepl-file-content.c',
diff --git a/tepl/tepl-file-saver.c b/tepl/tepl-file-saver.c
index e3a9fab..68c676a 100644
--- a/tepl/tepl-file-saver.c
+++ b/tepl/tepl-file-saver.c
@@ -1,20 +1,17 @@
/* SPDX-FileCopyrightText: 2005-2007 - Paolo Borelli and Paolo Maggi
* SPDX-FileCopyrightText: 2007 - Steve Frécinaux
* SPDX-FileCopyrightText: 2008 - Jesse van den Kieboom
- * SPDX-FileCopyrightText: 2014, 2016, 2017 - Sébastien Wilmet
+ * SPDX-FileCopyrightText: 2014-2020 - Sébastien Wilmet
* SPDX-License-Identifier: LGPL-3.0-or-later
*/
-#include "config.h"
#include "tepl-file-saver.h"
-#include <glib/gi18n-lib.h>
-#include "tepl-buffer-input-stream.h"
#include "tepl-enum-types.h"
/**
* SECTION:file-saver
- * @Short_description: Save a TeplBuffer into a file
* @Title: TeplFileSaver
+ * @Short_description: Save a #TeplBuffer into a file
* @See_also: #TeplFile, #TeplFileLoader
*
* A #TeplFileSaver object permits to save a #TeplBuffer into a #GFile.
@@ -22,24 +19,8 @@
* A file saver should be used only for one save operation, including errors
* handling. If an error occurs, you can reconfigure the saver and relaunch the
* operation with tepl_file_saver_save_async().
- *
- * #TeplFileSaver is a fork of #GtkSourceFileSaver, the code has been a little
- * improved (but no major changes). See the description of #TeplFile for more
- * background on why a fork was needed.
- */
-
-/* The code has been written initially in gedit (GeditDocumentSaver).
- * It uses a TeplBufferInputStream as input, create converter(s) if needed
- * for the encoding and the compression, and write the contents to a
- * GOutputStream (the file).
*/
-#if 0
-#define DEBUG(x) (x)
-#else
-#define DEBUG(x)
-#endif
-
#define WRITE_CHUNK_SIZE 8192
enum
@@ -48,10 +29,10 @@ enum
PROP_BUFFER,
PROP_FILE,
PROP_LOCATION,
- PROP_ENCODING,
PROP_NEWLINE_TYPE,
PROP_COMPRESSION_TYPE,
- PROP_FLAGS
+ PROP_FLAGS,
+ N_PROPERTIES
};
struct _TeplFileSaverPrivate
@@ -70,7 +51,6 @@ struct _TeplFileSaverPrivate
GFile *location;
- TeplEncoding *encoding;
TeplNewlineType newline_type;
TeplCompressionType compression_type;
TeplFileSaverFlags flags;
@@ -81,41 +61,12 @@ struct _TeplFileSaverPrivate
typedef struct _TaskData TaskData;
struct _TaskData
{
- GFileOutputStream *file_output_stream;
-
- /* The output_stream contains the file_output_stream, plus the required
- * converter(s) for the encoding and the compression type.
- * input_stream and output_stream cannot be spliced directly, because:
- * (1) We need to call the progress callback.
- * (2) Sync methods must be used for the input stream, and async
- * methods for the output stream.
- */
- TeplBufferInputStream *input_stream;
- GOutputStream *output_stream;
-
- goffset total_size;
- GFileProgressCallback progress_cb;
- gpointer progress_cb_data;
- GDestroyNotify progress_cb_notify;
-
- /* This field is used when cancelling the output stream: an error occurs
- * and is stored in this field, the output stream is cancelled
- * asynchronously, and then the error is reported to the task.
- */
- GError *error;
-
- gssize chunk_bytes_read;
- gssize chunk_bytes_written;
- gchar chunk_buffer[WRITE_CHUNK_SIZE];
-
- guint tried_mount : 1;
+ gint something;
};
-G_DEFINE_TYPE_WITH_PRIVATE (TeplFileSaver, tepl_file_saver, G_TYPE_OBJECT)
+static GParamSpec *properties[N_PROPERTIES];
-static void read_file_chunk (GTask *task);
-static void write_file_chunk (GTask *task);
-static void recover_not_mounted (GTask *task);
+G_DEFINE_TYPE_WITH_PRIVATE (TeplFileSaver, tepl_file_saver, G_TYPE_OBJECT)
static TaskData *
task_data_new (void)
@@ -124,26 +75,9 @@ task_data_new (void)
}
static void
-task_data_free (gpointer data)
+task_data_free (TaskData *data)
{
- TaskData *task_data = data;
-
- if (task_data == NULL)
- {
- return;
- }
-
- g_clear_object (&task_data->file_output_stream);
- g_clear_object (&task_data->input_stream);
- g_clear_object (&task_data->output_stream);
- g_clear_error (&task_data->error);
-
- if (task_data->progress_cb_notify != NULL)
- {
- task_data->progress_cb_notify (task_data->progress_cb_data);
- }
-
- g_free (task_data);
+ g_free (data);
}
static void
@@ -158,16 +92,12 @@ tepl_file_saver_set_property (GObject *object,
{
case PROP_BUFFER:
g_assert (saver->priv->source_buffer == NULL);
- saver->priv->source_buffer = g_value_get_object (value);
- g_object_add_weak_pointer (G_OBJECT (saver->priv->source_buffer),
- (gpointer *)&saver->priv->source_buffer);
+ g_set_weak_pointer (&saver->priv->source_buffer, g_value_get_object (value));
break;
case PROP_FILE:
g_assert (saver->priv->file == NULL);
- saver->priv->file = g_value_get_object (value);
- g_object_add_weak_pointer (G_OBJECT (saver->priv->file),
- (gpointer *)&saver->priv->file);
+ g_set_weak_pointer (&saver->priv->file, g_value_get_object (value));
break;
case PROP_LOCATION:
@@ -175,10 +105,6 @@ tepl_file_saver_set_property (GObject *object,
saver->priv->location = g_value_dup_object (value);
break;
- case PROP_ENCODING:
- tepl_file_saver_set_encoding (saver, g_value_get_boxed (value));
- break;
-
case PROP_NEWLINE_TYPE:
tepl_file_saver_set_newline_type (saver, g_value_get_enum (value));
break;
@@ -219,10 +145,6 @@ tepl_file_saver_get_property (GObject *object,
g_value_set_object (value, saver->priv->location);
break;
- case PROP_ENCODING:
- g_value_set_boxed (value, saver->priv->encoding);
- break;
-
case PROP_NEWLINE_TYPE:
g_value_set_enum (value, saver->priv->newline_type);
break;
@@ -241,43 +163,6 @@ tepl_file_saver_get_property (GObject *object,
}
}
-static void
-tepl_file_saver_dispose (GObject *object)
-{
- TeplFileSaver *saver = TEPL_FILE_SAVER (object);
-
- if (saver->priv->source_buffer != NULL)
- {
- g_object_remove_weak_pointer (G_OBJECT (saver->priv->source_buffer),
- (gpointer *)&saver->priv->source_buffer);
-
- saver->priv->source_buffer = NULL;
- }
-
- if (saver->priv->file != NULL)
- {
- g_object_remove_weak_pointer (G_OBJECT (saver->priv->file),
- (gpointer *)&saver->priv->file);
-
- saver->priv->file = NULL;
- }
-
- g_clear_object (&saver->priv->location);
- g_clear_object (&saver->priv->task);
-
- G_OBJECT_CLASS (tepl_file_saver_parent_class)->dispose (object);
-}
-
-static void
-tepl_file_saver_finalize (GObject *object)
-{
- TeplFileSaver *saver = TEPL_FILE_SAVER (object);
-
- tepl_encoding_free (saver->priv->encoding);
-
- G_OBJECT_CLASS (tepl_file_saver_parent_class)->finalize (object);
-}
-
static void
tepl_file_saver_constructed (GObject *object)
{
@@ -285,13 +170,9 @@ tepl_file_saver_constructed (GObject *object)
if (saver->priv->file != NULL)
{
- const TeplEncoding *encoding;
TeplNewlineType newline_type;
TeplCompressionType compression_type;
- encoding = tepl_file_get_encoding (saver->priv->file);
- tepl_file_saver_set_encoding (saver, encoding);
-
newline_type = tepl_file_get_newline_type (saver->priv->file);
tepl_file_saver_set_newline_type (saver, newline_type);
@@ -317,16 +198,28 @@ tepl_file_saver_constructed (GObject *object)
G_OBJECT_CLASS (tepl_file_saver_parent_class)->constructed (object);
}
+static void
+tepl_file_saver_dispose (GObject *object)
+{
+ TeplFileSaver *saver = TEPL_FILE_SAVER (object);
+
+ g_clear_weak_pointer (&saver->priv->source_buffer);
+ g_clear_weak_pointer (&saver->priv->file);
+ g_clear_object (&saver->priv->location);
+ g_clear_object (&saver->priv->task);
+
+ G_OBJECT_CLASS (tepl_file_saver_parent_class)->dispose (object);
+}
+
static void
tepl_file_saver_class_init (TeplFileSaverClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
- object_class->dispose = tepl_file_saver_dispose;
- object_class->finalize = tepl_file_saver_finalize;
object_class->set_property = tepl_file_saver_set_property;
object_class->get_property = tepl_file_saver_get_property;
object_class->constructed = tepl_file_saver_constructed;
+ object_class->dispose = tepl_file_saver_dispose;
/**
* TeplFileSaver:buffer:
@@ -336,33 +229,31 @@ tepl_file_saver_class_init (TeplFileSaverClass *klass)
*
* Since: 1.0
*/
- g_object_class_install_property (object_class,
- PROP_BUFFER,
- g_param_spec_object ("buffer",
- "TeplBuffer",
- "",
- GTK_SOURCE_TYPE_BUFFER,
- G_PARAM_READWRITE |
- G_PARAM_CONSTRUCT_ONLY |
- G_PARAM_STATIC_STRINGS));
+ properties[PROP_BUFFER] =
+ g_param_spec_object ("buffer",
+ "buffer",
+ "",
+ GTK_SOURCE_TYPE_BUFFER,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT_ONLY |
+ G_PARAM_STATIC_STRINGS);
/**
* TeplFileSaver:file:
*
- * The #TeplFile. The #TeplFileSaver object has a weak
- * reference to the file.
+ * The #TeplFile. The #TeplFileSaver object has a weak reference to the
+ * file.
*
* Since: 1.0
*/
- g_object_class_install_property (object_class,
- PROP_FILE,
- g_param_spec_object ("file",
- "TeplFile",
- "",
- TEPL_TYPE_FILE,
- G_PARAM_READWRITE |
- G_PARAM_CONSTRUCT_ONLY |
- G_PARAM_STATIC_STRINGS));
+ properties[PROP_FILE] =
+ g_param_spec_object ("file",
+ "file",
+ "",
+ TEPL_TYPE_FILE,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT_ONLY |
+ G_PARAM_STATIC_STRINGS);
/**
* TeplFileSaver:location:
@@ -372,32 +263,14 @@ tepl_file_saver_class_init (TeplFileSaverClass *klass)
*
* Since: 1.0
*/
- g_object_class_install_property (object_class,
- PROP_LOCATION,
- g_param_spec_object ("location",
- "Location",
- "",
- G_TYPE_FILE,
- G_PARAM_READWRITE |
- G_PARAM_CONSTRUCT_ONLY |
- G_PARAM_STATIC_STRINGS));
-
- /**
- * TeplFileSaver:encoding:
- *
- * The file's encoding.
- *
- * Since: 1.0
- */
- g_object_class_install_property (object_class,
- PROP_ENCODING,
- g_param_spec_boxed ("encoding",
- "Encoding",
- "",
- TEPL_TYPE_ENCODING,
- G_PARAM_READWRITE |
- G_PARAM_CONSTRUCT |
- G_PARAM_STATIC_STRINGS));
+ properties[PROP_LOCATION] =
+ g_param_spec_object ("location",
+ "location",
+ "",
+ G_TYPE_FILE,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT_ONLY |
+ G_PARAM_STATIC_STRINGS);
/**
* TeplFileSaver:newline-type:
@@ -406,16 +279,15 @@ tepl_file_saver_class_init (TeplFileSaverClass *klass)
*
* Since: 1.0
*/
- g_object_class_install_property (object_class,
- PROP_NEWLINE_TYPE,
- g_param_spec_enum ("newline-type",
- "Newline type",
- "",
- GTK_SOURCE_TYPE_NEWLINE_TYPE,
- TEPL_NEWLINE_TYPE_LF,
- G_PARAM_READWRITE |
- G_PARAM_CONSTRUCT |
- G_PARAM_STATIC_STRINGS));
+ properties[PROP_NEWLINE_TYPE] =
+ g_param_spec_enum ("newline-type",
+ "newline-type",
+ "",
+ GTK_SOURCE_TYPE_NEWLINE_TYPE,
+ TEPL_NEWLINE_TYPE_LF,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT |
+ G_PARAM_STATIC_STRINGS);
/**
* TeplFileSaver:compression-type:
@@ -424,16 +296,15 @@ tepl_file_saver_class_init (TeplFileSaverClass *klass)
*
* Since: 1.0
*/
- g_object_class_install_property (object_class,
- PROP_COMPRESSION_TYPE,
- g_param_spec_enum ("compression-type",
- "Compression type",
- "",
- GTK_SOURCE_TYPE_COMPRESSION_TYPE,
- TEPL_COMPRESSION_TYPE_NONE,
- G_PARAM_READWRITE |
- G_PARAM_CONSTRUCT |
- G_PARAM_STATIC_STRINGS));
+ properties[PROP_COMPRESSION_TYPE] =
+ g_param_spec_enum ("compression-type",
+ "compression-type",
+ "",
+ GTK_SOURCE_TYPE_COMPRESSION_TYPE,
+ TEPL_COMPRESSION_TYPE_NONE,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT |
+ G_PARAM_STATIC_STRINGS);
/**
* TeplFileSaver:flags:
@@ -442,24 +313,17 @@ tepl_file_saver_class_init (TeplFileSaverClass *klass)
*
* Since: 1.0
*/
- g_object_class_install_property (object_class,
- PROP_FLAGS,
- g_param_spec_flags ("flags",
- "Flags",
- "",
- TEPL_TYPE_FILE_SAVER_FLAGS,
- TEPL_FILE_SAVER_FLAGS_NONE,
- G_PARAM_READWRITE |
- G_PARAM_CONSTRUCT |
- G_PARAM_STATIC_STRINGS));
-
- /* Due to potential deadlocks when registering types, we need to ensure
- * the dependent private class TeplBufferInputStream has been registered
- * up front.
- *
- * See https://bugzilla.gnome.org/show_bug.cgi?id=780216
- */
- g_type_ensure (TEPL_TYPE_BUFFER_INPUT_STREAM);
+ properties[PROP_FLAGS] =
+ g_param_spec_flags ("flags",
+ "flags",
+ "",
+ TEPL_TYPE_FILE_SAVER_FLAGS,
+ TEPL_FILE_SAVER_FLAGS_NONE,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT |
+ G_PARAM_STATIC_STRINGS);
+
+ g_object_class_install_properties (object_class, N_PROPERTIES, properties);
}
static void
@@ -468,475 +332,6 @@ tepl_file_saver_init (TeplFileSaver *saver)
saver->priv = tepl_file_saver_get_instance_private (saver);
}
-/* BEGIN NOTE:
- *
- * This fixes an issue in GOutputStream that applies the atomic replace save
- * strategy. The stream moves the written file to the original file when the
- * stream is closed. However, there is no way currently to tell the stream that
- * the save should be aborted (there could be a conversion error). The patch
- * explicitly closes the output stream in all these cases with a GCancellable in
- * the cancelled state, causing the output stream to close, but not move the
- * file. This makes use of an implementation detail in the local file stream
- * and should be properly fixed by adding the appropriate API in GIO. Until
- * then, at least we prevent data corruption for now.
- *
- * Relevant bug reports:
- *
- * Bug 615110 - write file ignore encoding errors (gedit)
- * https://bugzilla.gnome.org/show_bug.cgi?id=615110
- *
- * Bug 602412 - g_file_replace does not restore original file when there is
- * errors while writing (glib/gio)
- * https://bugzilla.gnome.org/show_bug.cgi?id=602412
- */
-static void
-cancel_output_stream_ready_cb (GObject *source_object,
- GAsyncResult *result,
- gpointer user_data)
-{
- GOutputStream *output_stream = G_OUTPUT_STREAM (source_object);
- GTask *task = G_TASK (user_data);
- TaskData *task_data;
-
- task_data = g_task_get_task_data (task);
-
- g_output_stream_close_finish (output_stream, result, NULL);
-
- if (task_data->error != NULL)
- {
- GError *error = task_data->error;
- task_data->error = NULL;
- g_task_return_error (task, error);
- }
- else
- {
- g_task_return_boolean (task, FALSE);
- }
-}
-
-static void
-cancel_output_stream (GTask *task)
-{
- TaskData *task_data;
- GCancellable *cancellable;
-
- DEBUG ({
- g_print ("Cancel output stream\n");
- });
-
- task_data = g_task_get_task_data (task);
-
- cancellable = g_cancellable_new ();
- g_cancellable_cancel (cancellable);
-
- g_output_stream_close_async (task_data->output_stream,
- g_task_get_priority (task),
- cancellable,
- cancel_output_stream_ready_cb,
- task);
-
- g_object_unref (cancellable);
-}
-
-/*
- * END NOTE
- */
-
-static void
-close_output_stream_cb (GObject *source_object,
- GAsyncResult *result,
- gpointer user_data)
-{
- GOutputStream *output_stream = G_OUTPUT_STREAM (source_object);
- GTask *task = G_TASK (user_data);
- GError *error = NULL;
-
- DEBUG ({
- g_print ("%s\n", G_STRFUNC);
- });
-
- g_output_stream_close_finish (output_stream, result, &error);
-
- if (error != NULL)
- {
- DEBUG ({
- g_print ("Closing stream error: %s\n", error->message);
- });
-
- g_task_return_error (task, error);
- return;
- }
-
- /* Finished! */
- g_task_return_boolean (task, TRUE);
-}
-
-static void
-write_complete (GTask *task)
-{
- TaskData *task_data;
- GError *error = NULL;
-
- DEBUG ({
- g_print ("Close input stream\n");
- });
-
- task_data = g_task_get_task_data (task);
-
- g_input_stream_close (G_INPUT_STREAM (task_data->input_stream),
- g_task_get_cancellable (task),
- &error);
-
- if (error != NULL)
- {
- DEBUG ({
- g_print ("Closing input stream error: %s\n", error->message);
- });
-
- g_clear_error (&task_data->error);
- task_data->error = error;
- cancel_output_stream (task);
- return;
- }
-
- DEBUG ({
- g_print ("Close output stream\n");
- });
-
- g_output_stream_close_async (task_data->output_stream,
- g_task_get_priority (task),
- g_task_get_cancellable (task),
- close_output_stream_cb,
- task);
-}
-
-static void
-write_file_chunk_cb (GObject *source_object,
- GAsyncResult *result,
- gpointer user_data)
-{
- GOutputStream *output_stream = G_OUTPUT_STREAM (source_object);
- GTask *task = G_TASK (user_data);
- TaskData *task_data;
- gssize bytes_written;
- GError *error = NULL;
-
- DEBUG ({
- g_print ("%s\n", G_STRFUNC);
- });
-
- task_data = g_task_get_task_data (task);
-
- bytes_written = g_output_stream_write_finish (output_stream, result, &error);
-
- DEBUG ({
- g_print ("Written: %" G_GSSIZE_FORMAT "\n", bytes_written);
- });
-
- if (error != NULL)
- {
- DEBUG ({
- g_print ("Write error: %s\n", error->message);
- });
-
- g_clear_error (&task_data->error);
- task_data->error = error;
- cancel_output_stream (task);
- return;
- }
-
- task_data->chunk_bytes_written += bytes_written;
-
- /* Write again */
- if (task_data->chunk_bytes_written < task_data->chunk_bytes_read)
- {
- write_file_chunk (task);
- return;
- }
-
- if (task_data->progress_cb != NULL)
- {
- gsize total_chars_written;
-
- total_chars_written = _tepl_buffer_input_stream_tell (task_data->input_stream);
-
- task_data->progress_cb (total_chars_written,
- task_data->total_size,
- task_data->progress_cb_data);
- }
-
- read_file_chunk (task);
-}
-
-static void
-write_file_chunk (GTask *task)
-{
- TaskData *task_data;
-
- DEBUG ({
- g_print ("%s\n", G_STRFUNC);
- });
-
- task_data = g_task_get_task_data (task);
-
- g_output_stream_write_async (task_data->output_stream,
- task_data->chunk_buffer + task_data->chunk_bytes_written,
- task_data->chunk_bytes_read - task_data->chunk_bytes_written,
- g_task_get_priority (task),
- g_task_get_cancellable (task),
- write_file_chunk_cb,
- task);
-}
-
-static void
-read_file_chunk (GTask *task)
-{
- TaskData *task_data;
- GError *error = NULL;
-
- DEBUG ({
- g_print ("%s\n", G_STRFUNC);
- });
-
- task_data = g_task_get_task_data (task);
-
- task_data->chunk_bytes_written = 0;
-
- /* We use sync methods on doc stream since it is in memory. Using async
- * would be racy and we could end up with invalid iters.
- */
- task_data->chunk_bytes_read = g_input_stream_read (G_INPUT_STREAM (task_data->input_stream),
- task_data->chunk_buffer,
- WRITE_CHUNK_SIZE,
- g_task_get_cancellable (task),
- &error);
-
- if (error != NULL)
- {
- g_clear_error (&task_data->error);
- task_data->error = error;
- cancel_output_stream (task);
- return;
- }
-
- /* Check if we finished reading and writing. */
- if (task_data->chunk_bytes_read == 0)
- {
- write_complete (task);
- return;
- }
-
- write_file_chunk (task);
-}
-
-static void
-replace_file_cb (GObject *source_object,
- GAsyncResult *result,
- gpointer user_data)
-{
- GFile *location = G_FILE (source_object);
- GTask *task = G_TASK (user_data);
- TeplFileSaver *saver;
- TaskData *task_data;
- GOutputStream *output_stream;
- GError *error = NULL;
-
- DEBUG ({
- g_print ("%s\n", G_STRFUNC);
- });
-
- saver = g_task_get_source_object (task);
- task_data = g_task_get_task_data (task);
-
- g_clear_object (&task_data->file_output_stream);
- task_data->file_output_stream = g_file_replace_finish (location, result, &error);
-
- if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_NOT_MOUNTED) &&
- !task_data->tried_mount)
- {
- recover_not_mounted (task);
- g_error_free (error);
- return;
- }
- else if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_WRONG_ETAG))
- {
- g_task_return_new_error (task,
- TEPL_FILE_SAVER_ERROR,
- TEPL_FILE_SAVER_ERROR_EXTERNALLY_MODIFIED,
- _("The file is externally modified."));
- g_error_free (error);
- return;
- }
- else if (error != NULL)
- {
- DEBUG ({
- g_print ("Opening file failed: %s\n", error->message);
- });
-
- g_task_return_error (task, error);
- return;
- }
-
- if (saver->priv->compression_type == TEPL_COMPRESSION_TYPE_GZIP)
- {
- GZlibCompressor *compressor;
-
- DEBUG ({
- g_print ("Use gzip compressor\n");
- });
-
- compressor = g_zlib_compressor_new (G_ZLIB_COMPRESSOR_FORMAT_GZIP, -1);
-
- output_stream = g_converter_output_stream_new (G_OUTPUT_STREAM
(task_data->file_output_stream),
- G_CONVERTER (compressor));
-
- g_object_unref (compressor);
- }
- else
- {
- output_stream = G_OUTPUT_STREAM (task_data->file_output_stream);
- g_object_ref (output_stream);
- }
-
- g_return_if_fail (saver->priv->encoding != NULL);
-
- DEBUG ({
- g_print ("Encoding charset: %s\n",
- tepl_encoding_get_charset (saver->priv->encoding));
- });
-
- if (!tepl_encoding_is_utf8 (saver->priv->encoding))
- {
- GCharsetConverter *converter;
-
- converter = g_charset_converter_new (tepl_encoding_get_charset (saver->priv->encoding),
- "UTF-8",
- &error);
-
- if (error != NULL)
- {
- g_task_return_error (task, error);
- g_object_unref (output_stream);
- return;
- }
-
- g_clear_object (&task_data->output_stream);
- task_data->output_stream = g_converter_output_stream_new (output_stream,
- G_CONVERTER (converter));
-
- g_object_unref (converter);
- g_object_unref (output_stream);
- }
- else
- {
- g_clear_object (&task_data->output_stream);
- task_data->output_stream = G_OUTPUT_STREAM (output_stream);
- }
-
- task_data->total_size = _tepl_buffer_input_stream_get_total_size (task_data->input_stream);
-
- DEBUG ({
- g_print ("Total number of characters: %" G_GINT64_FORMAT "\n", task_data->total_size);
- });
-
- read_file_chunk (task);
-}
-
-static void
-begin_write (GTask *task)
-{
- TeplFileSaver *saver;
- gboolean create_backup;
- const gchar *etag;
-
- saver = g_task_get_source_object (task);
-
- create_backup = (saver->priv->flags & TEPL_FILE_SAVER_FLAGS_CREATE_BACKUP) != 0;
-
- DEBUG ({
- g_print ("Start replacing file contents\n");
- g_print ("Make backup: %s\n", create_backup ? "yes" : "no");
- });
-
- if (saver->priv->flags & TEPL_FILE_SAVER_FLAGS_IGNORE_MODIFICATION_TIME)
- {
- etag = NULL;
- }
- else
- {
- etag = _tepl_file_get_etag (saver->priv->file);
- }
-
- g_file_replace_async (saver->priv->location,
- etag,
- create_backup,
- G_FILE_CREATE_NONE,
- g_task_get_priority (task),
- g_task_get_cancellable (task),
- replace_file_cb,
- task);
-}
-
-static void
-mount_cb (GObject *source_object,
- GAsyncResult *result,
- gpointer user_data)
-{
- GFile *location = G_FILE (source_object);
- GTask *task = G_TASK (user_data);
- TeplFileSaver *saver;
- GError *error = NULL;
-
- DEBUG ({
- g_print ("%s\n", G_STRFUNC);
- });
-
- saver = g_task_get_source_object (task);
-
- g_file_mount_enclosing_volume_finish (location, result, &error);
-
- if (error != NULL)
- {
- g_task_return_error (task, error);
- return;
- }
-
- if (saver->priv->file != NULL)
- {
- _tepl_file_set_mounted (saver->priv->file);
- }
-
- begin_write (task);
-}
-
-static void
-recover_not_mounted (GTask *task)
-{
- TeplFileSaver *saver;
- TaskData *task_data;
- GMountOperation *mount_operation;
-
- saver = g_task_get_source_object (task);
- task_data = g_task_get_task_data (task);
-
- mount_operation = _tepl_file_create_mount_operation (saver->priv->file);
-
- DEBUG ({
- g_print ("%s\n", G_STRFUNC);
- });
-
- task_data->tried_mount = TRUE;
-
- g_file_mount_enclosing_volume (saver->priv->location,
- G_MOUNT_MOUNT_NONE,
- mount_operation,
- g_task_get_cancellable (task),
- mount_cb,
- task);
-
- g_object_unref (mount_operation);
-}
-
GQuark
tepl_file_saver_error_quark (void)
{
@@ -944,7 +339,7 @@ tepl_file_saver_error_quark (void)
if (G_UNLIKELY (quark == 0))
{
- quark = g_quark_from_static_string ("gtk-source-file-saver-error");
+ quark = g_quark_from_static_string ("TeplFileSaverError");
}
return quark;
@@ -1059,62 +454,6 @@ tepl_file_saver_get_location (TeplFileSaver *saver)
return saver->priv->location;
}
-/**
- * tepl_file_saver_set_encoding:
- * @saver: a #TeplFileSaver.
- * @encoding: (allow-none): the new encoding, or %NULL for UTF-8.
- *
- * Sets the encoding. If @encoding is %NULL, the UTF-8 encoding will be set.
- * By default the encoding is taken from the #TeplFile.
- *
- * Since: 1.0
- */
-void
-tepl_file_saver_set_encoding (TeplFileSaver *saver,
- const TeplEncoding *encoding)
-{
- TeplEncoding *my_encoding;
-
- g_return_if_fail (TEPL_IS_FILE_SAVER (saver));
- g_return_if_fail (saver->priv->task == NULL);
-
- if (encoding == NULL)
- {
- my_encoding = tepl_encoding_new_utf8 ();
- }
- else
- {
- my_encoding = tepl_encoding_copy (encoding);
- }
-
- if (!tepl_encoding_equals (saver->priv->encoding, my_encoding))
- {
- tepl_encoding_free (saver->priv->encoding);
- saver->priv->encoding = my_encoding;
-
- g_object_notify (G_OBJECT (saver), "encoding");
- }
- else
- {
- tepl_encoding_free (my_encoding);
- }
-}
-
-/**
- * tepl_file_saver_get_encoding:
- * @saver: a #TeplFileSaver.
- *
- * Returns: the encoding.
- * Since: 1.0
- */
-const TeplEncoding *
-tepl_file_saver_get_encoding (TeplFileSaver *saver)
-{
- g_return_val_if_fail (TEPL_IS_FILE_SAVER (saver), NULL);
-
- return saver->priv->encoding;
-}
-
/**
* tepl_file_saver_set_newline_type:
* @saver: a #TeplFileSaver.
@@ -1135,7 +474,7 @@ tepl_file_saver_set_newline_type (TeplFileSaver *saver,
if (saver->priv->newline_type != newline_type)
{
saver->priv->newline_type = newline_type;
- g_object_notify (G_OBJECT (saver), "newline-type");
+ g_object_notify_by_pspec (G_OBJECT (saver), properties[PROP_NEWLINE_TYPE]);
}
}
@@ -1174,7 +513,7 @@ tepl_file_saver_set_compression_type (TeplFileSaver *saver,
if (saver->priv->compression_type != compression_type)
{
saver->priv->compression_type = compression_type;
- g_object_notify (G_OBJECT (saver), "compression-type");
+ g_object_notify_by_pspec (G_OBJECT (saver), properties[PROP_COMPRESSION_TYPE]);
}
}
@@ -1210,7 +549,7 @@ tepl_file_saver_set_flags (TeplFileSaver *saver,
if (saver->priv->flags != flags)
{
saver->priv->flags = flags;
- g_object_notify (G_OBJECT (saver), "flags");
+ g_object_notify_by_pspec (G_OBJECT (saver), properties[PROP_FLAGS]);
}
}
@@ -1252,7 +591,7 @@ tepl_file_saver_get_flags (TeplFileSaver *saver)
*/
/* The GDestroyNotify is needed, currently the following bug is not fixed:
- * https://bugzilla.gnome.org/show_bug.cgi?id=616044
+ * https://gitlab.gnome.org/GNOME/gobject-introspection/issues/25
*/
void
tepl_file_saver_save_async (TeplFileSaver *saver,
@@ -1265,8 +604,6 @@ tepl_file_saver_save_async (TeplFileSaver *saver,
gpointer user_data)
{
TaskData *task_data;
- gboolean check_invalid_chars;
- gboolean implicit_trailing_newline;
g_return_if_fail (TEPL_IS_FILE_SAVER (saver));
g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
@@ -1276,11 +613,7 @@ tepl_file_saver_save_async (TeplFileSaver *saver,
g_task_set_priority (saver->priv->task, io_priority);
task_data = task_data_new ();
- g_task_set_task_data (saver->priv->task, task_data, task_data_free);
-
- task_data->progress_cb = progress_callback;
- task_data->progress_cb_data = progress_callback_data;
- task_data->progress_cb_notify = progress_callback_notify;
+ g_task_set_task_data (saver->priv->task, task_data, (GDestroyNotify)task_data_free);
if (saver->priv->source_buffer == NULL ||
saver->priv->file == NULL ||
@@ -1290,32 +623,7 @@ tepl_file_saver_save_async (TeplFileSaver *saver,
return;
}
- check_invalid_chars = (saver->priv->flags & TEPL_FILE_SAVER_FLAGS_IGNORE_INVALID_CHARS) == 0;
-
- if (check_invalid_chars && _tepl_buffer_has_invalid_chars (TEPL_BUFFER (saver->priv->source_buffer)))
- {
- g_task_return_new_error (saver->priv->task,
- TEPL_FILE_SAVER_ERROR,
- TEPL_FILE_SAVER_ERROR_INVALID_CHARS,
- _("The buffer contains invalid characters."));
- return;
- }
-
- DEBUG ({
- g_print ("Start saving\n");
- });
-
- implicit_trailing_newline = gtk_source_buffer_get_implicit_trailing_newline
(saver->priv->source_buffer);
-
- /* The BufferInputStream has a strong reference to the buffer.
- * We create the BufferInputStream here so we are sure that the
- * buffer will not be destroyed during the file saving.
- */
- task_data->input_stream = _tepl_buffer_input_stream_new (GTK_TEXT_BUFFER (saver->priv->source_buffer),
- saver->priv->newline_type,
- implicit_trailing_newline);
-
- begin_write (saver->priv->task);
+ g_task_return_boolean (saver->priv->task, TRUE);
}
/**
@@ -1351,15 +659,9 @@ tepl_file_saver_save_finish (TeplFileSaver *saver,
if (ok && saver->priv->file != NULL)
{
- TaskData *task_data;
- gchar *new_etag;
-
tepl_file_set_location (saver->priv->file,
saver->priv->location);
- _tepl_file_set_encoding (saver->priv->file,
- saver->priv->encoding);
-
_tepl_file_set_newline_type (saver->priv->file,
saver->priv->newline_type);
@@ -1369,11 +671,6 @@ tepl_file_saver_save_finish (TeplFileSaver *saver,
_tepl_file_set_externally_modified (saver->priv->file, FALSE);
_tepl_file_set_deleted (saver->priv->file, FALSE);
_tepl_file_set_readonly (saver->priv->file, FALSE);
-
- task_data = g_task_get_task_data (G_TASK (result));
- new_etag = g_file_output_stream_get_etag (task_data->file_output_stream);
- _tepl_file_set_etag (saver->priv->file, new_etag);
- g_free (new_etag);
}
if (ok && saver->priv->source_buffer != NULL)
diff --git a/tepl/tepl-file-saver.h b/tepl/tepl-file-saver.h
index b4210c0..19a9e69 100644
--- a/tepl/tepl-file-saver.h
+++ b/tepl/tepl-file-saver.h
@@ -1,7 +1,7 @@
/* SPDX-FileCopyrightText: 2005, 2007 - Paolo Maggi
- * Copyrhing 2007 - Steve Frécinaux
+ * SPDX-FileCopyrightText: 2007 - Steve Frécinaux
* SPDX-FileCopyrightText: 2008 - Jesse van den Kieboom
- * SPDX-FileCopyrightText: 2014, 2016, 2017 - Sébastien Wilmet
+ * SPDX-FileCopyrightText: 2014-2020 - Sébastien Wilmet
* SPDX-License-Identifier: LGPL-3.0-or-later
*/
@@ -14,7 +14,6 @@
#include <gtksourceview/gtksource.h>
#include <tepl/tepl-buffer.h>
-#include <tepl/tepl-encoding.h>
#include <tepl/tepl-file.h>
G_BEGIN_DECLS
@@ -40,6 +39,7 @@ typedef struct _TeplFileSaverPrivate TeplFileSaverPrivate;
* modified.
*
* An error code used with the %TEPL_FILE_SAVER_ERROR domain.
+ *
* Since: 1.0
*/
typedef enum
@@ -56,6 +56,7 @@ typedef enum
* @TEPL_FILE_SAVER_FLAGS_CREATE_BACKUP: Create a backup before saving the file.
*
* Flags to define the behavior of a #TeplFileSaver.
+ *
* Since: 1.0
*/
typedef enum
@@ -104,13 +105,6 @@ TeplFile * tepl_file_saver_get_file (TeplFileSaver *saver);
_TEPL_EXTERN
GFile * tepl_file_saver_get_location (TeplFileSaver *saver);
-_TEPL_EXTERN
-void tepl_file_saver_set_encoding (TeplFileSaver *saver,
- const TeplEncoding *encoding);
-
-_TEPL_EXTERN
-const TeplEncoding * tepl_file_saver_get_encoding (TeplFileSaver *saver);
-
_TEPL_EXTERN
void tepl_file_saver_set_newline_type (TeplFileSaver *saver,
TeplNewlineType newline_type);
diff --git a/testsuite/meson.build b/testsuite/meson.build
index f61f744..ae0a5c6 100644
--- a/testsuite/meson.build
+++ b/testsuite/meson.build
@@ -1,11 +1,9 @@
unit_tests = [
- 'test-buffer-input-stream',
'test-encoding',
'test-encoding-converter',
- 'test-file',
+ #'test-file',
'test-file-content',
'test-file-loader',
- 'test-file-saver',
'test-fold-region',
'test-info-bar',
'test-metadata',
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]