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/12/14 13:20:19 UTC

svn commit: r1848937 - in /subversion/trunk/subversion: include/private/svn_client_private.h libsvn_client/conflicts.c libsvn_client/copy.c libsvn_client/wc_editor.c tests/libsvn_client/client-test.c

Author: julianfoad
Date: Fri Dec 14 13:20:19 2018
New Revision: 1848937

URL: http://svn.apache.org/viewvc?rev=1848937&view=rev
Log:
Let repository-to-WC copies go through the WC editor.

For issue #4786 "Create a WC working-mods editor".

Similar to the patch committed in r1848892 and reverted in r1848897, except
that attempt failed on Windows because it created the copy target root
directory twice.

* subversion/include/private/svn_client_private.h
  (svn_client__repos_to_wc_copy): Rename to
    'svn_client__repos_to_wc_copy_internal'.
  (svn_client__repos_to_wc_copy_by_editor): New.

* subversion/libsvn_client/conflicts.c
  (merge_incoming_added_dir_replace): Update to use
    'svn_client__repos_to_wc_copy_by_editor'.

* subversion/libsvn_client/copy.c
  (copy_foreign_dir): Remove 'depth' parameter: not needed and was wrongly
    implemented anyway.
  (svn_client__repos_to_wc_copy_dir): Adjust caller.
  (is_same_repository): New, moved from 'wc_editor.c'.
  (svn_client__repos_to_wc_copy_by_editor): New.
  (svn_client__repos_to_wc_copy,
   repos_to_wc_copy_single): Determine same-repository here and here...
  (repos_to_wc_copy_locked): ... instead of here.

* subversion/libsvn_client/wc_editor.c
  (is_same_repository): Delete; moved to 'copy.c'.
  (dir_add,
   file_add): Don't determine same-repository here. Do set the 'created' flag.

* subversion/tests/libsvn_client/client-test.c
  (test_foreign_repos_copy): Update caller.

Modified:
    subversion/trunk/subversion/include/private/svn_client_private.h
    subversion/trunk/subversion/libsvn_client/conflicts.c
    subversion/trunk/subversion/libsvn_client/copy.c
    subversion/trunk/subversion/libsvn_client/wc_editor.c
    subversion/trunk/subversion/tests/libsvn_client/client-test.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=1848937&r1=1848936&r2=1848937&view=diff
==============================================================================
--- subversion/trunk/subversion/include/private/svn_client_private.h (original)
+++ subversion/trunk/subversion/include/private/svn_client_private.h Fri Dec 14 13:20:19 2018
@@ -398,10 +398,7 @@ svn_client__get_diff_summarize_callbacks
  * The caller should be holding a WC write lock that allows DST_ABSPATH to
  * be created, such as on the parent of DST_ABSPATH.
  *
- * SAME_REPOSITORIES must be true if and only if the source of this copy
- * is from the same repository at the WC parent of DST_ABSPATH.
- * If SAME_REPOSITORIES, then fill in the 'copy-from' in the WC target.
- * If not SAME_REPOSITORIES, then remove any svn:mergeinfo property.
+ * If not same repositories, then remove any svn:mergeinfo property.
  *
  * Use RA_SESSION to fetch the data. The session may point to a different
  * URL after returning.
@@ -410,16 +407,39 @@ svn_client__get_diff_summarize_callbacks
  * on copied directories.
  */
 svn_error_t *
