You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by ju...@apache.org on 2018/11/15 16:26:26 UTC

svn commit: r1846667 - in /subversion/trunk/subversion: include/private/svn_client_private.h libsvn_client/copy_foreign.c libsvn_client/wc_editor.c

Author: julianfoad
Date: Thu Nov 15 16:26:26 2018
New Revision: 1846667

URL: http://svn.apache.org/viewvc?rev=1846667&view=rev
Log:
Split out the code for issue SVN-4786: Create a WC working-mods editor.

* subversion/include/private/svn_client_private.h
  (svn_client__wc_editor_internal): New.

* subversion/libsvn_client/copy_foreign.c
  Move the WC editor implementation from here...

* subversion/libsvn_client/wc_editor.c
  ... to this new file, copied from 'copy_foreign.c'.

Added:
    subversion/trunk/subversion/libsvn_client/wc_editor.c
      - copied, changed from r1846666, subversion/trunk/subversion/libsvn_client/copy_foreign.c
Modified:
    subversion/trunk/subversion/include/private/svn_client_private.h
    subversion/trunk/subversion/libsvn_client/copy_foreign.c

Modified: subversion/trunk/subversion/include/private/svn_client_private.h
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/include/private/svn_client_private.h?rev=1846667&r1=1846666&r2=1846667&view=diff
==============================================================================
--- subversion/trunk/subversion/include/private/svn_client_private.h (original)
+++ subversion/trunk/subversion/include/private/svn_client_private.h Thu Nov 15 16:26:26 2018
@@ -452,6 +452,28 @@ svn_client__wc_editor(const svn_delta_ed
                       svn_client_ctx_t *ctx,
                       apr_pool_t *result_pool);
 
