Author: hwright
Date: Thu Apr  5 18:43:20 2012
New Revision: 1310005

URL: http://svn.apache.org/viewvc?rev=1310005&view=rev
Log:
On the ev2-export branch:
Use an Ev2-style driver to handle repos->repos copies.

Part of this commit is rather bogus, namely the bit where we still do a
delete+add.  This *should* be a move, and will be adjusted to such in a
future commit, but the fact that it doesn't cause any tests to fail as
currently implemented is somewhat strange (the Ev2 internal checks should
catch this, methinks).

* subversion/libsvn_client/copy.c
  (path_driver_cb_baton, path_driver_cb_func): Remove.
  (fetch_remote_kind_func, fetch_remote_props_func, drive_single_path,
   drive_editor): New.
  (repos_to_repos_copy): Delegate the driving of editors to the helper
    function.

Modified:
    subversion/branches/ev2-export/subversion/libsvn_client/copy.c

Modified: subversion/branches/ev2-export/subversion/libsvn_client/copy.c
URL: 
http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_client/copy.c?rev=1310005&r1=1310004&r2=1310005&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_client/copy.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_client/copy.c Thu Apr  5 
18:43:20 2012
@@ -537,117 +537,6 @@ typedef struct path_driver_info_t
 } path_driver_info_t;
 
 
