Author: stsp
Date: Thu Dec  1 12:33:05 2016
New Revision: 1772185

URL: http://svn.apache.org/viewvc?rev=1772185&view=rev
Log:
Make it possible to resolve tree conflicts raised by nested file moves
while updating an incoming move.

* subversion/libsvn_client/conflicts.c
  (verify_local_state_for_incoming_delete): Allow the old incoming repository
   path as a copy source for an update conflict victim.

* subversion/tests/libsvn_client/conflicts-test.c
  (test_update_incoming_dir_move_with_nested_file_move): Extend this test to
    cover resolution of the tree conflict created by the nested file move.

Modified:
    subversion/trunk/subversion/libsvn_client/conflicts.c
    subversion/trunk/subversion/tests/libsvn_client/conflicts-test.c

Modified: subversion/trunk/subversion/libsvn_client/conflicts.c
URL: 
http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_client/conflicts.c?rev=1772185&r1=1772184&r2=1772185&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_client/conflicts.c (original)
+++ subversion/trunk/subversion/libsvn_client/conflicts.c Thu Dec  1 12:33:05 
2016
@@ -6773,19 +6773,28 @@ verify_local_state_for_incoming_delete(s
                                      wcroot_abspath, conflict->local_abspath),
                                    scratch_pool),
                                   details->added_rev, copyfrom_rev);
