[nautilus] file-operations: Let file/directory creation work on Google Drive



commit 18fe29c85deb89502bca5ccb8d1073d109b6fb0e
Author: Debarshi Ray <debarshir gnome org>
Date:   Thu Jun 25 10:27:31 2015 +0200

    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 +-
 libnautilus-private/nautilus-file-operations.c |  175 +++++++++++++++++++++---
 2 files changed, 159 insertions(+), 18 deletions(-)
---
diff --git a/configure.ac b/configure.ac
index c6237c2..54b89f7 100644
--- a/configure.ac
+++ b/configure.ac
@@ -2,7 +2,7 @@ AC_PREREQ(2.54)
 
 dnl ===========================================================================
 
-m4_define(glib_minver,                 2.43.4)
+m4_define(glib_minver,                 2.45.7)
 m4_define(gnome_desktop_minver,        3.0.0)
 m4_define(pango_minver,                1.28.3)
 m4_define(gtk_minver,                  3.17.5)
diff --git a/libnautilus-private/nautilus-file-operations.c b/libnautilus-private/nautilus-file-operations.c
index f5f150e..2f189c4 100644
--- a/libnautilus-private/nautilus-file-operations.c
+++ b/libnautilus-private/nautilus-file-operations.c
@@ -3694,6 +3694,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,
@@ -3726,6 +3802,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;
 
@@ -3734,7 +3811,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;
@@ -4527,6 +4618,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);
 
@@ -6379,6 +6482,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) {
                        nautilus_file_undo_info_create_set_data (NAUTILUS_FILE_UNDO_INFO_CREATE 
(common->undo_info),
                                                                 dest, NULL, 0);
@@ -6393,6 +6508,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;
 
@@ -6416,24 +6543,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) {
-                                               nautilus_file_undo_info_create_set_data 
(NAUTILUS_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) {
+                                                       nautilus_file_undo_info_create_set_data 
(NAUTILUS_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;
                        }


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