Re: [PATCH] 312707: moving a file or folder onto itself destroys it



Alexander Larsson wrote:

However, will the temp move really work in the case we're discussing
though? Won't the move of the file in the destination folder actually
also change the name in of the file in the source folder (since they are
symlinked).

Yes; the source unexpectedly disappearing will cause the transfer to fail and the temp rename to be reverted, which leaves us in a good state (and with a bad error message).

Does this problem happen in inter-fs transfers at all?

It does (tested with ftp://foo localhost/ == file:///home/ftpusers/foo/).

The attached work-in-progress patch is an approach by re-ordering operations; it brings the pre-work target deletion (in the case of conflicts) and the post-work source deletion (in the case of move by copy-delete) into the work phase processing of each item such that

  - the conflict target is only deleted after the source is opened, so
    the handle keeps us from losing the source
  - if we did remove a conflict target and plan to remove the source
    after a successful copy, then before creating the new target check
    if removing the target removed the source as well, and decline to
    delete the source in that case.

As discussed on irc the other day, the first bit fails at least if the open file handle doesn't really mean an open file on the target filesystem; the second bit can fail due to caching e.g. on ftp. Still, between those caveats, it should work in the most common cases.

I'm not entirely sure about the correct use of some inout-ish params there... progress_info->file_index ends up inflated with this, too, atm

't.
Index: gnome-vfs-xfer.c
===================================================================
RCS file: /cvs/gnome/gnome-vfs/libgnomevfs/gnome-vfs-xfer.c,v
retrieving revision 1.125
diff -p -u -r1.125 gnome-vfs-xfer.c
--- gnome-vfs-xfer.c	8 Jul 2005 08:53:18 -0000	1.125
+++ gnome-vfs-xfer.c	31 Aug 2005 13:31:14 -0000
@@ -853,6 +853,7 @@ typedef struct {
 	GnomeVFSXferErrorMode *error_mode;
 	GnomeVFSProgressCallbackState *progress;
 	GnomeVFSResult result;
+	GHashTable *clobber_uristr_set;
 } HandleMergedNameConflictsParams;
 
 static gboolean
@@ -889,17 +890,16 @@ handle_merged_name_conflict_visit (const
 				/* FIXME bugzilla.eazel.com 1207:
 				 * move items to Trash here
 				 */
-				if (target_info->type == GNOME_VFS_FILE_TYPE_DIRECTORY) {
-					if (move_source_is_in_target (source_uri, target_uri)) {
-						/* Would like a better error here */
-						result = GNOME_VFS_ERROR_DIRECTORY_NOT_EMPTY;
-					} else {
-						result = remove_directory (target_uri, TRUE, params->progress, 
-									   params->xfer_options, params->error_mode, &skip);
-					}
+
+				if (target_info->type == GNOME_VFS_FILE_TYPE_DIRECTORY &&
+				    move_source_is_in_target (source_uri, target_uri)) {
+					/* Would like a better error here */
+					result = GNOME_VFS_ERROR_DIRECTORY_NOT_EMPTY;
 				} else {
-					result = remove_file (target_uri, params->progress,
-							      params->xfer_options, params->error_mode, &skip);
+					g_hash_table_insert (
+						params->clobber_uristr_set,
+						gnome_vfs_uri_to_string (target_uri, GNOME_VFS_URI_HIDE_NONE),
+						NULL);
 				}
 			}
 		}
@@ -922,7 +922,8 @@ handle_merged_directory_name_conflicts (
 					GnomeVFSXferErrorMode *error_mode,
 					GnomeVFSProgressCallbackState *progress,
 					GnomeVFSURI *source_uri,
-					GnomeVFSURI *target_uri)
+					GnomeVFSURI *target_uri,
+					GHashTable *clobber_uristr_set)
 {
 	GnomeVFSFileInfoOptions info_options;
 	GnomeVFSDirectoryVisitOptions visit_options;
@@ -933,7 +934,8 @@ handle_merged_directory_name_conflicts (
 	params.xfer_options = xfer_options;
 	params.error_mode = error_mode;
 	params.progress = progress;
-	
+	params.clobber_uristr_set = clobber_uristr_set;
+
 	/* set up the params for recursion */
 	visit_options = GNOME_VFS_DIRECTORY_VISIT_LOOPCHECK;
 	if (xfer_options & GNOME_VFS_XFER_SAMEFS)
@@ -958,7 +960,8 @@ handle_merged_directory_name_conflicts (
 
 /* Compares the list of files about to be created by a transfer with
  * any possible existing files with conflicting names in the target directory.
- * Handles conflicts, optionaly removing the conflicting file/directory
+ * Handles conflicts, optionally adding the conflicting file/directory to the
+ * set of items to remove.
  */
 static GnomeVFSResult
 handle_name_conflicts (GList **source_uri_list,
@@ -970,7 +973,8 @@ handle_name_conflicts (GList **source_ur
 		       gboolean move,
 		       gboolean link,
 		       GList **merge_source_uri_list,
-		       GList **merge_target_uri_list)
+		       GList **merge_target_uri_list,
+		       GHashTable *clobber_uristr_set)
 {
 	GnomeVFSResult result;
 	GList *source_item;
@@ -1011,6 +1015,7 @@ handle_name_conflicts (GList **source_ur
 	for (target_item = *target_uri_list, source_item = *source_uri_list; 
 	     target_item != NULL;) {
 		gboolean replace;
+		gboolean clobber = FALSE;	/* remove target, no merge */
 		gboolean skip;
 		gboolean is_move_to_self;
 		GnomeVFSURI *uri, *source_uri;
@@ -1047,26 +1052,32 @@ handle_name_conflicts (GList **source_ur
 						    gnome_vfs_get_file_info_uri (source_uri, source_info, GNOME_VFS_FILE_INFO_DEFAULT) == GNOME_VFS_OK &&
 						    source_info->type == GNOME_VFS_FILE_TYPE_DIRECTORY) {
 							if (move || (xfer_options & GNOME_VFS_XFER_RECURSIVE)) {
-								result = handle_merged_directory_name_conflicts (xfer_options, error_mode,
-														 progress, source_uri, uri);
+								result = handle_merged_directory_name_conflicts (
+									xfer_options,
+									error_mode,
+									progress,
+									source_uri,
+									uri,
+									clobber_uristr_set);
 							}
 							must_copy = TRUE;
 						} else {
-							result = remove_directory (uri, TRUE, progress, 
-										   xfer_options, error_mode, &skip);
+							clobber = TRUE;
 						}
 						gnome_vfs_file_info_unref (source_info);
 					}
 				} else {
-					result = remove_file (uri, progress,
-							      xfer_options, error_mode, &skip);
+					clobber = TRUE;
 				}
 			}
 			
 			gnome_vfs_file_info_clear (target_info);
 		}
 
-		
+		if (clobber) {
+			g_hash_table_insert (clobber_uristr_set, gnome_vfs_uri_to_string (uri, GNOME_VFS_URI_HIDE_NONE), NULL);
+		}
+
 		if (result != GNOME_VFS_OK) {
 			break;
 		}
@@ -1437,6 +1448,39 @@ copy_symlink (GnomeVFSURI *source_uri,
 	return result;
 }
 
+
+/** Remove file identified by uri; if a directory, remove recursively. */
+static GnomeVFSResult
+remove_uri (GnomeVFSURI *uri,
+	    GnomeVFSProgressCallbackState *progress,
+	    GnomeVFSXferOptions xfer_options,
+	    GnomeVFSXferErrorMode *error_mode,
+	    gboolean *skip)
+{
+	GnomeVFSResult result;
+	GnomeVFSFileInfo *info;
+	gboolean is_dir;
+
+	info = gnome_vfs_file_info_new ();	    
+	result = gnome_vfs_get_file_info_uri (
+		uri, info, GNOME_VFS_FILE_INFO_DEFAULT);
+	is_dir = (GNOME_VFS_FILE_TYPE_DIRECTORY == info->type);
+	gnome_vfs_file_info_unref (info);
+
+	if (result != GNOME_VFS_OK)
+		return result;
+
+	if (is_dir)
+		result = remove_directory (
+			uri, TRUE, progress, xfer_options, error_mode, skip);
+	else
+		result = remove_file (
+			uri, progress, xfer_options, error_mode, skip);
+
+	return result;
+}
+
+
 static GnomeVFSResult
 copy_file (GnomeVFSFileInfo *info,  
 	   GnomeVFSURI *source_uri,
@@ -1449,6 +1493,8 @@ copy_file (GnomeVFSFileInfo *info,  
 {
 	GnomeVFSResult close_result, result;
 	GnomeVFSHandle *source_handle, *target_handle;
+	gboolean remove_source =
+		(GNOME_VFS_XFER_REMOVESOURCE & xfer_options) != 0;
 
 	progress->progress_info->phase = GNOME_VFS_XFER_PHASE_OPENSOURCE;
 	progress->progress_info->bytes_copied = 0;
@@ -1463,6 +1509,23 @@ copy_file (GnomeVFSFileInfo *info,  
 		return result;
 	}
 
+	/* We may want to remove a conflicting target file. Having the source
+	 * file open at this point may help us not lose the source it if it
+	 * turns out the target is the source. */
+	if (GNOME_VFS_XFER_OVERWRITE_MODE_REPLACE == *overwrite_mode) {
+		remove_uri (
+			target_uri, progress, xfer_options, error_mode, skip);
+
+		/* If we plan to delete the source after the copy is done, we
+		 * want to know if deleting the conflict target deleted the
+		 * source too, in which case we'll want to skip the source
+		 * removal. If the uri_exists result comes from a cache entry
+		 * from before the conflict target removal, it's useless.
+		 */
+		remove_source = remove_source &&
+			gnome_vfs_uri_exists (source_uri);
+	}
+
 	progress->progress_info->phase = GNOME_VFS_XFER_PHASE_OPENTARGET;
 	result = xfer_create_target (&target_handle, target_uri,
 				     progress, xfer_options,
@@ -1533,6 +1596,9 @@ copy_file (GnomeVFSFileInfo *info,  
 		return GNOME_VFS_OK;
 	}
 
+	if (GNOME_VFS_OK == result && remove_source)
+		gnome_vfs_unlink_from_uri (source_uri);
+
 	return result;
 }
 
@@ -1544,7 +1610,8 @@ copy_directory (GnomeVFSFileInfo *source
 		GnomeVFSXferErrorMode *error_mode,
 		GnomeVFSXferOverwriteMode *overwrite_mode,
 		GnomeVFSProgressCallbackState *progress,
-		gboolean *skip)
+		gboolean *skip,
+		GHashTable *clobber_uristr_set)
 {
 	GnomeVFSResult result;
 	GnomeVFSDirectoryHandle *source_directory_handle;
@@ -1633,27 +1700,62 @@ copy_directory (GnomeVFSFileInfo *source
 				source_uri = gnome_vfs_uri_append_file_name (source_dir_uri, info->name);
 				dest_uri = gnome_vfs_uri_append_file_name (target_dir_uri, info->name);
 				
+				/* Set replace mode for the individual copy
+				 * operation if we have a pre-flight overwrite
+				 * decision on its target. */
+				GnomeVFSXferOverwriteMode child_overwrite = *overwrite_mode;
+				gchar *uristr = gnome_vfs_uri_to_string (dest_uri, GNOME_VFS_URI_HIDE_NONE);
+				gboolean clobber = g_hash_table_remove (clobber_uristr_set, uristr);
+				g_free (uristr);
+				if (clobber)
+					child_overwrite = GNOME_VFS_XFER_OVERWRITE_MODE_REPLACE;
+
 				if (info->type == GNOME_VFS_FILE_TYPE_REGULAR) {
-					result = copy_file (info, source_uri, dest_uri, 
-							    xfer_options, error_mode, overwrite_mode, 
-							    progress, &skip_child);
+					result = copy_file (
+						info,
+						source_uri,
+						dest_uri,
+						xfer_options,
+						error_mode,
+						&child_overwrite,
+						progress,
+						&skip_child);
 				} else if (info->type == GNOME_VFS_FILE_TYPE_DIRECTORY) {
-					result = copy_directory (info, source_uri, dest_uri, 
-								 xfer_options, error_mode, overwrite_mode, 
-								 progress, &skip_child);
+					result = copy_directory (
+						info,
+						source_uri,
+						dest_uri,
+						xfer_options,
+						error_mode,
+						&child_overwrite,
+						progress,
+						&skip_child,
+						clobber_uristr_set);
 				} else if (info->type == GNOME_VFS_FILE_TYPE_SYMBOLIC_LINK) {
 					if (xfer_options & GNOME_VFS_XFER_FOLLOW_LINKS_RECURSIVE) {
 						GnomeVFSFileInfo *symlink_target_info = gnome_vfs_file_info_new ();
 						result = gnome_vfs_get_file_info_uri (source_uri, symlink_target_info,
 										      GNOME_VFS_FILE_INFO_FOLLOW_LINKS);
 						if (result == GNOME_VFS_OK) 
-							result = copy_file (symlink_target_info, source_uri, dest_uri, 
-									    xfer_options, error_mode, overwrite_mode, 
-									    progress, &skip_child);
+							result = copy_file (
+								symlink_target_info,
+								source_uri,
+								dest_uri,
+								xfer_options,
+								error_mode,
+								&child_overwrite,
+								progress,
+								&skip_child);
 						gnome_vfs_file_info_unref (symlink_target_info);
 					} else {
-						result = copy_symlink (source_uri, dest_uri, info->symlink_name,
-								       error_mode, overwrite_mode, progress, &skip_child);
+						result = copy_symlink (
+							source_uri,
+							dest_uri,
+							info->symlink_name,
+							error_mode,
+							&child_overwrite,
+							progress,
+							&skip_child);
 					}
 				}
 				/* We don't want to overwrite a previous skip with FALSE, so we only
@@ -1661,6 +1763,12 @@ copy_directory (GnomeVFSFileInfo *source
 				 */
 				if (skip_child)
 					*skip = TRUE;
+
+				/* Copy overwrite mode only if we didn't force
+				 * replace. */
+				if (!clobber)
+					*overwrite_mode = child_overwrite;
+
 				/* just ignore all the other special file system objects here */
 			}
 			
@@ -1720,6 +1828,10 @@ copy_directory (GnomeVFSFileInfo *source
 		gnome_vfs_file_info_unref (target_dir_info);
 	}
 
+	if (GNOME_VFS_OK == result && GNOME_VFS_XFER_REMOVESOURCE & xfer_options) {
+		remove_directory (source_dir_uri, FALSE, progress, xfer_options, error_mode, skip);
+	}
+
 	return result;
 }
 
@@ -1730,7 +1842,7 @@ copy_items (const GList *source_uri_list
 	    GnomeVFSXferErrorMode *error_mode,
 	    GnomeVFSXferOverwriteMode overwrite_mode,
 	    GnomeVFSProgressCallbackState *progress,
-	    GList **p_source_uris_copied_list)
+	    GHashTable *clobber_uristr_set)
 {
 	GnomeVFSResult result;
 	const GList *source_item, *target_item;
@@ -1778,10 +1890,18 @@ copy_items (const GList *source_uri_list
 			gnome_vfs_file_info_unref (target_dir_info);
 			result = GNOME_VFS_OK;
 
+			/* Set replace mode for the individual copy operation
+			 * if we have a pre-flight overwrite decision on its
+			 * target. */
+			GnomeVFSXferOverwriteMode child_overwrite = GNOME_VFS_XFER_OVERWRITE_MODE_ABORT;
+			gchar *uristr = gnome_vfs_uri_to_string (
+				(GnomeVFSURI *)target_item->data, GNOME_VFS_URI_HIDE_NONE);
+			if (g_hash_table_remove (clobber_uristr_set, uristr))
+				child_overwrite = GNOME_VFS_XFER_OVERWRITE_MODE_REPLACE;
+			g_free (uristr);
+
 			/* optionally keep trying until we hit a unique target name */
 			for (count = 1; ; count++) {
-				GnomeVFSXferOverwriteMode overwrite_mode_abort;
-
 				target_uri = gnome_vfs_uri_append_string
 					(target_dir_uri, 
 					 progress->progress_info->duplicate_name);
@@ -1796,32 +1916,39 @@ copy_items (const GList *source_uri_list
 					result = GNOME_VFS_ERROR_INTERRUPTED;
 				}
 
-				overwrite_mode_abort = GNOME_VFS_XFER_OVERWRITE_MODE_ABORT;
-				
-				
 				if (info->type == GNOME_VFS_FILE_TYPE_REGULAR) {
-					result = copy_file (info, source_uri, target_uri, 
-							    xfer_options, error_mode, 
-							    &overwrite_mode_abort, 
-							    progress, &skip);
+					result = copy_file (
+						info,
+						source_uri,
+						target_uri,
+						xfer_options,
+						error_mode,
+						&child_overwrite, 
+						progress,
+						&skip);
 				} else if (info->type == GNOME_VFS_FILE_TYPE_DIRECTORY) {
-					result = copy_directory (info, source_uri, target_uri, 
-								 xfer_options, error_mode,
-								 &overwrite_mode_abort,
-								 progress, &skip);
+					result = copy_directory (
+						info,
+						source_uri,
+						target_uri,
+						xfer_options,
+						error_mode,
+						&child_overwrite,
+						progress,
+						&skip,
+						clobber_uristr_set);
                                 } else if (info->type == GNOME_VFS_FILE_TYPE_SYMBOLIC_LINK) {
-					result = copy_symlink (source_uri, target_uri, info->symlink_name,
-							       error_mode, &overwrite_mode_abort,
-							       progress, &skip);
+					result = copy_symlink (
+						source_uri,
+						target_uri,
+						info->symlink_name,
+						error_mode,
+						&child_overwrite,
+						progress,
+						&skip);
                                 }
 				/* just ignore all the other special file system objects here */
 
-				if (result == GNOME_VFS_OK && !skip) {
-					/* Add to list of successfully copied files... */
-					*p_source_uris_copied_list = g_list_prepend (*p_source_uris_copied_list, source_uri);
-					gnome_vfs_uri_ref (source_uri);
-				}
-
 				if (result != GNOME_VFS_ERROR_FILE_EXISTS) {
 					/* whatever happened, it wasn't a name conflict */
 					gnome_vfs_uri_unref (target_uri);
@@ -1885,7 +2012,8 @@ move_items (const GList *source_uri_list
 	    GnomeVFSXferOptions xfer_options,
 	    GnomeVFSXferErrorMode *error_mode,
 	    GnomeVFSXferOverwriteMode *overwrite_mode,
-	    GnomeVFSProgressCallbackState *progress)
+	    GnomeVFSProgressCallbackState *progress,
+	    GHashTable *clobber_uristr_set)
 {
 	GnomeVFSResult result;
 	const GList *source_item, *target_item;
@@ -1912,6 +2040,16 @@ move_items (const GList *source_uri_list
 			gnome_vfs_uri_extract_short_path_name
 			((GnomeVFSURI *)target_item->data);
 
+		/* Set replace mode for the individual move operation if we
+		 * have a pre-flight overwrite decision on the target. */
+		gchar *uristr = gnome_vfs_uri_to_string (
+			(GnomeVFSURI *)target_item->data, GNOME_VFS_URI_HIDE_NONE);
+		gboolean force_replace =
+			g_hash_table_remove (clobber_uristr_set, uristr)
+			|| (GNOME_VFS_XFER_OVERWRITE_MODE_REPLACE == *overwrite_mode
+			    && GNOME_VFS_XFER_USE_UNIQUE_NAMES & xfer_options);
+		g_free (uristr);
+
 		skip = FALSE;
 		conflict_count = 1;
 
@@ -1925,14 +2063,7 @@ move_items (const GList *source_uri_list
 			progress_set_source_target_uris (progress, source_uri, target_uri);
 			progress->progress_info->top_level_item = TRUE;
 
-			/* no matter what the replace mode, just overwrite the destination
-			 * handle_name_conflicts took care of conflicting files
-			 */
-			result = gnome_vfs_move_uri (source_uri, target_uri, 
-						     (xfer_options & GNOME_VFS_XFER_USE_UNIQUE_NAMES) != 0
-						     ? GNOME_VFS_XFER_OVERWRITE_MODE_ABORT
-						     : GNOME_VFS_XFER_OVERWRITE_MODE_REPLACE);
-
+			result = gnome_vfs_move_uri (source_uri, target_uri, force_replace);
 
 			if (result == GNOME_VFS_ERROR_FILE_EXISTS) {
 				/* deal with a name conflict -- ask the progress_callback for a better name */
@@ -1991,7 +2122,8 @@ link_items (const GList *source_uri_list
 	    GnomeVFSXferOptions xfer_options,
 	    GnomeVFSXferErrorMode *error_mode,
 	    GnomeVFSXferOverwriteMode *overwrite_mode,
-	    GnomeVFSProgressCallbackState *progress)
+	    GnomeVFSProgressCallbackState *progress,
+	    GHashTable *clobber_uristr_set)
 {
 	GnomeVFSResult result;
 	const GList *source_item, *target_item;
@@ -2019,6 +2151,18 @@ link_items (const GList *source_uri_list
 			gnome_vfs_uri_extract_short_path_name
 			((GnomeVFSURI *)target_item->data);
 
+		/* Remove conflicting target. */
+		gchar *uristr = gnome_vfs_uri_to_string (
+			(GnomeVFSURI *)target_item->data, GNOME_VFS_URI_HIDE_NONE);
+		if (g_hash_table_remove (clobber_uristr_set, uristr))
+			remove_uri (
+				(GnomeVFSURI *)target_item->data,
+				progress,
+				xfer_options,
+				error_mode,
+				&skip);
+		g_free (uristr);
+
 		skip = FALSE;
 		conflict_count = 1;
 
@@ -2033,9 +2177,6 @@ link_items (const GList *source_uri_list
 			progress->progress_info->top_level_item = TRUE;
 			progress_set_source_target_uris (progress, source_uri, target_uri);
 
-			/* no matter what the replace mode, just overwrite the destination
-			 * handle_name_conflicts took care of conflicting files
-			 */
 			result = gnome_vfs_create_symbolic_link (target_uri, source_reference); 
 			if (result == GNOME_VFS_ERROR_FILE_EXISTS) {
 				/* deal with a name conflict -- ask the progress_callback for a better name */
@@ -2324,7 +2465,6 @@ gnome_vfs_xfer_uri_internal (const GList
 	GnomeVFSResult result;
 	GList *source_uri_list, *target_uri_list;
 	GList *source_uri, *target_uri;
-	GList *source_uri_list_copied;
 	GList *merge_source_uri_list, *merge_target_uri_list;
 	GnomeVFSURI *target_dir_uri;
 	gboolean move, link;
@@ -2337,7 +2477,6 @@ gnome_vfs_xfer_uri_internal (const GList
 	move = FALSE;
 	link = FALSE;
 	target_dir_uri = NULL;
-	source_uri_list_copied = NULL;
 
 	/* Check and see if target is writable. Return error if it is not. */
 	call_progress (progress, GNOME_VFS_XFER_CHECKING_DESTINATION);
@@ -2354,6 +2493,7 @@ gnome_vfs_xfer_uri_internal (const GList
 	link = (xfer_options & GNOME_VFS_XFER_LINK_ITEMS) != 0;
 
 	if (move && link) {
+		gnome_vfs_uri_unref (target_dir_uri);
 		return GNOME_VFS_ERROR_BAD_PARAMETERS;
 	}
 
@@ -2426,11 +2566,12 @@ gnome_vfs_xfer_uri_internal (const GList
 			gnome_vfs_uri_unref (target_dir_uri);
 			target_dir_uri = NULL;
 		}
+	}
+
+	if (result == GNOME_VFS_OK) {
+		GHashTable *clobber_uristr_set = g_hash_table_new_full (
+			g_str_hash, g_str_equal, g_free, NULL);
 
-		if (result != GNOME_VFS_OK) {
-			return result;
-		}
-			
 		if ((xfer_options & GNOME_VFS_XFER_USE_UNIQUE_NAMES) == 0) {
 		
 			/* Save the preflight numbers, handle_name_conflicts would overwrite them */
@@ -2443,13 +2584,18 @@ gnome_vfs_xfer_uri_internal (const GList
 			progress->progress_info->bytes_total = 0;
 			progress->progress_info->files_total = 0;
 
-			result = handle_name_conflicts (&source_uri_list, &target_uri_list,
-						        xfer_options, &error_mode, &overwrite_mode,
-						        progress,
-							move,
-							link,
-							&merge_source_uri_list,
-							&merge_target_uri_list);
+			result = handle_name_conflicts (
+				&source_uri_list,
+				&target_uri_list,
+				xfer_options,
+				&error_mode,
+				&overwrite_mode,
+				progress,
+				move,
+				link,
+				&merge_source_uri_list,
+				&merge_target_uri_list,
+				clobber_uristr_set);
 
 			progress->progress_info->bytes_total = 0;
 			progress->progress_info->files_total = 0;
@@ -2525,41 +2671,51 @@ gnome_vfs_xfer_uri_internal (const GList
 
 			if (move) {
 				g_assert (!link);
-				result = move_items (source_uri_list, target_uri_list,
-						     xfer_options, &error_mode, &overwrite_mode, 
-						     progress);
+				result = move_items (
+					source_uri_list,
+					target_uri_list,
+					xfer_options,
+					&error_mode,
+					&overwrite_mode, 
+					progress,
+					clobber_uristr_set);
 				if (result == GNOME_VFS_OK && merge_source_uri_list != NULL) {
-					result = copy_items (merge_source_uri_list, merge_target_uri_list,
-							     xfer_options, &error_mode, overwrite_mode, 
-							     progress, &source_uri_list_copied);
+					result = copy_items (
+						merge_source_uri_list,
+						merge_target_uri_list,
+						xfer_options,
+						&error_mode,
+						overwrite_mode,
+						progress,
+						clobber_uristr_set);
 				}
 			} else if (link) {
-				result = link_items (source_uri_list, target_uri_list,
-						     xfer_options, &error_mode, &overwrite_mode,
-						     progress);
+				result = link_items (
+					source_uri_list,
+					target_uri_list,
+					xfer_options,
+					&error_mode,
+					&overwrite_mode,
+					progress,
+					clobber_uristr_set);
 			} else {
-				result = copy_items (source_uri_list, target_uri_list,
-						     xfer_options, &error_mode, overwrite_mode, 
-						     progress, &source_uri_list_copied);
-			}
-			
-			if (result == GNOME_VFS_OK) {
-				if (xfer_options & GNOME_VFS_XFER_REMOVESOURCE
-				    && !link) {
-					call_progress (progress, GNOME_VFS_XFER_PHASE_CLEANUP);
-					result = gnome_vfs_xfer_delete_items_common ( 
-						 	source_uri_list_copied,
-						 	error_mode, xfer_options, progress);
-				}
+				result = copy_items (
+					source_uri_list,
+					target_uri_list,
+					xfer_options,
+					&error_mode,
+					overwrite_mode,
+					progress,
+					clobber_uristr_set);
 			}
 		}
+		g_hash_table_destroy (clobber_uristr_set);
 	}
 
 	gnome_vfs_uri_list_free (source_uri_list);
 	gnome_vfs_uri_list_free (target_uri_list);
 	gnome_vfs_uri_list_free (merge_source_uri_list);
 	gnome_vfs_uri_list_free (merge_target_uri_list);
-	gnome_vfs_uri_list_free (source_uri_list_copied);
 
 	return result;
 }


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]