[phodav: 12/18] wip: move method movecopy



commit 632bb2581d913af132692e1adf4f25b61891ee9b
Author: Marc-André Lureau <marcandre lureau gmail com>
Date:   Thu Apr 10 19:06:23 2014 +0200

    wip: move method movecopy

 Makefile.am                        |    1 +
 libphodav/phodav-method-movecopy.c |  197 ++++++++++++++++++++++++++++++++++++
 libphodav/phodav-priv.h            |    2 +
 libphodav/phodav-server.c          |  178 +--------------------------------
 4 files changed, 201 insertions(+), 177 deletions(-)
---
diff --git a/Makefile.am b/Makefile.am
index 4e63829..fb90999 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -37,6 +37,7 @@ libphodav_1_0_la_SOURCES =                    \
        libphodav/phodav-method-delete.c        \
        libphodav/phodav-method-get.c           \
        libphodav/phodav-method-mkcol.c         \
+       libphodav/phodav-method-movecopy.c      \
        libphodav/phodav-method-propfind.c      \
        libphodav/phodav-method-proppatch.c     \
        libphodav/phodav-multistatus.c          \
diff --git a/libphodav/phodav-method-movecopy.c b/libphodav/phodav-method-movecopy.c
new file mode 100644
index 0000000..b01cc7b
--- /dev/null
+++ b/libphodav/phodav-method-movecopy.c
@@ -0,0 +1,197 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2; -*- */
+/*
+ * Copyright (C) 2013 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "phodav-priv.h"
+#include "phodav-utils.h"
+#include "phodav-lock.h"
+
+static gboolean
+do_copy_r (GFile *src, GFile *dest, GFileCopyFlags flags,
+           GCancellable *cancellable, GError **err)
+{
+  GFileEnumerator *e = NULL;
+  gboolean success = FALSE;
+  GFile *src_child = NULL;
+  GFile *dest_child = NULL;
+
+  if (!g_file_make_directory_with_parents (dest, cancellable, err))
+    goto end;
+
+  e = g_file_enumerate_children (src, "standard::*", G_FILE_QUERY_INFO_NONE,
+                                 cancellable, err);
+  if (!e)
+    goto end;
+
+  while (1)
+    {
+      GFileInfo *info = g_file_enumerator_next_file (e, cancellable, err);
+      if (!info)
+        break;
+
+      src_child = g_file_get_child (src, g_file_info_get_name (info));
+      dest_child = g_file_get_child (dest, g_file_info_get_name (info));
+      gboolean isdir = g_file_info_get_file_type (info) == G_FILE_TYPE_DIRECTORY;
+      g_object_unref (info);
+
+      if (isdir)
+        {
+          if (!do_copy_r (src_child, dest_child, flags, cancellable, err))
+            goto end;
+        }
+      else if (!g_file_copy (src_child, dest_child, flags, cancellable, NULL, NULL, err))
+        goto end;
+
+      g_clear_object (&src_child);
+      g_clear_object (&dest_child);
+    }
+
+  success = TRUE;
+
+end:
+  g_clear_object (&e);
+  g_clear_object (&src_child);
+  g_clear_object (&dest_child);
+
+  return success;
+}
+
+static gint
+do_movecopy_file (SoupMessage *msg, GFile *file,
+                  GFile *dest, const gchar *dest_path,
+                  GCancellable *cancellable, GError **err)
+{
+  GError *error = NULL;
+  gboolean overwrite;
+  DepthType depth;
+  gint status = SOUP_STATUS_PRECONDITION_FAILED;
+  gboolean copy = msg->method == SOUP_METHOD_COPY;
+  GFileCopyFlags flags = G_FILE_COPY_ALL_METADATA;
+  gboolean retry = FALSE;
+  gboolean exists;
+
+  depth = depth_from_string (soup_message_headers_get_one (msg->request_headers, "Depth"));
+  overwrite = !!g_strcmp0 (
+    soup_message_headers_get_one (msg->request_headers, "Overwrite"), "F");
+  if (overwrite)
+    flags |= G_FILE_COPY_OVERWRITE;
+  exists = g_file_query_exists (dest, cancellable);
+
+again:
+  switch (depth)
+    {
+    case DEPTH_INFINITY:
+    case DEPTH_ZERO: {
+        copy
+        ? g_file_copy (file, dest, flags, cancellable, NULL, NULL, &error)
+        : g_file_move (file, dest, flags, cancellable, NULL, NULL, &error);
+
+        if (overwrite && !retry &&
+            (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_IS_DIRECTORY) ||
+             g_error_matches (error, G_IO_ERROR, G_IO_ERROR_WOULD_MERGE)) &&
+            phodav_delete_file (dest_path, dest, NULL, cancellable) == SOUP_STATUS_NO_CONTENT)
+          {
+            g_clear_error (&error);
+            retry = TRUE;
+            goto again;
+          }
+        else if (!overwrite &&
+                 g_error_matches (error, G_IO_ERROR, G_IO_ERROR_EXISTS))
+          {
+            g_clear_error (&error);
+            goto end;
+          }
+        else if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_WOULD_RECURSE))
+          {
+            g_clear_error (&error);
+            if (copy)
+              {
+                if (depth == DEPTH_INFINITY)
+                  do_copy_r (file, dest, flags, cancellable, &error);
+                else
+                  g_file_make_directory_with_parents (dest, cancellable, &error);
+              }
+          }
+        else if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND))
+          {
+            status = SOUP_STATUS_CONFLICT;
+            g_clear_error (&error);
+            goto end;
+          }
+
+        break;
+      }
+
+    default:
+      g_warn_if_reached ();
+    }
+
+  if (error)
+    g_propagate_error (err, error);
+  else
+    status = exists ? SOUP_STATUS_NO_CONTENT : SOUP_STATUS_CREATED;
+
+end:
+  return status;
+}
+
+gint
+phodav_method_movecopy (PathHandler *handler, SoupMessage *msg,
+                        const char *path, GError **err)
+{
+  GFile *file = NULL, *dest_file = NULL;
+  GCancellable *cancellable = handler_get_cancellable (handler);
+  SoupURI *dest_uri = NULL;
+  gint status = SOUP_STATUS_NOT_FOUND;
+  const gchar *dest;
+  gchar *udest;
+  GList *submitted = NULL;
+
+  dest = soup_message_headers_get_one (msg->request_headers, "Destination");
+  if (!dest)
+    goto end;
+  dest_uri = soup_uri_new (dest);
+  dest = soup_uri_get_path (dest_uri);
+  if (!dest || !*dest)
+    goto end;
+
+  status = phodav_check_if (handler, msg, path, &submitted);
+  if (status != SOUP_STATUS_OK)
+    goto end;
+
+  if (server_path_has_other_locks (handler_get_server (handler), dest, submitted))
+    {
+      status = SOUP_STATUS_LOCKED;
+      goto end;
+    }
+
+  udest = g_uri_unescape_string (dest + 1, NULL);
+  dest_file = g_file_get_child (handler_get_file (handler), udest);
+  g_free (udest);
+
+  file = g_file_get_child (handler_get_file (handler), path + 1);
+  status = do_movecopy_file (msg, file, dest_file, dest,
+                             cancellable, err);
+
+end:
+  if (dest_uri)
+    soup_uri_free (dest_uri);
+  g_clear_object (&file);
+  g_clear_object (&dest_file);
+  g_list_free_full (submitted, (GDestroyNotify) lock_submitted_free);
+  return status;
+}
diff --git a/libphodav/phodav-priv.h b/libphodav/phodav-priv.h
index d8c4e2f..e96f0f7 100644
--- a/libphodav/phodav-priv.h
+++ b/libphodav/phodav-priv.h
@@ -113,6 +113,8 @@ gint                    phodav_method_mkcol                  (PathHandler *handl
                                                               const char *path, GError **err);
 gint                    phodav_method_delete                 (PathHandler *handler, SoupMessage *msg,
                                                               const char *path, GError **err);
+gint                    phodav_method_movecopy               (PathHandler *handler, SoupMessage *msg,
+                                                              const char *path, GError **err);
 
 
 G_END_DECLS
diff --git a/libphodav/phodav-server.c b/libphodav/phodav-server.c
index 13cb969..9b82120 100644
--- a/libphodav/phodav-server.c
+++ b/libphodav/phodav-server.c
@@ -461,182 +461,6 @@ server_path_has_other_locks (PhodavServer *self, const gchar *path, GList *locks
   return !server_foreach_parent_path (self, path, other_lock_exists, locks);
 }
 
-static gboolean
-do_copy_r (GFile *src, GFile *dest, GFileCopyFlags flags,
-           GCancellable *cancellable, GError **err)
-{
-  GFileEnumerator *e = NULL;
-  gboolean success = FALSE;
-  GFile *src_child = NULL;
-  GFile *dest_child = NULL;
-
-  if (!g_file_make_directory_with_parents (dest, cancellable, err))
-    goto end;
-
-  e = g_file_enumerate_children (src, "standard::*", G_FILE_QUERY_INFO_NONE,
-                                 cancellable, err);
-  if (!e)
-    goto end;
-
-  while (1)
-    {
-      GFileInfo *info = g_file_enumerator_next_file (e, cancellable, err);
-      if (!info)
-        break;
-
-      src_child = g_file_get_child (src, g_file_info_get_name (info));
-      dest_child = g_file_get_child (dest, g_file_info_get_name (info));
-      gboolean isdir = g_file_info_get_file_type (info) == G_FILE_TYPE_DIRECTORY;
-      g_object_unref (info);
-
-      if (isdir)
-        {
-          if (!do_copy_r (src_child, dest_child, flags, cancellable, err))
-            goto end;
-        }
-      else if (!g_file_copy (src_child, dest_child, flags, cancellable, NULL, NULL, err))
-        goto end;
-
-      g_clear_object (&src_child);
-      g_clear_object (&dest_child);
-    }
-
-  success = TRUE;
-
-end:
-  g_clear_object (&e);
-  g_clear_object (&src_child);
-  g_clear_object (&dest_child);
-
-  return success;
-}
-
-static gint
-do_movecopy_file (SoupMessage *msg, GFile *file,
-                  GFile *dest, const gchar *dest_path,
-                  GCancellable *cancellable, GError **err)
-{
-  GError *error = NULL;
-  gboolean overwrite;
-  DepthType depth;
-  gint status = SOUP_STATUS_PRECONDITION_FAILED;
-  gboolean copy = msg->method == SOUP_METHOD_COPY;
-  GFileCopyFlags flags = G_FILE_COPY_ALL_METADATA;
-  gboolean retry = FALSE;
-  gboolean exists;
-
-  depth = depth_from_string (soup_message_headers_get_one (msg->request_headers, "Depth"));
-  overwrite = !!g_strcmp0 (
-    soup_message_headers_get_one (msg->request_headers, "Overwrite"), "F");
-  if (overwrite)
-    flags |= G_FILE_COPY_OVERWRITE;
-  exists = g_file_query_exists (dest, cancellable);
-
-again:
-  switch (depth)
-    {
-    case DEPTH_INFINITY:
-    case DEPTH_ZERO: {
-        copy
-        ? g_file_copy (file, dest, flags, cancellable, NULL, NULL, &error)
-        : g_file_move (file, dest, flags, cancellable, NULL, NULL, &error);
-
-        if (overwrite && !retry &&
-            (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_IS_DIRECTORY) ||
-             g_error_matches (error, G_IO_ERROR, G_IO_ERROR_WOULD_MERGE)) &&
-            phodav_delete_file (dest_path, dest, NULL, cancellable) == SOUP_STATUS_NO_CONTENT)
-          {
-            g_clear_error (&error);
-            retry = TRUE;
-            goto again;
-          }
-        else if (!overwrite &&
-                 g_error_matches (error, G_IO_ERROR, G_IO_ERROR_EXISTS))
-          {
-            g_clear_error (&error);
-            goto end;
-          }
-        else if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_WOULD_RECURSE))
-          {
-            g_clear_error (&error);
-            if (copy)
-              {
-                if (depth == DEPTH_INFINITY)
-                  do_copy_r (file, dest, flags, cancellable, &error);
-                else
-                  g_file_make_directory_with_parents (dest, cancellable, &error);
-              }
-          }
-        else if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND))
-          {
-            status = SOUP_STATUS_CONFLICT;
-            g_clear_error (&error);
-            goto end;
-          }
-
-        break;
-      }
-
-    default:
-      g_warn_if_reached ();
-    }
-
-  if (error)
-    g_propagate_error (err, error);
-  else
-    status = exists ? SOUP_STATUS_NO_CONTENT : SOUP_STATUS_CREATED;
-
-end:
-  return status;
-}
-
-static gint
-method_movecopy (PathHandler *handler, SoupMessage *msg,
-                 const char *path, GError **err)
-{
-  GFile *file = NULL, *dest_file = NULL;
-  PhodavServer *self = handler->self;
-  SoupURI *dest_uri = NULL;
-  gint status = SOUP_STATUS_NOT_FOUND;
-  const gchar *dest;
-  gchar *udest;
-  GList *submitted = NULL;
-
-  dest = soup_message_headers_get_one (msg->request_headers, "Destination");
-  if (!dest)
-    goto end;
-  dest_uri = soup_uri_new (dest);
-  dest = soup_uri_get_path (dest_uri);
-  if (!dest || !*dest)
-    goto end;
-
-  status = phodav_check_if (handler, msg, path, &submitted);
-  if (status != SOUP_STATUS_OK)
-    goto end;
-
-  if (server_path_has_other_locks (self, dest, submitted))
-    {
-      status = SOUP_STATUS_LOCKED;
-      goto end;
-    }
-
-  udest = g_uri_unescape_string (dest + 1, NULL);
-  dest_file = g_file_get_child (handler->file, udest);
-  g_free (udest);
-
-  file = g_file_get_child (handler->file, path + 1);
-  status = do_movecopy_file (msg, file, dest_file, dest,
-                             self->cancellable, err);
-
-end:
-  if (dest_uri)
-    soup_uri_free (dest_uri);
-  g_clear_object (&file);
-  g_clear_object (&dest_file);
-  g_list_free_full (submitted, (GDestroyNotify) lock_submitted_free);
-  return status;
-}
-
 static gboolean G_GNUC_PURE
 check_lock (const gchar *key, Path *path, gpointer data)
 {
@@ -1011,7 +835,7 @@ server_callback (SoupServer *server, SoupMessage *msg,
     status = phodav_method_delete (handler, msg, path, &err);
   else if (msg->method == SOUP_METHOD_MOVE ||
            msg->method == SOUP_METHOD_COPY)
-    status = method_movecopy (handler, msg, path, &err);
+    status = phodav_method_movecopy (handler, msg, path, &err);
   else if (msg->method == SOUP_METHOD_LOCK)
     status = method_lock (handler, msg, path, &err);
   else if (msg->method == SOUP_METHOD_UNLOCK)


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