[gvfs/wip/rishi/goa: 4/5] Drive continued ...



commit 468add67dcf5ef9f7e7f677a5e07a6b579da802b
Author: Debarshi Ray <debarshir gnome org>
Date:   Mon Jun 29 20:15:18 2015 +0200

    Drive continued ...
    
    Honour remove_source in push
    Implement replace/write/query_info_on_write/...
    Guard against backups

 daemon/gvfsbackendgoogle.c |  284 +++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 280 insertions(+), 4 deletions(-)
---
diff --git a/daemon/gvfsbackendgoogle.c b/daemon/gvfsbackendgoogle.c
index e34f08a..3490756 100644
--- a/daemon/gvfsbackendgoogle.c
+++ b/daemon/gvfsbackendgoogle.c
@@ -38,12 +38,15 @@
 #include "gvfsbackendgoogle.h"
 #include "gvfsicon.h"
 #include "gvfsjobcloseread.h"
+#include "gvfsjobcopy.h"
 #include "gvfsjobcreatemonitor.h"
 #include "gvfsjobenumerate.h"
 #include "gvfsjobopenforread.h"
+#include "gvfsjobopenforwrite.h"
 #include "gvfsjobread.h"
 #include "gvfsjobseekread.h"
 #include "gvfsjobsetdisplayname.h"
+#include "gvfsjobwrite.h"
 #include "gvfsmonitor.h"
 
 struct _GVfsBackendGoogle
@@ -740,6 +743,8 @@ rebuild_entries (GVfsBackendGoogle  *self,
       g_clear_object (&feed);
     }
 
+  self->entries_stale = FALSE;
+
  out:
   g_clear_object (&feed);
   g_clear_object (&query);
