You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by st...@apache.org on 2016/10/11 13:40:59 UTC
svn commit: r1764240 - in /subversion/branches/resolve-incoming-add: ./
notes/meetings/berlin-16-minutes subversion/svn/conflict-callbacks.c
subversion/tests/libsvn_client/conflicts-test.c
Author: stsp
Date: Tue Oct 11 13:40:59 2016
New Revision: 1764240
URL: http://svn.apache.org/viewvc?rev=1764240&view=rev
Log:
On the resolve-incoming-add branch: Merge with trunk.
Added:
subversion/branches/resolve-incoming-add/notes/meetings/berlin-16-minutes
- copied unchanged from r1764239, subversion/trunk/notes/meetings/berlin-16-minutes
Modified:
subversion/branches/resolve-incoming-add/ (props changed)
subversion/branches/resolve-incoming-add/subversion/svn/conflict-callbacks.c
subversion/branches/resolve-incoming-add/subversion/tests/libsvn_client/conflicts-test.c
Propchange: subversion/branches/resolve-incoming-add/
------------------------------------------------------------------------------
--- svn:mergeinfo (original)
+++ svn:mergeinfo Tue Oct 11 13:40:59 2016
@@ -96,4 +96,4 @@
/subversion/branches/verify-at-commit:1462039-1462408
/subversion/branches/verify-keep-going:1439280-1546110
/subversion/branches/wc-collate-path:1402685-1480384
-/subversion/trunk:1762797-1764035
+/subversion/trunk:1762797-1764239
Modified: subversion/branches/resolve-incoming-add/subversion/svn/conflict-callbacks.c
URL: http://svn.apache.org/viewvc/subversion/branches/resolve-incoming-add/subversion/svn/conflict-callbacks.c?rev=1764240&r1=1764239&r2=1764240&view=diff
==============================================================================
--- subversion/branches/resolve-incoming-add/subversion/svn/conflict-callbacks.c (original)
+++ subversion/branches/resolve-incoming-add/subversion/svn/conflict-callbacks.c Tue Oct 11 13:40:59 2016
@@ -229,8 +229,8 @@ merge_prop_conflict(svn_stream_t *output
base_propval = svn_string_create_empty(pool);
if (my_propval == NULL)
my_propval = svn_string_create_empty(pool);
- if (my_propval == NULL)
- my_propval = svn_string_create_empty(pool);
+ if (their_propval == NULL)
+ their_propval = svn_string_create_empty(pool);
options->ignore_eol_style = TRUE;
SVN_ERR(svn_diff_mem_string_diff3(&diff, base_propval,
Modified: subversion/branches/resolve-incoming-add/subversion/tests/libsvn_client/conflicts-test.c
URL: http://svn.apache.org/viewvc/subversion/branches/resolve-incoming-add/subversion/tests/libsvn_client/conflicts-test.c?rev=1764240&r1=1764239&r2=1764240&view=diff
==============================================================================
--- subversion/branches/resolve-incoming-add/subversion/tests/libsvn_client/conflicts-test.c (original)
+++ subversion/branches/resolve-incoming-add/subversion/tests/libsvn_client/conflicts-test.c Tue Oct 11 13:40:59 2016
@@ -2356,6 +2356,9 @@ test_merge_incoming_move_dir(const svn_t
struct svn_client_status_t *status;
svn_stringbuf_t *buf;
svn_opt_revision_t opt_rev;
+ apr_array_header_t *options;
+ svn_client_conflict_option_t *option;
+ apr_array_header_t *possible_moved_to_abspaths;
SVN_ERR(svn_test__sandbox_create(b, "merge_incoming_move_dir", opts, pool));
@@ -2365,11 +2368,36 @@ test_merge_incoming_move_dir(const svn_t
deleted_path = svn_relpath_join(branch_path, deleted_dir_name, b->pool);
moved_to_path = svn_relpath_join(branch_path, new_dir_name, b->pool);
- /* Resolve the tree conflict. */
SVN_ERR(svn_test__create_client_ctx(&ctx, b, b->pool));
SVN_ERR(svn_client_conflict_get(&conflict, sbox_wc_path(b, deleted_path),
ctx, b->pool, b->pool));
SVN_ERR(svn_client_conflict_tree_get_details(conflict, ctx, b->pool));
+
+ /* Check possible move destinations for the directory. */
+ SVN_ERR(svn_client_conflict_tree_get_resolution_options(&options, conflict,
+ ctx, b->pool,
+ b->pool));
+ option = svn_client_conflict_option_find_by_id(
+ options, svn_client_conflict_option_incoming_move_dir_merge);
+ SVN_TEST_ASSERT(option != NULL);
+
+ SVN_ERR(svn_client_conflict_option_get_moved_to_abspath_candidates(
+ &possible_moved_to_abspaths, option, b->pool, b->pool));
+
+ /* XFAIL: Currently, the resolver finds two possible destinations for
+ * the moved folder:
+ *
+ * Possible working copy destinations for moved-away 'A_branch/B' are:
+ * (1): 'A_branch/newdir'
+ * (2): 'A/newdir'
+ * Only one destination can be a move; the others are copies.
+ */
+ SVN_TEST_INT_ASSERT(possible_moved_to_abspaths->nelts, 1);
+ SVN_TEST_STRING_ASSERT(
+ APR_ARRAY_IDX(possible_moved_to_abspaths, 0, const char *),
+ sbox_wc_path(b, moved_to_path));
+
+ /* Resolve the tree conflict. */
SVN_ERR(svn_client_conflict_tree_resolve_by_id(
conflict, svn_client_conflict_option_incoming_move_dir_merge,
ctx, b->pool));
@@ -3039,6 +3067,483 @@ test_merge_incoming_move_file_text_merge
return SVN_NO_ERROR;
}
+static svn_error_t *
+test_merge_incoming_edit_file_moved_away(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;
+ svn_stringbuf_t *buf;
+
+ SVN_ERR(svn_test__sandbox_create(
+ b, "merge_incoming_edit_file_moved_away", opts, pool));
+
+ SVN_ERR(sbox_add_and_commit_greek_tree(b));
+ /* Create a copy of node "A". */
+ SVN_ERR(sbox_wc_copy(b, "A", "A1"));
+ SVN_ERR(sbox_wc_commit(b, ""));
+ /* On "trunk", edit the file. */
+ SVN_ERR(sbox_file_write(b, "A/mu", "New trunk content.\n"));
+ SVN_ERR(sbox_wc_commit(b, ""));
+ /* On "branch", move the file. */
+ SVN_ERR(sbox_wc_move(b, "A1/mu", "A1/mu-moved"));
+ 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 in the file "mu". */
+ SVN_ERR(svn_client_conflict_get(&conflict, sbox_wc_path(b, "A1/mu"), 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,
+ -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: We don't offer an option to apply incoming changes to move
+ * destination in the remote edit vs local (to branch history) move
+ * during merge. Not too sure if the currently expected
+ * svn_client_conflict_option_update_move_destination is the proper
+ * expectation, or if we need a separate option, but currently the
+ * tree conflict resolver offers only the "postpone" and "mark as
+ * resolved" 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_update_move_destination,
+ -1 /* end of list */
+ };
+ SVN_ERR(assert_tree_conflict_options(conflict, ctx, expected_opts, pool));
+ }
+
+ /* Resolve the tree conflict by applying the incoming edit to the local
+ * move destination "mu-moved". */
+ SVN_ERR(svn_client_conflict_tree_resolve_by_id(
+ conflict, svn_client_conflict_option_update_move_destination,
+ ctx, pool));
+
+ /* The file should not be in conflict. */
+ SVN_ERR(svn_client_conflict_get(&conflict, sbox_wc_path(b, "A1/mu-moved"),
+ 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);
+
+ /* And it should have the expected content. */
+ SVN_ERR(svn_stringbuf_from_file2(&buf, sbox_wc_path(b, "A1/mu-moved"),
+ pool));
+ SVN_TEST_STRING_ASSERT(buf->data, "New trunk content.\n");
+
+ return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+test_merge_incoming_chained_move_local_edit(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;
+ svn_stringbuf_t *buf;
+
+ SVN_ERR(svn_test__sandbox_create(
+ b, "merge_incoming_chained_move_local_edit", opts, pool));
+
+ SVN_ERR(sbox_add_and_commit_greek_tree(b));
+ /* Create a copy of node "A". */
+ SVN_ERR(sbox_wc_copy(b, "A", "A1"));
+ SVN_ERR(sbox_wc_commit(b, ""));
+ /* On "trunk", move the file. */
+ SVN_ERR(sbox_wc_move(b, "A/mu", "A/mu-moved"));
+ SVN_ERR(sbox_wc_commit(b, ""));
+ /* On "trunk", move the file again. */
+ SVN_ERR(sbox_wc_move(b, "A/mu-moved", "A/mu-moved-again"));
+ SVN_ERR(sbox_wc_commit(b, ""));
+ /* On "branch", edit the file. */
+ SVN_ERR(sbox_file_write(b, "A1/mu", "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 in the file "mu". */
+ SVN_ERR(svn_client_conflict_get(&conflict, sbox_wc_path(b, "A1/mu"), 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));
+ }
+
+ /* Resolve the tree conflict by moving "mu" to "mu-moved-again". */
+ SVN_ERR(svn_client_conflict_tree_resolve_by_id(
+ conflict, svn_client_conflict_option_incoming_move_file_text_merge,
+ ctx, pool));
+
+ /* The file should not be in conflict. */
+ SVN_ERR(svn_client_conflict_get(&conflict, sbox_wc_path(b, "A1/mu"),
+ 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);
+
+ /* The move destination should have the expected content. */
+ SVN_ERR(svn_stringbuf_from_file2(&buf, sbox_wc_path(b, "A1/mu-moved-again"),
+ pool));
+ SVN_TEST_STRING_ASSERT(buf->data, "New branch content.\n");
+
+ 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;
+}
+
+static svn_error_t *
+test_merge_incoming_file_move_new_line_of_history(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;
+
+ SVN_ERR(svn_test__sandbox_create(
+ b, "merge_incoming_file_move_new_line_of_history", opts, pool));
+
+ SVN_ERR(sbox_add_and_commit_greek_tree(b));
+ /* Create a copy of node "A". */
+ SVN_ERR(sbox_wc_copy(b, "A", "A1"));
+ SVN_ERR(sbox_wc_commit(b, ""));
+ /* On "trunk", move the file. */
+ SVN_ERR(sbox_wc_move(b, "A/mu", "A/mu-moved"));
+ SVN_ERR(sbox_wc_commit(b, ""));
+ /* On "trunk", change the line of history of the moved file by
+ * replacing it. */
+ SVN_ERR(sbox_wc_delete(b, "A/mu-moved"));
+ SVN_ERR(sbox_file_write(b, "A/mu-moved", "x"));
+ SVN_ERR(sbox_wc_add(b, "A/mu-moved"));
+ SVN_ERR(sbox_wc_commit(b, ""));
+ /* On "trunk", move the replaced file. */
+ SVN_ERR(sbox_wc_move(b, "A/mu-moved", "A/mu-moved-again"));
+ SVN_ERR(sbox_wc_commit(b, ""));
+ /* On "branch", edit the file. */
+ SVN_ERR(sbox_file_write(b, "A1/mu", "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 in the file "mu". */
+ SVN_ERR(svn_client_conflict_get(&conflict, sbox_wc_path(b, "A1/mu"), 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));
+
+ /* The svn_client_conflict_option_incoming_move_file_text_merge option
+ * should not be available, as the "mu" file was actually deleted at
+ * some point (and the remaining move is a part of the new line of
+ * history). */
+ {
+ svn_client_conflict_option_id_t expected_opts[] = {
+ svn_client_conflict_option_postpone,
+ svn_client_conflict_option_accept_current_wc_state,
+ -1 /* end of list */
+ };
+ SVN_ERR(assert_tree_conflict_options(conflict, ctx, expected_opts, pool));
+ }
+
+ return SVN_NO_ERROR;
+}
+
/* ========================================================================== */
@@ -3085,7 +3590,8 @@ static struct svn_test_descriptor_t test
"update incoming move file text merge"),
SVN_TEST_OPTS_PASS(test_switch_incoming_move_file_text_merge,
"switch incoming move file text merge"),
- SVN_TEST_OPTS_PASS(test_merge_incoming_move_dir, "merge incoming move dir"),
+ SVN_TEST_OPTS_XFAIL(test_merge_incoming_move_dir,
+ "merge incoming move dir"),
SVN_TEST_OPTS_PASS(test_merge_incoming_move_dir2,
"merge incoming move dir with local edit"),
SVN_TEST_OPTS_PASS(test_merge_incoming_move_dir3,
@@ -3096,6 +3602,14 @@ static struct svn_test_descriptor_t test
"merge file property"),
SVN_TEST_OPTS_XFAIL(test_merge_incoming_move_file_text_merge_conflict,
"merge incoming move file merge with text conflict"),
+ SVN_TEST_OPTS_XFAIL(test_merge_incoming_edit_file_moved_away,
+ "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_OPTS_PASS(test_merge_incoming_file_move_new_line_of_history,
+ "merge incoming file move with new line of history"),
SVN_TEST_NULL
};