You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by rh...@apache.org on 2014/03/23 22:54:55 UTC

svn commit: r1580626 - in /subversion/trunk/subversion: libsvn_wc/wc_db.c tests/libsvn_wc/op-depth-test.c tests/libsvn_wc/utils.c tests/libsvn_wc/utils.h

Author: rhuijben
Date: Sun Mar 23 21:54:55 2014
New Revision: 1580626

URL: http://svn.apache.org/r1580626
Log:
Following up on r1560690 (backported in 1.8.8 and 1.7.16), obtain the
copyfrom_id a bit earlier to not only record the copy with the right
information but also at the right op-depth.

This resolves an issue I just found myself while performing a URL WC copy
on a working copy that was relocated. Both 1.8.8 and trunk would show
all nodes (except the copy root) as incomplete because each descendant
would be stored at its own op-root.

* subversion/libsvn_wc/wc_db.c
  (get_info_for_copy): Calculate the right copyfrom_id here
  (db_op_copy): Instead of here... because this value is used in more
    places than just when inserting the node. Most importantly for
    op_depth_for_copy().

* subversion/tests/libsvn_wc/op-depth-test.c
  (repo_wc_copy): New test.
  (test_funcs): Add test.

* subversion/tests/libsvn_wc/utils.c
  (sbox_wc_copy_url,
   sbox_wc_relocate): New functions.

* subversion/tests/libsvn_wc/utils.h
  (sbox_wc_copy_url,
   sbox_wc_relocate): New functions.

Modified:
    subversion/trunk/subversion/libsvn_wc/wc_db.c
    subversion/trunk/subversion/tests/libsvn_wc/op-depth-test.c
    subversion/trunk/subversion/tests/libsvn_wc/utils.c
    subversion/trunk/subversion/tests/libsvn_wc/utils.h

Modified: subversion/trunk/subversion/libsvn_wc/wc_db.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_wc/wc_db.c?rev=1580626&r1=1580625&r2=1580626&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_wc/wc_db.c (original)
+++ subversion/trunk/subversion/libsvn_wc/wc_db.c Sun Mar 23 21:54:55 2014
@@ -4155,8 +4155,9 @@ get_info_for_copy(apr_int64_t *copyfrom_
                   svn_wc__db_status_t *status,
                   svn_node_kind_t *kind,
                   svn_boolean_t *op_root,
-                  svn_wc__db_wcroot_t *wcroot,
+                  svn_wc__db_wcroot_t *src_wcroot,
                   const char *local_relpath,
+                  svn_wc__db_wcroot_t *dst_wcroot,
                   apr_pool_t *result_pool,
                   apr_pool_t *scratch_pool)
 {
@@ -4173,7 +4174,7 @@ get_info_for_copy(apr_int64_t *copyfrom_
                     NULL /* have_base */,
                     NULL /* have_more_work */,
                     NULL /* have_work */,
-                    wcroot, local_relpath, result_pool, scratch_pool));
+                    src_wcroot, local_relpath, result_pool, scratch_pool));
 
   if (op_root)
     *op_root = is_op_root;