@@ -799,6 +804,54 @@ g_vfs_backend_google_close_read (GVfsBackend       *_self,
 /* ---------------------------------------------------------------------------------------------------- */
 
 static void
+g_vfs_backend_google_close_write (GVfsBackend       *_self,
+                                  GVfsJobCloseWrite *job,
+                                  GVfsBackendHandle  handle)
+{
+  GVfsBackendGoogle *self = G_VFS_BACKEND_GOOGLE (_self);
+  GCancellable *cancellable = G_VFS_JOB (job)->cancellable;
+  GDataDocumentsDocument *entry = NULL;
+  GDataUploadStream *stream = GDATA_UPLOAD_STREAM (handle);
+  GError *error;
+
+  g_debug ("+ close_write: %p\n", handle);
+
+  if (!g_output_stream_is_closed (G_OUTPUT_STREAM (stream)))
+    {
+      error = NULL;
+      g_output_stream_close (G_OUTPUT_STREAM (stream), cancellable, &error);
+      if (error != NULL)
+        {
+          g_vfs_job_failed_from_error (G_VFS_JOB (job), error);
+          g_error_free (error);
+          goto out;
+        }
+    }
+
+  error = NULL;
+  entry = gdata_documents_service_finish_upload (self->service, stream, &error);
+  if (error != NULL)
+    {
+      g_vfs_job_failed_from_error (G_VFS_JOB (job), error);
+      g_error_free (error);
+      goto out;
+    }
+  else if (entry == NULL)
+    {
+      g_vfs_job_failed (G_VFS_JOB (job), G_IO_ERROR, G_IO_ERROR_FAILED, _("Failed to write"));
+      goto out;
+    }
+
+  g_vfs_job_succeeded (G_VFS_JOB (job));
+
+ out:
+  g_clear_object (&entry);
+  g_debug ("- close_write\n");
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+static void
 g_vfs_backend_google_copy (GVfsBackend           *_self,
                            GVfsJobCopy           *job,
                            const gchar           *source,
@@ -847,6 +900,16 @@ g_vfs_backend_google_copy (GVfsBackend           *_self,
            unescaped_destination);
   source = unescaped_source;
 
+  if (flags & G_FILE_COPY_BACKUP)
+    {
+      /* Return G_IO_ERROR_NOT_SUPPORTED instead of
+       * G_IO_ERROR_CANT_CREATE_BACKUP to proceed with the GIO
+       * fallback copy.
+       */
+      g_vfs_job_failed_literal (G_VFS_JOB (job), G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED, "Operation not 
supported");
+      goto out;
+    }
+
   error = NULL;
   find_root (self, cancellable, &error);
   if (error != NULL)
@@ -1205,8 +1268,6 @@ g_vfs_backend_google_enumerate (GVfsBackend           *_self,
           g_error_free (error);
           goto out;
         }
-
-      self->entries_stale = FALSE;
     }
 
   g_vfs_job_succeeded (G_VFS_JOB (job));
@@ -1822,6 +1883,18 @@ g_vfs_backend_google_push (GVfsBackend           *_self,
 
   self->entries_stale = TRUE;
 
+  if (remove_source)
+    {
+      error = NULL;
+      g_file_delete (local_file, cancellable, &error);
+      if (error != NULL)
+        {
+          g_vfs_job_failed_from_error (G_VFS_JOB (job), error);
+          g_error_free (error);
+          goto out;
+        }
+    }
+
   g_vfs_job_succeeded (G_VFS_JOB (job));
 
  out:
@@ -1991,6 +2064,48 @@ g_vfs_backend_google_query_info_on_read (GVfsBackend           *_self,
 
 /* ---------------------------------------------------------------------------------------------------- */
 
+static gboolean
+g_vfs_backend_google_query_info_on_write (GVfsBackend           *_self,
+                                          GVfsJobQueryInfoWrite *job,
+                                          GVfsBackendHandle      handle,
+                                          GFileInfo             *info,
+                                          GFileAttributeMatcher *matcher)
+{
+  GVfsBackendGoogle *self = G_VFS_BACKEND_GOOGLE (_self);
+  GDataEntry *entry;
+  GError *error;
+  GDataUploadStream *stream = GDATA_UPLOAD_STREAM (handle);
+  gchar *path = NULL;
+
+  g_debug ("+ query_info_on_write: %p\n", handle);
+
+  entry = gdata_upload_stream_get_entry (stream);
+  path = get_entry_path (self, entry);
+  if (path == NULL)
+    {
+      g_vfs_job_failed (G_VFS_JOB (job), G_IO_ERROR, G_IO_ERROR_NOT_FOUND, _("No such file or directory"));
+      goto out;
+    }
+
+  error = NULL;
+  build_file_info (self, path, entry, info, matcher, FALSE, NULL, &error);
+  if (error != NULL)
+    {
+      g_vfs_job_failed_from_error (G_VFS_JOB (job), error);
+      g_error_free (error);
+      goto out;
+    }
+
+  g_vfs_job_succeeded (G_VFS_JOB (job));
+
+ out:
+  g_free (path);
+  g_debug ("- query_info_on_write\n");
+  return TRUE;
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
 static void
 g_vfs_backend_google_seek_on_read (GVfsBackend       *_self,
                                    GVfsJobSeekRead   *job,
@@ -2128,12 +2243,11 @@ read_cb (GObject      *source_object,
          GAsyncResult *res,
          gpointer      user_data)
 {
-  GError *error;
+  GError *error = NULL;
   GInputStream *stream = G_INPUT_STREAM (source_object);
   GVfsJobRead *job = G_VFS_JOB_READ (user_data);
   gssize nread;
 
-  error = NULL;
   nread = g_input_stream_read_finish (stream, res, &error);
   if (error != NULL)
     {
@@ -2176,6 +2290,164 @@ g_vfs_backend_google_read (GVfsBackend       *_self,
 /* ---------------------------------------------------------------------------------------------------- */
 
 static void
+g_vfs_backend_google_replace (GVfsBackend         *_self,
+                              GVfsJobOpenForWrite *job,
+                              const gchar         *filename,
+                              const gchar         *etag,
+                              gboolean             make_backup,
+                              GFileCreateFlags     flags)
+{
+  GVfsBackendGoogle *self = G_VFS_BACKEND_GOOGLE (_self);
+  GCancellable *cancellable = G_VFS_JOB (job)->cancellable;
+  GDataEntry *entry;
+  GDataUploadStream *stream;
+  GError *error;
+  gboolean is_display_name;
+  gboolean is_root;
+  gchar *content_type = NULL;
+  gchar *id = NULL;
+  gchar *unescaped_filename = NULL;
+
+  g_rec_mutex_lock (&self->mutex);
+  unescaped_filename = unescape_basename_and_map_dirname (self, filename, &is_display_name);
+  g_debug ("+ replace: %s (%s, %d)\n", filename, unescaped_filename, is_display_name);
+
+  if (unescaped_filename == NULL)
+    {
+      g_vfs_job_failed (G_VFS_JOB (job), G_IO_ERROR, G_IO_ERROR_NOT_FOUND, _("No such file or directory"));
+      goto out;
+    }
+
+  is_folder_or_root (unescaped_filename, NULL, NULL, &is_root);
+  if (is_root)
+    {
+      g_vfs_job_failed (G_VFS_JOB (job),
+                        G_IO_ERROR,
+                        G_IO_ERROR_NOT_SUPPORTED,
+                        _("Can not create root directory"));
+      goto out;
+    }
+
+  if (make_backup)
+    {
+      g_vfs_job_failed (G_VFS_JOB (job),
+                        G_IO_ERROR,
+                        G_IO_ERROR_CANT_CREATE_BACKUP,
+                        _("Backup file creation failed"));
+      goto out;
+    }
+
+  if (is_display_name)
+    {
+    }
+  else
+    {
+      const gchar *title;
+
+      id = g_path_get_basename (unescaped_filename);
+      entry = g_hash_table_lookup (self->entries, id);
+
+      if (entry == NULL)
+        {
+          error = NULL;
+          rebuild_entries (self, cancellable, &error);
+          if (error != NULL)
+            {
+              g_vfs_job_failed_from_error (G_VFS_JOB (job), error);
+              g_error_free (error);
+              goto out;
+            }
+
+          entry = g_hash_table_lookup (self->entries, id);
+          if (entry == NULL)
+            {
+              g_vfs_job_failed (G_VFS_JOB (job), G_IO_ERROR, G_IO_ERROR_NOT_FOUND, _("No such file or 
directory"));
+              goto out;
+            }
+        }
+
+      title = gdata_entry_get_title (entry);
+      content_type = get_content_type_from_entry (entry);
+
+      error = NULL;
+      stream = gdata_documents_service_update_document (self->service,
+                                                        GDATA_DOCUMENTS_DOCUMENT (entry),
+                                                        title,
+                                                        content_type,
+                                                        cancellable,
+                                                        &error);
+      if (error != NULL)
+        {
+          g_vfs_job_failed_from_error (G_VFS_JOB (job), error);
+          g_error_free (error);
+          goto out;
+        }
+    }
+
+  g_vfs_job_open_for_write_set_handle (job, stream);
+  g_vfs_job_succeeded (G_VFS_JOB (job));
+
+ out:
+  g_free (content_type);
+  g_free (unescaped_filename);
+  g_debug ("- replace\n");
+  g_rec_mutex_unlock (&self->mutex);
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+static void
+write_cb (GObject      *source_object,
+          GAsyncResult *res,
+          gpointer      user_data)
+{
+  GError *error = NULL;
+  GOutputStream *stream = G_OUTPUT_STREAM (source_object);
+  GVfsJobWrite *job = G_VFS_JOB_WRITE (user_data);
+  gssize nwrite;
+
+  nwrite = g_output_stream_write_finish (stream, res, &error);
+  if (error != NULL)
+    {
+      g_vfs_job_failed_from_error (G_VFS_JOB (job), error);
+      g_error_free (error);
+      goto out;
+    }
+
+  g_vfs_job_write_set_written_size (job, (gsize) nwrite);
+  g_vfs_job_succeeded (G_VFS_JOB (job));
+
+ out:
+  g_object_unref (job);
+  g_debug ("- write\n");
+}
+
+static gboolean
+g_vfs_backend_google_write (GVfsBackend       *_self,
+                            GVfsJobWrite      *job,
+                            GVfsBackendHandle  handle,
+                            gchar             *buffer,
+                            gsize              buffer_size)
+{
+  GCancellable *cancellable = G_VFS_JOB (job)->cancellable;
+  GOutputStream *stream = G_OUTPUT_STREAM (handle);
+
+  g_debug ("+ write: %p\n", handle);
+
+  g_output_stream_write_async (stream,
+                               buffer,
+                               buffer_size,
+                               G_PRIORITY_DEFAULT,
+                               cancellable,
+                               write_cb,
+                               g_object_ref (job));
+
+  return TRUE;
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+static void
 g_vfs_backend_google_dispose (GObject *_self)
 {
   GVfsBackendGoogle *self = G_VFS_BACKEND_GOOGLE (_self);
@@ -2219,6 +2491,7 @@ g_vfs_backend_google_class_init (GVfsBackendGoogleClass * klass)
   gobject_class->finalize = g_vfs_backend_google_finalize;
 
   backend_class->try_close_read = g_vfs_backend_google_close_read;
+  backend_class->close_write = g_vfs_backend_google_close_write;
   backend_class->copy = g_vfs_backend_google_copy;
   backend_class->try_create_dir_monitor = g_vfs_backend_google_create_dir_monitor;
   backend_class->delete = g_vfs_backend_google_delete;
@@ -2231,9 +2504,12 @@ g_vfs_backend_google_class_init (GVfsBackendGoogleClass * klass)
   backend_class->try_query_fs_info = g_vfs_backend_google_query_fs_info;
   backend_class->query_info = g_vfs_backend_google_query_info;
   backend_class->query_info_on_read = g_vfs_backend_google_query_info_on_read;
+  backend_class->try_query_info_on_write = g_vfs_backend_google_query_info_on_write;
   backend_class->seek_on_read = g_vfs_backend_google_seek_on_read;
   backend_class->set_display_name = g_vfs_backend_google_set_display_name;
   backend_class->try_read = g_vfs_backend_google_read;
+  backend_class->replace = g_vfs_backend_google_replace;
+  backend_class->try_write = g_vfs_backend_google_write;
 }
 
 static void


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