[gvfs] dav: Emit progress callbacks when copying and moving



commit 5b053ef5a7d6b8391e30e1f915700b7d56bf5967
Author: Ross Lagerwall <rosslagerwall gmail com>
Date:   Thu May 14 07:35:41 2015 +0100

    dav: Emit progress callbacks when copying and moving
    
    For progress in applications like Nautilus to be shown correctly, they
    need at least one progress callback to be emitted at the end. This is
    supposed to be guaranteed according to the GIO documentation. With
    server-side copy and move using webdav, emit a single progress callback
    at the end with the source file size.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=749354

 daemon/gvfsbackenddav.c |   85 +++++++++++++++++-----------------------------
 1 files changed, 32 insertions(+), 53 deletions(-)
---
diff --git a/daemon/gvfsbackenddav.c b/daemon/gvfsbackenddav.c
index eae7511..2d83ca0 100644
--- a/daemon/gvfsbackenddav.c
+++ b/daemon/gvfsbackenddav.c
@@ -1206,43 +1206,6 @@ ms_response_to_fs_info (MsResponse *response,
     }
 }
 
-static GFileType
-ms_response_to_file_type (MsResponse *response)
-{
-  xmlNodeIter prop_iter;
-  MsPropstat  propstat;
-  GFileType   file_type;
-  guint       status;
-
-  file_type = G_FILE_TYPE_UNKNOWN;
-
-  ms_response_get_propstat_iter (response, &prop_iter);
-  while (xml_node_iter_next (&prop_iter))
-    {
-      xmlNodePtr iter;
-
-      status = ms_response_get_propstat (&prop_iter, &propstat);
-
-      if (! SOUP_STATUS_IS_SUCCESSFUL (status))
-        continue;
-
-      for (iter = propstat.prop_node->children; iter; iter = iter->next)
-        {
-          if (node_is_element (iter) &&
-              node_has_name_ns (iter, "resourcetype", "DAV:"))
-            break;
-        }
-
-      if (iter)
-        {
-          file_type = parse_resourcetype (iter);
-          break;
-        }
-    }
-
-  return file_type;
-}
-
 #define PROPSTAT_XML_BEGIN                        \
   "<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n" \
   " <D:propfind xmlns:D=\"DAV:\">\n"
