[gnome-photos/wip/rishi/collection: 44/51] glib: Add photos_glib_file_copy_async
- From: Debarshi Ray <debarshir src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-photos/wip/rishi/collection: 44/51] glib: Add photos_glib_file_copy_async
- Date: Thu, 8 Feb 2018 00:02:20 +0000 (UTC)
commit 273213fdcf380dd9acc727abf08189517792bcfb
Author: Debarshi Ray <debarshir gnome org>
Date: Sun Feb 4 14:38:30 2018 +0100
glib: Add photos_glib_file_copy_async
It's meant to copy the source GFile to the destination GFile and handle
name collisions in the process. If the destination already exists, it
will try to suffix a copy number to generate a unique filename and
proceed with that.
A subsequent commit will use this to copy files while importing content
from attached devices.
https://gitlab.gnome.org/GNOME/gnome-photos/issues/29
src/photos-glib.c | 190 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
src/photos-glib.h | 10 +++
2 files changed, 200 insertions(+)
---
diff --git a/src/photos-glib.c b/src/photos-glib.c
index f0c8b2ba..66ef69b0 100644
--- a/src/photos-glib.c
+++ b/src/photos-glib.c
@@ -29,8 +29,16 @@
#include "photos-glib.h"
+typedef struct _PhotosGLibFileCopyData PhotosGLibFileCopyData;
typedef struct _PhotosGLibFileCreateData PhotosGLibFileCreateData;
+struct _PhotosGLibFileCopyData
+{
+ GFile *unique_file;
+ GFileOutputStream *ostream;
+ gint io_priority;
+};
+
struct _PhotosGLibFileCreateData
{
GFile *dir;
@@ -63,6 +71,188 @@ photos_glib_app_info_launch_uri (GAppInfo *appinfo,
}
+static void
+photos_glib_file_copy_data_free (PhotosGLibFileCopyData *data)
+{
+ g_clear_object (&data->unique_file);
+ g_clear_object (&data->ostream);
+ g_slice_free (PhotosGLibFileCopyData, data);
+}
+
+
+G_DEFINE_AUTOPTR_CLEANUP_FUNC (PhotosGLibFileCopyData, photos_glib_file_copy_data_free);
+
+
+static PhotosGLibFileCopyData *
+photos_glib_file_copy_data_new (gint io_priority)
+{
+ PhotosGLibFileCopyData *data;
+
+ data = g_slice_new0 (PhotosGLibFileCopyData);
+ data->io_priority = io_priority;
+ return data;
+}
+
+
+static void
+photos_glib_file_copy_splice (GObject *source_object, GAsyncResult *res, gpointer user_data)
+{
+ GOutputStream *ostream = G_OUTPUT_STREAM (source_object);
+ g_autoptr (GTask) task = G_TASK (user_data);
+ PhotosGLibFileCopyData *data;
+
+ data = (PhotosGLibFileCopyData *) g_task_get_task_data (task);
+
+ g_assert_true (G_IS_FILE_OUTPUT_STREAM (ostream));
+ g_assert_true (G_FILE_OUTPUT_STREAM (ostream) == data->ostream);
+
+ {
+ g_autoptr (GError) error = NULL;
+
+ g_output_stream_splice_finish (ostream, res, &error);
+ if (error != NULL)
+ {
+ g_task_return_error (task, g_steal_pointer (&error));
+ goto out;
+ }
+ }
+
+ g_task_return_pointer (task, g_object_ref (data->unique_file), g_object_unref);
+
+ out:
+ return;
+}
+
+
+static void
+photos_glib_file_copy_read (GObject *source_object, GAsyncResult *res, gpointer user_data)
+{
+ GCancellable *cancellable;
+ GFile *source = G_FILE (source_object);
+ g_autoptr (GFileInputStream) istream = NULL;
+ g_autoptr (GTask) task = G_TASK (user_data);
+ PhotosGLibFileCopyData *data;
+
+ cancellable = g_task_get_cancellable (task);
+ data = (PhotosGLibFileCopyData *) g_task_get_task_data (task);
+
+ {
+ g_autoptr (GError) error = NULL;
+
+ istream = g_file_read_finish (source, res, &error);
+ if (error != NULL)
+ {
+ g_task_return_error (task, g_steal_pointer (&error));
+ goto out;
+ }
+ }
+
+ g_output_stream_splice_async (G_OUTPUT_STREAM (data->ostream),
+ G_INPUT_STREAM (istream),
+ G_OUTPUT_STREAM_SPLICE_CLOSE_SOURCE | G_OUTPUT_STREAM_SPLICE_CLOSE_TARGET,
+ data->io_priority,
+ cancellable,
+ photos_glib_file_copy_splice,
+ g_object_ref (task));
+
+ out:
+ return;
+}
+
+
+static void
+photos_glib_file_copy_create (GObject *source_object, GAsyncResult *res, gpointer user_data)
+{
+ GCancellable *cancellable;
+ g_autoptr (GFile) unique_file = NULL;
+ GFile *destination = G_FILE (source_object);
+ GFile *source;
+ g_autoptr (GFileOutputStream) ostream = NULL;
+ g_autoptr (GTask) task = G_TASK (user_data);
+ PhotosGLibFileCopyData *data;
+
+ cancellable = g_task_get_cancellable (task);
+ data = (PhotosGLibFileCopyData *) g_task_get_task_data (task);
+ source = G_FILE (g_task_get_source_object (task));
+
+ {
+ g_autoptr (GError) error = NULL;
+
+ ostream = photos_glib_file_create_finish (destination, res, &unique_file, &error);
+ if (error != NULL)
+ {
+ g_task_return_error (task, g_steal_pointer (&error));
+ goto out;
+ }
+ }
+
+ g_assert_null (data->ostream);
+ g_assert_true (G_IS_FILE_OUTPUT_STREAM (ostream));
+ data->ostream = g_object_ref (ostream);
+
+ g_assert_null (data->unique_file);
+ g_assert_true (G_IS_FILE (unique_file));
+ data->unique_file = g_object_ref (unique_file);
+
+ g_file_read_async (source, data->io_priority, cancellable, photos_glib_file_copy_read, g_object_ref
(task));
+
+ out:
+ return;
+}
+
+
+void
+photos_glib_file_copy_async (GFile *source,
+ GFile *destination,
+ GFileCopyFlags flags,
+ gint io_priority,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ GFileCreateFlags create_flags = G_FILE_CREATE_NONE;
+ g_autoptr (GTask) task = NULL;
+ g_autoptr (PhotosGLibFileCopyData) data = NULL;
+
+ g_return_if_fail (G_IS_FILE (source));
+ g_return_if_fail (G_IS_FILE (destination));
+ g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
+
+ task = g_task_new (source, cancellable, callback, user_data);
+ g_task_set_source_tag (task, photos_glib_file_copy_async);
+
+ data = photos_glib_file_copy_data_new (io_priority);
+ g_task_set_task_data (task, g_steal_pointer (&data), (GDestroyNotify) photos_glib_file_copy_data_free);
+
+ if ((flags & G_FILE_COPY_OVERWRITE) != 0)
+ create_flags |= G_FILE_CREATE_REPLACE_DESTINATION;
+
+ photos_glib_file_create_async (destination,
+ create_flags,
+ io_priority,
+ cancellable,
+ photos_glib_file_copy_create,
+ g_object_ref (task));
+}
+
+
+GFile *
+photos_glib_file_copy_finish (GFile *source, GAsyncResult *res, GError **error)
+{
+ GTask *task;
+
+ g_return_val_if_fail (G_IS_FILE (source), FALSE);
+
+ g_return_val_if_fail (g_task_is_valid (res, source), FALSE);
+ task = G_TASK (res);
+
+ g_return_val_if_fail (g_task_get_source_tag (task) == photos_glib_file_copy_async, FALSE);
+ g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+
+ return g_task_propagate_pointer (task, error);
+}
+
+
static gchar *
photos_glib_filename_get_extension_offset (const gchar *filename)
{
diff --git a/src/photos-glib.h b/src/photos-glib.h
index b122336b..2ad2810c 100644
--- a/src/photos-glib.h
+++ b/src/photos-glib.h
@@ -32,6 +32,16 @@ gboolean photos_glib_app_info_launch_uri (GAppInfo *appi
GAppLaunchContext *launch_context,
GError **error);
+void photos_glib_file_copy_async (GFile *source,
+ GFile *destination,
+ GFileCopyFlags flags,
+ gint io_priority,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+
+GFile *photos_glib_file_copy_finish (GFile *source, GAsyncResult *res, GError
**error);
+
void photos_glib_file_create_async (GFile *file,
GFileCreateFlags flags,
gint io_priority,
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]