-/* The baton used with the path_driver_cb_func() callback for a copy
-   or move operation. */
-struct path_driver_cb_baton
-{
-  /* The editor (and its state) used to perform the operation. */
-  const svn_delta_editor_t *editor;
-  void *edit_baton;
-
-  /* A hash of path -> path_driver_info_t *'s. */
-  apr_hash_t *action_hash;
-
-  /* Whether the operation is a move or copy. */
-  svn_boolean_t is_move;
-};
-
-static svn_error_t *
-path_driver_cb_func(void **dir_baton,
-                    void *parent_baton,
-                    void *callback_baton,
-                    const char *path,
-                    apr_pool_t *pool)
-{
-  struct path_driver_cb_baton *cb_baton = callback_baton;
-  svn_boolean_t do_delete = FALSE, do_add = FALSE;
-  path_driver_info_t *path_info = apr_hash_get(cb_baton->action_hash,
-                                               path,
-                                               APR_HASH_KEY_STRING);
-
-  /* Initialize return value. */
-  *dir_baton = NULL;
-
-  /* This function should never get an empty PATH.  We can neither
-     create nor delete the empty PATH, so if someone is calling us
-     with such, the code is just plain wrong. */
-  SVN_ERR_ASSERT(! svn_path_is_empty(path));
-
-  /* Check to see if we need to add the path as a directory. */
-  if (path_info->dir_add)
-    {
-      return cb_baton->editor->add_directory(path, parent_baton, NULL,
-                                             SVN_INVALID_REVNUM, pool,
-                                             dir_baton);
-    }
-
-  /* If this is a resurrection, we know the source and dest paths are
-     the same, and that our driver will only be calling us once.  */
-  if (path_info->resurrection)
-    {
-      /* If this is a move, we do nothing.  Otherwise, we do the copy.  */
-      if (! cb_baton->is_move)
-        do_add = TRUE;
-    }
-  /* Not a resurrection. */
-  else
-    {
-      /* If this is a move, we check PATH to see if it is the source
-         or the destination of the move. */
-      if (cb_baton->is_move)
-        {
-          if (strcmp(path_info->src_path, path) == 0)
-            do_delete = TRUE;
-          else
-            do_add = TRUE;
-        }
-      /* Not a move?  This must just be the copy addition. */
-      else
-        {
-          do_add = TRUE;
-        }
-    }
-
-  if (do_delete)
-    {
-      SVN_ERR(cb_baton->editor->delete_entry(path, SVN_INVALID_REVNUM,
-                                             parent_baton, pool));
-    }
-  if (do_add)
-    {
-      SVN_ERR(svn_path_check_valid(path, pool));
-
-      if (path_info->src_kind == svn_node_file)
-        {
-          void *file_baton;
-          SVN_ERR(cb_baton->editor->add_file(path, parent_baton,
-                                             path_info->src_url,
-                                             path_info->src_revnum,
-                                             pool, &file_baton));
-          if (path_info->mergeinfo)
-            SVN_ERR(cb_baton->editor->change_file_prop(file_baton,
-                                                       SVN_PROP_MERGEINFO,
-                                                       path_info->mergeinfo,
-                                                       pool));
-          SVN_ERR(cb_baton->editor->close_file(file_baton, NULL, pool));
-        }
-      else
-        {
-          SVN_ERR(cb_baton->editor->add_directory(path, parent_baton,
-                                                  path_info->src_url,
-                                                  path_info->src_revnum,
-                                                  pool, dir_baton));
-          if (path_info->mergeinfo)
-            SVN_ERR(cb_baton->editor->change_dir_prop(*dir_baton,
-                                                      SVN_PROP_MERGEINFO,
-                                                      path_info->mergeinfo,
-                                                      pool));
-        }
-    }
-  return SVN_NO_ERROR;
-}
-
-
 /* Starting with the path DIR relative to the RA_SESSION's session
    URL, work up through DIR's parents until an existing node is found.
    Push each nonexistent path onto the array NEW_DIRS, allocating in
@@ -728,6 +617,169 @@ find_absent_parents2(svn_ra_session_t *r
   return SVN_NO_ERROR;
 }
 
+/* This should probably be smarter... */
+static svn_error_t *
+fetch_remote_kind_func(svn_kind_t *kind,
+                       void *baton,
+                       const char *path,
+                       svn_revnum_t base_revision,
+                       apr_pool_t *scratch_pool)
+{
+  *kind = svn_kind_unknown;
+  return SVN_NO_ERROR;
+}
+
+/* This should probably be smarter... */
+static svn_error_t *
+fetch_remote_props_func(apr_hash_t **props,
+                        void *baton,
+                        const char *path,
+                        svn_revnum_t base_revision,
+                        apr_pool_t *result_pool,
+                        apr_pool_t *scratch_pool)
+{
+  *props = apr_hash_make(result_pool);
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+drive_single_path(svn_editor_t *editor,
+                  const char *path,
+                  path_driver_info_t *path_info,
+                  svn_boolean_t is_move,
+                  svn_revnum_t youngest,
+                  apr_pool_t *scratch_pool)
+{
+  apr_hash_t *props = apr_hash_make(scratch_pool);
+  apr_array_header_t *children = apr_array_make(scratch_pool, 1,
+                                                sizeof(const char *));
+  svn_boolean_t do_delete = FALSE;
+  svn_boolean_t do_add = FALSE;
+
+  /* Check to see if we need to add the path as a directory. */
+  if (path_info->dir_add)
+    {
+      return svn_error_trace(svn_editor_add_directory(editor, path, children,
+                                                      props,
+                                                      SVN_INVALID_REVNUM));
+     }
+
+  /* If this is a resurrection, we know the source and dest paths are
+     the same, and that our driver will only be calling us once.  */
+  if (path_info->resurrection)
+    {
+      /* If this is a move, we do nothing.  Otherwise, we do the copy.  */
+      if (!is_move)
+        do_add = TRUE;
+    }
+  /* Not a resurrection. */
+  else
+    {
+      /* If this is a move, we check PATH to see if it is the source
+         or the destination of the move. */
+      if (is_move)
+        {
+          if (strcmp(path_info->src_path, path) == 0)
+            do_delete = TRUE;
+          else
+            do_add = TRUE;
+        }
+      /* Not a move?  This must just be the copy addition. */
+      else
+        {
+          do_add = TRUE;
+        }
+    }
+
+  /* ### We need to handle moves here, rather than just pretend they are
+         a delete + add. */
+  if (do_delete)
+    {
+      SVN_ERR(svn_editor_delete(editor, path, youngest));
+    }
+  if (do_add)
+    {
+      SVN_ERR(svn_path_check_valid(path, scratch_pool));
+
+      /* ### Need to get existing props, rather than just set mergeinfo
+             on an empty set of props. */
+      if (path_info->mergeinfo)
+        apr_hash_set(props, SVN_PROP_MERGEINFO, APR_HASH_KEY_STRING,
+                     path_info->mergeinfo);
+
+      SVN_ERR(svn_editor_copy(editor,
+                              path_info->src_url, path_info->src_revnum,
+                              path, SVN_INVALID_REVNUM));
+
+      if (path_info->src_kind == svn_node_file)
+        SVN_ERR(svn_editor_alter_file(editor, path, SVN_INVALID_REVNUM,
+                                      props, NULL, NULL));
+      else
+        SVN_ERR(svn_editor_alter_directory(editor, path, SVN_INVALID_REVNUM,
+                                           props));
+    }
+
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+drive_editor(const svn_delta_editor_t *deditor,
+             void *dedit_baton,
+             apr_array_header_t *paths,
+             apr_hash_t *action_hash,
+             svn_boolean_t is_move,
+             svn_revnum_t youngest,
+             svn_cancel_func_t cancel_func,
+             void *cancel_baton,
+             apr_pool_t *scratch_pool)
+{
+  svn_editor_t *editor;
+  struct svn_delta__extra_baton *exb;
+  svn_delta_unlock_func_t unlock_func;
+  void *unlock_baton;
+  svn_boolean_t send_abs_paths;
+  svn_error_t *err = SVN_NO_ERROR;
+  apr_pool_t *iterpool;
+  int i;
+
+  /* Create the Ev2 editor from the Ev1 editor provided by the RA layer. */
+  SVN_ERR(svn_delta__editor_from_delta(&editor, &exb,
+                                       &unlock_func, &unlock_baton,
+                                       deditor, dedit_baton, &send_abs_paths,
+                                       cancel_func, cancel_baton,
+                                       fetch_remote_kind_func, NULL,
+                                       fetch_remote_props_func, NULL,
+                                       scratch_pool, scratch_pool));
+  if (exb->start_edit)
+    SVN_ERR(exb->start_edit(exb->baton, youngest));
+
+  iterpool = svn_pool_create(scratch_pool);
+  for (i = 0; i < paths->nelts; i++)
+    {
+      const char *path = APR_ARRAY_IDX(paths, i, const char *);
+      path_driver_info_t *path_info = apr_hash_get(action_hash, path,
+                                                   APR_HASH_KEY_STRING);
+
+      svn_pool_clear(iterpool);
+
+      err = drive_single_path(editor, path, path_info, is_move, youngest,
+                              iterpool);
+      if (err)
+        break;
+    }
+  svn_pool_destroy(iterpool);
+
+  if (err)
+    {
+      /* At least try to abort the edit (and fs txn) before throwing err. */
+      svn_error_clear(svn_editor_abort(editor));
+      return svn_error_trace(err);
+    }
+
+  /* Complete the edit. */
+  return svn_error_trace(svn_editor_complete(editor));
+}
+
 static svn_error_t *
 repos_to_repos_copy(const apr_array_header_t *copy_pairs,
                     svn_boolean_t make_parents,
@@ -738,7 +790,6 @@ repos_to_repos_copy(const apr_array_head
                     svn_boolean_t is_move,
                     apr_pool_t *pool)
 {
-  svn_error_t *err;
   apr_array_header_t *paths = apr_array_make(pool, 2 * copy_pairs->nelts,
                                              sizeof(const char *));
   apr_hash_t *action_hash = apr_hash_make(pool);
@@ -749,7 +800,6 @@ repos_to_repos_copy(const apr_array_head
   svn_ra_session_t *ra_session = NULL;
   const svn_delta_editor_t *editor;
   void *edit_baton;
-  struct path_driver_cb_baton cb_baton;
   apr_array_header_t *new_dirs = NULL;
   apr_hash_t *commit_revprops;
   int i;
@@ -1107,24 +1157,9 @@ repos_to_repos_copy(const apr_array_head
                                     NULL, TRUE, /* No lock tokens */
                                     pool));
 
-  /* Setup the callback baton. */
-  cb_baton.editor = editor;
-  cb_baton.edit_baton = edit_baton;
-  cb_baton.action_hash = action_hash;
-  cb_baton.is_move = is_move;
-
-  /* Call the path-based editor driver. */
-  err = svn_delta_path_driver(editor, edit_baton, youngest, paths,
-                              path_driver_cb_func, &cb_baton, pool);
-  if (err)
-    {
-      /* At least try to abort the edit (and fs txn) before throwing err. */
-      svn_error_clear(editor->abort_edit(edit_baton, pool));
-      return svn_error_trace(err);
-    }
-
-  /* Close the edit. */
-  return svn_error_trace(editor->close_edit(edit_baton, pool));
+  return svn_error_trace(drive_editor(editor, edit_baton, paths, action_hash,
+                                      is_move, youngest, ctx->cancel_func,
+                                      ctx->cancel_baton, pool));
 }
 
 /* Baton for check_url_kind */


Reply via email to