GFile: Add g_file_delete_async()
authorColin Walters <walters@verbum.org>
Sat, 28 Jul 2012 13:30:22 +0000 (09:30 -0400)
committerColin Walters <walters@verbum.org>
Mon, 30 Jul 2012 09:01:06 +0000 (05:01 -0400)
This looks like it was stubbed out but not implemented; the vtable
entry dates to commit 3781343738de4abddf56982325a77bd70a98cd26 which
is just alex's initial merge of gio into glib.

I was working on some code that wants an asynchronous rm -rf
equivalent, and so yeah, this is desirable.

https://bugzilla.gnome.org/show_bug.cgi?id=680760

docs/reference/gio/gio-sections.txt
gio/gfile.c
gio/gfile.h
gio/gio.symbols
gio/tests/file.c

index e709e83..991cc32 100644 (file)
@@ -127,6 +127,8 @@ g_file_set_display_name
 g_file_set_display_name_async
 g_file_set_display_name_finish
 g_file_delete
+g_file_delete_async
+g_file_delete_finish
 g_file_trash
 g_file_copy
 g_file_copy_async
index abc7e27..b76939f 100644 (file)
@@ -196,6 +196,14 @@ static void               g_file_real_replace_async               (GFile
 static GFileOutputStream *g_file_real_replace_finish              (GFile                  *file,
                                                                   GAsyncResult           *res,
                                                                   GError                **error);
+static void               g_file_real_delete_async                (GFile                  *file,
+                                                                  int                     io_priority,
+                                                                  GCancellable           *cancellable,
+                                                                  GAsyncReadyCallback     callback,
+                                                                  gpointer                user_data);
+static gboolean           g_file_real_delete_finish               (GFile                  *file,
+                                                                  GAsyncResult           *res,
+                                                                  GError                **error);
 static void               g_file_real_open_readwrite_async        (GFile                  *file,
                                                                    int                  io_priority,
                                                                    GCancellable           *cancellable,
@@ -294,6 +302,8 @@ g_file_default_init (GFileIface *iface)
   iface->create_finish = g_file_real_create_finish;
   iface->replace_async = g_file_real_replace_async;
   iface->replace_finish = g_file_real_replace_finish;
+  iface->delete_file_async = g_file_real_delete_async;
+  iface->delete_file_finish = g_file_real_delete_finish;
   iface->open_readwrite_async = g_file_real_open_readwrite_async;
   iface->open_readwrite_finish = g_file_real_open_readwrite_finish;
   iface->create_readwrite_async = g_file_real_create_readwrite_async;
@@ -3508,6 +3518,69 @@ g_file_delete (GFile         *file,
 }
 
 /**
+ * g_file_delete_async:
+ * @file: input #GFile.
+ * @io_priority: the <link linkend="io-priority">I/O priority</link>
+ *     of the request
+ * @cancellable: (allow-none): optional #GCancellable object, %NULL to ignore.
+ * @callback: a #GAsyncReadyCallback to call when the request is satisfied
+ * @user_data: the data to pass to callback function
+ *
+ * Asynchronously delete a file. If the @file is a directory, it will
+ * only be deleted if it is empty.
+ *
+ * Virtual: delete_file_async
+ * Since: 2.34
+ **/
+void
+g_file_delete_async (GFile               *file,
+                     int                  io_priority,
+                     GCancellable        *cancellable,
+                     GAsyncReadyCallback  callback,
+                     gpointer             user_data)
+{
+  GFileIface *iface;
+
+  g_return_if_fail (G_IS_FILE (file));
+
+  iface = G_FILE_GET_IFACE (file);
+  (* iface->delete_file_async) (file,
+                                io_priority,
+                                cancellable,
+                                callback,
+                                user_data);
+}
+
+/**
+ * g_file_delete_finish:
+ * @file: input #GFile.
+ * @res: a #GAsyncResult.
+ * @error: a #GError, or %NULL
+ *
+ * Finishes deleting a file started with
+ * g_file_delete_async().
+ *
+ * Virtual: delete_file_finish
+ * Since: 2.34
+ **/
+gboolean
+g_file_delete_finish (GFile            *file,
+                      GAsyncResult     *result,
+                      GError          **error)
+{
+  GFileIface *iface;
+
+  g_return_val_if_fail (G_IS_FILE (file), FALSE);
+  g_return_val_if_fail (G_IS_ASYNC_RESULT (result), FALSE);
+
+  if (g_async_result_legacy_propagate_error (result, error))
+    return FALSE;
+
+  iface = G_FILE_GET_IFACE (file);
+  return (* iface->delete_file_finish) (file, result, error);
+}
+
+/**
  * g_file_trash:
  * @file: #GFile to send to trash.
  * @cancellable: (allow-none): optional #GCancellable object, %NULL to ignore.
@@ -5257,6 +5330,51 @@ g_file_real_replace_finish (GFile         *file,
 }
 
 static void
+delete_async_thread (GSimpleAsyncResult *res,
+                     GObject            *object,
+                     GCancellable       *cancellable)
+{
+  GFileIface *iface;
+  GError *error = NULL;
+
+  iface = G_FILE_GET_IFACE (object);
+
+  if (!iface->delete_file (G_FILE (object),
+                           cancellable,
+                           &error))
+    g_simple_async_result_take_error (res, error);
+}
+
+static void
+g_file_real_delete_async (GFile               *file,
+                          int                  io_priority,
+                          GCancellable        *cancellable,
+                          GAsyncReadyCallback  callback,
+                          gpointer             user_data)
+{
+  GSimpleAsyncResult *res;
+
+  res = g_simple_async_result_new (G_OBJECT (file), callback, user_data, g_file_real_delete_async);
+  g_simple_async_result_run_in_thread (res, delete_async_thread, io_priority, cancellable);
+  g_object_unref (res);
+}
+
+static gboolean
+g_file_real_delete_finish (GFile         *file,
+                           GAsyncResult  *res,
+                           GError       **error)
+{
+  GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (res);
+
+  g_warn_if_fail (g_simple_async_result_get_source_tag (simple) == g_file_real_delete_async);
+
+  if (g_simple_async_result_propagate_error (simple, error))
+    return FALSE;
+
+  return TRUE;
+}
+
+static void
 open_readwrite_async_thread (GSimpleAsyncResult *res,
                             GObject            *object,
                             GCancellable       *cancellable)
index f784c5d..1a724db 100644 (file)
@@ -105,8 +105,8 @@ typedef struct _GFileIface                  GFileIface;
  * @replace_async: Asynchronously replaces the contents of a file.
  * @replace_finish: Finishes asynchronously replacing a file.
  * @delete_file: Deletes a file.
- * @_delete_file_async: Asynchronously deletes a file.
- * @_delete_file_finish: Finishes an asynchronous delete.
+ * @delete_file_async: Asynchronously deletes a file.
+ * @delete_file_finish: Finishes an asynchronous delete.
  * @trash: Sends a #GFile to the Trash location.
  * @_trash_async: Asynchronously sends a #GFile to the Trash location.
  * @_trash_finish: Finishes an asynchronous file trashing operation.
@@ -353,8 +353,14 @@ struct _GFileIface
   gboolean            (* delete_file)                 (GFile                *file,
                                                        GCancellable         *cancellable,
                                                        GError              **error);
-  void                (* _delete_file_async)          (void);
-  void                (* _delete_file_finish)         (void);
+  void                (* delete_file_async)           (GFile                *file,
+                                                      int                   io_priority,
+                                                      GCancellable         *cancellable,
+                                                      GAsyncReadyCallback   callback,
+                                                      gpointer              user_data);
+  gboolean            (* delete_file_finish)          (GFile                *file,
+                                                      GAsyncResult         *result,
+                                                      GError              **error);
 
   gboolean            (* trash)                       (GFile                *file,
                                                        GCancellable         *cancellable,
@@ -751,6 +757,19 @@ GFile *                 g_file_set_display_name_finish    (GFile
 gboolean                g_file_delete                     (GFile                      *file,
                                                           GCancellable               *cancellable,
                                                           GError                    **error);
+
+GLIB_AVAILABLE_IN_2_34
+void                    g_file_delete_async               (GFile                      *file,
+                                                          int                         io_priority,
+                                                          GCancellable               *cancellable,
+                                                          GAsyncReadyCallback         callback,
+                                                          gpointer                    user_data);
+
+GLIB_AVAILABLE_IN_2_34
+gboolean                g_file_delete_finish              (GFile                      *file,
+                                                          GAsyncResult               *result,
+                                                          GError                    **error);
+
 gboolean                g_file_trash                      (GFile                      *file,
                                                           GCancellable               *cancellable,
                                                           GError                    **error);
index 6db9bbd..a60e1e9 100644 (file)
@@ -303,6 +303,8 @@ g_file_set_display_name
 g_file_set_display_name_async
 g_file_set_display_name_finish
 g_file_delete
+g_file_delete_async
+g_file_delete_finish
 g_file_trash
 g_file_copy
 g_file_copy_async
index c7f840b..5fed88b 100644 (file)
@@ -592,6 +592,48 @@ test_replace_load (void)
   free (path);
 }
 
+static void
+on_file_deleted (GObject      *object,
+                GAsyncResult *result,
+                gpointer      user_data)
+{
+  GError *local_error = NULL;
+  GMainLoop *loop = user_data;
+
+  (void) g_file_delete_finish ((GFile*)object, result, &local_error);
+  g_assert_no_error (local_error);
+
+  g_main_loop_quit (loop);
+}
+
+static void
+test_async_delete (void)
+{
+  GFile *file;
+  GFileIOStream *iostream;
+  GError *local_error = NULL;
+  GError **error = &local_error;
+  GMainLoop *loop;
+
+  file = g_file_new_tmp ("g_file_delete_XXXXXX",
+                        &iostream, error);
+  g_assert_no_error (local_error);
+  g_object_unref (iostream);
+
+  g_assert (g_file_query_exists (file, NULL));
+
+  loop = g_main_loop_new (NULL, TRUE);
+
+  g_file_delete_async (file, G_PRIORITY_DEFAULT, NULL, on_file_deleted, loop);
+
+  g_main_loop_run (loop);
+
+  g_assert (!g_file_query_exists (file, NULL));
+
+  g_main_loop_unref (loop);
+  g_object_unref (file);
+}
+
 int
 main (int argc, char *argv[])
 {
@@ -609,6 +651,7 @@ main (int argc, char *argv[])
   g_test_add_data_func ("/file/async-create-delete/25", GINT_TO_POINTER (25), test_create_delete);
   g_test_add_data_func ("/file/async-create-delete/4096", GINT_TO_POINTER (4096), test_create_delete);
   g_test_add_func ("/file/replace-load", test_replace_load);
+  g_test_add_func ("/file/async-delete", test_async_delete);
 
   return g_test_run ();
 }