+/* Return an editor for applying local modifications to a WC.
+ *
+ * Like svn_client__wc_editor() but with additional options.
+ *
+ * If @a root_dir_add is true, then create and schedule for addition
+ * the root directory of this edit, else assume it is already a versioned,
+ * existing directory.
+ *
+ * If @a ignore_mergeinfo_changes is true, ignore any incoming changes
+ * to the 'svn:mergeinfo' property.
+ */
+svn_error_t *
+svn_client__wc_editor_internal(const svn_delta_editor_t **editor_p,
+                               void **edit_baton_p,
+                               const char *dst_abspath,
+                               svn_boolean_t root_dir_add,
+                               svn_boolean_t ignore_mergeinfo_changes,
+                               svn_wc_notify_func2_t notify_func,
+                               void *notify_baton,
+                               svn_client_ctx_t *ctx,
+                               apr_pool_t *result_pool);
+
 /** Send committable changes found in the WC to a delta-editor.
  *
  * Committable changes are found in TARGETS:DEPTH:CHANGELISTS.

Modified: subversion/trunk/subversion/libsvn_client/copy_foreign.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_client/copy_foreign.c?rev=1846667&r1=1846666&r2=1846667&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_client/copy_foreign.c (original)
+++ subversion/trunk/subversion/libsvn_client/copy_foreign.c Thu Nov 15 16:26:26 2018
@@ -38,581 +38,10 @@
 #include "svn_ra.h"
 #include "svn_wc.h"
 
-#include <apr_md5.h>
-
 #include "client.h"
-#include "private/svn_subr_private.h"
-#include "private/svn_wc_private.h"
 #include "svn_private_config.h"
 
 
-/* ------------------------------------------------------------------ */
-
-/* WC Modifications Editor.
- *
- * TODO:
- *   - tests
- *   - use for all existing scenarios ('svn add', 'svn propset', etc.)
- *   - copy-from (half done: in dir_add only, untested)
- *   - text-delta
- *   - Instead of 'root_dir_add' option, probably the driver should anchor
- *     at the parent dir.
- *   - Instead of 'ignore_mergeinfo' option, implement that as a wrapper.
- */
-
-struct edit_baton_t
-{
-  apr_pool_t *pool;
-  const char *anchor_abspath;
-
-  /* True => 'open_root' method will act as 'add_directory' */
-  svn_boolean_t root_dir_add;
-  /* True => filter out any incoming svn:mergeinfo property changes */
-  svn_boolean_t ignore_mergeinfo_changes;
-
-  svn_wc_context_t *wc_ctx;
-  svn_client_ctx_t *ctx;
-  svn_wc_notify_func2_t notify_func;
-  void *notify_baton;
-};
-
-struct dir_baton_t
-{
-  apr_pool_t *pool;
-
-  struct dir_baton_t *pb;
-  struct edit_baton_t *eb;
-
-  const char *local_abspath;
-
-  svn_boolean_t created;  /* already under version control in the WC */
-  apr_hash_t *properties;
-
-  int users;
-};
-
-/*  */
-static svn_error_t *
-get_path(const char **local_abspath_p,
-         const char *anchor_abspath,
-         const char *path,
-         apr_pool_t *result_pool)
-{
-  svn_boolean_t under_root;
-
-  SVN_ERR(svn_dirent_is_under_root(&under_root, local_abspath_p,
-                                   anchor_abspath, path, result_pool));
-  if (! under_root)
-    {
-      return svn_error_createf(
-                    SVN_ERR_WC_OBSTRUCTED_UPDATE, NULL,
-                    _("Path '%s' is not in the working copy"),
-                    svn_dirent_local_style(path, result_pool));
-    }
-  return SVN_NO_ERROR;
-}
-
-/* svn_delta_editor_t function */
-static svn_error_t *
-edit_open(void *edit_baton,
-          svn_revnum_t base_revision,
-          apr_pool_t *result_pool,
-          void **root_baton)
-{
-  struct edit_baton_t *eb = edit_baton;
-  apr_pool_t *dir_pool = svn_pool_create(eb->pool);
-  struct dir_baton_t *db = apr_pcalloc(dir_pool, sizeof(*db));
-
-  db->pool = dir_pool;
-  db->eb = eb;
-  db->users = 1;
-  db->local_abspath = eb->anchor_abspath;
-
-  db->created = !(eb->root_dir_add);
-  if (eb->root_dir_add)
-    SVN_ERR(svn_io_make_dir_recursively(eb->anchor_abspath, dir_pool));
-
-  *root_baton = db;
-
-  return SVN_NO_ERROR;
-}
-
-/* svn_delta_editor_t function */
-static svn_error_t *
-edit_close(void *edit_baton,
-           apr_pool_t *scratch_pool)
-{
-  return SVN_NO_ERROR;
-}
-
-/*  */
-static svn_error_t *
-delete_entry(const char *path,
-             svn_revnum_t revision,
-             void *parent_baton,
-             apr_pool_t *scratch_pool)
-{
-  struct dir_baton_t *pb = parent_baton;
-  struct edit_baton_t *eb = pb->eb;
-  const char *local_abspath;
-
-  SVN_ERR(get_path(&local_abspath,
-                   eb->anchor_abspath, path, scratch_pool));
-  SVN_ERR(svn_wc_delete4(eb->wc_ctx, local_abspath,
-                         FALSE /*keep_local*/,
-                         TRUE /*delete_unversioned*/,
-                         NULL, NULL, /*cancellation*/
-                         eb->notify_func, eb->notify_baton, scratch_pool));
-
-  return SVN_NO_ERROR;
-}
-
-/*  */
-static svn_error_t *
-dir_open_or_add(const char *path,
-                void *parent_baton,
-                struct dir_baton_t **child_baton)
-{
-  struct dir_baton_t *pb = parent_baton;
-  struct edit_baton_t *eb = pb->eb;
-  apr_pool_t *dir_pool = svn_pool_create(pb->pool);
-  struct dir_baton_t *db = apr_pcalloc(dir_pool, sizeof(*db));
-
-  pb->users++;
-
-  db->pb = pb;
-  db->eb = pb->eb;
-  db->pool = dir_pool;
-  db->users = 1;
-
-  SVN_ERR(get_path(&db->local_abspath,
-                   eb->anchor_abspath, path, db->pool));
-
-  *child_baton = db;
-  return SVN_NO_ERROR;
-}
-
-/* An svn_delta_editor_t function. */
-static svn_error_t *
-dir_open(const char *path,
-         void *parent_baton,
-         svn_revnum_t base_revision,
-         apr_pool_t *result_pool,
-         void **child_baton)
-{
-  struct dir_baton_t *db;
-
-  SVN_ERR(dir_open_or_add(path, parent_baton, &db));
-  db->created = TRUE;
-
-  *child_baton = db;
-  return SVN_NO_ERROR;
-}
-
-static svn_error_t *
-dir_add(const char *path,
-        void *parent_baton,
-        const char *copyfrom_path,
-        svn_revnum_t copyfrom_revision,
-        apr_pool_t *result_pool,
-        void **child_baton)
-{
-  struct dir_baton_t *db;
-
-  SVN_ERR(dir_open_or_add(path, parent_baton, &db));
-  SVN_ERR(svn_io_make_dir_recursively(db->local_abspath, db->pool));
-
-  if (copyfrom_path && SVN_IS_VALID_REVNUM(copyfrom_revision))
-    {
-      svn_opt_revision_t copy_src_peg_revision;
-
-      copy_src_peg_revision.kind = svn_opt_revision_number;
-      copy_src_peg_revision.value.number = copyfrom_revision;
-
-      SVN_ERR(svn_client__repos_to_wc_copy_dir(NULL /*timestamp_sleep*/,
-                                               copyfrom_path,
-                                               &copy_src_peg_revision,
-                                               &copy_src_peg_revision,
-                                               db->local_abspath,
-                                               TRUE /*ignore_externals*/,
-                                               NULL /*ra_session*/,
-                                               db->eb->ctx, db->pool));
-    }
-
-  *child_baton = db;
-  return SVN_NO_ERROR;
-}
-
-static svn_error_t *
-dir_change_prop(void *dir_baton,
-                const char *name,
-                const svn_string_t *value,
-                apr_pool_t *scratch_pool)
-{
-  struct dir_baton_t *db = dir_baton;
-  struct edit_baton_t *eb = db->eb;
-  svn_prop_kind_t prop_kind;
-
-  prop_kind = svn_property_kind2(name);
-
-  if (prop_kind != svn_prop_regular_kind
-      || (eb->ignore_mergeinfo_changes && ! strcmp(name, SVN_PROP_MERGEINFO)))
-    {
-      /* We can't handle DAV, ENTRY and merge specific props here */
-      return SVN_NO_ERROR;
-    }
-
-  if (! db->created)
-    {
-      /* Store properties to be added later in svn_wc_add_from_disk3() */
-      if (! db->properties)
-        db->properties = apr_hash_make(db->pool);
-
-      if (value != NULL)
-        svn_hash_sets(db->properties, apr_pstrdup(db->pool, name),
-                      svn_string_dup(value, db->pool));
-    }
-  else
-    {
-      SVN_ERR(svn_wc_prop_set4(eb->wc_ctx, db->local_abspath, name, value,
-                               svn_depth_empty, FALSE, NULL,
-                               NULL, NULL, /* Cancellation */
-                               NULL, NULL, /* Notification */
-                               scratch_pool));
-    }
-
-  return SVN_NO_ERROR;
-}
-
-/* Releases the directory baton if there are no more users */
-static svn_error_t *
-maybe_done(struct dir_baton_t *db)
-{
-  db->users--;
-
-  if (db->users == 0)
-    {
-      struct dir_baton_t *pb = db->pb;
-
-      svn_pool_clear(db->pool);
-
-      if (pb)
-        SVN_ERR(maybe_done(pb));
-    }
-
-  return SVN_NO_ERROR;
-}
-
-static svn_error_t *
-ensure_added(struct dir_baton_t *db,
-             apr_pool_t *scratch_pool)
-{
-  if (db->created)
-    return SVN_NO_ERROR;
-
-  if (db->pb)
-    SVN_ERR(ensure_added(db->pb, scratch_pool));
-
-  db->created = TRUE;
-
-  /* Add the directory with all the already collected properties */
-  SVN_ERR(svn_wc_add_from_disk3(db->eb->wc_ctx,
-                                db->local_abspath,
-                                db->properties,
-                                TRUE /* skip checks */,
-                                db->eb->notify_func,
-                                db->eb->notify_baton,
-                                scratch_pool));
-
-  return SVN_NO_ERROR;
-}
-
-static svn_error_t *
-dir_close(void *dir_baton,
-          apr_pool_t *scratch_pool)
-{
-  struct dir_baton_t *db = dir_baton;
-  /*struct edit_baton_t *eb = db->eb;*/
-
-  SVN_ERR(ensure_added(db, scratch_pool));
-
-  SVN_ERR(maybe_done(db));
-
-  return SVN_NO_ERROR;
-}
-
-struct file_baton_t
-{
-  apr_pool_t *pool;
-
-  struct dir_baton_t *pb;
-  struct edit_baton_t *eb;
-
-  const char *local_abspath;
-  svn_boolean_t created;  /* already under version control in the WC */
-  apr_hash_t *properties;
-
-  svn_boolean_t writing;
-  unsigned char digest[APR_MD5_DIGESTSIZE];
-
-  const char *tmp_path;
-};
-
-/*  */
-static svn_error_t *
-file_open_or_add(const char *path,
-                 void *parent_baton,
-                 struct file_baton_t **file_baton)
-{
-  struct dir_baton_t *pb = parent_baton;
-  struct edit_baton_t *eb = pb->eb;
-  apr_pool_t *file_pool = svn_pool_create(pb->pool);
-  struct file_baton_t *fb = apr_pcalloc(file_pool, sizeof(*fb));
-
-  pb->users++;
-
-  fb->pool = file_pool;
-  fb->eb = eb;
-  fb->pb = pb;
-
-  SVN_ERR(get_path(&fb->local_abspath,
-                   eb->anchor_abspath, path, fb->pool));
-
-  *file_baton = fb;
-  return SVN_NO_ERROR;
-}
-
-static svn_error_t *
-file_open(const char *path,
-          void *parent_baton,
-          svn_revnum_t base_revision,
-          apr_pool_t *result_pool,
-          void **file_baton)
-{
-  struct file_baton_t *fb;
-
-  SVN_ERR(file_open_or_add(path, parent_baton, &fb));
-  fb->created = TRUE;
-
-  *file_baton = fb;
-  return SVN_NO_ERROR;
-}
-
-static svn_error_t *
-file_add(const char *path,
-         void *parent_baton,
-         const char *copyfrom_path,
-         svn_revnum_t copyfrom_revision,
-         apr_pool_t *result_pool,
-         void **file_baton)
-{
-  struct file_baton_t *fb;
-
-  SVN_ERR(file_open_or_add(path, parent_baton, &fb));
-
-  *file_baton = fb;
-  return SVN_NO_ERROR;
-}
-
-static svn_error_t *
-file_change_prop(void *file_baton,
-                 const char *name,
-                 const svn_string_t *value,
-                 apr_pool_t *scratch_pool)
-{
-  struct file_baton_t *fb = file_baton;
-  struct edit_baton_t *eb = fb->eb;
-  svn_prop_kind_t prop_kind;
-
-  prop_kind = svn_property_kind2(name);
-
-  if (prop_kind != svn_prop_regular_kind
-      || (eb->ignore_mergeinfo_changes && ! strcmp(name, SVN_PROP_MERGEINFO)))
-    {
-      /* We can't handle DAV, ENTRY and merge specific props here */
-      return SVN_NO_ERROR;
-    }
-
-  if (! fb->created)
-    {
-      /* Store properties to be added later in svn_wc_add_from_disk3() */
-      if (! fb->properties)
-        fb->properties = apr_hash_make(fb->pool);
-
-      if (value != NULL)
-        svn_hash_sets(fb->properties, apr_pstrdup(fb->pool, name),
-                      svn_string_dup(value, fb->pool));
-    }
-  else
-    {
-      SVN_ERR(svn_wc_prop_set4(eb->wc_ctx, fb->local_abspath, name, value,
-                               svn_depth_empty, FALSE, NULL,
-                               NULL, NULL, /* Cancellation */
-                               NULL, NULL, /* Notification */
-                               scratch_pool));
-    }
-
-  return SVN_NO_ERROR;
-}
-
-static svn_error_t *
-file_textdelta(void *file_baton,
-               const char *base_checksum,
-               apr_pool_t *result_pool,
-               svn_txdelta_window_handler_t *handler,
-               void **handler_baton)
-{
-  struct file_baton_t *fb = file_baton;
-  svn_stream_t *target;
-
-  SVN_ERR_ASSERT(! fb->writing);
-
-  SVN_ERR(svn_stream_open_writable(&target, fb->local_abspath, fb->pool,
-                                   fb->pool));
-
-  fb->writing = TRUE;
-  svn_txdelta_apply(svn_stream_empty(fb->pool) /* source */,
-                    target,
-                    fb->digest,
-                    fb->local_abspath,
-                    fb->pool,
-                    /* Provide the handler directly */
-                    handler, handler_baton);
-
-  return SVN_NO_ERROR;
-}
-
-static svn_error_t *
-ensure_added_file(struct file_baton_t *fb,
-                  apr_pool_t *scratch_pool)
-{
-  struct edit_baton_t *eb = fb->eb;
-
-  if (fb->created)
-    return SVN_NO_ERROR;
-
-  if (fb->pb)
-    SVN_ERR(ensure_added(fb->pb, scratch_pool));
-
-  fb->created = TRUE;
-
-  /* Add the file with all the already collected properties */
-  SVN_ERR(svn_wc_add_from_disk3(eb->wc_ctx, fb->local_abspath, fb->properties,
-                                TRUE /* skip checks */,
-                                eb->notify_func, eb->notify_baton,
-                                fb->pool));
-
-  return SVN_NO_ERROR;
-}
-
-static svn_error_t *
-file_close(void *file_baton,
-           const char *text_checksum,
-           apr_pool_t *scratch_pool)
-{
-  struct file_baton_t *fb = file_baton;
-  struct dir_baton_t *pb = fb->pb;
-
-  if (text_checksum)
-    {
-      svn_checksum_t *expected_checksum;
-      svn_checksum_t *actual_checksum;
-
-      SVN_ERR(svn_checksum_parse_hex(&expected_checksum, svn_checksum_md5,
-                                     text_checksum, fb->pool));
-      actual_checksum = svn_checksum__from_digest_md5(fb->digest, fb->pool);
-
-      if (! svn_checksum_match(expected_checksum, actual_checksum))
-        return svn_error_trace(
-                    svn_checksum_mismatch_err(expected_checksum,
-                                              actual_checksum,
-                                              fb->pool,
-                                         _("Checksum mismatch for '%s'"),
-                                              svn_dirent_local_style(
-                                                    fb->local_abspath,
-                                                    fb->pool)));
-    }
-
-  SVN_ERR(ensure_added_file(fb, fb->pool));
-
-  svn_pool_destroy(fb->pool);
-  SVN_ERR(maybe_done(pb));
-
-  return SVN_NO_ERROR;
-}
-
-/* Return an editor for applying local modifications to a WC.
- *
- * If @a root_dir_add is true, then create and schedule for addition
- * the root directory of this edit, else assume it is already a versioned,
- * existing directory.
- *
- * If @a ignore_mergeinfo_changes is true, ignore any incoming changes
- * to the 'svn:mergeinfo' property.
- */
-static svn_error_t *
-svn_client__wc_editor_internal(const svn_delta_editor_t **editor_p,
-                               void **edit_baton_p,
-                               const char *dst_abspath,
-                               svn_boolean_t root_dir_add,
-                               svn_boolean_t ignore_mergeinfo_changes,
-                               svn_wc_notify_func2_t notify_func,
-                               void *notify_baton,
-                               svn_client_ctx_t *ctx,
-                               apr_pool_t *result_pool)
-{
-  svn_delta_editor_t *editor = svn_delta_default_editor(result_pool);
-  struct edit_baton_t *eb = apr_pcalloc(result_pool, sizeof(*eb));
-
-  eb->pool = result_pool;
-  eb->anchor_abspath = apr_pstrdup(result_pool, dst_abspath);
-  eb->root_dir_add = root_dir_add;
-  eb->ignore_mergeinfo_changes = ignore_mergeinfo_changes;
-
-  eb->wc_ctx = ctx->wc_ctx;
-  eb->ctx = ctx;
-  eb->notify_func = notify_func;
-  eb->notify_baton  = notify_baton;
-
-  editor->open_root = edit_open;
-  editor->close_edit = edit_close;
-
-  editor->delete_entry = delete_entry;
-
-  editor->open_directory = dir_open;
-  editor->add_directory = dir_add;
-  editor->change_dir_prop = dir_change_prop;
-  editor->close_directory = dir_close;
-
-  editor->open_file = file_open;
-  editor->add_file = file_add;
-  editor->change_file_prop = file_change_prop;
-  editor->apply_textdelta = file_textdelta;
-  editor->close_file = file_close;
-
-  *editor_p = editor;
-  *edit_baton_p = eb;
-  return SVN_NO_ERROR;
-}
-
-svn_error_t *
-svn_client__wc_editor(const svn_delta_editor_t **editor_p,
-                      void **edit_baton_p,
-                      const char *dst_abspath,
-                      svn_wc_notify_func2_t notify_func,
-                      void *notify_baton,
-                      svn_client_ctx_t *ctx,
-                      apr_pool_t *result_pool)
-{
-  SVN_ERR(svn_client__wc_editor_internal(editor_p, edit_baton_p,
-                                         dst_abspath,
-                                         FALSE /*root_dir_add*/,
-                                         FALSE /*ignore_mergeinfo_changes*/,
-                                         notify_func, notify_baton,
-                                         ctx, result_pool));
-  return SVN_NO_ERROR;
-}
-
 /** Copy a directory tree from a remote repository.
  *
  * Copy from RA_SESSION:LOCATION, depth DEPTH, to WC_CTX:DST_ABSPATH.

Copied: subversion/trunk/subversion/libsvn_client/wc_editor.c (from r1846666, subversion/trunk/subversion/libsvn_client/copy_foreign.c)
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_client/wc_editor.c?p2=subversion/trunk/subversion/libsvn_client/wc_editor.c&p1=subversion/trunk/subversion/libsvn_client/copy_foreign.c&r1=1846666&r2=1846667&rev=1846667&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_client/copy_foreign.c (original)
+++ subversion/trunk/subversion/libsvn_client/wc_editor.c Thu Nov 15 16:26:26 2018
@@ -32,10 +32,8 @@
 #include "svn_dirent_uri.h"
 #include "svn_error.h"
 #include "svn_error_codes.h"
-#include "svn_path.h"
 #include "svn_pools.h"
 #include "svn_props.h"
-#include "svn_ra.h"
 #include "svn_wc.h"
 
 #include <apr_md5.h>
@@ -541,16 +539,7 @@ file_close(void *file_baton,
   return SVN_NO_ERROR;
 }
 
-/* Return an editor for applying local modifications to a WC.
- *
- * If @a root_dir_add is true, then create and schedule for addition
- * the root directory of this edit, else assume it is already a versioned,
- * existing directory.
- *
- * If @a ignore_mergeinfo_changes is true, ignore any incoming changes
- * to the 'svn:mergeinfo' property.
- */
-static svn_error_t *
+svn_error_t *
 svn_client__wc_editor_internal(const svn_delta_editor_t **editor_p,
                                void **edit_baton_p,
                                const char *dst_abspath,
@@ -612,169 +601,3 @@ svn_client__wc_editor(const svn_delta_ed
                                          ctx, result_pool));
   return SVN_NO_ERROR;
 }
