rpms/file-roller/F-12 file-roller-2.28.2-gvfs-fuse.patch, NONE, 1.1 file-roller.spec, 1.164, 1.165

Tomas Bzatek tbzatek at fedoraproject.org
Tue May 18 13:07:37 UTC 2010


Author: tbzatek

Update of /cvs/extras/rpms/file-roller/F-12
In directory cvs01.phx2.fedoraproject.org:/tmp/cvs-serv18352

Modified Files:
	file-roller.spec 
Added Files:
	file-roller-2.28.2-gvfs-fuse.patch 
Log Message:
* Mon May 17 2010 Tomas Bzatek <tbzatek at redhat.com> 2.28.2-3
- Fix archive handling on remote GIO mounts without running fuse daemon (#527045, #518510)


file-roller-2.28.2-gvfs-fuse.patch:
 fr-archive.c |  593 +++++++++++++++++++++++++++++++++++++++++++++++++++++------
 fr-archive.h |    2 
 fr-window.c  |    8 
 gio-utils.c  |  155 +++++++++------
 gio-utils.h  |    2 
 5 files changed, 641 insertions(+), 119 deletions(-)

--- NEW FILE file-roller-2.28.2-gvfs-fuse.patch ---
diff -up file-roller-2.28.2/src/fr-archive.c.gvfs-fuse file-roller-2.28.2/src/fr-archive.c
--- file-roller-2.28.2/src/fr-archive.c.gvfs-fuse	2009-12-15 09:46:24.000000000 +0100
+++ file-roller-2.28.2/src/fr-archive.c	2010-05-17 16:59:32.000000000 +0200
@@ -114,16 +114,51 @@ struct _FrArchivePrivData {
 	FakeLoadFunc         add_is_stoppable_func;         /* Returns whether the add operation is
 							     * stoppable. */
 	gpointer             add_is_stoppable_data;
-  	GCancellable        *cancellable;
+	GCancellable        *cancellable;
 	char                *temp_dir;
 	gboolean             continue_adding_dropped_items;
 	DroppedItemsData    *dropped_items_data;
 
+	char                *temp_extraction_dir;
 	char                *extraction_destination;
+	gboolean             remote_extraction;
 	gboolean             extract_here;
 };
 
 
+typedef struct {
+	FrArchive      *archive;
+	char           *uri;
+	FrAction        action;
+	GList          *file_list;
+	char           *base_uri;
+	char           *dest_dir;
+	gboolean        update;
+	char           *tmp_dir;
+	guint           source_id;
+	char           *password;
+	gboolean        encrypt_header;
+	FrCompression   compression;
+	guint           volume_size;
+} XferData;
+
+
+static void
+xfer_data_free (XferData *data)
+{
+	if (data == NULL)
+		return;
+
+	g_free (data->uri);
+	g_free (data->password);
+	path_list_free (data->file_list);
+	g_free (data->base_uri);
+	g_free (data->dest_dir);
+	g_free (data->tmp_dir);
+	g_free (data);
+}
+
+
 #define MAX_CHUNK_LEN (NCARGS * 2 / 3) /* Max command line length */
 #define UNKNOWN_TYPE "application/octet-stream"
 #define SAME_FS (FALSE)
@@ -322,6 +357,8 @@ static void
 fr_archive_init (FrArchive *archive)
 {
 	archive->file = NULL;
+	archive->local_copy = NULL;
+	archive->is_remote = FALSE;
 	archive->command = NULL;
 	archive->is_compressed_file = FALSE;
 	archive->can_create_compressed_file = FALSE;
@@ -333,6 +370,7 @@ fr_archive_init (FrArchive *archive)
 	archive->priv->add_is_stoppable_data = NULL;
 
 	archive->priv->extraction_destination = NULL;
+	archive->priv->temp_extraction_dir = NULL;
 	archive->priv->cancellable = g_cancellable_new ();
 
 	archive->process = fr_process_new ();
@@ -350,18 +388,73 @@ fr_archive_new (void)
 }
 
 
+static GFile *
+get_local_copy_for_file (GFile *remote_file)
+{
+	char  *temp_dir;
+	GFile *local_copy = NULL;
+
+	temp_dir = get_temp_work_dir (NULL);
+	if (temp_dir != NULL) {
+		char  *archive_name;
+		char  *local_path;
+
+		archive_name = g_file_get_basename (remote_file);
+		local_path = g_build_filename (temp_dir, archive_name, NULL);
+		local_copy = g_file_new_for_path (local_path);
+
+		g_free (local_path);
+		g_free (archive_name);
+	}
+	g_free (temp_dir);
+
+	return local_copy;
+}
+
+
 static void
 fr_archive_set_uri (FrArchive  *archive,
 		    const char *uri)
 {
+	if ((archive->local_copy != NULL) && archive->is_remote) {
+		GFile  *temp_folder;
+		GError *err = NULL;
+
+		g_file_delete (archive->local_copy, NULL, &err);
+		if (err != NULL) {
+			g_warning ("Failed to delete the local copy: %s", err->message);
+			g_clear_error (&err);
+		}
+
+		temp_folder = g_file_get_parent (archive->local_copy);
+		g_file_delete (temp_folder, NULL, &err);
+		if (err != NULL) {
+			g_warning ("Failed to delete temp folder: %s", err->message);
+			g_clear_error (&err);
+		}
+
+		g_object_unref (temp_folder);
+	}
+
 	if (archive->file != NULL) {
 		g_object_unref (archive->file);
 		archive->file = NULL;
 	}
+	if (archive->local_copy != NULL) {
+		g_object_unref (archive->local_copy);
+		archive->local_copy = NULL;
+	}
 	archive->content_type = NULL;
 
-	if (uri != NULL)
-		archive->file = g_file_new_for_uri (uri);
+	if (uri == NULL)
+		return;
+
+	archive->file = g_file_new_for_uri (uri);
+	archive->is_remote = ! g_file_has_uri_scheme (archive->file, "file");
+	if (archive->is_remote)
+		archive->local_copy = get_local_copy_for_file (archive->file);
+	else
+		archive->local_copy = g_file_dup (archive->file);
 }
 
 
@@ -395,6 +488,7 @@ fr_archive_finalize (GObject *object)
 		dropped_items_data_free (archive->priv->dropped_items_data);
 		archive->priv->dropped_items_data = NULL;
 	}
+	g_free (archive->priv->temp_extraction_dir);
 	g_free (archive->priv->extraction_destination);
 	g_free (archive->priv);
 
@@ -500,7 +594,7 @@ create_command_from_type (FrArchive     
 	if (command_type == 0)
 		return FALSE;
 
-	filename = g_file_get_path (archive->file);
+	filename = g_file_get_path (archive->local_copy);
 	archive->command = FR_COMMAND (g_object_new (command_type,
 					             "process", archive->process,
 					             "filename", filename,
@@ -587,6 +681,79 @@ action_started (FrCommand *command,
 }
 
 
+/* -- copy_to_remote_location -- */
+
+
+static void
+fr_archive_copy_done (FrArchive *archive,
+		      FrAction   action,
+		      GError    *error)
+{
+	FrProcErrorType  error_type = FR_PROC_ERROR_NONE;
+	const char      *error_details = NULL;
+
+	if (error != NULL) {
+		error_type = (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED) ? FR_PROC_ERROR_STOPPED : FR_PROC_ERROR_GENERIC);
+		error_details = error->message;
+	}
+	fr_archive_action_completed (archive, action, error_type, error_details);
+}
+
+
+static void
+copy_to_remote_location_done (GError   *error,
+			      gpointer  user_data)
+{
+	XferData *xfer_data = user_data;
+
+	fr_archive_copy_done (xfer_data->archive, xfer_data->action, error);
+	xfer_data_free (xfer_data);
+}
+
+
+static void
+copy_to_remote_location_progress (goffset   current_file,
+                                  goffset   total_files,
+                                  GFile    *source,
+                                  GFile    *destination,
+                                  goffset   current_num_bytes,
+                                  goffset   total_num_bytes,
+                                  gpointer  user_data)
+{
+	XferData *xfer_data = user_data;
+
+	g_signal_emit (G_OBJECT (xfer_data->archive),
+		       fr_archive_signals[PROGRESS],
+		       0,
+		       (double) current_num_bytes / total_num_bytes);
+}
+
+
+static void
+copy_to_remote_location (FrArchive  *archive,
+			 FrAction    action)
+{
+	XferData *xfer_data;
+
+	xfer_data = g_new0 (XferData, 1);
+	xfer_data->archive = archive;
+	xfer_data->action = action;
+
+	g_copy_file_async (archive->local_copy,
+			   archive->file,
+			   G_FILE_COPY_OVERWRITE,
+			   G_PRIORITY_DEFAULT,
+			   archive->priv->cancellable,
+			   copy_to_remote_location_progress,
+			   xfer_data,
+			   copy_to_remote_location_done,
+			   xfer_data);
+}
+
+
+/* -- copy_extracted_files_to_destination -- */
+
+
 static void
 move_here (FrArchive *archive)
 {
@@ -655,6 +822,61 @@ move_here (FrArchive *archive)
 }
 
 
+static void
+copy_extracted_files_done (GError   *error,
+			   gpointer  user_data)
+{
+	FrArchive *archive = user_data;
+
+	remove_local_directory (archive->priv->temp_extraction_dir);
+	g_free (archive->priv->temp_extraction_dir);
+	archive->priv->temp_extraction_dir = NULL;
+
+	fr_archive_action_completed (archive,
+				     FR_ACTION_COPYING_FILES_TO_REMOTE,
+				     FR_PROC_ERROR_NONE,
+				     NULL);
+
+	if ((error == NULL) && (archive->priv->extract_here))
+		move_here (archive);
+
+	fr_archive_copy_done (archive, FR_ACTION_EXTRACTING_FILES, error);
+}
+
+
+static void
+copy_extracted_files_progress (goffset   current_file,
+                               goffset   total_files,
+                               GFile    *source,
+                               GFile    *destination,
+                               goffset   current_num_bytes,
+                               goffset   total_num_bytes,
+                               gpointer  user_data)
+{
+	FrArchive *archive = user_data;
+
+	g_signal_emit (G_OBJECT (archive),
+		       fr_archive_signals[PROGRESS],
+		       0,
+		       (double) current_file / (total_files + 1));
+}
+
+
+static void
+copy_extracted_files_to_destination (FrArchive *archive)
+{
+	g_directory_copy_async (archive->priv->temp_extraction_dir,
+				archive->priv->extraction_destination,
+				G_FILE_COPY_OVERWRITE,
+				G_PRIORITY_DEFAULT,
+				archive->priv->cancellable,
+				copy_extracted_files_progress,
+				archive,
+				copy_extracted_files_done,
+				archive);
+}
+
+
 static void add_dropped_items (DroppedItemsData *data);
 
 
@@ -671,6 +893,11 @@ fr_archive_change_name (FrArchive  *arch
 	g_object_unref (archive->file);
 	archive->file = g_file_get_child (parent, name);
 	g_object_unref (parent);
+
+	parent = g_file_get_parent (archive->local_copy);
+	g_object_unref (archive->local_copy);
+	archive->local_copy = g_file_get_child (parent, name);
+	g_object_unref (parent);
 }
 
 
@@ -685,6 +912,15 @@ action_performed (FrCommand   *command,
 #endif
 
 	switch (action) {
+	case FR_ACTION_DELETING_FILES:
+		if (error->type == FR_PROC_ERROR_NONE) {
+			if (! g_file_has_uri_scheme (archive->file, "file")) {
+				copy_to_remote_location (archive, action);
+				return;
+			}
+		}
+		break;
+
 	case FR_ACTION_ADDING_FILES:
 		if (error->type == FR_PROC_ERROR_NONE) {
 			fr_archive_remove_temp_work_dir (archive);
@@ -700,15 +936,33 @@ action_performed (FrCommand   *command,
 			 * original name */
 			if (archive->command->multi_volume)
 				fr_archive_change_name (archive, archive->command->filename);
+			if (! g_file_has_uri_scheme (archive->file, "file")) {
+				copy_to_remote_location (archive, action);
+				return;
+			}
 		}
 		break;
 
 	case FR_ACTION_EXTRACTING_FILES:
 		if (error->type == FR_PROC_ERROR_NONE) {
-			if (archive->priv->extract_here)
+			if (archive->priv->remote_extraction) {
+				copy_extracted_files_to_destination (archive);
+				return;
+			}
+			else if (archive->priv->extract_here)
 				move_here (archive);
 		}
 		else {
+			/* if an error occurred during extraction remove the
+			 * temp extraction dir, if used. */
+			g_print ("action_performed: ERROR!\n");
+
+			if ((archive->priv->remote_extraction) && (archive->priv->temp_extraction_dir != NULL)) {
+				remove_local_directory (archive->priv->temp_extraction_dir);
+				g_free (archive->priv->temp_extraction_dir);
+				archive->priv->temp_extraction_dir = NULL;
+			}
+
 			if (archive->priv->extract_here)
 				remove_directory (archive->priv->extraction_destination);
 		}
@@ -816,7 +1070,7 @@ fr_archive_create (FrArchive  *archive,
 
 	tmp_command = archive->command;
 
-	mime_type = get_mime_type_from_filename (archive->file);
+	mime_type = get_mime_type_from_filename (archive->local_copy);
 	if (! create_command_to_create_archive (archive, mime_type)) {
 		archive->command = tmp_command;
 		return FALSE;
@@ -870,11 +1124,11 @@ load_local_archive (FrArchive  *archive,
 
 	tmp_command = archive->command;
 
-	mime_type = get_mime_type_from_filename (archive->file);
+	mime_type = get_mime_type_from_filename (archive->local_copy);
 	if (! create_command_to_load_archive (archive, mime_type)) {
-		mime_type = get_mime_type_from_content (archive->file);
+		mime_type = get_mime_type_from_content (archive->local_copy);
 		if (! create_command_to_load_archive (archive, mime_type)) {
-			mime_type = get_mime_type_from_magic_numbers (archive->file);
+			mime_type = get_mime_type_from_magic_numbers (archive->local_copy);
 			if (! create_command_to_load_archive (archive, mime_type)) {
 				archive->command = tmp_command;
 				fr_archive_action_completed (archive,
@@ -912,6 +1166,86 @@ load_local_archive (FrArchive  *archive,
 }
 
 
+static void
+copy_remote_file_done (GError   *error,
+		       gpointer  user_data)
+{
+	XferData *xfer_data = user_data;
+
+	if (error != NULL)
+		fr_archive_copy_done (xfer_data->archive, FR_ACTION_LOADING_ARCHIVE, error);
+	else
+		load_local_archive (xfer_data->archive, xfer_data->uri, xfer_data->password);
+	xfer_data_free (xfer_data);
+}
+
+
+static void
+copy_remote_file_progress (goffset   current_file,
+                           goffset   total_files,
+                           GFile    *source,
+                           GFile    *destination,
+                           goffset   current_num_bytes,
+                           goffset   total_num_bytes,
+                           gpointer  user_data)
+{
+	XferData *xfer_data = user_data;
+
+	g_signal_emit (G_OBJECT (xfer_data->archive),
+		       fr_archive_signals[PROGRESS],
+		       0,
+		       (double) current_num_bytes / total_num_bytes);
+}
+
+
+static gboolean
+copy_remote_file_done_cb (gpointer user_data)
+{
+	XferData *xfer_data = user_data;
+
+	g_source_remove (xfer_data->source_id);
+	copy_remote_file_done (NULL, xfer_data);
+	return FALSE;
+}
+
+
+static void
+copy_remote_file (FrArchive  *archive,
+		  const char *password)
+{
+	XferData *xfer_data;
+
+	if (! g_file_query_exists (archive->file, NULL)) {
+		GError *error;
+		error = g_error_new (G_IO_ERROR, G_IO_ERROR_NOT_FOUND, _("The file doesn't exist"));
+		fr_archive_copy_done (archive, FR_ACTION_LOADING_ARCHIVE, error);
+		g_error_free (error);
+		return;
+	}
+
+	xfer_data = g_new0 (XferData, 1);
+	xfer_data->archive = archive;
+	xfer_data->uri = g_file_get_uri (archive->file);
+	if (password != NULL)
+		xfer_data->password = g_strdup (password);
+
+	if (! archive->is_remote) {
+		xfer_data->source_id = g_idle_add (copy_remote_file_done_cb, xfer_data);
+		return;
+	}
+
+	g_copy_file_async (archive->file,
+			   archive->local_copy,
+			   G_FILE_COPY_OVERWRITE,
+			   G_PRIORITY_DEFAULT,
+			   archive->priv->cancellable,
+			   copy_remote_file_progress,
+			   xfer_data,
+			   copy_remote_file_done,
+			   xfer_data);
+}
+
+
 gboolean
 fr_archive_load (FrArchive  *archive,
 		 const char *uri,
@@ -925,7 +1259,7 @@ fr_archive_load (FrArchive  *archive,
 		       FR_ACTION_LOADING_ARCHIVE);
 
 	fr_archive_set_uri (archive, uri);
-	load_local_archive (archive, uri, password);
+	copy_remote_file (archive, password);
 
 	return TRUE;
 }
@@ -944,7 +1278,7 @@ fr_archive_load_local (FrArchive  *archi
 		       FR_ACTION_LOADING_ARCHIVE);
 
 	fr_archive_set_uri (archive, uri);
-	load_local_archive (archive, uri, password);
+	copy_remote_file (archive, password);
 
 	return TRUE;
 }
@@ -1111,18 +1445,12 @@ convert_to_local_file_list (GList *file_
 	GList *scan;
 
 	for (scan = file_list; scan; scan = scan->next) {
-		GFile *file;
-		char  *uri = scan->data;
-		char  *local_filename;
-
-		file = g_file_new_for_uri (uri);
-		local_filename = g_file_get_path (file);
-		if (local_filename == NULL)
-			local_filename = g_strdup (uri);
+		char *uri = scan->data;
+		char *local_filename;
+
+		local_filename = g_uri_unescape_string (uri, G_URI_RESERVED_CHARS_ALLOWED_IN_PATH);
 		if (local_filename != NULL)
 			local_file_list = g_list_prepend (local_file_list, local_filename);
-
-		g_object_unref (file);
 	}
 
 	return local_file_list;
@@ -1437,6 +1765,145 @@ fr_archive_add_local_files (FrArchive   
 }
 
 
+static void
+copy_remote_files_done (GError   *error,
+			gpointer  user_data)
+{
+	XferData *xfer_data = user_data;
+
+	fr_archive_copy_done (xfer_data->archive, FR_ACTION_COPYING_FILES_FROM_REMOTE, error);
+
+	if (error == NULL)
+		fr_archive_add_local_files (xfer_data->archive,
+					    xfer_data->file_list,
+					    xfer_data->tmp_dir,
+					    xfer_data->dest_dir,
+					    FALSE,
+					    xfer_data->password,
+					    xfer_data->encrypt_header,
+					    xfer_data->compression,
+					    xfer_data->volume_size);
+	xfer_data_free (xfer_data);
+}
+
+
+static void
+copy_remote_files_progress (goffset   current_file,
+                            goffset   total_files,
+                            GFile    *source,
+                            GFile    *destination,
+                            goffset   current_num_bytes,
+                            goffset   total_num_bytes,
+                            gpointer  user_data)
+{
+	XferData *xfer_data = user_data;
+
+	g_signal_emit (G_OBJECT (xfer_data->archive),
+		       fr_archive_signals[PROGRESS],
+		       0,
+		       (double) current_file / (total_files + 1));
+}
+
+
+static void
+copy_remote_files (FrArchive     *archive,
+		   GList         *file_list,
+		   const char    *base_uri,
+		   const char    *dest_dir,
+		   gboolean       update,
+		   const char    *password,
+		   gboolean       encrypt_header,
+		   FrCompression  compression,
+		   guint          volume_size,
+		   const char    *tmp_dir)
+{
+	GList      *sources = NULL, *destinations = NULL;
+	GHashTable *created_folders;
+	GList      *scan;
+	XferData   *xfer_data;
+
+	created_folders = g_hash_table_new_full (g_str_hash, g_str_equal, (GDestroyNotify) g_free, NULL);
+	for (scan = file_list; scan; scan = scan->next) {
+		char  *partial_filename = scan->data;
+		char  *local_uri;
+		char  *local_folder_uri;
+		char  *remote_uri;
+
+		local_uri = g_strconcat ("file://", tmp_dir, "/", partial_filename, NULL);
+		local_folder_uri = remove_level_from_path (local_uri);
+		if (g_hash_table_lookup (created_folders, local_folder_uri) == NULL) {
+			GError *error = NULL;
+			if (! ensure_dir_exists (local_folder_uri, 0755, &error)) {
+				g_free (local_folder_uri);
+				g_free (local_uri);
+				gio_file_list_free (sources);
+				gio_file_list_free (destinations);
+				g_hash_table_destroy (created_folders);
+
+				fr_archive_action_completed (archive,
+							     FR_ACTION_COPYING_FILES_FROM_REMOTE,
+							     FR_PROC_ERROR_GENERIC,
+							     error->message);
+				g_clear_error (&error);
+				return;
+			}
+
+			g_hash_table_insert (created_folders, local_folder_uri, GINT_TO_POINTER (1));
+		}
+		else
+			g_free (local_folder_uri);
+
+		remote_uri = g_strconcat (base_uri, "/", partial_filename, NULL);
+		sources = g_list_append (sources, g_file_new_for_uri (remote_uri));
+		g_free (remote_uri);
+
+		destinations = g_list_append (destinations, g_file_new_for_uri (local_uri));
+		g_free (local_uri);
+	}
+	g_hash_table_destroy (created_folders);
+
+	xfer_data = g_new0 (XferData, 1);
+	xfer_data->archive = archive;
+	xfer_data->file_list = path_list_dup (file_list);
+	xfer_data->base_uri = g_strdup (base_uri);
+	xfer_data->dest_dir = g_strdup (dest_dir);
+	xfer_data->update = update;
+	xfer_data->dest_dir = g_strdup (dest_dir);
+	xfer_data->password = g_strdup (password);
+	xfer_data->encrypt_header = encrypt_header;
+	xfer_data->compression = compression;
+	xfer_data->volume_size = volume_size;
+	xfer_data->tmp_dir = g_strdup (tmp_dir);
+
+	g_signal_emit (G_OBJECT (archive),
+		       fr_archive_signals[START],
+		       0,
+		       FR_ACTION_COPYING_FILES_FROM_REMOTE);
+
+	g_copy_files_async (sources,
+			    destinations,
+			    G_FILE_COPY_OVERWRITE,
+			    G_PRIORITY_DEFAULT,
+			    archive->priv->cancellable,
+			    copy_remote_files_progress,
+			    xfer_data,
+			    copy_remote_files_done,
+			    xfer_data);
+
+	gio_file_list_free (sources);
+	gio_file_list_free (destinations);
+}
+
+
+static char *
+fr_archive_get_temp_work_dir (FrArchive *archive)
+{
+	fr_archive_remove_temp_work_dir (archive);
+	archive->priv->temp_dir = get_temp_work_dir (NULL);
+	return archive->priv->temp_dir;
+}
+
+
 void
 fr_archive_add_files (FrArchive     *archive,
 		      GList         *file_list,
@@ -1448,23 +1915,30 @@ fr_archive_add_files (FrArchive     *arc
 		      FrCompression  compression,
 		      guint          volume_size)
 {
-	GFile *file;
-	char  *local_dir;
-
-	file = g_file_new_for_uri (base_dir);
-	local_dir = g_file_get_path (file);
-	fr_archive_add_local_files (archive,
-				    file_list,
-				    local_dir,
-				    dest_dir,
-				    update,
-				    password,
-				    encrypt_header,
-				    compression,
-				    volume_size);
-
-	g_free (local_dir);
-	g_object_unref (file);
+	if (uri_is_local (base_dir)) {
+		char *local_dir = g_filename_from_uri (base_dir, NULL, NULL);
+		fr_archive_add_local_files (archive,
+					    file_list,
+					    local_dir,
+					    dest_dir,
+					    update,
+					    password,
+					    encrypt_header,
+					    compression,
+					    volume_size);
+		g_free (local_dir);
+	}
+	else
+		copy_remote_files (archive,
+				   file_list,
+				   base_dir,
+				   dest_dir,
+				   update,
+				   password,
+				   encrypt_header,
+				   compression,
+				   volume_size,
+				   fr_archive_get_temp_work_dir (archive));
 }
 
 
@@ -2669,25 +3143,38 @@ fr_archive_extract (FrArchive  *archive,
 		    gboolean    junk_paths,
 		    const char *password)
 {
-	GFile *file;
-	char  *local_destination;
-
 	g_free (archive->priv->extraction_destination);
 	archive->priv->extraction_destination = g_strdup (destination);
 
-	file = g_file_new_for_uri (destination);
-	local_destination = g_file_get_path (file);
-	fr_archive_extract_to_local (archive,
-				     file_list,
-				     local_destination,
-				     base_dir,
-				     skip_older,
-				     overwrite,
-				     junk_paths,
-				     password);
+	g_free (archive->priv->temp_extraction_dir);
+	archive->priv->temp_extraction_dir = NULL;
 
-	g_free (local_destination);
-	g_object_unref (file);
+	archive->priv->remote_extraction = ! uri_is_local (destination);
+	if (archive->priv->remote_extraction) {
+		archive->priv->temp_extraction_dir = get_temp_work_dir (NULL);
+		fr_archive_extract_to_local (archive,
+					     file_list,
+					     archive->priv->temp_extraction_dir,
+					     base_dir,
+					     skip_older,
+					     overwrite,
+					     junk_paths,
+					     password);
+	}
+	else {
+		char *local_destination;
+
+		local_destination = g_filename_from_uri (destination, NULL, NULL);
+		fr_archive_extract_to_local (archive,
+					     file_list,
+					     local_destination,
+					     base_dir,
+					     skip_older,
+					     overwrite,
+					     junk_paths,
+					     password);
+		g_free (local_destination);
+	}
 }
 
 
diff -up file-roller-2.28.2/src/fr-archive.h.gvfs-fuse file-roller-2.28.2/src/fr-archive.h
--- file-roller-2.28.2/src/fr-archive.h.gvfs-fuse	2009-11-07 19:38:19.000000000 +0100
+++ file-roller-2.28.2/src/fr-archive.h	2010-05-17 16:57:20.000000000 +0200
@@ -44,6 +44,8 @@ struct _FrArchive {
 	GObject  __parent;
 
 	GFile       *file;
+	GFile       *local_copy;
+	gboolean     is_remote;
 	const char  *content_type;
 	FrCommand   *command;
 	FrProcess   *process;
diff -up file-roller-2.28.2/src/fr-window.c.gvfs-fuse file-roller-2.28.2/src/fr-window.c
--- file-roller-2.28.2/src/fr-window.c.gvfs-fuse	2009-12-15 09:47:21.000000000 +0100
+++ file-roller-2.28.2/src/fr-window.c	2010-05-17 16:57:20.000000000 +0200
@@ -4185,14 +4185,14 @@ get_selection_data_from_clipboard_data (
 		      			FrClipboardData *data)
 {
 	GString *list;
-	char    *archive_uri;
+	char    *local_filename;
 	GList   *scan;
 
 	list = g_string_new (NULL);
 
-	archive_uri = g_file_get_uri (window->archive->file);
-	g_string_append (list, archive_uri);
-	g_free (archive_uri);
+	local_filename = g_file_get_uri (window->archive->local_copy);
+	g_string_append (list, local_filename);
+	g_free (local_filename);
 
 	g_string_append (list, "\r\n");
 	if (window->priv->password != NULL)
diff -up file-roller-2.28.2/src/gio-utils.c.gvfs-fuse file-roller-2.28.2/src/gio-utils.c
--- file-roller-2.28.2/src/gio-utils.c.gvfs-fuse	2009-11-07 19:38:19.000000000 +0100
+++ file-roller-2.28.2/src/gio-utils.c	2010-05-17 16:57:20.000000000 +0200
@@ -127,7 +127,7 @@ filter_empty (Filter *filter)
 
 
 typedef struct {
-	char                 *base_directory;
+	GFile                *base_directory;
 	gboolean              recursive;
 	gboolean              follow_links;
 	StartDirCallback      start_dir_func;
@@ -153,7 +153,8 @@ for_each_child_data_free (ForEachChildDa
 	if (fec == NULL)
 		return;
 
-	g_free (fec->base_directory);
+	if (fec->base_directory != NULL)
+		g_object_unref (fec->base_directory);
 	if (fec->current != NULL)
 		g_object_unref (fec->current);
 	if (fec->already_visited)
@@ -172,7 +173,7 @@ for_each_child_done_cb (gpointer user_da
 	g_source_remove (fec->source_id);
 	if (fec->current != NULL) {
 		g_object_unref (fec->current);
-		 fec->current = NULL;
+		fec->current = NULL;
 	}
 	if (fec->done_func)
 		fec->done_func (fec->error, fec->user_data);
@@ -212,8 +213,8 @@ for_each_child_start (ForEachChildData *
 
 
 static void
-for_each_child_set_current (ForEachChildData *fec,
-			    const char       *directory)
+for_each_child_set_current_uri (ForEachChildData *fec,
+				const char       *directory)
 {
 	if (fec->current != NULL)
 		g_object_unref (fec->current);
@@ -222,6 +223,15 @@ for_each_child_set_current (ForEachChild
 
 
 static void
+for_each_child_set_current (ForEachChildData *fec,
+			    GFile            *directory)
+{
+	if (fec->current != NULL)
+		g_object_unref (fec->current);
+	fec->current = g_file_dup (directory);
+}
+
+static void
 for_each_child_start_next_sub_directory (ForEachChildData *fec)
 {
 	char *sub_directory = NULL;
@@ -236,7 +246,7 @@ for_each_child_start_next_sub_directory 
 	}
 
 	if (sub_directory != NULL) {
-		for_each_child_set_current (fec, sub_directory);
+		for_each_child_set_current_uri (fec, sub_directory);
 		for_each_child_start (fec);
 	}
 	else
@@ -276,7 +286,6 @@ for_each_child_next_files_ready (GObject
 {
 	ForEachChildData *fec = user_data;
 	GList            *children, *scan;
-	char             *current_directory;
 
 	children = g_file_enumerator_next_files_finish (fec->enumerator,
                                                         result,
@@ -291,16 +300,16 @@ for_each_child_next_files_ready (GObject
 		return;
 	}
 
-	current_directory = g_file_get_uri (fec->current);
 	for (scan = children; scan; scan = scan->next) {
 		GFileInfo *child_info = scan->data;
-		char      *name, *uri;
+		GFile     *f;
+		char      *uri;
 
-		name = g_uri_escape_string (g_file_info_get_name (child_info), G_URI_RESERVED_CHARS_ALLOWED_IN_PATH_ELEMENT, FALSE);
-		uri = g_strconcat (current_directory, "/", name, NULL);
+		f = g_file_get_child (fec->current, g_file_info_get_name (child_info));
+		uri = g_file_get_uri (f);
 
 		if (g_file_info_get_file_type (child_info) == G_FILE_TYPE_DIRECTORY) {
-			/* avoid to visit a directory more than ones */
+			/* avoid to visit a directory more than once */
 
 			if (g_hash_table_lookup (fec->already_visited, uri) == NULL) {
 				char *sub_directory;
@@ -314,9 +323,8 @@ for_each_child_next_files_ready (GObject
 		fec->for_each_file_func (uri, child_info, fec->user_data);
 
 		g_free (uri);
-		g_free (name);
+		g_object_unref (f);
 	}
-	g_free (current_directory);
 
 	g_file_enumerator_next_files_async (fec->enumerator,
                                             N_FILES_PER_REQUEST,
@@ -404,7 +412,7 @@ for_each_child_start_current (ForEachChi
  * Each callback uses the same @user_data additional parameter.
  */
 void
-g_directory_foreach_child (const char           *directory,
+g_directory_foreach_child (GFile                *directory,
 			   gboolean              recursive,
 			   gboolean              follow_links,
 			   GCancellable         *cancellable,
@@ -419,7 +427,7 @@ g_directory_foreach_child (const char   
 
 	fec = g_new0 (ForEachChildData, 1);
 
-	fec->base_directory = g_strdup (directory);
+	fec->base_directory = g_object_ref (directory);
 	fec->recursive = recursive;
 	fec->follow_links = follow_links;
 	fec->cancellable = cancellable;
@@ -443,8 +451,8 @@ g_directory_foreach_child (const char   
 typedef struct {
 	GList             *files;
 	GList             *dirs;
-	char              *directory;
-	char              *base_dir;
+	GFile             *directory;
+	GFile             *base_dir;
 	GCancellable      *cancellable;
 	ListReadyCallback  done_func;
 	gpointer           done_data;
@@ -469,8 +477,10 @@ get_file_list_data_free (GetFileListData
 	path_list_free (gfl->files);
 	path_list_free (gfl->dirs);
 	path_list_free (gfl->to_visit);
-	g_free (gfl->directory);
-	g_free (gfl->base_dir);
+	if (gfl->directory != NULL)
+		g_object_unref (gfl->directory);
+	if (gfl->base_dir != NULL)
+		g_object_unref (gfl->base_dir);
 	g_free (gfl);
 }
 
@@ -479,27 +489,25 @@ get_file_list_data_free (GetFileListData
 
 
 static GList*
-get_relative_file_list (GList      *rel_list,
-			GList      *file_list,
-			const char *base_dir)
+get_relative_file_list (GList *rel_list,
+			GList *file_list,
+			GFile *base_dir)
 {
 	GList *scan;
-	int    base_len;
 
 	if (base_dir == NULL)
 		return NULL;
 
-	base_len = 0;
-	if (strcmp (base_dir, "/") != 0)
-		base_len = strlen (base_dir);
-
 	for (scan = file_list; scan; scan = scan->next) {
-		char *full_path = scan->data;
-
-		if (path_in_path (base_dir, full_path)) {
-			char *rel_path = g_uri_unescape_string (full_path + base_len + 1, NULL);
-			rel_list = g_list_prepend (rel_list, rel_path);
-		}
+		char  *full_path = scan->data;
+		GFile *f;
+		char  *relative_path;
+
+		f = g_file_new_for_commandline_arg (full_path);
+		relative_path = g_file_get_relative_path (base_dir, f);
+		if (relative_path != NULL)
+			rel_list = g_list_prepend (rel_list, relative_path);
+		g_object_unref (f);
 	}
 
 	return rel_list;
@@ -565,6 +573,7 @@ get_file_list_done (GError   *error,
 	GetFileListData *gfl = user_data;
 	GHashTable      *h_dirs;
 	GList           *scan;
+	char            *uri;
 
 	gfl->files = g_list_reverse (gfl->files);
 	gfl->dirs = g_list_reverse (gfl->dirs);
@@ -582,7 +591,7 @@ get_file_list_done (GError   *error,
 	if (gfl->base_dir != NULL) {
 		char *dir;
 
-		dir = g_strdup (gfl->base_dir);
+		dir = g_file_get_uri (gfl->base_dir);
 		gfl->dirs = g_list_prepend (gfl->dirs, dir);
 		g_hash_table_insert (h_dirs, dir, GINT_TO_POINTER (1));
 	}
@@ -594,11 +603,13 @@ get_file_list_done (GError   *error,
 	for (scan = gfl->dirs; scan; scan = scan->next)
 		g_hash_table_insert (h_dirs, (char*)scan->data, GINT_TO_POINTER (1));
 
-	gfl->dirs = g_list_concat (gfl->dirs, get_dir_list_from_file_list (h_dirs, gfl->base_dir, gfl->files, FALSE));
+	uri = g_file_get_uri (gfl->base_dir);
+	gfl->dirs = g_list_concat (gfl->dirs, get_dir_list_from_file_list (h_dirs, uri, gfl->files, FALSE));
 
 	if (filter_empty (gfl->include_filter))
-		gfl->dirs = g_list_concat (gfl->dirs, get_dir_list_from_file_list (h_dirs, gfl->base_dir, gfl->dirs, TRUE));
+		gfl->dirs = g_list_concat (gfl->dirs, get_dir_list_from_file_list (h_dirs, uri, gfl->dirs, TRUE));
 
+	g_free (uri);
 	/**/
 
 	if (error == NULL) {
@@ -680,8 +691,8 @@ g_directory_list_async (const char      
 	FilterOptions    filter_options;
 
 	gfl = g_new0 (GetFileListData, 1);
-	gfl->directory = g_strdup (directory);
-	gfl->base_dir = g_strdup (base_dir);
+	gfl->directory = g_file_new_for_commandline_arg (directory);
+	gfl->base_dir = g_file_new_for_commandline_arg (base_dir);
 	gfl->done_func = done_func;
 	gfl->done_data = done_data;
 
@@ -696,7 +707,7 @@ g_directory_list_async (const char      
 	gfl->exclude_filter = filter_new (exclude_files, ignorecase ? FILTER_IGNORECASE : FILTER_DEFAULT);
 	gfl->exclude_folders_filter = filter_new (exclude_folders, ignorecase ? FILTER_IGNORECASE : FILTER_DEFAULT);
 
-	g_directory_foreach_child (directory,
+	g_directory_foreach_child (gfl->directory,
 				   recursive,
 				   follow_links,
 				   cancellable,
@@ -756,7 +767,9 @@ static void
 get_items_for_current_dir (GetFileListData *gfl)
 {
 	const char *directory_name;
+	GFile      *directory_file;
 	char       *directory_uri;
+	char       *base_dir_uri;
 
 	if (gfl->current_dir == NULL) {
 		if (gfl->done_func) {
@@ -770,19 +783,20 @@ get_items_for_current_dir (GetFileListDa
 	}
 
 	directory_name = file_name_from_path ((char*) gfl->current_dir->data);
-	if (strcmp (gfl->base_dir, "/") == 0)
-		directory_uri = g_strconcat (gfl->base_dir, directory_name, NULL);
-	else
-		directory_uri = g_strconcat (gfl->base_dir, "/", directory_name, NULL);
+	directory_file = g_file_get_child (gfl->base_dir, directory_name);
+	directory_uri = g_file_get_uri (directory_file);
+	base_dir_uri = g_file_get_uri (gfl->base_dir);
 
 	g_directory_list_all_async (directory_uri,
-			   	    gfl->base_dir,
+				    base_dir_uri,
 				    TRUE,
 				    gfl->cancellable,
-			   	    get_items_for_current_dir_done,
-			   	    gfl);
+				    get_items_for_current_dir_done,
+				    gfl);
 
 	g_free (directory_uri);
+	g_free (base_dir_uri);
+	g_object_unref (directory_file);
 }
 
 
@@ -800,7 +814,7 @@ g_list_items_async (GList             *i
 	g_return_if_fail (base_dir != NULL);
 
 	gfl = g_new0 (GetFileListData, 1);
-	gfl->base_dir = g_strdup (base_dir);
+	gfl->base_dir = g_file_new_for_commandline_arg (base_dir);
 	gfl->cancellable = cancellable;
 	gfl->done_func = done_func;
 	gfl->done_data = done_data;
@@ -916,6 +930,19 @@ g_copy_files_ready_cb (GObject      *sou
 	GError        *error = NULL;
 
 	if (! g_file_copy_finish (source, result, &error)) {
+		/* source and target are directories, ignore the error */
+		if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_WOULD_MERGE))
+			g_clear_error (&error);
+		/* source is directory, create target directory */
+		if (g_error_matches (error, G_IO_ERROR,  G_IO_ERROR_WOULD_RECURSE)) {
+			g_clear_error (&error);
+			g_file_make_directory ((GFile*) cfd->destination->data,
+					       cfd->cancellable,
+					       &error);
+		}
+	}
+
+	if (error) {
 		if (cfd->callback)
 			cfd->callback (error, cfd->user_data);
 		g_clear_error (&error);
@@ -1123,8 +1150,8 @@ child_data_free (ChildData *child)
 
 
 typedef struct {
-	char                  *source;
-	char                  *destination;
+	GFile                 *source;
+	GFile                 *destination;
 	GFileCopyFlags         flags;
 	int                    io_priority;
 	GCancellable          *cancellable;
@@ -1149,8 +1176,10 @@ directory_copy_data_free (DirectoryCopyD
 	if (dcd == NULL)
 		return;
 
-	g_free (dcd->source);
-	g_free (dcd->destination);
+	if (dcd->source != NULL)
+		g_object_unref (dcd->source);
+	if (dcd->destination != NULL)
+		g_object_unref (dcd->destination);
 	if (dcd->current_source != NULL) {
 		g_object_unref (dcd->current_source);
 		dcd->current_source = NULL;
@@ -1161,7 +1190,6 @@ directory_copy_data_free (DirectoryCopyD
 	}
 	g_list_foreach (dcd->to_copy, (GFunc) child_data_free, NULL);
 	g_list_free (dcd->to_copy);
-	g_object_unref (dcd->cancellable);
 	g_free (dcd);
 }
 
@@ -1187,15 +1215,19 @@ static GFile *
 get_destination_for_uri (DirectoryCopyData *dcd,
 		         const char        *uri)
 {
-	char  *destination_uri;
+	GFile *f_uri;
 	GFile *destination_file;
+	char  *relative_path;
 
-	if (strlen (uri) <=  strlen (dcd->source))
-		return NULL;
+	f_uri = g_file_new_for_uri (uri);
+	relative_path = g_file_get_relative_path (dcd->source, f_uri);
+	if (relative_path != NULL)
+		destination_file = g_file_resolve_relative_path (dcd->destination, relative_path);
+	else
+		destination_file = g_file_dup (dcd->destination);
 
-	destination_uri = g_strconcat (dcd->destination, "/", uri + strlen (dcd->source) + 1, NULL);
-	destination_file = g_file_new_for_uri (destination_uri);
-	g_free (destination_uri);
+	g_free (relative_path);
+	g_object_unref (f_uri);
 
 	return destination_file;
 }
@@ -1417,9 +1449,10 @@ g_directory_copy_async (const char      
 {
 	DirectoryCopyData *dcd;
 
+	/* Creating GFile objects here will save us lot of effort in path construction */
 	dcd = g_new0 (DirectoryCopyData, 1);
-	dcd->source = g_strdup (source);
-	dcd->destination = g_strdup (destination);
+	dcd->source = g_file_new_for_commandline_arg (source);
+	dcd->destination = g_file_new_for_commandline_arg (destination);
 	dcd->flags = flags;
 	dcd->io_priority = io_priority;
 	dcd->cancellable = cancellable;
diff -up file-roller-2.28.2/src/gio-utils.h.gvfs-fuse file-roller-2.28.2/src/gio-utils.h
--- file-roller-2.28.2/src/gio-utils.h.gvfs-fuse	2009-04-30 10:47:42.000000000 +0200
+++ file-roller-2.28.2/src/gio-utils.h	2010-05-17 16:57:20.000000000 +0200
@@ -58,7 +58,7 @@ typedef void (*CopyDoneCallback)     (GE
 
 /* asynchronous recursive list functions */
 
-void   g_directory_foreach_child     (const char            *directory,
+void   g_directory_foreach_child     (GFile                 *directory,
 				      gboolean               recursive,
 				      gboolean               follow_links,
 				      GCancellable          *cancellable,


Index: file-roller.spec
===================================================================
RCS file: /cvs/extras/rpms/file-roller/F-12/file-roller.spec,v
retrieving revision 1.164
retrieving revision 1.165
diff -u -p -r1.164 -r1.165
--- file-roller.spec	7 Jan 2010 22:18:09 -0000	1.164
+++ file-roller.spec	18 May 2010 13:07:37 -0000	1.165
@@ -11,7 +11,7 @@
 Summary:	Tool for viewing and creating archives
 Name:		file-roller
 Version:	2.28.2
-Release: 	2%{?dist}
+Release: 	3%{?dist}
 License:	GPLv2+
 Group:		Applications/Archiving
 URL:		http://download.gnome.org/sources/file-roller/
@@ -20,6 +20,10 @@ Source:		http://download.gnome.org/sourc
 # https://bugzilla.gnome.org/show_bug.cgi?id=606074
 Patch0:		file-roller-arj-crash.patch
 
+# from master
+# http://bugzilla.gnome.org/show_bug.cgi?id=617769
+Patch1: file-roller-2.28.2-gvfs-fuse.patch
+
 BuildRoot:	%{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
 BuildRequires: glib2-devel >= %{glib2_version}
 BuildRequires: pango-devel >= %{pango_version}
@@ -54,6 +58,7 @@ such as tar or zip files.
 %prep
 %setup -q
 %patch0 -p1 -b .arj-crash
+%patch1 -p1 -b .gvfs-fuse
 
 %build
 %configure --disable-scrollkeeper --disable-static
@@ -130,6 +135,9 @@ fi
 %{_datadir}/icons/hicolor/scalable/apps/file-roller.svg
 
 %changelog
+* Mon May 17 2010 Tomas Bzatek <tbzatek at redhat.com> 2.28.2-3
+- Fix archive handling on remote GIO mounts without running fuse daemon (#527045, #518510)
+
 * Thu Jan  7 2010 Matthias Clasen <mclasen at redhat.com> 2.28.2-2
 - Fix a crash in the arj loader (#551717)
 



More information about the scm-commits mailing list