@@ -1333,6 +1296,7 @@ stat_location_begin (SoupURI  *uri,
     PROPSTAT_XML_BEGIN
     PROPSTAT_XML_PROP_BEGIN
     "<D:resourcetype/>\n"
+    "<D:getcontentlength/>\n"
     PROPSTAT_XML_PROP_END
     PROPSTAT_XML_END;
 
@@ -1355,6 +1319,7 @@ stat_location_begin (SoupURI  *uri,
 static gboolean
 stat_location_finish (SoupMessage *msg,
                       GFileType   *target_type,
+                      gint64      *target_size,
                       guint       *num_children)
 {
   Multistatus  ms;
@@ -1362,7 +1327,7 @@ stat_location_finish (SoupMessage *msg,
   gboolean     res;
   GError      *error;
   guint        child_count;
-  GFileType    file_type;
+  GFileInfo   *file_info;
 
   if (msg->status_code != 207)
     return FALSE;
@@ -1374,7 +1339,7 @@ stat_location_finish (SoupMessage *msg,
 
   res = FALSE;
   child_count = 0;
-  file_type = G_FILE_TYPE_UNKNOWN;
+  file_info = g_file_info_new ();
 
   multistatus_get_response_iter (&ms, &iter);
   while (xml_node_iter_next (&iter))
@@ -1386,7 +1351,7 @@ stat_location_finish (SoupMessage *msg,
 
       if (response.is_target)
         {
-          file_type = ms_response_to_file_type (&response);
+          ms_response_to_file_info (&response, file_info);
           res = TRUE;
         }
       else
@@ -1398,13 +1363,17 @@ stat_location_finish (SoupMessage *msg,
   if (res)
     {
       if (target_type)
-        *target_type = file_type;
+        *target_type = g_file_info_get_file_type (file_info);
+
+      if (target_size)
+        *target_size = g_file_info_get_size (file_info);
 
       if (num_children)
         *num_children = child_count;
     }
 
   multistatus_free (&ms);
+  g_object_unref (file_info);
   return res;
 }
 
@@ -1412,6 +1381,7 @@ static gboolean
 stat_location (GVfsBackend  *backend,
                SoupURI      *uri,
                GFileType    *target_type,
+               gint64       *target_size,
                guint        *num_children,
                GError      **error)
 {
@@ -1439,7 +1409,7 @@ stat_location (GVfsBackend  *backend,
       return FALSE;
     }
 
-  res = stat_location_finish (msg, target_type, num_children);
+  res = stat_location_finish (msg, target_type, target_size, num_children);
   g_object_unref (msg);
 
   if (res == FALSE)
@@ -1944,7 +1914,7 @@ do_mount (GVfsBackend  *backend,
     soup_message_set_uri (msg_stat, cur_uri);
 
     g_vfs_backend_dav_send_message (backend, msg_stat);
-    res = stat_location_finish (msg_stat, &file_type, NULL);
+    res = stat_location_finish (msg_stat, &file_type, NULL, NULL);
     is_collection = res && file_type == G_FILE_TYPE_DIRECTORY;
 
     g_debug (" [%s] webdav: %d, collection %d [res: %d]\n",
@@ -2302,7 +2272,7 @@ try_open_stat_done (SoupSession *session,
       return;
     }
 
-  res = stat_location_finish (msg, &target_type, NULL);
+  res = stat_location_finish (msg, &target_type, NULL, NULL);
 
   if (res == FALSE)
     {
@@ -2692,7 +2662,7 @@ do_delete (GVfsBackend   *backend,
   error = NULL;
 
   uri = g_vfs_backend_dav_uri_for_path (backend, filename, FALSE);
-  res = stat_location (backend, uri, &file_type, &num_children, &error);
+  res = stat_location (backend, uri, &file_type, NULL, &num_children, &error);
 
   if (res == FALSE)
     {
@@ -2801,7 +2771,8 @@ do_move (GVfsBackend *backend,
   guint status;
   GFileType source_ft, target_ft;
   GError *error = NULL;
-  gboolean res;
+  gboolean res, stat_res;
+  gint64 file_size;
 
   if (flags & G_FILE_COPY_BACKUP)
     {
@@ -2829,19 +2800,20 @@ do_move (GVfsBackend *backend,
   msg = soup_message_new_from_uri (SOUP_METHOD_MOVE, source_uri);
   target_uri = g_vfs_backend_dav_uri_for_path (backend, destination, FALSE);
 
-  res = stat_location (backend, target_uri, &target_ft, NULL, &error);
+  res = stat_location (backend, target_uri, &target_ft, NULL, NULL, &error);
   if (!res && !g_error_matches (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND))
     {
       g_vfs_job_failed_from_error (G_VFS_JOB (job), error);
       goto error;
     }
+  g_clear_error (&error);
 
+  stat_res = stat_location (backend, source_uri, &source_ft, &file_size, NULL, &error);
   if (res)
     {
       if (flags & G_FILE_COPY_OVERWRITE)
         {
-          res = stat_location (backend, source_uri, &source_ft, NULL, &error);
-          if (res)
+          if (stat_res)
             {
               if (target_ft == G_FILE_TYPE_DIRECTORY)
                 {
@@ -2902,6 +2874,8 @@ do_move (GVfsBackend *backend,
 
   if (SOUP_STATUS_IS_SUCCESSFUL (status))
     {
+      if (stat_res && progress_callback)
+        progress_callback (file_size, file_size, progress_callback_data);
       g_vfs_job_succeeded (G_VFS_JOB (job));
     }
   else if (status == SOUP_STATUS_PRECONDITION_FAILED ||
@@ -2935,6 +2909,7 @@ do_copy (GVfsBackend *backend,
   GFileType source_ft, target_ft;
   GError *error = NULL;
   gboolean res;
+  gint64 file_size;
 
   if (flags & G_FILE_COPY_BACKUP)
     {
@@ -2951,14 +2926,14 @@ do_copy (GVfsBackend *backend,
   source_uri = g_vfs_backend_dav_uri_for_path (backend, source, FALSE);
   target_uri = g_vfs_backend_dav_uri_for_path (backend, destination, FALSE);
 
-  res = stat_location (backend, source_uri, &source_ft, NULL, &error);
+  res = stat_location (backend, source_uri, &source_ft, &file_size, NULL, &error);
   if (!res)
     {
       g_vfs_job_failed_from_error (G_VFS_JOB (job), error);
       goto error;
     }
 
-  res = stat_location (backend, target_uri, &target_ft, NULL, &error);
+  res = stat_location (backend, target_uri, &target_ft, NULL, NULL, &error);
   if (res)
     {
       if (flags & G_FILE_COPY_OVERWRITE)
@@ -3012,7 +2987,11 @@ do_copy (GVfsBackend *backend,
    * and IS_REDIRECTION handling below. */
 
   if (SOUP_STATUS_IS_SUCCESSFUL (status))
-    g_vfs_job_succeeded (G_VFS_JOB (job));
+    {
+      if (progress_callback)
+        progress_callback (file_size, file_size, progress_callback_data);
+      g_vfs_job_succeeded (G_VFS_JOB (job));
+    }
   else if (status == SOUP_STATUS_PRECONDITION_FAILED ||
            SOUP_STATUS_IS_REDIRECTION (status))
     g_vfs_job_failed (G_VFS_JOB (job), G_IO_ERROR,
@@ -3234,7 +3213,7 @@ push_stat_dest_cb (SoupSession *session, SoupMessage *msg, gpointer user_data)
   PushHandle *handle = user_data;
   GFileType type;
 
-  if (stat_location_finish (msg, &type, NULL))
+  if (stat_location_finish (msg, &type, NULL, NULL))
     {
       if (!(handle->op_job->flags & G_FILE_COPY_OVERWRITE))
         {


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