-svn_client__repos_to_wc_copy(svn_boolean_t *timestamp_sleep,
+svn_client__repos_to_wc_copy_internal(svn_boolean_t *timestamp_sleep,
                              svn_node_kind_t kind,
                              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);
 
+/* Copy a directory tree or a file (according to KIND) from SRC_URL @ SRC_REV,
+ * to DST_ABSPATH in a WC.
+ *
+ * The caller should be holding a WC write lock that allows DST_ABSPATH to
+ * be created, such as on the parent of DST_ABSPATH.
+ *
+ * If not same repositories, then remove any svn:mergeinfo property.
+ *
+ * Use RA_SESSION to fetch the data. The session may point to a different
+ * URL after returning.
+ *
+ * This API does not process any externals definitions that may be present
+ * on copied directories.
+ */
+svn_error_t *
+svn_client__repos_to_wc_copy_by_editor(svn_boolean_t *timestamp_sleep,
+                svn_node_kind_t kind,
+                const char *src_url,
+                svn_revnum_t src_rev,
+                const char *dst_abspath,
+                svn_ra_session_t *ra_session,
+                svn_client_ctx_t *ctx,
+                apr_pool_t *scratch_pool);
+
 /** Return an editor for applying local modifications to a WC.
  *
  * Return an editor in @a *editor_p, @a *edit_baton_p that will apply

Modified: subversion/trunk/subversion/libsvn_client/conflicts.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_client/conflicts.c?rev=1848937&r1=1848936&r2=1848937&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_client/conflicts.c (original)
+++ subversion/trunk/subversion/libsvn_client/conflicts.c Fri Dec 14 13:20:19 2018
@@ -8041,12 +8041,11 @@ merge_incoming_added_dir_replace(svn_cli
   if (err)
     goto unlock_wc;
 
-  err = svn_client__repos_to_wc_copy(&timestamp_sleep,
-                                     svn_node_dir,
-                                     url, incoming_new_pegrev,
-                                     local_abspath,
-                                     TRUE /*same_repositories*/,
-                                     ra_session, ctx, scratch_pool);
+  err = svn_client__repos_to_wc_copy_by_editor(&timestamp_sleep,
+                                               svn_node_dir,
+                                               url, incoming_new_pegrev,
+                                               local_abspath,
+                                               ra_session, ctx, scratch_pool);
   if (err)
     goto unlock_wc;
 

