You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by ko...@apache.org on 2016/10/10 15:51:19 UTC

svn commit: r1764130 - /subversion/trunk/subversion/tests/libsvn_client/conflicts-test.c

Author: kotkov
Date: Mon Oct 10 15:51:19 2016
New Revision: 1764130

URL: http://svn.apache.org/viewvc?rev=1764130&view=rev
Log:
Add a failing test for "remote move vs local edit" tree conflict resolution
upon merge with a moved directory that also contains a moved file.

While we can currently resolve the conflict on the directory by moving it,
then the conflict resolver doesn't see the file move that occured within
the directory.

* subversion/tests/libsvn_client/conflicts-test.c
  (test_merge_incoming_move_dir_with_moved_file): New failing test.
  (test_funcs): Reference new test.

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

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=1764130&r1=1764129&r2=1764130&view=diff
==============================================================================
--- subversion/trunk/subversion/tests/libsvn_client/conflicts-test.c (original)
+++ subversion/trunk/subversion/tests/libsvn_client/conflicts-test.c Mon Oct 10 15:51:19 2016
@@ -3276,6 +3276,185 @@ test_merge_incoming_chained_move_local_e
   return SVN_NO_ERROR;
 }
 
+static svn_error_t *
+test_merge_incoming_move_dir_with_moved_file(const svn_test_opts_t *opts,
+                                             apr_pool_t *pool)
+{
+  svn_test__sandbox_t *b = apr_palloc(pool, sizeof(*b));
+  svn_client_ctx_t *ctx;
+  svn_opt_revision_t opt_rev;
+  svn_client_conflict_t *conflict;
+  svn_boolean_t text_conflicted;
+  apr_array_header_t *props_conflicted;
+  svn_boolean_t tree_conflicted;
+  struct status_baton sb;
+  struct svn_client_status_t *status;
+
+  SVN_ERR(svn_test__sandbox_create(
+            b, "merge_incoming_move_dir_with_moved_file", opts, pool));
+
+  SVN_ERR(sbox_add_and_commit_greek_tree(b));
+  /* Create a copy of node "A". */
+  SVN_ERR(sbox_wc_update(b, "", SVN_INVALID_REVNUM));
+  SVN_ERR(sbox_wc_copy(b, "A", "A1"));
+  SVN_ERR(sbox_wc_commit(b, ""));
+  /* On "trunk", move a file and then move the dir containing the file. */
+  SVN_ERR(sbox_wc_move(b, "A/B/lambda", "A/B/lambda-moved"));
+  SVN_ERR(sbox_wc_move(b, "A/B", "A/B-moved"));
+  SVN_ERR(sbox_wc_commit(b, ""));
+  /* On "branch", edit the file. */
+  SVN_ERR(sbox_file_write(b, "A1/B/lambda", "New branch content.\n"));
+  SVN_ERR(sbox_wc_commit(b, ""));
+
+  SVN_ERR(svn_test__create_client_ctx(&ctx, b, pool));
+
+  /* Merge "trunk" to "branch". */
+  SVN_ERR(sbox_wc_update(b, "", SVN_INVALID_REVNUM));
+  opt_rev.kind = svn_opt_revision_head;
+  opt_rev.value.number = SVN_INVALID_REVNUM;
+  SVN_ERR(svn_client_merge_peg5(svn_path_url_add_component2(b->repos_url, "A",
+                                                            pool),
+                                NULL, &opt_rev, sbox_wc_path(b, "A1"),
+                                svn_depth_infinity,
+                                FALSE, FALSE, FALSE, FALSE, FALSE, FALSE,
+                                NULL, ctx, pool));
+
+  /* We should have a tree conflict on the dir. */
+  SVN_ERR(svn_client_conflict_get(&conflict, sbox_wc_path(b, "A1/B"), ctx,
+                                  pool, pool));
+  SVN_ERR(svn_client_conflict_get_conflicted(&text_conflicted,
+                                             &props_conflicted,
+                                             &tree_conflicted,
+                                             conflict, pool, pool));
+  SVN_TEST_ASSERT(!text_conflicted);
+  SVN_TEST_INT_ASSERT(props_conflicted->nelts, 0);
+  SVN_TEST_ASSERT(tree_conflicted);
+
+  /* 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_dir_merge,
+      -1 /* end of list */
+    };
+    SVN_ERR(assert_tree_conflict_options(conflict, ctx, expected_opts, pool));
+  }
+
+  /* Resolve the tree conflict by moving the local directory and merging. */
+  SVN_ERR(svn_client_conflict_tree_resolve_by_id(
+            conflict, svn_client_conflict_option_incoming_move_dir_merge,
+            ctx, pool));
+
+  /* The dir should not be in conflict. */
+  SVN_ERR(svn_client_conflict_get(&conflict, sbox_wc_path(b, "A1/B"),
+                                  ctx, pool, pool));
+  SVN_ERR(svn_client_conflict_get_conflicted(&text_conflicted,
+                                             &props_conflicted,
+                                             &tree_conflicted,
+                                             conflict, pool, pool));
+  SVN_TEST_ASSERT(!text_conflicted);
+  SVN_TEST_INT_ASSERT(props_conflicted->nelts, 0);
+  SVN_TEST_ASSERT(!tree_conflicted);
+
+  /* Ensure that the move source dir has the expected status. */
+  opt_rev.kind = svn_opt_revision_working;
+  sb.result_pool = pool;
+  SVN_ERR(svn_client_status6(NULL, ctx, sbox_wc_path(b, "A1/B"),
+                             &opt_rev, svn_depth_empty, TRUE, TRUE,
+                             TRUE, TRUE, FALSE, TRUE, NULL,
+                             status_func, &sb, pool));
+  status = sb.status;
+  SVN_TEST_INT_ASSERT(status->kind, svn_node_dir);
+  SVN_TEST_ASSERT(status->versioned);
+  SVN_TEST_ASSERT(!status->conflicted);
+  SVN_TEST_INT_ASSERT(status->node_status, svn_wc_status_deleted);
+  SVN_TEST_INT_ASSERT(status->text_status, svn_wc_status_normal);
+  SVN_TEST_INT_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_STRING_ASSERT(status->moved_from_abspath, NULL);
+  SVN_TEST_STRING_ASSERT(status->moved_to_abspath,
+                         sbox_wc_path(b, "A1/B-moved"));
+
+  /* Ensure that the move destination dir has the expected status. */
+  opt_rev.kind = svn_opt_revision_working;
+  sb.result_pool = pool;
+  SVN_ERR(svn_client_status6(NULL, ctx, sbox_wc_path(b, "A1/B-moved"),
+                             &opt_rev, svn_depth_empty, TRUE, TRUE,
+                             TRUE, TRUE, FALSE, TRUE, NULL,
+                             status_func, &sb, pool));
+  status = sb.status;
+  SVN_TEST_INT_ASSERT(status->kind, svn_node_dir);
+  SVN_TEST_ASSERT(status->versioned);
+  SVN_TEST_ASSERT(!status->conflicted);
+  SVN_TEST_INT_ASSERT(status->node_status, svn_wc_status_added);
+  SVN_TEST_INT_ASSERT(status->text_status, svn_wc_status_normal);
+  SVN_TEST_INT_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_STRING_ASSERT(status->moved_from_abspath,
+                         sbox_wc_path(b, "A1/B"));
+  SVN_TEST_STRING_ASSERT(status->moved_to_abspath, NULL);
+
+  /* We should have another tree conflict on the moved-away file. */
+  SVN_ERR(svn_client_conflict_get(&conflict,
+                                  sbox_wc_path(b, "A1/B-moved/lambda"),
+                                  ctx, pool, pool));
+  SVN_ERR(svn_client_conflict_get_conflicted(&text_conflicted,
+                                             &props_conflicted,
+                                             &tree_conflicted,
+                                             conflict, pool, pool));
+  SVN_TEST_ASSERT(!text_conflicted);
+  SVN_TEST_INT_ASSERT(props_conflicted->nelts, 0);
+  SVN_TEST_ASSERT(tree_conflicted);
+
+  /* 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));
+
+  /* XFAIL: The conflict resolver doesn't find the move, and doesn't offer
+   * the svn_client_conflict_option_incoming_move_file_text_merge option. */
+  {
+    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));
+  }
+
+  /* ### Need to test resolving the conflict on "A1/B-moved/lambda". */
+
+  return SVN_NO_ERROR;
+}
+
 /* ========================================================================== */
 
 
@@ -3338,6 +3517,8 @@ static struct svn_test_descriptor_t test
                         "merge incoming edit for a moved-away working file"),
     SVN_TEST_OPTS_XFAIL(test_merge_incoming_chained_move_local_edit,
                         "merge incoming chained move vs local edit"),
+    SVN_TEST_OPTS_XFAIL(test_merge_incoming_move_dir_with_moved_file,
+                        "merge incoming moved dir with moved file"),
     SVN_TEST_NULL
   };