+      else if (operation == svn_wc_operation_update)
+        {
+          const char *old_repos_relpath;
 
-      else if (operation == svn_wc_operation_update &&
-               strcmp(copyfrom_repos_relpath, details->repos_relpath) != 0)
-        return svn_error_createf(SVN_ERR_WC_CONFLICT_RESOLVER_FAILURE, NULL,
-                                 _("Cannot resolve tree conflict on '%s' "
-                                   "(expected an item copied from '^/%s', "
-                                   "but the item was copied from '^/%s@%ld')"),
-                                 svn_dirent_local_style(
-                                   svn_dirent_skip_ancestor(
-                                     wcroot_abspath, conflict->local_abspath),
-                                   scratch_pool),
-                                 details->repos_relpath,
-                                 copyfrom_repos_relpath, copyfrom_rev);
+          SVN_ERR(svn_client_conflict_get_incoming_old_repos_location(
+                    &old_repos_relpath, NULL, NULL, conflict,
+                    scratch_pool, scratch_pool));
+          if (strcmp(copyfrom_repos_relpath, details->repos_relpath) != 0 &&
+              strcmp(copyfrom_repos_relpath, old_repos_relpath) != 0)
+            return svn_error_createf(SVN_ERR_WC_CONFLICT_RESOLVER_FAILURE, 
NULL,
+                                     _("Cannot resolve tree conflict on '%s' "
+                                       "(expected an item copied from '^/%s' "
+                                       "or from '^/%s' but the item was "
+                                       "copied from '^/%s@%ld')"),
+                                     svn_dirent_local_style(
+                                       svn_dirent_skip_ancestor(
+                                         wcroot_abspath, 
conflict->local_abspath),
+                                       scratch_pool),
+                                     details->repos_relpath,
+                                     old_repos_relpath,
+                                     copyfrom_repos_relpath, copyfrom_rev);
+        }
       else if (operation == svn_wc_operation_switch)
         {
           const char *old_repos_relpath;

Modified: subversion/trunk/subversion/tests/libsvn_client/conflicts-test.c
URL: 
http://svn.apache.org/viewvc/subversion/trunk/subversion/tests/libsvn_client/conflicts-test.c?rev=1772185&r1=1772184&r2=1772185&view=diff
==============================================================================
--- subversion/trunk/subversion/tests/libsvn_client/conflicts-test.c (original)
+++ subversion/trunk/subversion/tests/libsvn_client/conflicts-test.c Thu Dec  1 
12:33:05 2016
@@ -3209,6 +3209,10 @@ test_update_incoming_dir_move_with_neste
   apr_array_header_t *props_conflicted;
   svn_boolean_t tree_conflicted;
   svn_stringbuf_t *buf;
+  svn_node_kind_t kind;
+  svn_opt_revision_t opt_rev;
+  svn_client_status_t *status;
+  struct status_baton sb;
 
   SVN_ERR(svn_test__sandbox_create(
             b, "update_incoming_dir_move_with_moved_file", opts, pool));
@@ -3299,6 +3303,74 @@ test_update_incoming_dir_move_with_neste
   SVN_ERR(svn_stringbuf_from_file2(&buf, sbox_wc_path(b, deleted_file), pool));
   SVN_TEST_STRING_ASSERT(buf->data, modified_file_content);
 
+  /* Check available tree conflict resolution options. */
+  {
+    svn_client_conflict_option_id_t expected_opts[] = {
+      svn_client_conflict_option_postpone,
+      svn_client_conflict_option_accept_current_wc_state,
+      svn_client_conflict_option_incoming_delete_ignore,
+      svn_client_conflict_option_incoming_delete_accept,
+      -1 /* end of list */
+    };
+    SVN_ERR(assert_tree_conflict_options(conflict, ctx, expected_opts, pool));
+  }
+
+  SVN_ERR(svn_client_conflict_tree_get_details(conflict, ctx, pool));
+
+  {
+    svn_client_conflict_option_id_t expected_opts[] = {
+      svn_client_conflict_option_postpone,
+      svn_client_conflict_option_accept_current_wc_state,
+      svn_client_conflict_option_incoming_move_file_text_merge,
+      -1 /* end of list */
+    };
+    SVN_ERR(assert_tree_conflict_options(conflict, ctx, expected_opts, pool));
+  }
+
+  SVN_ERR(svn_client_conflict_tree_resolve_by_id(
+            conflict, svn_client_conflict_option_incoming_move_file_text_merge,
+            ctx, pool));
+
+  /* Ensure that the deleted file is gone. */
+  SVN_ERR(svn_io_check_path(sbox_wc_path(b, deleted_file), &kind, b->pool));
+  SVN_TEST_ASSERT(kind == svn_node_none);
+
+  /* Ensure that the moved-target file has the expected status. */
+  opt_rev.kind = svn_opt_revision_working;
+  sb.result_pool = b->pool;
+  SVN_ERR(svn_client_status6(NULL, ctx, sbox_wc_path(b, moved_file),
+                             &opt_rev, svn_depth_unknown, TRUE, TRUE,
+                             TRUE, TRUE, FALSE, TRUE, NULL,
+                             status_func, &sb, b->pool));
+  status = sb.status;
+  SVN_TEST_ASSERT(status->kind == svn_node_file);
+  SVN_TEST_ASSERT(status->versioned);
+  SVN_TEST_ASSERT(!status->conflicted);
+  SVN_TEST_ASSERT(status->node_status == svn_wc_status_modified);
+  SVN_TEST_ASSERT(status->text_status == svn_wc_status_modified);
+  SVN_TEST_ASSERT(status->prop_status == svn_wc_status_none);
+  SVN_TEST_ASSERT(!status->copied);
+  SVN_TEST_ASSERT(!status->switched);
+  SVN_TEST_ASSERT(!status->file_external);
+  SVN_TEST_ASSERT(status->moved_from_abspath == NULL);
+  SVN_TEST_ASSERT(status->moved_to_abspath == NULL);
+
+  /* The file should not be in conflict. */
+  SVN_ERR(svn_client_conflict_get(&conflict, sbox_wc_path(b, moved_file),
+                                  ctx, b->pool, b->pool));
+
+  SVN_ERR(svn_client_conflict_get_conflicted(&text_conflicted,
+                                             &props_conflicted,
+                                             &tree_conflicted,
+                                             conflict, b->pool, b->pool));
+  SVN_TEST_ASSERT(!text_conflicted &&
+                  props_conflicted->nelts == 0 &&
+                  !tree_conflicted);
+
+  /* Make sure the file has the expected content. */
+  SVN_ERR(svn_stringbuf_from_file2(&buf, sbox_wc_path(b, moved_file), pool));
+  SVN_TEST_STRING_ASSERT(buf->data, modified_file_content);
+
   return SVN_NO_ERROR;
 }
 


Reply via email to