Modified: subversion/branches/swig-py3/subversion/libsvn_client/copy.c
URL: 
http://svn.apache.org/viewvc/subversion/branches/swig-py3/subversion/libsvn_client/copy.c?rev=1847678&r1=1847677&r2=1847678&view=diff
==============================================================================
--- subversion/branches/swig-py3/subversion/libsvn_client/copy.c (original)
+++ subversion/branches/swig-py3/subversion/libsvn_client/copy.c Wed Nov 28 
21:25:32 2018
@@ -578,7 +578,7 @@ pin_externals_prop(svn_string_t **pinned
 static svn_error_t *
 resolve_pinned_externals(apr_hash_t **pinned_externals,
                          const apr_hash_t *externals_to_pin,
-                         svn_client__copy_pair_t *pair,
+                         const svn_client__copy_pair_t *pair,
                          svn_ra_session_t *ra_session,
                          const char *repos_root_url,
                          svn_client_ctx_t *ctx,
@@ -1100,13 +1100,9 @@ verify_wc_dsts(const apr_array_header_t
 }
 
 static svn_error_t *
-verify_wc_srcs_and_dsts(const apr_array_header_t *copy_pairs,
-                        svn_boolean_t make_parents,
-                        svn_boolean_t is_move,
-                        svn_boolean_t metadata_only,
-                        svn_client_ctx_t *ctx,
-                        apr_pool_t *result_pool,
-                        apr_pool_t *scratch_pool)
+verify_wc_srcs(const apr_array_header_t *copy_pairs,
+               svn_client_ctx_t *ctx,
+               apr_pool_t *scratch_pool)
 {
   int i;
   apr_pool_t *iterpool = svn_pool_create(scratch_pool);
@@ -1133,10 +1129,6 @@ verify_wc_srcs_and_dsts(const apr_array_
                                         pair->src_abspath_or_url,
                                         scratch_pool));
     }
-
-  SVN_ERR(verify_wc_dsts(copy_pairs, make_parents, is_move, metadata_only, ctx,
-                         result_pool, iterpool));
-
   svn_pool_destroy(iterpool);
 
   return SVN_NO_ERROR;
@@ -2318,9 +2310,15 @@ struct notification_adjust_baton
 };
 
 /* A svn_wc_notify_func2_t function that wraps BATON->inner_func (whose
- * baton is BATON->inner_baton) and adjusts the notification paths that
- * start with BATON->checkout_abspath to start instead with
- * BATON->final_abspath. */
+ * baton is BATON->inner_baton) to turn the result of a 'checkout' into
+ * what we want to see for a 'copy to WC' operation.
+ *
+ *  - Adjust the notification paths that start with BATON->checkout_abspath
+ *    to start instead with BATON->final_abspath.
+ *  - Change start-of-update notification into a plain WC 'add' for the root.
+ *  - Change checkout 'add' notifications into a plain WC 'add'.
+ *  - Discard 'update_completed' notifications.
+ */
 static void
 notification_adjust_func(void *baton,
                          const svn_wc_notify_t *notify,
@@ -2333,17 +2331,182 @@ notification_adjust_func(void *baton,
   relpath = svn_dirent_skip_ancestor(nb->checkout_abspath, notify->path);
   inner_notify->path = svn_dirent_join(nb->final_abspath, relpath, pool);
 
+  /* Convert 'update' notifications to plain 'add' notifications; discard
+     notifications about checkout/update starting/finishing. */
+  if (notify->action == svn_wc_notify_update_started  /* root */
+      || notify->action == svn_wc_notify_update_add)  /* non-root */
+    {
+      inner_notify->action = svn_wc_notify_add;
+    }
+  else if (notify->action == svn_wc_notify_update_update
+           || notify->action == svn_wc_notify_update_completed)
+    {
+      /* update_update happens only for a prop mod on root; the root was
+         already notified so discard this */
+      return;
+    }
+
   if (nb->inner_func)
     nb->inner_func(nb->inner_baton, inner_notify, pool);
 }
 
+svn_error_t *
+svn_client__repos_to_wc_copy_dir(svn_boolean_t *timestamp_sleep,
+                                 const char *src_url,
+                                 svn_revnum_t src_revnum,
+                                 const char *dst_abspath,
+                                 svn_boolean_t ignore_externals,
+                                 svn_boolean_t same_repositories,
+                                 svn_ra_session_t *ra_session,
+                                 svn_client_ctx_t *ctx,
+                                 apr_pool_t *scratch_pool)
+{
+  const char *tmpdir_abspath, *tmp_abspath;
+
+  SVN_ERR_ASSERT(svn_dirent_is_absolute(dst_abspath));
+
+  if (!same_repositories)
+    {
+      svn_client__pathrev_t *location;
+
+      *timestamp_sleep = TRUE;
+
+      SVN_ERR(svn_client__pathrev_create_with_session(&location, ra_session,
+                                                      src_revnum, src_url,
+                                                      scratch_pool));
+      SVN_ERR(svn_client__copy_foreign(location,
+                                       dst_abspath,
+                                       svn_depth_infinity,
+                                       ra_session,
+                                       ctx, scratch_pool));
+
+      return SVN_NO_ERROR;
+    }
+
+  /* Find a temporary location in which to check out the copy source. */
+  SVN_ERR(svn_wc__get_tmpdir(&tmpdir_abspath, ctx->wc_ctx, dst_abspath,
+                             scratch_pool, scratch_pool));
+
+  /* Get a temporary path. The crude way we do this is to create a
+     temporary file, remember its name, and let it be deleted immediately. */
+  SVN_ERR(svn_io_open_unique_file3(NULL, &tmp_abspath, tmpdir_abspath,
+                                   svn_io_file_del_on_close,
+                                   scratch_pool, scratch_pool));
+
+  /* Make a new checkout of the requested source. While doing so,
+   * resolve copy_src_revnum to an actual revision number in case it
+   * was until now 'invalid' meaning 'head'.  Ask this function not to
+   * sleep for timestamps, by passing a sleep_needed output param.
+   * Send notifications for all nodes except the root node, and adjust
+   * them to refer to the destination rather than this temporary path. */
+  {
+    svn_wc_notify_func2_t old_notify_func2 = ctx->notify_func2;
+    void *old_notify_baton2 = ctx->notify_baton2;
+    struct notification_adjust_baton nb;
+    svn_error_t *err;
+    svn_opt_revision_t copy_src_revision;
+
+    copy_src_revision.kind = svn_opt_revision_number;
+    copy_src_revision.value.number = src_revnum;
+
+    nb.inner_func = ctx->notify_func2;
+    nb.inner_baton = ctx->notify_baton2;
+    nb.checkout_abspath = tmp_abspath;
+    nb.final_abspath = dst_abspath;
+    ctx->notify_func2 = notification_adjust_func;
+    ctx->notify_baton2 = &nb;
+
+    err = svn_client__checkout_internal(NULL /*result_rev*/, timestamp_sleep,
+                                        src_url,
+                                        tmp_abspath,
+                                        &copy_src_revision,
+                                        &copy_src_revision,
+                                        svn_depth_infinity,
+                                        ignore_externals,
+                                        FALSE, /* we don't allow obstructions 
*/
+                                        ra_session, ctx, scratch_pool);
+
+    ctx->notify_func2 = old_notify_func2;
+    ctx->notify_baton2 = old_notify_baton2;
+
+    SVN_ERR(err);
+  }
+
+  /* Schedule dst_path for addition in parent, with copy history.
+     Don't send any notification here.
+     Then remove the temporary checkout's .svn dir in preparation for
+     moving the rest of it into the final destination. */
+  SVN_ERR(svn_wc_copy3(ctx->wc_ctx, tmp_abspath, dst_abspath,
+                       TRUE /* metadata_only */,
+                       NULL, NULL, /* don't allow user to cancel here */
+                       NULL, NULL, scratch_pool));
+  SVN_ERR(svn_wc__acquire_write_lock(NULL, ctx->wc_ctx, tmp_abspath,
+                                     FALSE, scratch_pool, scratch_pool));
+  SVN_ERR(svn_wc_remove_from_revision_control2(ctx->wc_ctx,
+                                               tmp_abspath,
+                                               FALSE, FALSE,
+                                               NULL, NULL, /* don't cancel */
+                                               scratch_pool));
+
+  /* Move the temporary disk tree into place. */
+  SVN_ERR(svn_io_file_rename2(tmp_abspath, dst_abspath, FALSE, scratch_pool));
+
+  return SVN_NO_ERROR;
+}
+
+svn_error_t *
+svn_client__repos_to_wc_copy_file(svn_boolean_t *timestamp_sleep,
+                                  const char *src_url,
+                                  svn_revnum_t src_rev,
+                                  const char *dst_abspath,
+                                  svn_boolean_t same_repositories,
+                                  svn_ra_session_t *ra_session,
+                                  svn_client_ctx_t *ctx,
+                                  apr_pool_t *scratch_pool)
+{
+  const char *src_rel;
+  apr_hash_t *new_props;
+  svn_stream_t *new_base_contents = svn_stream_buffered(scratch_pool);
+
+  SVN_ERR(svn_ra_get_path_relative_to_session(ra_session, &src_rel, src_url,
+                                              scratch_pool));
+  /* Fetch the file content. */
+  SVN_ERR(svn_ra_get_file(ra_session, src_rel, src_rev,
+                          new_base_contents, NULL, &new_props,
+                          scratch_pool));
+  if (!same_repositories)
+    svn_hash_sets(new_props, SVN_PROP_MERGEINFO, NULL);
+
+  *timestamp_sleep = TRUE;
+  SVN_ERR(svn_wc_add_repos_file4(
+            ctx->wc_ctx, dst_abspath,
+            new_base_contents, NULL, new_props, NULL,
+            same_repositories ? src_url : NULL,
+            same_repositories ? src_rev : SVN_INVALID_REVNUM,
+            ctx->cancel_func, ctx->cancel_baton,
+            scratch_pool));
+  /* Do our own notification for the root node, even if we could possibly
+     have delegated it.  See also issue #2198. */
+  if (ctx->notify_func2)
+    {
+      svn_wc_notify_t *notify
+        = svn_wc_create_notify(dst_abspath, svn_wc_notify_add, scratch_pool);
+
+      notify->kind = svn_node_file;
+      ctx->notify_func2(ctx->notify_baton2, notify, scratch_pool);
+    }
+  return SVN_NO_ERROR;
+}
+
 /* Peform each individual copy operation for a repos -> wc copy.  A
    helper for repos_to_wc_copy().
 
-   Resolve PAIR->src_revnum to a real revision number if it isn't already. */
+   PAIR->src_revnum PAIR->src_abspath_or_url should already have been
+   resolved to the operative revision number and operative URL.
+ */
 static svn_error_t *
 repos_to_wc_copy_single(svn_boolean_t *timestamp_sleep,
-                        svn_client__copy_pair_t *pair,
+                        const svn_client__copy_pair_t *pair,
                         svn_boolean_t same_repositories,
                         svn_boolean_t ignore_externals,
                         svn_boolean_t pin_externals,
@@ -2355,6 +2518,8 @@ repos_to_wc_copy_single(svn_boolean_t *t
   apr_hash_t *src_mergeinfo;
   const char *dst_abspath = pair->dst_abspath_or_url;
 
+  SVN_ERR_ASSERT(SVN_IS_VALID_REVNUM(pair->src_revnum));
+  SVN_ERR_ASSERT(svn_path_is_url(pair->src_abspath_or_url));
   SVN_ERR_ASSERT(svn_dirent_is_absolute(dst_abspath));
 
   if (!same_repositories && ctx->notify_func2)
@@ -2374,98 +2539,23 @@ repos_to_wc_copy_single(svn_boolean_t *t
 
   if (pair->src_kind == svn_node_dir)
     {
-      if (same_repositories)
-        {
-          const char *tmpdir_abspath, *tmp_abspath;
-
-          /* Find a temporary location in which to check out the copy source. 
*/
-          SVN_ERR(svn_wc__get_tmpdir(&tmpdir_abspath, ctx->wc_ctx, dst_abspath,
-                                     pool, pool));
-
-          SVN_ERR(svn_io_open_unique_file3(NULL, &tmp_abspath, tmpdir_abspath,
-                                           svn_io_file_del_on_close, pool, 
pool));
-
-          /* Make a new checkout of the requested source. While doing so,
-           * resolve pair->src_revnum to an actual revision number in case it
-           * was until now 'invalid' meaning 'head'.  Ask this function not to
-           * sleep for timestamps, by passing a sleep_needed output param.
-           * Send notifications for all nodes except the root node, and adjust
-           * them to refer to the destination rather than this temporary path. 
*/
-          {
-            svn_wc_notify_func2_t old_notify_func2 = ctx->notify_func2;
-            void *old_notify_baton2 = ctx->notify_baton2;
-            struct notification_adjust_baton nb;
-            svn_error_t *err;
-
-            nb.inner_func = ctx->notify_func2;
-            nb.inner_baton = ctx->notify_baton2;
-            nb.checkout_abspath = tmp_abspath;
-            nb.final_abspath = dst_abspath;
-            ctx->notify_func2 = notification_adjust_func;
-            ctx->notify_baton2 = &nb;
-
-            /* Avoid a chicken-and-egg problem:
-             * If pinning externals we'll need to adjust externals
-             * properties before checking out any externals.
-             * But copy needs to happen before pinning because else there
-             * are no svn:externals properties to pin. */
-            if (pin_externals)
-              ignore_externals = TRUE;
-
-            err = svn_client__checkout_internal(&pair->src_revnum, 
timestamp_sleep,
-                                                pair->src_original,
-                                                tmp_abspath,
-                                                &pair->src_peg_revision,
-                                                &pair->src_op_revision,
-                                                svn_depth_infinity,
-                                                ignore_externals, FALSE,
-                                                ra_session, ctx, pool);
-
-            ctx->notify_func2 = old_notify_func2;
-            ctx->notify_baton2 = old_notify_baton2;
-
-            SVN_ERR(err);
-          }
-
-          *timestamp_sleep = TRUE;
-
-          /* Schedule dst_path for addition in parent, with copy history.
-             Don't send any notification here.
-             Then remove the temporary checkout's .svn dir in preparation for
-             moving the rest of it into the final destination. */
-          SVN_ERR(svn_wc_copy3(ctx->wc_ctx, tmp_abspath, dst_abspath,
-                               TRUE /* metadata_only */,
-                               ctx->cancel_func, ctx->cancel_baton,
-                               NULL, NULL, pool));
-          SVN_ERR(svn_wc__acquire_write_lock(NULL, ctx->wc_ctx, tmp_abspath,
-                                             FALSE, pool, pool));
-          SVN_ERR(svn_wc_remove_from_revision_control2(ctx->wc_ctx,
-                                                       tmp_abspath,
-                                                       FALSE, FALSE,
-                                                       ctx->cancel_func,
-                                                       ctx->cancel_baton,
-                                                       pool));
-
-          /* Move the temporary disk tree into place. */
-          SVN_ERR(svn_io_file_rename2(tmp_abspath, dst_abspath, FALSE, pool));
-        }
-      else
-        {
-          *timestamp_sleep = TRUE;
+      /* Avoid a chicken-and-egg problem:
+       * If pinning externals we'll need to adjust externals
+       * properties before checking out any externals.
+       * But copy needs to happen before pinning because else there
+       * are no svn:externals properties to pin. */
+      if (pin_externals)
+        ignore_externals = TRUE;
 
-          SVN_ERR(svn_client__copy_foreign(pair->src_abspath_or_url,
-                                           dst_abspath,
-                                           &pair->src_peg_revision,
-                                           &pair->src_op_revision,
-                                           svn_depth_infinity,
-                                           FALSE /* make_parents */,
-                                           TRUE /* already_locked */,
-                                           ctx, pool));
+      SVN_ERR(svn_client__repos_to_wc_copy_dir(timestamp_sleep,
+                                               pair->src_abspath_or_url,
+                                               pair->src_revnum,
+                                               dst_abspath,
+                                               ignore_externals,
+                                               same_repositories,
+                                               ra_session, ctx, pool));
 
-          return SVN_NO_ERROR;
-        }
-
-      if (pin_externals)
+      if (same_repositories && pin_externals)
         {
           apr_hash_t *pinned_externals;
           apr_hash_index_t *hi;
@@ -2523,51 +2613,28 @@ repos_to_wc_copy_single(svn_boolean_t *t
 
   else if (pair->src_kind == svn_node_file)
     {
-      apr_hash_t *new_props;
-      const char *src_rel;
-      svn_stream_t *new_base_contents = svn_stream_buffered(pool);
-
-      SVN_ERR(svn_ra_get_path_relative_to_session(ra_session, &src_rel,
-                                                  pair->src_abspath_or_url,
-                                                  pool));
-      /* Fetch the file content. While doing so, resolve pair->src_revnum
-       * to an actual revision number if it's 'invalid' meaning 'head'. */
-      SVN_ERR(svn_ra_get_file(ra_session, src_rel, pair->src_revnum,
-                              new_base_contents,
-                              &pair->src_revnum, &new_props, pool));
-
-      if (new_props && ! same_repositories)
-        svn_hash_sets(new_props, SVN_PROP_MERGEINFO, NULL);
-
-      *timestamp_sleep = TRUE;
-
-      SVN_ERR(svn_wc_add_repos_file4(
-         ctx->wc_ctx, dst_abspath,
-         new_base_contents, NULL, new_props, NULL,
-         same_repositories ? pair->src_abspath_or_url : NULL,
-         same_repositories ? pair->src_revnum : SVN_INVALID_REVNUM,
-         ctx->cancel_func, ctx->cancel_baton,
-         pool));
-    }
-
-  /* Record the implied mergeinfo (before the notification callback
-     is invoked for the root node). */
-  SVN_ERR(svn_client__get_repos_mergeinfo(
-            &src_mergeinfo, ra_session,
-            pair->src_abspath_or_url, pair->src_revnum,
-            svn_mergeinfo_inherited, TRUE /*squelch_incapable*/, pool));
-  SVN_ERR(extend_wc_mergeinfo(dst_abspath, src_mergeinfo, ctx, pool));
-
-  /* Do our own notification for the root node, even if we could possibly
-     have delegated it.  See also issue #1552.
+      SVN_ERR(svn_client__repos_to_wc_copy_file(timestamp_sleep,
+                                                pair->src_abspath_or_url,
+                                                pair->src_revnum,
+                                                dst_abspath,
+                                                same_repositories,
+                                                ra_session,
+                                                ctx, pool));
+    }
+
+  if (same_repositories)
+    {
+      /* Record the implied mergeinfo (before the notification callback
+         is invoked for the root node). */
+      SVN_ERR(svn_client__get_repos_mergeinfo(&src_mergeinfo, ra_session,
+                                              pair->src_abspath_or_url,
+                                              pair->src_revnum,
+                                              svn_mergeinfo_inherited,
+                                              TRUE /*squelch_incapable*/,
+                                              pool));
+      SVN_ERR(extend_wc_mergeinfo(dst_abspath, src_mergeinfo, ctx, pool));
 
-     ### Maybe this notification should mention the mergeinfo change. */
-  if (ctx->notify_func2)
-    {
-      svn_wc_notify_t *notify = svn_wc_create_notify(
-                                  dst_abspath, svn_wc_notify_add, pool);
-      notify->kind = pair->src_kind;
-      ctx->notify_func2(ctx->notify_baton2, notify, pool);
+      /* ### Maybe the notification should mention this mergeinfo change. */
     }
 
   return SVN_NO_ERROR;
@@ -2588,12 +2655,6 @@ repos_to_wc_copy_locked(svn_boolean_t *t
   svn_boolean_t same_repositories;
   apr_pool_t *iterpool = svn_pool_create(scratch_pool);
 
-  /* We've already checked for physical obstruction by a working file.
-     But there could also be logical obstruction by an entry whose
-     working file happens to be missing.*/
-  SVN_ERR(verify_wc_dsts(copy_pairs, FALSE, FALSE, FALSE /* metadata_only */,
-                         ctx, scratch_pool, iterpool));
-
   /* Decide whether the two repositories are the same or not. */
   {
     const char *parent_abspath;
@@ -2642,7 +2703,6 @@ repos_to_wc_copy_locked(svn_boolean_t *t
 static svn_error_t *
 repos_to_wc_copy(svn_boolean_t *timestamp_sleep,
                  const apr_array_header_t *copy_pairs,
-                 svn_boolean_t make_parents,
                  svn_boolean_t ignore_externals,
                  svn_boolean_t pin_externals,
                  const apr_hash_t *externals_to_pin,
@@ -2696,8 +2756,6 @@ repos_to_wc_copy(svn_boolean_t *timestam
     {
       svn_client__copy_pair_t *pair = APR_ARRAY_IDX(copy_pairs, i,
                                                     svn_client__copy_pair_t *);
-      svn_node_kind_t dst_parent_kind, dst_kind;
-      const char *dst_parent;
       const char *src_rel;
 
       svn_pool_clear(iterpool);
@@ -2721,33 +2779,6 @@ repos_to_wc_copy(svn_boolean_t *timestam
                _("Path '%s' not found in head revision"),
                pair->src_abspath_or_url);
         }
-
-      /* Figure out about dst. */
-      SVN_ERR(svn_io_check_path(pair->dst_abspath_or_url, &dst_kind,
-                                iterpool));
-      if (dst_kind != svn_node_none)
-        {
-          return svn_error_createf(
-            SVN_ERR_ENTRY_EXISTS, NULL,
-            _("Path '%s' already exists"),
-            svn_dirent_local_style(pair->dst_abspath_or_url, pool));
-        }
-
-      /* Make sure the destination parent is a directory and produce a clear
-         error message if it is not. */
-      dst_parent = svn_dirent_dirname(pair->dst_abspath_or_url, iterpool);
-      SVN_ERR(svn_io_check_path(dst_parent, &dst_parent_kind, iterpool));
-      if (make_parents && dst_parent_kind == svn_node_none)
-        {
-          SVN_ERR(svn_client__make_local_parents(dst_parent, TRUE, ctx,
-                                                 iterpool));
-        }
-      else if (dst_parent_kind != svn_node_dir)
-        {
-          return svn_error_createf(SVN_ERR_WC_NOT_WORKING_COPY, NULL,
-                                   _("Path '%s' is not a directory"),
-                                   svn_dirent_local_style(dst_parent, pool));
-        }
     }
   svn_pool_destroy(iterpool);
 
@@ -3070,8 +3101,9 @@ try_copy(svn_boolean_t *timestamp_sleep,
   /* Now, call the right handler for the operation. */
   if ((! srcs_are_urls) && (! dst_is_url))
     {
-      SVN_ERR(verify_wc_srcs_and_dsts(copy_pairs, make_parents, is_move,
-                                      metadata_only, ctx, pool, pool));
+      SVN_ERR(verify_wc_srcs(copy_pairs, ctx, pool));
+      SVN_ERR(verify_wc_dsts(copy_pairs, make_parents, is_move, metadata_only,
+                             ctx, pool, pool));
 
       /* Copy or move all targets. */
       if (is_move)
@@ -3101,9 +3133,13 @@ try_copy(svn_boolean_t *timestamp_sleep,
     }
   else if ((srcs_are_urls) && (! dst_is_url))
     {
+      SVN_ERR(verify_wc_dsts(copy_pairs, make_parents,
+                             FALSE, FALSE /* metadata_only */,
+                             ctx, pool, pool));
+
       return svn_error_trace(
         repos_to_wc_copy(timestamp_sleep,
-                         copy_pairs, make_parents, ignore_externals,
+                         copy_pairs, ignore_externals,
                          pin_externals, externals_to_pin, ctx, pool));
     }
   else

Modified: subversion/branches/swig-py3/subversion/libsvn_client/copy_foreign.c
URL: 
http://svn.apache.org/viewvc/subversion/branches/swig-py3/subversion/libsvn_client/copy_foreign.c?rev=1847678&r1=1847677&r2=1847678&view=diff
==============================================================================
--- subversion/branches/swig-py3/subversion/libsvn_client/copy_foreign.c 
(original)
+++ subversion/branches/swig-py3/subversion/libsvn_client/copy_foreign.c Wed 
Nov 28 21:25:32 2018
@@ -38,395 +38,52 @@
 #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"
 
-struct edit_baton_t
-{
-  apr_pool_t *pool;
-  const char *anchor_abspath;
-
-  svn_wc_context_t *wc_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;
-  apr_hash_t *properties;
-
-  int users;
-};
-
-/* 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;
-
-  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 *
-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 *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));
-  svn_boolean_t under_root;
-
-  pb->users++;
-
-  db->pb = pb;
-  db->eb = pb->eb;
-  db->pool = dir_pool;
-  db->users = 1;
-
-  SVN_ERR(svn_dirent_is_under_root(&under_root, &db->local_abspath,
-                                   eb->anchor_abspath, path, db->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, db->pool));
-    }
-
-  SVN_ERR(svn_io_make_dir_recursively(db->local_abspath, 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
-      || ! strcmp(name, SVN_PROP_MERGEINFO))
-    {
-      /* We can't handle DAV, ENTRY and merge specific props here */
-      return SVN_NO_ERROR;
-    }
-
-  if (! db->created)
-    {
-      /* We can still store them in the hash for immediate addition
-         with the svn_wc_add_from_disk3() call */
-      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
-    {
-      /* We have already notified for this directory, so don't do that again */
-      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;
-  apr_hash_t *properties;
-
-  svn_boolean_t writing;
-  unsigned char digest[APR_MD5_DIGESTSIZE];
-
-  const char *tmp_path;
-};
-
-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 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));
-  svn_boolean_t under_root;
-
-  pb->users++;
-
-  fb->pool = file_pool;
-  fb->eb = eb;
-  fb->pb = pb;
-
-  SVN_ERR(svn_dirent_is_under_root(&under_root, &fb->local_abspath,
-                                   eb->anchor_abspath, path, fb->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, fb->pool));
-    }
-
-  *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;
-  svn_prop_kind_t prop_kind;
-
-  prop_kind = svn_property_kind2(name);
-
-  if (prop_kind != svn_prop_regular_kind
-      || ! strcmp(name, SVN_PROP_MERGEINFO))
-    {
-      /* We can't handle DAV, ENTRY and merge specific props here */
-      return SVN_NO_ERROR;
-    }
-
-  /* We store all properties in the hash for immediate addition
-      with the svn_wc_add_from_disk3() call */
-  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));
-
-  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 *
-file_close(void *file_baton,
-           const char *text_checksum,
-           apr_pool_t *scratch_pool)
-{
-  struct file_baton_t *fb = file_baton;
-  struct edit_baton_t *eb = fb->eb;
-  struct dir_baton_t *pb = fb->pb;
-
-  SVN_ERR(ensure_added(pb, fb->pool));
-
-  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(svn_wc_add_from_disk3(eb->wc_ctx, fb->local_abspath, fb->properties,
-                                TRUE /* skip checks */,
-                                eb->notify_func, eb->notify_baton,
-                                fb->pool));
-
-  svn_pool_destroy(fb->pool);
-  SVN_ERR(maybe_done(pb));
-
-  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,
-                 svn_wc_context_t *wc_ctx,
+                 const 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)
 {
-  struct edit_baton_t eb;
-  svn_delta_editor_t *editor = svn_delta_default_editor(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;
 
-  eb.pool = scratch_pool;
-  eb.anchor_abspath = dst_abspath;
-
-  eb.wc_ctx = wc_ctx;
-  eb.notify_func = notify_func;
-  eb.notify_baton  = notify_baton;
-
-  editor->open_root = edit_open;
-  editor->close_edit = edit_close;
-
-  editor->add_directory = dir_add;
-  editor->change_dir_prop = dir_change_prop;
-  editor->close_directory = dir_close;
-
-  editor->add_file = file_add;
-  editor->change_file_prop = file_change_prop;
-  editor->apply_textdelta = file_textdelta;
-  editor->close_file = file_close;
+  /* Get a WC editor. It does not need an RA session because we will not
+     be sending it any 'copy from' requests, only 'add' requests. */
+  SVN_ERR(svn_client__wc_editor_internal(&editor, &eb,
+                                         dst_abspath,
+                                         TRUE /*root_dir_add*/,
+                                         TRUE /*ignore_mergeinfo_changes*/,
+                                         notify_func, notify_baton,
+                                         NULL /*ra_session*/,
+                                         ctx, scratch_pool));
 
   SVN_ERR(svn_delta_get_cancellation_editor(cancel_func, cancel_baton,
-                                            editor, &eb,
+                                            editor, eb,
                                             &wrapped_editor, &wrapped_baton,
                                             scratch_pool));
 
@@ -446,72 +103,26 @@ copy_foreign_dir(svn_ra_session_t *ra_se
 
 
 svn_error_t *
-svn_client__copy_foreign(const char *url,
+svn_client__copy_foreign(const svn_client__pathrev_t *loc,
                          const char *dst_abspath,
-                         svn_opt_revision_t *peg_revision,
-                         svn_opt_revision_t *revision,
                          svn_depth_t depth,
-                         svn_boolean_t make_parents,
-                         svn_boolean_t already_locked,
+                         svn_ra_session_t *ra_session,
                          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));
+  SVN_ERR(svn_ra_reparent(ra_session, loc->url, 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);
-
-  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));
-    }
-
-  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));
-
+                loc->url);
 
   if (kind == svn_node_file)
     {
@@ -538,37 +149,19 @@ svn_client__copy_foreign(const char *url
               }
           }
 
-      if (!already_locked)
-        SVN_WC__CALL_WITH_WRITE_LOCK(
-              svn_wc_add_from_disk3(ctx->wc_ctx, dst_abspath, props,
+      SVN_ERR(svn_wc_add_from_disk3(ctx->wc_ctx, dst_abspath, props,
                                     TRUE /* skip checks */,
                                     ctx->notify_func2, ctx->notify_baton2,
-                                    scratch_pool),
-              ctx->wc_ctx, dir_abspath, FALSE, scratch_pool);
-      else
-        SVN_ERR(svn_wc_add_from_disk3(ctx->wc_ctx, dst_abspath, props,
-                                      TRUE /* skip checks */,
-                                      ctx->notify_func2, ctx->notify_baton2,
-                                      scratch_pool));
+                                    scratch_pool));
     }
   else
     {
-      if (!already_locked)
-        SVN_WC__CALL_WITH_WRITE_LOCK(
-              copy_foreign_dir(ra_session, loc,
-                               ctx->wc_ctx, dst_abspath,
+      SVN_ERR(copy_foreign_dir(ra_session, loc,
+                               dst_abspath,
                                depth,
                                ctx->notify_func2, ctx->notify_baton2,
                                ctx->cancel_func, ctx->cancel_baton,
-                               scratch_pool),
-              ctx->wc_ctx, dir_abspath, FALSE, scratch_pool);
-      else
-        SVN_ERR(copy_foreign_dir(ra_session, loc,
-                                 ctx->wc_ctx, dst_abspath,
-                                 depth,
-                                 ctx->notify_func2, ctx->notify_baton2,
-                                 ctx->cancel_func, ctx->cancel_baton,
-                                 scratch_pool));
+                               ctx, scratch_pool));
     }
 
   return SVN_NO_ERROR;

Modified: subversion/branches/swig-py3/subversion/libsvn_client/deprecated.c
URL: 
http://svn.apache.org/viewvc/subversion/branches/swig-py3/subversion/libsvn_client/deprecated.c?rev=1847678&r1=1847677&r2=1847678&view=diff
==============================================================================
--- subversion/branches/swig-py3/subversion/libsvn_client/deprecated.c 
(original)
+++ subversion/branches/swig-py3/subversion/libsvn_client/deprecated.c Wed Nov 
28 21:25:32 2018
@@ -1726,7 +1726,7 @@ svn_client_log(const apr_array_header_t
    * we just invoke the receiver manually on a hand-constructed log
    * message for revision 0.
    *
-   * See also http://subversion.tigris.org/issues/show_bug.cgi?id=692.
+   * See also https://issues.apache.org/jira/browse/SVN-692.
    */
   if (err && (err->apr_err == SVN_ERR_FS_NO_SUCH_REVISION)
       && (start->kind == svn_opt_revision_head)


Reply via email to