From 684a46ff77f49389c4657a53b561c8fc81107440 Mon Sep 17 00:00:00 2001 From: Reuben Green Date: Wed, 14 Aug 2019 11:16:21 +0100 Subject: [PATCH] Prevent unnecessary fallback copy-delete in file move when overwriting Allows the use of native filesystem move (rather than a copy-and-delete-fallback) when overwriting files in a file move, with the user having the option (via a thunar_job_ask_replace dialog box) to replace or skip files, or else cancel the whole operation. Also adds a few calls to g_object_unref to the code in the same function (thunar_transfer_job_execute) which moves files out of the trash, to prevent possible memory leaks when such operations are canceled. (Bug #15727) --- thunar/thunar-transfer-job.c | 77 +++++++++++++++++++++++++++--------- 1 file changed, 59 insertions(+), 18 deletions(-) diff --git a/thunar/thunar-transfer-job.c b/thunar/thunar-transfer-job.c index cfa932ad..409f0532 100644 --- a/thunar/thunar-transfer-job.c +++ b/thunar/thunar-transfer-job.c @@ -854,6 +854,7 @@ thunar_transfer_job_execute (ExoJob *job, GFileInfo *info; GFileCopyFlags flags; gboolean parent_exists; + gboolean move_successful; GError *err = NULL; GList *new_files_list = NULL; GList *snext; @@ -923,6 +924,7 @@ thunar_transfer_job_execute (ExoJob *job, if (exo_job_set_error_if_cancelled (job, &err)) { g_object_unref (target_parent); + g_object_unref (info); break; } @@ -946,6 +948,7 @@ thunar_transfer_job_execute (ExoJob *job, { g_object_unref (target_parent); g_free (parent_display_name); + g_object_unref (info); break; } @@ -966,6 +969,7 @@ thunar_transfer_job_execute (ExoJob *job, g_object_unref (target_parent); g_free (parent_display_name); + g_object_unref (info); break; } @@ -983,11 +987,41 @@ thunar_transfer_job_execute (ExoJob *job, exo_job_info_message (job, _("Trying to move \"%s\""), g_file_info_get_display_name (info)); - if (g_file_move (node->source_file, tp->data, - flags, - exo_job_get_cancellable (job), - NULL, NULL, &err)) - { + /* try moving without overwriting */ + move_successful = g_file_move (node->source_file, tp->data, + flags, + exo_job_get_cancellable (job), + NULL, NULL, &err); + + /* if the file already exists, ask the user if they want to overwrite it */ + response = THUNAR_JOB_RESPONSE_YES; + if (!move_successful && err->code == G_IO_ERROR_EXISTS) + { + g_clear_error (&err); + response = thunar_job_ask_replace (THUNAR_JOB (job), node->source_file, tp->data, NULL); + + /* if the user chose to overwrite then try to do so */ + if (response == THUNAR_JOB_RESPONSE_YES) + move_successful = g_file_move (node->source_file, tp->data, + flags | G_FILE_COPY_OVERWRITE, + exo_job_get_cancellable (job), + NULL, NULL, &err); + + /* if the user chose to cancel then abort all remaining file moves */ + if (response == THUNAR_JOB_RESPONSE_CANCEL) + { + /* release all the remaining source and target files, and free the lists */ + g_list_free_full (transfer_job->source_node_list, thunar_transfer_node_free); + transfer_job->source_node_list = NULL; + g_list_free_full (transfer_job->target_file_list, g_object_unref); + transfer_job->target_file_list= NULL; + g_object_unref (info); + break; + } + } + + if (move_successful) + { /* notify the thumbnail cache of the move operation */ thunar_thumbnail_cache_move_file (thumbnail_cache, node->source_file, @@ -995,17 +1029,11 @@ thunar_transfer_job_execute (ExoJob *job, /* add the target file to the new files list */ new_files_list = thunar_g_file_list_prepend (new_files_list, tp->data); + } - /* release source and target files */ - thunar_transfer_node_free (node); - g_object_unref (tp->data); - - /* drop the matching list items */ - transfer_job->source_node_list = g_list_delete_link (transfer_job->source_node_list, sp); - transfer_job->target_file_list = g_list_delete_link (transfer_job->target_file_list, tp); - } - else if (!exo_job_is_cancelled (job)) - { + /* if the file moves failed but the user confirmed them, prepare for the fallback copy and delete */ + if (!move_successful && response == THUNAR_JOB_RESPONSE_YES) + { g_clear_error (&err); /* update progress information */ @@ -1019,12 +1047,26 @@ thunar_transfer_job_execute (ExoJob *job, g_object_unref (info); break; } + } + else + { + /* release source and target files */ + thunar_transfer_node_free (node); + g_object_unref (tp->data); + + /* drop the matching list items */ + transfer_job->source_node_list = g_list_delete_link (transfer_job->source_node_list, sp); + transfer_job->target_file_list = g_list_delete_link (transfer_job->target_file_list, tp); } - } + } + else if (transfer_job->type == THUNAR_TRANSFER_JOB_COPY) { if (!thunar_transfer_job_collect_node (THUNAR_TRANSFER_JOB (job), node, &err)) - break; + { + g_object_unref (info); + break; + } } g_object_unref (info); @@ -1218,4 +1260,3 @@ thunar_transfer_job_get_status (ThunarTransferJob *job) return g_string_free (status, FALSE); } - -- 2.23.0.rc1