Modified: subversion/trunk/subversion/libsvn_client/copy.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_client/copy.c?rev=1848937&r1=1848936&r2=1848937&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_client/copy.c (original)
+++ subversion/trunk/subversion/libsvn_client/copy.c Fri Dec 14 13:20:19 2018
@@ -2355,7 +2355,7 @@ notification_adjust_func(void *baton,
 
 /** Copy a directory tree from a remote repository.
  *
- * Copy from RA_SESSION:LOCATION, depth DEPTH, to WC_CTX:DST_ABSPATH.
+ * Copy from RA_SESSION:LOCATION 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
@@ -2368,7 +2368,6 @@ static svn_error_t *
 copy_foreign_dir(svn_ra_session_t *ra_session,
                  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,
@@ -2403,8 +2402,9 @@ copy_foreign_dir(svn_ra_session_t *ra_se
                             FALSE, FALSE, wrapped_editor, wrapped_baton,
                             scratch_pool, scratch_pool));
 
-  SVN_ERR(reporter->set_path(reporter_baton, "", location->rev, depth,
-                             TRUE /* incomplete */,
+  SVN_ERR(reporter->set_path(reporter_baton, "", location->rev,
+                             svn_depth_infinity /* irrelevant */,
+                             TRUE /*start_empty*/,
                              NULL, scratch_pool));
 
   SVN_ERR(reporter->finish_report(reporter_baton, scratch_pool));
@@ -2440,7 +2440,6 @@ svn_client__repos_to_wc_copy_dir(svn_boo
       SVN_ERR(svn_ra_reparent(ra_session, src_url, scratch_pool));
       SVN_ERR(copy_foreign_dir(ra_session, location,
                                dst_abspath,
-                               svn_depth_infinity,
                                ctx->notify_func2, ctx->notify_baton2,
                                ctx->cancel_func, ctx->cancel_baton,
                                ctx, scratch_pool));
@@ -2568,18 +2567,43 @@ svn_client__repos_to_wc_copy_file(svn_bo
   return SVN_NO_ERROR;
 }
 
+/* Are RA_SESSION and the versioned *parent* dir of WC_TARGET_ABSPATH in
+ * the same repository?
+ */
+static svn_error_t *
+is_same_repository(svn_boolean_t *same_repository,
+                   svn_ra_session_t *ra_session,
+                   const char *wc_target_abspath,
+                   svn_client_ctx_t *ctx,
+                   apr_pool_t *scratch_pool)
+{
+  const char *src_uuid, *dst_uuid;
+
+  /* Get the repository UUIDs of copy source URL and WC parent path */
+  SVN_ERR(svn_ra_get_uuid2(ra_session, &src_uuid, scratch_pool));
+  SVN_ERR(svn_client_get_repos_root(NULL /*root_url*/, &dst_uuid,
+                                    svn_dirent_dirname(wc_target_abspath,
+                                                       scratch_pool),
+                                    ctx, scratch_pool, scratch_pool));
+  *same_repository = (strcmp(src_uuid, dst_uuid) == 0);
+  return SVN_NO_ERROR;
+}
+
 svn_error_t *
-svn_client__repos_to_wc_copy(svn_boolean_t *timestamp_sleep,
+svn_client__repos_to_wc_copy_internal(svn_boolean_t *timestamp_sleep,
                              svn_node_kind_t kind,
                              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)
 {
   svn_boolean_t timestamp_sleep_ignored;
+  svn_boolean_t same_repositories;
+
+  SVN_ERR(is_same_repository(&same_repositories,
+                             ra_session, dst_abspath, ctx, scratch_pool));
 
   if (!timestamp_sleep)
     timestamp_sleep = &timestamp_sleep_ignored;
@@ -2605,6 +2629,54 @@ svn_client__repos_to_wc_copy(svn_boolean
   return SVN_NO_ERROR;
 }
 
+svn_error_t *
+svn_client__repos_to_wc_copy_by_editor(svn_boolean_t *timestamp_sleep,
+                svn_node_kind_t kind,
+                const char *src_url,
+                svn_revnum_t src_rev,
+                const char *dst_abspath,
+                svn_ra_session_t *ra_session,
+                svn_client_ctx_t *ctx,
+                apr_pool_t *scratch_pool)
+{
+  const svn_delta_editor_t *editor;
+  void *eb;
+  const char *src_anchor = svn_uri_dirname(src_url, scratch_pool);
+  const char *dst_target = svn_dirent_basename(dst_abspath, scratch_pool);
+  void *rb, *db;
+
+  SVN_ERR(svn_ra_reparent(ra_session, src_anchor, scratch_pool));
+
+  SVN_ERR(svn_client__wc_editor(&editor, &eb,
+                                svn_dirent_dirname(dst_abspath, scratch_pool),
+                                ctx->notify_func2, ctx->notify_baton2,
+                                ra_session,
+                                ctx, scratch_pool));
+
+  SVN_ERR(editor->open_root(eb, SVN_INVALID_REVNUM, scratch_pool, &rb));
+  if (kind == svn_node_dir)
+    {
+      SVN_ERR(editor->add_directory(dst_target, rb,
+                                    src_url, src_rev,
+                                    scratch_pool,
+                                    &db));
+      SVN_ERR(editor->close_directory(db, scratch_pool));
+    }
+  else
+    {
+      SVN_ERR(editor->add_file(dst_target, rb,
+                               src_url, src_rev,
+                               scratch_pool,
+                               &db));
+      SVN_ERR(editor->close_file(db, NULL, scratch_pool));
+    }
+  SVN_ERR(editor->close_edit(eb, scratch_pool));
+
+  if (timestamp_sleep)
+    *timestamp_sleep = TRUE;
+  return SVN_NO_ERROR;
+}
+
 /* Peform each individual copy operation for a repos -> wc copy.  A
    helper for repos_to_wc_copy().
 
@@ -2614,7 +2686,6 @@ svn_client__repos_to_wc_copy(svn_boolean
 static svn_error_t *
 repos_to_wc_copy_single(svn_boolean_t *timestamp_sleep,
                         const svn_client__copy_pair_t *pair,
-                        svn_boolean_t same_repositories,
                         svn_boolean_t ignore_externals,
                         svn_boolean_t pin_externals,
                         const apr_hash_t *externals_to_pin,
@@ -2624,11 +2695,14 @@ repos_to_wc_copy_single(svn_boolean_t *t
 {
   apr_hash_t *src_mergeinfo;
   const char *dst_abspath = pair->dst_abspath_or_url;
+  svn_boolean_t same_repositories;
 
   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));
 
+  SVN_ERR(is_same_repository(&same_repositories,
+                             ra_session, dst_abspath, ctx, pool));
   if (!same_repositories && ctx->notify_func2)
     {
       svn_wc_notify_t *notify;
@@ -2644,13 +2718,13 @@ repos_to_wc_copy_single(svn_boolean_t *t
         SVN_ERR(ctx->cancel_func(ctx->cancel_baton));
     }
 
-  SVN_ERR(svn_client__repos_to_wc_copy(timestamp_sleep,
-                                       pair->src_kind,
-                                       pair->src_abspath_or_url,
-                                       pair->src_revnum,
-                                       dst_abspath,
-                                       same_repositories,
-                                       ra_session, ctx, pool));
+  SVN_ERR(svn_client__repos_to_wc_copy_by_editor(
+            timestamp_sleep,
+            pair->src_kind,
+            pair->src_abspath_or_url,
+            pair->src_revnum,
+            dst_abspath,
+            ra_session, ctx, pool));
 
   /* Fetch externals, pinning them if requested */
   if (!ignore_externals && pair->src_kind == svn_node_dir)
@@ -2746,32 +2820,8 @@ repos_to_wc_copy_locked(svn_boolean_t *t
                         apr_pool_t *scratch_pool)
 {
   int i;
-  svn_boolean_t same_repositories;
   apr_pool_t *iterpool = svn_pool_create(scratch_pool);
 
-  /* Decide whether the two repositories are the same or not. */
-  {
-    const char *parent_abspath;
-    const char *src_uuid, *dst_uuid;
-
-    /* Get the repository uuid of SRC_URL */
-    SVN_ERR(svn_ra_get_uuid2(ra_session, &src_uuid, iterpool));
-
-    /* Get repository uuid of dst's parent directory, since dst may
-       not exist.  ### TODO:  we should probably walk up the wc here,
-       in case the parent dir has an imaginary URL.  */
-    if (copy_pairs->nelts == 1)
-      parent_abspath = svn_dirent_dirname(top_dst_abspath, scratch_pool);
-    else
-      parent_abspath = top_dst_abspath;
-
-    SVN_ERR(svn_client_get_repos_root(NULL /* root_url */, &dst_uuid,
-                                      parent_abspath, ctx,
-                                      iterpool, iterpool));
-    /* ### Also check repos_root_url? */
-    same_repositories = (strcmp(src_uuid, dst_uuid) == 0);
-  }
-
   /* Perform the move for each of the copy_pairs. */
   for (i = 0; i < copy_pairs->nelts; i++)
     {
@@ -2784,7 +2834,6 @@ repos_to_wc_copy_locked(svn_boolean_t *t
       SVN_ERR(repos_to_wc_copy_single(timestamp_sleep,
                                       APR_ARRAY_IDX(copy_pairs, i,
                                                     svn_client__copy_pair_t *),
-                                      same_repositories,
                                       ignore_externals,
                                       pin_externals, externals_to_pin,
                                       ra_session, ctx, iterpool));

Modified: subversion/trunk/subversion/libsvn_client/wc_editor.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_client/wc_editor.c?rev=1848937&r1=1848936&r2=1848937&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_client/wc_editor.c (original)
+++ subversion/trunk/subversion/libsvn_client/wc_editor.c Fri Dec 14 13:20:19 2018
@@ -209,28 +209,6 @@ dir_open(const char *path,
   return SVN_NO_ERROR;
 }
 
-/* Are RA_SESSION and the versioned *parent* dir of WC_TARGET_ABSPATH in
- * the same repository?
- */
-static svn_error_t *
-is_same_repository(svn_boolean_t *same_repository,
-                   svn_ra_session_t *ra_session,
-                   const char *wc_target_abspath,
-                   svn_client_ctx_t *ctx,
-                   apr_pool_t *scratch_pool)
-{
-  const char *src_uuid, *dst_uuid;
-
-  /* Get the repository UUIDs of copy source URL and WC parent path */
-  SVN_ERR(svn_ra_get_uuid2(ra_session, &src_uuid, scratch_pool));
-  SVN_ERR(svn_client_get_repos_root(NULL /*root_url*/, &dst_uuid,
-                                    svn_dirent_dirname(wc_target_abspath,
-                                                       scratch_pool),
-                                    ctx, scratch_pool, scratch_pool));
-  *same_repository = (strcmp(src_uuid, dst_uuid) == 0);
-  return SVN_NO_ERROR;
-}
-
 static svn_error_t *
 dir_add(const char *path,
         void *parent_baton,
@@ -242,25 +220,21 @@ dir_add(const char *path,
   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_boolean_t same_repository;
-      svn_boolean_t timestamp_sleep;
-
-      SVN_ERR(is_same_repository(&same_repository,
-                                 db->eb->ra_session, db->local_abspath,
-                                 db->eb->ctx, db->pool));
-
-      SVN_ERR(svn_client__repos_to_wc_copy(&timestamp_sleep,
+      SVN_ERR(svn_client__repos_to_wc_copy_internal(NULL /*timestamp_sleep*/,
                                            svn_node_dir,
                                            copyfrom_path,
                                            copyfrom_revision,
                                            db->local_abspath,
-                                           same_repository,
                                            db->eb->ra_session,
                                            db->eb->ctx, db->pool));
+      db->created = TRUE;
+    }
+  else
+    {
+      SVN_ERR(svn_io_make_dir_recursively(db->local_abspath, db->pool));
     }
 
   *child_baton = db;
@@ -436,21 +410,14 @@ file_add(const char *path,
 
   if (copyfrom_path && SVN_IS_VALID_REVNUM(copyfrom_revision))
     {
-      svn_boolean_t same_repository;
-      svn_boolean_t timestamp_sleep;
-
-      SVN_ERR(is_same_repository(&same_repository,
-                                 fb->eb->ra_session, fb->local_abspath,
-                                 fb->eb->ctx, fb->pool));
-
-      SVN_ERR(svn_client__repos_to_wc_copy(&timestamp_sleep,
+      SVN_ERR(svn_client__repos_to_wc_copy_internal(NULL /*timestamp_sleep*/,
                                            svn_node_file,
                                            copyfrom_path,
                                            copyfrom_revision,
                                            fb->local_abspath,
-                                           same_repository,
                                            fb->eb->ra_session,
                                            fb->eb->ctx, fb->pool));
+      fb->created = TRUE;
     }
 
   *file_baton = fb;

Modified: subversion/trunk/subversion/tests/libsvn_client/client-test.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/tests/libsvn_client/client-test.c?rev=1848937&r1=1848936&r2=1848937&view=diff
==============================================================================
--- subversion/trunk/subversion/tests/libsvn_client/client-test.c (original)
+++ subversion/trunk/subversion/tests/libsvn_client/client-test.c Fri Dec 14 13:20:19 2018
@@ -766,22 +766,18 @@ test_foreign_repos_copy(const svn_test_o
 
   loc->url = svn_path_url_add_component2(repos2_url, "A", pool);
   SVN_WC__CALL_WITH_WRITE_LOCK(
-    svn_client__repos_to_wc_copy(NULL /*sleep*/, svn_node_dir,
+    svn_client__repos_to_wc_copy_by_editor(NULL /*sleep*/, svn_node_dir,
                              loc->url, loc->rev,
                              svn_dirent_join(wc_path, "A-copied", pool),
-                             /*svn_depth_infinity,*/
-                             FALSE /*same_repositories*/,
                              ra_session, ctx, pool),
     ctx->wc_ctx, wc_path, FALSE, pool);
 
   SVN_ERR(svn_ra_reparent(ra_session, repos2_url, pool));
   loc->url = svn_path_url_add_component2(repos2_url, "iota", pool);
   SVN_WC__CALL_WITH_WRITE_LOCK(
-    svn_client__repos_to_wc_copy(NULL /*sleep*/, svn_node_file,
+    svn_client__repos_to_wc_copy_by_editor(NULL /*sleep*/, svn_node_file,
                              loc->url, loc->rev,
                              svn_dirent_join(wc_path, "iota-copied", pool),
-                             /*svn_depth_infinity,*/
-                             FALSE /*same_repositories*/,
                              ra_session, ctx, pool),
     ctx->wc_ctx, wc_path, FALSE, pool);