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 2022/01/14 14:01:51 UTC
svn commit: r1897034 [32/37] - in /subversion/branches/multi-wc-format: ./ build/ build/ac-macros/ build/generator/ build/generator/swig/ build/generator/templates/ contrib/client-side/ contrib/client-side/svn_load_dirs/ contrib/hook-scripts/ contrib/s...
Modified: subversion/branches/multi-wc-format/subversion/tests/libsvn_client/conflicts-test.c
URL: http://svn.apache.org/viewvc/subversion/branches/multi-wc-format/subversion/tests/libsvn_client/conflicts-test.c?rev=1897034&r1=1897033&r2=1897034&view=diff
==============================================================================
--- subversion/branches/multi-wc-format/subversion/tests/libsvn_client/conflicts-test.c (original)
+++ subversion/branches/multi-wc-format/subversion/tests/libsvn_client/conflicts-test.c Fri Jan 14 14:01:45 2022
@@ -154,7 +154,7 @@ assert_text_conflict_options(svn_client_
return SVN_NO_ERROR;
}
-/*
+/*
* The following tests verify resolution of "incoming file add vs.
* local file obstruction upon merge" tree conflicts.
*/
@@ -170,6 +170,7 @@ static const char *deleted_file_name = "
static const char *deleted_dir_name = "B";
static const char *deleted_dir_child = "lambda";
static const char *new_dir_name = "newdir";
+static const char *unversioned_file_name = "unversioned.txt";
/* File property content. */
static const char *propval_trunk = "This is a property on the trunk.";
@@ -177,6 +178,8 @@ static const char *propval_branch = "Thi
static const char *propval_different = "This is a different property value.";
/* File content. */
+static const char *new_file_content =
+ "This is a new file\n";
static const char *modified_file_content =
"This is a modified file\n";
static const char *modified_file_on_branch_content =
@@ -185,6 +188,8 @@ static const char *added_file_on_branch_
"This is a file added on the branch\n";
static const char *modified_file_in_working_copy_content =
"This is a modified file in the working copy\n";
+static const char *unversioned_file_content =
+ "This is an unversioned file\n";
/* A helper function which prepares a working copy for the tests below. */
static svn_error_t *
@@ -477,7 +482,7 @@ test_merge_incoming_added_file_replace_a
return SVN_NO_ERROR;
}
-/*
+/*
* The following tests verify resolution of "incoming dir add vs.
* local dir obstruction upon merge" tree conflicts.
*/
@@ -1357,7 +1362,7 @@ create_wc_with_incoming_delete_file_merg
}
else
{
- /* Commit modifcation and run a merge from the trunk to the branch. */
+ /* Commit modification and run a merge from the trunk to the branch. */
SVN_ERR(sbox_wc_commit(b, ""));
SVN_ERR(sbox_wc_update(b, "", SVN_INVALID_REVNUM));
/* This should raise an "incoming delete vs local edit" tree conflict. */
@@ -1448,7 +1453,7 @@ test_merge_incoming_delete_file_ignore(c
SVN_TEST_ASSERT(!status->file_external);
SVN_TEST_ASSERT(status->moved_from_abspath == NULL);
SVN_TEST_ASSERT(status->moved_to_abspath == NULL);
-
+
SVN_ERR(svn_client_conflict_get(&conflict, sbox_wc_path(b, deleted_path),
ctx, b->pool, b->pool));
@@ -1801,7 +1806,7 @@ test_update_incoming_delete_file_ignore(
SVN_TEST_ASSERT(!status->file_external);
SVN_TEST_ASSERT(status->moved_from_abspath == NULL);
SVN_TEST_ASSERT(status->moved_to_abspath == NULL);
-
+
SVN_ERR(svn_client_conflict_get(&conflict, sbox_wc_path(b, deleted_path),
ctx, b->pool, b->pool));
@@ -2111,7 +2116,7 @@ create_wc_with_incoming_delete_dir_confl
if (local_add)
{
const char *new_child_path;
-
+
new_child_path = svn_relpath_join(branch_path,
svn_relpath_join(deleted_dir_name,
new_file_name_branch,
@@ -2621,6 +2626,7 @@ test_merge_incoming_delete_vs_local_dele
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 */
};
@@ -2634,6 +2640,7 @@ test_merge_incoming_delete_vs_local_dele
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 */
};
@@ -4120,7 +4127,7 @@ create_wc_with_dir_add_vs_dir_add_update
SVN_ERR(svn_io_dir_make(sbox_wc_path(b, new_file_child_path),
APR_OS_DEFAULT, b->pool));
- /* Update to the HEAD revision.
+ /* Update to the HEAD revision.
* This should raise an "incoming add vs local add" tree conflict. */
SVN_ERR(sbox_wc_update(b, "", SVN_INVALID_REVNUM));
@@ -5019,7 +5026,7 @@ test_cherry_pick_post_move_edit(const sv
/* And "A1/mu" should have expected contents. */
SVN_ERR(svn_stringbuf_from_file2(&buf, sbox_wc_path(b, "A1/mu"), pool));
- SVN_TEST_STRING_ASSERT(buf->data,
+ SVN_TEST_STRING_ASSERT(buf->data,
"<<<<<<< .working" "\n"
"This is the file 'mu'." "\n"
"||||||| .old" "\n"
@@ -5119,7 +5126,7 @@ test_merge_incoming_move_dir_across_bran
apr_array_header_t *possible_moved_to_abspaths;
SVN_ERR(svn_test__sandbox_create(b,
- "merge_incoming_move_dir accross branches",
+ "merge_incoming_move_dir across branches",
opts, pool));
SVN_ERR(create_wc_with_incoming_delete_dir_conflict_across_branches(b));
@@ -6189,6 +6196,1269 @@ test_file_vs_dir_move_merge_assertion_fa
return SVN_NO_ERROR;
}
+static svn_error_t *
+test_update_file_add_vs_unversiond_file(const svn_test_opts_t *opts,
+ apr_pool_t *pool)
+{
+ svn_test__sandbox_t *b = apr_palloc(pool, sizeof(*b));
+ svn_client_conflict_t *conflict;
+ svn_client_ctx_t *ctx;
+ struct status_baton sb;
+ struct svn_client_status_t *status;
+ svn_opt_revision_t opt_rev;
+ svn_stringbuf_t *buf;
+
+ SVN_ERR(svn_test__sandbox_create(b, "update_file_add_vs_unversioned_file",
+ opts, pool));
+
+ SVN_ERR(sbox_add_and_commit_greek_tree(b)); /* r1 */
+
+ /* Add a new file. */
+ SVN_ERR(sbox_file_write(b, new_file_name, new_file_content));
+ SVN_ERR(sbox_wc_add(b, new_file_name));
+ SVN_ERR(sbox_wc_commit(b, "")); /* r2 */
+
+ SVN_ERR(sbox_wc_update(b, "", 1)); /* back to r1 */
+
+ /* Create an identical unversioned file. */
+ SVN_ERR(sbox_file_write(b, new_file_name, new_file_content));
+ SVN_ERR(sbox_wc_update(b, "", 2)); /* back to r2 */
+
+ SVN_ERR(svn_test__create_client_ctx(&ctx, b, b->pool));
+ SVN_ERR(svn_client_conflict_get(&conflict, sbox_wc_path(b, new_file_name),
+ ctx, b->pool, b->pool));
+ SVN_TEST_ASSERT(svn_client_conflict_get_local_change(conflict) ==
+ svn_wc_conflict_reason_unversioned);
+ SVN_TEST_ASSERT(svn_client_conflict_get_incoming_change(conflict) ==
+ svn_wc_conflict_action_add);
+ {
+ 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_added_file_text_merge,
+ -1 /* end of list */
+ };
+ SVN_ERR(assert_tree_conflict_options(conflict, ctx, expected_opts,
+ b->pool));
+ }
+
+ SVN_ERR(svn_client_conflict_tree_resolve_by_id(
+ conflict,
+ svn_client_conflict_option_incoming_added_file_text_merge,
+ ctx, b->pool));
+
+ /* Ensure that the 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, new_file_name),
+ &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_normal);
+ SVN_TEST_ASSERT(status->text_status == svn_wc_status_normal);
+ 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);
+
+ /* Ensure that the file has the expected content. */
+ SVN_ERR(svn_stringbuf_from_file2(&buf, sbox_wc_path(b, new_file_name),
+ b->pool));
+ SVN_TEST_STRING_ASSERT(buf->data, new_file_content);
+ return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+test_switch_file_add_vs_unversiond_file(const svn_test_opts_t *opts,
+ apr_pool_t *pool)
+{
+ svn_test__sandbox_t *b = apr_palloc(pool, sizeof(*b));
+ svn_client_conflict_t *conflict;
+ svn_client_ctx_t *ctx;
+ struct status_baton sb;
+ struct svn_client_status_t *status;
+ svn_opt_revision_t opt_rev;
+ svn_stringbuf_t *buf;
+ svn_revnum_t result_rev;
+ const char *trunk_url;
+ const char *new_file_path;
+
+ SVN_ERR(svn_test__sandbox_create(b, "switch_file_add_vs_unversioned_file",
+ opts, pool));
+
+ SVN_ERR(sbox_add_and_commit_greek_tree(b)); /* r1 */
+
+ /* Create a branch of node "A". */
+ SVN_ERR(sbox_wc_copy(b, trunk_path, branch_path));
+ SVN_ERR(sbox_wc_commit(b, "")); /* r2 */
+
+ /* Add a new file on trunk. */
+ new_file_path = svn_relpath_join(trunk_path, new_file_name, b->pool);
+ SVN_ERR(sbox_file_write(b, new_file_path, new_file_content));
+ SVN_ERR(sbox_wc_add(b, new_file_path));
+ SVN_ERR(sbox_wc_commit(b, "")); /* r3 */
+
+ SVN_ERR(sbox_wc_update(b, "", 2)); /* back to r2 */
+
+ /* Create an identical unversioned file on the branch. */
+ new_file_path = svn_relpath_join(branch_path, new_file_name, b->pool);
+ SVN_ERR(sbox_file_write(b, new_file_path, new_file_content));
+
+ /* Switch branch to trunk. */
+ trunk_url = apr_pstrcat(b->pool, b->repos_url, "/", trunk_path, SVN_VA_NULL);
+ SVN_ERR(svn_test__create_client_ctx(&ctx, b, b->pool));
+ opt_rev.kind = svn_opt_revision_head;
+ opt_rev.value.number = SVN_INVALID_REVNUM;
+ SVN_ERR(svn_client_switch3(&result_rev, sbox_wc_path(b, branch_path),
+ trunk_url, &opt_rev, &opt_rev,
+ svn_depth_infinity,
+ TRUE, FALSE, FALSE, FALSE, ctx, b->pool));
+
+ SVN_ERR(svn_client_conflict_get(&conflict, sbox_wc_path(b, new_file_path),
+ ctx, b->pool, b->pool));
+ SVN_TEST_ASSERT(svn_client_conflict_get_local_change(conflict) ==
+ svn_wc_conflict_reason_unversioned);
+ SVN_TEST_ASSERT(svn_client_conflict_get_incoming_change(conflict) ==
+ svn_wc_conflict_action_add);
+ {
+ 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_added_file_text_merge,
+ -1 /* end of list */
+ };
+ SVN_ERR(assert_tree_conflict_options(conflict, ctx, expected_opts,
+ b->pool));
+ }
+
+ SVN_ERR(svn_client_conflict_tree_resolve_by_id(
+ conflict,
+ svn_client_conflict_option_incoming_added_file_text_merge,
+ ctx, b->pool));
+
+ /* Ensure that the 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, new_file_path),
+ &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_normal);
+ SVN_TEST_ASSERT(status->text_status == svn_wc_status_normal);
+ 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);
+
+ /* Ensure that the file has the expected content. */
+ SVN_ERR(svn_stringbuf_from_file2(&buf, sbox_wc_path(b, new_file_path),
+ b->pool));
+ SVN_TEST_STRING_ASSERT(buf->data, new_file_content);
+ return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+create_unversioned_dir(const char **new_file_path,
+ const char **unversioned_file_path,
+ const char *new_dir_path,
+ svn_test__sandbox_t *b, apr_pool_t *pool)
+{
+ apr_file_t *file;
+ apr_size_t content_len;
+
+ /* Create an unversioned directory. */
+ SVN_ERR(svn_io_dir_make(sbox_wc_path(b, new_dir_path), APR_OS_DEFAULT,
+ b->pool));
+
+ /* Create an unversioned file which will collide with a versioned file. */
+ *new_file_path = svn_relpath_join(new_dir_path, new_file_name, b->pool);
+ SVN_ERR(svn_io_file_open(&file, sbox_wc_path(b, *new_file_path),
+ (APR_READ | APR_WRITE | APR_CREATE | APR_TRUNCATE), APR_OS_DEFAULT,
+ b->pool));
+ content_len = strlen(unversioned_file_content);
+ SVN_ERR(svn_io_file_write(file, unversioned_file_content, &content_len,
+ b->pool));
+ SVN_ERR(svn_io_file_close(file, b->pool));
+
+ /* Create another unversioned file at a different path. */
+ *unversioned_file_path = svn_relpath_join(new_dir_path, unversioned_file_name,
+ b->pool);
+ SVN_ERR(svn_io_file_open(&file, sbox_wc_path(b, *unversioned_file_path),
+ (APR_READ | APR_WRITE | APR_CREATE | APR_TRUNCATE), APR_OS_DEFAULT,
+ b->pool));
+ content_len = strlen(unversioned_file_content);
+ SVN_ERR(svn_io_file_write(file, unversioned_file_content, &content_len,
+ b->pool));
+ SVN_ERR(svn_io_file_close(file, b->pool));
+
+ return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+resolve_added_dir_vs_unversioned_dir(const char *new_dir_path,
+ const char *new_file_path,
+ const char *unversioned_file_path,
+ svn_test__sandbox_t *b, apr_pool_t *pool)
+{
+ svn_client_ctx_t *ctx;
+ svn_client_conflict_t *conflict;
+ svn_opt_revision_t opt_rev;
+ struct status_baton sb;
+ struct svn_client_status_t *status;
+ svn_stringbuf_t *buf;
+
+ SVN_ERR(svn_test__create_client_ctx(&ctx, b, b->pool));
+ SVN_ERR(svn_client_conflict_get(&conflict, sbox_wc_path(b, new_dir_path),
+ ctx, b->pool, b->pool));
+ SVN_TEST_ASSERT(svn_client_conflict_get_local_change(conflict) ==
+ svn_wc_conflict_reason_unversioned);
+ SVN_TEST_ASSERT(svn_client_conflict_get_incoming_change(conflict) ==
+ svn_wc_conflict_action_add);
+ {
+ 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_added_dir_merge,
+ -1 /* end of list */
+ };
+ SVN_ERR(assert_tree_conflict_options(conflict, ctx, expected_opts,
+ b->pool));
+ }
+
+ SVN_ERR(svn_client_conflict_tree_resolve_by_id(
+ conflict,
+ svn_client_conflict_option_incoming_added_dir_merge,
+ ctx, b->pool));
+
+ /* Ensure that the directory 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, new_dir_path),
+ &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_dir);
+ SVN_TEST_ASSERT(status->versioned);
+ SVN_TEST_ASSERT(!status->conflicted);
+ SVN_TEST_ASSERT(status->node_status == svn_wc_status_normal);
+ SVN_TEST_ASSERT(status->text_status == svn_wc_status_normal);
+ 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);
+
+ /* Ensure that the "collision" 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, new_file_path),
+ &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);
+
+ /* Ensure that the file has the expected content. */
+ SVN_ERR(svn_stringbuf_from_file2(&buf, sbox_wc_path(b, new_file_path),
+ b->pool));
+ SVN_TEST_STRING_ASSERT(buf->data, unversioned_file_content);
+
+ /* Ensure that the unversioned file has the expected status. */
+ opt_rev.kind = svn_opt_revision_working;
+ sb.result_pool = b->pool;
+ SVN_TEST_ASSERT_ERROR(
+ svn_client_status6(NULL, ctx, sbox_wc_path(b, unversioned_file_path),
+ &opt_rev, svn_depth_unknown, TRUE, TRUE,
+ TRUE, TRUE, FALSE, TRUE, NULL,
+ status_func, &sb, b->pool),
+ SVN_ERR_ENTRY_NOT_FOUND);
+
+ /* Ensure that the file has the expected content. */
+ SVN_ERR(svn_stringbuf_from_file2(&buf, sbox_wc_path(b, unversioned_file_path),
+ b->pool));
+ SVN_TEST_STRING_ASSERT(buf->data, unversioned_file_content);
+
+ return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+test_update_dir_add_vs_unversioned_dir(const svn_test_opts_t *opts,
+ apr_pool_t *pool)
+{
+ svn_test__sandbox_t *b = apr_palloc(pool, sizeof(*b));
+ const char *new_dir_path;
+ const char *new_file_path;
+ const char *unversioned_file_path;
+
+ SVN_ERR(svn_test__sandbox_create(b, "update_dir_add_vs_unversioned_dir",
+ opts, pool));
+
+ SVN_ERR(sbox_add_and_commit_greek_tree(b)); /* r1 */
+
+ /* Add a new directory */
+ new_dir_path = svn_relpath_join(trunk_path, new_dir_name, b->pool);
+ SVN_ERR(sbox_wc_mkdir(b, new_dir_path));
+ new_file_path = svn_relpath_join(new_dir_path, new_file_name, b->pool);
+ SVN_ERR(sbox_file_write(b, new_file_path, new_file_content));
+ SVN_ERR(sbox_wc_add(b, new_file_path));
+ SVN_ERR(sbox_wc_commit(b, "")); /* r2 */
+
+ SVN_ERR(sbox_wc_update(b, "", 1)); /* back to r1 */
+
+ new_dir_path = svn_relpath_join(trunk_path, new_dir_name, b->pool);
+ SVN_ERR(create_unversioned_dir(&new_file_path, &unversioned_file_path,
+ new_dir_path, b, b->pool));
+
+ SVN_ERR(sbox_wc_update(b, "", 2)); /* back to r2 */
+
+ SVN_ERR(resolve_added_dir_vs_unversioned_dir(new_dir_path, new_file_path,
+ unversioned_file_path,
+ b, b->pool));
+ return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+test_switch_dir_add_vs_unversioned_dir(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_revnum_t result_rev;
+ const char *trunk_url;
+ const char *new_dir_path;
+ const char *new_file_path;
+ const char *unversioned_file_path;
+
+ SVN_ERR(svn_test__sandbox_create(b, "switch_dir_add_vs_unversioned_dir",
+ opts, pool));
+
+ SVN_ERR(sbox_add_and_commit_greek_tree(b)); /* r1 */
+
+ /* Create a branch of node "A". */
+ SVN_ERR(sbox_wc_copy(b, trunk_path, branch_path));
+ SVN_ERR(sbox_wc_commit(b, "")); /* r2 */
+
+ /* Add a new directory on trunk. */
+ new_dir_path = svn_relpath_join(trunk_path, new_dir_name, b->pool);
+ SVN_ERR(sbox_wc_mkdir(b, new_dir_path));
+ new_file_path = svn_relpath_join(new_dir_path, new_file_name, b->pool);
+ SVN_ERR(sbox_file_write(b, new_file_path, new_file_content));
+ SVN_ERR(sbox_wc_add(b, new_file_path));
+ SVN_ERR(sbox_wc_commit(b, "")); /* r3 */
+
+ SVN_ERR(sbox_wc_update(b, "", 2)); /* back to r2 */
+
+ new_dir_path = svn_relpath_join(branch_path, new_dir_name, b->pool);
+ SVN_ERR(create_unversioned_dir(&new_file_path, &unversioned_file_path,
+ new_dir_path, b, b->pool));
+
+ /* Switch branch to trunk. */
+ trunk_url = apr_pstrcat(b->pool, b->repos_url, "/", trunk_path, SVN_VA_NULL);
+ SVN_ERR(svn_test__create_client_ctx(&ctx, b, b->pool));
+ opt_rev.kind = svn_opt_revision_head;
+ opt_rev.value.number = SVN_INVALID_REVNUM;
+ SVN_ERR(svn_client_switch3(&result_rev, sbox_wc_path(b, branch_path),
+ trunk_url, &opt_rev, &opt_rev,
+ svn_depth_infinity,
+ TRUE, FALSE, FALSE, FALSE, ctx, b->pool));
+
+ SVN_ERR(resolve_added_dir_vs_unversioned_dir(new_dir_path, new_file_path,
+ unversioned_file_path,
+ b, b->pool));
+
+ return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+create_file_move_vs_file_move_merge_conflict(svn_client_conflict_t **conflict,
+ svn_boolean_t edit_file,
+ svn_test__sandbox_t *b,
+ svn_client_ctx_t *ctx)
+{
+ svn_opt_revision_t opt_rev;
+ const char *branch_url;
+
+ /* Create a branch of node "A". */
+ SVN_ERR(sbox_wc_copy(b, "A", "A2"));
+ SVN_ERR(sbox_wc_commit(b, "")); /* r2 */
+
+ /* Move a file on trunk. */
+ SVN_ERR(sbox_wc_move(b, "A/mu", "A/mu-moved"));
+ SVN_ERR(sbox_wc_commit(b, "")); /* r3 */
+
+ /* Move the same file to a different location on the branch. */
+ SVN_ERR(sbox_wc_move(b, "A2/mu", "A2/mu-also-moved"));
+ SVN_ERR(sbox_wc_commit(b, ""));
+ if (edit_file)
+ {
+ /* Edit moved a file on the branch. */
+ SVN_ERR(sbox_file_write(b, "A2/mu-also-moved", modified_file_content));
+ SVN_ERR(sbox_wc_commit(b, ""));
+ }
+
+ /* Merge branch to trunk. */
+ SVN_ERR(sbox_wc_update(b, "", SVN_INVALID_REVNUM));
+ branch_url = apr_pstrcat(b->pool, b->repos_url, "/A2", SVN_VA_NULL);
+ opt_rev.kind = svn_opt_revision_head;
+ opt_rev.value.number = SVN_INVALID_REVNUM;
+ SVN_ERR(svn_client_merge_peg5(branch_url, NULL, &opt_rev,
+ sbox_wc_path(b, "A"),
+ svn_depth_infinity,
+ FALSE, FALSE, FALSE, FALSE, FALSE, FALSE,
+ NULL, ctx, b->pool));
+
+ SVN_ERR(svn_client_conflict_get(conflict, sbox_wc_path(b, "A/mu"),
+ ctx, b->pool, b->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_delete_ignore,
+ svn_client_conflict_option_incoming_delete_accept,
+ -1 /* end of list */
+ };
+ SVN_ERR(assert_tree_conflict_options(*conflict, ctx, expected_opts,
+ b->pool));
+ }
+
+ SVN_ERR(svn_client_conflict_tree_get_details(*conflict, ctx, b->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_both_moved_file_merge,
+ svn_client_conflict_option_both_moved_file_move_merge,
+ -1 /* end of list */
+ };
+ SVN_ERR(assert_tree_conflict_options(*conflict, ctx, expected_opts,
+ b->pool));
+ }
+
+ return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+test_merge_file_move_vs_file_move(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_client_conflict_t *conflict;
+ svn_opt_revision_t opt_rev;
+ struct status_baton sb;
+ struct svn_client_status_t *status;
+
+ SVN_ERR(svn_test__sandbox_create(b, "merge_file_move_vs_file_move",
+ opts, pool));
+
+ SVN_ERR(sbox_add_and_commit_greek_tree(b)); /* r1 */
+
+ SVN_ERR(svn_test__create_client_ctx(&ctx, b, b->pool));
+ SVN_ERR(create_file_move_vs_file_move_merge_conflict(&conflict,
+ FALSE, b, ctx));
+
+ SVN_ERR(svn_client_conflict_tree_resolve_by_id(
+ conflict,
+ svn_client_conflict_option_both_moved_file_merge,
+ ctx, b->pool));
+
+ /* The node "A/mu" should no longer exist. */
+ SVN_TEST_ASSERT_ERROR(svn_client_conflict_get(
+ &conflict, sbox_wc_path(b, "A/mu"), ctx, pool, pool),
+ SVN_ERR_WC_PATH_NOT_FOUND);
+
+ /* The node "A/mu-also-moved" should not exist. */
+ SVN_TEST_ASSERT_ERROR(svn_client_conflict_get(
+ &conflict, sbox_wc_path(b, "A/mu-also-moved"), ctx,
+ pool, pool),
+ SVN_ERR_WC_PATH_NOT_FOUND);
+
+ /* Ensure that the merged 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, "A/mu-moved"),
+ &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_normal);
+ SVN_TEST_ASSERT(status->text_status == svn_wc_status_normal);
+ 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);
+
+ return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+test_merge_file_move_vs_file_move_accept_move(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_client_conflict_t *conflict;
+ svn_opt_revision_t opt_rev;
+ struct status_baton sb;
+ struct svn_client_status_t *status;
+
+ SVN_ERR(svn_test__sandbox_create(b,
+ "merge_file_move_vs_file_move_accept_move",
+ opts, pool));
+
+ SVN_ERR(sbox_add_and_commit_greek_tree(b)); /* r1 */
+
+ SVN_ERR(svn_test__create_client_ctx(&ctx, b, b->pool));
+ SVN_ERR(create_file_move_vs_file_move_merge_conflict(&conflict,
+ FALSE, b, ctx));
+
+ SVN_ERR(svn_client_conflict_tree_resolve_by_id(
+ conflict,
+ svn_client_conflict_option_both_moved_file_move_merge,
+ ctx, b->pool));
+
+ /* The node "A/mu" should no longer exist. */
+ SVN_TEST_ASSERT_ERROR(svn_client_conflict_get(&conflict,
+ sbox_wc_path(b, "A/mu"),
+ ctx, pool, pool),
+ SVN_ERR_WC_PATH_NOT_FOUND);
+
+ /* The node "A/mu-moved" should be moved to "A/mu-also-moved". */
+ opt_rev.kind = svn_opt_revision_working;
+ sb.result_pool = b->pool;
+ SVN_ERR(svn_client_status6(NULL, ctx, sbox_wc_path(b, "A/mu-moved"),
+ &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_deleted);
+ SVN_TEST_ASSERT(status->text_status == svn_wc_status_normal);
+ 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_STRING_ASSERT(status->moved_to_abspath,
+ sbox_wc_path(b, "A/mu-also-moved"));
+
+
+ /* Ensure that the merged 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, "A/mu-also-moved"),
+ &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_added);
+ SVN_TEST_ASSERT(status->text_status == svn_wc_status_normal);
+ 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_STRING_ASSERT(status->moved_from_abspath,
+ sbox_wc_path(b, "A/mu-moved"));
+ SVN_TEST_ASSERT(status->moved_to_abspath == NULL);
+
+ return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+test_merge_file_edit_move_vs_file_move(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_client_conflict_t *conflict;
+ svn_opt_revision_t opt_rev;
+ struct status_baton sb;
+ struct svn_client_status_t *status;
+ svn_stringbuf_t *buf;
+
+ SVN_ERR(svn_test__sandbox_create(b, "merge_file_edit_move_vs_file_move",
+ opts, pool));
+
+ SVN_ERR(sbox_add_and_commit_greek_tree(b)); /* r1 */
+
+ SVN_ERR(svn_test__create_client_ctx(&ctx, b, b->pool));
+ SVN_ERR(create_file_move_vs_file_move_merge_conflict(&conflict,
+ TRUE, b, ctx));
+
+ SVN_ERR(svn_client_conflict_tree_resolve_by_id(
+ conflict,
+ svn_client_conflict_option_both_moved_file_merge,
+ ctx, b->pool));
+
+ /* The node "A/mu" should no longer exist. */
+ SVN_TEST_ASSERT_ERROR(svn_client_conflict_get(
+ &conflict, sbox_wc_path(b, "A/mu"), ctx, pool, pool),
+ SVN_ERR_WC_PATH_NOT_FOUND);
+
+ /* The node "A/mu-also-moved" should not exist. */
+ SVN_TEST_ASSERT_ERROR(svn_client_conflict_get(
+ &conflict, sbox_wc_path(b, "A/mu-also-moved"), ctx,
+ pool, pool),
+ SVN_ERR_WC_PATH_NOT_FOUND);
+
+ /* Ensure that the merged 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, "A/mu-moved"),
+ &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);
+
+ /* Make sure the file has the expected content. */
+ SVN_ERR(svn_stringbuf_from_file2(&buf, sbox_wc_path(b, "A/mu-moved"), pool));
+ SVN_TEST_STRING_ASSERT(buf->data, modified_file_content);
+
+ return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+test_merge_file_edit_move_vs_file_move_accept_move(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_client_conflict_t *conflict;
+ svn_opt_revision_t opt_rev;
+ struct status_baton sb;
+ struct svn_client_status_t *status;
+ svn_stringbuf_t *buf;
+
+ SVN_ERR(svn_test__sandbox_create(
+ b, "merge_file_edit_move_vs_file_move_accept_move", opts, pool));
+
+ SVN_ERR(sbox_add_and_commit_greek_tree(b)); /* r1 */
+
+ SVN_ERR(svn_test__create_client_ctx(&ctx, b, b->pool));
+ SVN_ERR(create_file_move_vs_file_move_merge_conflict(&conflict,
+ TRUE, b, ctx));
+
+ SVN_ERR(svn_client_conflict_tree_resolve_by_id(
+ conflict,
+ svn_client_conflict_option_both_moved_file_move_merge,
+ ctx, b->pool));
+
+ /* The node "A/mu" should no longer exist. */
+ SVN_TEST_ASSERT_ERROR(svn_client_conflict_get(&conflict,
+ sbox_wc_path(b, "A/mu"),
+ ctx, pool, pool),
+ SVN_ERR_WC_PATH_NOT_FOUND);
+
+ /* The node "A/mu-moved" should be moved to "A/mu-also-moved". */
+ opt_rev.kind = svn_opt_revision_working;
+ sb.result_pool = b->pool;
+ SVN_ERR(svn_client_status6(NULL, ctx, sbox_wc_path(b, "A/mu-moved"),
+ &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_deleted);
+ SVN_TEST_ASSERT(status->text_status == svn_wc_status_normal);
+ 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_STRING_ASSERT(status->moved_to_abspath,
+ sbox_wc_path(b, "A/mu-also-moved"));
+
+
+ /* Ensure that the merged 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, "A/mu-also-moved"),
+ &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_added);
+ 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_STRING_ASSERT(status->moved_from_abspath,
+ sbox_wc_path(b, "A/mu-moved"));
+ SVN_TEST_ASSERT(status->moved_to_abspath == NULL);
+
+ /* Make sure the file has the expected content. */
+ SVN_ERR(svn_stringbuf_from_file2(&buf, sbox_wc_path(b, "A/mu-also-moved"),
+ pool));
+ SVN_TEST_STRING_ASSERT(buf->data, modified_file_content);
+
+ return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+create_dir_move_vs_dir_move_merge_conflict(svn_client_conflict_t **conflict,
+ svn_test__sandbox_t *b,
+ svn_client_ctx_t *ctx)
+{
+ svn_opt_revision_t opt_rev;
+ const char *branch_url;
+ apr_array_header_t *options;
+ svn_client_conflict_option_t *option;
+ apr_array_header_t *possible_moved_to_abspaths;
+
+ /* Create a branch of node "A". */
+ SVN_ERR(sbox_wc_copy(b, "A", "A2"));
+ SVN_ERR(sbox_wc_commit(b, "")); /* r2 */
+
+ /* Move a directory on trunk. */
+ SVN_ERR(sbox_wc_move(b, "A/B", "A/B-moved"));
+ SVN_ERR(sbox_wc_commit(b, "")); /* r3 */
+
+ /* Edit a file in the moved directory on trunk. */
+ SVN_ERR(sbox_file_write(b, "A/B-moved/E/alpha",
+ modified_file_content));
+ SVN_ERR(sbox_wc_commit(b, ""));
+
+ /* Move the same directory to a different location on the branch. */
+ SVN_ERR(sbox_wc_move(b, "A2/B", "A2/B-also-moved"));
+ SVN_ERR(sbox_wc_commit(b, ""));
+
+ /* Edit a file in the moved directory on the branch. */
+ SVN_ERR(sbox_file_write(b, "A2/B-also-moved/lambda",
+ modified_file_content));
+ SVN_ERR(sbox_wc_commit(b, ""));
+
+ /* Merge branch to trunk. */
+ SVN_ERR(sbox_wc_update(b, "", SVN_INVALID_REVNUM));
+ branch_url = apr_pstrcat(b->pool, b->repos_url, "/A2", SVN_VA_NULL);
+ opt_rev.kind = svn_opt_revision_head;
+ opt_rev.value.number = SVN_INVALID_REVNUM;
+ SVN_ERR(svn_client_merge_peg5(branch_url, NULL, &opt_rev,
+ sbox_wc_path(b, "A"),
+ svn_depth_infinity,
+ FALSE, FALSE, FALSE, FALSE, FALSE, FALSE,
+ NULL, ctx, b->pool));
+
+ SVN_ERR(svn_client_conflict_get(conflict, sbox_wc_path(b, "A/B"),
+ ctx, b->pool, b->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_delete_ignore,
+ svn_client_conflict_option_incoming_delete_accept,
+ -1 /* end of list */
+ };
+ SVN_ERR(assert_tree_conflict_options(*conflict, ctx, expected_opts,
+ b->pool));
+ }
+
+ SVN_ERR(svn_client_conflict_tree_get_details(*conflict, ctx, b->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_both_moved_dir_merge,
+ svn_client_conflict_option_both_moved_dir_move_merge,
+ -1 /* end of list */
+ };
+ SVN_ERR(assert_tree_conflict_options(*conflict, ctx, expected_opts,
+ b->pool));
+ }
+
+ 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_both_moved_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));
+
+ /* The resolver finds two possible move destinations because both
+ * branches are checked out into the same working copy.
+ *
+ * Possible working copy destinations for moved-away 'A/B' are:
+ * (1): 'A/B-also-moved
+ * (2): 'A2/B-also-moved
+ * Only one destination can be a move; the others are copies.
+ */
+ SVN_TEST_INT_ASSERT(possible_moved_to_abspaths->nelts, 2);
+ SVN_TEST_STRING_ASSERT(
+ APR_ARRAY_IDX(possible_moved_to_abspaths, 0, const char *),
+ sbox_wc_path(b, "A/B-also-moved"));
+ SVN_TEST_STRING_ASSERT(
+ APR_ARRAY_IDX(possible_moved_to_abspaths, 1, const char *),
+ sbox_wc_path(b, "A2/B-also-moved"));
+
+ return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+test_merge_dir_move_vs_dir_move(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_client_conflict_t *conflict;
+ svn_opt_revision_t opt_rev;
+ struct status_baton sb;
+ struct svn_client_status_t *status;
+ svn_stringbuf_t *buf;
+
+ SVN_ERR(svn_test__sandbox_create(b, "merge_dir_move_vs_dir_move",
+ opts, pool));
+
+ SVN_ERR(sbox_add_and_commit_greek_tree(b)); /* r1 */
+
+ SVN_ERR(svn_test__create_client_ctx(&ctx, b, b->pool));
+ SVN_ERR(create_dir_move_vs_dir_move_merge_conflict(&conflict, b, ctx));
+
+ SVN_ERR(svn_client_conflict_tree_resolve_by_id(
+ conflict,
+ svn_client_conflict_option_both_moved_dir_merge,
+ ctx, b->pool));
+
+ /* The node "A/B" should not exist. */
+ SVN_TEST_ASSERT_ERROR(svn_client_conflict_get(&conflict,
+ sbox_wc_path(b, "A/B"),
+ ctx, pool, pool),
+ SVN_ERR_WC_PATH_NOT_FOUND);
+
+ /* The node "A/B-also-moved" should not exist. */
+ SVN_TEST_ASSERT_ERROR(svn_client_conflict_get(
+ &conflict,
+ sbox_wc_path(b, "A/B-also-moved"), ctx, pool, pool),
+ SVN_ERR_WC_PATH_NOT_FOUND);
+
+ /* Ensure that the merged directory 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, "A/B-moved"),
+ &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_dir);
+ SVN_TEST_ASSERT(status->versioned);
+ SVN_TEST_ASSERT(!status->conflicted);
+ SVN_TEST_ASSERT(status->node_status == svn_wc_status_normal);
+ SVN_TEST_ASSERT(status->text_status == svn_wc_status_normal);
+ 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);
+
+ /* Make sure the edited files have the expected content. */
+ SVN_ERR(svn_stringbuf_from_file2(&buf, sbox_wc_path(b, "A/B-moved/lambda"),
+ pool));
+ SVN_TEST_STRING_ASSERT(buf->data, modified_file_content);
+ SVN_ERR(svn_stringbuf_from_file2(&buf, sbox_wc_path(b, "A/B-moved/E/alpha"),
+ pool));
+ SVN_TEST_STRING_ASSERT(buf->data, modified_file_content);
+
+ return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+test_merge_dir_move_vs_dir_move_accept_move(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_client_conflict_t *conflict;
+ svn_opt_revision_t opt_rev;
+ struct status_baton sb;
+ struct svn_client_status_t *status;
+ svn_stringbuf_t *buf;
+
+ SVN_ERR(svn_test__sandbox_create(b, "merge_dir_move_vs_dir_move_accept_move",
+ opts, pool));
+
+ SVN_ERR(sbox_add_and_commit_greek_tree(b)); /* r1 */
+
+ SVN_ERR(svn_test__create_client_ctx(&ctx, b, b->pool));
+ SVN_ERR(create_dir_move_vs_dir_move_merge_conflict(&conflict, b, ctx));
+
+ SVN_ERR(svn_client_conflict_tree_resolve_by_id(
+ conflict,
+ svn_client_conflict_option_both_moved_dir_move_merge,
+ ctx, b->pool));
+
+ /* The node "A/B" should not exist. */
+ SVN_TEST_ASSERT_ERROR(svn_client_conflict_get(&conflict,
+ sbox_wc_path(b, "A/B"),
+ ctx, pool, pool),
+ SVN_ERR_WC_PATH_NOT_FOUND);
+
+ /* The node "A/B-moved" should be moved to A/B-also-moved. */
+ opt_rev.kind = svn_opt_revision_working;
+ sb.result_pool = b->pool;
+ SVN_ERR(svn_client_status6(NULL, ctx, sbox_wc_path(b, "A/B-moved"),
+ &opt_rev, svn_depth_empty, TRUE, TRUE,
+ TRUE, TRUE, FALSE, TRUE, NULL,
+ status_func, &sb, b->pool));
+ status = sb.status;
+ SVN_TEST_ASSERT(status->kind == svn_node_dir);
+ SVN_TEST_ASSERT(status->versioned);
+ SVN_TEST_ASSERT(!status->conflicted);
+ SVN_TEST_ASSERT(status->node_status == svn_wc_status_deleted);
+ SVN_TEST_ASSERT(status->text_status == svn_wc_status_normal);
+ 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_STRING_ASSERT(status->moved_to_abspath,
+ sbox_wc_path(b, "A/B-also-moved"));
+
+ /* Ensure that the merged directory has the expected status. */
+ SVN_ERR(svn_client_status6(NULL, ctx, sbox_wc_path(b, "A/B-also-moved"),
+ &opt_rev, svn_depth_empty, TRUE, TRUE,
+ TRUE, TRUE, FALSE, TRUE, NULL,
+ status_func, &sb, b->pool));
+ status = sb.status;
+ SVN_TEST_ASSERT(status->kind == svn_node_dir);
+ SVN_TEST_ASSERT(status->versioned);
+ SVN_TEST_ASSERT(!status->conflicted);
+ SVN_TEST_ASSERT(status->node_status == svn_wc_status_added);
+ SVN_TEST_ASSERT(status->text_status == svn_wc_status_normal);
+ 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_STRING_ASSERT(status->moved_from_abspath,
+ sbox_wc_path(b, "A/B-moved"));
+ SVN_TEST_ASSERT(status->moved_to_abspath == NULL);
+
+ /* Make sure the edited files have the expected content. */
+ SVN_ERR(svn_stringbuf_from_file2(&buf,
+ sbox_wc_path(b, "A/B-also-moved/lambda"),
+ pool));
+ SVN_TEST_STRING_ASSERT(buf->data, modified_file_content);
+ SVN_ERR(svn_stringbuf_from_file2(&buf,
+ sbox_wc_path(b, "A/B-also-moved/E/alpha"),
+ pool));
+ SVN_TEST_STRING_ASSERT(buf->data, modified_file_content);
+
+ return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+create_file_move_vs_file_move_update_conflict(svn_client_conflict_t **conflict,
+ svn_test__sandbox_t *b,
+ svn_client_ctx_t *ctx)
+{
+ apr_array_header_t *options;
+ svn_client_conflict_option_t *option;
+ apr_array_header_t *possible_moved_to_abspaths;
+
+ /* Move a file. */
+ SVN_ERR(sbox_wc_move(b, "A/mu", "A/mu-moved"));
+
+ /* Edit moved file. */
+ SVN_ERR(sbox_file_write(b, "A/mu-moved", modified_file_content));
+ SVN_ERR(sbox_wc_commit(b, ""));
+
+ /* Update back to r1, */
+ SVN_ERR(sbox_wc_update(b, "", 1)); /* r2 */
+
+ /* Copy the file to test handling of ambiguous moves. */
+ SVN_ERR(sbox_wc_copy(b, "A/mu", "A/mu-copied"));
+
+ /* Move the same file to a different location. */
+ SVN_ERR(sbox_wc_move(b, "A/mu", "A/mu-also-moved"));
+
+ /* Edit moved file. */
+ SVN_ERR(sbox_file_write(b, "A/mu-also-moved",
+ modified_file_in_working_copy_content));
+
+ /* Update to r2. */
+ /* This should raise an "incoming delete vs local delete" tree conflict. */
+ SVN_ERR(sbox_wc_update(b, "", SVN_INVALID_REVNUM));
+
+ SVN_ERR(svn_client_conflict_get(conflict, sbox_wc_path(b, "A/mu"),
+ ctx, b->pool, b->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_delete_ignore,
+ svn_client_conflict_option_incoming_delete_accept,
+ -1 /* end of list */
+ };
+ SVN_ERR(assert_tree_conflict_options(*conflict, ctx, expected_opts,
+ b->pool));
+ }
+
+ SVN_ERR(svn_client_conflict_tree_get_details(*conflict, ctx, b->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_both_moved_file_merge,
+ svn_client_conflict_option_both_moved_file_move_merge,
+ -1 /* end of list */
+ };
+ SVN_ERR(assert_tree_conflict_options(*conflict, ctx, expected_opts,
+ b->pool));
+ }
+
+ /* Check possible move destinations for the file. */
+ 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_both_moved_file_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));
+
+ /* The resolver finds two possible destinations for the moved file:
+ *
+ * Possible working copy destinations for moved-away 'A/mu' are:
+ * (1): 'A/mu-also-moved'
+ * (2): 'A/mu-copied'
+ * Only one destination can be a move; the others are copies.
+ */
+ SVN_TEST_INT_ASSERT(possible_moved_to_abspaths->nelts, 2);
+ SVN_TEST_STRING_ASSERT(
+ APR_ARRAY_IDX(possible_moved_to_abspaths, 0, const char *),
+ sbox_wc_path(b, "A/mu-also-moved"));
+ SVN_TEST_STRING_ASSERT(
+ APR_ARRAY_IDX(possible_moved_to_abspaths, 1, const char *),
+ sbox_wc_path(b, "A/mu-copied"));
+
+ return SVN_NO_ERROR;
+}
+
+
+static svn_error_t *
+test_update_file_move_vs_file_move(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_client_conflict_t *conflict;
+ svn_opt_revision_t opt_rev;
+ struct status_baton sb;
+ struct svn_client_status_t *status;
+ svn_stringbuf_t *buf;
+ svn_node_kind_t kind;
+ char *conflicted_content;
+
+ SVN_ERR(svn_test__sandbox_create(b, "update_file_move_vs_file_move",
+ opts, pool));
+
+ SVN_ERR(sbox_add_and_commit_greek_tree(b)); /* r1 */
+
+ SVN_ERR(svn_test__create_client_ctx(&ctx, b, b->pool));
+ SVN_ERR(create_file_move_vs_file_move_update_conflict(&conflict, b, ctx));
+
+ SVN_ERR(svn_client_conflict_tree_resolve_by_id(
+ conflict,
+ svn_client_conflict_option_both_moved_file_merge,
+ ctx, b->pool));
+
+ /* The node "A/mu" should no longer exist. */
+ SVN_TEST_ASSERT_ERROR(svn_client_conflict_get(
+ &conflict, sbox_wc_path(b, "A/mu"), ctx, pool, pool),
+ SVN_ERR_WC_PATH_NOT_FOUND);
+
+ /* The node "A/mu-moved" should now have moved to "A/mu-also-moved. */
+ SVN_ERR(svn_io_check_path(sbox_wc_path(b, "A/mu"), &kind, b->pool));
+ SVN_TEST_ASSERT(kind == svn_node_none);
+ opt_rev.kind = svn_opt_revision_working;
+ sb.result_pool = b->pool;
+ SVN_ERR(svn_client_status6(NULL, ctx, sbox_wc_path(b, "A/mu-moved"),
+ &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_deleted);
+ SVN_TEST_ASSERT(status->text_status == svn_wc_status_normal);
+ 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_STRING_ASSERT(status->moved_to_abspath,
+ sbox_wc_path(b, "A/mu-also-moved"));
+
+ /* Ensure that the merged 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, "A/mu-also-moved"),
+ &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_conflicted);
+ SVN_TEST_ASSERT(status->text_status == svn_wc_status_conflicted);
+ 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_STRING_ASSERT(status->moved_from_abspath,
+ sbox_wc_path(b, "A/mu-moved"));
+ SVN_TEST_ASSERT(status->moved_to_abspath == NULL);
+
+ /* Ensure that the moved+merged file has the expected content. */
+ SVN_ERR(svn_stringbuf_from_file2(&buf, sbox_wc_path(b, "A/mu-also-moved"),
+ b->pool));
+ conflicted_content = apr_psprintf(b->pool,
+ "<<<<<<< .working\n"
+ "%s"
+ "||||||| .old\n"
+ "This is the file 'mu'.\n"
+ "=======\n"
+ "%s"
+ ">>>>>>> .new\n",
+ modified_file_in_working_copy_content,
+ modified_file_content);
+ SVN_TEST_STRING_ASSERT(buf->data, conflicted_content);
+
+ return SVN_NO_ERROR;
+}
+
+/* Same test case as above, but accept the incoming move. */
+static svn_error_t *
+test_update_file_move_vs_file_move_accept_move(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_client_conflict_t *conflict;
+ svn_opt_revision_t opt_rev;
+ struct status_baton sb;
+ struct svn_client_status_t *status;
+ svn_stringbuf_t *buf;
+ char *conflicted_content;
+
+ SVN_ERR(svn_test__sandbox_create(b,
+ "update_file_move_vs_file_move_accept_move",
+ opts, pool));
+
+ SVN_ERR(sbox_add_and_commit_greek_tree(b)); /* r1 */
+
+ SVN_ERR(svn_test__create_client_ctx(&ctx, b, b->pool));
+ SVN_ERR(create_file_move_vs_file_move_update_conflict(&conflict, b, ctx));
+
+ SVN_ERR(svn_client_conflict_tree_resolve_by_id(
+ conflict,
+ svn_client_conflict_option_both_moved_file_move_merge,
+ ctx, b->pool));
+
+ /* The node "A/mu" should no longer exist. */
+ SVN_TEST_ASSERT_ERROR(svn_client_conflict_get(
+ &conflict, sbox_wc_path(b, "A/mu"), ctx, pool, pool),
+ SVN_ERR_WC_PATH_NOT_FOUND);
+
+ /* The node "A/mu-also-moved" should not exist. */
+ SVN_TEST_ASSERT_ERROR(svn_client_conflict_get(
+ &conflict, sbox_wc_path(b, "A/mu-also-moved"), ctx,
+ pool, pool),
+ SVN_ERR_WC_PATH_NOT_FOUND);
+
+ /* Ensure that the merged 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, "A/mu-moved"),
+ &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_conflicted);
+ SVN_TEST_ASSERT(status->text_status == svn_wc_status_conflicted);
+ 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);
+
+ /* Ensure that the moved+merged file has the expected content. */
+ SVN_ERR(svn_stringbuf_from_file2(&buf, sbox_wc_path(b, "A/mu-moved"),
+ b->pool));
+ conflicted_content = apr_psprintf(b->pool,
+ "<<<<<<< .working\n" /* ### labels need fixing */
+ "%s"
+ "||||||| .old\n"
+ "This is the file 'mu'.\n"
+ "=======\n"
+ "%s"
+ ">>>>>>> .new\n",
+ modified_file_content,
+ modified_file_in_working_copy_content);
+ SVN_TEST_STRING_ASSERT(buf->data, conflicted_content);
+
+ return SVN_NO_ERROR;
+}
+
+
/* ========================================================================== */
@@ -6293,6 +7563,30 @@ static struct svn_test_descriptor_t test
"local missing conflict with ambiguous dir moves"),
SVN_TEST_OPTS_PASS(test_file_vs_dir_move_merge_assertion_failure,
"file v dir move merge assertion failure"),
+ SVN_TEST_OPTS_PASS(test_update_file_add_vs_unversiond_file,
+ "file add vs unversioned file during update"),
+ SVN_TEST_OPTS_PASS(test_switch_file_add_vs_unversiond_file,
+ "file add vs unversioned file during switch"),
+ SVN_TEST_OPTS_PASS(test_update_dir_add_vs_unversioned_dir,
+ "dir add vs unversioned dir during update"),
+ SVN_TEST_OPTS_PASS(test_switch_dir_add_vs_unversioned_dir,
+ "dir add vs unversioned dir during switch"),
+ SVN_TEST_OPTS_PASS(test_merge_file_move_vs_file_move,
+ "file move vs file move during merge"),
+ SVN_TEST_OPTS_PASS(test_merge_file_move_vs_file_move_accept_move,
+ "file move vs file move during merge accept move"),
+ SVN_TEST_OPTS_PASS(test_merge_file_edit_move_vs_file_move,
+ "file move vs file edit-move during merge"),
+ SVN_TEST_OPTS_PASS(test_merge_file_edit_move_vs_file_move_accept_move,
+ "file edit-move vs file move merge accept move"),
+ SVN_TEST_OPTS_PASS(test_merge_dir_move_vs_dir_move,
+ "dir move vs dir move during merge"),
+ SVN_TEST_OPTS_PASS(test_merge_dir_move_vs_dir_move_accept_move,
+ "dir move vs dir move during merge accept move"),
+ SVN_TEST_OPTS_PASS(test_update_file_move_vs_file_move,
+ "file move vs file move during update"),
+ SVN_TEST_OPTS_PASS(test_update_file_move_vs_file_move_accept_move,
+ "file move vs file move during update accept move"),
SVN_TEST_NULL
};
Modified: subversion/branches/multi-wc-format/subversion/tests/libsvn_client/mtcc-test.c
URL: http://svn.apache.org/viewvc/subversion/branches/multi-wc-format/subversion/tests/libsvn_client/mtcc-test.c?rev=1897034&r1=1897033&r2=1897034&view=diff
==============================================================================
--- subversion/branches/multi-wc-format/subversion/tests/libsvn_client/mtcc-test.c (original)
+++ subversion/branches/multi-wc-format/subversion/tests/libsvn_client/mtcc-test.c Fri Jan 14 14:01:45 2022
@@ -693,7 +693,7 @@ test_file_revs_both_ways(const svn_test_
subpool));
SVN_TEST_ASSERT(hrb.last == 6);
- /* Ressurect mu */
+ /* Resurrect mu */
svn_pool_clear(subpool);
SVN_ERR(svn_client__mtcc_create(&mtcc, repos_url, 7, ctx, subpool, subpool));
SVN_ERR(svn_client__mtcc_add_copy("mu", 6, "mu", mtcc, subpool));
Modified: subversion/branches/multi-wc-format/subversion/tests/libsvn_diff/diff-diff3-test.c
URL: http://svn.apache.org/viewvc/subversion/branches/multi-wc-format/subversion/tests/libsvn_diff/diff-diff3-test.c?rev=1897034&r1=1897033&r2=1897034&view=diff
==============================================================================
--- subversion/branches/multi-wc-format/subversion/tests/libsvn_diff/diff-diff3-test.c (original)
+++ subversion/branches/multi-wc-format/subversion/tests/libsvn_diff/diff-diff3-test.c Fri Jan 14 14:01:45 2022
@@ -28,6 +28,8 @@
#include "svn_pools.h"
#include "svn_utf.h"
+#include "private/svn_string_private.h"
+
/* Used to terminate lines in large multi-line string literals. */
#define NL APR_EOL_STR
@@ -2071,15 +2073,13 @@ test_three_way_merge_conflict_styles(apr
}
-#define MAKE_STRING(cstr) { (cstr), sizeof((cstr))-1 }
-
static svn_error_t *
test_diff4(apr_pool_t *pool)
{
svn_diff_t *diff;
svn_stream_t *actual, *expected;
svn_boolean_t same;
- static svn_string_t B2 = MAKE_STRING(
+ static svn_string_t B2 = SVN__STATIC_STRING(
"int main (int argc, char **argv)\n"
"{\n"
" /* line minus-five of context */\n"
@@ -2094,7 +2094,7 @@ test_diff4(apr_pool_t *pool)
" /* line plus-four of context */\n"
" /* line plus-five of context */\n"
"}\n");
- static svn_string_t B2new = MAKE_STRING(
+ static svn_string_t B2new = SVN__STATIC_STRING(
"int main (int argc, char **argv)\n"
"{\n"
" /* line minus-five of context */\n"
@@ -2109,7 +2109,7 @@ test_diff4(apr_pool_t *pool)
" /* line plus-four of context */\n"
" /* line plus-five of context */\n"
"}\n");
- static svn_string_t T1 = MAKE_STRING(
+ static svn_string_t T1 = SVN__STATIC_STRING(
"int main (int argc, char **argv)\n"
"{\n"
" /* line minus-five of context */\n"
@@ -2124,7 +2124,7 @@ test_diff4(apr_pool_t *pool)
" /* line plus-four of context */\n"
" /* line plus-five of context */\n"
"}\n");
- static svn_string_t T2 = MAKE_STRING(
+ static svn_string_t T2 = SVN__STATIC_STRING(
"#include <stdio.h>\n"
"\n"
"int main (int argc, char **argv)\n"
@@ -2141,7 +2141,7 @@ test_diff4(apr_pool_t *pool)
" /* line plus-four of context */\n"
" /* line plus-five of context */\n"
"}\n");
- static svn_string_t T3 = MAKE_STRING(
+ static svn_string_t T3 = SVN__STATIC_STRING(
"#include <stdio.h>\n"
"\n"
"int main (int argc, char **argv)\n"
Modified: subversion/branches/multi-wc-format/subversion/tests/libsvn_fs/fs-test.c
URL: http://svn.apache.org/viewvc/subversion/branches/multi-wc-format/subversion/tests/libsvn_fs/fs-test.c?rev=1897034&r1=1897033&r2=1897034&view=diff
==============================================================================
--- subversion/branches/multi-wc-format/subversion/tests/libsvn_fs/fs-test.c (original)
+++ subversion/branches/multi-wc-format/subversion/tests/libsvn_fs/fs-test.c Fri Jan 14 14:01:45 2022
@@ -5479,7 +5479,7 @@ commit_timestamp(const svn_test_opts_t *
APR_HASH_KEY_STRING);
SVN_TEST_ASSERT(!svn_date);
- /* Commit that overwites a missing svn:date. */
+ /* Commit that overwrites a missing svn:date. */
SVN_ERR(svn_fs_begin_txn(&txn, fs, rev, pool));
SVN_ERR(svn_fs_txn_root(&txn_root, txn, pool));
SVN_ERR(svn_fs_make_dir(txn_root, "/zig", pool));
@@ -7219,7 +7219,7 @@ test_cache_clear_during_stream(const svn
* Just to be sure, make it not too uniform to keep self-txdelta at bay. */
SVN_ERR(svn_fs_apply_textdelta(&consumer_func, &consumer_baton,
txn_root, "/foo", NULL, NULL, subpool));
- stream = svn_txdelta_target_push(consumer_func, consumer_baton,
+ stream = svn_txdelta_target_push(consumer_func, consumer_baton,
svn_stream_empty(subpool), subpool);
for (i = 0; i < 10000; ++ i)
{
@@ -7369,6 +7369,106 @@ closest_copy_test_svn_4677(const svn_tes
return SVN_NO_ERROR;
}
+static svn_error_t *
+test_closest_copy_file_replaced_with_dir(const svn_test_opts_t *opts,
+ apr_pool_t *pool)
+{
+ svn_fs_t *fs;
+ svn_fs_txn_t *txn;
+ svn_fs_root_t *txn_root;
+ svn_fs_root_t *rev_root;
+ svn_revnum_t youngest_rev;
+ svn_fs_root_t *copy_root;
+ const char *copy_path;
+
+ /* Prepare a filesystem. */
+ SVN_ERR(svn_test__create_fs(&fs, "test-closest-copy-file-replaced-with-dir",
+ opts, pool));
+
+ youngest_rev = 0;
+
+ /* Modeled after the case described in the thread:
+ "[PATCH] A test for "Can't get entries" error"
+ https://lists.apache.org/thread.html/693a95b0da834387e78a7f08df2392b634397d32f37428c81c02f8c5@%3Cdev.subversion.apache.org%3E
+ */
+ /* r1: Add a directory with a file. */
+ SVN_ERR(svn_fs_begin_txn2(&txn, fs, youngest_rev, 0, pool));
+ SVN_ERR(svn_fs_txn_root(&txn_root, txn, pool));
+ SVN_ERR(svn_fs_make_dir(txn_root, "/A", pool));
+ SVN_ERR(svn_fs_make_file(txn_root, "/A/mu", pool));
+ SVN_ERR(test_commit_txn(&youngest_rev, txn, NULL, pool));
+ SVN_TEST_INT_ASSERT(youngest_rev, 1);
+
+ /* r2: Copy the directory. */
+ SVN_ERR(svn_fs_begin_txn2(&txn, fs, youngest_rev, 0, pool));
+ SVN_ERR(svn_fs_txn_root(&txn_root, txn, pool));
+ SVN_ERR(svn_fs_revision_root(&rev_root, fs, 1, pool));
+ SVN_ERR(svn_fs_copy(rev_root, "/A", txn_root, "/B", pool));
+ SVN_ERR(test_commit_txn(&youngest_rev, txn, NULL, pool));
+ SVN_TEST_INT_ASSERT(youngest_rev, 2);
+
+ /* r3: Delete the file. */
+ SVN_ERR(svn_fs_begin_txn2(&txn, fs, youngest_rev, 0, pool));
+ SVN_ERR(svn_fs_txn_root(&txn_root, txn, pool));
+ SVN_ERR(svn_fs_delete(txn_root, "/B/mu", pool));
+ SVN_ERR(test_commit_txn(&youngest_rev, txn, NULL, pool));
+ SVN_TEST_INT_ASSERT(youngest_rev, 3);
+
+ /* r4: Replace the file with a new directory containing a file. */
+ SVN_ERR(svn_fs_begin_txn2(&txn, fs, youngest_rev, 0, pool));
+ SVN_ERR(svn_fs_txn_root(&txn_root, txn, pool));
+ SVN_ERR(svn_fs_make_dir(txn_root, "/B/mu", pool));
+ SVN_ERR(svn_fs_make_file(txn_root, "/B/mu/iota", pool));
+ SVN_ERR(test_commit_txn(&youngest_rev, txn, NULL, pool));
+ SVN_TEST_INT_ASSERT(youngest_rev, 4);
+
+ /* Test a couple of svn_fs_closest_copy() calls; the second call used
+ to fail with an unexpected SVN_ERR_FS_NOT_DIRECTORY error. */
+
+ SVN_ERR(svn_fs_revision_root(&rev_root, fs, 2, pool));
+ SVN_ERR(svn_fs_closest_copy(©_root, ©_path, rev_root, "/B/mu", pool));
+
+ SVN_TEST_ASSERT(copy_root != NULL);
+ SVN_TEST_INT_ASSERT(svn_fs_revision_root_revision(copy_root), 2);
+ SVN_TEST_STRING_ASSERT(copy_path, "/B");
+
+ SVN_ERR(svn_fs_revision_root(&rev_root, fs, 4, pool));
+ SVN_ERR(svn_fs_closest_copy(©_root, ©_path, rev_root, "/B/mu/iota", pool));
+
+ SVN_TEST_ASSERT(copy_root == NULL);
+ SVN_TEST_ASSERT(copy_path == NULL);
+
+ return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+test_unrecognized_ioctl(const svn_test_opts_t *opts,
+ apr_pool_t *pool)
+{
+ svn_fs_t *fs;
+ svn_error_t *err;
+ svn_fs_ioctl_code_t code = {0};
+
+ SVN_ERR(svn_test__create_fs(&fs, "test-unrecognized-ioctl", opts, pool));
+
+ code.fs_type = "NON-EXISTING";
+ code.code = 98765;
+ err = svn_fs_ioctl(fs, code, NULL, NULL, NULL, NULL, pool, pool);
+ SVN_TEST_ASSERT_ERROR(err, SVN_ERR_FS_UNRECOGNIZED_IOCTL_CODE);
+
+ code.fs_type = "NON-EXISTING";
+ code.code = 98765;
+ err = svn_fs_ioctl(NULL, code, NULL, NULL, NULL, NULL, pool, pool);
+ SVN_TEST_ASSERT_ERROR(err, SVN_ERR_FS_UNKNOWN_FS_TYPE);
+
+ code.fs_type = opts->fs_type;
+ code.code = 98765;
+ err = svn_fs_ioctl(NULL, code, NULL, NULL, NULL, NULL, pool, pool);
+ SVN_TEST_ASSERT_ERROR(err, SVN_ERR_FS_UNRECOGNIZED_IOCTL_CODE);
+
+ return SVN_NO_ERROR;
+}
+
/* ------------------------------------------------------------------------ */
/* The test table. */
@@ -7513,6 +7613,10 @@ static struct svn_test_descriptor_t test
"test rep-sharing on content rather than SHA1"),
SVN_TEST_OPTS_PASS(closest_copy_test_svn_4677,
"test issue SVN-4677 regression"),
+ SVN_TEST_OPTS_PASS(test_closest_copy_file_replaced_with_dir,
+ "svn_fs_closest_copy after replacing file with dir"),
+ SVN_TEST_OPTS_PASS(test_unrecognized_ioctl,
+ "test svn_fs_ioctl with unrecognized code"),
SVN_TEST_NULL
};
Modified: subversion/branches/multi-wc-format/subversion/tests/libsvn_fs/locks-test.c
URL: http://svn.apache.org/viewvc/subversion/branches/multi-wc-format/subversion/tests/libsvn_fs/locks-test.c?rev=1897034&r1=1897033&r2=1897034&view=diff
==============================================================================
--- subversion/branches/multi-wc-format/subversion/tests/libsvn_fs/locks-test.c (original)
+++ subversion/branches/multi-wc-format/subversion/tests/libsvn_fs/locks-test.c Fri Jan 14 14:01:45 2022
@@ -1089,6 +1089,9 @@ lock_cb_error(const svn_test_opts_t *opt
return SVN_NO_ERROR;
}
+/* XXX NOTE:
+ This test will fail on most Unix-like systems when run as the
+ root user, because flock() will ignore file permissions. */
static svn_error_t *
obtain_write_lock_failure(const svn_test_opts_t *opts,
apr_pool_t *pool)
Modified: subversion/branches/multi-wc-format/subversion/tests/libsvn_fs_fs/fs-fs-pack-test.c
URL: http://svn.apache.org/viewvc/subversion/branches/multi-wc-format/subversion/tests/libsvn_fs_fs/fs-fs-pack-test.c?rev=1897034&r1=1897033&r2=1897034&view=diff
==============================================================================
--- subversion/branches/multi-wc-format/subversion/tests/libsvn_fs_fs/fs-fs-pack-test.c (original)
+++ subversion/branches/multi-wc-format/subversion/tests/libsvn_fs_fs/fs-fs-pack-test.c Fri Jan 14 14:01:45 2022
@@ -59,7 +59,8 @@ static const char *
get_rev_contents(svn_revnum_t rev, apr_pool_t *pool)
{
/* Toss in a bunch of magic numbers for spice. */
- apr_int64_t num = ((rev * 1234353 + 4358) * 4583 + ((rev % 4) << 1)) / 42;
+ apr_int64_t rev64 = rev;
+ apr_int64_t num = ((rev64 * 1234353 + 4358) * 4583 + ((rev64 % 4) << 1)) / 42;
return apr_psprintf(pool, "%" APR_INT64_T_FMT "\n", num);
}
@@ -1693,7 +1694,7 @@ compare_0_length_rep(const svn_test_opts
enum { COUNT = 5 };
const char *file_names[COUNT] = { no_rep_file,
- empty_plain_file,
+ empty_plain_file,
plain_file,
empty_delta_file,
delta_file };
Modified: subversion/branches/multi-wc-format/subversion/tests/libsvn_fs_fs/fs-fs-private-test.c
URL: http://svn.apache.org/viewvc/subversion/branches/multi-wc-format/subversion/tests/libsvn_fs_fs/fs-fs-private-test.c?rev=1897034&r1=1897033&r2=1897034&view=diff
==============================================================================
--- subversion/branches/multi-wc-format/subversion/tests/libsvn_fs_fs/fs-fs-private-test.c (original)
+++ subversion/branches/multi-wc-format/subversion/tests/libsvn_fs_fs/fs-fs-private-test.c Fri Jan 14 14:01:45 2022
@@ -35,6 +35,8 @@
#include "private/svn_subr_private.h"
#include "../../libsvn_fs_fs/index.h"
+#include "../../libsvn_fs_fs/rep-cache.h"
+#include "../../libsvn_fs/fs-loader.h"
#include "../svn_test_fs.h"
@@ -199,8 +201,10 @@ get_repo_stats(const svn_test_opts_t *op
svn_repos_t *repos;
svn_revnum_t rev;
apr_size_t i;
- svn_fs_fs__stats_t *stats;
svn_fs_fs__extension_info_t *extension_info;
+ svn_fs_fs__ioctl_get_stats_input_t input = {0};
+ svn_fs_fs__ioctl_get_stats_output_t *output;
+ const svn_fs_fs__stats_t *stats;
/* Bail (with success) on known-untestable scenarios */
if (strcmp(opts->fs_type, "fsfs") != 0)
@@ -211,8 +215,9 @@ get_repo_stats(const svn_test_opts_t *op
SVN_ERR(create_greek_repo(&repos, &rev, opts, REPO_NAME, pool, pool));
/* Gather statistics info on that repo. */
- SVN_ERR(svn_fs_fs__get_stats(&stats, svn_repos_fs(repos), NULL, NULL,
- NULL, NULL, pool, pool));
+ SVN_ERR(svn_fs_ioctl(svn_repos_fs(repos), SVN_FS_FS__IOCTL_GET_STATS,
+ &input, (void**)&output, NULL, NULL, pool, pool));
+ stats = output->stats;
/* Check that the stats make sense. */
SVN_TEST_ASSERT(stats->total_size > 1000 && stats->total_size < 10000);
@@ -324,6 +329,7 @@ dump_index(const svn_test_opts_t *opts,
svn_repos_t *repos;
svn_revnum_t rev;
dump_baton_t baton;
+ svn_fs_fs__ioctl_dump_index_input_t input = {0};
/* Bail (with success) on known-untestable scenarios */
if (strcmp(opts->fs_type, "fsfs") != 0)
@@ -342,8 +348,12 @@ dump_index(const svn_test_opts_t *opts,
baton.offset = 0;
baton.revision = rev;
baton.numbers_seen = svn_bit_array__create(100, pool);
- SVN_ERR(svn_fs_fs__dump_index(svn_repos_fs(repos), rev, dump_index_entry,
- &baton, NULL, NULL, pool));
+
+ input.revision = rev;
+ input.callback_func = dump_index_entry;
+ input.callback_baton = &baton;
+ SVN_ERR(svn_fs_ioctl(svn_repos_fs(repos), SVN_FS_FS__IOCTL_DUMP_INDEX,
+ &input, NULL, NULL, NULL, pool, pool));
/* Check that we've got all data (20 noderevs + 20 reps + 1 changes list). */
SVN_TEST_ASSERT(baton.invocations == 41);
@@ -377,6 +387,8 @@ load_index(const svn_test_opts_t *opts,
apr_array_header_t *entries = apr_array_make(pool, 41, sizeof(void *));
apr_array_header_t *alt_entries = apr_array_make(pool, 1, sizeof(void *));
svn_fs_fs__p2l_entry_t entry;
+ svn_fs_fs__ioctl_dump_index_input_t dump_input = {0};
+ svn_fs_fs__ioctl_load_index_input_t load_input = {0};
/* Bail (with success) on known-untestable scenarios */
if (strcmp(opts->fs_type, "fsfs") != 0)
@@ -391,8 +403,11 @@ load_index(const svn_test_opts_t *opts,
SVN_ERR(create_greek_repo(&repos, &rev, opts, REPO_NAME, pool, pool));
/* Read the original index contents for REV in ENTRIES. */
- SVN_ERR(svn_fs_fs__dump_index(svn_repos_fs(repos), rev, receive_index,
- entries, NULL, NULL, pool));
+ dump_input.revision = rev;
+ dump_input.callback_func = receive_index;
+ dump_input.callback_baton = entries;
+ SVN_ERR(svn_fs_ioctl(svn_repos_fs(repos), SVN_FS_FS__IOCTL_DUMP_INDEX,
+ &dump_input, NULL, NULL, NULL, pool, pool));
/* Replace it with an index that declares the whole revision contents as
* "unused". */
@@ -404,14 +419,21 @@ load_index(const svn_test_opts_t *opts,
entry.item.revision = SVN_INVALID_REVNUM;
APR_ARRAY_PUSH(alt_entries, svn_fs_fs__p2l_entry_t *) = &entry;
- SVN_ERR(svn_fs_fs__load_index(svn_repos_fs(repos), rev, alt_entries, pool));
+ load_input.revision = rev;
+ load_input.entries = alt_entries;
+ SVN_ERR(svn_fs_ioctl(svn_repos_fs(repos), SVN_FS_FS__IOCTL_LOAD_INDEX,
+ &load_input, NULL, NULL, NULL, pool, pool));
+
SVN_TEST_ASSERT_ERROR(svn_repos_verify_fs3(repos, rev, rev, FALSE, FALSE,
NULL, NULL, NULL, NULL, NULL,
NULL, pool),
SVN_ERR_FS_INDEX_CORRUPTION);
/* Restore the original index. */
- SVN_ERR(svn_fs_fs__load_index(svn_repos_fs(repos), rev, entries, pool));
+ load_input.revision = rev;
+ load_input.entries = entries;
+ SVN_ERR(svn_fs_ioctl(svn_repos_fs(repos), SVN_FS_FS__IOCTL_LOAD_INDEX,
+ &load_input, NULL, NULL, NULL, pool, pool));
SVN_ERR(svn_repos_verify_fs3(repos, rev, rev, FALSE, FALSE, NULL, NULL,
NULL, NULL, NULL, NULL, pool));
@@ -420,6 +442,63 @@ load_index(const svn_test_opts_t *opts,
#undef REPO_NAME
+/* ------------------------------------------------------------------------ */
+
+static svn_error_t *
+build_rep_cache(const svn_test_opts_t *opts, apr_pool_t *pool)
+{
+ svn_fs_t *fs;
+ fs_fs_data_t *ffd;
+ svn_fs_txn_t *txn;
+ svn_fs_root_t *txn_root;
+ svn_revnum_t rev;
+ svn_boolean_t exists;
+ const char *fs_path;
+ svn_fs_fs__ioctl_build_rep_cache_input_t input = {0};
+
+ /* Bail (with success) on known-untestable scenarios */
+ if (strcmp(opts->fs_type, "fsfs") != 0)
+ return svn_error_create(SVN_ERR_TEST_SKIPPED, NULL,
+ "this will test FSFS repositories only");
+
+ if (opts->server_minor_version && (opts->server_minor_version < 6))
+ return svn_error_create(SVN_ERR_TEST_SKIPPED, NULL,
+ "pre-1.6 SVN doesn't support FSFS rep-sharing");
+
+ /* Create a filesystem and explicitly disable rep-sharing. */
+ fs_path = "test-repo-build-rep-cache-test";
+ SVN_ERR(svn_test__create_fs2(&fs, fs_path, opts, NULL, pool));
+ ffd = fs->fsap_data;
+ ffd->rep_sharing_allowed = FALSE;
+
+ /* Add the Greek tree. */
+ SVN_ERR(svn_fs_begin_txn(&txn, fs, 0, pool));
+ SVN_ERR(svn_fs_txn_root(&txn_root, txn, pool));
+ SVN_ERR(svn_test__create_greek_tree(txn_root, pool));
+ SVN_ERR(svn_fs_commit_txn(NULL, &rev, txn, pool));
+ SVN_TEST_ASSERT(SVN_IS_VALID_REVNUM(rev));
+
+ /* Make sure the rep-cache does not exist. */
+ SVN_ERR(svn_fs_fs__exists_rep_cache(&exists, fs, pool));
+ SVN_TEST_ASSERT(!exists);
+
+ /* Build and verify the rep-cache. */
+ ffd->rep_sharing_allowed = TRUE;
+
+ input.start_rev = rev;
+ input.end_rev = rev;
+ SVN_ERR(svn_fs_ioctl(fs, SVN_FS_FS__IOCTL_BUILD_REP_CACHE,
+ &input, NULL, NULL, NULL, pool, pool));
+
+ SVN_ERR(svn_fs_fs__exists_rep_cache(&exists, fs, pool));
+ SVN_TEST_ASSERT(exists);
+
+ SVN_ERR(svn_fs_verify(fs_path, NULL, 0, SVN_INVALID_REVNUM,
+ NULL, NULL, NULL, NULL, pool));
+
+ return SVN_NO_ERROR;
+}
+
/* The test table. */
@@ -435,6 +514,8 @@ static struct svn_test_descriptor_t test
"dump the P2L index"),
SVN_TEST_OPTS_PASS(load_index,
"load the P2L index"),
+ SVN_TEST_OPTS_PASS(build_rep_cache,
+ "build the representation cache"),
SVN_TEST_NULL
};
Modified: subversion/branches/multi-wc-format/subversion/tests/libsvn_fs_x/fs-x-pack-test.c
URL: http://svn.apache.org/viewvc/subversion/branches/multi-wc-format/subversion/tests/libsvn_fs_x/fs-x-pack-test.c?rev=1897034&r1=1897033&r2=1897034&view=diff
==============================================================================
--- subversion/branches/multi-wc-format/subversion/tests/libsvn_fs_x/fs-x-pack-test.c (original)
+++ subversion/branches/multi-wc-format/subversion/tests/libsvn_fs_x/fs-x-pack-test.c Fri Jan 14 14:01:45 2022
@@ -680,7 +680,7 @@ recover_fully_packed(const svn_test_opts
/* ------------------------------------------------------------------------ */
/* Regression test for issue #4320 (fsfs file-hinting fails when reading a rep
- from the transaction that is commiting rev = SHARD_SIZE). */
+ from the transaction that is committing rev = SHARD_SIZE). */
#define REPO_NAME "test-repo-file-hint-at-shard-boundary"
#define SHARD_SIZE 4
#define MAX_REV (SHARD_SIZE - 1)
Propchange: subversion/branches/multi-wc-format/subversion/tests/libsvn_ra/
------------------------------------------------------------------------------
--- svn:ignore (original)
+++ svn:ignore Fri Jan 14 14:01:45 2022
@@ -1,4 +1,13 @@
*.lo
.libs
+base_revision_above_youngest
+commit_cb_failure
+commit_empty_last_change
+delete_revision_above_youngest
+errors_from_callbacks
ra-test
+ra_list_has_props
+ra_revision_errors
+test-get-dir
test-repo-*
+test-run_checkout
Modified: subversion/branches/multi-wc-format/subversion/tests/libsvn_ra/ra-test.c
URL: http://svn.apache.org/viewvc/subversion/branches/multi-wc-format/subversion/tests/libsvn_ra/ra-test.c?rev=1897034&r1=1897033&r2=1897034&view=diff
==============================================================================
--- subversion/branches/multi-wc-format/subversion/tests/libsvn_ra/ra-test.c (original)
+++ subversion/branches/multi-wc-format/subversion/tests/libsvn_ra/ra-test.c Fri Jan 14 14:01:45 2022
@@ -62,7 +62,8 @@ make_and_open_repos(svn_ra_session_t **s
pool, pool));
SVN_ERR(svn_ra_initialize(pool));
- SVN_ERR(svn_ra_open4(session, NULL, url, NULL, cbtable, NULL, NULL, pool));
+ SVN_ERR(svn_ra_open5(session, NULL, NULL, url, NULL, cbtable, NULL, NULL,
+ pool));
return SVN_NO_ERROR;
}
@@ -94,6 +95,41 @@ commit_changes(svn_ra_session_t *session
return SVN_NO_ERROR;
}
+/* Commit two revisions: add 'B', then delete 'A' */
+static svn_error_t *
+commit_two_changes(svn_ra_session_t *session,
+ apr_pool_t *pool)
+{
+ apr_hash_t *revprop_table = apr_hash_make(pool);
+ const svn_delta_editor_t *editor;
+ void *edit_baton;
+ void *root_baton, *dir_baton;
+
+ /* mkdir B */
+ SVN_ERR(svn_ra_get_commit_editor3(session, &editor, &edit_baton,
+ revprop_table,
+ NULL, NULL, NULL, TRUE, pool));
+ SVN_ERR(editor->open_root(edit_baton, SVN_INVALID_REVNUM,
+ pool, &root_baton));
+ SVN_ERR(editor->add_directory("B", root_baton, NULL, SVN_INVALID_REVNUM,
+ pool, &dir_baton));
+ SVN_ERR(editor->close_directory(dir_baton, pool));
+ SVN_ERR(editor->close_directory(root_baton, pool));
+ SVN_ERR(editor->close_edit(edit_baton, pool));
+
+ /* delete A */
+ SVN_ERR(svn_ra_get_commit_editor3(session, &editor, &edit_baton,
+ revprop_table,
+ NULL, NULL, NULL, TRUE, pool));
+ SVN_ERR(editor->open_root(edit_baton, SVN_INVALID_REVNUM,
+ pool, &root_baton));
+ SVN_ERR(editor->delete_entry("A", SVN_INVALID_REVNUM, root_baton, pool));
+ SVN_ERR(editor->close_directory(root_baton, pool));
+ SVN_ERR(editor->close_edit(edit_baton, pool));
+
+ return SVN_NO_ERROR;
+}
+
static svn_error_t *
commit_tree(svn_ra_session_t *session,
apr_pool_t *pool)
@@ -352,7 +388,7 @@ check_tunnel_callback_test(const svn_tes
NULL, NULL, NULL, pool));
b->last_check = TRUE;
- SVN_TEST_ASSERT_ERROR(svn_ra_open4(&session, NULL,
+ SVN_TEST_ASSERT_ERROR(svn_ra_open5(&session, NULL, NULL,
"svn+foo://localhost/no-repo",
NULL, cbtable, NULL, NULL, pool),
SVN_ERR_RA_CANNOT_CREATE_SESSION);
@@ -395,7 +431,7 @@ tunnel_callback_test(const svn_test_opts
NULL, NULL, NULL, pool));
b->last_check = FALSE;
- SVN_ERR(svn_ra_open4(&session, NULL, url, NULL, cbtable, NULL, NULL,
+ SVN_ERR(svn_ra_open5(&session, NULL, NULL, url, NULL, cbtable, NULL, NULL,
scratch_pool));
SVN_TEST_ASSERT(b->last_check);
SVN_TEST_ASSERT(b->open_count > 0);
@@ -1556,7 +1592,7 @@ tunnel_run_checkout(const svn_test_opts_
b->last_check = FALSE;
- SVN_ERR(svn_ra_open4(&session, NULL, url, NULL, cbtable, NULL, NULL,
+ SVN_ERR(svn_ra_open5(&session, NULL, NULL, url, NULL, cbtable, NULL, NULL,
scratch_pool));
SVN_ERR(commit_changes(session, pool));
@@ -1626,16 +1662,16 @@ commit_empty_last_change(const svn_test_
SVN_ERR(svn_ra_get_commit_editor3(session, &editor, &edit_baton,
revprop_table,
NULL, NULL, NULL, TRUE, tmp_pool));
-
+
SVN_ERR(editor->open_root(edit_baton, 1, tmp_pool, &root_baton));
SVN_ERR(editor->close_directory(root_baton, tmp_pool));
SVN_ERR(editor->close_edit(edit_baton, tmp_pool));
-
+
SVN_ERR(svn_ra_stat(session, "", 2+i, &dirent, tmp_pool));
-
+
SVN_TEST_ASSERT(dirent != NULL);
SVN_TEST_STRING_ASSERT(dirent->last_author, "jrandom");
-
+
/* BDB used to only updates last_changed on the repos_root when there
was an actual change. Now all filesystems behave in the same way */
SVN_TEST_INT_ASSERT(dirent->created_rev, 2+i);
@@ -1698,7 +1734,7 @@ commit_locked_file(const svn_test_opts_t
SVN_ERR(svn_ra_create_callbacks(&cbtable, pool));
SVN_ERR(svn_test__init_auth_baton(&cbtable->auth_baton, pool));
- SVN_ERR(svn_ra_open4(&session, NULL, url, NULL, cbtable,
+ SVN_ERR(svn_ra_open5(&session, NULL, NULL, url, NULL, cbtable,
NULL, NULL, pool));
SVN_ERR(svn_ra_get_commit_editor3(session, &editor, &edit_baton,
apr_hash_make(pool),
@@ -1731,7 +1767,7 @@ commit_locked_file(const svn_test_opts_t
}
/* Open a new session using the file parent's URL. */
- SVN_ERR(svn_ra_open4(&session, NULL, url, NULL, cbtable,
+ SVN_ERR(svn_ra_open5(&session, NULL, NULL, url, NULL, cbtable,
NULL, NULL, pool));
/* Create a new commit editor supplying our lock token. */
@@ -1784,6 +1820,63 @@ commit_locked_file(const svn_test_opts_t
return SVN_NO_ERROR;
}
+/* Cases of 'get-deleted-rev' that should return SVN_INVALID_REVNUM. */
+static svn_error_t *
+test_get_deleted_rev_no_delete(const svn_test_opts_t *opts,
+ apr_pool_t *pool)
+{
+ svn_ra_session_t *ra_session;
+ svn_revnum_t revision_deleted;
+
+ SVN_ERR(make_and_open_repos(&ra_session,
+ "test-repo-get-deleted-rev-no-delete", opts,
+ pool));
+ SVN_ERR(commit_changes(ra_session, pool));
+ SVN_ERR(commit_two_changes(ra_session, pool));
+
+ /* expect 'no deletion' in the range up to r2, when it is deleted in r3 */
+ /* This was failing over RA-SVN where the 'get-deleted-rev' wire command's
+ prototype cannot directly represent that result. A new enough client and
+ server collaborate on a work-around implemented using an error code. */
+ SVN_ERR(svn_ra_get_deleted_rev(ra_session, "A", 1, 2,
+ &revision_deleted, pool));
+ SVN_TEST_INT_ASSERT(revision_deleted, SVN_INVALID_REVNUM);
+
+ /* this connection should still be open: a simple case should still work */
+ SVN_ERR(svn_ra_get_deleted_rev(ra_session, "A", 1, 3,
+ &revision_deleted, pool));
+ SVN_TEST_INT_ASSERT(revision_deleted, 3);
+
+ return SVN_NO_ERROR;
+}
+
+/* Cases of 'get-deleted-rev' that should return an error. */
+static svn_error_t *
+test_get_deleted_rev_errors(const svn_test_opts_t *opts,
+ apr_pool_t *pool)
+{
+ svn_ra_session_t *ra_session;
+ svn_revnum_t revision_deleted;
+ svn_error_t *err;
+
+ SVN_ERR(make_and_open_repos(&ra_session,
+ "test-repo-get-deleted-rev-errors", opts, pool));
+ SVN_ERR(commit_changes(ra_session, pool));
+
+ /* expect an error when searching up to r3, when repository head is r1 */
+ err = svn_ra_get_deleted_rev(ra_session, "A", 1, 3, &revision_deleted, pool);
+
+ /* mod_dav_svn returns a generic error code for "500 Internal Server Error";
+ * the other RA layers return the specific error code for "no such revision".
+ * We should make these consistent, but for now that's how it is. */
+ if (opts->repos_url && strncmp(opts->repos_url, "http", 4) == 0)
+ SVN_TEST_ASSERT_ERROR(err, SVN_ERR_RA_DAV_REQUEST_FAILED);
+ else
+ SVN_TEST_ASSERT_ERROR(err, SVN_ERR_FS_NO_SUCH_REVISION);
+
+ return SVN_NO_ERROR;
+}
+
/* The test table. */
@@ -1820,6 +1913,10 @@ static struct svn_test_descriptor_t test
"check how last change applies to empty commit"),
SVN_TEST_OPTS_PASS(commit_locked_file,
"check commit editor for a locked file"),
+ SVN_TEST_OPTS_PASS(test_get_deleted_rev_no_delete,
+ "test get-deleted-rev no delete"),
+ SVN_TEST_OPTS_PASS(test_get_deleted_rev_errors,
+ "test get-deleted-rev errors"),
SVN_TEST_NULL
};