-
-/** Copy a directory tree from a remote repository.
- *
- * Copy from RA_SESSION:LOCATION, depth DEPTH, to WC_CTX:DST_ABSPATH.
- *
- * Create the directory DST_ABSPATH, if not present. Its parent should be
- * already under version control in the WC and in a suitable state for
- * scheduling the addition of a child.
- *
- * Ignore any incoming non-regular properties (entry-props, DAV/WC-props).
- * Remove any incoming 'svn:mergeinfo' properties.
- */
-static svn_error_t *
-copy_foreign_dir(svn_ra_session_t *ra_session,
-                 svn_client__pathrev_t *location,
-                 const char *dst_abspath,
-                 svn_depth_t depth,
-                 svn_wc_notify_func2_t notify_func,
-                 void *notify_baton,
-                 svn_cancel_func_t cancel_func,
-                 void *cancel_baton,
-                 svn_client_ctx_t *ctx,
-                 apr_pool_t *scratch_pool)
-{
-  const svn_delta_editor_t *editor;
-  void *eb;
-  const svn_delta_editor_t *wrapped_editor;
-  void *wrapped_baton;
-  const svn_ra_reporter3_t *reporter;
-  void *reporter_baton;
-
-  SVN_ERR(svn_client__wc_editor_internal(&editor, &eb,
-                                         dst_abspath,
-                                         TRUE /*root_dir_add*/,
-                                         TRUE /*ignore_mergeinfo_changes*/,
-                                         notify_func, notify_baton,
-                                         ctx, scratch_pool));
-
-  SVN_ERR(svn_delta_get_cancellation_editor(cancel_func, cancel_baton,
-                                            editor, eb,
-                                            &wrapped_editor, &wrapped_baton,
-                                            scratch_pool));
-
-  SVN_ERR(svn_ra_do_update3(ra_session, &reporter, &reporter_baton,
-                            location->rev, "", svn_depth_infinity,
-                            FALSE, FALSE, wrapped_editor, wrapped_baton,
-                            scratch_pool, scratch_pool));
-
-  SVN_ERR(reporter->set_path(reporter_baton, "", location->rev, depth,
-                             TRUE /* incomplete */,
-                             NULL, scratch_pool));
-
-  SVN_ERR(reporter->finish_report(reporter_baton, scratch_pool));
-
-  return SVN_NO_ERROR;
-}
-
-
-svn_error_t *
-svn_client__copy_foreign(const char *url,
-                         const char *dst_abspath,
-                         const svn_opt_revision_t *peg_revision,
-                         const svn_opt_revision_t *revision,
-                         svn_depth_t depth,
-                         svn_boolean_t make_parents,
-                         svn_client_ctx_t *ctx,
-                         apr_pool_t *scratch_pool)
-{
-  svn_ra_session_t *ra_session;
-  svn_client__pathrev_t *loc;
-  svn_node_kind_t kind;
-  svn_node_kind_t wc_kind;
-  const char *dir_abspath;
-
-  SVN_ERR_ASSERT(svn_path_is_url(url));
-  SVN_ERR_ASSERT(svn_dirent_is_absolute(dst_abspath));
-
-  /* Do we need to validate/update revisions? */
-
-  SVN_ERR(svn_client__ra_session_from_path2(&ra_session, &loc,
-                                            url, NULL,
-                                            peg_revision,
-                                            revision, ctx,
-                                            scratch_pool));
-
-  /* The source must exist */
-  SVN_ERR(svn_ra_check_path(ra_session, "", loc->rev, &kind, scratch_pool));
-  if (kind != svn_node_file && kind != svn_node_dir)
-    return svn_error_createf(
-                SVN_ERR_ILLEGAL_TARGET, NULL,
-                _("'%s' is not a valid location inside a repository"),
-                url);
-
-  /* The target path must not exist (at least not as a versioned node) */
-  SVN_ERR(svn_wc_read_kind2(&wc_kind, ctx->wc_ctx, dst_abspath, FALSE, TRUE,
-                            scratch_pool));
-  if (wc_kind != svn_node_none)
-    {
-      return svn_error_createf(
-                SVN_ERR_ENTRY_EXISTS, NULL,
-                _("'%s' is already under version control"),
-                svn_dirent_local_style(dst_abspath, scratch_pool));
-    }
-
-  /* Either the target path's parent must be a versioned directory already
-     or we must create it if MAKE_PARENTS is true */
-  dir_abspath = svn_dirent_dirname(dst_abspath, scratch_pool);
-  SVN_ERR(svn_wc_read_kind2(&wc_kind, ctx->wc_ctx, dir_abspath,
-                            FALSE, FALSE, scratch_pool));
-  if (wc_kind == svn_node_none)
-    {
-      if (make_parents)
-        SVN_ERR(svn_client__make_local_parents(dir_abspath, make_parents, ctx,
-                                               scratch_pool));
-
-      SVN_ERR(svn_wc_read_kind2(&wc_kind, ctx->wc_ctx, dir_abspath,
-                                FALSE, FALSE, scratch_pool));
-    }
-  if (wc_kind != svn_node_dir)
-    return svn_error_createf(
-                SVN_ERR_ENTRY_NOT_FOUND, NULL,
-                _("Can't add '%s', because no parent directory is found"),
-                svn_dirent_local_style(dst_abspath, scratch_pool));
-
-  if (kind == svn_node_file)
-    {
-      svn_stream_t *target;
-      apr_hash_t *props;
-      apr_hash_index_t *hi;
-      SVN_ERR(svn_stream_open_writable(&target, dst_abspath, scratch_pool,
-                                       scratch_pool));
-
-      SVN_ERR(svn_ra_get_file(ra_session, "", loc->rev, target, NULL, &props,
-                              scratch_pool));
-
-      if (props != NULL)
-        for (hi = apr_hash_first(scratch_pool, props); hi;
-             hi = apr_hash_next(hi))
-          {
-            const char *name = apr_hash_this_key(hi);
-
-            if (svn_property_kind2(name) != svn_prop_regular_kind
-                || ! strcmp(name, SVN_PROP_MERGEINFO))
-              {
-                /* We can't handle DAV, ENTRY and merge specific props here */
-                svn_hash_sets(props, name, NULL);
-              }
-          }
-
-      SVN_ERR(svn_wc_add_from_disk3(ctx->wc_ctx, dst_abspath, props,
-                                    TRUE /* skip checks */,
-                                    ctx->notify_func2, ctx->notify_baton2,
-                                    scratch_pool));
-    }
-  else
-    {
-      SVN_ERR(copy_foreign_dir(ra_session, loc,
-                               dst_abspath,
-                               depth,
-                               ctx->notify_func2, ctx->notify_baton2,
-                               ctx->cancel_func, ctx->cancel_baton,
-                               ctx, scratch_pool));
-    }
-
-  return SVN_NO_ERROR;
-}