@@ -4188,7 +4189,7 @@ get_info_for_copy(apr_int64_t *copyfrom_
                        scratch_pool);
       SVN_ERR(get_info_for_copy(copyfrom_id, copyfrom_relpath, copyfrom_rev,
                                 NULL, NULL, NULL,
-                                wcroot, parent_relpath,
+                                src_wcroot, parent_relpath, dst_wcroot,
                                 scratch_pool, scratch_pool));
       if (*copyfrom_relpath)
         *copyfrom_relpath = svn_relpath_join(*copyfrom_relpath, base_name,
@@ -4197,7 +4198,7 @@ get_info_for_copy(apr_int64_t *copyfrom_
   else if (node_status == svn_wc__db_status_added)
     {
       SVN_ERR(scan_addition(&node_status, NULL, NULL, NULL, NULL, NULL, NULL,
-                            NULL, NULL, NULL, wcroot, local_relpath,
+                            NULL, NULL, NULL, src_wcroot, local_relpath,
                             scratch_pool, scratch_pool));
     }
   else if (node_status == svn_wc__db_status_deleted && is_op_root)
@@ -4206,7 +4207,7 @@ get_info_for_copy(apr_int64_t *copyfrom_
 
       SVN_ERR(scan_deletion_txn(&base_del_relpath, NULL,
                                 &work_del_relpath,
-                                NULL, wcroot, local_relpath,
+                                NULL, src_wcroot, local_relpath,
                                 scratch_pool, scratch_pool));
       if (work_del_relpath)
         {
@@ -4219,7 +4220,8 @@ get_info_for_copy(apr_int64_t *copyfrom_
           SVN_ERR(scan_addition(NULL, &op_root_relpath,
                                 NULL, NULL, /* repos_* */
                                 copyfrom_relpath, copyfrom_id, copyfrom_rev,
-                                NULL, NULL, NULL, wcroot, parent_del_relpath,
+                                NULL, NULL, NULL,
+                                src_wcroot, parent_del_relpath,
                                 scratch_pool, scratch_pool));
           *copyfrom_relpath
             = svn_relpath_join(*copyfrom_relpath,
@@ -4234,7 +4236,7 @@ get_info_for_copy(apr_int64_t *copyfrom_
                                                     copyfrom_id, NULL, NULL,
                                                     NULL, NULL, NULL, NULL,
                                                     NULL, NULL, NULL, NULL,
-                                                    wcroot, local_relpath,
+                                                    src_wcroot, local_relpath,
                                                     result_pool,
                                                     scratch_pool));
         }
@@ -4256,6 +4258,24 @@ get_info_for_copy(apr_int64_t *copyfrom_
   if (status)
     *status = node_status;
 
+  if (src_wcroot != dst_wcroot && copyfrom_relpath)
+    {
+      const char *repos_root_url;
+      const char *repos_uuid;
+
+      /* Pass the right repos-id for the destination db. We can't just use
+         the id of the source database, as this value can change after
+         relocation (and perhaps also when we start storing multiple
+         working copies in a single db)! */
+
+      SVN_ERR(svn_wc__db_fetch_repos_info(&repos_root_url, &repos_uuid,
+                                          src_wcroot->sdb, *copyfrom_id,
+                                          scratch_pool));
+
+      SVN_ERR(create_repos_id(copyfrom_id, repos_root_url, repos_uuid,
+                              dst_wcroot->sdb, scratch_pool));
+    }
+
   return SVN_NO_ERROR;
 }
 
@@ -4415,8 +4435,9 @@ db_op_copy(svn_wc__db_wcroot_t *src_wcro
   const apr_array_header_t *children;
 
   SVN_ERR(get_info_for_copy(&copyfrom_id, &copyfrom_relpath, &copyfrom_rev,
-                            &status, &kind, &op_root, src_wcroot,
-                            src_relpath, scratch_pool, scratch_pool));
+                            &status, &kind, &op_root,
+                            src_wcroot, src_relpath, dst_wcroot,
+                            scratch_pool, scratch_pool));
 
   SVN_ERR(op_depth_for_copy(&dst_op_depth, &dst_np_op_depth,
                             &dst_parent_op_depth,
@@ -4641,21 +4662,6 @@ db_op_copy(svn_wc__db_wcroot_t *src_wcro
     }
   else
     {
-      if (copyfrom_relpath)
-        {
-          const char *repos_root_url;
-          const char *repos_uuid;
-
-          /* Pass the right repos-id for the destination db! */
-
-          SVN_ERR(svn_wc__db_fetch_repos_info(&repos_root_url, &repos_uuid,
-                                              src_wcroot->sdb, copyfrom_id,
-                                              scratch_pool));
-
-          SVN_ERR(create_repos_id(&copyfrom_id, repos_root_url, repos_uuid,
-                                  dst_wcroot->sdb, scratch_pool));
-        }
-
       SVN_ERR(cross_db_copy(src_wcroot, src_relpath, dst_wcroot,
                             dst_relpath, dst_presence, dst_op_depth,
                             dst_np_op_depth, kind,

Modified: subversion/trunk/subversion/tests/libsvn_wc/op-depth-test.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/tests/libsvn_wc/op-depth-test.c?rev=1580626&r1=1580625&r2=1580626&view=diff
==============================================================================
--- subversion/trunk/subversion/tests/libsvn_wc/op-depth-test.c (original)
+++ subversion/trunk/subversion/tests/libsvn_wc/op-depth-test.c Sun Mar 23 21:54:55 2014
@@ -9569,6 +9569,78 @@ movedhere_extract_retract(const svn_test
   return SVN_NO_ERROR;
 }
 
+static svn_error_t *
+repo_wc_copy(const svn_test_opts_t *opts, apr_pool_t *pool)
+{
+  svn_test__sandbox_t b;
+  const char *repos_dir;
+  const char *new_repos_dir;
+  const char *new_repos_url;
+
+  SVN_ERR(svn_test__sandbox_create(&b, "repo_wc_copy",
+                                   opts, pool));
+  SVN_ERR(sbox_add_and_commit_greek_tree(&b));
+
+  SVN_ERR(sbox_wc_copy_url(&b,
+                           svn_path_url_add_component2(b.repos_url, "A/B",
+                                                       pool),
+                           -1, "AA"));
+
+  {
+    nodes_row_t nodes[] = {
+
+      {1, "AA/lambda",   "normal", 1, "A/B/lambda"},
+      {1, "AA",          "normal", 1, "A/B"},
+      {1, "AA/E/beta",   "normal", 1, "A/B/E/beta"},
+      {1, "AA/E/alpha",  "normal", 1, "A/B/E/alpha"},
+      {1, "AA/F",        "normal", 1, "A/B/F"},
+      {1, "AA/E",        "normal", 1, "A/B/E"},
+
+      { 0 },
+    };
+    SVN_ERR(check_db_rows(&b, "AA", nodes));
+  }
+
+  SVN_ERR(svn_uri_get_dirent_from_file_url(&repos_dir, b.repos_url,
+                                           pool));
+  new_repos_dir = apr_pstrcat(pool, repos_dir, "-2", SVN_VA_NULL);
+  new_repos_url = apr_pstrcat(pool, b.repos_url, "-2", SVN_VA_NULL);
+
+  svn_test_add_dir_cleanup(new_repos_dir);
+
+  SVN_ERR(svn_io_remove_dir2(new_repos_dir, TRUE, NULL, NULL, pool));
+  SVN_ERR(svn_io_copy_dir_recursively(repos_dir,
+                                      svn_dirent_dirname(new_repos_dir, pool),
+                                      svn_dirent_basename(new_repos_dir, pool),
+                                      FALSE, NULL, NULL, pool));
+
+  SVN_ERR(sbox_wc_relocate(&b, new_repos_url));
+
+  /* This produced an invalid copy in Subversion <= 1.8.8.
+     Status would show all descendants as incomplete */
+  SVN_ERR(sbox_wc_copy_url(&b,
+                           svn_path_url_add_component2(b.repos_url, "A/B",
+                                                       pool),
+                           -1, "BB"));
+
+  {
+    nodes_row_t nodes[] = {
+
+      {1, "BB/lambda",   "normal", 1, "A/B/lambda"},
+      {1, "BB",          "normal", 1, "A/B"},
+      {1, "BB/E/beta",   "normal", 1, "A/B/E/beta"},
+      {1, "BB/E/alpha",  "normal", 1, "A/B/E/alpha"},
+      {1, "BB/F",        "normal", 1, "A/B/F"},
+      {1, "BB/E",        "normal", 1, "A/B/E"},
+
+      { 0 },
+    };
+    SVN_ERR(check_db_rows(&b, "BB", nodes));
+  }
+
+  return SVN_NO_ERROR;
+}
+
 
 /* ---------------------------------------------------------------------- */
 /* The list of test functions */
@@ -9759,6 +9831,8 @@ static struct svn_test_descriptor_t test
                        "simple move bump"),
     SVN_TEST_OPTS_PASS(movedhere_extract_retract,
                        "movedhere extract retract"),
+    SVN_TEST_OPTS_PASS(repo_wc_copy,
+                       "repo_wc_copy"),
     SVN_TEST_NULL
   };
 

Modified: subversion/trunk/subversion/tests/libsvn_wc/utils.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/tests/libsvn_wc/utils.c?rev=1580626&r1=1580625&r2=1580626&view=diff
==============================================================================
--- subversion/trunk/subversion/tests/libsvn_wc/utils.c (original)
+++ subversion/trunk/subversion/tests/libsvn_wc/utils.c Sun Mar 23 21:54:55 2014
@@ -228,6 +228,45 @@ sbox_wc_copy(svn_test__sandbox_t *b, con
 }
 
 svn_error_t *
+sbox_wc_copy_url(svn_test__sandbox_t *b, const char *from_url,
+                 svn_revnum_t revision, const char *to_path)
+{
+  apr_pool_t *scratch_pool = b->pool;
+  svn_client_ctx_t *ctx;
+  svn_opt_revision_t rev = { svn_opt_revision_unspecified, {0} };
+  svn_client_copy_source_t* src;
+  apr_array_header_t *sources = apr_array_make(
+                                        scratch_pool, 1,
+                                        sizeof(svn_client_copy_source_t *));
+
+  SVN_ERR(svn_client_create_context2(&ctx, NULL, scratch_pool));
+  ctx->wc_ctx = b->wc_ctx;
+
+  if (SVN_IS_VALID_REVNUM(revision))
+    {
+      rev.kind = svn_opt_revision_number;
+      rev.value.number = revision;
+    }
+
+  src = apr_pcalloc(scratch_pool, sizeof(*src));
+
+  src->path = from_url;
+  src->revision = &rev;
+  src->peg_revision = &rev;
+
+  APR_ARRAY_PUSH(sources, svn_client_copy_source_t *) = src;
+
+  SVN_ERR(svn_client_copy6(sources, sbox_wc_path(b, to_path),
+                           FALSE, FALSE, FALSE, NULL, NULL, NULL,
+                           ctx, scratch_pool));
+
+  ctx->wc_ctx = NULL;
+
+  return SVN_NO_ERROR;
+}
+
+
+svn_error_t *
 sbox_wc_revert(svn_test__sandbox_t *b, const char *path, svn_depth_t depth)
 {
   const char *abspath = sbox_wc_path(b, path);
@@ -446,6 +485,24 @@ sbox_wc_propset(svn_test__sandbox_t *b,
 }
 
 svn_error_t *
+sbox_wc_relocate(svn_test__sandbox_t *b,
+                 const char *new_repos_url)
+{
+  apr_pool_t *scratch_pool = b->pool;
+  svn_client_ctx_t *ctx;
+
+  SVN_ERR(svn_client_create_context2(&ctx, NULL, scratch_pool));
+  ctx->wc_ctx = b->wc_ctx;
+
+  SVN_ERR(svn_client_relocate2(b->wc_abspath, b->repos_url,
+                               new_repos_url, FALSE, ctx,scratch_pool));
+
+  b->repos_url = apr_pstrdup(b->pool, new_repos_url);
+
+  return SVN_NO_ERROR;
+}
+
+svn_error_t *
 sbox_add_and_commit_greek_tree(svn_test__sandbox_t *b)
 {
   const struct svn_test__tree_entry_t *node;

Modified: subversion/trunk/subversion/tests/libsvn_wc/utils.h
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/tests/libsvn_wc/utils.h?rev=1580626&r1=1580625&r2=1580626&view=diff
==============================================================================
--- subversion/trunk/subversion/tests/libsvn_wc/utils.h (original)
+++ subversion/trunk/subversion/tests/libsvn_wc/utils.h Sun Mar 23 21:54:55 2014
@@ -104,6 +104,14 @@ sbox_wc_mkdir(svn_test__sandbox_t *b, co
 svn_error_t *
 sbox_wc_copy(svn_test__sandbox_t *b, const char *from_path, const char *to_path);
 
+svn_error_t *
+sbox_wc_copy_url(svn_test__sandbox_t *b, const char *from_url,
+                 svn_revnum_t revision, const char *to_path);
+
+svn_error_t *
+sbox_wc_relocate(svn_test__sandbox_t *b,
+                 const char *new_repos_url);
+
 /* Revert a WC file or directory tree at PATH */
 svn_error_t *
 sbox_wc_revert(svn_test__sandbox_t *b, const char *path, svn_depth_t depth);