Commit 14a1c201 authored by Colin Walters's avatar Colin Walters

GFile: Add g_file_delete_async()

This looks like it was stubbed out but not implemented; the vtable
entry dates to commit 37813437 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
parent 6b6bef75
......@@ -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
......
......@@ -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;
......@@ -3507,6 +3517,69 @@ g_file_delete (GFile *file,
return (* iface->delete_file) (file, cancellable, error);
}
/**
* 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.
......@@ -5256,6 +5329,51 @@ g_file_real_replace_finish (GFile *file,
return NULL;
}
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,
......
......@@ -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);
......
......@@ -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
......
......@@ -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 ();
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment