Blob Blame Raw
From abb47a4ad34662135aa62db3fd77d37893ee0b4a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Bj=C3=B6rn=20Esser?= <besser82@fedoraproject.org>
Date: Fri, 8 Sep 2017 19:57:13 +0200
Subject: [PATCH 1/5] file: Let renames work on Google Drive Renaming an item
 on Google Drive does not change the actual GVfs path because the path is made
 up of document-ids, which do not change. A rename operation only affects the
 title of the entry. In GIO terms, only the standard::display-name changes,
 but the standard::name remains the same.

Therefore, if there is already a file with the same standard::name,
then don't mark it as gone if it is the same file that we are renaming.

https://bugzilla.gnome.org/show_bug.cgi?id=740383
---
 libnemo-private/nemo-file.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/libnemo-private/nemo-file.c b/libnemo-private/nemo-file.c
index daefcc9c5..dad5c1256 100644
--- a/libnemo-private/nemo-file.c
+++ b/libnemo-private/nemo-file.c
@@ -1759,10 +1759,11 @@ rename_get_info_callback (GObject *source_object,
 		new_name = g_file_info_get_name (new_info);
 		
 		/* If there was another file by the same name in this
-		 * directory, mark it gone.
+		 * directory and it is not the same file that we are
+		 * renaming, mark it gone.
 		 */
 		existing_file = nemo_directory_find_file_by_name (directory, new_name);
-		if (existing_file != NULL) {
+		if (existing_file != NULL && existing_file != op->file) {
 			nemo_file_mark_gone (existing_file);
 			nemo_file_changed (existing_file);
 		}

From 5abf310f1fa3145bc76ab27d445cc72ee03dfc5a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Bj=C3=B6rn=20Esser?= <besser82@fedoraproject.org>
Date: Sat, 9 Sep 2017 09:29:43 +0200
Subject: [PATCH 2/5] file, file-undo-operations: Let renames on Google Drive
 be undone We really should be using standard::display-name when renaming
 files - g_file_get_basename is simply not the right thing to use. Moreover,
 in case of Google Drive, the URI might not change with the display name and
 we can not get the old display name from the old GFile.

Therefore, let's explicitly keep track of the old and new display
names to address these issues.

https://bugzilla.gnome.org/show_bug.cgi?id=754785
---
 libnemo-private/nemo-file-undo-operations.c | 29 ++++++++++++++++++-----------
 libnemo-private/nemo-file-undo-operations.h |  9 ++++++---
 libnemo-private/nemo-file.c                 |  9 +++++++--
 3 files changed, 31 insertions(+), 16 deletions(-)

diff --git a/libnemo-private/nemo-file-undo-operations.c b/libnemo-private/nemo-file-undo-operations.c
index ce2754411..8fedd3894 100644
--- a/libnemo-private/nemo-file-undo-operations.c
+++ b/libnemo-private/nemo-file-undo-operations.c
@@ -862,6 +862,8 @@ G_DEFINE_TYPE (NemoFileUndoInfoRename, nemo_file_undo_info_rename, NEMO_TYPE_FIL
 struct _NemoFileUndoInfoRenameDetails {
 	GFile *old_file;
 	GFile *new_file;
+	gchar *old_display_name;
+	gchar *new_display_name;
 };
 
 static void
@@ -892,16 +894,13 @@ rename_redo_func (NemoFileUndoInfo *info,
 		  GtkWindow *parent_window)
 {
 	NemoFileUndoInfoRename *self = NEMO_FILE_UNDO_INFO_RENAME (info);
-	gchar *new_name;
 	NemoFile *file;
 
-	new_name = g_file_get_basename (self->priv->new_file);
 	file = nemo_file_get (self->priv->old_file);
-	nemo_file_rename (file, new_name,
+	nemo_file_rename (file, self->priv->new_display_name,
 			      file_undo_info_operation_callback, self);
 
 	nemo_file_unref (file);
-	g_free (new_name);
 }
 
 static void
@@ -909,16 +908,13 @@ rename_undo_func (NemoFileUndoInfo *info,
 		  GtkWindow *parent_window)
 {
 	NemoFileUndoInfoRename *self = NEMO_FILE_UNDO_INFO_RENAME (info);
-	gchar *new_name;
 	NemoFile *file;
 
-	new_name = g_file_get_basename (self->priv->old_file);
 	file = nemo_file_get (self->priv->new_file);
-	nemo_file_rename (file, new_name,
+	nemo_file_rename (file, self->priv->old_display_name,
 			      file_undo_info_operation_callback, self);
 
 	nemo_file_unref (file);
-	g_free (new_name);
 }
 
 static void
@@ -934,6 +930,8 @@ nemo_file_undo_info_rename_finalize (GObject *obj)
 	NemoFileUndoInfoRename *self = NEMO_FILE_UNDO_INFO_RENAME (obj);
 	g_clear_object (&self->priv->old_file);
 	g_clear_object (&self->priv->new_file);
+	g_free (self->priv->old_display_name);
+	g_free (self->priv->new_display_name);
 
 	G_OBJECT_CLASS (nemo_file_undo_info_rename_parent_class)->finalize (obj);
 }
@@ -963,11 +961,20 @@ nemo_file_undo_info_rename_new (void)
 }
 
 void
-nemo_file_undo_info_rename_set_data (NemoFileUndoInfoRename *self,
-					 GFile                      *old_file,
-					 GFile                      *new_file)
+nemo_file_undo_info_rename_set_data_pre (NemoFileUndoInfoRename *self,
+					     GFile                      *old_file,
+					     gchar                      *old_display_name,
+					     gchar                      *new_display_name)
 {
 	self->priv->old_file = g_object_ref (old_file);
+	self->priv->old_display_name = g_strdup (old_display_name);
+	self->priv->new_display_name = g_strdup (new_display_name);
+}
+
+void
+nemo_file_undo_info_rename_set_data_post (NemoFileUndoInfoRename *self,
+					      GFile                      *new_file)
+{
 	self->priv->new_file = g_object_ref (new_file);
 }
 
diff --git a/libnemo-private/nemo-file-undo-operations.h b/libnemo-private/nemo-file-undo-operations.h
index fe8a842d6..bbcf40656 100644
--- a/libnemo-private/nemo-file-undo-operations.h
+++ b/libnemo-private/nemo-file-undo-operations.h
@@ -179,9 +179,12 @@ struct _NemoFileUndoInfoRenameClass {
 
 GType nemo_file_undo_info_rename_get_type (void) G_GNUC_CONST;
 NemoFileUndoInfo *nemo_file_undo_info_rename_new (void);
-void nemo_file_undo_info_rename_set_data (NemoFileUndoInfoRename *self,
-					      GFile                      *old_file,
-					      GFile                      *new_file);
+void nemo_file_undo_info_rename_set_data_pre (NemoFileUndoInfoRename *self,
+						  GFile                      *old_file,
+						  gchar                      *old_display_name,
+						  gchar                      *new_display_name);
+void nemo_file_undo_info_rename_set_data_post (NemoFileUndoInfoRename *self,
+						   GFile                      *new_file);
 
 /* trash */
 #define NEMO_TYPE_FILE_UNDO_INFO_TRASH         (nemo_file_undo_info_trash_get_type ())
diff --git a/libnemo-private/nemo-file.c b/libnemo-private/nemo-file.c
index dad5c1256..012e25780 100644
--- a/libnemo-private/nemo-file.c
+++ b/libnemo-private/nemo-file.c
@@ -1815,8 +1815,8 @@ rename_callback (GObject *source_object,
 
 	if (new_file != NULL) {
 		if (op->undo_info != NULL) {
-			nemo_file_undo_info_rename_set_data (NEMO_FILE_UNDO_INFO_RENAME (op->undo_info),
-								 G_FILE (source_object), new_file);
+			nemo_file_undo_info_rename_set_data_post (NEMO_FILE_UNDO_INFO_RENAME (op->undo_info),
+								      new_file);
 		}
 
 		g_file_query_info_async (new_file,
@@ -2000,6 +2000,11 @@ nemo_file_rename (NemoFile *file,
 	/* Tell the undo manager a rename is taking place */
 	if (!nemo_file_undo_manager_pop_flag ()) {
 		op->undo_info = nemo_file_undo_info_rename_new ();
+
+		old_name = nemo_file_get_display_name (file);
+		nemo_file_undo_info_rename_set_data_pre (NEMO_FILE_UNDO_INFO_RENAME (op->undo_info),
+							     location, old_name, new_file_name);
+		g_free (old_name);
 	}
 
 	/* Do the renaming. */

From 4eaecde496bdff18eedbd82bd94f2fc67e9d6dff Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Bj=C3=B6rn=20Esser?= <besser82@fedoraproject.org>
Date: Sat, 9 Sep 2017 09:32:40 +0200
Subject: [PATCH 3/5] file-operations: Let file/directory creation work on
 Google Drive Immediately check the volatility of the newly created file or
 directory and switch to using the "real" persistent URI. The following
 operations are affected:   - creating new directories   - creating new files
 from templates   - dragging & dropping text to create new files   - copying
 and moving of files and directories

The Google Drive backend doesn't support creating symbolic links so we
ignore that case.

https://bugzilla.gnome.org/show_bug.cgi?id=751481
---
 configure.ac                           |   2 +-
 libnemo-private/nemo-file-operations.c | 175 +++++++++++++++++++++++++++++----
 2 files changed, 159 insertions(+), 18 deletions(-)

diff --git a/configure.ac b/configure.ac
index 805b11c22..a87ba29ee 100644
--- a/configure.ac
+++ b/configure.ac
@@ -2,7 +2,7 @@ AC_PREREQ(2.54)
 
 dnl ===========================================================================
 
-m4_define(glib_minver,                 2.37.3)
+m4_define(glib_minver,                 2.45.7)
 m4_define(cinnamon_desktop_minver,     2.6.1)
 m4_define(pango_minver,                1.28.3)
 m4_define(gtk_minver,                  3.9.10)
diff --git a/libnemo-private/nemo-file-operations.c b/libnemo-private/nemo-file-operations.c
index 06bf7959d..7d86a695c 100644
--- a/libnemo-private/nemo-file-operations.c
+++ b/libnemo-private/nemo-file-operations.c
@@ -3536,6 +3536,82 @@ is_dir (GFile *file)
 	return res;
 }
 
+static GFile*
+map_possibly_volatile_file_to_real (GFile *volatile_file,
+				    GCancellable *cancellable,
+				    GError **error)
+{
+	GFile *real_file = NULL;
+	GFileInfo *info = NULL;
+
+	info = g_file_query_info (volatile_file,
+				  G_FILE_ATTRIBUTE_STANDARD_IS_SYMLINK","
+				  G_FILE_ATTRIBUTE_STANDARD_IS_VOLATILE","
+				  G_FILE_ATTRIBUTE_STANDARD_SYMLINK_TARGET,
+				  G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
+				  cancellable,
+				  error);
+	if (info == NULL) {
+		return NULL;
+	} else {
+		gboolean is_volatile;
+
+		is_volatile = g_file_info_get_attribute_boolean (info,
+								 G_FILE_ATTRIBUTE_STANDARD_IS_VOLATILE);
+		if (is_volatile) {
+			const gchar *target;
+
+			target = g_file_info_get_symlink_target (info);
+			real_file = g_file_resolve_relative_path (volatile_file, target);
+		}
+	}
+
+	g_object_unref (info);
+
+	if (real_file == NULL)
+		real_file = g_object_ref (volatile_file);
+
+	return real_file;
+}
+
+static GFile*
+map_possibly_volatile_file_to_real_on_write (GFile *volatile_file,
+					     GFileOutputStream *stream,
+					     GCancellable *cancellable,
+					     GError **error)
+{
+	GFile *real_file = NULL;
+	GFileInfo *info = NULL;
+
+	info = g_file_output_stream_query_info (stream,
+						G_FILE_ATTRIBUTE_STANDARD_IS_SYMLINK","
+						G_FILE_ATTRIBUTE_STANDARD_IS_VOLATILE","
+						G_FILE_ATTRIBUTE_STANDARD_SYMLINK_TARGET,
+						cancellable,
+						error);
+	if (info == NULL) {
+		return NULL;
+	} else {
+		gboolean is_volatile;
+
+		is_volatile = g_file_info_get_attribute_boolean (info,
+								 G_FILE_ATTRIBUTE_STANDARD_IS_VOLATILE);
+		if (is_volatile) {
+			const gchar *target;
+
+			target = g_file_info_get_symlink_target (info);
+			real_file = g_file_resolve_relative_path (volatile_file, target);
+		}
+	}
+
+	g_object_unref (info);
+
+	if (real_file == NULL)
+		real_file = g_object_ref (volatile_file);
+
+	return real_file;
+}
+
 static void copy_move_file (CopyMoveJob *job,
 			    GFile *src,
 			    GFile *dest_dir,
@@ -3568,6 +3644,7 @@ create_dest_dir (CommonJob *job,
 	char *primary, *secondary, *details;
 	int response;
 	gboolean handled_invalid_filename;
+	gboolean res;
 
 	handled_invalid_filename = *dest_fs_type != NULL;
 
@@ -3576,7 +3653,21 @@ create_dest_dir (CommonJob *job,
 	   copying the attributes, because we need to be sure we can write to it */
 	
 	error = NULL;
-	if (!g_file_make_directory (*dest, job->cancellable, &error)) {
+	res = g_file_make_directory (*dest, job->cancellable, &error);
+
+	if (res) {
+		GFile *real;
+
+		real = map_possibly_volatile_file_to_real (*dest, job->cancellable, &error);
+		if (real == NULL) {
+			res = FALSE;
+		} else {
+			g_object_unref (*dest);
+			*dest = real;
+		}
+	}
+
+	if (!res) {
 		if (IS_IO_ERROR (error, CANCELLED)) {
 			g_error_free (error);
 			return CREATE_DEST_DIR_FAILED;
@@ -4387,6 +4478,18 @@ copy_move_file (CopyMoveJob *copy_job,
 	}
 	
 	if (res) {
+		GFile *real;
+
+		real = map_possibly_volatile_file_to_real (dest, job->cancellable, &error);
+		if (real == NULL) {
+			res = FALSE;
+		} else {
+			g_object_unref (dest);
+			dest = real;
+		}
+	}
+
+	if (res) {
 		transfer_info->num_files ++;
 		report_copy_progress (copy_job, source_info, transfer_info);
 
@@ -6228,6 +6331,18 @@ create_job (GIOSchedulerJob *io_job,
 					     common->cancellable,
 					     &error);
 
+		if (res) {
+			GFile *real;
+
+			real = map_possibly_volatile_file_to_real (dest, common->cancellable, &error);
+			if (real == NULL) {
+				res = FALSE;
+			} else {
+				g_object_unref (dest);
+				dest = real;
+			}
+		}
+
 		if (res && common->undo_info != NULL) {
 			nemo_file_undo_info_create_set_data (NEMO_FILE_UNDO_INFO_CREATE (common->undo_info),
 								 dest, NULL, 0);
@@ -6242,6 +6357,18 @@ create_job (GIOSchedulerJob *io_job,
 					   NULL, NULL,
 					   &error);
 
+			if (res) {
+				GFile *real;
+
+				real = map_possibly_volatile_file_to_real (dest, common->cancellable, &error);
+				if (real == NULL) {
+					res = FALSE;
+				} else {
+					g_object_unref (dest);
+					dest = real;
+				}
+			}
+
 			if (res && common->undo_info != NULL) {
 				gchar *uri;
 
@@ -6265,24 +6392,38 @@ create_job (GIOSchedulerJob *io_job,
 					     common->cancellable,
 					     &error);
 			if (out) {
-				res = g_output_stream_write_all (G_OUTPUT_STREAM (out),
-								 data, length,
-								 NULL,
-								 common->cancellable,
-								 &error);
-				if (res) {
-					res = g_output_stream_close (G_OUTPUT_STREAM (out),
-								     common->cancellable,
-								     &error);
-
-					if (res && common->undo_info != NULL) {
-						nemo_file_undo_info_create_set_data (NEMO_FILE_UNDO_INFO_CREATE (common->undo_info),
-											 dest, data, length);
+				GFile *real;
+
+				real = map_possibly_volatile_file_to_real_on_write (dest,
+										    out,
+										    common->cancellable,
+										    &error);
+				if (real == NULL) {
+					res = FALSE;
+					g_object_unref (out);
+				} else {
+					g_object_unref (dest);
+					dest = real;
+
+					res = g_output_stream_write_all (G_OUTPUT_STREAM (out),
+									 data, length,
+									 NULL,
+									 common->cancellable,
+									 &error);
+					if (res) {
+						res = g_output_stream_close (G_OUTPUT_STREAM (out),
+									     common->cancellable,
+									     &error);
+
+						if (res && common->undo_info != NULL) {
+							nemo_file_undo_info_create_set_data (NEMO_FILE_UNDO_INFO_CREATE (common->undo_info),
+												 dest, data, length);
+						}
 					}
-				}
 
-				/* This will close if the write failed and we didn't close */
-				g_object_unref (out);
+					/* This will close if the write failed and we didn't close */
+					g_object_unref (out);
+				}
 			} else {
 				res = FALSE;
 			}

From aea38dc263cd33b87a2044347a27692f0b6d80db Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Bj=C3=B6rn=20Esser?= <besser82@fedoraproject.org>
Date: Sat, 9 Sep 2017 09:38:15 +0200
Subject: [PATCH 4/5] Do not set an activation URI for files in Trash
 https://bugzilla.gnome.org/show_bug.cgi?id=689248

---
 libnemo-private/nemo-file.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/libnemo-private/nemo-file.c b/libnemo-private/nemo-file.c
index 012e25780..62945f04f 100644
--- a/libnemo-private/nemo-file.c
+++ b/libnemo-private/nemo-file.c
@@ -2224,7 +2224,8 @@ update_info_internal (NemoFile *file,
 	}
 	file->details->type = file_type;
 
-	if (!file->details->got_custom_activation_uri) {
+	if (!file->details->got_custom_activation_uri &&
+	    !nemo_file_is_in_trash (file)) {
 		activation_uri = g_file_info_get_attribute_string (info, G_FILE_ATTRIBUTE_STANDARD_TARGET_URI);
 		if (activation_uri == NULL) {
 			if (file->details->activation_uri) {
@@ -2235,7 +2236,7 @@ update_info_internal (NemoFile *file,
 		} else {
 			old_activation_uri = file->details->activation_uri;
 			file->details->activation_uri = g_strdup (activation_uri);
-			
+
 			if (old_activation_uri) {
 				if (strcmp (old_activation_uri,
 					    file->details->activation_uri) != 0) {

From f2ad4a52947c53107f6017db0db79553175d3582 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Bj=C3=B6rn=20Esser?= <besser82@fedoraproject.org>
Date: Sat, 9 Sep 2017 09:46:40 +0200
Subject: [PATCH 5/5] file: Set activation URI for certain files only Drag&drop
 of native Google Drive files doesn't work correctly, because target path is
 used, which causes requests for HTTP backend and fails. The activation URI is
 used for drag&drop since some time ago. Recently, this behavior has been
 disabled for trash locations. This behavior seems to make sense for recent
 locations in order to allow dropping in applications, which are not based on
 GLib/GIO. It also makes sense for afpbrowse, dnssd, network, and smbbrowse
 backends when mounting and bookmarking. Let's set the activation URI only for
 the mentioned. This change should not affect nautilus links (i.e. desktop
 files and symlinks), which are handled by different codepath, it should
 affectonly certain GVfs backends.

https://bugzilla.gnome.org/show_bug.cgi?id=768168
---
 libnemo-private/nemo-file.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/libnemo-private/nemo-file.c b/libnemo-private/nemo-file.c
index 62945f04f..88d8ee27b 100644
--- a/libnemo-private/nemo-file.c
+++ b/libnemo-private/nemo-file.c
@@ -2225,7 +2225,8 @@ update_info_internal (NemoFile *file,
 	file->details->type = file_type;
 
 	if (!file->details->got_custom_activation_uri &&
-	    !nemo_file_is_in_trash (file)) {
+           (g_file_info_get_attribute_boolean (info, G_FILE_ATTRIBUTE_STANDARD_IS_VIRTUAL) ||
+            nemo_file_is_in_recent (file))) {
 		activation_uri = g_file_info_get_attribute_string (info, G_FILE_ATTRIBUTE_STANDARD_TARGET_URI);
 		if (activation_uri == NULL) {
 			if (file->details->activation_uri) {