summaryrefslogtreecommitdiff
path: root/subversion/tests/libsvn_wc
diff options
context:
space:
mode:
authorLorry Tar Creator <lorry-tar-importer@baserock.org>2015-03-18 13:33:26 +0000
committer <>2015-07-08 14:41:01 +0000
commitbb0ef45f7c46b0ae221b26265ef98a768c33f820 (patch)
tree98bae10dde41c746c51ae97ec4f879e330415aa7 /subversion/tests/libsvn_wc
parent239dfafe71711b2f4c43d7b90a1228d7bdc5195e (diff)
downloadsubversion-tarball-subversion-1.8.13.tar.gz
Imported from /home/lorry/working-area/delta_subversion-tarball/subversion-1.8.13.tar.gz.subversion-1.8.13
Diffstat (limited to 'subversion/tests/libsvn_wc')
-rw-r--r--subversion/tests/libsvn_wc/conflict-data-test.c831
-rwxr-xr-xsubversion/tests/libsvn_wc/create_wc_for_upgrade.sh8
-rw-r--r--subversion/tests/libsvn_wc/db-test.c363
-rw-r--r--subversion/tests/libsvn_wc/entries-compat.c148
-rw-r--r--subversion/tests/libsvn_wc/op-depth-test.c6654
-rw-r--r--subversion/tests/libsvn_wc/pristine-store-test.c7
-rw-r--r--subversion/tests/libsvn_wc/tree-conflict-data-test.c307
-rw-r--r--subversion/tests/libsvn_wc/utils.c385
-rw-r--r--subversion/tests/libsvn_wc/utils.h101
-rw-r--r--subversion/tests/libsvn_wc/wc-incomplete-tester.c2
-rw-r--r--subversion/tests/libsvn_wc/wc-queries-test.c897
-rw-r--r--subversion/tests/libsvn_wc/wc-test.c323
12 files changed, 8955 insertions, 1071 deletions
diff --git a/subversion/tests/libsvn_wc/conflict-data-test.c b/subversion/tests/libsvn_wc/conflict-data-test.c
new file mode 100644
index 0000000..97d22ea
--- /dev/null
+++ b/subversion/tests/libsvn_wc/conflict-data-test.c
@@ -0,0 +1,831 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+/*
+ * conflict-data-test.c -- test the storage of tree conflict data
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <apr_hash.h>
+#include <apr_tables.h>
+
+#include "svn_props.h"
+#include "svn_pools.h"
+#include "svn_hash.h"
+#include "svn_types.h"
+#include "svn_wc.h"
+#include "private/svn_wc_private.h"
+#include "utils.h"
+#include "../svn_test.h"
+#include "../../libsvn_wc/tree_conflicts.h"
+#include "../../libsvn_wc/wc.h"
+#include "../../libsvn_wc/wc_db.h"
+#include "../../libsvn_wc/conflicts.h"
+
+/* A quick way to create error messages. */
+static svn_error_t *
+fail(apr_pool_t *pool, const char *fmt, ...)
+{
+ va_list ap;
+ char *msg;
+
+ va_start(ap, fmt);
+ msg = apr_pvsprintf(pool, fmt, ap);
+ va_end(ap);
+
+ return svn_error_create(SVN_ERR_TEST_FAILED, 0, msg);
+}
+
+/* Assert that two integers are equal. Return an error if not. */
+#define ASSERT_INT_EQ(a, b) \
+ do { \
+ if ((a) != (b)) \
+ return svn_error_createf(SVN_ERR_TEST_FAILED, NULL, \
+ "failed: ASSERT_INT_EQ(" #a ", " #b ") " \
+ "-> (%d == %d)", a, b); \
+ } while (0)
+
+/* Assert that two strings are equal or both null. Return an error if not. */
+#define ASSERT_STR_EQ(a, b) \
+ SVN_TEST_STRING_ASSERT(a, b)
+
+/* Assert that two version_t's are equal or both null. Return an error if not. */
+static svn_error_t *
+compare_version(const svn_wc_conflict_version_t *actual,
+ const svn_wc_conflict_version_t *expected)
+{
+ if (actual == NULL && expected == NULL)
+ return SVN_NO_ERROR;
+
+ SVN_TEST_ASSERT(actual && expected);
+ ASSERT_STR_EQ(actual->repos_url, expected->repos_url);
+ ASSERT_INT_EQ((int)actual->peg_rev, (int)expected->peg_rev);
+ ASSERT_STR_EQ(actual->path_in_repos, expected->path_in_repos);
+ ASSERT_INT_EQ(actual->node_kind, expected->node_kind);
+ return SVN_NO_ERROR;
+}
+
+/* Assert that two conflict descriptions contain exactly the same data
+ * (including names of temporary files), or are both NULL. Return an
+ * error if not. */
+static svn_error_t *
+compare_conflict(const svn_wc_conflict_description2_t *actual,
+ const svn_wc_conflict_description2_t *expected)
+{
+ if (actual == NULL && expected == NULL)
+ return SVN_NO_ERROR;
+
+ SVN_TEST_ASSERT(actual && expected);
+
+ ASSERT_INT_EQ(actual->kind, expected->kind);
+ ASSERT_STR_EQ(actual->local_abspath, expected->local_abspath);
+ ASSERT_INT_EQ(actual->node_kind, expected->node_kind);
+ ASSERT_STR_EQ(actual->property_name, expected->property_name);
+ ASSERT_INT_EQ(actual->is_binary, expected->is_binary);
+ ASSERT_STR_EQ(actual->mime_type, expected->mime_type);
+ ASSERT_INT_EQ(actual->action, expected->action);
+ ASSERT_INT_EQ(actual->reason, expected->reason);
+ ASSERT_STR_EQ(actual->base_abspath, expected->base_abspath);
+ ASSERT_STR_EQ(actual->their_abspath, expected->their_abspath);
+ ASSERT_STR_EQ(actual->my_abspath, expected->my_abspath);
+ ASSERT_STR_EQ(actual->merged_file, expected->merged_file);
+ ASSERT_INT_EQ(actual->operation, expected->operation);
+ SVN_ERR(compare_version(actual->src_left_version,
+ expected->src_left_version));
+ SVN_ERR(compare_version(actual->src_right_version,
+ expected->src_right_version));
+ return SVN_NO_ERROR;
+}
+
+/* Assert that a file contains the expected data. Return an
+ * error if not. */
+static svn_error_t *
+compare_file_content(const char *file_abspath,
+ const char *expected_val,
+ apr_pool_t *scratch_pool)
+{
+ svn_stringbuf_t *actual_val;
+
+ SVN_ERR(svn_stringbuf_from_file2(&actual_val, file_abspath, scratch_pool));
+ ASSERT_STR_EQ(actual_val->data, expected_val);
+ return SVN_NO_ERROR;
+}
+
+/* Assert that ACTUAL and EXPECTED both represent the same property
+ * conflict, or are both NULL. Return an error if not.
+ *
+ * Compare the property values found in files named by
+ * ACTUAL->base_abspath, ACTUAL->my_abspath, ACTUAL->merged_abspath
+ * with EXPECTED_BASE_VAL, EXPECTED_MY_VAL, EXPECTED_THEIR_VAL
+ * respectively, ignoring the corresponding fields in EXPECTED. */
+static svn_error_t *
+compare_prop_conflict(const svn_wc_conflict_description2_t *actual,
+ const svn_wc_conflict_description2_t *expected,
+ const char *expected_base_val,
+ const char *expected_my_val,
+ const char *expected_their_val,
+ apr_pool_t *scratch_pool)
+{
+ if (actual == NULL && expected == NULL)
+ return SVN_NO_ERROR;
+
+ SVN_TEST_ASSERT(actual && expected);
+ ASSERT_INT_EQ(actual->kind, svn_wc_conflict_kind_property);
+ ASSERT_INT_EQ(expected->kind, svn_wc_conflict_kind_property);
+
+ ASSERT_STR_EQ(actual->local_abspath, expected->local_abspath);
+ ASSERT_INT_EQ(actual->node_kind, expected->node_kind);
+ ASSERT_STR_EQ(actual->property_name, expected->property_name);
+ ASSERT_INT_EQ(actual->action, expected->action);
+ ASSERT_INT_EQ(actual->reason, expected->reason);
+ ASSERT_INT_EQ(actual->operation, expected->operation);
+ SVN_ERR(compare_version(actual->src_left_version,
+ expected->src_left_version));
+ SVN_ERR(compare_version(actual->src_right_version,
+ expected->src_right_version));
+
+ SVN_ERR(compare_file_content(actual->base_abspath, expected_base_val,
+ scratch_pool));
+ SVN_ERR(compare_file_content(actual->my_abspath, expected_my_val,
+ scratch_pool));
+ /* Historical wart: for a prop conflict, 'theirs' is in the 'merged_file'
+ * field, and the conflict artifact file is in the 'theirs_abspath' field. */
+ SVN_ERR(compare_file_content(actual->merged_file, expected_their_val,
+ scratch_pool));
+ /*ASSERT_STR_EQ(actual->theirs_abspath, conflict_artifact_file));*/
+
+ /* These are 'undefined' for a prop conflict */
+ /*ASSERT_INT_EQ(actual->is_binary, expected->is_binary);*/
+ /*ASSERT_STR_EQ(actual->mime_type, expected->mime_type);*/
+
+ return SVN_NO_ERROR;
+}
+
+/* Create and return a tree conflict description */
+static svn_wc_conflict_description2_t *
+tree_conflict_create(const char *local_abspath,
+ svn_node_kind_t node_kind,
+ svn_wc_operation_t operation,
+ svn_wc_conflict_action_t action,
+ svn_wc_conflict_reason_t reason,
+ const char *left_repo,
+ const char *left_path,
+ svn_revnum_t left_revnum,
+ svn_node_kind_t left_kind,
+ const char *right_repo,
+ const char *right_path,
+ svn_revnum_t right_revnum,
+ svn_node_kind_t right_kind,
+ apr_pool_t *result_pool)
+{
+ svn_wc_conflict_version_t *left, *right;
+ svn_wc_conflict_description2_t *conflict;
+
+ left = svn_wc_conflict_version_create2(left_repo, NULL, left_path,
+ left_revnum, left_kind, result_pool);
+ right = svn_wc_conflict_version_create2(right_repo, NULL, right_path,
+ right_revnum, right_kind,
+ result_pool);
+ conflict = svn_wc_conflict_description_create_tree2(
+ local_abspath, node_kind, operation,
+ left, right, result_pool);
+ conflict->action = action;
+ conflict->reason = reason;
+ return conflict;
+}
+
+static svn_error_t *
+test_deserialize_tree_conflict(apr_pool_t *pool)
+{
+ const svn_wc_conflict_description2_t *conflict;
+ svn_wc_conflict_description2_t *exp_conflict;
+ const char *tree_conflict_data;
+ const char *local_abspath;
+ const svn_skel_t *skel;
+
+ tree_conflict_data = "(conflict Foo.c file update deleted edited "
+ "(version 0 2 -1 0 0 ) (version 0 2 -1 0 0 ))";
+
+ SVN_ERR(svn_dirent_get_absolute(&local_abspath, "Foo.c", pool));
+ exp_conflict = svn_wc_conflict_description_create_tree2(
+ local_abspath, svn_node_file, svn_wc_operation_update,
+ NULL, NULL, pool);
+ exp_conflict->action = svn_wc_conflict_action_delete;
+ exp_conflict->reason = svn_wc_conflict_reason_edited;
+
+ skel = svn_skel__parse(tree_conflict_data, strlen(tree_conflict_data), pool);
+ SVN_ERR(svn_wc__deserialize_conflict(&conflict, skel, "", pool, pool));
+
+ if ((conflict->node_kind != exp_conflict->node_kind) ||
+ (conflict->action != exp_conflict->action) ||
+ (conflict->reason != exp_conflict->reason) ||
+ (conflict->operation != exp_conflict->operation) ||
+ (strcmp(conflict->local_abspath, exp_conflict->local_abspath) != 0))
+ return fail(pool, "Unexpected tree conflict");
+
+ return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+test_serialize_tree_conflict_data(apr_pool_t *pool)
+{
+ svn_wc_conflict_description2_t *conflict;
+ const char *tree_conflict_data;
+ const char *expected;
+ const char *local_abspath;
+ svn_skel_t *skel;
+
+ SVN_ERR(svn_dirent_get_absolute(&local_abspath, "Foo.c", pool));
+
+ conflict = svn_wc_conflict_description_create_tree2(
+ local_abspath, svn_node_file, svn_wc_operation_update,
+ NULL, NULL, pool);
+ conflict->action = svn_wc_conflict_action_delete;
+ conflict->reason = svn_wc_conflict_reason_edited;
+
+ SVN_ERR(svn_wc__serialize_conflict(&skel, conflict, pool, pool));
+ tree_conflict_data = svn_skel__unparse(skel, pool)->data;
+
+ expected = "(conflict Foo.c file update deleted edited "
+ "(version 0 2 -1 0 0 ) (version 0 2 -1 0 0 ))";
+
+ if (strcmp(expected, tree_conflict_data) != 0)
+ return fail(pool, "Unexpected text from tree conflict\n"
+ " Expected: %s\n"
+ " Actual: %s\n", expected, tree_conflict_data);
+
+ return SVN_NO_ERROR;
+}
+
+/* Test WC-DB-level conflict APIs. Especially tree conflicts. */
+static svn_error_t *
+test_read_write_tree_conflicts(const svn_test_opts_t *opts,
+ apr_pool_t *pool)
+{
+ svn_test__sandbox_t sbox;
+
+ const char *parent_abspath;
+ const char *child1_abspath, *child2_abspath;
+ svn_wc_conflict_description2_t *conflict1, *conflict2;
+
+ SVN_ERR(svn_test__sandbox_create(&sbox, "read_write_tree_conflicts", opts, pool));
+ parent_abspath = svn_dirent_join(sbox.wc_abspath, "A", pool);
+ SVN_ERR(svn_wc__db_op_add_directory(sbox.wc_ctx->db, parent_abspath,
+ NULL /*props*/, NULL, pool));
+ child1_abspath = svn_dirent_join(parent_abspath, "foo", pool);
+ child2_abspath = svn_dirent_join(parent_abspath, "bar", pool);
+
+ conflict1 = tree_conflict_create(child1_abspath, svn_node_file,
+ svn_wc_operation_merge,
+ svn_wc_conflict_action_delete,
+ svn_wc_conflict_reason_edited,
+ "dummy://localhost", "path/to/foo",
+ 51, svn_node_file,
+ "dummy://localhost", "path/to/foo",
+ 52, svn_node_none,
+ pool);
+
+ conflict2 = tree_conflict_create(child2_abspath, svn_node_dir,
+ svn_wc_operation_merge,
+ svn_wc_conflict_action_replace,
+ svn_wc_conflict_reason_edited,
+ "dummy://localhost", "path/to/bar",
+ 51, svn_node_dir,
+ "dummy://localhost", "path/to/bar",
+ 52, svn_node_file,
+ pool);
+
+ /* Write */
+ SVN_ERR(svn_wc__add_tree_conflict(sbox.wc_ctx, /*child1_abspath,*/
+ conflict1, pool));
+ SVN_ERR(svn_wc__add_tree_conflict(sbox.wc_ctx, /*child2_abspath,*/
+ conflict2, pool));
+
+ /* Query (conflict1 through WC-DB API, conflict2 through WC API) */
+ {
+ svn_boolean_t text_c, prop_c, tree_c;
+
+ SVN_ERR(svn_wc__internal_conflicted_p(&text_c, &prop_c, &tree_c,
+ sbox.wc_ctx->db, child1_abspath, pool));
+ SVN_TEST_ASSERT(tree_c);
+ SVN_TEST_ASSERT(! text_c && ! prop_c);
+
+ SVN_ERR(svn_wc_conflicted_p3(&text_c, &prop_c, &tree_c,
+ sbox.wc_ctx, child2_abspath, pool));
+ SVN_TEST_ASSERT(tree_c);
+ SVN_TEST_ASSERT(! text_c && ! prop_c);
+ }
+
+ /* Read conflicts back */
+ {
+ const svn_wc_conflict_description2_t *read_conflict;
+
+ SVN_ERR(svn_wc__get_tree_conflict(&read_conflict, sbox.wc_ctx,
+ child1_abspath, pool, pool));
+ SVN_ERR(compare_conflict(read_conflict, conflict1));
+
+ SVN_ERR(svn_wc__get_tree_conflict(&read_conflict, sbox.wc_ctx,
+ child2_abspath, pool, pool));
+ SVN_ERR(compare_conflict(read_conflict, conflict2));
+ }
+
+ /* Read many */
+ {
+ const apr_array_header_t *victims;
+
+ SVN_ERR(svn_wc__db_read_conflict_victims(&victims,
+ sbox.wc_ctx->db, parent_abspath,
+ pool, pool));
+ SVN_TEST_ASSERT(victims->nelts == 2);
+ }
+
+ /* ### TODO: to test...
+ * svn_wc__db_read_conflicts
+ * svn_wc__node_get_conflict_info
+ * svn_wc__del_tree_conflict
+ */
+
+ return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+test_serialize_prop_conflict(const svn_test_opts_t *opts,
+ apr_pool_t *pool)
+{
+ svn_test__sandbox_t sbox;
+ svn_skel_t *conflict_skel;
+ svn_boolean_t complete;
+
+ SVN_ERR(svn_test__sandbox_create(&sbox, "test_serialize_prop_conflict", opts, pool));
+
+ conflict_skel = svn_wc__conflict_skel_create(pool);
+
+ SVN_TEST_ASSERT(conflict_skel != NULL);
+ SVN_TEST_ASSERT(svn_skel__list_length(conflict_skel) == 2);
+
+ SVN_ERR(svn_wc__conflict_skel_is_complete(&complete, conflict_skel));
+ SVN_TEST_ASSERT(!complete); /* Nothing set */
+
+ {
+ apr_hash_t *mine = apr_hash_make(pool);
+ apr_hash_t *their_old = apr_hash_make(pool);
+ apr_hash_t *theirs = apr_hash_make(pool);
+ apr_hash_t *conflicts = apr_hash_make(pool);
+ const char *marker_abspath;
+
+ apr_hash_set(mine, "prop", APR_HASH_KEY_STRING,
+ svn_string_create("Mine", pool));
+
+ apr_hash_set(their_old, "prop", APR_HASH_KEY_STRING,
+ svn_string_create("Their-Old", pool));
+
+ apr_hash_set(theirs, "prop", APR_HASH_KEY_STRING,
+ svn_string_create("Theirs", pool));
+
+ apr_hash_set(conflicts, "prop", APR_HASH_KEY_STRING, "");
+
+ SVN_ERR(svn_io_open_unique_file3(NULL, &marker_abspath, sbox.wc_abspath,
+ svn_io_file_del_on_pool_cleanup, pool,
+ pool));
+
+ SVN_ERR(svn_wc__conflict_skel_add_prop_conflict(conflict_skel,
+ sbox.wc_ctx->db,
+ sbox.wc_abspath,
+ marker_abspath,
+ mine, their_old,
+ theirs, conflicts,
+ pool, pool));
+ }
+
+ SVN_ERR(svn_wc__conflict_skel_is_complete(&complete, conflict_skel));
+ SVN_TEST_ASSERT(!complete); /* Misses operation */
+
+ SVN_ERR(svn_wc__conflict_skel_set_op_update(
+ conflict_skel,
+ svn_wc_conflict_version_create2("http://my-repos/svn",
+ "uuid", "trunk", 12,
+ svn_node_dir, pool),
+ NULL /* wc_only */,
+ pool, pool));
+
+ SVN_ERR(svn_wc__conflict_skel_is_complete(&complete, conflict_skel));
+ SVN_TEST_ASSERT(complete); /* Everything available */
+
+ {
+ apr_hash_t *mine;
+ apr_hash_t *their_old;
+ apr_hash_t *theirs;
+ apr_hash_t *conflicts;
+ const char *marker_abspath;
+ svn_string_t *v;
+
+ SVN_ERR(svn_wc__conflict_read_prop_conflict(&marker_abspath,
+ &mine,
+ &their_old,
+ &theirs,
+ &conflicts,
+ sbox.wc_ctx->db,
+ sbox.wc_abspath,
+ conflict_skel,
+ pool, pool));
+
+ SVN_TEST_ASSERT(svn_dirent_is_ancestor(sbox.wc_abspath, marker_abspath));
+
+ v = apr_hash_get(mine, "prop", APR_HASH_KEY_STRING);
+ SVN_TEST_STRING_ASSERT(v->data, "Mine");
+
+ v = apr_hash_get(their_old, "prop", APR_HASH_KEY_STRING);
+ SVN_TEST_STRING_ASSERT(v->data, "Their-Old");
+
+ v = apr_hash_get(theirs, "prop", APR_HASH_KEY_STRING);
+ SVN_TEST_STRING_ASSERT(v->data, "Theirs");
+
+ SVN_TEST_ASSERT(apr_hash_count(conflicts) == 1);
+ }
+
+ return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+test_serialize_text_conflict(const svn_test_opts_t *opts,
+ apr_pool_t *pool)
+{
+ svn_test__sandbox_t sbox;
+ svn_skel_t *conflict_skel;
+ svn_boolean_t complete;
+
+ SVN_ERR(svn_test__sandbox_create(&sbox, "test_serialize_text_conflict", opts, pool));
+
+ conflict_skel = svn_wc__conflict_skel_create(pool);
+
+ SVN_ERR(svn_wc__conflict_skel_add_text_conflict(
+ conflict_skel,
+ sbox.wc_ctx->db, sbox.wc_abspath,
+ svn_dirent_join(sbox.wc_abspath, "mine", pool),
+ svn_dirent_join(sbox.wc_abspath, "old-theirs", pool),
+ svn_dirent_join(sbox.wc_abspath, "theirs", pool),
+ pool, pool));
+
+ SVN_ERR(svn_wc__conflict_skel_set_op_merge(
+ conflict_skel,
+ svn_wc_conflict_version_create2("http://my-repos/svn",
+ "uuid", "trunk", 12,
+ svn_node_dir, pool),
+ svn_wc_conflict_version_create2("http://my-repos/svn",
+ "uuid", "branch/my", 8,
+ svn_node_dir, pool),
+ pool, pool));
+
+ SVN_ERR(svn_wc__conflict_skel_is_complete(&complete, conflict_skel));
+ SVN_TEST_ASSERT(complete); /* Everything available */
+
+ {
+ const char *mine_abspath;
+ const char *old_their_abspath;
+ const char *their_abspath;
+
+ SVN_ERR(svn_wc__conflict_read_text_conflict(&mine_abspath,
+ &old_their_abspath,
+ &their_abspath,
+ sbox.wc_ctx->db,
+ sbox.wc_abspath,
+ conflict_skel,
+ pool, pool));
+
+ SVN_TEST_STRING_ASSERT(
+ svn_dirent_skip_ancestor(sbox.wc_abspath, mine_abspath),
+ "mine");
+
+ SVN_TEST_STRING_ASSERT(
+ svn_dirent_skip_ancestor(sbox.wc_abspath, old_their_abspath),
+ "old-theirs");
+
+ SVN_TEST_STRING_ASSERT(
+ svn_dirent_skip_ancestor(sbox.wc_abspath, their_abspath),
+ "theirs");
+ }
+
+ {
+ svn_wc_operation_t operation;
+ svn_boolean_t text_conflicted;
+ const apr_array_header_t *locs;
+ SVN_ERR(svn_wc__conflict_read_info(&operation, &locs,
+ &text_conflicted, NULL, NULL,
+ sbox.wc_ctx->db, sbox.wc_abspath,
+ conflict_skel, pool, pool));
+
+ SVN_TEST_ASSERT(text_conflicted);
+ SVN_TEST_ASSERT(operation == svn_wc_operation_merge);
+
+ SVN_TEST_ASSERT(locs != NULL && locs->nelts == 2);
+ SVN_TEST_ASSERT(APR_ARRAY_IDX(locs, 0, svn_wc_conflict_version_t*) != NULL);
+ SVN_TEST_ASSERT(APR_ARRAY_IDX(locs, 1, svn_wc_conflict_version_t*) != NULL);
+ }
+
+ {
+ const apr_array_header_t *markers;
+ const char *old_their_abspath;
+ const char *their_abspath;
+ const char *mine_abspath;
+
+ SVN_ERR(svn_wc__conflict_read_markers(&markers,
+ sbox.wc_ctx->db, sbox.wc_abspath,
+ conflict_skel, pool, pool));
+
+ SVN_TEST_ASSERT(markers != NULL);
+ SVN_TEST_ASSERT(markers->nelts == 3);
+
+ old_their_abspath = APR_ARRAY_IDX(markers, 0, const char *);
+ mine_abspath = APR_ARRAY_IDX(markers, 1, const char *);
+ their_abspath = APR_ARRAY_IDX(markers, 2, const char *);
+
+ SVN_TEST_STRING_ASSERT(
+ svn_dirent_skip_ancestor(sbox.wc_abspath, mine_abspath),
+ "mine");
+
+ SVN_TEST_STRING_ASSERT(
+ svn_dirent_skip_ancestor(sbox.wc_abspath, old_their_abspath),
+ "old-theirs");
+
+ SVN_TEST_STRING_ASSERT(
+ svn_dirent_skip_ancestor(sbox.wc_abspath, their_abspath),
+ "theirs");
+ }
+
+ return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+test_serialize_tree_conflict(const svn_test_opts_t *opts,
+ apr_pool_t *pool)
+{
+ svn_test__sandbox_t sbox;
+ svn_skel_t *conflict_skel;
+ svn_boolean_t complete;
+
+ SVN_ERR(svn_test__sandbox_create(&sbox, "test_serialize_tree_conflict", opts, pool));
+
+ conflict_skel = svn_wc__conflict_skel_create(pool);
+
+ SVN_ERR(svn_wc__conflict_skel_add_tree_conflict(
+ conflict_skel,
+ sbox.wc_ctx->db, sbox_wc_path(&sbox, "A/B"),
+ svn_wc_conflict_reason_moved_away,
+ svn_wc_conflict_action_delete,
+ sbox_wc_path(&sbox, "A/B"),
+ pool, pool));
+
+ SVN_ERR(svn_wc__conflict_skel_set_op_switch(
+ conflict_skel,
+ svn_wc_conflict_version_create2("http://my-repos/svn",
+ "uuid", "trunk", 12,
+ svn_node_dir, pool),
+ NULL /* wc_only */,
+ pool, pool));
+
+ SVN_ERR(svn_wc__conflict_skel_is_complete(&complete, conflict_skel));
+ SVN_TEST_ASSERT(complete); /* Everything available */
+
+ {
+ svn_wc_conflict_reason_t local_change;
+ svn_wc_conflict_action_t incoming_change;
+ const char *moved_away_op_root_abspath;
+
+ SVN_ERR(svn_wc__conflict_read_tree_conflict(&local_change,
+ &incoming_change,
+ &moved_away_op_root_abspath,
+ sbox.wc_ctx->db,
+ sbox.wc_abspath,
+ conflict_skel,
+ pool, pool));
+
+ SVN_TEST_ASSERT(local_change == svn_wc_conflict_reason_moved_away);
+ SVN_TEST_ASSERT(incoming_change == svn_wc_conflict_action_delete);
+ SVN_TEST_ASSERT(!strcmp(moved_away_op_root_abspath,
+ sbox_wc_path(&sbox, "A/B")));
+ }
+
+ return SVN_NO_ERROR;
+}
+
+/* A conflict resolver callback baton for test_prop_conflicts(). */
+typedef struct test_prop_conflict_baton_t
+{
+ /* Sets of properties. */
+ apr_hash_t *mine;
+ apr_hash_t *their_old;
+ apr_hash_t *theirs;
+ /* The set of prop names in conflict. */
+ apr_hash_t *conflicts;
+
+ /* We use all the fields of DESC except the base/theirs/mine/merged paths. */
+ svn_wc_conflict_description2_t *desc;
+
+ int conflicts_seen;
+} test_prop_conflict_baton_t;
+
+/* Set *CONFLICT_SKEL_P to a new property conflict skel reflecting the
+ * conflict details given in B. */
+static svn_error_t *
+create_prop_conflict_skel(svn_skel_t **conflict_skel_p,
+ svn_wc_context_t *wc_ctx,
+ const test_prop_conflict_baton_t *b,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
+{
+ svn_skel_t *conflict_skel = svn_wc__conflict_skel_create(result_pool);
+ const char *marker_abspath;
+ svn_boolean_t complete;
+
+ SVN_ERR(svn_io_write_unique(&marker_abspath,
+ b->desc->local_abspath,
+ "conflict-artifact-file-content\n", 6,
+ svn_io_file_del_none, scratch_pool));
+
+ SVN_ERR(svn_wc__conflict_skel_add_prop_conflict(conflict_skel,
+ wc_ctx->db,
+ b->desc->local_abspath,
+ marker_abspath,
+ b->mine, b->their_old,
+ b->theirs, b->conflicts,
+ result_pool, scratch_pool));
+
+ switch (b->desc->operation)
+ {
+ case svn_wc_operation_update:
+ SVN_ERR(svn_wc__conflict_skel_set_op_update(
+ conflict_skel,
+ b->desc->src_left_version, b->desc->src_right_version,
+ result_pool, scratch_pool));
+ break;
+ case svn_wc_operation_switch:
+ SVN_ERR(svn_wc__conflict_skel_set_op_switch(
+ conflict_skel,
+ b->desc->src_left_version, b->desc->src_right_version,
+ result_pool, scratch_pool));
+ break;
+ case svn_wc_operation_merge:
+ SVN_ERR(svn_wc__conflict_skel_set_op_merge(
+ conflict_skel,
+ b->desc->src_left_version, b->desc->src_right_version,
+ result_pool, scratch_pool));
+ break;
+ default:
+ SVN_ERR_MALFUNCTION();
+ }
+
+ SVN_ERR(svn_wc__conflict_skel_is_complete(&complete, conflict_skel));
+ SVN_TEST_ASSERT(complete);
+ *conflict_skel_p = conflict_skel;
+ return SVN_NO_ERROR;
+}
+
+/* A conflict resolver callback for test_prop_conflicts(), that checks
+ * that the conflict described to it matches the one described in BATON,
+ * and also counts the number of times it is called. */
+static svn_error_t *
+prop_conflict_cb(svn_wc_conflict_result_t **result_p,
+ const svn_wc_conflict_description2_t *desc,
+ void *baton,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
+{
+ test_prop_conflict_baton_t *b = baton;
+
+ SVN_ERR(compare_prop_conflict(
+ desc, b->desc,
+ svn_prop_get_value(b->their_old, desc->property_name),
+ svn_prop_get_value(b->mine, desc->property_name),
+ svn_prop_get_value(b->theirs, desc->property_name),
+ scratch_pool));
+ b->conflicts_seen++;
+
+ *result_p = svn_wc_create_conflict_result(svn_wc_conflict_choose_postpone,
+ NULL /*merged_file*/, result_pool);
+ return SVN_NO_ERROR;
+}
+
+/* Test for correct retrieval of property conflict descriptions from
+ * the WC DB.
+ *
+ * Presently it tests just one prop conflict, and only during the
+ * 'resolve' operation. We should also test during the 'update'/
+ * 'switch'/'merge' operations.
+ */
+static svn_error_t *
+test_prop_conflicts(const svn_test_opts_t *opts,
+ apr_pool_t *pool)
+{
+ svn_test__sandbox_t sbox;
+ svn_skel_t *conflict_skel;
+ svn_error_t *err;
+ const char *lock_abspath;
+ test_prop_conflict_baton_t *b = apr_pcalloc(pool, sizeof(*b));
+ svn_wc_conflict_description2_t *desc = apr_pcalloc(pool, sizeof(*desc));
+
+ SVN_ERR(svn_test__sandbox_create(&sbox, "test_prop_conflicts", opts, pool));
+
+ /* Describe a property conflict */
+ b->mine = apr_hash_make(pool);
+ b->their_old = apr_hash_make(pool);
+ b->theirs = apr_hash_make(pool);
+ b->conflicts = apr_hash_make(pool);
+ svn_hash_sets(b->mine, "prop", svn_string_create("Mine", pool));
+ svn_hash_sets(b->their_old, "prop", svn_string_create("Their-Old", pool));
+ svn_hash_sets(b->theirs, "prop", svn_string_create("Theirs", pool));
+ svn_hash_sets(b->conflicts, "prop", "");
+
+ b->desc = desc;
+ desc->local_abspath = sbox.wc_abspath;
+ desc->kind = svn_wc_conflict_kind_property;
+ desc->node_kind = svn_node_dir;
+ desc->operation = svn_wc_operation_update;
+ desc->action = svn_wc_conflict_action_edit;
+ desc->reason = svn_wc_conflict_reason_edited;
+ desc->mime_type = NULL;
+ desc->is_binary = FALSE;
+ desc->property_name = "prop";
+ desc->src_left_version
+ = svn_wc_conflict_version_create2(sbox.repos_url, "uuid",
+ "trunk", 12, svn_node_dir, pool);
+ desc->src_right_version = NULL; /* WC only */
+
+ b->conflicts_seen = 0;
+
+ /* Record a conflict */
+ {
+ apr_pool_t *subpool = svn_pool_create(pool);
+ SVN_ERR(create_prop_conflict_skel(&conflict_skel, sbox.wc_ctx, b,
+ pool, subpool));
+ svn_pool_clear(subpool);
+ SVN_ERR(svn_wc__db_op_mark_conflict(sbox.wc_ctx->db,
+ sbox.wc_abspath,
+ conflict_skel, NULL, subpool));
+ svn_pool_destroy(subpool);
+ }
+
+ /* Test the API for resolving the conflict: check that correct details
+ * of the conflict are returned. */
+ SVN_ERR(svn_wc__acquire_write_lock_for_resolve(&lock_abspath, sbox.wc_ctx,
+ sbox.wc_abspath, pool, pool));
+ err = svn_wc__resolve_conflicts(sbox.wc_ctx, sbox.wc_abspath,
+ svn_depth_empty,
+ FALSE /* resolve_text */,
+ "" /* resolve_prop (ALL props) */,
+ FALSE /* resolve_tree */,
+ svn_wc_conflict_choose_unspecified,
+ prop_conflict_cb, b,
+ NULL, NULL, /* cancellation */
+ NULL, NULL, /* notification */
+ pool);
+
+ SVN_ERR(svn_error_compose_create(err,
+ svn_wc__release_write_lock(sbox.wc_ctx,
+ lock_abspath,
+ pool)));
+
+ ASSERT_INT_EQ(b->conflicts_seen, 1);
+ return SVN_NO_ERROR;
+}
+
+/* The test table. */
+
+struct svn_test_descriptor_t test_funcs[] =
+ {
+ SVN_TEST_NULL,
+ SVN_TEST_PASS2(test_deserialize_tree_conflict,
+ "deserialize tree conflict"),
+ SVN_TEST_PASS2(test_serialize_tree_conflict_data,
+ "serialize tree conflict data"),
+ SVN_TEST_OPTS_PASS(test_read_write_tree_conflicts,
+ "read and write tree conflict data"),
+ SVN_TEST_OPTS_PASS(test_serialize_prop_conflict,
+ "read and write a property conflict"),
+ SVN_TEST_OPTS_PASS(test_serialize_text_conflict,
+ "read and write a text conflict"),
+ SVN_TEST_OPTS_PASS(test_serialize_tree_conflict,
+ "read and write a tree conflict"),
+ SVN_TEST_OPTS_PASS(test_prop_conflicts,
+ "test prop conflicts"),
+ SVN_TEST_NULL
+ };
+
diff --git a/subversion/tests/libsvn_wc/create_wc_for_upgrade.sh b/subversion/tests/libsvn_wc/create_wc_for_upgrade.sh
index 10ded2e..622595c 100755
--- a/subversion/tests/libsvn_wc/create_wc_for_upgrade.sh
+++ b/subversion/tests/libsvn_wc/create_wc_for_upgrade.sh
@@ -83,10 +83,10 @@ echo epsilon > epsilon
### row is created).
# a file with just .working
-### what comes after epsilon??
-echo lambda > lambda
-"${SVN}" add lambda
-"${SVN}" propset l-prop l-value lambda
+# zeta = epsilon+1
+echo zeta > zeta
+"${SVN}" add zeta
+"${SVN}" propset z-prop z-value zeta
# a file with .base and .working
"${SVN}" propset b-more b-value2 beta
diff --git a/subversion/tests/libsvn_wc/db-test.c b/subversion/tests/libsvn_wc/db-test.c
index 462fcb7..45e9c4d 100644
--- a/subversion/tests/libsvn_wc/db-test.c
+++ b/subversion/tests/libsvn_wc/db-test.c
@@ -97,91 +97,91 @@ static const char * const TESTING_DATA = (
"insert into nodes values ("
" 1, '', 0, null, 1, '', 1, 'normal',"
" null, null, 'dir', '()', 'infinity', null, null, 1, " TIME_1s ", '" AUTHOR_1 "',"
- " null, null, null, null);"
+ " null, null, null, null, null);"
"insert into nodes values ("
" 1, 'A', 0, '', 1, 'A', 1, 'normal',"
" null, null, 'file', '()', null, '$sha1$" SHA1_1 "', null, 1, " TIME_1s ", '" AUTHOR_1 "',"
- " 10, null, null, null);"
+ " 10, null, null, null, null);"
"insert into nodes values ("
" 1, 'B', 0, '', 1, 'B', null, 'excluded',"
" null, null, 'symlink', null, null, null, null, null, null, null,"
- " null, null, null, null);"
+ " null, null, null, null, null);"
"insert into nodes values ("
- " 1, 'C', 0, '', 1, 'C', null, 'absent',"
+ " 1, 'C', 0, '', 1, 'C', null, 'server-excluded',"
" null, null, 'unknown', null, null, null, null, null, null, null,"
- " null, null, null, null);"
+ " null, null, null, null, null);"
"insert into nodes values ("
" 1, 'D', 0, '', 1, 'D', null, 'not-present',"
" null, null, 'unknown', null, null, null, null, null, null, null,"
- " null, null, null, null);"
+ " null, null, null, null, null);"
"insert into nodes values ("
" 1, 'E', 0, '', 1, 'E', null, 'incomplete',"
" null, null, 'unknown', null, null, null, null, null, null, null,"
- " null, null, null, null);"
+ " null, null, null, null, null);"
"insert into nodes values ("
" 1, 'F', 0, '', 1, 'F', 1, 'normal',"
" null, null, 'file', '()', null, '$sha1$" SHA1_1 "', null, 1, " TIME_1s ", '" AUTHOR_1 "',"
- " 15, null, null, null);"
+ " 15, null, null, null, null);"
"insert into nodes values ("
" 1, 'G', 0, '', 2, 'G-alt', 1, 'normal',"
" null, null, 'file', '()', null, '$sha1$" SHA1_1 "', null, 2, " TIME_2s ", '" AUTHOR_2 "',"
- " 15, null, null, null);"
+ " 15, null, null, null, null);"
"insert into nodes values ("
" 1, 'H', 0, '', 1, 'H', 1, 'normal',"
" null, null, 'symlink', '()', null, null, 'H-target', 1, " TIME_1s ", '" AUTHOR_1 "',"
- " null, null, null, null);"
+ " null, null, null, null, null);"
"insert into nodes values ("
" 1, 'I', 0, '', 1, 'I', 1, 'normal',"
" null, null, 'dir', '()', null, null, null, 1, " TIME_1s ", '" AUTHOR_1 "',"
- " null, null, null, null);"
+ " null, null, null, null, null);"
"insert into nodes values ("
" 1, 'J', 0, '', 1, 'J', 1, 'normal',"
" null, null, 'dir', '()', null, null, null, 1, " TIME_1s ", '" AUTHOR_1 "',"
- " null, null, null, null);"
+ " null, null, null, null, null);"
"insert into nodes values ("
" 1, 'J/J-e', 0, 'J', 1, 'J/J-e', 1, 'normal',"
- " null, null, 'dir', '()', null, null, null, 1, " TIME_1s ", '" AUTHOR_1 "',"
- " null, null, null, null);"
+ " null, 'other/place', 'dir', '()', null, null, null, 1, " TIME_1s ", '" AUTHOR_1 "',"
+ " null, null, null, null, null);"
"insert into nodes values ("
" 1, 'J/J-e/J-e-a', 0, 'J/J-e', 1, 'J/J-e/J-e-a', 1, 'normal',"
" null, null, 'file', '()', null, '$sha1$" SHA1_1 "', null, 1, " TIME_1s ", '" AUTHOR_1 "',"
- " 15, null, null, null);"
+ " 15, null, null, null, null);"
"insert into nodes values ("
" 1, 'J/J-e/J-e-b', 0, 'J/J-e', 1, 'J/J-e/J-e-b', 1, 'normal',"
" null, null, 'dir', '()', null, null, null, 1, " TIME_1s ", '" AUTHOR_1 "',"
- " null, null, null, null);"
+ " null, null, null, null, null);"
"insert into nodes values ("
" 1, 'J/J-e/J-e-b/Jeba', 0, 'J/J-e/J-e-b', 1, 'J/J-e/J-e-b/Jeba', 1, 'normal',"
" null, null, 'file', '()', null, '$sha1$" SHA1_1 "', null, 1, " TIME_1s ", '" AUTHOR_1 "',"
- " 15, null, null, null);"
+ " 15, null, null, null, null);"
"insert into nodes values ("
" 1, 'J/J-f', 0, 'J', 1, 'J/J-f', 1, 'normal',"
" null, null, 'dir', '()', null, null, null, 1, " TIME_1s ", '" AUTHOR_1 "',"
- " null, null, null, null);"
+ " null, null, null, null, null);"
"insert into nodes values ("
" 1, 'J/J-f/J-f-a', 0, 'J/J-f', 1, 'J/J-f/J-f-a', 1, 'normal',"
" null, null, 'dir', '()', null, null, null, 1, " TIME_1s ", '" AUTHOR_1 "',"
- " null, null, null, null);"
+ " null, null, null, null, null);"
"insert into nodes values ("
" 1, 'K', 0, '', 1, 'K', 1, 'normal',"
" null, null, 'dir', '()', null, null, null, 1, " TIME_1s ", '" AUTHOR_1 "',"
- " null, null, null, null);"
+ " null, null, null, null, null);"
"insert into nodes values ("
" 1, 'K/K-a', 0, 'K', 1, 'K/K-a', 1, 'normal',"
" null, null, 'file', '()', null, '$sha1$" SHA1_1 "', null, 1, " TIME_1s ", '" AUTHOR_1 "',"
- " 15, null, null, null);"
+ " 15, null, null, null, null);"
"insert into nodes values ("
" 1, 'K/K-b', 0, 'K', 1, 'K/K-b', 1, 'normal',"
- " null, null, 'file', '()', null, '$sha1$" SHA1_1 "', null, 1, " TIME_1s ", '" AUTHOR_1 "',"
- " 15, null, null, null);"
+ " null, 'moved/away', 'file', '()', null, '$sha1$" SHA1_1 "', null, 1, " TIME_1s ", '" AUTHOR_1 "',"
+ " 15, null, null, null, null);"
""
/* Load data into NODES table;
### op_depths have not been calculated by me yet;
the value 1 is just 'good enough' to make the nodes WORKING nodes. */
"insert into nodes values ("
" 1, 'I', 1, '', 2, 'some/dir', 2, 'normal',"
- " 0, null, 'dir', '()', 'immediates', null, null, 2, " TIME_2s ", '" AUTHOR_2 "',"
- " null, null, null, null);"
+ " null, null, 'dir', '()', 'immediates', null, null, 2, " TIME_2s ", '" AUTHOR_2 "',"
+ " null, null, null, null, null);"
/* I'm not sure what the working J is supposed to represent. It
replaces the base J, but is it a copy or not? It has no
@@ -189,112 +189,136 @@ static const char * const TESTING_DATA = (
implies they are children of a copied J. */
"insert into nodes values ("
" 1, 'J', 1, '', null, null, null, 'normal',"
- " 0, null, 'dir', '()', 'immediates', null, null, null, null, null,"
- " null, null, null, null);"
+ " null, null, 'dir', '()', 'immediates', null, null, null, null, null,"
+ " null, null, null, null, null);"
"insert into nodes values ("
" 1, 'J/J-a', 1, 'J', null, null, null, 'normal',"
- " 0, null, 'file', '()', null, null, null, null, null, null,"
- " null, null, null, null);"
+ " null, null, 'file', '()', null, null, null, null, null, null,"
+ " null, null, null, null, null);"
"insert into nodes values ("
" 1, 'J/J-b', 2, 'J', 2, 'some/dir', 2, 'normal',"
- " 0, null, 'dir', '()', 'infinity', null, null, 2, " TIME_2s ", '" AUTHOR_2 "',"
- " null, null, null, null);"
+ " null, null, 'dir', '()', 'infinity', null, null, 2, " TIME_2s ", '" AUTHOR_2 "',"
+ " null, null, null, null, null);"
"insert into nodes values ("
" 1, 'J/J-b/J-b-a', 3, 'J/J-b', 2, 'another/dir', 2, 'normal',"
- " 0, null, 'dir', '()', 'infinity', null, null, 2, " TIME_2s ", '" AUTHOR_2 "',"
- " null, null, null, null);"
+ " null, null, 'dir', '()', 'infinity', null, null, 2, " TIME_2s ", '" AUTHOR_2 "',"
+ " null, null, null, null, null);"
"insert into nodes values ("
" 1, 'J/J-b/J-b-b', 2, 'J/J-b', null, null, 2, 'normal',"
- " 0, null, 'file', '()', null, null, null, null, null, null,"
- " null, null, null, null);"
+ " null, null, 'file', '()', null, null, null, null, null, null,"
+ " null, null, null, null, null);"
"insert into nodes values ("
" 1, 'J/J-c', 1, 'J', null, null, null, 'normal',"
- " 0, null, 'dir', '()', null, null, null, null, null, null,"
- " null, null, null, null);"
+ " null, null, 'dir', '()', null, null, null, null, null, null,"
+ " null, null, null, null, null);"
"insert into nodes values ("
" 1, 'J/J-c/J-c-a', 1, 'J/J-c', null, null, null, 'normal',"
- " 0, null, 'dir', '()', null, null, null, null, null, null,"
- " null, null, null, null);"
+ " null, null, 'dir', '()', null, null, null, null, null, null,"
+ " null, null, null, null, null);"
"insert into nodes values ("
" 1, 'J/J-c', 2, 'J', null, null, null, 'base-deleted',"
- " 0, null, 'dir', '()', null, null, null, null, null, null,"
- " null, null, null, null);"
+ " null, null, 'dir', '()', null, null, null, null, null, null,"
+ " null, null, null, null, null);"
"insert into nodes values ("
" 1, 'J/J-c/J-c-a', 2, 'J/J-c', null, null, null, 'base-deleted',"
- " 0, null, 'dir', '()', null, null, null, null, null, null,"
- " null, null, null, null);"
+ " null, null, 'dir', '()', null, null, null, null, null, null,"
+ " null, null, null, null, null);"
"insert into nodes values ("
" 1, 'J/J-d', 2, 'J', 2, 'moved/file', 2, 'normal',"
" 1, null, 'file', '()', null, '$sha1$" SHA1_1 "', null, 2, " TIME_2s ", '" AUTHOR_2 "',"
- " 10, null, null, null);"
+ " 10, null, null, null, null);"
+ "insert into nodes values ("
+ " 1, 'moved/file', 0, 'moved', 2, 'moved/file', 2, 'normal',"
+ " null, null, 'file', '()', null, '$sha1$" SHA1_1 "', null, 2, " TIME_2s ", '" AUTHOR_2 "',"
+ " 10, null, null, null, null);"
+ "insert into nodes values ("
+ " 1, 'moved/file', 2, 'moved', 2, 'moved/file', 2, 'base-deleted',"
+ " null, 'J/J-d', 'file', '()', null, null, null, null, null, null,"
+ " 10, null, null, null, null);"
"insert into nodes values ("
" 1, 'J/J-e', 1, 'J', null, null, null, 'normal',"
- " 0, 'other/place', 'dir', '()', null, null, null, null, null, null,"
- " null, null, null, null);"
+ " null, null, 'dir', '()', null, null, null, null, null, null,"
+ " null, null, null, null, null);"
"insert into nodes values ("
" 1, 'J/J-e/J-e-a', 1, 'J/J-e', null, null, null, 'normal',"
- " 0, null, 'file', '()', null, null, null, null, null, null,"
- " null, null, null, null);"
+ " null, null, 'file', '()', null, null, null, null, null, null,"
+ " null, null, null, null, null);"
"insert into nodes values ("
" 1, 'J/J-e/J-e-b', 1, 'J/J-e', null, null, null, 'normal',"
- " 0, null, 'dir', '()', null, null, null, null, null, null,"
- " null, null, null, null);"
+ " null, null, 'dir', '()', null, null, null, null, null, null,"
+ " null, null, null, null, null);"
"insert into nodes values ("
" 1, 'J/J-e', 2, 'J', null, null, null, 'base-deleted',"
- " 0, 'other/place', 'dir', '()', null, null, null, null, null, null,"
- " null, null, null, null);"
+ " null, null, 'dir', '()', null, null, null, null, null, null,"
+ " null, null, null, null, null);"
"insert into nodes values ("
" 1, 'J/J-e/J-e-a', 2, 'J/J-e', null, null, null, 'base-deleted',"
- " 0, null, 'file', '()', null, null, null, null, null, null,"
- " null, null, null, null);"
+ " null, null, 'file', '()', null, null, null, null, null, null,"
+ " null, null, null, null, null);"
"insert into nodes values ("
" 1, 'J/J-e/J-e-b', 2, 'J/J-e', null, null, null, 'base-deleted',"
- " 0, null, 'dir', '()', null, null, null, null, null, null,"
- " null, null, null, null);"
+ " null, null, 'dir', '()', null, null, null, null, null, null,"
+ " null, null, null, null, null);"
"insert into nodes values ("
" 1, 'J/J-e/J-e-b/Jeba', 1, 'J/J-e/J-e-b', null, null, null, 'base-deleted',"
- " 0, null, 'file', '()', null, null, null, null, null, null,"
- " null, null, null, null);"
+ " null, null, 'file', '()', null, null, null, null, null, null,"
+ " null, null, null, null, null);"
"insert into nodes values ("
" 1, 'J/J-f', 1, 'J', null, null, null, 'normal',"
- " 0, null, 'dir', '()', 'immediates', null, null, null, null, null,"
- " null, null, null, null);"
+ " null, null, 'dir', '()', 'immediates', null, null, null, null, null,"
+ " null, null, null, null, null);"
"insert into nodes values ("
" 1, 'J/J-f/J-f-a', 1, 'J/J-f', null, null, null, 'base-deleted',"
- " 0, null, 'dir', '()', 'immediates', null, null, null, null, null,"
- " null, null, null, null);"
+ " null, null, 'dir', '()', 'immediates', null, null, null, null, null,"
+ " null, null, null, null, null);"
"insert into nodes values ("
" 1, 'K', 1, '', null, null, null, 'base-deleted',"
- " 0, null, 'dir', '()', null, null, null, null, null, null,"
- " null, null, null, null);"
+ " null, null, 'dir', '()', null, null, null, null, null, null,"
+ " null, null, null, null, null);"
"insert into nodes values ("
" 1, 'K/K-a', 1, 'K', null, null, null, 'base-deleted',"
- " 0, null, 'file', '()', null, null, null, null, null, null,"
- " null, null, null, null);"
+ " null, null, 'file', '()', null, null, null, null, null, null,"
+ " null, null, null, null, null);"
"insert into nodes values ("
" 1, 'K/K-b', 1, 'K', null, null, null, 'base-deleted',"
- " 0, 'moved/away', 'file', '()', null, null, null, null, null, null,"
- " null, null, null, null);"
+ " null, null, 'file', '()', null, null, null, null, null, null,"
+ " null, null, null, null, null);"
"insert into nodes values ("
" 1, 'L', 1, '', null, null, null, 'normal',"
- " 0, null, 'dir', '()', 'immediates', null, null, null, null, null,"
- " null, null, null, null);"
+ " null, null, 'dir', '()', 'immediates', null, null, null, null, null,"
+ " null, null, null, null, null);"
"insert into nodes values ("
" 1, 'L/L-a', 1, 'L', null, null, null, 'normal',"
- " 0, null, 'dir', '()', 'immediates', null, null, null, null, null,"
- " null, null, null, null);"
+ " null, null, 'dir', '()', 'immediates', null, null, null, null, null,"
+ " null, null, null, null, null);"
"insert into nodes values ("
" 1, 'L/L-a/L-a-a', 1, 'L/L-a', null, null, null, 'normal',"
- " 0, null, 'dir', '()', 'immediates', null, null, null, null, null,"
- " null, null, null, null);"
+ " null, null, 'dir', '()', 'immediates', null, null, null, null, null,"
+ " null, null, null, null, null);"
"insert into nodes values ("
" 1, 'L/L-a', 2, 'L', null, null, null, 'base-deleted',"
- " 0, null, 'dir', '()', 'immediates', null, null, null, null, null,"
- " null, null, null, null);"
+ " null, null, 'dir', '()', 'immediates', null, null, null, null, null,"
+ " null, null, null, null, null);"
"insert into nodes values ("
" 1, 'L/L-a/L-a-a', 2, 'L/L-a', null, null, null, 'base-deleted',"
- " 0, null, 'dir', '()', 'immediates', null, null, null, null, null,"
- " null, null, null, null);"
+ " null, null, 'dir', '()', 'immediates', null, null, null, null, null,"
+ " null, null, null, null, null);"
+ "insert into nodes values ("
+ " 1, 'other/place', 2, 'other', null, null, null, 'normal',"
+ " 1, null, 'dir', '()', 'immediates', null, null, null, null, null,"
+ " null, null, null, null, null);"
+ "insert into nodes values ("
+ " 1, 'other/place/J-e-a', 2, 'other/place', null, null, null, 'normal',"
+ " null, null, 'dir', '()', 'immediates', null, null, null, null, null,"
+ " null, null, null, null, null);"
+ "insert into nodes values ("
+ " 1, 'other/place/J-e-b', 2, 'other/place', null, null, null, 'normal',"
+ " null, null, 'dir', '()', null, null, null, 1, " TIME_1s ", '" AUTHOR_1 "',"
+ " null, null, null, null, null);"
+ "insert into nodes values ("
+ " 1, 'other/place/J-e-b/Jeba', 0, 'other/place/J-e-b', null, null, null, 'normal',"
+ " null, null, 'file', '()', null, '$sha1$" SHA1_1 "', null, 1, " TIME_1s ", '" AUTHOR_1 "',"
+ " 15, null, null, null, null);"
"insert into actual_node values ("
" 1, 'I', '', null, null, null, null, null, 'changelist', null, "
" null, null, null, null, null);"
@@ -316,9 +340,11 @@ create_open(svn_wc__db_t **db,
SVN_ERR(svn_dirent_get_absolute(local_abspath,
svn_dirent_join("fake-wc", subdir, pool),
pool));
- SVN_ERR(svn_wc__db_open(db, NULL, TRUE, TRUE, pool, pool));
+ SVN_ERR(svn_wc__db_open(db, NULL, FALSE, TRUE, pool, pool));
SVN_ERR(svn_test__create_fake_wc(*local_abspath, TESTING_DATA, pool, pool));
+ svn_test_add_dir_cleanup(*local_abspath);
+
return SVN_NO_ERROR;
}
@@ -354,7 +380,7 @@ static svn_error_t *
test_getting_info(apr_pool_t *pool)
{
const char *local_abspath;
- svn_wc__db_kind_t kind;
+ svn_node_kind_t kind;
svn_wc__db_status_t status;
svn_revnum_t revision;
const char *repos_relpath;
@@ -367,6 +393,7 @@ test_getting_info(apr_pool_t *pool)
const svn_checksum_t *checksum;
const char *target;
svn_boolean_t had_props;
+ apr_hash_t *props;
svn_boolean_t update_root;
svn_wc__db_lock_t *lock;
svn_wc__db_t *db;
@@ -379,11 +406,11 @@ test_getting_info(apr_pool_t *pool)
&status, &kind, &revision,
&repos_relpath, &repos_root_url, &repos_uuid,
&changed_rev, &changed_date, &changed_author,&depth, &checksum,
- &target, &lock, &had_props,
+ &target, &lock, &had_props, &props,
&update_root,
db, local_abspath,
pool, pool));
- SVN_TEST_ASSERT(kind == svn_wc__db_kind_dir);
+ SVN_TEST_ASSERT(kind == svn_node_dir);
SVN_TEST_ASSERT(status == svn_wc__db_status_normal);
SVN_TEST_ASSERT(revision == 1);
SVN_TEST_STRING_ASSERT(repos_relpath, "");
@@ -396,6 +423,9 @@ test_getting_info(apr_pool_t *pool)
SVN_TEST_ASSERT(checksum == NULL);
SVN_TEST_ASSERT(target == NULL);
SVN_TEST_ASSERT(lock == NULL);
+ SVN_TEST_ASSERT(!had_props);
+ SVN_TEST_ASSERT(apr_hash_count(props) == 0);
+ /* SVN_TEST_ASSERT(update_root == ???); */
/* Test: file-specific values. */
SVN_ERR(svn_wc__db_base_get_info(
@@ -403,10 +433,10 @@ test_getting_info(apr_pool_t *pool)
&repos_relpath, &repos_root_url, &repos_uuid,
NULL, NULL, NULL, NULL,
&checksum, NULL, NULL,
- NULL, NULL,
+ NULL, NULL, NULL,
db, svn_dirent_join(local_abspath, "A", pool),
pool, pool));
- SVN_TEST_ASSERT(kind == svn_wc__db_kind_file);
+ SVN_TEST_ASSERT(kind == svn_node_file);
SVN_TEST_STRING_ASSERT(SHA1_1, svn_checksum_to_cstring(checksum, pool));
SVN_TEST_STRING_ASSERT(repos_relpath, "A");
SVN_TEST_STRING_ASSERT(repos_root_url, ROOT_ONE);
@@ -418,10 +448,10 @@ test_getting_info(apr_pool_t *pool)
&repos_relpath, &repos_root_url, &repos_uuid,
&changed_rev, &changed_date, &changed_author,
&depth, &checksum, &target, &lock,
- NULL, NULL,
+ NULL, NULL, NULL,
db, svn_dirent_join(local_abspath, "B", pool),
pool, pool));
- SVN_TEST_ASSERT(kind == svn_wc__db_kind_symlink);
+ SVN_TEST_ASSERT(kind == svn_node_symlink);
SVN_TEST_ASSERT(status == svn_wc__db_status_excluded);
SVN_TEST_ASSERT(!SVN_IS_VALID_REVNUM(revision));
SVN_TEST_STRING_ASSERT(repos_relpath, "B");
@@ -435,16 +465,16 @@ test_getting_info(apr_pool_t *pool)
SVN_TEST_ASSERT(target == NULL);
SVN_TEST_ASSERT(lock == NULL);
- /* Test: unknown kind, absent presence. */
+ /* Test: unknown kind, server-excluded presence. */
SVN_ERR(svn_wc__db_base_get_info(
&status, &kind, NULL,
NULL, NULL, NULL,
NULL, NULL, NULL,
NULL, NULL, NULL,
- NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL,
db, svn_dirent_join(local_abspath, "C", pool),
pool, pool));
- SVN_TEST_ASSERT(kind == svn_wc__db_kind_unknown);
+ SVN_TEST_ASSERT(kind == svn_node_unknown);
SVN_TEST_ASSERT(status == svn_wc__db_status_server_excluded);
/* Test: not-present presence. */
@@ -453,7 +483,7 @@ test_getting_info(apr_pool_t *pool)
NULL, NULL, NULL,
NULL, NULL, NULL,
NULL, NULL, NULL,
- NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL,
db, svn_dirent_join(local_abspath, "D", pool),
pool, pool));
SVN_TEST_ASSERT(status == svn_wc__db_status_not_present);
@@ -464,7 +494,7 @@ test_getting_info(apr_pool_t *pool)
NULL, NULL, NULL,
NULL, NULL, NULL,
NULL, NULL, NULL,
- NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL,
db, svn_dirent_join(local_abspath, "E", pool),
pool, pool));
SVN_TEST_ASSERT(status == svn_wc__db_status_incomplete);
@@ -475,7 +505,7 @@ test_getting_info(apr_pool_t *pool)
NULL, NULL, NULL,
NULL, NULL, NULL,
NULL, &checksum, NULL,
- NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL,
db, svn_dirent_join(local_abspath, "F", pool),
pool, pool));
SVN_TEST_STRING_ASSERT(SHA1_1,
@@ -487,7 +517,7 @@ test_getting_info(apr_pool_t *pool)
&repos_relpath, &repos_root_url, &repos_uuid,
&changed_rev, &changed_date, &changed_author,
NULL, NULL, NULL,
- NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL,
db, svn_dirent_join(local_abspath, "G", pool),
pool, pool));
SVN_TEST_STRING_ASSERT(repos_relpath, "G-alt");
@@ -503,7 +533,7 @@ test_getting_info(apr_pool_t *pool)
NULL, NULL, NULL,
NULL, NULL, NULL,
NULL, &checksum, &target,
- NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL,
db, svn_dirent_join(local_abspath, "H", pool),
pool, pool));
SVN_TEST_ASSERT(checksum == NULL);
@@ -515,11 +545,10 @@ test_getting_info(apr_pool_t *pool)
NULL, NULL, NULL,
NULL, NULL, NULL,
NULL, NULL, NULL,
- NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL,
db, svn_dirent_join(local_abspath, "missing-file", pool),
pool, pool);
- SVN_TEST_ASSERT(err != NULL && err->apr_err == SVN_ERR_WC_PATH_NOT_FOUND);
- svn_error_clear(err);
+ SVN_TEST_ASSERT_ERROR(err, SVN_ERR_WC_PATH_NOT_FOUND);
return SVN_NO_ERROR;
}
@@ -529,12 +558,12 @@ static svn_error_t *
validate_node(svn_wc__db_t *db,
const char *local_abspath,
const char *relpath,
- svn_wc__db_kind_t expected_kind,
+ svn_node_kind_t expected_kind,
svn_wc__db_status_t expected_status,
apr_pool_t *scratch_pool)
{
const char *path = svn_dirent_join(local_abspath, relpath, scratch_pool);
- svn_wc__db_kind_t kind;
+ svn_node_kind_t kind;
svn_wc__db_status_t status;
apr_hash_t *props;
const svn_string_t *value;
@@ -544,14 +573,12 @@ validate_node(svn_wc__db_t *db,
NULL, NULL, NULL,
NULL, NULL, NULL,
NULL, NULL, NULL,
- NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL,
db, path,
scratch_pool, scratch_pool));
SVN_TEST_ASSERT(kind == expected_kind);
SVN_TEST_ASSERT(status == expected_status);
- SVN_ERR(svn_wc__db_base_get_props(&props, db, path,
- scratch_pool, scratch_pool));
switch (status)
{
case svn_wc__db_status_server_excluded:
@@ -559,13 +586,18 @@ validate_node(svn_wc__db_t *db,
case svn_wc__db_status_incomplete:
case svn_wc__db_status_not_present:
/* Our tests aren't setting properties on these node types, so
- short-circuit examination of name/value pairs. */
+ short-circuit examination of name/value pairs, to avoid having
+ to handle the error from svn_wc__db_base_get_props(). */
return SVN_NO_ERROR;
-
default:
- SVN_TEST_ASSERT(props != NULL);
+ break; /* Fall through */
}
+ SVN_ERR(svn_wc__db_base_get_props(&props, db, path,
+ scratch_pool, scratch_pool));
+
+ SVN_TEST_ASSERT(props != NULL);
+
value = apr_hash_get(props, "p1", APR_HASH_KEY_STRING);
SVN_TEST_STRING_ASSERT(value->data, "v1");
@@ -628,7 +660,7 @@ test_inserting_nodes(apr_pool_t *pool)
props,
1, TIME_1a, AUTHOR_1,
children, svn_depth_infinity,
- NULL, NULL, FALSE, NULL, NULL,
+ NULL, NULL, FALSE, NULL, NULL, NULL,
pool));
/* Replace an incomplete node with a file node. */
@@ -640,7 +672,8 @@ test_inserting_nodes(apr_pool_t *pool)
props,
1, TIME_1a, AUTHOR_1,
checksum,
- NULL, NULL, FALSE, NULL, FALSE, FALSE, NULL,
+ NULL, FALSE, FALSE, NULL, NULL, FALSE, FALSE,
+ NULL, NULL,
pool));
/* Create a new symlink node. */
@@ -652,14 +685,15 @@ test_inserting_nodes(apr_pool_t *pool)
props,
1, TIME_1a, AUTHOR_1,
"O-target",
- NULL, NULL, FALSE, NULL, NULL,
+ NULL, FALSE, FALSE, NULL, NULL, FALSE, FALSE,
+ NULL, NULL,
pool));
- /* Replace an incomplete node with an absent file node. */
+ /* Replace an incomplete node with an server-excluded file node. */
SVN_ERR(svn_wc__db_base_add_excluded_node(
db, svn_dirent_join(local_abspath, "N/N-b", pool),
"N/N-b", ROOT_ONE, UUID_ONE, 3,
- svn_wc__db_kind_file, svn_wc__db_status_server_excluded,
+ svn_node_file, svn_wc__db_status_server_excluded,
NULL, NULL,
pool));
@@ -667,7 +701,7 @@ test_inserting_nodes(apr_pool_t *pool)
SVN_ERR(svn_wc__db_base_add_excluded_node(
db, svn_dirent_join(local_abspath, "P", pool),
"P", ROOT_ONE, UUID_ONE, 3,
- svn_wc__db_kind_dir, svn_wc__db_status_excluded,
+ svn_node_dir, svn_wc__db_status_excluded,
NULL, NULL,
pool));
@@ -675,44 +709,44 @@ test_inserting_nodes(apr_pool_t *pool)
SVN_ERR(svn_wc__db_base_add_not_present_node(
db, svn_dirent_join(local_abspath, "Q", pool),
"Q", ROOT_ONE, UUID_ONE, 3,
- svn_wc__db_kind_symlink,
+ svn_node_symlink,
NULL, NULL,
pool));
- /* Create a new absent unknown-kind node. */
+ /* Create a new server-excluded unknown-kind node. */
SVN_ERR(svn_wc__db_base_add_excluded_node(
db, svn_dirent_join(local_abspath, "R", pool),
"R", ROOT_ONE, UUID_ONE, 3,
- svn_wc__db_kind_unknown, svn_wc__db_status_server_excluded,
+ svn_node_unknown, svn_wc__db_status_server_excluded,
NULL, NULL,
pool));
/* Are all the nodes where we expect them to be? */
SVN_ERR(validate_node(db, local_abspath, "N",
- svn_wc__db_kind_dir, svn_wc__db_status_normal,
+ svn_node_dir, svn_wc__db_status_normal,
pool));
SVN_ERR(validate_node(db, local_abspath, "N/N-a",
- svn_wc__db_kind_file, svn_wc__db_status_normal,
+ svn_node_file, svn_wc__db_status_normal,
pool));
SVN_ERR(validate_node(db, local_abspath, "N/N-b",
- svn_wc__db_kind_file,
+ svn_node_file,
svn_wc__db_status_server_excluded,
pool));
SVN_ERR(validate_node(db, local_abspath, "N/N-c",
- svn_wc__db_kind_unknown, svn_wc__db_status_incomplete,
+ svn_node_unknown, svn_wc__db_status_incomplete,
pool));
SVN_ERR(validate_node(db, local_abspath, "O",
- svn_wc__db_kind_symlink, svn_wc__db_status_normal,
+ svn_node_symlink, svn_wc__db_status_normal,
pool));
SVN_ERR(validate_node(db, local_abspath, "P",
- svn_wc__db_kind_dir, svn_wc__db_status_excluded,
+ svn_node_dir, svn_wc__db_status_excluded,
pool));
SVN_ERR(validate_node(db, local_abspath, "Q",
- svn_wc__db_kind_symlink, svn_wc__db_status_not_present,
+ svn_node_symlink, svn_wc__db_status_not_present,
pool));
SVN_ERR(validate_node(db, local_abspath, "R",
- svn_wc__db_kind_unknown,
+ svn_node_unknown,
svn_wc__db_status_server_excluded,
pool));
@@ -768,7 +802,7 @@ static svn_error_t *
test_working_info(apr_pool_t *pool)
{
const char *local_abspath;
- svn_wc__db_kind_t kind;
+ svn_node_kind_t kind;
svn_wc__db_status_t status;
svn_revnum_t revision;
const char *repos_relpath;
@@ -777,10 +811,10 @@ test_working_info(apr_pool_t *pool)
svn_revnum_t changed_rev;
apr_time_t changed_date;
const char *changed_author;
- apr_time_t last_mod_time;
+ apr_time_t recorded_time;
svn_depth_t depth;
const svn_checksum_t *checksum;
- svn_filesize_t translated_size;
+ svn_filesize_t recorded_size;
const char *target;
const char *changelist;
const char *original_repos_relpath;
@@ -806,13 +840,13 @@ test_working_info(apr_pool_t *pool)
&changed_rev, &changed_date, &changed_author,
&depth, &checksum, &target, &original_repos_relpath,
&original_root_url, &original_uuid, &original_revnum,
- &lock, &translated_size, &last_mod_time, &changelist,
+ &lock, &recorded_size, &recorded_time, &changelist,
&conflicted, &op_root, &had_props, &props_mod,
&have_base, &have_more_work, &have_work,
db, svn_dirent_join(local_abspath, "I", pool),
pool, pool));
SVN_TEST_ASSERT(status == svn_wc__db_status_added);
- SVN_TEST_ASSERT(kind == svn_wc__db_kind_dir);
+ SVN_TEST_ASSERT(kind == svn_node_dir);
SVN_TEST_ASSERT(revision == SVN_INVALID_REVNUM);
SVN_TEST_ASSERT(repos_relpath == NULL);
SVN_TEST_ASSERT(repos_root_url == NULL);
@@ -822,18 +856,22 @@ test_working_info(apr_pool_t *pool)
SVN_TEST_STRING_ASSERT(changed_author, AUTHOR_2);
SVN_TEST_ASSERT(depth == svn_depth_immediates);
SVN_TEST_ASSERT(checksum == NULL);
- SVN_TEST_ASSERT(translated_size == SVN_INVALID_FILESIZE);
+ SVN_TEST_ASSERT(recorded_size == SVN_INVALID_FILESIZE);
SVN_TEST_ASSERT(target == NULL);
SVN_TEST_STRING_ASSERT(changelist, "changelist");
SVN_TEST_STRING_ASSERT(original_repos_relpath, "some/dir");
SVN_TEST_STRING_ASSERT(original_root_url, ROOT_TWO);
SVN_TEST_STRING_ASSERT(original_uuid, UUID_TWO);
SVN_TEST_ASSERT(original_revnum == 2);
- SVN_TEST_ASSERT(props_mod == FALSE);
- SVN_TEST_ASSERT(have_base == TRUE);
- SVN_TEST_ASSERT(have_work == TRUE);
- SVN_TEST_ASSERT(conflicted == FALSE);
+ SVN_TEST_ASSERT(!had_props);
+ SVN_TEST_ASSERT(!props_mod);
+ SVN_TEST_ASSERT(have_base);
+ /* SVN_TEST_ASSERT(have_more_work...); */
+ SVN_TEST_ASSERT(have_work);
+ SVN_TEST_ASSERT(!conflicted);
SVN_TEST_ASSERT(lock == NULL);
+ /* SVN_TEST_ASSERT(last_mod_time...); */
+ /* SVN_TEST_ASSERT(op_root...); */
/* ### we need a hojillion more tests in here. I just want to get this
@@ -859,14 +897,14 @@ test_pdh(apr_pool_t *pool)
SVN_ERR(svn_wc__db_base_add_excluded_node(
db, svn_dirent_join(local_abspath, "sub", pool),
"sub", ROOT_ONE, UUID_ONE, 1,
- svn_wc__db_kind_file, svn_wc__db_status_server_excluded,
+ svn_node_file, svn_wc__db_status_server_excluded,
NULL, NULL,
pool));
SVN_ERR(svn_wc__db_base_add_excluded_node(
db, svn_dirent_join(local_abspath, "sub/A", pool),
"sub/A", ROOT_ONE, UUID_ONE, 1,
- svn_wc__db_kind_file, svn_wc__db_status_server_excluded,
+ svn_node_file, svn_wc__db_status_server_excluded,
NULL, NULL,
pool));
@@ -888,6 +926,10 @@ test_scan_addition(apr_pool_t *pool)
const char *original_root_url;
const char *original_uuid;
svn_revnum_t original_revision;
+ const char *moved_from_abspath;
+ const char *move_op_root_abspath;
+ const char *move_op_root_src;
+ const char *delete_op_root_abspath;
SVN_ERR(create_open(&db, &local_abspath, "test_scan_addition", pool));
@@ -935,9 +977,24 @@ test_scan_addition(apr_pool_t *pool)
&original_revision,
db, svn_dirent_join(local_abspath, "J/J-d", pool),
pool, pool));
+ SVN_ERR(svn_wc__db_scan_moved(
+ &moved_from_abspath,
+ &move_op_root_abspath,
+ &move_op_root_src,
+ &delete_op_root_abspath,
+ db, svn_dirent_join(local_abspath, "J/J-d", pool),
+ pool, pool));
SVN_TEST_ASSERT(status == svn_wc__db_status_moved_here);
SVN_TEST_ASSERT(validate_abspath(local_abspath, "J/J-d",
op_root_abspath, pool));
+ SVN_TEST_ASSERT(validate_abspath(local_abspath, "moved/file",
+ moved_from_abspath, pool));
+ SVN_TEST_ASSERT(validate_abspath(local_abspath, "J/J-d",
+ move_op_root_abspath, pool));
+ SVN_TEST_ASSERT(validate_abspath(local_abspath, "moved/file",
+ move_op_root_src, pool));
+ SVN_TEST_ASSERT(validate_abspath(local_abspath, "moved/file",
+ delete_op_root_abspath, pool));
SVN_TEST_STRING_ASSERT(repos_relpath, "J/J-d");
SVN_TEST_STRING_ASSERT(repos_root_url, ROOT_ONE);
SVN_TEST_STRING_ASSERT(repos_uuid, UUID_ONE);
@@ -1015,6 +1072,7 @@ test_scan_deletion(apr_pool_t *pool)
const char *base_del_abspath;
const char *work_del_abspath;
const char *moved_to_abspath;
+ const char *copy_op_root_abspath;
SVN_ERR(create_open(&db, &local_abspath, "test_scan_deletion", pool));
@@ -1023,34 +1081,41 @@ test_scan_deletion(apr_pool_t *pool)
&base_del_abspath,
&moved_to_abspath,
&work_del_abspath,
+ &copy_op_root_abspath,
db, svn_dirent_join(local_abspath, "J/J-e", pool),
pool, pool));
- SVN_TEST_ASSERT(validate_abspath(local_abspath, "J/J-e",
+ SVN_TEST_ASSERT(validate_abspath(local_abspath, "J",
base_del_abspath, pool));
SVN_TEST_ASSERT(validate_abspath(local_abspath, "other/place",
moved_to_abspath, pool));
SVN_TEST_ASSERT(validate_abspath(local_abspath, "J/J-e",
work_del_abspath, pool));
+ SVN_TEST_ASSERT(validate_abspath(local_abspath, "other/place",
+ copy_op_root_abspath, pool));
/* Node was moved elsewhere (child of operation root). */
SVN_ERR(svn_wc__db_scan_deletion(
&base_del_abspath,
&moved_to_abspath,
&work_del_abspath,
+ &copy_op_root_abspath,
db, svn_dirent_join(local_abspath, "J/J-e/J-e-a", pool),
pool, pool));
- SVN_TEST_ASSERT(validate_abspath(local_abspath, "J/J-e",
+ SVN_TEST_ASSERT(validate_abspath(local_abspath, "J",
base_del_abspath, pool));
- SVN_TEST_ASSERT(validate_abspath(local_abspath, "other/place",
+ SVN_TEST_ASSERT(validate_abspath(local_abspath, "other/place/J-e-a",
moved_to_abspath, pool));
SVN_TEST_ASSERT(validate_abspath(local_abspath, "J/J-e",
work_del_abspath, pool));
+ SVN_TEST_ASSERT(validate_abspath(local_abspath, "other/place",
+ copy_op_root_abspath, pool));
/* Root of delete. Parent is a WORKING node. */
SVN_ERR(svn_wc__db_scan_deletion(
&base_del_abspath,
&moved_to_abspath,
&work_del_abspath,
+ NULL,
db, svn_dirent_join(local_abspath, "J/J-c", pool),
pool, pool));
/* Implicit delete of "J" (via replacement). */
@@ -1065,6 +1130,7 @@ test_scan_deletion(apr_pool_t *pool)
&base_del_abspath,
&moved_to_abspath,
&work_del_abspath,
+ NULL,
db, svn_dirent_join(local_abspath, "J/J-c/J-c-a", pool),
pool, pool));
/* Implicit delete of "J" (via replacement). */
@@ -1079,14 +1145,15 @@ test_scan_deletion(apr_pool_t *pool)
&base_del_abspath,
&moved_to_abspath,
&work_del_abspath,
+ NULL,
db, svn_dirent_join(local_abspath, "J/J-e/J-e-b/Jeba", pool),
pool, pool));
/* ### I don't understand this. "J/J-e/J-e-b/Jeba" is a deleted
base node that is not overlayed by the replacement rooted at "J".
Why does base_del_abspath refer to "J-e"? */
- SVN_TEST_ASSERT(validate_abspath(local_abspath, "J/J-e",
+ SVN_TEST_ASSERT(validate_abspath(local_abspath, "J",
base_del_abspath, pool));
- SVN_TEST_ASSERT(validate_abspath(local_abspath, "other/place",
+ SVN_TEST_ASSERT(validate_abspath(local_abspath, "other/place/J-e-b/Jeba",
moved_to_abspath, pool));
SVN_TEST_ASSERT(work_del_abspath == NULL);
@@ -1095,6 +1162,7 @@ test_scan_deletion(apr_pool_t *pool)
&base_del_abspath,
&moved_to_abspath,
&work_del_abspath,
+ NULL,
db, svn_dirent_join(local_abspath, "J/J-f/J-f-a", pool),
pool, pool));
/* Implicit delete of "J" (via replacement). */
@@ -1108,6 +1176,7 @@ test_scan_deletion(apr_pool_t *pool)
&base_del_abspath,
&moved_to_abspath,
&work_del_abspath,
+ NULL,
db, svn_dirent_join(local_abspath, "K", pool),
pool, pool));
SVN_TEST_ASSERT(validate_abspath(local_abspath, "K",
@@ -1120,6 +1189,7 @@ test_scan_deletion(apr_pool_t *pool)
&base_del_abspath,
&moved_to_abspath,
&work_del_abspath,
+ NULL,
db, svn_dirent_join(local_abspath, "K/K-a", pool),
pool, pool));
SVN_TEST_ASSERT(validate_abspath(local_abspath, "K",
@@ -1132,12 +1202,15 @@ test_scan_deletion(apr_pool_t *pool)
&base_del_abspath,
&moved_to_abspath,
&work_del_abspath,
+ &copy_op_root_abspath,
db, svn_dirent_join(local_abspath, "K/K-b", pool),
pool, pool));
- SVN_TEST_ASSERT(validate_abspath(local_abspath, "K/K-b",
+ SVN_TEST_ASSERT(validate_abspath(local_abspath, "K",
base_del_abspath, pool));
SVN_TEST_ASSERT(validate_abspath(local_abspath, "moved/away",
moved_to_abspath, pool));
+ SVN_TEST_ASSERT(validate_abspath(local_abspath, "moved/away",
+ copy_op_root_abspath, pool));
SVN_TEST_ASSERT(work_del_abspath == NULL);
/* Subtree deletion of added tree. Start at child. */
@@ -1145,6 +1218,7 @@ test_scan_deletion(apr_pool_t *pool)
&base_del_abspath,
&moved_to_abspath,
&work_del_abspath,
+ NULL,
db, svn_dirent_join(local_abspath, "L/L-a/L-a-a", pool),
pool, pool));
SVN_TEST_ASSERT(base_del_abspath == NULL);
@@ -1157,6 +1231,7 @@ test_scan_deletion(apr_pool_t *pool)
&base_del_abspath,
&moved_to_abspath,
&work_del_abspath,
+ NULL,
db, svn_dirent_join(local_abspath, "L/L-a", pool),
pool, pool));
SVN_TEST_ASSERT(base_del_abspath == NULL);
@@ -1356,6 +1431,7 @@ test_externals_store(apr_pool_t *pool)
"not-a-uuid",
12,
props,
+ NULL,
10,
987654,
"somebody",
@@ -1368,6 +1444,7 @@ test_externals_store(apr_pool_t *pool)
FALSE, NULL,
FALSE,
NULL,
+ NULL,
pool));
SVN_ERR(svn_wc__db_external_add_dir(db,
@@ -1384,7 +1461,7 @@ test_externals_store(apr_pool_t *pool)
{
svn_wc__db_status_t status;
- svn_wc__db_kind_t kind;
+ svn_node_kind_t kind;
const char *repos_root_url;
const char *repos_uuid;
const char *defining_abspath;
@@ -1401,7 +1478,7 @@ test_externals_store(apr_pool_t *pool)
pool, pool));
SVN_TEST_ASSERT(status == svn_wc__db_status_normal);
- SVN_TEST_ASSERT(kind == svn_wc__db_kind_file);
+ SVN_TEST_ASSERT(kind == svn_node_file);
SVN_TEST_STRING_ASSERT(repos_root_url, "svn://some-repos/svn");
SVN_TEST_STRING_ASSERT(repos_uuid, "not-a-uuid");
SVN_TEST_STRING_ASSERT(defining_abspath, subdir);
@@ -1432,7 +1509,7 @@ test_externals_store(apr_pool_t *pool)
pool, pool));
SVN_TEST_ASSERT(status == svn_wc__db_status_normal);
- SVN_TEST_ASSERT(kind == svn_wc__db_kind_dir);
+ SVN_TEST_ASSERT(kind == svn_node_dir);
SVN_TEST_STRING_ASSERT(repos_root_url, "svn://other-repos/nsv");
SVN_TEST_STRING_ASSERT(repos_uuid, "no-uuid-either");
SVN_TEST_STRING_ASSERT(defining_abspath, subdir);
diff --git a/subversion/tests/libsvn_wc/entries-compat.c b/subversion/tests/libsvn_wc/entries-compat.c
index eed6bca..34ad425 100644
--- a/subversion/tests/libsvn_wc/entries-compat.c
+++ b/subversion/tests/libsvn_wc/entries-compat.c
@@ -96,171 +96,171 @@ static const char * const TESTING_DATA = (
"insert into nodes values ("
" 1, '', 0, null, 1, '', 1, 'normal',"
" null, null, 'dir', '()', 'infinity', null, null, 1, " TIME_1s ", '" AUTHOR_1 "',"
- " null, null, null, null);"
+ " null, null, null, null, null);"
"insert into nodes values ("
" 1, 'A', 0, '', 1, 'A', 1, 'normal',"
" null, null, 'file', '()', null, '$sha1$" SHA1_1 "', null, 1, " TIME_1s ", '" AUTHOR_1 "',"
- " 10, null, null, null);"
+ " 10, null, null, null, null);"
"insert into nodes values ("
" 1, 'B', 0, '', 1, 'B', null, 'excluded',"
" null, null, 'symlink', null, null, null, null, null, null, null,"
- " null, null, null, null);"
+ " null, null, null, null, null);"
"insert into nodes values ("
- " 1, 'C', 0, '', 1, 'C', null, 'absent',"
+ " 1, 'C', 0, '', 1, 'C', null, 'server-excluded',"
" null, null, 'unknown', null, null, null, null, null, null, null,"
- " null, null, null, null);"
+ " null, null, null, null, null);"
"insert into nodes values ("
" 1, 'D', 0, '', 1, 'D', null, 'not-present',"
" null, null, 'unknown', null, null, null, null, null, null, null,"
- " null, null, null, null);"
+ " null, null, null, null, null);"
"insert into nodes values ("
" 1, 'E', 0, '', 1, 'E', null, 'incomplete',"
" null, null, 'unknown', null, null, null, null, null, null, null,"
- " null, null, null, null);"
+ " null, null, null, null, null);"
"insert into nodes values ("
" 1, 'F', 0, '', 1, 'F', 1, 'normal',"
" null, null, 'file', '()', null, '$sha1$" SHA1_1 "', null, 1, " TIME_1s ", '" AUTHOR_1 "',"
- " 15, null, null, null);"
+ " 15, null, null, null, null);"
"insert into nodes values ("
" 1, 'G', 0, '', 2, 'G-alt', 1, 'normal',"
" null, null, 'file', '()', null, '$sha1$" SHA1_1 "', null, 2, " TIME_2s ", '" AUTHOR_2 "',"
- " 15, null, null, null);"
+ " 15, null, null, null, null);"
"insert into nodes values ("
" 1, 'H', 0, '', 1, 'H', 1, 'normal',"
" null, null, 'symlink', '()', null, null, 'H-target', 1, " TIME_1s ", '" AUTHOR_1 "',"
- " null, null, null, null);"
+ " null, null, null, null, null);"
"insert into nodes values ("
" 1, 'I', 0, '', 1, 'I', 1, 'normal',"
" null, null, 'dir', '()', null, null, null, 1, " TIME_1s ", '" AUTHOR_1 "',"
- " null, null, null, null);"
+ " null, null, null, null, null);"
"insert into nodes values ("
" 1, 'J', 0, '', 1, 'J', 1, 'normal',"
" null, null, 'dir', '()', null, null, null, 1, " TIME_1s ", '" AUTHOR_1 "',"
- " null, null, null, null);"
+ " null, null, null, null, null);"
"insert into nodes values ("
" 1, 'J/J-e', 0, 'J', 1, 'J/J-e', 1, 'normal',"
" null, null, 'dir', '()', null, null, null, 1, " TIME_1s ", '" AUTHOR_1 "',"
- " null, null, null, null);"
+ " null, null, null, null, null);"
"insert into nodes values ("
" 1, 'J/J-e/J-e-a', 0, 'J/J-e', 1, 'J/J-e/J-e-a', 1, 'normal',"
" null, null, 'file', '()', null, '$sha1$" SHA1_1 "', null, 1, " TIME_1s ", '" AUTHOR_1 "',"
- " 15, null, null, null);"
+ " 15, null, null, null, null);"
"insert into nodes values ("
" 1, 'J/J-e/J-e-b', 0, 'J/J-e', 1, 'J/J-e/J-e-b', 1, 'normal',"
" null, null, 'dir', '()', null, null, null, 1, " TIME_1s ", '" AUTHOR_1 "',"
- " null, null, null, null);"
+ " null, null, null, null, null);"
"insert into nodes values ("
" 1, 'J/J-e/J-e-b/Jeba', 0, 'J/J-e/J-e-b', 1, 'J/J-e/J-e-b/Jeba', 1, 'normal',"
" null, null, 'file', '()', null, '$sha1$" SHA1_1 "', null, 1, " TIME_1s ", '" AUTHOR_1 "',"
- " 15, null, null, null);"
+ " 15, null, null, null, null);"
"insert into nodes values ("
" 1, 'J/J-f', 0, 'J', 1, 'J/J-f', 1, 'normal',"
" null, null, 'dir', '()', null, null, null, 1, " TIME_1s ", '" AUTHOR_1 "',"
- " null, null, null, null);"
+ " null, null, null, null, null);"
"insert into nodes values ("
" 1, 'J/J-f/J-f-a', 0, 'J/J-f', 1, 'J/J-f/J-f-a', 1, 'normal',"
" null, null, 'dir', '()', null, null, null, 1, " TIME_1s ", '" AUTHOR_1 "',"
- " null, null, null, null);"
+ " null, null, null, null, null);"
"insert into nodes values ("
" 1, 'K', 0, '', 1, 'K', 1, 'normal',"
" null, null, 'dir', '()', null, null, null, 1, " TIME_1s ", '" AUTHOR_1 "',"
- " null, null, null, null);"
+ " null, null, null, null, null);"
"insert into nodes values ("
" 1, 'K/K-a', 0, 'K', 1, 'K/K-a', 1, 'normal',"
" null, null, 'file', '()', null, '$sha1$" SHA1_1 "', null, 1, " TIME_1s ", '" AUTHOR_1 "',"
- " 15, null, null, null);"
+ " 15, null, null, null, null);"
"insert into nodes values ("
" 1, 'K/K-b', 0, 'K', 1, 'K/K-b', 1, 'normal',"
" null, null, 'file', '()', null, '$sha1$" SHA1_1 "', null, 1, " TIME_1s ", '" AUTHOR_1 "',"
- " 15, null, null, null);"
+ " 15, null, null, null, null);"
""
/* Load data into NODES table;
### op_depths have not been calculated by me yet;
the value 1 is just 'good enough' to make the nodes WORKING nodes. */
"insert into nodes values ("
" 1, 'I', 1, '', 2, 'some/dir', 2, 'normal',"
- " 0, null, 'dir', '()', 'immediates', null, null, 2, " TIME_2s ", '" AUTHOR_2 "',"
- " null, null, null, null);"
+ " null, null, 'dir', '()', 'immediates', null, null, 2, " TIME_2s ", '" AUTHOR_2 "',"
+ " null, null, null, null, null);"
"insert into nodes values ("
" 1, 'J', 1, '', null, null, null, 'normal',"
- " 0, null, 'dir', '()', 'immediates', null, null, null, null, null,"
- " null, null, null, null);"
+ " null, null, 'dir', '()', 'immediates', null, null, null, null, null,"
+ " null, null, null, null, null);"
"insert into nodes values ("
" 1, 'J/J-a', 1, 'J', null, null, null, 'normal',"
- " 0, null, 'file', '()', null, null, null, null, null, null,"
- " null, null, null, null);"
+ " null, null, 'file', '()', null, null, null, null, null, null,"
+ " null, null, null, null, null);"
"insert into nodes values ("
" 1, 'J/J-b', 1, 'J', 2, 'some/dir', 2, 'normal',"
- " 0, null, 'dir', '()', 'infinity', null, null, 2, " TIME_2s ", '" AUTHOR_2 "',"
- " null, null, null, null);"
+ " null, null, 'dir', '()', 'infinity', null, null, 2, " TIME_2s ", '" AUTHOR_2 "',"
+ " null, null, null, null, null);"
"insert into nodes values ("
" 1, 'J/J-b/J-b-a', 1, 'J/J-b', 2, 'another/dir', 2, 'normal',"
- " 0, null, 'dir', '()', 'infinity', null, null, 2, " TIME_2s ", '" AUTHOR_2 "',"
- " null, null, null, null);"
+ " null, null, 'dir', '()', 'infinity', null, null, 2, " TIME_2s ", '" AUTHOR_2 "',"
+ " null, null, null, null, null);"
"insert into nodes values ("
" 1, 'J/J-b/J-b-b', 1, 'J/J-b', null, null, null, 'normal',"
- " 0, null, 'file', '()', null, null, null, null, null, null,"
- " null, null, null, null);"
+ " null, null, 'file', '()', null, null, null, null, null, null,"
+ " null, null, null, null, null);"
"insert into nodes values ("
" 1, 'J/J-c', 1, 'J', null, null, null, 'not-present',"
- " 0, null, 'dir', '()', null, null, null, null, null, null,"
- " null, null, null, null);"
+ " null, null, 'dir', '()', null, null, null, null, null, null,"
+ " null, null, null, null, null);"
"insert into nodes values ("
" 1, 'J/J-c/J-c-a', 1, 'J/J-c', null, null, null, 'not-present',"
- " 0, null, 'dir', '()', null, null, null, null, null, null,"
- " null, null, null, null);"
+ " null, null, 'dir', '()', null, null, null, null, null, null,"
+ " null, null, null, null, null);"
"insert into nodes values ("
" 1, 'J/J-d', 1, 'J', 2, 'moved/file', 2, 'normal',"
" 1, null, 'file', '()', null, '$sha1$" SHA1_1 "', null, 2, " TIME_2s ", '" AUTHOR_2 "',"
- " 10, null, null, null);"
+ " 10, null, null, null, null);"
"insert into nodes values ("
" 1, 'J/J-e', 1, 'J', null, null, null, 'not-present',"
- " 0, 'other/place', 'dir', '()', null, null, null, null, null, null,"
- " null, null, null, null);"
+ " null, 'other/place', 'dir', '()', null, null, null, null, null, null,"
+ " null, null, null, null, null);"
"insert into nodes values ("
" 1, 'J/J-e/J-e-a', 1, 'J/J-e', null, null, null, 'not-present',"
- " 0, null, 'file', '()', null, null, null, null, null, null,"
- " null, null, null, null);"
+ " null, null, 'file', '()', null, null, null, null, null, null,"
+ " null, null, null, null, null);"
"insert into nodes values ("
" 1, 'J/J-e/J-e-b', 1, 'J/J-e', null, null, null, 'not-present',"
- " 0, null, 'dir', '()', null, null, null, null, null, null,"
- " null, null, null, null);"
+ " null, null, 'dir', '()', null, null, null, null, null, null,"
+ " null, null, null, null, null);"
"insert into nodes values ("
" 1, 'J/J-e/J-e-b/Jeba', 1, 'J/J-e/J-e-b', null, null, null, 'base-deleted',"
- " 0, null, 'file', '()', null, null, null, null, null, null,"
- " null, null, null, null);"
+ " null, null, 'file', '()', null, null, null, null, null, null,"
+ " null, null, null, null, null);"
"insert into nodes values ("
" 1, 'J/J-f', 1, 'J', null, null, null, 'normal',"
- " 0, null, 'dir', '()', 'immediates', null, null, null, null, null,"
- " null, null, null, null);"
+ " null, null, 'dir', '()', 'immediates', null, null, null, null, null,"
+ " null, null, null, null, null);"
"insert into nodes values ("
" 1, 'J/J-f/J-f-a', 1, 'J/J-f', null, null, null, 'base-deleted',"
- " 0, null, 'dir', '()', 'immediates', null, null, null, null, null,"
- " null, null, null, null);"
+ " null, null, 'dir', '()', 'immediates', null, null, null, null, null,"
+ " null, null, null, null, null);"
"insert into nodes values ("
" 1, 'K', 1, '', null, null, null, 'base-deleted',"
- " 0, null, 'dir', '()', null, null, null, null, null, null,"
- " null, null, null, null);"
+ " null, null, 'dir', '()', null, null, null, null, null, null,"
+ " null, null, null, null, null);"
"insert into nodes values ("
" 1, 'K/K-a', 1, 'K', null, null, null, 'base-deleted',"
- " 0, null, 'file', '()', null, null, null, null, null, null,"
- " null, null, null, null);"
+ " null, null, 'file', '()', null, null, null, null, null, null,"
+ " null, null, null, null, null);"
"insert into nodes values ("
" 1, 'K/K-b', 1, 'K', null, null, null, 'base-deleted',"
- " 0, 'moved/away', 'file', '()', null, null, null, null, null, null,"
- " null, null, null, null);"
+ " null, 'moved/away', 'file', '()', null, null, null, null, null, null,"
+ " null, null, null, null, null);"
"insert into nodes values ("
" 1, 'L', 1, '', null, null, null, 'normal',"
- " 0, null, 'dir', '()', 'immediates', null, null, null, null, null,"
- " null, null, null, null);"
+ " null, null, 'dir', '()', 'immediates', null, null, null, null, null,"
+ " null, null, null, null, null);"
"insert into nodes values ("
" 1, 'L/L-a', 1, 'L', null, null, null, 'not-present',"
- " 0, null, 'dir', '()', 'immediates', null, null, null, null, null,"
- " null, null, null, null);"
+ " null, null, 'dir', '()', 'immediates', null, null, null, null, null,"
+ " null, null, null, null, null);"
"insert into nodes values ("
" 1, 'L/L-a/L-a-a', 1, 'L/L-a', null, null, null, 'not-present',"
- " 0, null, 'dir', '()', 'immediates', null, null, null, null, null,"
- " null, null, null, null);"
+ " null, null, 'dir', '()', 'immediates', null, null, null, null, null,"
+ " null, null, null, null, null);"
"insert into actual_node values ("
" 1, 'I', '', null, null, null, null, null, 'changelist', null, "
" null, null, null, null, null);"
@@ -274,11 +274,11 @@ static const char * const TESTING_DATA = (
"insert into nodes values ("
" 1, 'M', 0, '', 1, 'M', 1, 'normal', "
" null, null, 'dir', '()', null, null, null, 1, " TIME_1s ", '" AUTHOR_1 "', "
- " null, null, null, null);"
+ " null, null, null, null, null);"
"insert into nodes values ("
" 1, 'M/M-a', 0, 'M', 1, 'M/M-a', 1, 'not-present', "
" null, null, 'file', '()', null, null, null, 1, null, null, "
- " null, null, null, null);"
+ " null, null, null, null, null);"
);
@@ -295,7 +295,7 @@ static const char * const M_TESTING_DATA = (
"insert into nodes values ("
" 1, '', 0, null, 1, 'M', 1, 'normal',"
" null, null, 'dir', '()', 'infinity', null, null, 1, " TIME_1s ", '" AUTHOR_1 "',"
- " null, null, null, null);"
+ " null, null, null, null, null);"
);
@@ -332,10 +332,12 @@ create_open(svn_wc__db_t **db,
pool));
SVN_ERR(svn_wc__db_open(db,
NULL /* config */,
- TRUE /* auto_upgrade */,
+ FALSE /* not_upgraded_ok */,
TRUE /* enforce_empty_wq */,
pool, pool));
+ svn_test_add_dir_cleanup(*local_abspath);
+
return SVN_NO_ERROR;
}
@@ -601,12 +603,14 @@ test_access_baton_like_locking(apr_pool_t *pool)
{
const char *url, *repos_root_url, *repos_uuid;
const char *subdir = svn_dirent_join(local_abspath, "sub-wc", pool);
+ const char *repos_relpath;
svn_boolean_t is_root;
- SVN_ERR(svn_wc__node_get_url(&url, wc_ctx, local_abspath, pool, pool));
- SVN_ERR(svn_wc__node_get_repos_info(&repos_root_url, &repos_uuid,
+ SVN_ERR(svn_wc__node_get_repos_info(NULL, &repos_relpath,
+ &repos_root_url, &repos_uuid,
wc_ctx, local_abspath,
pool, pool));
+ url = svn_path_url_add_component2(repos_root_url, repos_relpath, pool);
SVN_ERR(svn_io_make_dir_recursively(subdir, pool));
SVN_ERR(svn_wc_ensure_adm3(subdir, repos_uuid,
@@ -614,13 +618,13 @@ test_access_baton_like_locking(apr_pool_t *pool)
repos_root_url, 0, svn_depth_infinity,
pool));
- SVN_ERR(svn_wc__check_wc_root(&is_root, NULL, NULL, wc_ctx->db, subdir,
- pool));
+ SVN_ERR(svn_wc__db_is_switched(&is_root, NULL, NULL, wc_ctx->db, subdir,
+ pool));
SVN_TEST_ASSERT(is_root);
- SVN_ERR(svn_wc__check_wc_root(&is_root, NULL, NULL, wc_ctx2->db, subdir,
- pool));
+ SVN_ERR(svn_wc__db_is_switched(&is_root, NULL, NULL, wc_ctx2->db, subdir,
+ pool));
/* This test was added to show a regression where the next check failed,
but the check above this succeeded */
diff --git a/subversion/tests/libsvn_wc/op-depth-test.c b/subversion/tests/libsvn_wc/op-depth-test.c
index c385c39..39afcf4 100644
--- a/subversion/tests/libsvn_wc/op-depth-test.c
+++ b/subversion/tests/libsvn_wc/op-depth-test.c
@@ -35,6 +35,7 @@
#include "svn_wc.h"
#include "svn_client.h"
#include "svn_hash.h"
+#include "svn_sorts.h"
#include "utils.h"
@@ -43,6 +44,8 @@
#include "private/svn_dep_compat.h"
#include "../../libsvn_wc/wc.h"
#include "../../libsvn_wc/wc_db.h"
+#include "../../libsvn_wc/workqueue.h"
+#include "../../libsvn_wc/conflicts.h"
#define SVN_WC__I_AM_WC_DB
#include "../../libsvn_wc/wc_db_private.h"
@@ -52,6 +55,14 @@
#pragma warning(disable: 4221) /* nonstandard extension used */
#endif
+/* This macro is not available in 1.8.x, but let's just use it here */
+#ifndef SVN_VA_NULL
+struct svn_null_pointer_constant_stdarg_sentinel_t;
+
+/** Null pointer constant used as a sentinel in variable argument lists. */
+#define SVN_VA_NULL ((struct svn_null_pointer_constant_stdarg_sentinel_t*)0)
+#endif
+
/* Compare strings, like strcmp but either or both may be NULL which
* compares equal to NULL and not equal to any non-NULL string. */
static int
@@ -77,260 +88,14 @@ open_wc_db(svn_sqlite__db_t **sdb,
apr_pool_t *scratch_pool)
{
SVN_ERR(svn_wc__db_util_open_db(sdb, wc_root_abspath, "wc.db",
- svn_sqlite__mode_readwrite, my_statements,
+ svn_sqlite__mode_readwrite,
+ FALSE /* exclusive */, my_statements,
result_pool, scratch_pool));
return SVN_NO_ERROR;
}
/* ---------------------------------------------------------------------- */
-/* Functions for easy manipulation of a WC. Paths given to these functions
- * can be relative to the WC root as stored in the WC baton. */
-
-/* Return the abspath of PATH which is absolute or relative to the WC in B. */
-#define wc_path(b, path) (svn_dirent_join((b)->wc_abspath, (path), (b)->pool))
-
-/* Create a file on disk at PATH, with TEXT as its content. */
-static void
-file_write(svn_test__sandbox_t *b, const char *path, const char *text)
-{
- FILE *f = fopen(wc_path(b, path), "w");
- fputs(text, f);
- fclose(f);
-}
-
-/* Schedule for addition the single node that exists on disk at PATH,
- * non-recursively. */
-static svn_error_t *
-wc_add(svn_test__sandbox_t *b, const char *path)
-{
- const char *parent_abspath;
- path = wc_path(b, path);
- parent_abspath = svn_dirent_dirname(path, b->pool);
- SVN_ERR(svn_wc__acquire_write_lock(NULL, b->wc_ctx, parent_abspath, FALSE,
- b->pool, b->pool));
- SVN_ERR(svn_wc_add_from_disk(b->wc_ctx, path, NULL, NULL, b->pool));
- SVN_ERR(svn_wc__release_write_lock(b->wc_ctx, parent_abspath, b->pool));
- return SVN_NO_ERROR;
-}
-
-/* Create a single directory on disk. */
-static svn_error_t *
-disk_mkdir(svn_test__sandbox_t *b, const char *path)
-{
- path = wc_path(b, path);
- SVN_ERR(svn_io_dir_make(path, APR_FPROT_OS_DEFAULT, b->pool));
- return SVN_NO_ERROR;
-}
-
-/* Create a single directory on disk and schedule it for addition. */
-static svn_error_t *
-wc_mkdir(svn_test__sandbox_t *b, const char *path)
-{
- SVN_ERR(disk_mkdir(b, path));
- SVN_ERR(wc_add(b, path));
- return SVN_NO_ERROR;
-}
-
-#if 0 /* not used */
-/* Copy the file or directory tree FROM_PATH to TO_PATH which must not exist
- * beforehand. */
-static svn_error_t *
-disk_copy(svn_test__sandbox_t *b, const char *from_path, const char *to_path)
-{
- const char *to_dir, *to_name;
- from_path = wc_path(b, from_path);
- to_path = wc_path(b, to_path);
- svn_dirent_split(&to_dir, &to_name, to_path, b->pool);
- return svn_io_copy_dir_recursively(from_path, to_dir, to_name,
- FALSE, NULL, NULL, b->pool);
-}
-#endif
-
-/* Copy the WC file or directory tree FROM_PATH to TO_PATH which must not
- * exist beforehand. */
-static svn_error_t *
-wc_copy(svn_test__sandbox_t *b, const char *from_path, const char *to_path)
-{
- from_path = wc_path(b, from_path);
- to_path = wc_path(b, to_path);
- return svn_wc_copy3(b->wc_ctx, from_path, to_path, FALSE,
- NULL, NULL, NULL, NULL, b->pool);
-}
-
-/* Revert a WC file or directory tree at PATH */
-static svn_error_t *
-wc_revert(svn_test__sandbox_t *b, const char *path, svn_depth_t depth)
-{
- const char *abspath = wc_path(b, path);
- const char *dir_abspath = svn_dirent_dirname(abspath, b->pool);
- const char *lock_root_abspath;
-
- SVN_ERR(svn_wc__acquire_write_lock(&lock_root_abspath, b->wc_ctx,
- dir_abspath, FALSE /* lock_anchor */,
- b->pool, b->pool));
- SVN_ERR(svn_wc_revert4(b->wc_ctx, abspath, depth, FALSE, NULL,
- NULL, NULL, /* cancel baton + func */
- NULL, NULL, /* notify baton + func */
- b->pool));
- SVN_ERR(svn_wc__release_write_lock(b->wc_ctx, lock_root_abspath, b->pool));
- return SVN_NO_ERROR;
-}
-
-static svn_error_t *
-wc_delete(svn_test__sandbox_t *b, const char *path)
-{
- const char *abspath = wc_path(b, path);
- const char *dir_abspath = svn_dirent_dirname(abspath, b->pool);
- const char *lock_root_abspath;
-
- SVN_ERR(svn_wc__acquire_write_lock(&lock_root_abspath, b->wc_ctx,
- dir_abspath, FALSE,
- b->pool, b->pool));
- SVN_ERR(svn_wc_delete4(b->wc_ctx, abspath, FALSE, TRUE,
- NULL, NULL, /* cancel baton + func */
- NULL, NULL, /* notify baton + func */
- b->pool));
- SVN_ERR(svn_wc__release_write_lock(b->wc_ctx, lock_root_abspath, b->pool));
- return SVN_NO_ERROR;
-}
-
-static svn_error_t *
-wc_exclude(svn_test__sandbox_t *b, const char *path)
-{
- const char *abspath = wc_path(b, path);
- const char *lock_root_abspath;
-
- SVN_ERR(svn_wc__acquire_write_lock(&lock_root_abspath, b->wc_ctx,
- abspath, TRUE,
- b->pool, b->pool));
- SVN_ERR(svn_wc_exclude(b->wc_ctx, abspath,
- NULL, NULL, /* cancel baton + func */
- NULL, NULL, /* notify baton + func */
- b->pool));
- SVN_ERR(svn_wc__release_write_lock(b->wc_ctx, lock_root_abspath, b->pool));
- return SVN_NO_ERROR;
-}
-
-static svn_error_t *
-wc_commit(svn_test__sandbox_t *b, const char *path)
-{
- svn_client_ctx_t *ctx;
- apr_array_header_t *targets = apr_array_make(b->pool, 1,
- sizeof(const char *));
-
- APR_ARRAY_PUSH(targets, const char *) = wc_path(b, path);
- SVN_ERR(svn_client_create_context(&ctx, b->pool));
- return svn_client_commit5(targets, svn_depth_infinity,
- FALSE, FALSE, TRUE, /* keep locks/cl's/use_ops*/
- NULL, NULL, NULL, NULL, ctx, b->pool);
-}
-
-static svn_error_t *
-wc_update(svn_test__sandbox_t *b, const char *path, svn_revnum_t revnum)
-{
- svn_client_ctx_t *ctx;
- apr_array_header_t *result_revs;
- apr_array_header_t *paths = apr_array_make(b->pool, 1,
- sizeof(const char *));
- svn_opt_revision_t revision;
- revision.kind = svn_opt_revision_number;
- revision.value.number = revnum;
-
- APR_ARRAY_PUSH(paths, const char *) = wc_path(b, path);
- SVN_ERR(svn_client_create_context(&ctx, b->pool));
- return svn_client_update4(&result_revs, paths, &revision, svn_depth_infinity,
- TRUE, FALSE, FALSE, FALSE, FALSE,
- ctx, b->pool);
-}
-
-static svn_error_t *
-wc_resolved(svn_test__sandbox_t *b, const char *path)
-{
- svn_client_ctx_t *ctx;
-
- SVN_ERR(svn_client_create_context(&ctx, b->pool));
- return svn_client_resolved(wc_path(b, path), TRUE, ctx, b->pool);
-}
-
-static svn_error_t *
-wc_move(svn_test__sandbox_t *b, const char *src, const char *dst)
-{
- svn_client_ctx_t *ctx;
- apr_array_header_t *paths = apr_array_make(b->pool, 1,
- sizeof(const char *));
-
- SVN_ERR(svn_client_create_context(&ctx, b->pool));
- APR_ARRAY_PUSH(paths, const char *) = wc_path(b, src);
- return svn_client_move6(paths, wc_path(b, dst),
- FALSE, FALSE, NULL, NULL, NULL, ctx, b->pool);
-}
-
-static svn_error_t *
-wc_propset(svn_test__sandbox_t *b,
- const char *name,
- const char *value,
- const char *path)
-{
- svn_client_ctx_t *ctx;
- apr_array_header_t *paths = apr_array_make(b->pool, 1,
- sizeof(const char *));
-
- SVN_ERR(svn_client_create_context(&ctx, b->pool));
- APR_ARRAY_PUSH(paths, const char *) = wc_path(b, path);
- return svn_client_propset_local(name, svn_string_create(value, b->pool),
- paths, svn_depth_empty, TRUE, NULL, ctx,
- b->pool);
-}
-
-/* Create the Greek tree on disk in the WC, and commit it. */
-static svn_error_t *
-add_and_commit_greek_tree(svn_test__sandbox_t *b)
-{
- const char *greek_tree_dirs[8] =
- {
- "A",
- "A/B",
- "A/B/E",
- "A/B/F",
- "A/C",
- "A/D",
- "A/D/G",
- "A/D/H"
- };
- const char *greek_tree_files[12][2] =
- {
- { "iota", "This is the file 'iota'.\n" },
- { "A/mu", "This is the file 'mu'.\n" },
- { "A/B/lambda", "This is the file 'lambda'.\n" },
- { "A/B/E/alpha", "This is the file 'alpha'.\n" },
- { "A/B/E/beta", "This is the file 'beta'.\n" },
- { "A/D/gamma", "This is the file 'gamma'.\n" },
- { "A/D/G/pi", "This is the file 'pi'.\n" },
- { "A/D/G/rho", "This is the file 'rho'.\n" },
- { "A/D/G/tau", "This is the file 'tau'.\n" },
- { "A/D/H/chi", "This is the file 'chi'.\n" },
- { "A/D/H/psi", "This is the file 'psi'.\n" },
- { "A/D/H/omega", "This is the file 'omega'.\n" }
- };
- int i;
-
- for (i = 0; i < 8; i++)
- SVN_ERR(wc_mkdir(b, greek_tree_dirs[i]));
-
- for (i = 0; i < 12; i++)
- {
- file_write(b, greek_tree_files[i][0], greek_tree_files[i][1]);
- SVN_ERR(wc_add(b, greek_tree_files[i][0]));
- }
-
- SVN_ERR(wc_commit(b, ""));
-
- return SVN_NO_ERROR;
-}
-
-
-/* ---------------------------------------------------------------------- */
/* Functions for comparing expected and found WC DB data. */
/* Some of the fields from a NODES table row. */
@@ -341,36 +106,87 @@ typedef struct nodes_row_t {
svn_revnum_t repo_revnum;
const char *repo_relpath;
svn_boolean_t file_external;
+ const char *moved_to;
+ svn_boolean_t moved_here;
+ const char *props; /* comma-separated list of prop names */
} nodes_row_t;
/* Macro for filling in the REPO_* fields of a non-base NODES_ROW_T
* that has no copy-from info. */
-#define NO_COPY_FROM SVN_INVALID_REVNUM, NULL
+#define NO_COPY_FROM SVN_INVALID_REVNUM, NULL, FALSE
+#define MOVED_HERE FALSE, NULL, TRUE
+#define NOT_MOVED FALSE, NULL, FALSE
+
+/* Return a comma-separated list of the prop names in PROPS, in lexically
+ * ascending order, or NULL if PROPS is empty or NULL. (Here, we don't
+ * care about the difference between 'has no props' and 'can't have props',
+ * and we choose to represent both of those as NULL.) */
+static const char *
+props_hash_to_text(apr_hash_t *props, apr_pool_t *pool)
+{
+ apr_array_header_t *props_sorted;
+ svn_stringbuf_t *str;
+ int i;
+
+ if (! props)
+ return NULL;
+
+ str = svn_stringbuf_create_empty(pool);
+ props_sorted = svn_sort__hash(props, svn_sort_compare_items_lexically, pool);
+ for (i = 0; i < props_sorted->nelts; i++)
+ {
+ const svn_sort__item_t *item
+ = &APR_ARRAY_IDX(props_sorted, i, svn_sort__item_t);
+
+ if (str->len)
+ svn_stringbuf_appendbyte(str, ',');
+ svn_stringbuf_appendcstr(str, item->key);
+ }
+ return str->len ? str->data : NULL;
+}
/* Return a human-readable string representing ROW. */
static const char *
print_row(const nodes_row_t *row,
apr_pool_t *result_pool)
{
- const char *file_external_str;
+ const char *file_external_str, *moved_here_str, *moved_to_str, *props;
if (row == NULL)
return "(null)";
+ if (row->moved_to)
+ moved_to_str = apr_psprintf(result_pool, ", moved-to %s", row->moved_to);
+ else
+ moved_to_str = "";
+
+ if (row->moved_here)
+ moved_here_str = ", moved-here";
+ else
+ moved_here_str = "";
+
if (row->file_external)
file_external_str = ", file-external";
else
file_external_str = "";
-
+
+ if (row->props)
+ props = apr_psprintf(result_pool, ", p=(%s)", row->props);
+ else
+ props = "";
+
if (row->repo_revnum == SVN_INVALID_REVNUM)
- return apr_psprintf(result_pool, "%d, %s, %s%s",
+ return apr_psprintf(result_pool, "%d, \"%s\", \"%s\"%s%s%s%s",
row->op_depth, row->local_relpath, row->presence,
- file_external_str);
+ moved_here_str, moved_to_str,
+ file_external_str, props);
else
- return apr_psprintf(result_pool, "%d, %s, %s, from ^/%s@%d%s",
+ return apr_psprintf(result_pool, "%d, \"%s\", \"%s\", %s ^/%s@%d%s%s%s%s",
row->op_depth, row->local_relpath, row->presence,
+ row->op_depth == 0 ? "base" : "copyfrom",
row->repo_relpath, (int)row->repo_revnum,
- file_external_str);
+ moved_here_str, moved_to_str,
+ file_external_str, props);
}
/* A baton to pass through svn_hash_diff() to compare_nodes_rows(). */
@@ -412,7 +228,14 @@ compare_nodes_rows(const void *key, apr_ssize_t klen,
else if (expected->repo_revnum != found->repo_revnum
|| (strcmp_null(expected->repo_relpath, found->repo_relpath) != 0)
|| (strcmp_null(expected->presence, found->presence) != 0)
- || (expected->file_external != found->file_external))
+ || (expected->file_external != found->file_external)
+ || (expected->moved_here != found->moved_here)
+ || (expected->moved_to && !found->moved_to)
+ || (!expected->moved_to && found->moved_to)
+ || (expected->moved_to
+ && strcmp(expected->moved_to, found->moved_to))
+ || (expected->props != NULL
+ && strcmp_null(expected->props, found->props) != 0))
{
b->errors = svn_error_createf(
SVN_ERR_TEST_FAILED, b->errors,
@@ -441,10 +264,13 @@ check_db_rows(svn_test__sandbox_t *b,
int i;
svn_sqlite__stmt_t *stmt;
static const char *const statements[] = {
- "SELECT op_depth, presence, local_relpath, revision, repos_path, "
- " file_external "
- "FROM nodes "
- "WHERE local_relpath = ?1 OR local_relpath LIKE ?2",
+ "SELECT op_depth, nodes.presence, nodes.local_relpath, revision,"
+ " repos_path, file_external, def_local_relpath, moved_to, moved_here,"
+ " properties"
+ " FROM nodes "
+ " LEFT OUTER JOIN externals"
+ " ON nodes.local_relpath = externals.local_relpath"
+ " WHERE nodes.local_relpath = ?1 OR nodes.local_relpath LIKE ?2",
NULL };
#define STMT_SELECT_NODES_INFO 0
@@ -470,6 +296,7 @@ check_db_rows(svn_test__sandbox_t *b,
{
const char *key;
nodes_row_t *row = apr_palloc(b->pool, sizeof(*row));
+ apr_hash_t *props_hash;
row->op_depth = svn_sqlite__column_int(stmt, 0);
row->presence = svn_sqlite__column_text(stmt, 1, b->pool);
@@ -477,6 +304,15 @@ check_db_rows(svn_test__sandbox_t *b,
row->repo_revnum = svn_sqlite__column_revnum(stmt, 3);
row->repo_relpath = svn_sqlite__column_text(stmt, 4, b->pool);
row->file_external = !svn_sqlite__column_is_null(stmt, 5);
+ if (row->file_external && svn_sqlite__column_is_null(stmt, 6))
+ comparison_baton.errors
+ = svn_error_createf(SVN_ERR_TEST_FAILED, comparison_baton.errors,
+ "incomplete {%s}", print_row(row, b->pool));
+ row->moved_to = svn_sqlite__column_text(stmt, 7, b->pool);
+ row->moved_here = svn_sqlite__column_boolean(stmt, 8);
+ SVN_ERR(svn_sqlite__column_properties(&props_hash, stmt, 9,
+ b->pool, b->pool));
+ row->props = props_hash_to_text(props_hash, b->pool);
key = apr_psprintf(b->pool, "%d %s", row->op_depth, row->local_relpath);
apr_hash_set(found_hash, key, APR_HASH_KEY_STRING, row);
@@ -534,22 +370,22 @@ struct copy_subtest_t
static svn_error_t *
wc_wc_copies(svn_test__sandbox_t *b)
{
- SVN_ERR(add_and_commit_greek_tree(b));
+ SVN_ERR(sbox_add_and_commit_greek_tree(b));
/* Create the various kinds of source node which will be copied */
- file_write(b, source_added_file, "New file");
- SVN_ERR(wc_add(b, source_added_file));
- SVN_ERR(wc_mkdir(b, source_added_dir));
- SVN_ERR(wc_mkdir(b, source_added_dir2));
+ sbox_file_write(b, source_added_file, "New file");
+ SVN_ERR(sbox_wc_add(b, source_added_file));
+ SVN_ERR(sbox_wc_mkdir(b, source_added_dir));
+ SVN_ERR(sbox_wc_mkdir(b, source_added_dir2));
- SVN_ERR(wc_copy(b, source_base_file, source_copied_file));
- SVN_ERR(wc_copy(b, source_base_dir, source_copied_dir));
+ SVN_ERR(sbox_wc_copy(b, source_base_file, source_copied_file));
+ SVN_ERR(sbox_wc_copy(b, source_base_dir, source_copied_dir));
/* Delete some nodes so that we can test copying onto these paths */
- SVN_ERR(wc_delete(b, "A/D/gamma"));
- SVN_ERR(wc_delete(b, "A/D/G"));
+ SVN_ERR(sbox_wc_delete(b, "A/D/gamma"));
+ SVN_ERR(sbox_wc_delete(b, "A/D/G"));
/* Test copying various things */
@@ -647,11 +483,7 @@ wc_wc_copies(svn_test__sandbox_t *b)
/* Perform each subtest in turn. */
for (subtest = subtests; subtest->from_path; subtest++)
{
- SVN_ERR(svn_wc_copy3(b->wc_ctx,
- wc_path(b, subtest->from_path),
- wc_path(b, subtest->to_path),
- FALSE /* metadata_only */,
- NULL, NULL, NULL, NULL, b->pool));
+ SVN_ERR(sbox_wc_copy(b, subtest->from_path, subtest->to_path));
SVN_ERR(check_db_rows(b, subtest->to_path, subtest->expected));
}
}
@@ -664,14 +496,14 @@ wc_wc_copies(svn_test__sandbox_t *b)
static svn_error_t *
repo_wc_copies(svn_test__sandbox_t *b)
{
- SVN_ERR(add_and_commit_greek_tree(b));
+ SVN_ERR(sbox_add_and_commit_greek_tree(b));
/* Delete some nodes so that we can test copying onto these paths */
- SVN_ERR(wc_delete(b, "A/B/lambda"));
- SVN_ERR(wc_delete(b, "A/D/gamma"));
- SVN_ERR(wc_delete(b, "A/D/G"));
- SVN_ERR(wc_delete(b, "A/D/H"));
+ SVN_ERR(sbox_wc_delete(b, "A/B/lambda"));
+ SVN_ERR(sbox_wc_delete(b, "A/D/gamma"));
+ SVN_ERR(sbox_wc_delete(b, "A/D/G"));
+ SVN_ERR(sbox_wc_delete(b, "A/D/H"));
/* Test copying various things */
@@ -761,7 +593,7 @@ repo_wc_copies(svn_test__sandbox_t *b)
source.peg_revision = &rev;
APR_ARRAY_PUSH(sources, svn_client_copy_source_t *) = &source;
SVN_ERR(svn_client_copy6(sources,
- wc_path(b, subtest->to_path),
+ sbox_wc_path(b, subtest->to_path),
FALSE, FALSE, FALSE,
NULL, NULL, NULL, ctx, b->pool));
}
@@ -801,7 +633,7 @@ test_reverts(const svn_test_opts_t *opts, apr_pool_t *pool)
/* Implement revert tests below, now that we have a wc with lots of
copy-changes */
- SVN_ERR(wc_revert(&b, "A/B/D-added", svn_depth_infinity));
+ SVN_ERR(sbox_wc_revert(&b, "A/B/D-added", svn_depth_infinity));
SVN_ERR(check_db_rows(&b, "A/B/D-added", no_node_rows_expected));
return SVN_NO_ERROR;
@@ -813,10 +645,10 @@ test_deletes(const svn_test_opts_t *opts, apr_pool_t *pool)
svn_test__sandbox_t b;
SVN_ERR(svn_test__sandbox_create(&b, "deletes", opts, pool));
- SVN_ERR(add_and_commit_greek_tree(&b));
+ SVN_ERR(sbox_add_and_commit_greek_tree(&b));
- file_write(&b, "A/B/E/new-file", "New file");
- SVN_ERR(wc_add(&b, "A/B/E/new-file"));
+ sbox_file_write(&b, "A/B/E/new-file", "New file");
+ SVN_ERR(sbox_wc_add(&b, "A/B/E/new-file"));
{
nodes_row_t rows[] = {
{ 4, "A/B/E/new-file", "normal", NO_COPY_FROM },
@@ -825,7 +657,7 @@ test_deletes(const svn_test_opts_t *opts, apr_pool_t *pool)
SVN_ERR(check_db_rows(&b, "A/B/E/new-file", rows));
}
- SVN_ERR(wc_delete(&b, "A/B/E/alpha"));
+ SVN_ERR(sbox_wc_delete(&b, "A/B/E/alpha"));
{
nodes_row_t rows[] = {
{ 0, "A/B/E/alpha", "normal", 1, "A/B/E/alpha" },
@@ -835,7 +667,7 @@ test_deletes(const svn_test_opts_t *opts, apr_pool_t *pool)
SVN_ERR(check_db_rows(&b, "A/B/E/alpha", rows));
}
- SVN_ERR(wc_delete(&b, "A/B/F"));
+ SVN_ERR(sbox_wc_delete(&b, "A/B/F"));
{
nodes_row_t rows[] = {
{ 0, "A/B/F", "normal", 1, "A/B/F" },
@@ -845,7 +677,7 @@ test_deletes(const svn_test_opts_t *opts, apr_pool_t *pool)
SVN_ERR(check_db_rows(&b, "A/B/F", rows));
}
- SVN_ERR(wc_delete(&b, "A/B"));
+ SVN_ERR(sbox_wc_delete(&b, "A/B"));
{
nodes_row_t rows[] = {
{ 0, "A/B", "normal", 1, "A/B", },
@@ -874,11 +706,11 @@ test_adds(const svn_test_opts_t *opts, apr_pool_t *pool)
svn_test__sandbox_t b;
SVN_ERR(svn_test__sandbox_create(&b, "adds", opts, pool));
- SVN_ERR(add_and_commit_greek_tree(&b));
+ SVN_ERR(sbox_add_and_commit_greek_tree(&b));
/* add file */
- file_write(&b, "new-file", "New file");
- SVN_ERR(wc_add(&b, "new-file"));
+ sbox_file_write(&b, "new-file", "New file");
+ SVN_ERR(sbox_wc_add(&b, "new-file"));
{
nodes_row_t rows[] = {
{ 1, "new-file", "normal", NO_COPY_FROM },
@@ -887,8 +719,8 @@ test_adds(const svn_test_opts_t *opts, apr_pool_t *pool)
}
/* add dir */
- SVN_ERR(wc_mkdir(&b, "new-dir"));
- SVN_ERR(wc_mkdir(&b, "new-dir/D2"));
+ SVN_ERR(sbox_wc_mkdir(&b, "new-dir"));
+ SVN_ERR(sbox_wc_mkdir(&b, "new-dir/D2"));
{
nodes_row_t rows[] = {
{ 1, "new-dir", "normal", NO_COPY_FROM },
@@ -898,9 +730,9 @@ test_adds(const svn_test_opts_t *opts, apr_pool_t *pool)
}
/* replace file */
- SVN_ERR(wc_delete(&b, "iota"));
- file_write(&b, "iota", "New iota file");
- SVN_ERR(wc_add(&b, "iota"));
+ SVN_ERR(sbox_wc_delete(&b, "iota"));
+ sbox_file_write(&b, "iota", "New iota file");
+ SVN_ERR(sbox_wc_add(&b, "iota"));
{
nodes_row_t rows[] = {
{ 0, "iota", "normal", 1, "iota" },
@@ -910,9 +742,9 @@ test_adds(const svn_test_opts_t *opts, apr_pool_t *pool)
}
/* replace dir */
- SVN_ERR(wc_delete(&b, "A/B/E"));
- SVN_ERR(wc_mkdir(&b, "A/B/E"));
- SVN_ERR(wc_mkdir(&b, "A/B/E/D2"));
+ SVN_ERR(sbox_wc_delete(&b, "A/B/E"));
+ SVN_ERR(sbox_wc_mkdir(&b, "A/B/E"));
+ SVN_ERR(sbox_wc_mkdir(&b, "A/B/E/D2"));
{
nodes_row_t rows[] = {
{ 0, "A/B/E", "normal", 1, "A/B/E" },
@@ -935,12 +767,12 @@ test_adds_change_kind(const svn_test_opts_t *opts, apr_pool_t *pool)
svn_test__sandbox_t b;
SVN_ERR(svn_test__sandbox_create(&b, "adds", opts, pool));
- SVN_ERR(add_and_commit_greek_tree(&b));
+ SVN_ERR(sbox_add_and_commit_greek_tree(&b));
/* replace dir with file */
- SVN_ERR(wc_delete(&b, "A/B/E"));
- file_write(&b, "A/B/E", "New E file");
- SVN_ERR(wc_add(&b, "A/B/E"));
+ SVN_ERR(sbox_wc_delete(&b, "A/B/E"));
+ sbox_file_write(&b, "A/B/E", "New E file");
+ SVN_ERR(sbox_wc_add(&b, "A/B/E"));
{
nodes_row_t rows[] = {
{ 0, "A/B/E", "normal", 1, "A/B/E" },
@@ -954,9 +786,9 @@ test_adds_change_kind(const svn_test_opts_t *opts, apr_pool_t *pool)
}
/* replace file with dir */
- SVN_ERR(wc_delete(&b, "iota"));
- SVN_ERR(wc_mkdir(&b, "iota"));
- SVN_ERR(wc_mkdir(&b, "iota/D2"));
+ SVN_ERR(sbox_wc_delete(&b, "iota"));
+ SVN_ERR(sbox_wc_mkdir(&b, "iota"));
+ SVN_ERR(sbox_wc_mkdir(&b, "iota/D2"));
{
nodes_row_t rows[] = {
{ 0, "iota", "normal", 1, "iota" },
@@ -976,10 +808,10 @@ test_delete_of_copies(const svn_test_opts_t *opts, apr_pool_t *pool)
svn_test__sandbox_t b;
SVN_ERR(svn_test__sandbox_create(&b, "deletes_of_copies", opts, pool));
- SVN_ERR(add_and_commit_greek_tree(&b));
- SVN_ERR(wc_copy(&b, "A/B", "A/B-copied"));
+ SVN_ERR(sbox_add_and_commit_greek_tree(&b));
+ SVN_ERR(sbox_wc_copy(&b, "A/B", "A/B-copied"));
- SVN_ERR(wc_delete(&b, "A/B-copied/E"));
+ SVN_ERR(sbox_wc_delete(&b, "A/B-copied/E"));
{
nodes_row_t rows[] = {
{ 2, "A/B-copied/E", "normal", 1, "A/B/E" },
@@ -993,7 +825,7 @@ test_delete_of_copies(const svn_test_opts_t *opts, apr_pool_t *pool)
SVN_ERR(check_db_rows(&b, "A/B-copied/E", rows));
}
- SVN_ERR(wc_copy(&b, "A/D/G", "A/B-copied/E"));
+ SVN_ERR(sbox_wc_copy(&b, "A/D/G", "A/B-copied/E"));
{
nodes_row_t rows[] = {
{ 2, "A/B-copied/E", "normal", 1, "A/B/E" },
@@ -1010,7 +842,7 @@ test_delete_of_copies(const svn_test_opts_t *opts, apr_pool_t *pool)
SVN_ERR(check_db_rows(&b, "A/B-copied/E", rows));
}
- SVN_ERR(wc_delete(&b, "A/B-copied/E/rho"));
+ SVN_ERR(sbox_wc_delete(&b, "A/B-copied/E/rho"));
{
nodes_row_t rows[] = {
{ 2, "A/B-copied/E", "normal", 1, "A/B/E" },
@@ -1028,7 +860,7 @@ test_delete_of_copies(const svn_test_opts_t *opts, apr_pool_t *pool)
SVN_ERR(check_db_rows(&b, "A/B-copied/E", rows));
}
- SVN_ERR(wc_delete(&b, "A/B-copied/E"));
+ SVN_ERR(sbox_wc_delete(&b, "A/B-copied/E"));
{
nodes_row_t rows[] = {
{ 2, "A/B-copied/E", "normal", 1, "A/B/E" },
@@ -1042,9 +874,9 @@ test_delete_of_copies(const svn_test_opts_t *opts, apr_pool_t *pool)
SVN_ERR(check_db_rows(&b, "A/B-copied/E", rows));
}
- SVN_ERR(wc_copy(&b, "A/B", "A/B-copied/E"));
+ SVN_ERR(sbox_wc_copy(&b, "A/B", "A/B-copied/E"));
- SVN_ERR(wc_delete(&b, "A/B-copied/E/F"));
+ SVN_ERR(sbox_wc_delete(&b, "A/B-copied/E/F"));
{
nodes_row_t rows[] = {
{ 3, "A/B-copied/E/F", "normal", 1, "A/B/F" },
@@ -1054,7 +886,7 @@ test_delete_of_copies(const svn_test_opts_t *opts, apr_pool_t *pool)
SVN_ERR(check_db_rows(&b, "A/B-copied/E/F", rows));
}
- SVN_ERR(wc_delete(&b, "A/B-copied"));
+ SVN_ERR(sbox_wc_delete(&b, "A/B-copied"));
{
nodes_row_t rows[] = { { 0 } };
SVN_ERR(check_db_rows(&b, "A/B-copied", rows));
@@ -1070,11 +902,11 @@ test_delete_with_base(const svn_test_opts_t *opts, apr_pool_t *pool)
svn_test__sandbox_t b;
SVN_ERR(svn_test__sandbox_create(&b, "deletes_with_base", opts, pool));
- SVN_ERR(add_and_commit_greek_tree(&b));
- SVN_ERR(wc_delete(&b, "A/B/E/beta"));
- SVN_ERR(wc_commit(&b, ""));
+ SVN_ERR(sbox_add_and_commit_greek_tree(&b));
+ SVN_ERR(sbox_wc_delete(&b, "A/B/E/beta"));
+ SVN_ERR(sbox_wc_commit(&b, ""));
- SVN_ERR(wc_delete(&b, "A/B/E"));
+ SVN_ERR(sbox_wc_delete(&b, "A/B/E"));
{
nodes_row_t rows[] = {
{ 0, "A/B/E", "normal", 1, "A/B/E"},
@@ -1087,9 +919,9 @@ test_delete_with_base(const svn_test_opts_t *opts, apr_pool_t *pool)
SVN_ERR(check_db_rows(&b, "A/B/E", rows));
}
- SVN_ERR(wc_copy(&b, "A/B/F", "A/B/E"));
- SVN_ERR(wc_copy(&b, "A/mu", "A/B/E/alpha"));
- SVN_ERR(wc_copy(&b, "A/mu", "A/B/E/beta"));
+ SVN_ERR(sbox_wc_copy(&b, "A/B/F", "A/B/E"));
+ SVN_ERR(sbox_wc_copy(&b, "A/mu", "A/B/E/alpha"));
+ SVN_ERR(sbox_wc_copy(&b, "A/mu", "A/B/E/beta"));
{
nodes_row_t rows[] = {
{ 0, "A/B/E", "normal", 1, "A/B/E"},
@@ -1105,7 +937,7 @@ test_delete_with_base(const svn_test_opts_t *opts, apr_pool_t *pool)
SVN_ERR(check_db_rows(&b, "A/B/E", rows));
}
- SVN_ERR(wc_delete(&b, "A/B/E"));
+ SVN_ERR(sbox_wc_delete(&b, "A/B/E"));
{
nodes_row_t rows[] = {
{ 0, "A/B/E", "normal", 1, "A/B/E"},
@@ -1137,16 +969,16 @@ test_delete_with_update(const svn_test_opts_t *opts, apr_pool_t *pool)
svn_test__sandbox_t b;
SVN_ERR(svn_test__sandbox_create(&b, "delete_with_update", opts, pool));
- SVN_ERR(wc_mkdir(&b, "A"));
- SVN_ERR(wc_commit(&b, ""));
- SVN_ERR(wc_mkdir(&b, "A/B"));
- SVN_ERR(wc_mkdir(&b, "A/B/C"));
- SVN_ERR(wc_commit(&b, ""));
- SVN_ERR(wc_update(&b, "", 1));
-
- SVN_ERR(wc_delete(&b, "A"));
- SVN_ERR(wc_mkdir(&b, "A"));
- SVN_ERR(wc_mkdir(&b, "A/B"));
+ SVN_ERR(sbox_wc_mkdir(&b, "A"));
+ SVN_ERR(sbox_wc_commit(&b, ""));
+ SVN_ERR(sbox_wc_mkdir(&b, "A/B"));
+ SVN_ERR(sbox_wc_mkdir(&b, "A/B/C"));
+ SVN_ERR(sbox_wc_commit(&b, ""));
+ SVN_ERR(sbox_wc_update(&b, "", 1));
+
+ SVN_ERR(sbox_wc_delete(&b, "A"));
+ SVN_ERR(sbox_wc_mkdir(&b, "A"));
+ SVN_ERR(sbox_wc_mkdir(&b, "A/B"));
{
nodes_row_t rows[] = {
{ 0, "A", "normal", 1, "A"},
@@ -1156,7 +988,7 @@ test_delete_with_update(const svn_test_opts_t *opts, apr_pool_t *pool)
};
SVN_ERR(check_db_rows(&b, "A", rows));
}
- SVN_ERR(wc_update(&b, "", 2));
+ SVN_ERR(sbox_wc_update(&b, "", 2));
{
nodes_row_t rows[] = {
{ 0, "A", "normal", 2, "A"},
@@ -1170,8 +1002,8 @@ test_delete_with_update(const svn_test_opts_t *opts, apr_pool_t *pool)
};
SVN_ERR(check_db_rows(&b, "A", rows));
}
- SVN_ERR(wc_resolved(&b, ""));
- SVN_ERR(wc_update(&b, "", 1));
+ SVN_ERR(sbox_wc_resolved(&b, ""));
+ SVN_ERR(sbox_wc_update(&b, "", 1));
{
nodes_row_t rows[] = {
{ 0, "A", "normal", 1, "A"},
@@ -1213,9 +1045,9 @@ insert_dirs(svn_test__sandbox_t *b,
if (nodes->local_relpath[0])
{
SVN_ERR(svn_sqlite__get_statement(&stmt, sdb, 2));
- SVN_ERR(svn_sqlite__bindf(stmt, "sissrs",
+ SVN_ERR(svn_sqlite__bindf(stmt, "sdssrs",
nodes->local_relpath,
- (apr_int64_t)nodes->op_depth,
+ nodes->op_depth,
nodes->presence,
nodes->repo_relpath,
nodes->repo_revnum,
@@ -1225,9 +1057,9 @@ insert_dirs(svn_test__sandbox_t *b,
else
{
SVN_ERR(svn_sqlite__get_statement(&stmt, sdb, 1));
- SVN_ERR(svn_sqlite__bindf(stmt, "sissr",
+ SVN_ERR(svn_sqlite__bindf(stmt, "sdssr",
nodes->local_relpath,
- (apr_int64_t)nodes->op_depth,
+ nodes->op_depth,
nodes->presence,
nodes->repo_relpath,
nodes->repo_revnum));
@@ -1258,7 +1090,7 @@ base_dir_insert_remove(svn_test__sandbox_t *b,
nodes_row_t *added)
{
nodes_row_t *after;
- const char *dir_abspath = wc_path(b, local_relpath);
+ const char *dir_abspath = sbox_wc_path(b, local_relpath);
int i;
apr_int64_t num_before = count_rows(before), num_added = count_rows(added);
@@ -1270,10 +1102,10 @@ base_dir_insert_remove(svn_test__sandbox_t *b,
"not-even-a-uuid", revision,
apr_hash_make(b->pool), revision,
0, NULL, NULL, svn_depth_infinity,
- NULL, NULL, FALSE, NULL, NULL,
+ NULL, NULL, FALSE, NULL, NULL, NULL,
b->pool));
- after = apr_palloc(b->pool, sizeof(*after) * (num_before + num_added + 1));
+ after = apr_palloc(b->pool, sizeof(*after) * (apr_size_t)(num_before + num_added + 1));
for (i = 0; i < num_before; ++i)
after[i] = before[i];
for (i = 0; i < num_added; ++i)
@@ -1282,7 +1114,14 @@ base_dir_insert_remove(svn_test__sandbox_t *b,
SVN_ERR(check_db_rows(b, "", after));
- SVN_ERR(svn_wc__db_base_remove(b->wc_ctx->db, dir_abspath, b->pool));
+ SVN_ERR(svn_wc__db_base_remove(b->wc_ctx->db, dir_abspath,
+ FALSE /* keep_as_Working */,
+ FALSE /* queue_deletes */,
+ FALSE /* remove_locks */,
+ SVN_INVALID_REVNUM,
+ NULL, NULL, b->pool));
+ SVN_ERR(svn_wc__wq_run(b->wc_ctx->db, dir_abspath,
+ NULL, NULL, b->pool));
SVN_ERR(check_db_rows(b, "", before));
@@ -1598,7 +1437,7 @@ temp_op_make_copy(svn_test__sandbox_t *b,
SVN_ERR(insert_dirs(b, before));
- SVN_ERR(svn_wc__db_temp_op_make_copy(b->wc_ctx->db, dir_abspath, b->pool));
+ SVN_ERR(svn_wc__db_op_make_copy(b->wc_ctx->db, dir_abspath, NULL, NULL, b->pool));
SVN_ERR(check_db_rows(b, "", after));
@@ -1698,39 +1537,39 @@ test_wc_move(const svn_test_opts_t *opts, apr_pool_t *pool)
svn_test__sandbox_t b;
SVN_ERR(svn_test__sandbox_create(&b, "wc_move", opts, pool));
- SVN_ERR(wc_mkdir(&b, "A"));
- SVN_ERR(wc_mkdir(&b, "A/B"));
- SVN_ERR(wc_mkdir(&b, "A/B/C"));
- SVN_ERR(wc_commit(&b, ""));
- SVN_ERR(wc_update(&b, "", 1));
+ SVN_ERR(sbox_wc_mkdir(&b, "A"));
+ SVN_ERR(sbox_wc_mkdir(&b, "A/B"));
+ SVN_ERR(sbox_wc_mkdir(&b, "A/B/C"));
+ SVN_ERR(sbox_wc_commit(&b, ""));
+ SVN_ERR(sbox_wc_update(&b, "", 1));
- SVN_ERR(wc_move(&b, "A/B/C", "A/B/C-move"));
+ SVN_ERR(sbox_wc_move(&b, "A/B/C", "A/B/C-move"));
{
nodes_row_t rows[] = {
{ 0, "", "normal", 1, "" },
{ 0, "A", "normal", 1, "A" },
{ 0, "A/B", "normal", 1, "A/B" },
- { 0, "A/B/C", "normal", 1, "A/B/C" },
- { 3, "A/B/C", "base-deleted", NO_COPY_FROM },
- { 3, "A/B/C-move", "normal", 1, "A/B/C" },
+ { 0, "A/B/C", "normal", 1, "A/B/C"},
+ { 3, "A/B/C", "base-deleted", NO_COPY_FROM, "A/B/C-move" },
+ { 3, "A/B/C-move", "normal", 1, "A/B/C", MOVED_HERE },
{ 0 }
};
SVN_ERR(check_db_rows(&b, "", rows));
}
- SVN_ERR(wc_move(&b, "A/B", "A/B-move"));
+ SVN_ERR(sbox_wc_move(&b, "A/B", "A/B-move"));
{
nodes_row_t rows[] = {
{ 0, "", "normal", 1, "" },
{ 0, "A", "normal", 1, "A" },
- { 0, "A/B", "normal", 1, "A/B" },
- { 0, "A/B/C", "normal", 1, "A/B/C" },
- { 2, "A/B", "base-deleted", NO_COPY_FROM },
- { 2, "A/B/C", "base-deleted", NO_COPY_FROM },
- { 2, "A/B-move", "normal", 1, "A/B" },
- { 2, "A/B-move/C", "normal", 1, "A/B/C" },
- { 3, "A/B-move/C", "base-deleted", NO_COPY_FROM },
- { 3, "A/B-move/C-move", "normal", 1, "A/B/C" },
+ { 0, "A/B", "normal", 1, "A/B"},
+ { 0, "A/B/C", "normal", 1, "A/B/C"},
+ { 2, "A/B", "base-deleted", NO_COPY_FROM, "A/B-move" },
+ { 2, "A/B/C", "base-deleted", NO_COPY_FROM},
+ { 2, "A/B-move", "normal", 1, "A/B", MOVED_HERE },
+ { 2, "A/B-move/C", "normal", 1, "A/B/C", MOVED_HERE },
+ { 3, "A/B-move/C", "base-deleted", NO_COPY_FROM, "A/B-move/C-move" },
+ { 3, "A/B-move/C-move", "normal", 1, "A/B/C", MOVED_HERE },
{ 0 }
};
SVN_ERR(check_db_rows(&b, "", rows));
@@ -1745,14 +1584,14 @@ test_mixed_rev_copy(const svn_test_opts_t *opts, apr_pool_t *pool)
svn_test__sandbox_t b;
SVN_ERR(svn_test__sandbox_create(&b, "mixed_rev_copy", opts, pool));
- SVN_ERR(wc_mkdir(&b, "A"));
- SVN_ERR(wc_commit(&b, ""));
- SVN_ERR(wc_mkdir(&b, "A/B"));
- SVN_ERR(wc_commit(&b, ""));
- SVN_ERR(wc_mkdir(&b, "A/B/C"));
- SVN_ERR(wc_commit(&b, ""));
-
- SVN_ERR(wc_copy(&b, "A", "X"));
+ SVN_ERR(sbox_wc_mkdir(&b, "A"));
+ SVN_ERR(sbox_wc_commit(&b, ""));
+ SVN_ERR(sbox_wc_mkdir(&b, "A/B"));
+ SVN_ERR(sbox_wc_commit(&b, ""));
+ SVN_ERR(sbox_wc_mkdir(&b, "A/B/C"));
+ SVN_ERR(sbox_wc_commit(&b, ""));
+
+ SVN_ERR(sbox_wc_copy(&b, "A", "X"));
{
nodes_row_t rows[] = {
{ 1, "X", "normal", 1, "A" },
@@ -1765,7 +1604,7 @@ test_mixed_rev_copy(const svn_test_opts_t *opts, apr_pool_t *pool)
SVN_ERR(check_db_rows(&b, "X", rows));
}
- SVN_ERR(wc_copy(&b, "A/B", "X/Y"));
+ SVN_ERR(sbox_wc_copy(&b, "A/B", "X/Y"));
{
nodes_row_t rows[] = {
{ 1, "X", "normal", 1, "A" },
@@ -1781,7 +1620,7 @@ test_mixed_rev_copy(const svn_test_opts_t *opts, apr_pool_t *pool)
SVN_ERR(check_db_rows(&b, "X", rows));
}
- SVN_ERR(wc_delete(&b, "X/B/C"));
+ SVN_ERR(sbox_wc_delete(&b, "X/B/C"));
{
nodes_row_t rows[] = {
{ 1, "X", "normal", 1, "A" },
@@ -1796,8 +1635,8 @@ test_mixed_rev_copy(const svn_test_opts_t *opts, apr_pool_t *pool)
SVN_ERR(check_db_rows(&b, "X", rows));
}
- SVN_ERR(wc_delete(&b, "X"));
- SVN_ERR(wc_update(&b, "A/B/C", 0));
+ SVN_ERR(sbox_wc_delete(&b, "X"));
+ SVN_ERR(sbox_wc_update(&b, "A/B/C", 0));
{
nodes_row_t rows[] = {
{ 0, "", "normal", 0, "" },
@@ -1809,7 +1648,7 @@ test_mixed_rev_copy(const svn_test_opts_t *opts, apr_pool_t *pool)
SVN_ERR(check_db_rows(&b, "", rows));
}
- SVN_ERR(wc_copy(&b, "A", "X"));
+ SVN_ERR(sbox_wc_copy(&b, "A", "X"));
{
nodes_row_t rows[] = {
{ 1, "X", "normal", 1, "A" },
@@ -1830,23 +1669,23 @@ test_delete_of_replace(const svn_test_opts_t *opts, apr_pool_t *pool)
svn_test__sandbox_t b;
SVN_ERR(svn_test__sandbox_create(&b, "delete_of_replace", opts, pool));
- SVN_ERR(wc_mkdir(&b, "A"));
- SVN_ERR(wc_mkdir(&b, "A/B"));
- SVN_ERR(wc_mkdir(&b, "A/B/C"));
- SVN_ERR(wc_mkdir(&b, "A/B/C/F"));
- SVN_ERR(wc_mkdir(&b, "A/B/C/F/K"));
- SVN_ERR(wc_mkdir(&b, "A/B/C/G"));
- SVN_ERR(wc_mkdir(&b, "A/B/C/G/K"));
- SVN_ERR(wc_commit(&b, ""));
- SVN_ERR(wc_update(&b, "", 1));
-
- SVN_ERR(wc_copy(&b, "A", "X"));
- SVN_ERR(wc_move(&b, "X/B/C/F", "X/B/C/H"));
- SVN_ERR(wc_commit(&b, ""));
- SVN_ERR(wc_update(&b, "", 2));
-
- SVN_ERR(wc_delete(&b, "A/B"));
- SVN_ERR(wc_copy(&b, "X/B", "A/B"));
+ SVN_ERR(sbox_wc_mkdir(&b, "A"));
+ SVN_ERR(sbox_wc_mkdir(&b, "A/B"));
+ SVN_ERR(sbox_wc_mkdir(&b, "A/B/C"));
+ SVN_ERR(sbox_wc_mkdir(&b, "A/B/C/F"));
+ SVN_ERR(sbox_wc_mkdir(&b, "A/B/C/F/K"));
+ SVN_ERR(sbox_wc_mkdir(&b, "A/B/C/G"));
+ SVN_ERR(sbox_wc_mkdir(&b, "A/B/C/G/K"));
+ SVN_ERR(sbox_wc_commit(&b, ""));
+ SVN_ERR(sbox_wc_update(&b, "", 1));
+
+ SVN_ERR(sbox_wc_copy(&b, "A", "X"));
+ SVN_ERR(sbox_wc_move(&b, "X/B/C/F", "X/B/C/H"));
+ SVN_ERR(sbox_wc_commit(&b, ""));
+ SVN_ERR(sbox_wc_update(&b, "", 2));
+
+ SVN_ERR(sbox_wc_delete(&b, "A/B"));
+ SVN_ERR(sbox_wc_copy(&b, "X/B", "A/B"));
{
nodes_row_t rows[] = {
{ 0, "A", "normal", 2, "A" },
@@ -1869,7 +1708,7 @@ test_delete_of_replace(const svn_test_opts_t *opts, apr_pool_t *pool)
SVN_ERR(check_db_rows(&b, "A", rows));
}
- SVN_ERR(wc_delete(&b, "A/B"));
+ SVN_ERR(sbox_wc_delete(&b, "A/B"));
{
nodes_row_t rows[] = {
{ 0, "A", "normal", 2, "A" },
@@ -1899,25 +1738,25 @@ test_del_replace_not_present(const svn_test_opts_t *opts, apr_pool_t *pool)
svn_test__sandbox_t b;
SVN_ERR(svn_test__sandbox_create(&b, "del_replace_not_present", opts, pool));
- SVN_ERR(wc_mkdir(&b, "A"));
- SVN_ERR(wc_mkdir(&b, "A/B"));
- SVN_ERR(wc_mkdir(&b, "A/B/X"));
- SVN_ERR(wc_mkdir(&b, "A/B/Y"));
- SVN_ERR(wc_mkdir(&b, "A/B/Z"));
- SVN_ERR(wc_commit(&b, ""));
-
- SVN_ERR(wc_copy(&b, "A", "X"));
- SVN_ERR(wc_mkdir(&b, "X/B/W"));
- SVN_ERR(wc_commit(&b, ""));
-
- SVN_ERR(wc_update(&b, "", 2));
- SVN_ERR(wc_update(&b, "A/B/X", 0));
- SVN_ERR(wc_update(&b, "A/B/Y", 0));
- SVN_ERR(wc_update(&b, "X/B/W", 0));
- SVN_ERR(wc_update(&b, "X/B/Y", 0));
- SVN_ERR(wc_update(&b, "X/B/Z", 0));
-
- SVN_ERR(wc_delete(&b, "A"));
+ SVN_ERR(sbox_wc_mkdir(&b, "A"));
+ SVN_ERR(sbox_wc_mkdir(&b, "A/B"));
+ SVN_ERR(sbox_wc_mkdir(&b, "A/B/X"));
+ SVN_ERR(sbox_wc_mkdir(&b, "A/B/Y"));
+ SVN_ERR(sbox_wc_mkdir(&b, "A/B/Z"));
+ SVN_ERR(sbox_wc_commit(&b, ""));
+
+ SVN_ERR(sbox_wc_copy(&b, "A", "X"));
+ SVN_ERR(sbox_wc_mkdir(&b, "X/B/W"));
+ SVN_ERR(sbox_wc_commit(&b, ""));
+
+ SVN_ERR(sbox_wc_update(&b, "", 2));
+ SVN_ERR(sbox_wc_update(&b, "A/B/X", 0));
+ SVN_ERR(sbox_wc_update(&b, "A/B/Y", 0));
+ SVN_ERR(sbox_wc_update(&b, "X/B/W", 0));
+ SVN_ERR(sbox_wc_update(&b, "X/B/Y", 0));
+ SVN_ERR(sbox_wc_update(&b, "X/B/Z", 0));
+
+ SVN_ERR(sbox_wc_delete(&b, "A"));
{
nodes_row_t rows[] = {
{ 0, "A", "normal", 2, "A" },
@@ -1933,7 +1772,7 @@ test_del_replace_not_present(const svn_test_opts_t *opts, apr_pool_t *pool)
SVN_ERR(check_db_rows(&b, "A", rows));
}
- SVN_ERR(wc_copy(&b, "X", "A"));
+ SVN_ERR(sbox_wc_copy(&b, "X", "A"));
{
nodes_row_t rows[] = {
{ 0, "A", "normal", 2, "A" },
@@ -1952,7 +1791,7 @@ test_del_replace_not_present(const svn_test_opts_t *opts, apr_pool_t *pool)
SVN_ERR(check_db_rows(&b, "A", rows));
}
- SVN_ERR(wc_delete(&b, "A"));
+ SVN_ERR(sbox_wc_delete(&b, "A"));
{
nodes_row_t rows[] = {
{ 0, "A", "normal", 2, "A" },
@@ -2091,7 +1930,7 @@ revert(svn_test__sandbox_t *b,
actual_row_t *before_actual,
actual_row_t *after_actual)
{
- const char *local_abspath = wc_path(b, local_relpath);
+ const char *local_abspath = sbox_wc_path(b, local_relpath);
svn_error_t *err;
if (!before_actual)
@@ -2202,12 +2041,10 @@ test_op_revert(const svn_test_opts_t *opts, apr_pool_t *pool)
before, before, before_actual4, after_actual4));
err = revert(&b, "A/B", svn_depth_empty,
before, before, common_actual5, common_actual5);
- SVN_TEST_ASSERT(err && err->apr_err == SVN_ERR_WC_INVALID_OPERATION_DEPTH);
- svn_error_clear(err);
+ SVN_TEST_ASSERT_ERROR(err, SVN_ERR_WC_INVALID_OPERATION_DEPTH);
err = revert(&b, "A/B/C", svn_depth_empty,
before, before, common_actual6, common_actual6);
- SVN_TEST_ASSERT(err && err->apr_err == SVN_ERR_WC_INVALID_OPERATION_DEPTH);
- svn_error_clear(err);
+ SVN_TEST_ASSERT_ERROR(err, SVN_ERR_WC_INVALID_OPERATION_DEPTH);
}
{
@@ -2260,30 +2097,24 @@ test_op_revert(const svn_test_opts_t *opts, apr_pool_t *pool)
err = revert(&b, "A/B", svn_depth_empty,
common, common, NULL, NULL);
- SVN_TEST_ASSERT(err && err->apr_err == SVN_ERR_WC_INVALID_OPERATION_DEPTH);
- svn_error_clear(err);
+ SVN_TEST_ASSERT_ERROR(err, SVN_ERR_WC_INVALID_OPERATION_DEPTH);
err = revert(&b, "A/B", svn_depth_empty,
common, common, common_actual, common_actual);
- SVN_TEST_ASSERT(err && err->apr_err == SVN_ERR_WC_INVALID_OPERATION_DEPTH);
- svn_error_clear(err);
+ SVN_TEST_ASSERT_ERROR(err, SVN_ERR_WC_INVALID_OPERATION_DEPTH);
err = revert(&b, "P", svn_depth_empty,
common, common, NULL, NULL);
- SVN_TEST_ASSERT(err && err->apr_err == SVN_ERR_WC_INVALID_OPERATION_DEPTH);
- svn_error_clear(err);
+ SVN_TEST_ASSERT_ERROR(err, SVN_ERR_WC_INVALID_OPERATION_DEPTH);
err = revert(&b, "P", svn_depth_empty,
common, common, common_actual, common_actual);
- SVN_TEST_ASSERT(err && err->apr_err == SVN_ERR_WC_INVALID_OPERATION_DEPTH);
- svn_error_clear(err);
+ SVN_TEST_ASSERT_ERROR(err, SVN_ERR_WC_INVALID_OPERATION_DEPTH);
err = revert(&b, "X", svn_depth_empty,
common, common, NULL, NULL);
- SVN_TEST_ASSERT(err && err->apr_err == SVN_ERR_WC_INVALID_OPERATION_DEPTH);
- svn_error_clear(err);
+ SVN_TEST_ASSERT_ERROR(err, SVN_ERR_WC_INVALID_OPERATION_DEPTH);
err = revert(&b, "X", svn_depth_empty,
common, common, common_actual, common_actual);
- SVN_TEST_ASSERT(err && err->apr_err == SVN_ERR_WC_INVALID_OPERATION_DEPTH);
- svn_error_clear(err);
+ SVN_TEST_ASSERT_ERROR(err, SVN_ERR_WC_INVALID_OPERATION_DEPTH);
}
{
@@ -2484,8 +2315,7 @@ test_op_revert(const svn_test_opts_t *opts, apr_pool_t *pool)
};
err = revert(&b, "A", svn_depth_empty,
common, common, NULL, NULL);
- SVN_TEST_ASSERT(err && err->apr_err == SVN_ERR_WC_INVALID_OPERATION_DEPTH);
- svn_error_clear(err);
+ SVN_TEST_ASSERT_ERROR(err, SVN_ERR_WC_INVALID_OPERATION_DEPTH);
}
{
@@ -2751,27 +2581,27 @@ test_children_of_replaced_dir(const svn_test_opts_t *opts, apr_pool_t *pool)
A_abspath = svn_dirent_join(b.wc_abspath, "A", pool);
/* Set up the base state as revision 1. */
- SVN_ERR(wc_mkdir(&b, "A"));
- SVN_ERR(wc_mkdir(&b, "A/F"));
- SVN_ERR(wc_mkdir(&b, "A/G"));
- SVN_ERR(wc_mkdir(&b, "A/H"));
- SVN_ERR(wc_mkdir(&b, "A/L"));
- SVN_ERR(wc_mkdir(&b, "X"));
- SVN_ERR(wc_mkdir(&b, "X/G"));
- SVN_ERR(wc_mkdir(&b, "X/H"));
- SVN_ERR(wc_mkdir(&b, "X/I"));
- SVN_ERR(wc_mkdir(&b, "X/K"));
- SVN_ERR(wc_commit(&b, ""));
- SVN_ERR(wc_update(&b, "", 1));
+ SVN_ERR(sbox_wc_mkdir(&b, "A"));
+ SVN_ERR(sbox_wc_mkdir(&b, "A/F"));
+ SVN_ERR(sbox_wc_mkdir(&b, "A/G"));
+ SVN_ERR(sbox_wc_mkdir(&b, "A/H"));
+ SVN_ERR(sbox_wc_mkdir(&b, "A/L"));
+ SVN_ERR(sbox_wc_mkdir(&b, "X"));
+ SVN_ERR(sbox_wc_mkdir(&b, "X/G"));
+ SVN_ERR(sbox_wc_mkdir(&b, "X/H"));
+ SVN_ERR(sbox_wc_mkdir(&b, "X/I"));
+ SVN_ERR(sbox_wc_mkdir(&b, "X/K"));
+ SVN_ERR(sbox_wc_commit(&b, ""));
+ SVN_ERR(sbox_wc_update(&b, "", 1));
/* Replace A with a copy of X. */
- SVN_ERR(wc_delete(&b, "A"));
- SVN_ERR(wc_copy(&b, "X", "A"));
+ SVN_ERR(sbox_wc_delete(&b, "A"));
+ SVN_ERR(sbox_wc_copy(&b, "X", "A"));
/* Make other local mods. */
- SVN_ERR(wc_delete(&b, "A/G"));
- SVN_ERR(wc_mkdir(&b, "A/J"));
- SVN_ERR(wc_mkdir(&b, "A/L"));
+ SVN_ERR(sbox_wc_delete(&b, "A/G"));
+ SVN_ERR(sbox_wc_mkdir(&b, "A/J"));
+ SVN_ERR(sbox_wc_mkdir(&b, "A/L"));
/* Test several variants of "list the children of 'A'". */
@@ -2819,15 +2649,17 @@ do_delete(svn_test__sandbox_t *b,
actual_row_t *actual_before,
actual_row_t *actual_after)
{
- const char *local_abspath = wc_path(b, local_relpath);
+ const char *local_abspath = sbox_wc_path(b, local_relpath);
SVN_ERR(insert_dirs(b, before));
SVN_ERR(insert_actual(b, actual_before));
SVN_ERR(check_db_rows(b, "", before));
SVN_ERR(check_db_actual(b, actual_before));
- SVN_ERR(svn_wc__db_op_delete(b->wc_ctx->db, local_abspath,
- NULL, NULL /* notification */,
+ SVN_ERR(svn_wc__db_op_delete(b->wc_ctx->db, local_abspath, NULL,
+ TRUE /* delete_dir_externals */,
+ NULL /* conflict */, NULL /* work_item */,
NULL, NULL /* cancellation */,
+ NULL, NULL /* notification */,
b->pool));
SVN_ERR(check_db_rows(b, "", after));
SVN_ERR(check_db_actual(b, actual_after));
@@ -3069,13 +2901,13 @@ test_child_replace_with_same_origin(const svn_test_opts_t *opts,
SVN_ERR(svn_test__sandbox_create(&b, "child_replace_with_same", opts, pool));
/* Set up the base state as revision 1. */
- SVN_ERR(wc_mkdir(&b, "A"));
- SVN_ERR(wc_mkdir(&b, "A/B"));
- SVN_ERR(wc_mkdir(&b, "A/B/C"));
- SVN_ERR(wc_commit(&b, ""));
- SVN_ERR(wc_update(&b, "", 1));
+ SVN_ERR(sbox_wc_mkdir(&b, "A"));
+ SVN_ERR(sbox_wc_mkdir(&b, "A/B"));
+ SVN_ERR(sbox_wc_mkdir(&b, "A/B/C"));
+ SVN_ERR(sbox_wc_commit(&b, ""));
+ SVN_ERR(sbox_wc_update(&b, "", 1));
- SVN_ERR(wc_copy(&b, "A", "X"));
+ SVN_ERR(sbox_wc_copy(&b, "A", "X"));
{
nodes_row_t rows[] = {
@@ -3087,7 +2919,7 @@ test_child_replace_with_same_origin(const svn_test_opts_t *opts,
SVN_ERR(check_db_rows(&b, "X", rows));
}
- SVN_ERR(wc_delete(&b, "X/B"));
+ SVN_ERR(sbox_wc_delete(&b, "X/B"));
{
nodes_row_t rows[] = {
{1, "X", "normal", 1, "A"},
@@ -3102,7 +2934,7 @@ test_child_replace_with_same_origin(const svn_test_opts_t *opts,
SVN_ERR(check_db_rows(&b, "X", rows));
}
- SVN_ERR(wc_copy(&b, "A/B", "X/B"));
+ SVN_ERR(sbox_wc_copy(&b, "A/B", "X/B"));
{
/* The revisions match what was here, so for an optimal commit
this should have exactly the same behavior as reverting X/B.
@@ -3138,38 +2970,38 @@ test_shadowed_update(const svn_test_opts_t *opts, apr_pool_t *pool)
SVN_ERR(svn_test__sandbox_create(&b, "shadowed_update", opts, pool));
/* Set up the base state as revision 1. */
- file_write(&b, "iota", "This is iota");
- SVN_ERR(wc_add(&b, "iota"));
- SVN_ERR(wc_commit(&b, ""));
+ sbox_file_write(&b, "iota", "This is iota");
+ SVN_ERR(sbox_wc_add(&b, "iota"));
+ SVN_ERR(sbox_wc_commit(&b, ""));
/* And create two trees in r2 */
- SVN_ERR(wc_mkdir(&b, "A"));
- SVN_ERR(wc_mkdir(&b, "A/B"));
- SVN_ERR(wc_mkdir(&b, "A/B/C"));
+ SVN_ERR(sbox_wc_mkdir(&b, "A"));
+ SVN_ERR(sbox_wc_mkdir(&b, "A/B"));
+ SVN_ERR(sbox_wc_mkdir(&b, "A/B/C"));
- SVN_ERR(wc_mkdir(&b, "K"));
- SVN_ERR(wc_mkdir(&b, "K/L"));
- SVN_ERR(wc_mkdir(&b, "K/L/M"));
- SVN_ERR(wc_commit(&b, ""));
+ SVN_ERR(sbox_wc_mkdir(&b, "K"));
+ SVN_ERR(sbox_wc_mkdir(&b, "K/L"));
+ SVN_ERR(sbox_wc_mkdir(&b, "K/L/M"));
+ SVN_ERR(sbox_wc_commit(&b, ""));
/* And change something in r3 */
- file_write(&b, "iota", "This is a new iota");
- SVN_ERR(wc_commit(&b, ""));
+ sbox_file_write(&b, "iota", "This is a new iota");
+ SVN_ERR(sbox_wc_commit(&b, ""));
/* And delete C & M */
- SVN_ERR(wc_delete(&b, "A/B/C"));
- SVN_ERR(wc_delete(&b, "K/L/M"));
- SVN_ERR(wc_commit(&b, ""));
+ SVN_ERR(sbox_wc_delete(&b, "A/B/C"));
+ SVN_ERR(sbox_wc_delete(&b, "K/L/M"));
+ SVN_ERR(sbox_wc_commit(&b, ""));
/* And now create the shadowed situation */
- SVN_ERR(wc_update(&b, "", 2));
- SVN_ERR(wc_copy(&b, "A", "A_tmp"));
- SVN_ERR(wc_update(&b, "", 1));
- SVN_ERR(wc_move(&b, "A_tmp", "A"));
+ SVN_ERR(sbox_wc_update(&b, "", 2));
+ SVN_ERR(sbox_wc_copy(&b, "A", "A_tmp"));
+ SVN_ERR(sbox_wc_update(&b, "", 1));
+ SVN_ERR(sbox_wc_move(&b, "A_tmp", "A"));
- SVN_ERR(wc_mkdir(&b, "K"));
- SVN_ERR(wc_mkdir(&b, "K/L"));
- SVN_ERR(wc_mkdir(&b, "K/L/M"));
+ SVN_ERR(sbox_wc_mkdir(&b, "K"));
+ SVN_ERR(sbox_wc_mkdir(&b, "K/L"));
+ SVN_ERR(sbox_wc_mkdir(&b, "K/L/M"));
/* Verify situation before update */
{
@@ -3190,7 +3022,7 @@ test_shadowed_update(const svn_test_opts_t *opts, apr_pool_t *pool)
}
/* And now bring in A and K below the local information */
- SVN_ERR(wc_update(&b, "", 3));
+ SVN_ERR(sbox_wc_update(&b, "", 3));
{
nodes_row_t rows[] = {
@@ -3223,9 +3055,9 @@ test_shadowed_update(const svn_test_opts_t *opts, apr_pool_t *pool)
}
/* Update again to remove C and M */
- SVN_ERR(wc_resolved(&b, "A"));
- SVN_ERR(wc_resolved(&b, "K"));
- SVN_ERR(wc_update(&b, "", 4));
+ SVN_ERR(sbox_wc_resolved(&b, "A"));
+ SVN_ERR(sbox_wc_resolved(&b, "K"));
+ SVN_ERR(sbox_wc_update(&b, "", 4));
{
nodes_row_t rows[] = {
@@ -3255,11 +3087,11 @@ test_shadowed_update(const svn_test_opts_t *opts, apr_pool_t *pool)
}
/* Update again to bring C and M back */
- SVN_ERR(wc_resolved(&b, "A"));
- SVN_ERR(wc_resolved(&b, "K"));
- SVN_ERR(wc_update(&b, "", 3));
+ SVN_ERR(sbox_wc_resolved(&b, "A"));
+ SVN_ERR(sbox_wc_resolved(&b, "K"));
+ SVN_ERR(sbox_wc_update(&b, "", 3));
- SVN_ERR(wc_delete(&b, "K/L/M"));
+ SVN_ERR(sbox_wc_delete(&b, "K/L/M"));
{
nodes_row_t rows[] = {
{0, "", "normal", 3, ""},
@@ -3289,13 +3121,13 @@ test_shadowed_update(const svn_test_opts_t *opts, apr_pool_t *pool)
}
/* Resolve conflict on K and go back to r1 */
- SVN_ERR(wc_revert(&b, "K", svn_depth_infinity));
- SVN_ERR(wc_update(&b, "", 1));
+ SVN_ERR(sbox_wc_revert(&b, "K", svn_depth_infinity));
+ SVN_ERR(sbox_wc_update(&b, "", 1));
- SVN_ERR(wc_mkdir(&b, "K"));
- SVN_ERR(wc_mkdir(&b, "K/L"));
+ SVN_ERR(sbox_wc_mkdir(&b, "K"));
+ SVN_ERR(sbox_wc_mkdir(&b, "K/L"));
- SVN_ERR(wc_update(&b, "", 3));
+ SVN_ERR(sbox_wc_update(&b, "", 3));
{
nodes_row_t rows[] = {
@@ -3316,10 +3148,10 @@ test_shadowed_update(const svn_test_opts_t *opts, apr_pool_t *pool)
}
/* Update the shadowed K/L/M to r4 where they do not exit */
- SVN_ERR(wc_resolved(&b, "K"));
- SVN_ERR(wc_update(&b, "K/L/M", 4));
- SVN_ERR(wc_resolved(&b, "A"));
- SVN_ERR(wc_update(&b, "A/B/C", 4));
+ SVN_ERR(sbox_wc_resolved(&b, "K"));
+ SVN_ERR(sbox_wc_update(&b, "K/L/M", 4));
+ SVN_ERR(sbox_wc_resolved(&b, "A"));
+ SVN_ERR(sbox_wc_update(&b, "A/B/C", 4));
{
nodes_row_t rows[] = {
@@ -3361,24 +3193,24 @@ test_copy_of_deleted(const svn_test_opts_t *opts, apr_pool_t *pool)
svn_test__sandbox_t b;
SVN_ERR(svn_test__sandbox_create(&b, "copy_of_deleted", opts, pool));
- SVN_ERR(add_and_commit_greek_tree(&b));
+ SVN_ERR(sbox_add_and_commit_greek_tree(&b));
- /* Recreate the test scenario from copy_tests.py copy_wc_url_with_absent */
+ /* Recreate the test scenario from copy_tests.py copy_wc_url_with_server_excluded */
/* Delete A/B */
- SVN_ERR(wc_delete(&b, "A/B"));
+ SVN_ERR(sbox_wc_delete(&b, "A/B"));
/* A/no not-present but in HEAD */
- SVN_ERR(wc_copy(&b, "A/mu", "A/no"));
- SVN_ERR(wc_commit(&b, "A/no"));
- SVN_ERR(wc_update(&b, "A/no", 1));
+ SVN_ERR(sbox_wc_copy(&b, "A/mu", "A/no"));
+ SVN_ERR(sbox_wc_commit(&b, "A/no"));
+ SVN_ERR(sbox_wc_update(&b, "A/no", 1));
/* A/mu not-present and not in HEAD */
- SVN_ERR(wc_delete(&b, "A/mu"));
- SVN_ERR(wc_commit(&b, "A/mu"));
+ SVN_ERR(sbox_wc_delete(&b, "A/mu"));
+ SVN_ERR(sbox_wc_commit(&b, "A/mu"));
/* A/D excluded */
- SVN_ERR(wc_exclude(&b, "A/D"));
+ SVN_ERR(sbox_wc_exclude(&b, "A/D"));
/* This should have created this structure */
{
@@ -3408,7 +3240,7 @@ test_copy_of_deleted(const svn_test_opts_t *opts, apr_pool_t *pool)
SVN_ERR(check_db_rows(&b, "A", rows));
}
- SVN_ERR(wc_copy(&b, "A", "A_copied"));
+ SVN_ERR(sbox_wc_copy(&b, "A", "A_copied"));
/* I would expect this behavior, as this copies all layers where possible
instead of just constructing a top level layer with not-present nodes
@@ -3451,12 +3283,12 @@ test_case_rename(const svn_test_opts_t *opts, apr_pool_t *pool)
apr_hash_t *dirents;
SVN_ERR(svn_test__sandbox_create(&b, "case_rename", opts, pool));
- SVN_ERR(add_and_commit_greek_tree(&b));
+ SVN_ERR(sbox_add_and_commit_greek_tree(&b));
- SVN_ERR(wc_move(&b, "A", "a"));
- SVN_ERR(wc_move(&b, "iota", "iotA"));
+ SVN_ERR(sbox_wc_move(&b, "A", "a"));
+ SVN_ERR(sbox_wc_move(&b, "iota", "iotA"));
- SVN_ERR(svn_io_get_dirents3(&dirents, wc_path(&b, ""), TRUE, pool, pool));
+ SVN_ERR(svn_io_get_dirents3(&dirents, sbox_wc_path(&b, ""), TRUE, pool, pool));
/* A shouldn't be there, but a should */
SVN_TEST_ASSERT(apr_hash_get(dirents, "a", APR_HASH_KEY_STRING));
@@ -3474,14 +3306,14 @@ commit_file_external(const svn_test_opts_t *opts, apr_pool_t *pool)
svn_test__sandbox_t b;
SVN_ERR(svn_test__sandbox_create(&b, "commit_file_external", opts, pool));
- file_write(&b, "f", "this is f\n");
- SVN_ERR(wc_add(&b, "f"));
- SVN_ERR(wc_propset(&b, "svn:externals", "^/f g", ""));
- SVN_ERR(wc_commit(&b, ""));
- SVN_ERR(wc_update(&b, "", 1));
- file_write(&b, "g", "this is f\nmodified via g\n");
- SVN_ERR(wc_commit(&b, ""));
- SVN_ERR(wc_update(&b, "", 2));
+ sbox_file_write(&b, "f", "this is f\n");
+ SVN_ERR(sbox_wc_add(&b, "f"));
+ SVN_ERR(sbox_wc_propset(&b, "svn:externals", "^/f g", ""));
+ SVN_ERR(sbox_wc_commit(&b, ""));
+ SVN_ERR(sbox_wc_update(&b, "", 1));
+ sbox_file_write(&b, "g", "this is f\nmodified via g\n");
+ SVN_ERR(sbox_wc_commit(&b, ""));
+ SVN_ERR(sbox_wc_update(&b, "", 2));
{
nodes_row_t rows[] = {
@@ -3496,6 +3328,196 @@ commit_file_external(const svn_test_opts_t *opts, apr_pool_t *pool)
return SVN_NO_ERROR;
}
+static svn_error_t *
+revert_file_externals(const svn_test_opts_t *opts, apr_pool_t *pool)
+{
+ svn_test__sandbox_t b;
+
+ SVN_ERR(svn_test__sandbox_create(&b, "revert_file_externals", opts, pool));
+ sbox_file_write(&b, "f", "this is f\n");
+ SVN_ERR(sbox_wc_add(&b, "f"));
+ SVN_ERR(sbox_wc_propset(&b, "svn:externals", "^/f g", ""));
+ SVN_ERR(sbox_wc_commit(&b, ""));
+ SVN_ERR(sbox_wc_update(&b, "", 1));
+ SVN_ERR(sbox_wc_propset(&b, "svn:externals", "^/f h", ""));
+ SVN_ERR(sbox_wc_mkdir(&b, "A"));
+ SVN_ERR(sbox_wc_propset(&b, "svn:externals", "^/f g", "A"));
+ {
+ nodes_row_t rows[] = {
+ { 0, "", "normal", 1, "" },
+ { 0, "f", "normal", 1, "f" },
+ { 0, "g", "normal", 1, "f", TRUE },
+ { 1, "A", "normal", NO_COPY_FROM },
+ { 0 }
+ };
+ SVN_ERR(check_db_rows(&b, "", rows));
+ }
+
+ SVN_ERR(sbox_wc_update(&b, "", 1));
+ {
+ nodes_row_t rows[] = {
+ { 0, "", "normal", 1, "" },
+ { 0, "f", "normal", 1, "f" },
+ { 1, "A", "normal", NO_COPY_FROM },
+ { 0, "h", "normal", 1, "f", TRUE },
+ { 0, "A/g", "normal", 1, "f", TRUE },
+ { 0 }
+ };
+ SVN_ERR(check_db_rows(&b, "", rows));
+ }
+
+ SVN_ERR(sbox_wc_revert(&b, "", svn_depth_infinity));
+ {
+ nodes_row_t rows[] = {
+ { 0, "", "normal", 1, "" },
+ { 0, "f", "normal", 1, "f" },
+ { 0, "h", "normal", 1, "f", TRUE },
+ { 0, "A/g", "normal", 1, "f", TRUE },
+ { 0 }
+ };
+ SVN_ERR(check_db_rows(&b, "", rows));
+ }
+
+ SVN_ERR(sbox_wc_update(&b, "", 1));
+ {
+ nodes_row_t rows[] = {
+ { 0, "", "normal", 1, "" },
+ { 0, "f", "normal", 1, "f" },
+ { 0, "g", "normal", 1, "f", TRUE },
+ { 0 }
+ };
+ SVN_ERR(check_db_rows(&b, "", rows));
+ }
+
+ return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+copy_file_externals(const svn_test_opts_t *opts, apr_pool_t *pool)
+{
+ svn_test__sandbox_t b;
+
+ SVN_ERR(svn_test__sandbox_create(&b, "copy_file_externals", opts, pool));
+ sbox_file_write(&b, "f", "this is f\n");
+ SVN_ERR(sbox_wc_add(&b, "f"));
+ SVN_ERR(sbox_wc_mkdir(&b, "A"));
+ SVN_ERR(sbox_wc_propset(&b, "svn:externals", "^/f g", "A"));
+ SVN_ERR(sbox_wc_commit(&b, ""));
+ SVN_ERR(sbox_wc_mkdir(&b, "A/B"));
+ SVN_ERR(sbox_wc_propset(&b, "svn:externals", "^/f g", "A/B"));
+ SVN_ERR(sbox_wc_update(&b, "", 1));
+ {
+ nodes_row_t rows[] = {
+ { 0, "", "normal", 1, "" },
+ { 0, "f", "normal", 1, "f" },
+ { 0, "A", "normal", 1, "A" },
+ { 2, "A/B", "normal", NO_COPY_FROM },
+ { 0, "A/g", "normal", 1, "f", TRUE },
+ { 0, "A/B/g", "normal", 1, "f", TRUE },
+ { 0 }
+ };
+ SVN_ERR(check_db_rows(&b, "", rows));
+ }
+
+ SVN_ERR(sbox_wc_copy(&b, "A", "X"));
+ {
+ nodes_row_t rows[] = {
+ { 0, "", "normal", 1, "" },
+ { 0, "f", "normal", 1, "f" },
+ { 0, "A", "normal", 1, "A" },
+ { 2, "A/B", "normal", NO_COPY_FROM },
+ { 0, "A/g", "normal", 1, "f", TRUE },
+ { 0, "A/B/g", "normal", 1, "f", TRUE },
+ { 1, "X", "normal", 1, "A" },
+ { 2, "X/B", "normal", NO_COPY_FROM },
+ { 0 }
+ };
+ SVN_ERR(check_db_rows(&b, "", rows));
+ }
+
+ SVN_ERR(sbox_wc_update(&b, "", 1));
+ {
+ nodes_row_t rows[] = {
+ { 0, "", "normal", 1, "" },
+ { 0, "f", "normal", 1, "f" },
+ { 0, "A", "normal", 1, "A" },
+ { 2, "A/B", "normal", NO_COPY_FROM },
+ { 0, "A/g", "normal", 1, "f", TRUE },
+ { 0, "A/B/g", "normal", 1, "f", TRUE },
+ { 1, "X", "normal", 1, "A" },
+ { 2, "X/B", "normal", NO_COPY_FROM },
+ { 0, "X/g", "normal", 1, "f", TRUE },
+ { 0, "X/B/g", "normal", 1, "f", TRUE },
+ { 0 }
+ };
+ SVN_ERR(check_db_rows(&b, "", rows));
+ }
+
+ SVN_ERR(sbox_wc_delete(&b, "X"));
+ {
+ nodes_row_t rows[] = {
+ { 0, "", "normal", 1, "" },
+ { 0, "f", "normal", 1, "f" },
+ { 0, "A", "normal", 1, "A" },
+ { 2, "A/B", "normal", NO_COPY_FROM },
+ { 0, "A/g", "normal", 1, "f", TRUE },
+ { 0, "A/B/g", "normal", 1, "f", TRUE },
+ { 0 }
+ };
+ SVN_ERR(check_db_rows(&b, "", rows));
+ }
+
+ SVN_ERR(sbox_wc_update(&b, "", 1));
+ {
+ nodes_row_t rows[] = {
+ { 0, "", "normal", 1, "" },
+ { 0, "f", "normal", 1, "f" },
+ { 0, "A", "normal", 1, "A" },
+ { 2, "A/B", "normal", NO_COPY_FROM },
+ { 0, "A/g", "normal", 1, "f", TRUE },
+ { 0, "A/B/g", "normal", 1, "f", TRUE },
+ { 0 }
+ };
+ SVN_ERR(check_db_rows(&b, "", rows));
+ }
+
+ return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+copy_wc_wc_server_excluded(const svn_test_opts_t *opts, apr_pool_t *pool)
+{
+ svn_test__sandbox_t b;
+ nodes_row_t before[] = {
+ {0, "", "normal", 1, ""},
+ {0, "A", "normal", 1, "A"},
+ {0, "A/B", "normal", 1, "A/B"},
+ {0, "A/B/E", "server-excluded", 1, "A/B/E"},
+ {0}
+ };
+ nodes_row_t after[] = {
+ {0, "", "normal", 1, ""},
+ {0, "A", "normal", 1, "A"},
+ {0, "A/B", "normal", 1, "A/B"},
+ {0, "A/B/E", "server-excluded", 1, "A/B/E"},
+ {1, "X", "normal", 1, "A"},
+ {1, "X/B", "normal", 1, "A/B"},
+ {1, "X/B/E", "incomplete", 1, "A/B/E"},
+ {0}
+ };
+ svn_error_t *err;
+
+ SVN_ERR(svn_test__sandbox_create(&b, "copy_wc_wc_server_excluded", opts, pool));
+ SVN_ERR(insert_dirs(&b, before));
+ SVN_ERR(check_db_rows(&b, "", before));
+ SVN_ERR(sbox_disk_mkdir(&b, "A"));
+ err = sbox_wc_copy(&b, "A", "X");
+ SVN_TEST_ASSERT_ERROR(err, SVN_ERR_WC_PATH_UNEXPECTED_STATUS);
+ SVN_ERR(check_db_rows(&b, "", after));
+
+ return SVN_NO_ERROR;
+}
+
/* Issue 4040 */
static svn_error_t *
incomplete_switch(const svn_test_opts_t *opts, apr_pool_t *pool)
@@ -3504,17 +3526,17 @@ incomplete_switch(const svn_test_opts_t *opts, apr_pool_t *pool)
SVN_ERR(svn_test__sandbox_create(&b, "incomplete_switch", opts, pool));
- SVN_ERR(wc_mkdir(&b, "A"));
- SVN_ERR(wc_mkdir(&b, "A/B"));
- SVN_ERR(wc_mkdir(&b, "A/B/C"));
- SVN_ERR(wc_mkdir(&b, "A/B/C/D"));
- SVN_ERR(wc_commit(&b, ""));
- SVN_ERR(wc_copy(&b, "A", "X"));
- SVN_ERR(wc_commit(&b, ""));
- SVN_ERR(wc_copy(&b, "A", "X/A"));
- SVN_ERR(wc_commit(&b, ""));
- SVN_ERR(wc_delete(&b, "X/A"));
- SVN_ERR(wc_commit(&b, ""));
+ SVN_ERR(sbox_wc_mkdir(&b, "A"));
+ SVN_ERR(sbox_wc_mkdir(&b, "A/B"));
+ SVN_ERR(sbox_wc_mkdir(&b, "A/B/C"));
+ SVN_ERR(sbox_wc_mkdir(&b, "A/B/C/D"));
+ SVN_ERR(sbox_wc_commit(&b, ""));
+ SVN_ERR(sbox_wc_copy(&b, "A", "X"));
+ SVN_ERR(sbox_wc_commit(&b, ""));
+ SVN_ERR(sbox_wc_copy(&b, "A", "X/A"));
+ SVN_ERR(sbox_wc_commit(&b, ""));
+ SVN_ERR(sbox_wc_delete(&b, "X/A"));
+ SVN_ERR(sbox_wc_commit(&b, ""));
{
/* Interrupted switch from A@1 to X@3 */
@@ -3529,7 +3551,7 @@ incomplete_switch(const svn_test_opts_t *opts, apr_pool_t *pool)
{0}
};
- nodes_row_t after_update[] = {
+ nodes_row_t after_update[] = {
{0, "", "normal", 4, "X"},
{0, "B", "normal", 4, "A/B"},
{0, "B/C", "normal", 4, "A/B/C"},
@@ -3539,13 +3561,5466 @@ incomplete_switch(const svn_test_opts_t *opts, apr_pool_t *pool)
SVN_ERR(insert_dirs(&b, before));
SVN_ERR(check_db_rows(&b, "", before));
- SVN_ERR(wc_update(&b, "", 4));
+ SVN_ERR(sbox_wc_update(&b, "", 4));
SVN_ERR(check_db_rows(&b, "", after_update));
}
return SVN_NO_ERROR;
}
+static svn_error_t *
+nested_moves_child_first(const svn_test_opts_t *opts, apr_pool_t *pool)
+{
+ svn_test__sandbox_t b;
+
+ SVN_ERR(svn_test__sandbox_create(&b, "nested_moves_child_first", opts, pool));
+
+ SVN_ERR(sbox_wc_mkdir(&b, "A"));
+ SVN_ERR(sbox_wc_mkdir(&b, "A/B"));
+ SVN_ERR(sbox_wc_mkdir(&b, "A/B/C"));
+ SVN_ERR(sbox_wc_commit(&b, ""));
+ SVN_ERR(sbox_wc_update(&b, "", 1));
+
+ {
+ nodes_row_t nodes[] = {
+ {0, "", "normal", 1, ""},
+ {0, "A", "normal", 1, "A"},
+ {0, "A/B", "normal", 1, "A/B"},
+ {0, "A/B/C", "normal", 1, "A/B/C"},
+ {0}
+ };
+ SVN_ERR(check_db_rows(&b, "", nodes));
+ }
+ SVN_ERR(sbox_wc_move(&b, "A/B/C", "A/B/C2"));
+ {
+ nodes_row_t nodes[] = {
+ {0, "", "normal", 1, ""},
+ {0, "A", "normal", 1, "A"},
+ {0, "A/B", "normal", 1, "A/B"},
+ {0, "A/B/C", "normal", 1, "A/B/C"},
+ {3, "A/B/C", "base-deleted", NO_COPY_FROM, "A/B/C2"},
+ {3, "A/B/C2", "normal", 1, "A/B/C", MOVED_HERE},
+ {0}
+ };
+ SVN_ERR(check_db_rows(&b, "", nodes));
+ }
+ SVN_ERR(sbox_wc_move(&b, "A/B", "A/B2"));
+ {
+ nodes_row_t nodes[] = {
+ {0, "", "normal", 1, ""},
+ {0, "A", "normal", 1, "A"},
+ {0, "A/B", "normal", 1, "A/B"},
+ {0, "A/B/C", "normal", 1, "A/B/C"},
+ {2, "A/B", "base-deleted", NO_COPY_FROM, "A/B2"},
+ {2, "A/B/C", "base-deleted", NO_COPY_FROM},
+ {2, "A/B2", "normal", 1, "A/B", MOVED_HERE},
+ {2, "A/B2/C", "normal", 1, "A/B/C", MOVED_HERE},
+ {3, "A/B2/C", "base-deleted", NO_COPY_FROM, "A/B2/C2"},
+ {3, "A/B2/C2", "normal", 1, "A/B/C", MOVED_HERE},
+ {0}
+ };
+ SVN_ERR(check_db_rows(&b, "", nodes));
+ }
+ SVN_ERR(sbox_wc_move(&b, "A", "A2"));
+ {
+ nodes_row_t nodes[] = {
+ {0, "", "normal", 1, ""},
+ {0, "A", "normal", 1, "A"},
+ {0, "A/B", "normal", 1, "A/B"},
+ {0, "A/B/C", "normal", 1, "A/B/C"},
+ {1, "A", "base-deleted", NO_COPY_FROM, "A2"},
+ {1, "A/B", "base-deleted", NO_COPY_FROM},
+ {1, "A/B/C", "base-deleted", NO_COPY_FROM},
+ {1, "A2", "normal", 1, "A", MOVED_HERE},
+ {1, "A2/B", "normal", 1, "A/B", MOVED_HERE},
+ {1, "A2/B/C", "normal", 1, "A/B/C", MOVED_HERE},
+ {2, "A2/B", "base-deleted", NO_COPY_FROM, "A2/B2"},
+ {2, "A2/B/C", "base-deleted", NO_COPY_FROM},
+ {2, "A2/B2", "normal", 1, "A/B", MOVED_HERE},
+ {2, "A2/B2/C", "normal", 1, "A/B/C", MOVED_HERE},
+ {3, "A2/B2/C", "base-deleted", NO_COPY_FROM, "A2/B2/C2"},
+ {3, "A2/B2/C2","normal", 1, "A/B/C", MOVED_HERE},
+ {0}
+ };
+ SVN_ERR(check_db_rows(&b, "", nodes));
+ }
+
+ /* Revert should leave the A to A2 move */
+ SVN_ERR(sbox_wc_revert(&b, "A2/B2", svn_depth_infinity));
+ SVN_ERR(sbox_wc_revert(&b, "A2/B", svn_depth_infinity));
+ {
+ nodes_row_t nodes[] = {
+ {0, "", "normal", 1, ""},
+ {0, "A", "normal", 1, "A"},
+ {0, "A/B", "normal", 1, "A/B"},
+ {0, "A/B/C", "normal", 1, "A/B/C"},
+ {1, "A", "base-deleted", NO_COPY_FROM, "A2"},
+ {1, "A/B", "base-deleted", NO_COPY_FROM},
+ {1, "A/B/C", "base-deleted", NO_COPY_FROM},
+ {1, "A2", "normal", 1, "A", MOVED_HERE},
+ {1, "A2/B", "normal", 1, "A/B", MOVED_HERE},
+ {1, "A2/B/C", "normal", 1, "A/B/C", MOVED_HERE},
+ {0}
+ };
+ SVN_ERR(check_db_rows(&b, "", nodes));
+ }
+
+ return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+nested_moves_child_last(const svn_test_opts_t *opts, apr_pool_t *pool)
+{
+ svn_test__sandbox_t b;
+
+ SVN_ERR(svn_test__sandbox_create(&b, "nested_moves_child_last", opts, pool));
+
+ SVN_ERR(sbox_wc_mkdir(&b, "A"));
+ SVN_ERR(sbox_wc_mkdir(&b, "A/B"));
+ SVN_ERR(sbox_wc_mkdir(&b, "A/B/C"));
+ SVN_ERR(sbox_wc_commit(&b, ""));
+ SVN_ERR(sbox_wc_update(&b, "", 1));
+
+ {
+ nodes_row_t nodes[] = {
+ {0, "", "normal", 1, ""},
+ {0, "A", "normal", 1, "A"},
+ {0, "A/B", "normal", 1, "A/B"},
+ {0, "A/B/C", "normal", 1, "A/B/C"},
+ {0}
+ };
+ SVN_ERR(check_db_rows(&b, "", nodes));
+ }
+ SVN_ERR(sbox_wc_move(&b, "A", "A2"));
+ {
+ nodes_row_t nodes[] = {
+ {0, "", "normal", 1, ""},
+ {0, "A", "normal", 1, "A"},
+ {0, "A/B", "normal", 1, "A/B"},
+ {0, "A/B/C", "normal", 1, "A/B/C"},
+ {1, "A", "base-deleted", NO_COPY_FROM, "A2"},
+ {1, "A/B", "base-deleted", NO_COPY_FROM},
+ {1, "A/B/C", "base-deleted", NO_COPY_FROM},
+ {1, "A2", "normal", 1, "A", MOVED_HERE},
+ {1, "A2/B", "normal", 1, "A/B", MOVED_HERE},
+ {1, "A2/B/C", "normal", 1, "A/B/C", MOVED_HERE},
+ {0}
+ };
+ SVN_ERR(check_db_rows(&b, "", nodes));
+ }
+ SVN_ERR(sbox_wc_move(&b, "A2/B", "A2/B2"));
+ {
+ nodes_row_t nodes[] = {
+ {0, "", "normal", 1, ""},
+ {0, "A", "normal", 1, "A"},
+ {0, "A/B", "normal", 1, "A/B"},
+ {0, "A/B/C", "normal", 1, "A/B/C"},
+ {1, "A", "base-deleted", NO_COPY_FROM, "A2"},
+ {1, "A/B", "base-deleted", NO_COPY_FROM},
+ {1, "A/B/C", "base-deleted", NO_COPY_FROM},
+ {1, "A2", "normal", 1, "A", MOVED_HERE},
+ {1, "A2/B", "normal", 1, "A/B", MOVED_HERE},
+ {1, "A2/B/C", "normal", 1, "A/B/C", MOVED_HERE},
+ {2, "A2/B", "base-deleted", NO_COPY_FROM, "A2/B2"},
+ {2, "A2/B/C", "base-deleted", NO_COPY_FROM},
+ {2, "A2/B2", "normal", 1, "A/B", MOVED_HERE},
+ {2, "A2/B2/C", "normal", 1, "A/B/C", MOVED_HERE},
+ {0}
+ };
+ SVN_ERR(check_db_rows(&b, "", nodes));
+ }
+ SVN_ERR(sbox_wc_move(&b, "A2/B2/C", "A2/B2/C2"));
+ {
+ nodes_row_t nodes[] = {
+ {0, "", "normal", 1, ""},
+ {0, "A", "normal", 1, "A"},
+ {0, "A/B", "normal", 1, "A/B"},
+ {0, "A/B/C", "normal", 1, "A/B/C"},
+ {1, "A", "base-deleted", NO_COPY_FROM, "A2"},
+ {1, "A/B", "base-deleted", NO_COPY_FROM},
+ {1, "A/B/C", "base-deleted", NO_COPY_FROM},
+ {1, "A2", "normal", 1, "A", MOVED_HERE},
+ {1, "A2/B", "normal", 1, "A/B", MOVED_HERE},
+ {1, "A2/B/C", "normal", 1, "A/B/C", MOVED_HERE},
+ {2, "A2/B", "base-deleted", NO_COPY_FROM, "A2/B2"},
+ {2, "A2/B/C", "base-deleted", NO_COPY_FROM},
+ {2, "A2/B2", "normal", 1, "A/B", MOVED_HERE},
+ {2, "A2/B2/C", "normal", 1, "A/B/C", MOVED_HERE},
+ {3, "A2/B2/C", "base-deleted", NO_COPY_FROM, "A2/B2/C2"},
+ {3, "A2/B2/C2","normal", 1, "A/B/C", MOVED_HERE},
+ {0}
+ };
+ SVN_ERR(check_db_rows(&b, "", nodes));
+ }
+
+ /* Revert should leave the A to A2 move */
+ SVN_ERR(sbox_wc_revert(&b, "A2/B2", svn_depth_infinity));
+ SVN_ERR(sbox_wc_revert(&b, "A2/B", svn_depth_infinity));
+ {
+ nodes_row_t nodes[] = {
+ {0, "", "normal", 1, ""},
+ {0, "A", "normal", 1, "A"},
+ {0, "A/B", "normal", 1, "A/B"},
+ {0, "A/B/C", "normal", 1, "A/B/C"},
+ {1, "A", "base-deleted", NO_COPY_FROM, "A2"},
+ {1, "A/B", "base-deleted", NO_COPY_FROM},
+ {1, "A/B/C", "base-deleted", NO_COPY_FROM},
+ {1, "A2", "normal", 1, "A", MOVED_HERE},
+ {1, "A2/B", "normal", 1, "A/B", MOVED_HERE},
+ {1, "A2/B/C", "normal", 1, "A/B/C", MOVED_HERE},
+ {0}
+ };
+ SVN_ERR(check_db_rows(&b, "", nodes));
+ }
+
+ return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+move_in_copy(const svn_test_opts_t *opts, apr_pool_t *pool)
+{
+ svn_test__sandbox_t b;
+
+ SVN_ERR(svn_test__sandbox_create(&b, "move_in_copy", opts, pool));
+
+ SVN_ERR(sbox_wc_mkdir(&b, "A"));
+ SVN_ERR(sbox_wc_mkdir(&b, "A/B"));
+ SVN_ERR(sbox_wc_commit(&b, ""));
+ SVN_ERR(sbox_wc_update(&b, "", 1));
+ SVN_ERR(sbox_wc_copy(&b, "A", "A2"));
+
+ {
+ nodes_row_t nodes[] = {
+ {0, "", "normal", 1, ""},
+ {0, "A", "normal", 1, "A"},
+ {0, "A/B", "normal", 1, "A/B"},
+ {1, "A2", "normal", 1, "A"},
+ {1, "A2/B", "normal", 1, "A/B"},
+ {0}
+ };
+ SVN_ERR(check_db_rows(&b, "", nodes));
+ }
+ SVN_ERR(sbox_wc_move(&b, "A2/B", "A2/B2"));
+ {
+ nodes_row_t nodes[] = {
+ {0, "", "normal", 1, ""},
+ {0, "A", "normal", 1, "A"},
+ {0, "A/B", "normal", 1, "A/B"},
+ {1, "A2", "normal", 1, "A"},
+ {1, "A2/B", "normal", 1, "A/B"},
+ {2, "A2/B", "base-deleted", NO_COPY_FROM, "A2/B2"},
+ {2, "A2/B2", "normal", 1, "A/B", MOVED_HERE},
+ {0}
+ };
+ SVN_ERR(check_db_rows(&b, "", nodes));
+ }
+
+ return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+move_in_replace(const svn_test_opts_t *opts, apr_pool_t *pool)
+{
+ svn_test__sandbox_t b;
+
+ SVN_ERR(svn_test__sandbox_create(&b, "move_in_replace", opts, pool));
+
+ SVN_ERR(sbox_wc_mkdir(&b, "A"));
+ SVN_ERR(sbox_wc_mkdir(&b, "A/B"));
+ SVN_ERR(sbox_wc_mkdir(&b, "X"));
+ SVN_ERR(sbox_wc_mkdir(&b, "X/B"));
+ SVN_ERR(sbox_wc_commit(&b, ""));
+ SVN_ERR(sbox_wc_update(&b, "", 1));
+ SVN_ERR(sbox_wc_delete(&b, "A"));
+ SVN_ERR(sbox_wc_copy(&b, "X", "A"));
+
+ {
+ nodes_row_t nodes[] = {
+ {0, "", "normal", 1, ""},
+ {0, "A", "normal", 1, "A"},
+ {0, "A/B", "normal", 1, "A/B"},
+ {0, "X", "normal", 1, "X"},
+ {0, "X/B", "normal", 1, "X/B"},
+ {1, "A", "normal", 1, "X"},
+ {1, "A/B", "normal", 1, "X/B"},
+ {0}
+ };
+ SVN_ERR(check_db_rows(&b, "", nodes));
+ }
+ SVN_ERR(sbox_wc_move(&b, "A/B", "A/B2"));
+ {
+ nodes_row_t nodes[] = {
+ {0, "", "normal", 1, ""},
+ {0, "A", "normal", 1, "A"},
+ {0, "A/B", "normal", 1, "A/B"},
+ {0, "X", "normal", 1, "X"},
+ {0, "X/B", "normal", 1, "X/B"},
+ {1, "A", "normal", 1, "X"},
+ {1, "A/B", "normal", 1, "X/B"},
+ {2, "A/B", "base-deleted", NO_COPY_FROM, "A/B2"},
+ {2, "A/B2", "normal", 1, "X/B", MOVED_HERE},
+ {0}
+ };
+ SVN_ERR(check_db_rows(&b, "", nodes));
+ }
+
+ return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+copy_a_move(const svn_test_opts_t *opts, apr_pool_t *pool)
+{
+ svn_test__sandbox_t b;
+
+ SVN_ERR(svn_test__sandbox_create(&b, "copy_a_move", opts, pool));
+
+ SVN_ERR(sbox_wc_mkdir(&b, "A"));
+ SVN_ERR(sbox_wc_mkdir(&b, "A/B"));
+ SVN_ERR(sbox_wc_mkdir(&b, "A/B/C"));
+ SVN_ERR(sbox_wc_commit(&b, ""));
+ SVN_ERR(sbox_wc_update(&b, "", 1));
+
+ {
+ nodes_row_t nodes[] = {
+ {0, "", "normal", 1, ""},
+ {0, "A", "normal", 1, "A"},
+ {0, "A/B", "normal", 1, "A/B"},
+ {0, "A/B/C", "normal", 1, "A/B/C"},
+ {0}
+ };
+ SVN_ERR(check_db_rows(&b, "", nodes));
+ }
+ SVN_ERR(sbox_wc_move(&b, "A/B/C", "A/C2"));
+ {
+ nodes_row_t nodes[] = {
+ {0, "", "normal", 1, ""},
+ {0, "A", "normal", 1, "A"},
+ {0, "A/B", "normal", 1, "A/B"},
+ {0, "A/B/C", "normal", 1, "A/B/C"},
+ {2, "A/C2", "normal", 1, "A/B/C", MOVED_HERE},
+ {3, "A/B/C", "base-deleted", NO_COPY_FROM, "A/C2"},
+ {0}
+ };
+ SVN_ERR(check_db_rows(&b, "", nodes));
+ }
+ /* Copying a move doesn't copy any moved-to/here artifacts, which
+ means that moving inside a copy is not the same as copying
+ something that contains a move? Is this behaviour correct? */
+ SVN_ERR(sbox_wc_copy(&b, "A", "A2"));
+ {
+ nodes_row_t nodes[] = {
+ {0, "", "normal", 1, ""},
+ {0, "A", "normal", 1, "A"},
+ {0, "A/B", "normal", 1, "A/B"},
+ {0, "A/B/C", "normal", 1, "A/B/C"},
+ {2, "A/C2", "normal", 1, "A/B/C", MOVED_HERE},
+ {3, "A/B/C", "base-deleted", NO_COPY_FROM, "A/C2"},
+ {1, "A2", "normal", 1, "A"},
+ {1, "A2/B", "normal", 1, "A/B"},
+ {1, "A2/B/C", "normal", 1, "A/B/C"},
+ {2, "A2/C2", "normal", 1, "A/B/C"}, /* MOVED_HERE? */
+ {3, "A2/B/C", "base-deleted", NO_COPY_FROM}, /* "A2/C2"? */
+ {0}
+ };
+ SVN_ERR(check_db_rows(&b, "", nodes));
+ }
+
+ return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+move_to_swap(const svn_test_opts_t *opts, apr_pool_t *pool)
+{
+ svn_test__sandbox_t b;
+
+ SVN_ERR(svn_test__sandbox_create(&b, "move_to_swap", opts, pool));
+
+ SVN_ERR(sbox_wc_mkdir(&b, "A"));
+ SVN_ERR(sbox_wc_mkdir(&b, "A/B"));
+ SVN_ERR(sbox_wc_mkdir(&b, "X"));
+ SVN_ERR(sbox_wc_mkdir(&b, "X/Y"));
+ SVN_ERR(sbox_wc_commit(&b, ""));
+ SVN_ERR(sbox_wc_update(&b, "", 1));
+
+ SVN_ERR(sbox_wc_move(&b, "A/B", "X/B"));
+ SVN_ERR(sbox_wc_move(&b, "X/Y", "A/Y"));
+
+ {
+ nodes_row_t nodes[] = {
+ {0, "", "normal", 1, ""},
+ {0, "A", "normal", 1, "A"},
+ {0, "A/B", "normal", 1, "A/B"},
+ {0, "X", "normal", 1, "X"},
+ {0, "X/Y", "normal", 1, "X/Y"},
+ {2, "A/B", "base-deleted", NO_COPY_FROM, "X/B"},
+ {2, "A/Y", "normal", 1, "X/Y", MOVED_HERE},
+ {2, "X/Y", "base-deleted", NO_COPY_FROM, "A/Y"},
+ {2, "X/B", "normal", 1, "A/B", MOVED_HERE},
+ {0}
+ };
+ SVN_ERR(check_db_rows(&b, "", nodes));
+ }
+
+ SVN_ERR(sbox_wc_move(&b, "A", "A2"));
+
+ {
+ nodes_row_t nodes[] = {
+ {0, "", "normal", 1, ""},
+ {0, "A", "normal", 1, "A"},
+ {0, "A/B", "normal", 1, "A/B"},
+ {0, "X", "normal", 1, "X"},
+ {0, "X/Y", "normal", 1, "X/Y"},
+ {1, "A", "base-deleted", NO_COPY_FROM, "A2"},
+ {1, "A/B", "base-deleted", NO_COPY_FROM},
+ {1, "A2", "normal", 1, "A", MOVED_HERE},
+ {1, "A2/B", "normal", 1, "A/B", MOVED_HERE},
+ {2, "A2/B", "base-deleted", NO_COPY_FROM, "X/B"},
+ {2, "A2/Y", "normal", 1, "X/Y", MOVED_HERE},
+ {2, "X/Y", "base-deleted", NO_COPY_FROM, "A2/Y"},
+ {2, "X/B", "normal", 1, "A/B", MOVED_HERE},
+ {0}
+ };
+ SVN_ERR(check_db_rows(&b, "", nodes));
+ }
+
+ SVN_ERR(sbox_wc_move(&b, "X", "A"));
+
+ {
+ nodes_row_t nodes[] = {
+ {0, "", "normal", 1, ""},
+ {0, "A", "normal", 1, "A"},
+ {0, "A/B", "normal", 1, "A/B"},
+ {0, "X", "normal", 1, "X"},
+ {0, "X/Y", "normal", 1, "X/Y"},
+ {1, "A", "normal", 1, "X", FALSE, "A2", TRUE},
+ {1, "A/B", "base-deleted", NO_COPY_FROM},
+ {1, "A/Y", "normal", 1, "X/Y", MOVED_HERE},
+ {1, "A2", "normal", 1, "A", MOVED_HERE},
+ {1, "A2/B", "normal", 1, "A/B", MOVED_HERE},
+ {1, "X", "base-deleted", NO_COPY_FROM, "A"},
+ {1, "X/Y", "base-deleted", NO_COPY_FROM},
+ {2, "A/B", "normal", 1, "A/B", MOVED_HERE},
+ {2, "A/Y", "base-deleted", NO_COPY_FROM, "A2/Y"},
+ {2, "A2/B", "base-deleted", NO_COPY_FROM, "A/B"},
+ {2, "A2/Y", "normal", 1, "X/Y", MOVED_HERE},
+ {0}
+ };
+ SVN_ERR(check_db_rows(&b, "", nodes));
+ }
+
+ SVN_ERR(sbox_wc_move(&b, "A2", "X"));
+
+ {
+ nodes_row_t nodes[] = {
+ {0, "", "normal", 1, ""},
+ {0, "A", "normal", 1, "A"},
+ {0, "A/B", "normal", 1, "A/B"},
+ {0, "X", "normal", 1, "X"},
+ {0, "X/Y", "normal", 1, "X/Y"},
+ {1, "A", "normal", 1, "X", FALSE, "X", TRUE},
+ {1, "A/Y", "normal", 1, "X/Y", MOVED_HERE},
+ {1, "A/B", "base-deleted", NO_COPY_FROM},
+ {1, "X", "normal", 1, "A", FALSE, "A", TRUE},
+ {1, "X/B", "normal", 1, "A/B", MOVED_HERE},
+ {1, "X/Y", "base-deleted", NO_COPY_FROM},
+ {2, "A/Y", "base-deleted", NO_COPY_FROM, "X/Y"},
+ {2, "X/B", "base-deleted", NO_COPY_FROM, "A/B"},
+ {2, "A/B", "normal", 1, "A/B", MOVED_HERE},
+ {2, "X/Y", "normal", 1, "X/Y", MOVED_HERE},
+ {0}
+ };
+ SVN_ERR(check_db_rows(&b, "", nodes));
+ }
+
+ /* Revert and try in different order */
+ SVN_ERR(sbox_wc_revert(&b, "", svn_depth_infinity));
+
+ SVN_ERR(sbox_wc_move(&b, "A", "A2"));
+ SVN_ERR(sbox_wc_move(&b, "X", "A"));
+ SVN_ERR(sbox_wc_move(&b, "A2", "X"));
+
+ {
+ nodes_row_t nodes[] = {
+ {0, "", "normal", 1, ""},
+ {0, "A", "normal", 1, "A"},
+ {0, "A/B", "normal", 1, "A/B"},
+ {0, "X", "normal", 1, "X"},
+ {0, "X/Y", "normal", 1, "X/Y"},
+ {1, "A", "normal", 1, "X", FALSE, "X", TRUE},
+ {1, "A/Y", "normal", 1, "X/Y", MOVED_HERE},
+ {1, "A/B", "base-deleted", NO_COPY_FROM},
+ {1, "X", "normal", 1, "A", FALSE, "A", TRUE},
+ {1, "X/B", "normal", 1, "A/B", MOVED_HERE},
+ {1, "X/Y", "base-deleted", NO_COPY_FROM},
+ {0}
+ };
+ SVN_ERR(check_db_rows(&b, "", nodes));
+ }
+
+ SVN_ERR(sbox_wc_move(&b, "A/Y", "X/Y"));
+ SVN_ERR(sbox_wc_move(&b, "X/B", "A/B"));
+
+ {
+ nodes_row_t nodes[] = {
+ {0, "", "normal", 1, ""},
+ {0, "A", "normal", 1, "A"},
+ {0, "A/B", "normal", 1, "A/B"},
+ {0, "X", "normal", 1, "X"},
+ {0, "X/Y", "normal", 1, "X/Y"},
+ {1, "A", "normal", 1, "X", FALSE, "X", TRUE},
+ {1, "A/Y", "normal", 1, "X/Y", MOVED_HERE},
+ {1, "A/B", "base-deleted", NO_COPY_FROM},
+ {1, "X", "normal", 1, "A", FALSE, "A", TRUE},
+ {1, "X/B", "normal", 1, "A/B", MOVED_HERE},
+ {1, "X/Y", "base-deleted", NO_COPY_FROM},
+ {2, "A/Y", "base-deleted", NO_COPY_FROM, "X/Y"},
+ {2, "X/B", "base-deleted", NO_COPY_FROM, "A/B"},
+ {2, "A/B", "normal", 1, "A/B", MOVED_HERE},
+ {2, "X/Y", "normal", 1, "X/Y", MOVED_HERE},
+ {0}
+ };
+ SVN_ERR(check_db_rows(&b, "", nodes));
+ }
+
+ /* And move this last bit back and check if the db state is restored */
+ SVN_ERR(sbox_wc_move(&b, "A/B", "X/B"));
+ SVN_ERR(sbox_wc_move(&b, "X/Y", "A/Y"));
+
+ {
+ /* Exact the same as before the initial moves */
+ nodes_row_t nodes[] = {
+ {0, "", "normal", 1, ""},
+ {0, "A", "normal", 1, "A"},
+ {0, "A/B", "normal", 1, "A/B"},
+ {0, "X", "normal", 1, "X"},
+ {0, "X/Y", "normal", 1, "X/Y"},
+ {1, "A", "normal", 1, "X", FALSE, "X", TRUE},
+ {1, "A/Y", "normal", 1, "X/Y", MOVED_HERE},
+ {1, "A/B", "base-deleted", NO_COPY_FROM},
+ {1, "X", "normal", 1, "A", FALSE, "A", TRUE},
+ {1, "X/B", "normal", 1, "A/B", MOVED_HERE},
+ {1, "X/Y", "base-deleted", NO_COPY_FROM},
+ {0}
+ };
+ SVN_ERR(check_db_rows(&b, "", nodes));
+ }
+
+ /* And try to undo the rest */
+ SVN_ERR(sbox_wc_move(&b, "A", "A2"));
+ SVN_ERR(sbox_wc_move(&b, "X", "A"));
+ SVN_ERR(sbox_wc_move(&b, "A2", "X"));
+
+ {
+ nodes_row_t nodes[] = {
+ {0, "", "normal", 1, ""},
+ {0, "A", "normal", 1, "A"},
+ {0, "A/B", "normal", 1, "A/B"},
+ {0, "X", "normal", 1, "X"},
+ {0, "X/Y", "normal", 1, "X/Y"},
+
+ {0}
+ };
+
+ SVN_ERR(check_db_rows(&b, "", nodes));
+ }
+
+ return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+revert_nested_move(const svn_test_opts_t *opts, apr_pool_t *pool)
+{
+ svn_test__sandbox_t b;
+ nodes_row_t nodes_A_moved[] = {
+ {0, "", "normal", 1, ""},
+ {0, "A", "normal", 1, "A"},
+ {0, "A/B", "normal", 1, "A/B"},
+ {0, "A/B/C", "normal", 1, "A/B/C"},
+ {1, "A", "base-deleted", NO_COPY_FROM, "A2"},
+ {1, "A/B", "base-deleted", NO_COPY_FROM},
+ {1, "A/B/C", "base-deleted", NO_COPY_FROM},
+ {1, "A2", "normal", 1, "A", MOVED_HERE},
+ {1, "A2/B", "normal", 1, "A/B", MOVED_HERE},
+ {1, "A2/B/C", "normal", 1, "A/B/C", MOVED_HERE},
+ {0}
+ };
+ nodes_row_t nodes_AB_moved[] = {
+ {0, "", "normal", 1, ""},
+ {0, "A", "normal", 1, "A"},
+ {0, "A/B", "normal", 1, "A/B"},
+ {0, "A/B/C", "normal", 1, "A/B/C"},
+ {1, "A", "base-deleted", NO_COPY_FROM, "A2"},
+ {1, "A/B", "base-deleted", NO_COPY_FROM},
+ {1, "A/B/C", "base-deleted", NO_COPY_FROM},
+ {1, "A2", "normal", 1, "A", MOVED_HERE},
+ {1, "A2/B", "normal", 1, "A/B", MOVED_HERE},
+ {1, "A2/B/C", "normal", 1, "A/B/C", MOVED_HERE},
+ {2, "A2/B", "base-deleted", NO_COPY_FROM, "A2/B2"},
+ {2, "A2/B/C", "base-deleted", NO_COPY_FROM},
+ {2, "A2/B2", "normal", 1, "A/B", MOVED_HERE},
+ {2, "A2/B2/C", "normal", 1, "A/B/C", MOVED_HERE},
+ {0}
+ };
+ nodes_row_t nodes_ABC_moved[] = {
+ {0, "", "normal", 1, ""},
+ {0, "A", "normal", 1, "A"},
+ {0, "A/B", "normal", 1, "A/B"},
+ {0, "A/B/C", "normal", 1, "A/B/C"},
+ {1, "A", "base-deleted", NO_COPY_FROM, "A2"},
+ {1, "A/B", "base-deleted", NO_COPY_FROM},
+ {1, "A/B/C", "base-deleted", NO_COPY_FROM},
+ {1, "A2", "normal", 1, "A", MOVED_HERE},
+ {1, "A2/B", "normal", 1, "A/B", MOVED_HERE},
+ {1, "A2/B/C", "normal", 1, "A/B/C", MOVED_HERE},
+ {2, "A2/B", "base-deleted", NO_COPY_FROM, "A2/B2"},
+ {2, "A2/B/C", "base-deleted", NO_COPY_FROM},
+ {2, "A2/B2", "normal", 1, "A/B", MOVED_HERE},
+ {2, "A2/B2/C", "normal", 1, "A/B/C", MOVED_HERE},
+ {3, "A2/B2/C", "base-deleted", NO_COPY_FROM, "A2/B2/C2"},
+ {3, "A2/B2/C2", "normal", 1, "A/B/C", MOVED_HERE},
+ {0}
+ };
+ nodes_row_t nodes_AB_moved_C_copied[] = {
+ {0, "", "normal", 1, ""},
+ {0, "A", "normal", 1, "A"},
+ {0, "A/B", "normal", 1, "A/B"},
+ {0, "A/B/C", "normal", 1, "A/B/C"},
+ {1, "A", "base-deleted", NO_COPY_FROM, "A2"},
+ {1, "A/B", "base-deleted", NO_COPY_FROM},
+ {1, "A/B/C", "base-deleted", NO_COPY_FROM},
+ {1, "A2", "normal", 1, "A", MOVED_HERE},
+ {1, "A2/B", "normal", 1, "A/B", MOVED_HERE},
+ {1, "A2/B/C", "normal", 1, "A/B/C", MOVED_HERE},
+ {2, "A2/B", "base-deleted", NO_COPY_FROM, "A2/B2"},
+ {2, "A2/B/C", "base-deleted", NO_COPY_FROM},
+ {2, "A2/B2", "normal", 1, "A/B", MOVED_HERE},
+ {2, "A2/B2/C", "normal", 1, "A/B/C", MOVED_HERE},
+ {3, "A2/B2/C2", "normal", 1, "A/B/C"},
+ {0}
+ };
+ nodes_row_t nodes_AC_moved_B_copied[] = {
+ {0, "", "normal", 1, ""},
+ {0, "A", "normal", 1, "A"},
+ {0, "A/B", "normal", 1, "A/B"},
+ {0, "A/B/C", "normal", 1, "A/B/C"},
+ {1, "A", "base-deleted", NO_COPY_FROM, "A2"},
+ {1, "A/B", "base-deleted", NO_COPY_FROM},
+ {1, "A/B/C", "base-deleted", NO_COPY_FROM},
+ {1, "A2", "normal", 1, "A", MOVED_HERE},
+ {1, "A2/B", "normal", 1, "A/B", MOVED_HERE},
+ {1, "A2/B/C", "normal", 1, "A/B/C", MOVED_HERE},
+ {2, "A2/B2", "normal", 1, "A/B"},
+ {2, "A2/B2/C", "normal", 1, "A/B/C"},
+ {3, "A2/B2/C", "base-deleted", NO_COPY_FROM, "A2/B2/C2"},
+ {3, "A2/B2/C2", "normal", 1, "A/B/C", MOVED_HERE},
+ {0}
+ };
+
+ SVN_ERR(svn_test__sandbox_create(&b, "revert_nested_move", opts, pool));
+
+ SVN_ERR(sbox_wc_mkdir(&b, "A"));
+ SVN_ERR(sbox_wc_mkdir(&b, "A/B"));
+ SVN_ERR(sbox_wc_mkdir(&b, "A/B/C"));
+ SVN_ERR(sbox_wc_commit(&b, ""));
+ SVN_ERR(sbox_wc_update(&b, "", 1));
+
+ SVN_ERR(sbox_wc_move(&b, "A", "A2"));
+ SVN_ERR(check_db_rows(&b, "", nodes_A_moved));
+
+ SVN_ERR(sbox_wc_move(&b, "A2/B", "A2/B2"));
+ SVN_ERR(check_db_rows(&b, "", nodes_AB_moved));
+
+ SVN_ERR(sbox_wc_move(&b, "A2/B2/C", "A2/B2/C2"));
+ SVN_ERR(check_db_rows(&b, "", nodes_ABC_moved));
+
+ SVN_ERR(sbox_wc_revert(&b, "A2/B", svn_depth_infinity));
+ SVN_ERR(sbox_wc_revert(&b, "A2/B2", svn_depth_infinity));
+ SVN_ERR(check_db_rows(&b, "", nodes_A_moved));
+
+ SVN_ERR(sbox_wc_move(&b, "A2/B", "A2/B2"));
+ SVN_ERR(sbox_wc_move(&b, "A2/B2/C", "A2/B2/C2"));
+ SVN_ERR(check_db_rows(&b, "", nodes_ABC_moved));
+
+ SVN_ERR(sbox_wc_revert(&b, "A2/B2/C", svn_depth_empty));
+ SVN_ERR(check_db_rows(&b, "", nodes_AB_moved_C_copied));
+ SVN_ERR(sbox_wc_revert(&b, "A2/B2/C2", svn_depth_infinity));
+ SVN_ERR(check_db_rows(&b, "", nodes_AB_moved));
+
+ SVN_ERR(sbox_wc_move(&b, "A2/B2/C", "A2/B2/C2"));
+ SVN_ERR(check_db_rows(&b, "", nodes_ABC_moved));
+
+ SVN_ERR(sbox_wc_revert(&b, "A2/B2/C", svn_depth_infinity));
+ SVN_ERR(check_db_rows(&b, "", nodes_AB_moved_C_copied));
+ SVN_ERR(sbox_wc_revert(&b, "A2/B2/C2", svn_depth_infinity));
+ SVN_ERR(check_db_rows(&b, "", nodes_AB_moved));
+
+ SVN_ERR(sbox_wc_revert(&b, "A2/B", svn_depth_infinity));
+ SVN_ERR(sbox_wc_revert(&b, "A2/B2", svn_depth_infinity));
+ SVN_ERR(check_db_rows(&b, "", nodes_A_moved));
+
+ /* Check moves in reverse order */
+ SVN_ERR(sbox_wc_revert(&b, "", svn_depth_infinity));
+ SVN_ERR(sbox_wc_move(&b, "A/B/C", "A/B/C2"));
+ SVN_ERR(sbox_wc_move(&b, "A/B", "A/B2"));
+ SVN_ERR(sbox_wc_move(&b, "A", "A2"));
+ SVN_ERR(check_db_rows(&b, "", nodes_ABC_moved));
+
+ SVN_ERR(sbox_wc_revert(&b, "A2/B", svn_depth_infinity));
+ SVN_ERR(check_db_rows(&b, "", nodes_AC_moved_B_copied));
+
+ return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+move_on_move(const svn_test_opts_t *opts, apr_pool_t *pool)
+{
+ svn_test__sandbox_t b;
+
+ SVN_ERR(svn_test__sandbox_create(&b, "move_on_move", opts, pool));
+
+ SVN_ERR(sbox_wc_mkdir(&b, "A"));
+ SVN_ERR(sbox_wc_mkdir(&b, "A/B"));
+ SVN_ERR(sbox_wc_mkdir(&b, "X"));
+ SVN_ERR(sbox_wc_mkdir(&b, "X/B"));
+ SVN_ERR(sbox_wc_commit(&b, ""));
+ SVN_ERR(sbox_wc_update(&b, "", 1));
+
+ SVN_ERR(sbox_wc_move(&b, "A/B", "B2"));
+ SVN_ERR(sbox_wc_delete(&b, "A"));
+ SVN_ERR(sbox_wc_copy(&b, "X", "A"));
+
+ {
+ nodes_row_t nodes[] = {
+ {0, "", "normal", 1, ""},
+ {0, "A", "normal", 1, "A"},
+ {0, "A/B", "normal", 1, "A/B"},
+ {0, "X", "normal", 1, "X"},
+ {0, "X/B", "normal", 1, "X/B"},
+ {1, "B2", "normal", 1, "A/B", MOVED_HERE},
+ {1, "A", "normal", 1, "X"},
+ {1, "A/B", "normal", 1, "X/B", FALSE, "B2"},
+ {0}
+ };
+ SVN_ERR(check_db_rows(&b, "", nodes));
+ }
+
+ SVN_ERR(sbox_wc_move(&b, "A/B", "B3"));
+ {
+ nodes_row_t nodes[] = {
+ {0, "", "normal", 1, ""},
+ {0, "A", "normal", 1, "A"},
+ {0, "A/B", "normal", 1, "A/B"},
+ {0, "X", "normal", 1, "X"},
+ {0, "X/B", "normal", 1, "X/B"},
+ {1, "B2", "normal", 1, "A/B", MOVED_HERE},
+ {1, "B3", "normal", 1, "X/B", MOVED_HERE},
+ {1, "A", "normal", 1, "X"},
+ {1, "A/B", "normal", 1, "X/B", FALSE, "B2"},
+ {2, "A/B", "base-deleted", NO_COPY_FROM, "B3"},
+ {0}
+ };
+ SVN_ERR(check_db_rows(&b, "", nodes));
+ }
+
+ return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+move_on_move2(const svn_test_opts_t *opts, apr_pool_t *pool)
+{
+ svn_test__sandbox_t b;
+
+ SVN_ERR(svn_test__sandbox_create(&b, "move_on_move2", opts, pool));
+
+ SVN_ERR(sbox_wc_mkdir(&b, "A"));
+ SVN_ERR(sbox_wc_mkdir(&b, "A/B"));
+ SVN_ERR(sbox_wc_mkdir(&b, "X"));
+ SVN_ERR(sbox_wc_mkdir(&b, "X/B"));
+ SVN_ERR(sbox_wc_commit(&b, ""));
+ SVN_ERR(sbox_wc_update(&b, "", 1));
+
+ SVN_ERR(sbox_wc_move(&b, "A", "A2"));
+ SVN_ERR(sbox_wc_delete(&b, "A"));
+ SVN_ERR(sbox_wc_copy(&b, "X", "A"));
+
+ {
+ nodes_row_t nodes[] = {
+ {0, "", "normal", 1, ""},
+ {0, "A", "normal", 1, "A"},
+ {0, "A/B", "normal", 1, "A/B"},
+ {0, "X", "normal", 1, "X"},
+ {0, "X/B", "normal", 1, "X/B"},
+ {1, "A2", "normal", 1, "A", MOVED_HERE},
+ {1, "A2/B", "normal", 1, "A/B", MOVED_HERE},
+ {1, "A", "normal", 1, "X", FALSE, "A2"},
+ {1, "A/B", "normal", 1, "X/B"},
+ {0}
+ };
+ SVN_ERR(check_db_rows(&b, "", nodes));
+ }
+
+ SVN_ERR(sbox_wc_move(&b, "A/B", "B3"));
+ {
+ nodes_row_t nodes[] = {
+ {0, "", "normal", 1, ""},
+ {0, "A", "normal", 1, "A"},
+ {0, "A/B", "normal", 1, "A/B"},
+ {0, "X", "normal", 1, "X"},
+ {0, "X/B", "normal", 1, "X/B"},
+ {1, "A2", "normal", 1, "A", MOVED_HERE},
+ {1, "A2/B", "normal", 1, "A/B", MOVED_HERE},
+ {1, "B3", "normal", 1, "X/B", MOVED_HERE},
+ {1, "A", "normal", 1, "X", FALSE, "A2"},
+ {1, "A/B", "normal", 1, "X/B"},
+ {2, "A/B", "base-deleted", NO_COPY_FROM, "B3"},
+ {0}
+ };
+ SVN_ERR(check_db_rows(&b, "", nodes));
+ }
+
+ return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+move_added(const svn_test_opts_t *opts, apr_pool_t *pool)
+{
+ svn_test__sandbox_t b;
+
+ SVN_ERR(svn_test__sandbox_create(&b, "move_added", opts, pool));
+
+ SVN_ERR(sbox_wc_mkdir(&b, "A"));
+ SVN_ERR(sbox_wc_mkdir(&b, "A/B"));
+ SVN_ERR(sbox_wc_commit(&b, ""));
+ SVN_ERR(sbox_wc_update(&b, "", 1));
+
+ SVN_ERR(sbox_wc_mkdir(&b, "A/B/C"));
+ SVN_ERR(sbox_wc_move(&b, "A", "A2"));
+ SVN_ERR(sbox_wc_mkdir(&b, "A2/B/C2"));
+
+ /* Both A2/B/C and A2/B/C2 are simple adds inside the move. It
+ doesn't seem right for A2/B/C to be marked moved_here. */
+ {
+ nodes_row_t nodes[] = {
+ {0, "", "normal", 1, ""},
+ {0, "A", "normal", 1, "A"},
+ {0, "A/B", "normal", 1, "A/B"},
+ {1, "A", "base-deleted", NO_COPY_FROM, "A2"},
+ {1, "A/B", "base-deleted", NO_COPY_FROM},
+ {1, "A2", "normal", 1, "A", MOVED_HERE},
+ {1, "A2/B", "normal", 1, "A/B", MOVED_HERE},
+ {3, "A2/B/C", "normal", NO_COPY_FROM},
+ {3, "A2/B/C2", "normal", NO_COPY_FROM},
+ {0}
+ };
+ SVN_ERR(check_db_rows(&b, "", nodes));
+ }
+
+ return SVN_NO_ERROR;
+}
+
+/* Test the result of 'update' when the incoming changes are inside a
+ * directory that is locally moved. */
+static svn_error_t *
+move_update(const svn_test_opts_t *opts, apr_pool_t *pool)
+{
+ svn_test__sandbox_t b;
+
+ SVN_ERR(svn_test__sandbox_create(&b, "move_update", opts, pool));
+
+ /* r1: Create files 'f', 'h' */
+ SVN_ERR(sbox_wc_mkdir(&b, "A"));
+ SVN_ERR(sbox_wc_mkdir(&b, "A/B"));
+ sbox_file_write(&b, "A/B/f", "r1 content\n");
+ sbox_file_write(&b, "A/B/h", "r1 content\n");
+ SVN_ERR(sbox_wc_add(&b, "A/B/f"));
+ SVN_ERR(sbox_wc_add(&b, "A/B/h"));
+ SVN_ERR(sbox_wc_commit(&b, ""));
+
+ /* r2: Modify 'f' */
+ sbox_file_write(&b, "A/B/f", "r1 content\nr2 content\n");
+ SVN_ERR(sbox_wc_commit(&b, ""));
+
+ /* r3: Delete 'h', add 'g' */
+ sbox_file_write(&b, "A/B/g", "r3 content\n");
+ SVN_ERR(sbox_wc_add(&b, "A/B/g"));
+ SVN_ERR(sbox_wc_delete(&b, "A/B/h"));
+ SVN_ERR(sbox_wc_commit(&b, ""));
+
+ /* r4: Add a new subtree 'X' */
+ SVN_ERR(sbox_wc_mkdir(&b, "X"));
+ sbox_file_write(&b, "X/f", "r4 content\n");
+ sbox_file_write(&b, "X/g", "r4 content\n");
+ sbox_file_write(&b, "X/h", "r4 content\n");
+ SVN_ERR(sbox_wc_add(&b, "X/f"));
+ SVN_ERR(sbox_wc_add(&b, "X/g"));
+ SVN_ERR(sbox_wc_add(&b, "X/h"));
+ SVN_ERR(sbox_wc_commit(&b, ""));
+
+ /* r5: Add a subtree 'A/B/C' */
+ SVN_ERR(sbox_wc_mkdir(&b, "A/B/C"));
+ SVN_ERR(sbox_wc_commit(&b, ""));
+
+ SVN_ERR(sbox_wc_update(&b, "", 1));
+
+ /* A is single-revision so A2 is a single-revision copy */
+ SVN_ERR(sbox_wc_move(&b, "A", "A2"));
+ {
+ nodes_row_t nodes[] = {
+ {0, "", "normal", 1, ""},
+ {0, "A", "normal", 1, "A"},
+ {0, "A/B", "normal", 1, "A/B"},
+ {0, "A/B/f", "normal", 1, "A/B/f"},
+ {0, "A/B/h", "normal", 1, "A/B/h"},
+ {1, "A", "base-deleted", NO_COPY_FROM, "A2"},
+ {1, "A/B", "base-deleted", NO_COPY_FROM},
+ {1, "A/B/f", "base-deleted", NO_COPY_FROM},
+ {1, "A/B/h", "base-deleted", NO_COPY_FROM},
+ {1, "A2", "normal", 1, "A", MOVED_HERE},
+ {1, "A2/B", "normal", 1, "A/B", MOVED_HERE},
+ {1, "A2/B/f", "normal", 1, "A/B/f", MOVED_HERE},
+ {1, "A2/B/h", "normal", 1, "A/B/h", MOVED_HERE},
+ {0}
+ };
+ SVN_ERR(check_db_rows(&b, "", nodes));
+ }
+
+ /* Update causes a tree-conflict on A due to incoming text-change. */
+ SVN_ERR(sbox_wc_update(&b, "", 2));
+ {
+ nodes_row_t nodes[] = {
+ {0, "", "normal", 2, ""},
+ {0, "A", "normal", 2, "A"},
+ {0, "A/B", "normal", 2, "A/B"},
+ {0, "A/B/f", "normal", 2, "A/B/f"},
+ {0, "A/B/h", "normal", 2, "A/B/h"},
+ {1, "A", "base-deleted", NO_COPY_FROM, "A2"},
+ {1, "A/B", "base-deleted", NO_COPY_FROM},
+ {1, "A/B/f", "base-deleted", NO_COPY_FROM},
+ {1, "A/B/h", "base-deleted", NO_COPY_FROM},
+ {1, "A2", "normal", 1, "A", MOVED_HERE},
+ {1, "A2/B", "normal", 1, "A/B", MOVED_HERE},
+ {1, "A2/B/f", "normal", 1, "A/B/f", MOVED_HERE},
+ {1, "A2/B/h", "normal", 1, "A/B/h", MOVED_HERE},
+ {0}
+ };
+ SVN_ERR(check_db_rows(&b, "", nodes));
+ }
+
+ /* Resolve should update the move. */
+ SVN_ERR(sbox_wc_resolve(&b, "A", svn_depth_empty,
+ svn_wc_conflict_choose_mine_conflict));
+ {
+ nodes_row_t nodes[] = {
+ {0, "", "normal", 2, ""},
+ {0, "A", "normal", 2, "A"},
+ {0, "A/B", "normal", 2, "A/B"},
+ {0, "A/B/f", "normal", 2, "A/B/f"},
+ {0, "A/B/h", "normal", 2, "A/B/h"},
+ {1, "A", "base-deleted", NO_COPY_FROM, "A2"},
+ {1, "A/B", "base-deleted", NO_COPY_FROM},
+ {1, "A/B/f", "base-deleted", NO_COPY_FROM},
+ {1, "A/B/h", "base-deleted", NO_COPY_FROM},
+ {1, "A2", "normal", 2, "A", MOVED_HERE},
+ {1, "A2/B", "normal", 2, "A/B", MOVED_HERE},
+ {1, "A2/B/f", "normal", 2, "A/B/f", MOVED_HERE},
+ {1, "A2/B/h", "normal", 2, "A/B/h", MOVED_HERE},
+ {0}
+ };
+ SVN_ERR(check_db_rows(&b, "", nodes));
+ }
+
+ /* Update causes a tree-conflict on due to incoming add. */
+ SVN_ERR(sbox_wc_update(&b, "", 3));
+ {
+ nodes_row_t nodes[] = {
+ {0, "", "normal", 3, ""},
+ {0, "A", "normal", 3, "A"},
+ {0, "A/B", "normal", 3, "A/B"},
+ {0, "A/B/f", "normal", 3, "A/B/f"},
+ {0, "A/B/g", "normal", 3, "A/B/g"},
+ {1, "A", "base-deleted", NO_COPY_FROM, "A2"},
+ {1, "A/B", "base-deleted", NO_COPY_FROM},
+ {1, "A/B/f", "base-deleted", NO_COPY_FROM},
+ {1, "A/B/g", "base-deleted", NO_COPY_FROM},
+ {1, "A2", "normal", 2, "A", MOVED_HERE},
+ {1, "A2/B", "normal", 2, "A/B", MOVED_HERE},
+ {1, "A2/B/f", "normal", 2, "A/B/f", MOVED_HERE},
+ {1, "A2/B/h", "normal", 2, "A/B/h", MOVED_HERE},
+ {0}
+ };
+ SVN_ERR(check_db_rows(&b, "", nodes));
+ }
+
+ SVN_ERR(sbox_wc_resolve(&b, "A", svn_depth_empty,
+ svn_wc_conflict_choose_mine_conflict));
+ {
+ nodes_row_t nodes[] = {
+ {0, "", "normal", 3, ""},
+ {0, "A", "normal", 3, "A"},
+ {0, "A/B", "normal", 3, "A/B"},
+ {0, "A/B/f", "normal", 3, "A/B/f"},
+ {0, "A/B/g", "normal", 3, "A/B/g"},
+ {1, "A", "base-deleted", NO_COPY_FROM, "A2"},
+ {1, "A/B", "base-deleted", NO_COPY_FROM},
+ {1, "A/B/f", "base-deleted", NO_COPY_FROM},
+ {1, "A/B/g", "base-deleted", NO_COPY_FROM},
+ {1, "A2", "normal", 3, "A", MOVED_HERE},
+ {1, "A2/B", "normal", 3, "A/B", MOVED_HERE},
+ {1, "A2/B/f", "normal", 3, "A/B/f", MOVED_HERE},
+ {1, "A2/B/g", "normal", 3, "A/B/g", MOVED_HERE},
+ {0}
+ };
+ SVN_ERR(check_db_rows(&b, "", nodes));
+ }
+
+ SVN_ERR(sbox_wc_delete(&b, "A2/B"));
+ {
+ nodes_row_t nodes[] = {
+ {0, "", "normal", 3, ""},
+ {0, "A", "normal", 3, "A"},
+ {0, "A/B", "normal", 3, "A/B"},
+ {0, "A/B/f", "normal", 3, "A/B/f"},
+ {0, "A/B/g", "normal", 3, "A/B/g"},
+ {1, "A", "base-deleted", NO_COPY_FROM, "A2"},
+ {1, "A/B", "base-deleted", NO_COPY_FROM},
+ {1, "A/B/f", "base-deleted", NO_COPY_FROM},
+ {1, "A/B/g", "base-deleted", NO_COPY_FROM},
+ {1, "A2", "normal", 3, "A", MOVED_HERE},
+ {1, "A2/B", "normal", 3, "A/B", MOVED_HERE},
+ {1, "A2/B/f", "normal", 3, "A/B/f", MOVED_HERE},
+ {1, "A2/B/g", "normal", 3, "A/B/g", MOVED_HERE},
+ {2, "A2/B", "base-deleted", NO_COPY_FROM},
+ {2, "A2/B/f", "base-deleted", NO_COPY_FROM},
+ {2, "A2/B/g", "base-deleted", NO_COPY_FROM},
+ {0}
+ };
+ SVN_ERR(check_db_rows(&b, "", nodes));
+ }
+
+ SVN_ERR(sbox_wc_update(&b, "", 2));
+ SVN_ERR(sbox_wc_resolve(&b, "A", svn_depth_empty,
+ svn_wc_conflict_choose_mine_conflict));
+ {
+ nodes_row_t nodes[] = {
+ {0, "", "normal", 2, ""},
+ {0, "A", "normal", 2, "A"},
+ {0, "A/B", "normal", 2, "A/B"},
+ {0, "A/B/f", "normal", 2, "A/B/f"},
+ {0, "A/B/h", "normal", 2, "A/B/h"},
+ {1, "A", "base-deleted", NO_COPY_FROM, "A2"},
+ {1, "A/B", "base-deleted", NO_COPY_FROM},
+ {1, "A/B/f", "base-deleted", NO_COPY_FROM},
+ {1, "A/B/h", "base-deleted", NO_COPY_FROM},
+ {1, "A2", "normal", 2, "A", MOVED_HERE},
+ {1, "A2/B", "normal", 2, "A/B", MOVED_HERE},
+ {1, "A2/B/f", "normal", 2, "A/B/f", MOVED_HERE},
+ {1, "A2/B/h", "normal", 2, "A/B/h", MOVED_HERE},
+ {2, "A2/B", "base-deleted", NO_COPY_FROM},
+ {2, "A2/B/f", "base-deleted", NO_COPY_FROM},
+ {2, "A2/B/h", "base-deleted", NO_COPY_FROM},
+ {0}
+ };
+ SVN_ERR(check_db_rows(&b, "", nodes));
+ }
+
+ SVN_ERR(sbox_wc_update(&b, "X", 4));
+ SVN_ERR(sbox_wc_copy(&b, "X", "A2/B"));
+ {
+ nodes_row_t nodes[] = {
+ {0, "", "normal", 2, ""},
+ {0, "A", "normal", 2, "A"},
+ {0, "A/B", "normal", 2, "A/B"},
+ {0, "A/B/f", "normal", 2, "A/B/f"},
+ {0, "A/B/h", "normal", 2, "A/B/h"},
+ {0, "X", "normal", 4, "X"},
+ {0, "X/f", "normal", 4, "X/f"},
+ {0, "X/g", "normal", 4, "X/g"},
+ {0, "X/h", "normal", 4, "X/h"},
+ {1, "A", "base-deleted", NO_COPY_FROM, "A2"},
+ {1, "A/B", "base-deleted", NO_COPY_FROM},
+ {1, "A/B/f", "base-deleted", NO_COPY_FROM},
+ {1, "A/B/h", "base-deleted", NO_COPY_FROM},
+ {1, "A2", "normal", 2, "A", MOVED_HERE},
+ {1, "A2/B", "normal", 2, "A/B", MOVED_HERE},
+ {1, "A2/B/f", "normal", 2, "A/B/f", MOVED_HERE},
+ {1, "A2/B/h", "normal", 2, "A/B/h", MOVED_HERE},
+ {2, "A2/B", "normal", 4, "X"},
+ {2, "A2/B/f", "normal", 4, "X/f"},
+ {2, "A2/B/g", "normal", 4, "X/g"},
+ {2, "A2/B/h", "normal", 4, "X/h"},
+ {0}
+ };
+ SVN_ERR(check_db_rows(&b, "", nodes));
+ }
+
+ SVN_ERR(sbox_wc_update(&b, "", 4));
+ SVN_ERR(sbox_wc_resolve(&b, "A", svn_depth_empty,
+ svn_wc_conflict_choose_mine_conflict));
+ {
+ nodes_row_t nodes[] = {
+ {0, "", "normal", 4, ""},
+ {0, "A", "normal", 4, "A"},
+ {0, "A/B", "normal", 4, "A/B"},
+ {0, "A/B/f", "normal", 4, "A/B/f"},
+ {0, "A/B/g", "normal", 4, "A/B/g"},
+ {0, "X", "normal", 4, "X"},
+ {0, "X/f", "normal", 4, "X/f"},
+ {0, "X/g", "normal", 4, "X/g"},
+ {0, "X/h", "normal", 4, "X/h"},
+ {1, "A", "base-deleted", NO_COPY_FROM, "A2"},
+ {1, "A/B", "base-deleted", NO_COPY_FROM},
+ {1, "A/B/f", "base-deleted", NO_COPY_FROM},
+ {1, "A/B/g", "base-deleted", NO_COPY_FROM},
+ {1, "A2", "normal", 4, "A", MOVED_HERE},
+ {1, "A2/B", "normal", 4, "A/B", MOVED_HERE},
+ {1, "A2/B/f", "normal", 4, "A/B/f", MOVED_HERE},
+ {1, "A2/B/g", "normal", 4, "A/B/g", MOVED_HERE},
+ {2, "A2/B", "normal", 4, "X"},
+ {2, "A2/B/f", "normal", 4, "X/f"},
+ {2, "A2/B/g", "normal", 4, "X/g"},
+ {2, "A2/B/h", "normal", 4, "X/h"},
+ {0}
+ };
+ SVN_ERR(check_db_rows(&b, "", nodes));
+ }
+
+ SVN_ERR(sbox_wc_update(&b, "", 5));
+ SVN_ERR(sbox_wc_resolve(&b, "A", svn_depth_empty,
+ svn_wc_conflict_choose_mine_conflict));
+ {
+ nodes_row_t nodes[] = {
+ {0, "", "normal", 5, ""},
+ {0, "A", "normal", 5, "A"},
+ {0, "A/B", "normal", 5, "A/B"},
+ {0, "A/B/f", "normal", 5, "A/B/f"},
+ {0, "A/B/g", "normal", 5, "A/B/g"},
+ {0, "A/B/C", "normal", 5, "A/B/C"},
+ {0, "X", "normal", 5, "X"},
+ {0, "X/f", "normal", 5, "X/f"},
+ {0, "X/g", "normal", 5, "X/g"},
+ {0, "X/h", "normal", 5, "X/h"},
+ {1, "A", "base-deleted", NO_COPY_FROM, "A2"},
+ {1, "A/B", "base-deleted", NO_COPY_FROM},
+ {1, "A/B/f", "base-deleted", NO_COPY_FROM},
+ {1, "A/B/g", "base-deleted", NO_COPY_FROM},
+ {1, "A/B/C", "base-deleted", NO_COPY_FROM},
+ {1, "A2", "normal", 5, "A", MOVED_HERE},
+ {1, "A2/B", "normal", 5, "A/B", MOVED_HERE},
+ {1, "A2/B/f", "normal", 5, "A/B/f", MOVED_HERE},
+ {1, "A2/B/g", "normal", 5, "A/B/g", MOVED_HERE},
+ {1, "A2/B/C", "normal", 5, "A/B/C", MOVED_HERE},
+ {2, "A2/B", "normal", 4, "X"},
+ {2, "A2/B/f", "normal", 4, "X/f"},
+ {2, "A2/B/g", "normal", 4, "X/g"},
+ {2, "A2/B/h", "normal", 4, "X/h"},
+ {2, "A2/B/C", "base-deleted", NO_COPY_FROM},
+ {0}
+ };
+ SVN_ERR(check_db_rows(&b, "", nodes));
+ }
+
+
+ return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+check_moved_to(apr_array_header_t *moved_tos,
+ int i,
+ int op_depth,
+ const char *local_relpath)
+{
+ struct svn_wc__db_moved_to_t *moved_to;
+
+ if (i >= moved_tos->nelts)
+ return svn_error_createf(SVN_ERR_TEST_FAILED, NULL,
+ "moved-to %d not found", i);
+
+ moved_to = APR_ARRAY_IDX(moved_tos, i, struct svn_wc__db_moved_to_t *);
+
+ if (moved_to->op_depth != op_depth
+ || strcmp(moved_to->local_relpath, local_relpath))
+ return svn_error_createf(SVN_ERR_TEST_FAILED, NULL,
+ "expected: {%d '%s'} found[%d]: {%d '%s'}",
+ op_depth, local_relpath, i,
+ moved_to->op_depth, moved_to->local_relpath);
+
+ return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+test_scan_delete(const svn_test_opts_t *opts, apr_pool_t *pool)
+{
+ svn_test__sandbox_t b;
+ const char *moved_to_abspath, *moved_to_op_root_abspath;
+ apr_array_header_t *moved_tos;
+
+ SVN_ERR(svn_test__sandbox_create(&b, "scan_delete", opts, pool));
+
+ SVN_ERR(sbox_wc_mkdir(&b, "A"));
+ SVN_ERR(sbox_wc_mkdir(&b, "A/B"));
+ SVN_ERR(sbox_wc_mkdir(&b, "A/B/C"));
+ SVN_ERR(sbox_wc_mkdir(&b, "A2"));
+ SVN_ERR(sbox_wc_mkdir(&b, "A2/B"));
+ SVN_ERR(sbox_wc_mkdir(&b, "C2"));
+ SVN_ERR(sbox_wc_commit(&b, ""));
+ SVN_ERR(sbox_wc_update(&b, "", 1));
+
+ SVN_ERR(sbox_wc_move(&b, "A2", "X"));
+ SVN_ERR(sbox_wc_move(&b, "X/B", "Z"));
+ SVN_ERR(sbox_wc_move(&b, "A/B", "X/B"));
+ SVN_ERR(sbox_wc_move(&b, "X/B/C", "Y"));
+ SVN_ERR(sbox_wc_move(&b, "C2", "X/B/C"));
+
+ {
+ nodes_row_t nodes[] = {
+ {0, "", "normal", 1, ""},
+ {0, "A", "normal", 1, "A"},
+ {0, "A/B", "normal", 1, "A/B"},
+ {0, "A/B/C", "normal", 1, "A/B/C"},
+ {0, "A2", "normal", 1, "A2"},
+ {0, "A2/B", "normal", 1, "A2/B"},
+ {0, "C2", "normal", 1, "C2"},
+ {1, "A2", "base-deleted", NO_COPY_FROM, "X"},
+ {1, "A2/B", "base-deleted", NO_COPY_FROM},
+ {1, "Z", "normal", 1, "A2/B", MOVED_HERE},
+ {1, "X", "normal", 1, "A2", MOVED_HERE},
+ {1, "X/B", "normal", 1, "A2/B", MOVED_HERE},
+ {2, "A/B", "base-deleted", NO_COPY_FROM, "X/B"},
+ {2, "A/B/C", "base-deleted", NO_COPY_FROM},
+ {2, "X/B", "normal", 1, "A/B", FALSE, "Z", TRUE},
+ {2, "X/B/C", "normal", 1, "A/B/C", MOVED_HERE},
+ {1, "Y", "normal", 1, "A/B/C", MOVED_HERE},
+ {1, "C2", "base-deleted", NO_COPY_FROM, "X/B/C"},
+ {3, "X/B/C", "normal", 1, "C2", FALSE, "Y", TRUE},
+ {0}
+ };
+ SVN_ERR(check_db_rows(&b, "", nodes));
+ }
+
+ SVN_ERR(svn_wc__db_scan_deletion(NULL, &moved_to_abspath,
+ NULL, &moved_to_op_root_abspath,
+ b.wc_ctx->db, sbox_wc_path(&b, "C2"),
+ pool, pool));
+ SVN_TEST_STRING_ASSERT(moved_to_abspath, sbox_wc_path(&b, "X/B/C"));
+ SVN_TEST_STRING_ASSERT(moved_to_op_root_abspath, sbox_wc_path(&b, "X/B/C"));
+
+ SVN_ERR(svn_wc__db_scan_deletion(NULL, &moved_to_abspath,
+ NULL, &moved_to_op_root_abspath,
+ b.wc_ctx->db, sbox_wc_path(&b, "A/B"),
+ pool, pool));
+ SVN_TEST_STRING_ASSERT(moved_to_abspath, sbox_wc_path(&b, "X/B"));
+ SVN_TEST_STRING_ASSERT(moved_to_op_root_abspath, sbox_wc_path(&b, "X/B"));
+
+ SVN_ERR(svn_wc__db_follow_moved_to(&moved_tos, b.wc_ctx->db,
+ sbox_wc_path(&b, "A/B/C"), pool, pool));
+ SVN_ERR(check_moved_to(moved_tos, 0, 2, "X/B/C"));
+ SVN_ERR(check_moved_to(moved_tos, 1, 3, "Y"));
+ SVN_TEST_ASSERT(moved_tos->nelts == 2);
+
+ SVN_ERR(svn_wc__db_scan_deletion(NULL, &moved_to_abspath,
+ NULL, &moved_to_op_root_abspath,
+ b.wc_ctx->db, sbox_wc_path(&b, "A/B/C"),
+ pool, pool));
+ SVN_TEST_STRING_ASSERT(moved_to_abspath, sbox_wc_path(&b, "X/B/C"));
+ SVN_TEST_STRING_ASSERT(moved_to_op_root_abspath, sbox_wc_path(&b, "X/B"));
+
+ SVN_ERR(svn_wc__db_scan_deletion(NULL, &moved_to_abspath,
+ NULL, &moved_to_op_root_abspath,
+ b.wc_ctx->db, sbox_wc_path(&b, "A2"),
+ pool, pool));
+ SVN_TEST_STRING_ASSERT(moved_to_abspath, sbox_wc_path(&b, "X"));
+ SVN_TEST_STRING_ASSERT(moved_to_op_root_abspath, sbox_wc_path(&b, "X"));
+
+ SVN_ERR(svn_wc__db_scan_deletion(NULL, &moved_to_abspath,
+ NULL, &moved_to_op_root_abspath,
+ b.wc_ctx->db, sbox_wc_path(&b, "A2/B"),
+ pool, pool));
+ SVN_TEST_STRING_ASSERT(moved_to_abspath, sbox_wc_path(&b, "X/B"));
+ SVN_TEST_STRING_ASSERT(moved_to_op_root_abspath, sbox_wc_path(&b, "X"));
+
+ return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+test_follow_moved_to(const svn_test_opts_t *opts, apr_pool_t *pool)
+{
+ svn_test__sandbox_t b;
+ apr_array_header_t *moved_tos;
+
+ SVN_ERR(svn_test__sandbox_create(&b, "follow_moved_to", opts, pool));
+
+ SVN_ERR(sbox_wc_mkdir(&b, "A1"));
+ SVN_ERR(sbox_wc_mkdir(&b, "A1/B"));
+ SVN_ERR(sbox_wc_mkdir(&b, "A1/B/C"));
+ SVN_ERR(sbox_wc_mkdir(&b, "A1/B/C/D"));
+ SVN_ERR(sbox_wc_mkdir(&b, "A1/B/C/D/E"));
+ SVN_ERR(sbox_wc_mkdir(&b, "A2"));
+ SVN_ERR(sbox_wc_mkdir(&b, "A2/B"));
+ SVN_ERR(sbox_wc_mkdir(&b, "A2/B/C"));
+ SVN_ERR(sbox_wc_mkdir(&b, "A2/B/C/D"));
+ SVN_ERR(sbox_wc_mkdir(&b, "A2/B/C/D/E"));
+ SVN_ERR(sbox_wc_mkdir(&b, "A3"));
+ SVN_ERR(sbox_wc_mkdir(&b, "A3/B"));
+ SVN_ERR(sbox_wc_mkdir(&b, "A3/B/C"));
+ SVN_ERR(sbox_wc_mkdir(&b, "A3/B/C/D"));
+ SVN_ERR(sbox_wc_mkdir(&b, "A3/B/C/D/E"));
+ SVN_ERR(sbox_wc_commit(&b, ""));
+ SVN_ERR(sbox_wc_update(&b, "", 1));
+
+ {
+ nodes_row_t nodes[] = {
+ {0, "", "normal", 1, ""},
+ {0, "A1", "normal", 1, "A1"},
+ {0, "A1/B", "normal", 1, "A1/B"},
+ {0, "A1/B/C", "normal", 1, "A1/B/C"},
+ {0, "A1/B/C/D", "normal", 1, "A1/B/C/D"},
+ {0, "A1/B/C/D/E", "normal", 1, "A1/B/C/D/E"},
+ {0, "A2", "normal", 1, "A2"},
+ {0, "A2/B", "normal", 1, "A2/B"},
+ {0, "A2/B/C", "normal", 1, "A2/B/C"},
+ {0, "A2/B/C/D", "normal", 1, "A2/B/C/D"},
+ {0, "A2/B/C/D/E", "normal", 1, "A2/B/C/D/E"},
+ {0, "A3", "normal", 1, "A3"},
+ {0, "A3/B", "normal", 1, "A3/B"},
+ {0, "A3/B/C", "normal", 1, "A3/B/C"},
+ {0, "A3/B/C/D", "normal", 1, "A3/B/C/D"},
+ {0, "A3/B/C/D/E", "normal", 1, "A3/B/C/D/E"},
+ {0}
+ };
+ SVN_ERR(check_db_rows(&b, "", nodes));
+ }
+
+ SVN_ERR(sbox_wc_move(&b, "A1", "X"));
+ SVN_ERR(sbox_wc_move(&b, "A2", "A1"));
+ SVN_ERR(sbox_wc_move(&b, "A3", "A2"));
+ SVN_ERR(sbox_wc_move(&b, "X", "A3"));
+ SVN_ERR(sbox_wc_move(&b, "A1/B", "X"));
+ SVN_ERR(sbox_wc_move(&b, "A2/B", "A1/B"));
+ SVN_ERR(sbox_wc_move(&b, "A3/B", "A2/B"));
+ SVN_ERR(sbox_wc_move(&b, "X", "A3/B"));
+ SVN_ERR(sbox_wc_move(&b, "A1/B/C/D", "X"));
+ SVN_ERR(sbox_wc_move(&b, "A2/B/C/D", "A1/B/C/D"));
+ SVN_ERR(sbox_wc_move(&b, "A3/B/C/D", "A2/B/C/D"));
+ SVN_ERR(sbox_wc_move(&b, "X", "A3/B/C/D"));
+ SVN_ERR(sbox_wc_move(&b, "A1/B/C/D/E", "X"));
+ SVN_ERR(sbox_wc_move(&b, "A2/B/C/D/E", "A1/B/C/D/E"));
+ SVN_ERR(sbox_wc_move(&b, "A3/B/C/D/E", "A2/B/C/D/E"));
+ SVN_ERR(sbox_wc_move(&b, "X", "A3/B/C/D/E"));
+
+ {
+ nodes_row_t nodes[] = {
+ {0, "", "normal", 1, ""},
+ {0, "A1", "normal", 1, "A1"},
+ {0, "A1/B", "normal", 1, "A1/B"},
+ {0, "A1/B/C", "normal", 1, "A1/B/C"},
+ {0, "A1/B/C/D", "normal", 1, "A1/B/C/D"},
+ {0, "A1/B/C/D/E", "normal", 1, "A1/B/C/D/E"},
+ {0, "A2", "normal", 1, "A2"},
+ {0, "A2/B", "normal", 1, "A2/B"},
+ {0, "A2/B/C", "normal", 1, "A2/B/C"},
+ {0, "A2/B/C/D", "normal", 1, "A2/B/C/D"},
+ {0, "A2/B/C/D/E", "normal", 1, "A2/B/C/D/E"},
+ {0, "A3", "normal", 1, "A3"},
+ {0, "A3/B", "normal", 1, "A3/B"},
+ {0, "A3/B/C", "normal", 1, "A3/B/C"},
+ {0, "A3/B/C/D", "normal", 1, "A3/B/C/D"},
+ {0, "A3/B/C/D/E", "normal", 1, "A3/B/C/D/E"},
+
+ {1, "A1", "normal", 1, "A2", FALSE, "A3", TRUE},
+ {1, "A1/B", "normal", 1, "A2/B", MOVED_HERE},
+ {1, "A1/B/C", "normal", 1, "A2/B/C", MOVED_HERE},
+ {1, "A1/B/C/D", "normal", 1, "A2/B/C/D", MOVED_HERE},
+ {1, "A1/B/C/D/E", "normal", 1, "A2/B/C/D/E", MOVED_HERE},
+
+ {1, "A2", "normal", 1, "A3", FALSE, "A1", TRUE},
+ {1, "A2/B", "normal", 1, "A3/B", MOVED_HERE},
+ {1, "A2/B/C", "normal", 1, "A3/B/C", MOVED_HERE},
+ {1, "A2/B/C/D", "normal", 1, "A3/B/C/D", MOVED_HERE},
+ {1, "A2/B/C/D/E", "normal", 1, "A3/B/C/D/E", MOVED_HERE},
+
+ {1, "A3", "normal", 1, "A1", FALSE, "A2", TRUE},
+ {1, "A3/B", "normal", 1, "A1/B", MOVED_HERE},
+ {1, "A3/B/C", "normal", 1, "A1/B/C", MOVED_HERE},
+ {1, "A3/B/C/D", "normal", 1, "A1/B/C/D", MOVED_HERE},
+ {1, "A3/B/C/D/E", "normal", 1, "A1/B/C/D/E", MOVED_HERE},
+
+ {2, "A1/B", "normal", 1, "A3/B", FALSE, "A3/B", TRUE},
+ {2, "A1/B/C", "normal", 1, "A3/B/C", MOVED_HERE},
+ {2, "A1/B/C/D", "normal", 1, "A3/B/C/D", MOVED_HERE},
+ {2, "A1/B/C/D/E", "normal", 1, "A3/B/C/D/E", MOVED_HERE},
+
+ {2, "A2/B", "normal", 1, "A1/B", FALSE, "A1/B", TRUE},
+ {2, "A2/B/C", "normal", 1, "A1/B/C", MOVED_HERE},
+ {2, "A2/B/C/D", "normal", 1, "A1/B/C/D", MOVED_HERE},
+ {2, "A2/B/C/D/E", "normal", 1, "A1/B/C/D/E", MOVED_HERE},
+
+ {2, "A3/B", "normal", 1, "A2/B", FALSE, "A2/B", TRUE},
+ {2, "A3/B/C", "normal", 1, "A2/B/C", MOVED_HERE},
+ {2, "A3/B/C/D", "normal", 1, "A2/B/C/D", MOVED_HERE},
+ {2, "A3/B/C/D/E", "normal", 1, "A2/B/C/D/E", MOVED_HERE},
+
+ {4, "A1/B/C/D", "normal", 1, "A1/B/C/D", FALSE, "A3/B/C/D", TRUE},
+ {4, "A1/B/C/D/E", "normal", 1, "A1/B/C/D/E", MOVED_HERE},
+
+ {4, "A2/B/C/D", "normal", 1, "A2/B/C/D", FALSE, "A1/B/C/D", TRUE},
+ {4, "A2/B/C/D/E", "normal", 1, "A2/B/C/D/E", MOVED_HERE},
+
+ {4, "A3/B/C/D", "normal", 1, "A3/B/C/D", FALSE, "A2/B/C/D", TRUE},
+ {4, "A3/B/C/D/E", "normal", 1, "A3/B/C/D/E", MOVED_HERE},
+
+ {5, "A1/B/C/D/E", "normal", 1, "A2/B/C/D/E", FALSE, "A3/B/C/D/E", TRUE},
+ {5, "A2/B/C/D/E", "normal", 1, "A3/B/C/D/E", FALSE, "A1/B/C/D/E", TRUE},
+ {5, "A3/B/C/D/E", "normal", 1, "A1/B/C/D/E", FALSE, "A2/B/C/D/E", TRUE},
+ {0}
+ };
+ SVN_ERR(check_db_rows(&b, "", nodes));
+ }
+
+ /* A1->A3, A3/B->A2/B, A2/B/C/D->A1/B/C/D, A1/B/C/D/E->A3/B/C/D/E */
+ SVN_ERR(svn_wc__db_follow_moved_to(&moved_tos, b.wc_ctx->db,
+ sbox_wc_path(&b, "A1"), pool, pool));
+ SVN_ERR(check_moved_to(moved_tos, 0, 1, "A3"));
+ SVN_TEST_ASSERT(moved_tos->nelts == 1);
+
+ SVN_ERR(svn_wc__db_follow_moved_to(&moved_tos, b.wc_ctx->db,
+ sbox_wc_path(&b, "A1/B"), pool, pool));
+ SVN_ERR(check_moved_to(moved_tos, 0, 1, "A3/B"));
+ SVN_ERR(check_moved_to(moved_tos, 1, 2, "A2/B"));
+ SVN_TEST_ASSERT(moved_tos->nelts == 2);
+
+ SVN_ERR(svn_wc__db_follow_moved_to(&moved_tos, b.wc_ctx->db,
+ sbox_wc_path(&b, "A1/B/C"), pool, pool));
+ SVN_ERR(check_moved_to(moved_tos, 0, 1, "A3/B/C"));
+ SVN_ERR(check_moved_to(moved_tos, 1, 2, "A2/B/C"));
+ SVN_TEST_ASSERT(moved_tos->nelts == 2);
+
+ SVN_ERR(svn_wc__db_follow_moved_to(&moved_tos, b.wc_ctx->db,
+ sbox_wc_path(&b, "A1/B/C/D"), pool, pool));
+ SVN_ERR(check_moved_to(moved_tos, 0, 1, "A3/B/C/D"));
+ SVN_ERR(check_moved_to(moved_tos, 1, 2, "A2/B/C/D"));
+ SVN_ERR(check_moved_to(moved_tos, 2, 4, "A1/B/C/D"));
+ SVN_TEST_ASSERT(moved_tos->nelts == 3);
+
+ SVN_ERR(svn_wc__db_follow_moved_to(&moved_tos, b.wc_ctx->db,
+ sbox_wc_path(&b, "A1/B/C/D/E"), pool, pool));
+ SVN_ERR(check_moved_to(moved_tos, 0, 1, "A3/B/C/D/E"));
+ SVN_ERR(check_moved_to(moved_tos, 1, 2, "A2/B/C/D/E"));
+ SVN_ERR(check_moved_to(moved_tos, 2, 4, "A1/B/C/D/E"));
+ SVN_ERR(check_moved_to(moved_tos, 3, 5, "A3/B/C/D/E"));
+ SVN_TEST_ASSERT(moved_tos->nelts == 4);
+
+ SVN_ERR(sbox_wc_delete(&b, "A3/B/C/D/E"));
+ SVN_ERR(svn_wc__db_follow_moved_to(&moved_tos, b.wc_ctx->db,
+ sbox_wc_path(&b, "A1/B/C/D/E"), pool, pool));
+ SVN_ERR(check_moved_to(moved_tos, 0, 1, "A3/B/C/D/E"));
+ SVN_ERR(check_moved_to(moved_tos, 1, 2, "A2/B/C/D/E"));
+ SVN_ERR(check_moved_to(moved_tos, 2, 4, "A1/B/C/D/E"));
+ SVN_TEST_ASSERT(moved_tos->nelts == 3);
+
+ return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+mixed_rev_move(const svn_test_opts_t *opts, apr_pool_t *pool)
+{
+ svn_test__sandbox_t b;
+ apr_array_header_t *moved_tos;
+
+ SVN_ERR(svn_test__sandbox_create(&b, "mixed_rev_move", opts, pool));
+
+ SVN_ERR(sbox_wc_mkdir(&b, "A"));
+ SVN_ERR(sbox_wc_commit(&b, ""));
+ SVN_ERR(sbox_wc_mkdir(&b, "A/B"));
+ SVN_ERR(sbox_wc_commit(&b, ""));
+ SVN_ERR(sbox_wc_mkdir(&b, "A/B/C"));
+ SVN_ERR(sbox_wc_commit(&b, ""));
+
+ {
+ nodes_row_t nodes[] = {
+ {0, "", "normal", 0, ""},
+ {0, "A", "normal", 1, "A"},
+ {0, "A/B", "normal", 2, "A/B"},
+ {0, "A/B/C", "normal", 3, "A/B/C"},
+ {0}
+ };
+ SVN_ERR(check_db_rows(&b, "", nodes));
+ }
+
+ /* We don't allow mixed-rev move in 1.8 and the command line client
+ will return an error, but for compatibility with 1.7 move has an
+ allow_mixed_revisions=TRUE flag which is being used here so the
+ move transforms automatically into copy+delete. This test was
+ written before that transforming was implemented so still expects
+ some move information. */
+ SVN_ERR(sbox_wc_move(&b, "A", "X"));
+
+ {
+ nodes_row_t nodes[] = {
+ {0, "", "normal", 0, ""},
+ {0, "A", "normal", 1, "A"},
+ {0, "A/B", "normal", 2, "A/B"},
+ {0, "A/B/C", "normal", 3, "A/B/C"},
+ {1, "A", "base-deleted", NO_COPY_FROM, "X"},
+ {1, "A/B", "base-deleted", NO_COPY_FROM},
+ {1, "A/B/C", "base-deleted", NO_COPY_FROM},
+ {1, "X", "normal", 1, "A", MOVED_HERE},
+ {1, "X/B", "not-present", 2, "A/B"},
+ {2, "X/B", "normal", 2, "A/B"},
+ {2, "X/B/C", "not-present", 3, "A/B/C"},
+ {3, "X/B/C", "normal", 3, "A/B/C"},
+ {0}
+ };
+ SVN_ERR(check_db_rows(&b, "", nodes));
+ }
+
+ /* ### These values PASS but I'm not sure they are correct. */
+ SVN_ERR(svn_wc__db_follow_moved_to(&moved_tos, b.wc_ctx->db,
+ sbox_wc_path(&b, "A/B/C"), pool, pool));
+ SVN_ERR(check_moved_to(moved_tos, 0, 1, "X/B/C"));
+ SVN_TEST_ASSERT(moved_tos->nelts == 1);
+
+ SVN_ERR(svn_wc__db_follow_moved_to(&moved_tos, b.wc_ctx->db,
+ sbox_wc_path(&b, "A/B"), pool, pool));
+ SVN_ERR(check_moved_to(moved_tos, 0, 1, "X/B"));
+ SVN_TEST_ASSERT(moved_tos->nelts == 1);
+
+ SVN_ERR(svn_wc__db_follow_moved_to(&moved_tos, b.wc_ctx->db,
+ sbox_wc_path(&b, "A"), pool, pool));
+ SVN_ERR(check_moved_to(moved_tos, 0, 1, "X"));
+ SVN_TEST_ASSERT(moved_tos->nelts == 1);
+
+
+ /* This move doesn't record moved-to */
+ SVN_ERR(sbox_wc_move(&b, "X/B", "X/Y"));
+
+ {
+ nodes_row_t nodes[] = {
+ {0, "", "normal", 0, ""},
+ {0, "A", "normal", 1, "A"},
+ {0, "A/B", "normal", 2, "A/B"},
+ {0, "A/B/C", "normal", 3, "A/B/C"},
+ {1, "A", "base-deleted", NO_COPY_FROM, "X"},
+ {1, "A/B", "base-deleted", NO_COPY_FROM},
+ {1, "A/B/C", "base-deleted", NO_COPY_FROM},
+ {1, "X", "normal", 1, "A", MOVED_HERE},
+ {1, "X/B", "not-present", 2, "A/B"},
+ {2, "X/Y", "normal", 2, "A/B"},
+ {2, "X/Y/C", "not-present", NO_COPY_FROM},
+ {3, "X/Y/C", "normal", 3, "A/B/C"},
+ {0}
+ };
+ SVN_ERR(check_db_rows(&b, "", nodes));
+ }
+
+ SVN_ERR(svn_wc__db_follow_moved_to(&moved_tos, b.wc_ctx->db,
+ sbox_wc_path(&b, "A/B/C"), pool, pool));
+ SVN_TEST_ASSERT(moved_tos->nelts == 0);
+
+ SVN_ERR(svn_wc__db_follow_moved_to(&moved_tos, b.wc_ctx->db,
+ sbox_wc_path(&b, "A/B"), pool, pool));
+ SVN_TEST_ASSERT(moved_tos->nelts == 0);
+
+ SVN_ERR(svn_wc__db_follow_moved_to(&moved_tos, b.wc_ctx->db,
+ sbox_wc_path(&b, "A"), pool, pool));
+ SVN_ERR(check_moved_to(moved_tos, 0, 1, "X"));
+ SVN_TEST_ASSERT(moved_tos->nelts == 1);
+
+ return SVN_NO_ERROR;
+}
+
+/* Test the result of 'update' when the incoming changes are inside a
+ * directory that is locally moved. */
+static svn_error_t *
+update_prop_mod_into_moved(const svn_test_opts_t *opts, apr_pool_t *pool)
+{
+ svn_test__sandbox_t b;
+
+ SVN_ERR(svn_test__sandbox_create(&b, "update_prop_mod_into_moved", opts, pool));
+
+ /* r1: Create files 'f', 'h' */
+ SVN_ERR(sbox_wc_mkdir(&b, "A"));
+ SVN_ERR(sbox_wc_mkdir(&b, "A/B"));
+ sbox_file_write(&b, "A/B/f", "r1 content\n");
+ sbox_file_write(&b, "A/B/h", "r1 content\n");
+ SVN_ERR(sbox_wc_add(&b, "A/B/f"));
+ SVN_ERR(sbox_wc_add(&b, "A/B/h"));
+ SVN_ERR(sbox_wc_propset(&b, "pd", "f1", "A/B/f"));
+ SVN_ERR(sbox_wc_propset(&b, "pn", "f1", "A/B/f"));
+ SVN_ERR(sbox_wc_propset(&b, "pm", "f1", "A/B/f"));
+ SVN_ERR(sbox_wc_propset(&b, "p", "h1", "A/B/h"));
+ SVN_ERR(sbox_wc_commit(&b, ""));
+
+ /* r2: Modify 'f'. Delete prop 'pd', modify prop 'pm', add prop 'pa',
+ * leave prop 'pn' unchanged. */
+ sbox_file_write(&b, "A/B/f", "r1 content\nr2 content\n");
+ SVN_ERR(sbox_wc_propset(&b, "pd", NULL, "A/B/f"));
+ SVN_ERR(sbox_wc_propset(&b, "pm", "f2", "A/B/f"));
+ SVN_ERR(sbox_wc_propset(&b, "pa", "f2", "A/B/f"));
+ SVN_ERR(sbox_wc_commit(&b, ""));
+
+ /* r3: Delete 'h', add 'g' */
+ sbox_file_write(&b, "A/B/g", "r3 content\n");
+ SVN_ERR(sbox_wc_add(&b, "A/B/g"));
+ SVN_ERR(sbox_wc_propset(&b, "p", "g3", "A/B/g"));
+ SVN_ERR(sbox_wc_delete(&b, "A/B/h"));
+ SVN_ERR(sbox_wc_commit(&b, ""));
+
+ SVN_ERR(sbox_wc_update(&b, "", 1));
+ {
+ nodes_row_t nodes[] = {
+ {0, "", "normal", 1, ""},
+ {0, "A", "normal", 1, "A"},
+ {0, "A/B", "normal", 1, "A/B"},
+ {0, "A/B/f", "normal", 1, "A/B/f", NOT_MOVED, "pd,pm,pn"},
+ {0, "A/B/h", "normal", 1, "A/B/h", NOT_MOVED, "p"},
+ {0}
+ };
+ SVN_ERR(check_db_rows(&b, "", nodes));
+ }
+
+ /* A is single-revision so A2 is a single-revision copy */
+ SVN_ERR(sbox_wc_move(&b, "A", "A2"));
+ {
+ nodes_row_t nodes[] = {
+ {0, "", "normal", 1, ""},
+ {0, "A", "normal", 1, "A"},
+ {0, "A/B", "normal", 1, "A/B"},
+ {0, "A/B/f", "normal", 1, "A/B/f", NOT_MOVED, "pd,pm,pn"},
+ {0, "A/B/h", "normal", 1, "A/B/h", NOT_MOVED, "p"},
+ {1, "A", "base-deleted", NO_COPY_FROM, "A2"},
+ {1, "A/B", "base-deleted", NO_COPY_FROM},
+ {1, "A/B/f", "base-deleted", NO_COPY_FROM},
+ {1, "A/B/h", "base-deleted", NO_COPY_FROM},
+ {1, "A2", "normal", 1, "A", MOVED_HERE},
+ {1, "A2/B", "normal", 1, "A/B", MOVED_HERE},
+ {1, "A2/B/f", "normal", 1, "A/B/f", MOVED_HERE, "pd,pm,pn"},
+ {1, "A2/B/h", "normal", 1, "A/B/h", MOVED_HERE, "p"},
+ {0}
+ };
+ SVN_ERR(check_db_rows(&b, "", nodes));
+ }
+
+ /* Update causes a tree-conflict on A due to incoming text-change. */
+ SVN_ERR(sbox_wc_update(&b, "", 2));
+ {
+ nodes_row_t nodes[] = {
+ {0, "", "normal", 2, ""},
+ {0, "A", "normal", 2, "A"},
+ {0, "A/B", "normal", 2, "A/B"},
+ {0, "A/B/f", "normal", 2, "A/B/f", NOT_MOVED, "pa,pm,pn"},
+ {0, "A/B/h", "normal", 2, "A/B/h", NOT_MOVED, "p"},
+ {1, "A", "base-deleted", NO_COPY_FROM, "A2"},
+ {1, "A/B", "base-deleted", NO_COPY_FROM},
+ {1, "A/B/f", "base-deleted", NO_COPY_FROM},
+ {1, "A/B/h", "base-deleted", NO_COPY_FROM},
+ {1, "A2", "normal", 1, "A", MOVED_HERE},
+ {1, "A2/B", "normal", 1, "A/B", MOVED_HERE},
+ {1, "A2/B/f", "normal", 1, "A/B/f", MOVED_HERE, "pd,pm,pn"},
+ {1, "A2/B/h", "normal", 1, "A/B/h", MOVED_HERE, "p"},
+ {0}
+ };
+ SVN_ERR(check_db_rows(&b, "", nodes));
+ }
+
+ /* Resolve should update the move. */
+ SVN_ERR(sbox_wc_resolve(&b, "A", svn_depth_empty,
+ svn_wc_conflict_choose_mine_conflict));
+ {
+ nodes_row_t nodes[] = {
+ {0, "", "normal", 2, ""},
+ {0, "A", "normal", 2, "A"},
+ {0, "A/B", "normal", 2, "A/B"},
+ {0, "A/B/f", "normal", 2, "A/B/f", NOT_MOVED, "pa,pm,pn"},
+ {0, "A/B/h", "normal", 2, "A/B/h", NOT_MOVED, "p"},
+ {1, "A", "base-deleted", NO_COPY_FROM, "A2"},
+ {1, "A/B", "base-deleted", NO_COPY_FROM},
+ {1, "A/B/f", "base-deleted", NO_COPY_FROM},
+ {1, "A/B/h", "base-deleted", NO_COPY_FROM},
+ {1, "A2", "normal", 2, "A", MOVED_HERE},
+ {1, "A2/B", "normal", 2, "A/B", MOVED_HERE},
+ {1, "A2/B/f", "normal", 2, "A/B/f", MOVED_HERE, "pa,pm,pn"},
+ {1, "A2/B/h", "normal", 2, "A/B/h", MOVED_HERE, "p"},
+ {0}
+ };
+ SVN_ERR(check_db_rows(&b, "", nodes));
+ }
+
+ return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+nested_move_update(const svn_test_opts_t *opts, apr_pool_t *pool)
+{
+ svn_test__sandbox_t b;
+
+ SVN_ERR(svn_test__sandbox_create(&b, "nested_move_update", opts, pool));
+
+ /* r1: Create file 'f' */
+ SVN_ERR(sbox_wc_mkdir(&b, "A"));
+ SVN_ERR(sbox_wc_mkdir(&b, "A/B"));
+ SVN_ERR(sbox_wc_mkdir(&b, "A/B/C"));
+ sbox_file_write(&b, "A/B/C/f", "r1 content\n");
+ SVN_ERR(sbox_wc_add(&b, "A/B/C/f"));
+ SVN_ERR(sbox_wc_commit(&b, ""));
+
+ /* r2: Modify 'f' */
+ sbox_file_write(&b, "A/B/C/f", "r1 content\nr2 content\n");
+ SVN_ERR(sbox_wc_commit(&b, ""));
+
+ /* r3: Create 'X' */
+ SVN_ERR(sbox_wc_mkdir(&b, "X"));
+ SVN_ERR(sbox_wc_commit(&b, ""));
+
+ SVN_ERR(sbox_wc_update(&b, "", 1));
+
+ SVN_ERR(sbox_wc_move(&b, "A", "A2"));
+ SVN_ERR(sbox_wc_move(&b, "A2/B/C", "A2/B/C2"));
+ {
+ nodes_row_t nodes[] = {
+ {0, "", "normal", 1, ""},
+ {0, "A", "normal", 1, "A"},
+ {0, "A/B", "normal", 1, "A/B"},
+ {0, "A/B/C", "normal", 1, "A/B/C"},
+ {0, "A/B/C/f", "normal", 1, "A/B/C/f"},
+ {1, "A", "base-deleted", NO_COPY_FROM, "A2"},
+ {1, "A/B", "base-deleted", NO_COPY_FROM},
+ {1, "A/B/C", "base-deleted", NO_COPY_FROM},
+ {1, "A/B/C/f", "base-deleted", NO_COPY_FROM},
+ {1, "A2", "normal", 1, "A", MOVED_HERE},
+ {1, "A2/B", "normal", 1, "A/B", MOVED_HERE},
+ {1, "A2/B/C", "normal", 1, "A/B/C", MOVED_HERE},
+ {1, "A2/B/C/f", "normal", 1, "A/B/C/f", MOVED_HERE},
+ {3, "A2/B/C", "base-deleted", NO_COPY_FROM, "A2/B/C2"},
+ {3, "A2/B/C/f", "base-deleted", NO_COPY_FROM},
+ {3, "A2/B/C2", "normal", 1, "A/B/C", MOVED_HERE},
+ {3, "A2/B/C2/f", "normal", 1, "A/B/C/f", MOVED_HERE},
+ {0}
+ };
+ SVN_ERR(check_db_rows(&b, "", nodes));
+ }
+
+ SVN_ERR(sbox_wc_update(&b, "", 2));
+
+ /* Following the A->A2 move should raise a tree-conflict on A2/B/C,
+ resolving that may require an explicit resolve. */
+ SVN_ERR(sbox_wc_resolve(&b, "A", svn_depth_empty,
+ svn_wc_conflict_choose_mine_conflict));
+ SVN_ERR(sbox_wc_resolve(&b, "A2/B/C", svn_depth_empty,
+ svn_wc_conflict_choose_mine_conflict));
+ {
+ nodes_row_t nodes[] = {
+ {0, "", "normal", 2, ""},
+ {0, "A", "normal", 2, "A"},
+ {0, "A/B", "normal", 2, "A/B"},
+ {0, "A/B/C", "normal", 2, "A/B/C"},
+ {0, "A/B/C/f", "normal", 2, "A/B/C/f"},
+ {1, "A", "base-deleted", NO_COPY_FROM, "A2"},
+ {1, "A/B", "base-deleted", NO_COPY_FROM},
+ {1, "A/B/C", "base-deleted", NO_COPY_FROM},
+ {1, "A/B/C/f", "base-deleted", NO_COPY_FROM},
+ {1, "A2", "normal", 2, "A", MOVED_HERE},
+ {1, "A2/B", "normal", 2, "A/B", MOVED_HERE},
+ {1, "A2/B/C", "normal", 2, "A/B/C", MOVED_HERE},
+ {1, "A2/B/C/f", "normal", 2, "A/B/C/f", MOVED_HERE},
+ {3, "A2/B/C", "base-deleted", NO_COPY_FROM, "A2/B/C2"},
+ {3, "A2/B/C/f", "base-deleted", NO_COPY_FROM},
+ {3, "A2/B/C2", "normal", 2, "A/B/C", MOVED_HERE},
+ {3, "A2/B/C2/f", "normal", 2, "A/B/C/f", MOVED_HERE},
+ {0}
+ };
+ SVN_ERR(check_db_rows(&b, "", nodes));
+ }
+
+ /* Update A to r3 brings no changes but updates the revisions. */
+ SVN_ERR(sbox_wc_update(&b, "A", 3));
+ {
+ nodes_row_t nodes[] = {
+ {0, "", "normal", 2, ""},
+ {0, "A", "normal", 3, "A"},
+ {0, "A/B", "normal", 3, "A/B"},
+ {0, "A/B/C", "normal", 3, "A/B/C"},
+ {0, "A/B/C/f", "normal", 3, "A/B/C/f"},
+ {1, "A", "base-deleted", NO_COPY_FROM, "A2"},
+ {1, "A/B", "base-deleted", NO_COPY_FROM},
+ {1, "A/B/C", "base-deleted", NO_COPY_FROM},
+ {1, "A/B/C/f", "base-deleted", NO_COPY_FROM},
+ {1, "A2", "normal", 3, "A", MOVED_HERE},
+ {1, "A2/B", "normal", 3, "A/B", MOVED_HERE},
+ {1, "A2/B/C", "normal", 3, "A/B/C", MOVED_HERE},
+ {1, "A2/B/C/f", "normal", 3, "A/B/C/f", MOVED_HERE},
+ {3, "A2/B/C", "base-deleted", NO_COPY_FROM, "A2/B/C2"},
+ {3, "A2/B/C/f", "base-deleted", NO_COPY_FROM},
+ {3, "A2/B/C2", "normal", 3, "A/B/C", MOVED_HERE},
+ {3, "A2/B/C2/f", "normal", 3, "A/B/C/f", MOVED_HERE},
+ {0}
+ };
+ SVN_ERR(check_db_rows(&b, "", nodes));
+ }
+
+ return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+nested_move_commit(const svn_test_opts_t *opts, apr_pool_t *pool)
+{
+ svn_test__sandbox_t b;
+
+ SVN_ERR(svn_test__sandbox_create(&b, "nested_move_commit", opts, pool));
+
+ /* r1: Create file 'f' */
+ SVN_ERR(sbox_wc_mkdir(&b, "A"));
+ SVN_ERR(sbox_wc_mkdir(&b, "A/B"));
+ SVN_ERR(sbox_wc_mkdir(&b, "A/B/C"));
+ sbox_file_write(&b, "A/B/C/f", "r1 content\n");
+ SVN_ERR(sbox_wc_add(&b, "A/B/C/f"));
+ SVN_ERR(sbox_wc_commit(&b, ""));
+ SVN_ERR(sbox_wc_update(&b, "", 1));
+
+ SVN_ERR(sbox_wc_move(&b, "A/B/C", "C2"));
+
+ {
+ const char *moved_to;
+ const char *expected_to;
+ SVN_ERR(svn_wc__db_scan_deletion(NULL, NULL, NULL, &moved_to,
+ b.wc_ctx->db, sbox_wc_path(&b, "A/B/C"),
+ pool, pool));
+
+ expected_to = sbox_wc_path(&b, "C2");
+
+ if (strcmp(moved_to, expected_to) != 0)
+ return svn_error_createf(SVN_ERR_TEST_FAILED, NULL,
+ "Expected moved to %s, but was %s",
+ expected_to, moved_to);
+ }
+ {
+ const char *moved_from;
+ const char *expected_from;
+ SVN_ERR(svn_wc__db_scan_moved(&moved_from, NULL, NULL, NULL,
+ b.wc_ctx->db, sbox_wc_path(&b, "C2"),
+ pool, pool));
+
+ expected_from = sbox_wc_path(&b, "A/B/C");
+
+ if (strcmp(moved_from, expected_from) != 0)
+ return svn_error_createf(SVN_ERR_TEST_FAILED, NULL,
+ "Expected moved from %s, but was %s",
+ expected_from, moved_from);
+ }
+
+ SVN_ERR(sbox_wc_move(&b, "A", "A2"));
+ {
+ nodes_row_t nodes[] = {
+ {0, "", "normal", 1, ""},
+ {0, "A", "normal", 1, "A"},
+ {0, "A/B", "normal", 1, "A/B"},
+ {0, "A/B/C", "normal", 1, "A/B/C"},
+ {0, "A/B/C/f", "normal", 1, "A/B/C/f"},
+ {1, "A", "base-deleted", NO_COPY_FROM, "A2"},
+ {1, "A/B", "base-deleted", NO_COPY_FROM},
+ {1, "A/B/C", "base-deleted", NO_COPY_FROM},
+ {1, "A/B/C/f", "base-deleted", NO_COPY_FROM},
+ {1, "A2", "normal", 1, "A", MOVED_HERE},
+ {1, "A2/B", "normal", 1, "A/B", MOVED_HERE},
+ {1, "A2/B/C", "normal", 1, "A/B/C", MOVED_HERE},
+ {1, "A2/B/C/f", "normal", 1, "A/B/C/f", MOVED_HERE},
+ {3, "A2/B/C", "base-deleted", NO_COPY_FROM, "C2"},
+ {3, "A2/B/C/f", "base-deleted", NO_COPY_FROM},
+ {1, "C2", "normal", 1, "A/B/C", MOVED_HERE},
+ {1, "C2/f", "normal", 1, "A/B/C/f", MOVED_HERE},
+ {0}
+ };
+ SVN_ERR(check_db_rows(&b, "", nodes));
+ }
+
+ {
+ const char *moved_to;
+ const char *expected_to;
+ SVN_ERR(svn_wc__db_scan_deletion(NULL, NULL, NULL, &moved_to,
+ b.wc_ctx->db, sbox_wc_path(&b, "A/B/C"),
+ pool, pool));
+
+ /* A/B/C is part of the A->A2 move. */
+ expected_to = sbox_wc_path(&b, "A2");
+ if (strcmp(moved_to, expected_to) != 0)
+ return svn_error_createf(SVN_ERR_TEST_FAILED, NULL,
+ "Expected moved to %s, but was %s",
+ expected_to, moved_to);
+
+ SVN_ERR(svn_wc__db_scan_deletion(NULL, NULL, NULL, &moved_to,
+ b.wc_ctx->db, sbox_wc_path(&b, "A2/B/C"),
+ pool, pool));
+
+ /* A2/B/C is the A2/B/C->C2 move. */
+ expected_to = sbox_wc_path(&b, "C2");
+ if (strcmp(moved_to, expected_to) != 0)
+ return svn_error_createf(SVN_ERR_TEST_FAILED, NULL,
+ "Expected moved to %s, but was %s",
+ expected_to, moved_to);
+ }
+ {
+ const char *moved_from;
+ const char *expected_from;
+ SVN_ERR(svn_wc__db_scan_moved(&moved_from, NULL, NULL, NULL,
+ b.wc_ctx->db, sbox_wc_path(&b, "C2"),
+ pool, pool));
+
+ /* C2 is the A2/B/C->C2 move. */
+ expected_from = sbox_wc_path(&b, "A2/B/C");
+ if (strcmp(moved_from, expected_from) != 0)
+ return svn_error_createf(SVN_ERR_TEST_FAILED, NULL,
+ "Expected moved from %s, but was %s",
+ expected_from, moved_from);
+ }
+
+ {
+ apr_array_header_t *targets = apr_array_make(pool, 2, sizeof(const char *));
+
+ APR_ARRAY_PUSH(targets, const char *) = sbox_wc_path(&b, "A");
+ APR_ARRAY_PUSH(targets, const char *) = sbox_wc_path(&b, "A2");
+
+ SVN_ERR(sbox_wc_commit_ex(&b, targets, svn_depth_empty));
+ }
+
+ {
+ nodes_row_t nodes[] = {
+ {0, "", "normal", 1, ""},
+ {0, "A", "not-present", 2, "A"},
+ {0, "A2", "normal", 2, "A2"},
+ {0, "A2/B", "normal", 2, "A2/B"},
+ {0, "A2/B/C", "normal", 2, "A2/B/C"},
+ {0, "A2/B/C/f", "normal", 2, "A2/B/C/f"},
+ {3, "A2/B/C", "base-deleted", NO_COPY_FROM, "C2"},
+ {3, "A2/B/C/f", "base-deleted", NO_COPY_FROM},
+
+ /* These need to have their copyfrom information updated */
+ {1, "C2", "normal", 2, "A2/B/C", MOVED_HERE},
+ {1, "C2/f", "normal", 2, "A2/B/C/f", MOVED_HERE},
+ {0}
+ };
+ SVN_ERR(check_db_rows(&b, "", nodes));
+ }
+
+ {
+ const char *moved_to;
+ const char *expected_to;
+ SVN_ERR(svn_wc__db_scan_deletion(NULL, NULL, NULL, &moved_to,
+ b.wc_ctx->db, sbox_wc_path(&b, "A2/B/C"),
+ pool, pool));
+
+ expected_to = sbox_wc_path(&b, "C2");
+
+ if (strcmp(moved_to, expected_to) != 0)
+ return svn_error_createf(SVN_ERR_TEST_FAILED, NULL,
+ "Expected moved to %s, but was %s",
+ expected_to, moved_to);
+ }
+
+ {
+ const char *moved_from;
+ const char *expected_from;
+ SVN_ERR(svn_wc__db_scan_moved(&moved_from, NULL, NULL, NULL,
+ b.wc_ctx->db, sbox_wc_path(&b, "C2"),
+ pool, pool));
+
+ expected_from = sbox_wc_path(&b, "A2/B/C");
+
+ if (strcmp(moved_from, expected_from) != 0)
+ return svn_error_createf(SVN_ERR_TEST_FAILED, NULL,
+ "Expected moved from %s, but was %s",
+ expected_from, moved_from);
+ }
+
+ return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+nested_move_update2(const svn_test_opts_t *opts, apr_pool_t *pool)
+{
+ svn_test__sandbox_t b;
+
+ SVN_ERR(svn_test__sandbox_create(&b, "nested_move_update2", opts, pool));
+
+ SVN_ERR(sbox_wc_mkdir(&b, "A"));
+ SVN_ERR(sbox_wc_mkdir(&b, "A/B"));
+ SVN_ERR(sbox_wc_mkdir(&b, "P"));
+ SVN_ERR(sbox_wc_mkdir(&b, "P/Q"));
+ SVN_ERR(sbox_wc_commit(&b, ""));
+ SVN_ERR(sbox_wc_mkdir(&b, "X"));
+ SVN_ERR(sbox_wc_commit(&b, ""));
+ SVN_ERR(sbox_wc_update(&b, "", 1));
+ SVN_ERR(sbox_wc_move(&b, "A", "A2"));
+ SVN_ERR(sbox_wc_move(&b, "P", "A"));
+ SVN_ERR(sbox_wc_move(&b, "A2", "P"));
+ SVN_ERR(sbox_wc_move(&b, "A/Q", "A/Q2"));
+ SVN_ERR(sbox_wc_move(&b, "P/B", "P/B2"));
+
+ {
+ nodes_row_t nodes[] = {
+ {0, "", "normal", 1, ""},
+ {0, "A", "normal", 1, "A"},
+ {0, "A/B", "normal", 1, "A/B"},
+ {0, "P", "normal", 1, "P"},
+ {0, "P/Q", "normal", 1, "P/Q"},
+ {1, "A", "normal", 1, "P", FALSE, "P", TRUE},
+ {1, "A/B", "base-deleted", NO_COPY_FROM},
+ {1, "A/Q", "normal", 1, "P/Q", MOVED_HERE},
+ {1, "P", "normal", 1, "A", FALSE, "A", TRUE},
+ {1, "P/Q", "base-deleted", NO_COPY_FROM},
+ {1, "P/B", "normal", 1, "A/B", MOVED_HERE},
+ {2, "A/Q", "base-deleted", NO_COPY_FROM, "A/Q2"},
+ {2, "A/Q2", "normal", 1, "P/Q", MOVED_HERE},
+ {2, "P/B", "base-deleted", NO_COPY_FROM, "P/B2"},
+ {2, "P/B2", "normal", 1, "A/B", MOVED_HERE},
+ {0}
+ };
+ SVN_ERR(check_db_rows(&b, "", nodes));
+ }
+
+ /* Update A bumps revisions but only for moves originating in A. In
+ particular A/Q to A/Q2 does not get bumped. */
+ SVN_ERR(sbox_wc_update(&b, "A", 2));
+ {
+ nodes_row_t nodes[] = {
+ {0, "", "normal", 1, ""},
+ {0, "A", "normal", 2, "A"},
+ {0, "A/B", "normal", 2, "A/B"},
+ {0, "P", "normal", 1, "P"},
+ {0, "P/Q", "normal", 1, "P/Q"},
+ {1, "A", "normal", 1, "P", FALSE, "P", TRUE},
+ {1, "A/B", "base-deleted", NO_COPY_FROM},
+ {1, "A/Q", "normal", 1, "P/Q", MOVED_HERE},
+ {1, "P", "normal", 2, "A", FALSE, "A", TRUE},
+ {1, "P/Q", "base-deleted", NO_COPY_FROM},
+ {1, "P/B", "normal", 2, "A/B", MOVED_HERE},
+ {2, "A/Q", "base-deleted", NO_COPY_FROM, "A/Q2"},
+ {2, "A/Q2", "normal", 1, "P/Q", MOVED_HERE},
+ {2, "P/B", "base-deleted", NO_COPY_FROM, "P/B2"},
+ {2, "P/B2", "normal", 2, "A/B", MOVED_HERE},
+ {0}
+ };
+ SVN_ERR(check_db_rows(&b, "", nodes));
+ }
+
+ return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+check_tree_conflict_repos_path(svn_test__sandbox_t *b,
+ const char *wc_path,
+ const char *repos_path1,
+ const char *repos_path2)
+{
+ svn_skel_t *conflict;
+ svn_wc_operation_t operation;
+ const apr_array_header_t *locations;
+ svn_boolean_t text_conflicted, prop_conflicted, tree_conflicted;
+
+ SVN_ERR(svn_wc__db_read_conflict(&conflict, b->wc_ctx->db,
+ sbox_wc_path(b, wc_path),
+ b->pool, b->pool));
+
+ SVN_ERR(svn_wc__conflict_read_info(&operation, &locations,
+ &text_conflicted, &prop_conflicted,
+ &tree_conflicted,
+ b->wc_ctx->db, b->wc_abspath,
+ conflict, b->pool, b->pool));
+
+ SVN_ERR_ASSERT(tree_conflicted);
+
+ if (repos_path1)
+ {
+ svn_wc_conflict_version_t *version
+ = APR_ARRAY_IDX(locations, 0, svn_wc_conflict_version_t *);
+
+ SVN_ERR_ASSERT(!strcmp(version->path_in_repos, repos_path1));
+ }
+
+ if (repos_path2)
+ {
+ svn_wc_conflict_version_t *version
+ = APR_ARRAY_IDX(locations, 1, svn_wc_conflict_version_t *);
+
+ SVN_ERR_ASSERT(!strcmp(version->path_in_repos, repos_path2));
+ }
+
+ return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+move_update_conflicts(const svn_test_opts_t *opts, apr_pool_t *pool)
+{
+ svn_test__sandbox_t b;
+
+ SVN_ERR(svn_test__sandbox_create(&b, "move_update_conflicts", opts, pool));
+
+ SVN_ERR(sbox_wc_mkdir(&b, "X"));
+ SVN_ERR(sbox_wc_mkdir(&b, "X/A"));
+ SVN_ERR(sbox_wc_mkdir(&b, "X/A/B"));
+ SVN_ERR(sbox_wc_mkdir(&b, "X/A/B/C"));
+ SVN_ERR(sbox_wc_mkdir(&b, "X/A/B/C/D"));
+ SVN_ERR(sbox_wc_commit(&b, ""));
+ SVN_ERR(sbox_wc_mkdir(&b, "X/A/B/C/D/E"));
+ SVN_ERR(sbox_wc_mkdir(&b, "X/A/B/F"));
+ SVN_ERR(sbox_wc_commit(&b, ""));
+ SVN_ERR(sbox_wc_switch(&b, "", "/X", svn_depth_infinity));
+ SVN_ERR(sbox_wc_update(&b, "", 1));
+ SVN_ERR(sbox_wc_move(&b, "A", "A2"));
+ SVN_ERR(sbox_wc_move(&b, "A2/B/C", "A2/B/C2"));
+ sbox_file_write(&b, "A2/B/F", "obstruction\n");
+
+ {
+ nodes_row_t nodes[] = {
+ {0, "", "normal", 1, "X"},
+ {0, "A", "normal", 1, "X/A"},
+ {0, "A/B", "normal", 1, "X/A/B"},
+ {0, "A/B/C", "normal", 1, "X/A/B/C"},
+ {0, "A/B/C/D", "normal", 1, "X/A/B/C/D"},
+ {1, "A", "base-deleted", NO_COPY_FROM, "A2"},
+ {1, "A/B", "base-deleted", NO_COPY_FROM},
+ {1, "A/B/C", "base-deleted", NO_COPY_FROM},
+ {1, "A/B/C/D", "base-deleted", NO_COPY_FROM},
+ {1, "A2", "normal", 1, "X/A", MOVED_HERE},
+ {1, "A2/B", "normal", 1, "X/A/B", MOVED_HERE},
+ {1, "A2/B/C", "normal", 1, "X/A/B/C", MOVED_HERE},
+ {1, "A2/B/C/D", "normal", 1, "X/A/B/C/D", MOVED_HERE},
+ {3, "A2/B/C", "base-deleted", NO_COPY_FROM, "A2/B/C2"},
+ {3, "A2/B/C/D", "base-deleted", NO_COPY_FROM},
+ {3, "A2/B/C2", "normal", 1, "X/A/B/C", MOVED_HERE},
+ {3, "A2/B/C2/D", "normal", 1, "X/A/B/C/D", MOVED_HERE},
+ {0}
+ };
+ SVN_ERR(check_db_rows(&b, "", nodes));
+ }
+
+ SVN_ERR(sbox_wc_update(&b, "A", 2));
+ SVN_ERR(check_tree_conflict_repos_path(&b, "A", "X/A", "X/A"));
+ SVN_ERR(sbox_wc_resolve(&b, "A", svn_depth_empty,
+ svn_wc_conflict_choose_mine_conflict));
+ {
+ nodes_row_t nodes[] = {
+ {0, "", "normal", 1, "X"},
+ {0, "A", "normal", 2, "X/A"},
+ {0, "A/B", "normal", 2, "X/A/B"},
+ {0, "A/B/C", "normal", 2, "X/A/B/C"},
+ {0, "A/B/C/D", "normal", 2, "X/A/B/C/D"},
+ {0, "A/B/C/D/E", "normal", 2, "X/A/B/C/D/E"},
+ {0, "A/B/F", "normal", 2, "X/A/B/F"},
+ {1, "A", "base-deleted", NO_COPY_FROM, "A2"},
+ {1, "A/B", "base-deleted", NO_COPY_FROM},
+ {1, "A/B/C", "base-deleted", NO_COPY_FROM},
+ {1, "A/B/C/D", "base-deleted", NO_COPY_FROM},
+ {1, "A/B/C/D/E", "base-deleted", NO_COPY_FROM},
+ {1, "A/B/F", "base-deleted", NO_COPY_FROM},
+ {1, "A2", "normal", 2, "X/A", MOVED_HERE},
+ {1, "A2/B", "normal", 2, "X/A/B", MOVED_HERE},
+ {1, "A2/B/C", "normal", 2, "X/A/B/C", MOVED_HERE},
+ {1, "A2/B/C/D", "normal", 2, "X/A/B/C/D", MOVED_HERE},
+ {1, "A2/B/C/D/E", "normal", 2, "X/A/B/C/D/E", MOVED_HERE},
+ {1, "A2/B/F", "normal", 2, "X/A/B/F", MOVED_HERE},
+ {3, "A2/B/C", "base-deleted", NO_COPY_FROM, "A2/B/C2"},
+ {3, "A2/B/C/D", "base-deleted", NO_COPY_FROM},
+ {3, "A2/B/C/D/E", "base-deleted", NO_COPY_FROM},
+ {3, "A2/B/C2", "normal", 1, "X/A/B/C", MOVED_HERE},
+ {3, "A2/B/C2/D", "normal", 1, "X/A/B/C/D", MOVED_HERE},
+ {0}
+ };
+ SVN_ERR(check_db_rows(&b, "", nodes));
+ }
+
+ SVN_ERR(check_tree_conflict_repos_path(&b, "A2/B/C", "X/A/B/C", "X/A/B/C"));
+ SVN_ERR(check_tree_conflict_repos_path(&b, "A2/B/F", NULL, "X/A/B/F"));
+
+ return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+move_update_delete_mods(const svn_test_opts_t *opts, apr_pool_t *pool)
+{
+ svn_test__sandbox_t b;
+
+ SVN_ERR(svn_test__sandbox_create(&b, "move_update_delete_mods", opts, pool));
+
+ SVN_ERR(sbox_wc_mkdir(&b, "A"));
+ SVN_ERR(sbox_wc_mkdir(&b, "A/B"));
+ SVN_ERR(sbox_wc_mkdir(&b, "A/B/C"));
+ SVN_ERR(sbox_wc_mkdir(&b, "A/B/D"));
+ sbox_file_write(&b, "A/B/C/f", "r1 content\n");
+ SVN_ERR(sbox_wc_add(&b, "A/B/C/f"));
+ SVN_ERR(sbox_wc_commit(&b, ""));
+ SVN_ERR(sbox_wc_delete(&b, "A/B/C"));
+ SVN_ERR(sbox_wc_delete(&b, "A/B/D"));
+ SVN_ERR(sbox_wc_commit(&b, ""));
+ SVN_ERR(sbox_wc_update(&b, "", 1));
+
+ SVN_ERR(sbox_wc_move(&b, "A/B", "B2"));
+ sbox_file_write(&b, "B2/C/f", "modified content\n");
+ SVN_ERR(sbox_wc_delete(&b, "B2/D"));
+ {
+ nodes_row_t nodes[] = {
+ {0, "", "normal", 1, ""},
+ {0, "A", "normal", 1, "A"},
+ {0, "A/B", "normal", 1, "A/B"},
+ {0, "A/B/C", "normal", 1, "A/B/C"},
+ {0, "A/B/C/f", "normal", 1, "A/B/C/f"},
+ {0, "A/B/D", "normal", 1, "A/B/D"},
+ {2, "A/B", "base-deleted", NO_COPY_FROM, "B2"},
+ {2, "A/B/C", "base-deleted", NO_COPY_FROM},
+ {2, "A/B/C/f", "base-deleted", NO_COPY_FROM},
+ {2, "A/B/D", "base-deleted", NO_COPY_FROM},
+ {1, "B2", "normal", 1, "A/B", MOVED_HERE},
+ {1, "B2/C", "normal", 1, "A/B/C", MOVED_HERE},
+ {1, "B2/C/f", "normal", 1, "A/B/C/f", MOVED_HERE},
+ {1, "B2/D", "normal", 1, "A/B/D", MOVED_HERE},
+ {2, "B2/D", "base-deleted", NO_COPY_FROM},
+ {0}
+ };
+ SVN_ERR(check_db_rows(&b, "", nodes));
+ }
+
+ SVN_ERR(sbox_wc_update(&b, "A", 2));
+ SVN_ERR(sbox_wc_resolve(&b, "A/B", svn_depth_empty,
+ svn_wc_conflict_choose_mine_conflict));
+ {
+ nodes_row_t nodes[] = {
+ {0, "", "normal", 1, ""},
+ {0, "A", "normal", 2, "A"},
+ {0, "A/B", "normal", 2, "A/B"},
+ {2, "A/B", "base-deleted", NO_COPY_FROM, "B2"},
+ {1, "B2", "normal", 2, "A/B", MOVED_HERE},
+ {2, "B2/C", "normal", 1, "A/B/C"},
+ {2, "B2/C/f", "normal", 1, "A/B/C/f"},
+ {0}
+ };
+ SVN_ERR(check_db_rows(&b, "", nodes));
+ }
+
+ SVN_ERR(check_tree_conflict_repos_path(&b, "B2/C", "A/B/C", "A/B/C"));
+ SVN_ERR(check_tree_conflict_repos_path(&b, "B2/D", "A/B/D", "A/B/D"));
+
+ return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+nested_moves2(const svn_test_opts_t *opts, apr_pool_t *pool)
+{
+ svn_test__sandbox_t b;
+
+ SVN_ERR(svn_test__sandbox_create(&b, "nested_moves2", opts, pool));
+
+ SVN_ERR(sbox_wc_mkdir(&b, "A"));
+ SVN_ERR(sbox_wc_mkdir(&b, "A/A"));
+ SVN_ERR(sbox_wc_mkdir(&b, "A/A/A"));
+ SVN_ERR(sbox_wc_mkdir(&b, "A/A/A/A"));
+ SVN_ERR(sbox_wc_mkdir(&b, "A/A/A/A/A"));
+ SVN_ERR(sbox_wc_mkdir(&b, "A/A/A/A/A/A"));
+ SVN_ERR(sbox_wc_commit(&b, ""));
+ SVN_ERR(sbox_wc_mkdir(&b, "X"));
+ SVN_ERR(sbox_wc_commit(&b, ""));
+
+ SVN_ERR(sbox_wc_move(&b, "A/A/A/A/A/A", "C"));
+ SVN_ERR(sbox_wc_move(&b, "A/A/A/A", "D"));
+ SVN_ERR(sbox_wc_move(&b, "A/A", "E"));
+
+ {
+ nodes_row_t nodes[] = {
+ {0, "", "normal", 0, ""},
+ {0, "X", "normal", 2, "X"},
+ {0, "A", "normal", 1, "A"},
+ {0, "A/A", "normal", 1, "A/A"},
+ {0, "A/A/A", "normal", 1, "A/A/A"},
+ {0, "A/A/A/A", "normal", 1, "A/A/A/A"},
+ {0, "A/A/A/A/A", "normal", 1, "A/A/A/A/A"},
+ {0, "A/A/A/A/A/A", "normal", 1, "A/A/A/A/A/A"},
+ {2, "A/A", "base-deleted", NO_COPY_FROM, "E"},
+ {2, "A/A/A", "base-deleted", NO_COPY_FROM},
+ {2, "A/A/A/A", "base-deleted", NO_COPY_FROM},
+ {2, "A/A/A/A/A", "base-deleted", NO_COPY_FROM},
+ {2, "A/A/A/A/A/A", "base-deleted", NO_COPY_FROM},
+ {1, "E", "normal", 1, "A/A", MOVED_HERE},
+ {1, "E/A", "normal", 1, "A/A/A", MOVED_HERE},
+ {1, "E/A/A", "normal", 1, "A/A/A/A", MOVED_HERE},
+ {1, "E/A/A/A", "normal", 1, "A/A/A/A/A", MOVED_HERE},
+ {1, "E/A/A/A/A", "normal", 1, "A/A/A/A/A/A", MOVED_HERE},
+ {3, "E/A/A", "base-deleted", NO_COPY_FROM, "D"},
+ {3, "E/A/A/A", "base-deleted", NO_COPY_FROM},
+ {3, "E/A/A/A/A", "base-deleted", NO_COPY_FROM},
+ {1, "D", "normal", 1, "A/A/A/A", MOVED_HERE},
+ {1, "D/A", "normal", 1, "A/A/A/A/A", MOVED_HERE},
+ {1, "D/A/A", "normal", 1, "A/A/A/A/A/A", MOVED_HERE},
+ {3, "D/A/A", "base-deleted", NO_COPY_FROM, "C"},
+ {1, "C", "normal", 1, "A/A/A/A/A/A", MOVED_HERE},
+ {0}
+ };
+ SVN_ERR(check_db_rows(&b, "", nodes));
+ }
+
+ SVN_ERR(sbox_wc_update(&b, "A", 2));
+ {
+ nodes_row_t nodes[] = {
+ {0, "", "normal", 0, ""},
+ {0, "X", "normal", 2, "X"},
+ {0, "A", "normal", 2, "A"},
+ {0, "A/A", "normal", 2, "A/A"},
+ {0, "A/A/A", "normal", 2, "A/A/A"},
+ {0, "A/A/A/A", "normal", 2, "A/A/A/A"},
+ {0, "A/A/A/A/A", "normal", 2, "A/A/A/A/A"},
+ {0, "A/A/A/A/A/A", "normal", 2, "A/A/A/A/A/A"},
+ {2, "A/A", "base-deleted", NO_COPY_FROM, "E"},
+ {2, "A/A/A", "base-deleted", NO_COPY_FROM},
+ {2, "A/A/A/A", "base-deleted", NO_COPY_FROM},
+ {2, "A/A/A/A/A", "base-deleted", NO_COPY_FROM},
+ {2, "A/A/A/A/A/A", "base-deleted", NO_COPY_FROM},
+ {1, "E", "normal", 2, "A/A", MOVED_HERE},
+ {1, "E/A", "normal", 2, "A/A/A", MOVED_HERE},
+ {1, "E/A/A", "normal", 2, "A/A/A/A", MOVED_HERE},
+ {1, "E/A/A/A", "normal", 2, "A/A/A/A/A", MOVED_HERE},
+ {1, "E/A/A/A/A", "normal", 2, "A/A/A/A/A/A", MOVED_HERE},
+ {3, "E/A/A", "base-deleted", NO_COPY_FROM, "D"},
+ {3, "E/A/A/A", "base-deleted", NO_COPY_FROM},
+ {3, "E/A/A/A/A", "base-deleted", NO_COPY_FROM},
+ {1, "D", "normal", 2, "A/A/A/A", MOVED_HERE},
+ {1, "D/A", "normal", 2, "A/A/A/A/A", MOVED_HERE},
+ {1, "D/A/A", "normal", 2, "A/A/A/A/A/A", MOVED_HERE},
+ {3, "D/A/A", "base-deleted", NO_COPY_FROM, "C"},
+ {1, "C", "normal", 2, "A/A/A/A/A/A", MOVED_HERE},
+ {0}
+ };
+ SVN_ERR(check_db_rows(&b, "", nodes));
+ }
+
+ return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+move_in_delete(const svn_test_opts_t *opts, apr_pool_t *pool)
+{
+ svn_test__sandbox_t b;
+
+ SVN_ERR(svn_test__sandbox_create(&b, "move_in_delete", opts, pool));
+
+ SVN_ERR(sbox_wc_mkdir(&b, "A"));
+ SVN_ERR(sbox_wc_mkdir(&b, "A/B"));
+ SVN_ERR(sbox_wc_mkdir(&b, "A/B/C"));
+ SVN_ERR(sbox_wc_commit(&b, ""));
+ SVN_ERR(sbox_wc_mkdir(&b, "A/B/C/D"));
+ SVN_ERR(sbox_wc_commit(&b, ""));
+ SVN_ERR(sbox_wc_mkdir(&b, "A/B/C/D/E"));
+ SVN_ERR(sbox_wc_commit(&b, ""));
+ SVN_ERR(sbox_wc_mkdir(&b, "X"));
+ SVN_ERR(sbox_wc_commit(&b, ""));
+ SVN_ERR(sbox_wc_update(&b, "", 1));
+
+ SVN_ERR(sbox_wc_move(&b, "A/B/C", "C2"));
+ SVN_ERR(sbox_wc_delete(&b, "A/B"));
+ {
+ nodes_row_t nodes[] = {
+ {0, "", "normal", 1, ""},
+ {0, "A", "normal", 1, "A"},
+ {0, "A/B", "normal", 1, "A/B"},
+ {0, "A/B/C", "normal", 1, "A/B/C"},
+ {2, "A/B", "base-deleted", NO_COPY_FROM},
+ {2, "A/B/C", "base-deleted", NO_COPY_FROM, "C2"},
+ {1, "C2", "normal", 1, "A/B/C", MOVED_HERE},
+ {0}
+ };
+ SVN_ERR(check_db_rows(&b, "", nodes));
+ }
+
+ SVN_ERR(sbox_wc_update(&b, "", 2));
+ SVN_ERR(sbox_wc_resolve(&b, "A/B", svn_depth_empty,
+ svn_wc_conflict_choose_mine_conflict));
+ SVN_ERR(sbox_wc_resolve(&b, "A/B/C", svn_depth_empty,
+ svn_wc_conflict_choose_mine_conflict));
+ {
+ nodes_row_t nodes[] = {
+ {0, "", "normal", 2, ""},
+ {0, "A", "normal", 2, "A"},
+ {0, "A/B", "normal", 2, "A/B"},
+ {0, "A/B/C", "normal", 2, "A/B/C"},
+ {0, "A/B/C/D", "normal", 2, "A/B/C/D"},
+ {2, "A/B", "base-deleted", NO_COPY_FROM},
+ {2, "A/B/C", "base-deleted", NO_COPY_FROM, "C2"},
+ {2, "A/B/C/D", "base-deleted", NO_COPY_FROM},
+ {1, "C2", "normal", 2, "A/B/C", MOVED_HERE},
+ {1, "C2/D", "normal", 2, "A/B/C/D", MOVED_HERE},
+ {0}
+ };
+ SVN_ERR(check_db_rows(&b, "", nodes));
+ }
+
+ SVN_ERR(sbox_wc_update(&b, "", 3));
+ SVN_ERR(sbox_wc_revert(&b, "A/B", svn_depth_empty));
+ {
+ nodes_row_t nodes[] = {
+ {0, "", "normal", 3, ""},
+ {0, "A", "normal", 3, "A"},
+ {0, "A/B", "normal", 3, "A/B"},
+ {0, "A/B/C", "normal", 3, "A/B/C"},
+ {0, "A/B/C/D", "normal", 3, "A/B/C/D"},
+ {0, "A/B/C/D/E", "normal", 3, "A/B/C/D/E"},
+ {3, "A/B/C", "base-deleted", NO_COPY_FROM, "C2"},
+ {3, "A/B/C/D", "base-deleted", NO_COPY_FROM},
+ {3, "A/B/C/D/E", "base-deleted", NO_COPY_FROM},
+ {1, "C2", "normal", 2, "A/B/C", MOVED_HERE},
+ {1, "C2/D", "normal", 2, "A/B/C/D", MOVED_HERE},
+ {0}
+ };
+ SVN_ERR(check_db_rows(&b, "", nodes));
+ }
+
+ /* Revert should have left a tree-conflict (or broken the move). */
+ SVN_ERR(sbox_wc_resolve(&b, "A/B/C", svn_depth_empty,
+ svn_wc_conflict_choose_mine_conflict));
+ {
+ nodes_row_t nodes[] = {
+ {0, "", "normal", 3, ""},
+ {0, "A", "normal", 3, "A"},
+ {0, "A/B", "normal", 3, "A/B"},
+ {0, "A/B/C", "normal", 3, "A/B/C"},
+ {0, "A/B/C/D", "normal", 3, "A/B/C/D"},
+ {0, "A/B/C/D/E", "normal", 3, "A/B/C/D/E"},
+ {3, "A/B/C", "base-deleted", NO_COPY_FROM, "C2"},
+ {3, "A/B/C/D", "base-deleted", NO_COPY_FROM},
+ {3, "A/B/C/D/E", "base-deleted", NO_COPY_FROM},
+ {1, "C2", "normal", 3, "A/B/C", MOVED_HERE},
+ {1, "C2/D", "normal", 3, "A/B/C/D", MOVED_HERE},
+ {1, "C2/D/E", "normal", 3, "A/B/C/D/E", MOVED_HERE},
+ {0}
+ };
+ SVN_ERR(check_db_rows(&b, "", nodes));
+ }
+
+ return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+switch_move(const svn_test_opts_t *opts, apr_pool_t *pool)
+{
+ svn_test__sandbox_t b;
+
+ SVN_ERR(svn_test__sandbox_create(&b, "switch_move", opts, pool));
+
+ SVN_ERR(sbox_wc_mkdir(&b, "A"));
+ SVN_ERR(sbox_wc_mkdir(&b, "A/B"));
+ SVN_ERR(sbox_wc_mkdir(&b, "A/B/C"));
+ SVN_ERR(sbox_wc_mkdir(&b, "A/B/D"));
+ SVN_ERR(sbox_wc_mkdir(&b, "A/B/D/E"));
+ SVN_ERR(sbox_wc_commit(&b, ""));
+ SVN_ERR(sbox_wc_copy(&b, "A", "X"));
+ SVN_ERR(sbox_wc_commit(&b, ""));
+ SVN_ERR(sbox_wc_mkdir(&b, "X/B/D/E/F"));
+ SVN_ERR(sbox_wc_commit(&b, ""));
+ SVN_ERR(sbox_wc_switch(&b, "", "/A", svn_depth_infinity));
+ SVN_ERR(sbox_wc_update(&b, "", 2));
+
+ SVN_ERR(sbox_wc_move(&b, "B/C", "C2"));
+ SVN_ERR(sbox_wc_move(&b, "B/D", "D2"));
+ SVN_ERR(sbox_wc_move(&b, "D2/E", "D2/E2"));
+ {
+ nodes_row_t nodes[] = {
+ {0, "", "normal", 2, "A"},
+ {0, "B", "normal", 2, "A/B"},
+ {0, "B/C", "normal", 2, "A/B/C"},
+ {0, "B/D", "normal", 2, "A/B/D"},
+ {0, "B/D/E", "normal", 2, "A/B/D/E"},
+ {2, "B/C", "base-deleted", NO_COPY_FROM, "C2"},
+ {2, "B/D", "base-deleted", NO_COPY_FROM, "D2"},
+ {2, "B/D/E", "base-deleted", NO_COPY_FROM},
+ {1, "C2", "normal", 2, "A/B/C", MOVED_HERE},
+ {1, "D2", "normal", 2, "A/B/D", MOVED_HERE},
+ {1, "D2/E", "normal", 2, "A/B/D/E", MOVED_HERE},
+ {2, "D2/E", "base-deleted", NO_COPY_FROM, "D2/E2"},
+ {2, "D2/E2", "normal", 2, "A/B/D/E", MOVED_HERE},
+ {0}
+ };
+ SVN_ERR(check_db_rows(&b, "", nodes));
+ }
+
+ /* Switch "bumps" revisions and paths and raises conflicts just like
+ update. */
+ SVN_ERR(sbox_wc_switch(&b, "", "/X", svn_depth_infinity));
+ {
+ nodes_row_t nodes[] = {
+ {0, "", "normal", 3, "X"},
+ {0, "B", "normal", 3, "X/B"},
+ {0, "B/C", "normal", 3, "X/B/C"},
+ {0, "B/D", "normal", 3, "X/B/D"},
+ {0, "B/D/E", "normal", 3, "X/B/D/E"},
+ {0, "B/D/E/F", "normal", 3, "X/B/D/E/F"},
+ {2, "B/C", "base-deleted", NO_COPY_FROM, "C2"},
+ {2, "B/D", "base-deleted", NO_COPY_FROM, "D2"},
+ {2, "B/D/E", "base-deleted", NO_COPY_FROM},
+ {2, "B/D/E/F", "base-deleted", NO_COPY_FROM},
+ {1, "C2", "normal", 3, "X/B/C", MOVED_HERE},
+ {1, "D2", "normal", 2, "A/B/D", MOVED_HERE},
+ {1, "D2/E", "normal", 2, "A/B/D/E", MOVED_HERE},
+ {2, "D2/E", "base-deleted", NO_COPY_FROM, "D2/E2"},
+ {2, "D2/E2", "normal", 2, "A/B/D/E", MOVED_HERE},
+ {0}
+ };
+ SVN_ERR(check_db_rows(&b, "", nodes));
+ }
+
+ /* Conflicts from switch are resolved just like those from update. */
+ SVN_ERR(sbox_wc_resolve(&b, "B/D", svn_depth_empty,
+ svn_wc_conflict_choose_mine_conflict));
+ {
+ nodes_row_t nodes[] = {
+ {0, "", "normal", 3, "X"},
+ {0, "B", "normal", 3, "X/B"},
+ {0, "B/C", "normal", 3, "X/B/C"},
+ {0, "B/D", "normal", 3, "X/B/D"},
+ {0, "B/D/E", "normal", 3, "X/B/D/E"},
+ {0, "B/D/E/F", "normal", 3, "X/B/D/E/F"},
+ {2, "B/C", "base-deleted", NO_COPY_FROM, "C2"},
+ {2, "B/D", "base-deleted", NO_COPY_FROM, "D2"},
+ {2, "B/D/E", "base-deleted", NO_COPY_FROM},
+ {2, "B/D/E/F", "base-deleted", NO_COPY_FROM},
+ {1, "C2", "normal", 3, "X/B/C", MOVED_HERE},
+ {1, "D2", "normal", 3, "X/B/D", MOVED_HERE},
+ {1, "D2/E", "normal", 3, "X/B/D/E", MOVED_HERE},
+ {1, "D2/E/F", "normal", 3, "X/B/D/E/F", MOVED_HERE},
+ {2, "D2/E", "base-deleted", NO_COPY_FROM, "D2/E2"},
+ {2, "D2/E/F", "base-deleted", NO_COPY_FROM},
+ {2, "D2/E2", "normal", 2, "A/B/D/E", MOVED_HERE},
+ {0}
+ };
+ SVN_ERR(check_db_rows(&b, "", nodes));
+ }
+
+ SVN_ERR(sbox_wc_resolve(&b, "D2/E", svn_depth_empty,
+ svn_wc_conflict_choose_mine_conflict));
+ {
+ nodes_row_t nodes[] = {
+ {0, "", "normal", 3, "X"},
+ {0, "B", "normal", 3, "X/B"},
+ {0, "B/C", "normal", 3, "X/B/C"},
+ {0, "B/D", "normal", 3, "X/B/D"},
+ {0, "B/D/E", "normal", 3, "X/B/D/E"},
+ {0, "B/D/E/F", "normal", 3, "X/B/D/E/F"},
+ {2, "B/C", "base-deleted", NO_COPY_FROM, "C2"},
+ {2, "B/D", "base-deleted", NO_COPY_FROM, "D2"},
+ {2, "B/D/E", "base-deleted", NO_COPY_FROM},
+ {2, "B/D/E/F", "base-deleted", NO_COPY_FROM},
+ {1, "C2", "normal", 3, "X/B/C", MOVED_HERE},
+ {1, "D2", "normal", 3, "X/B/D", MOVED_HERE},
+ {1, "D2/E", "normal", 3, "X/B/D/E", MOVED_HERE},
+ {1, "D2/E/F", "normal", 3, "X/B/D/E/F", MOVED_HERE},
+ {2, "D2/E", "base-deleted", NO_COPY_FROM, "D2/E2"},
+ {2, "D2/E/F", "base-deleted", NO_COPY_FROM},
+ {2, "D2/E2", "normal", 3, "X/B/D/E", MOVED_HERE},
+ {2, "D2/E2/F", "normal", 3, "X/B/D/E/F", MOVED_HERE},
+ {0}
+ };
+ SVN_ERR(check_db_rows(&b, "", nodes));
+ }
+
+ return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+move_replace(const svn_test_opts_t *opts, apr_pool_t *pool)
+{
+ svn_test__sandbox_t b;
+
+ SVN_ERR(svn_test__sandbox_create(&b, "move_replace", opts, pool));
+
+ SVN_ERR(sbox_wc_mkdir(&b, "A"));
+ SVN_ERR(sbox_wc_mkdir(&b, "B"));
+ SVN_ERR(sbox_wc_commit(&b, ""));
+ SVN_ERR(sbox_wc_mkdir(&b, "B/X"));
+ SVN_ERR(sbox_wc_commit(&b, ""));
+ SVN_ERR(sbox_wc_update(&b, "", 1));
+
+ SVN_ERR(sbox_wc_move(&b, "A", "X"));
+ SVN_ERR(sbox_wc_move(&b, "B", "A"));
+ SVN_ERR(sbox_wc_move(&b, "X", "B"));
+ {
+ nodes_row_t nodes[] = {
+ {0, "", "normal", 1, ""},
+ {0, "A", "normal", 1, "A"},
+ {0, "B", "normal", 1, "B"},
+ {1, "A", "normal", 1, "B", FALSE, "B", TRUE},
+ {1, "B", "normal", 1, "A", FALSE, "A", TRUE},
+ {0}
+ };
+ SVN_ERR(check_db_rows(&b, "", nodes));
+ }
+
+ SVN_ERR(sbox_wc_update(&b, "", 2));
+ {
+ nodes_row_t nodes[] = {
+ {0, "", "normal", 2, ""},
+ {0, "A", "normal", 2, "A"},
+ {0, "B", "normal", 2, "B"},
+ {0, "B/X", "normal", 2, "B/X"},
+ {1, "A", "normal", 1, "B", FALSE, "B", TRUE},
+ {1, "B", "normal", 2, "A", FALSE, "A", TRUE},
+ {1, "B/X", "base-deleted", NO_COPY_FROM},
+ {0}
+ };
+ SVN_ERR(check_db_rows(&b, "", nodes));
+ }
+
+ SVN_ERR(sbox_wc_resolve(&b, "B", svn_depth_empty,
+ svn_wc_conflict_choose_mine_conflict));
+ {
+ nodes_row_t nodes[] = {
+ {0, "", "normal", 2, ""},
+ {0, "A", "normal", 2, "A"},
+ {0, "B", "normal", 2, "B"},
+ {0, "B/X", "normal", 2, "B/X"},
+ {1, "A", "normal", 2, "B", FALSE, "B", TRUE},
+ {1, "A/X", "normal", 2, "B/X", MOVED_HERE},
+ {1, "B", "normal", 2, "A", FALSE, "A", TRUE},
+ {1, "B/X", "base-deleted", NO_COPY_FROM},
+ {0}
+ };
+ SVN_ERR(check_db_rows(&b, "", nodes));
+ }
+
+ return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+layered_moved_to(const svn_test_opts_t *opts, apr_pool_t *pool)
+{
+ svn_test__sandbox_t b;
+ svn_error_t *err;
+
+ SVN_ERR(svn_test__sandbox_create(&b, "layered_moved_to", opts, pool));
+
+ SVN_ERR(sbox_wc_mkdir(&b, "A"));
+ SVN_ERR(sbox_wc_mkdir(&b, "A/B"));
+ SVN_ERR(sbox_wc_mkdir(&b, "A/B/C"));
+ SVN_ERR(sbox_wc_mkdir(&b, "A/B/C/D"));
+ SVN_ERR(sbox_wc_mkdir(&b, "A/B/C/D/E"));
+ SVN_ERR(sbox_wc_mkdir(&b, "C"));
+ SVN_ERR(sbox_wc_mkdir(&b, "C/D"));
+ SVN_ERR(sbox_wc_mkdir(&b, "C/D/E"));
+ SVN_ERR(sbox_wc_commit(&b, ""));
+ SVN_ERR(sbox_wc_propset(&b, "property", "value", "A/B/C/D/E"));
+ SVN_ERR(sbox_wc_commit(&b, ""));
+ SVN_ERR(sbox_wc_propset(&b, "property", "value", "C/D/E"));
+ SVN_ERR(sbox_wc_commit(&b, ""));
+ SVN_ERR(sbox_wc_mkdir(&b, "P"));
+ SVN_ERR(sbox_wc_commit(&b, ""));
+ SVN_ERR(sbox_wc_propset(&b, "property2", "value", "A/B/C/D/E"));
+ SVN_ERR(sbox_wc_propset(&b, "property2", "value", "C/D/E"));
+ SVN_ERR(sbox_wc_commit(&b, ""));
+ SVN_ERR(sbox_wc_update(&b, "", 1));
+
+ SVN_ERR(sbox_wc_move(&b, "A", "X"));
+ SVN_ERR(sbox_wc_move(&b, "X/B/C/D/E", "E2"));
+ SVN_ERR(sbox_wc_delete(&b, "X/B/C"));
+ SVN_ERR(sbox_wc_move(&b, "C", "X/B/C"));
+ SVN_ERR(sbox_wc_move(&b, "X/B/C/D/E", "E3"));
+ {
+ nodes_row_t nodes[] = {
+ {0, "", "normal", 1, ""},
+ {0, "A", "normal", 1, "A"},
+ {0, "A/B", "normal", 1, "A/B"},
+ {0, "A/B/C", "normal", 1, "A/B/C"},
+ {0, "A/B/C/D", "normal", 1, "A/B/C/D"},
+ {0, "A/B/C/D/E", "normal", 1, "A/B/C/D/E"},
+ {0, "C", "normal", 1, "C"},
+ {0, "C/D", "normal", 1, "C/D"},
+ {0, "C/D/E", "normal", 1, "C/D/E"},
+ {1, "A", "base-deleted", NO_COPY_FROM, "X"},
+ {1, "A/B", "base-deleted", NO_COPY_FROM},
+ {1, "A/B/C", "base-deleted", NO_COPY_FROM},
+ {1, "A/B/C/D", "base-deleted", NO_COPY_FROM},
+ {1, "A/B/C/D/E", "base-deleted", NO_COPY_FROM},
+ {1, "C", "base-deleted", NO_COPY_FROM, "X/B/C"},
+ {1, "C/D", "base-deleted", NO_COPY_FROM},
+ {1, "C/D/E", "base-deleted", NO_COPY_FROM},
+ {1, "X", "normal", 1, "A", MOVED_HERE},
+ {1, "X/B", "normal", 1, "A/B", MOVED_HERE},
+ {1, "X/B/C", "normal", 1, "A/B/C", MOVED_HERE},
+ {1, "X/B/C/D", "normal", 1, "A/B/C/D", MOVED_HERE},
+ {1, "X/B/C/D/E", "normal", 1, "A/B/C/D/E", MOVED_HERE},
+ {3, "X/B/C", "normal", 1, "C", MOVED_HERE},
+ {3, "X/B/C/D", "normal", 1, "C/D", MOVED_HERE},
+ {3, "X/B/C/D/E", "normal", 1, "C/D/E", FALSE, "E2", TRUE},
+ {5, "X/B/C/D/E", "base-deleted", NO_COPY_FROM, "E3"},
+ {1, "E2", "normal", 1, "A/B/C/D/E", MOVED_HERE},
+ {1, "E3", "normal", 1, "C/D/E", MOVED_HERE},
+ {0}
+ };
+ SVN_ERR(check_db_rows(&b, "", nodes));
+ }
+
+ SVN_ERR(sbox_wc_update(&b, "A", 2));
+ SVN_ERR(sbox_wc_resolve(&b, "A", svn_depth_empty,
+ svn_wc_conflict_choose_mine_conflict));
+ SVN_ERR(sbox_wc_resolve(&b, "X/B/C", svn_depth_empty,
+ svn_wc_conflict_choose_mine_conflict));
+ SVN_ERR(sbox_wc_resolve(&b, "X/B/C/D/E", svn_depth_empty,
+ svn_wc_conflict_choose_mine_conflict));
+ {
+ nodes_row_t nodes[] = {
+ {0, "", "normal", 1, ""},
+ {0, "A", "normal", 2, "A"},
+ {0, "A/B", "normal", 2, "A/B"},
+ {0, "A/B/C", "normal", 2, "A/B/C"},
+ {0, "A/B/C/D", "normal", 2, "A/B/C/D"},
+ {0, "A/B/C/D/E", "normal", 2, "A/B/C/D/E"},
+ {0, "C", "normal", 1, "C"},
+ {0, "C/D", "normal", 1, "C/D"},
+ {0, "C/D/E", "normal", 1, "C/D/E"},
+ {1, "A", "base-deleted", NO_COPY_FROM, "X"},
+ {1, "A/B", "base-deleted", NO_COPY_FROM},
+ {1, "A/B/C", "base-deleted", NO_COPY_FROM},
+ {1, "A/B/C/D", "base-deleted", NO_COPY_FROM},
+ {1, "A/B/C/D/E", "base-deleted", NO_COPY_FROM},
+ {1, "C", "base-deleted", NO_COPY_FROM, "X/B/C"},
+ {1, "C/D", "base-deleted", NO_COPY_FROM},
+ {1, "C/D/E", "base-deleted", NO_COPY_FROM},
+ {1, "X", "normal", 2, "A", MOVED_HERE},
+ {1, "X/B", "normal", 2, "A/B", MOVED_HERE},
+ {1, "X/B/C", "normal", 2, "A/B/C", MOVED_HERE},
+ {1, "X/B/C/D", "normal", 2, "A/B/C/D", MOVED_HERE},
+ {1, "X/B/C/D/E", "normal", 2, "A/B/C/D/E", MOVED_HERE},
+ {3, "X/B/C", "normal", 1, "C", MOVED_HERE},
+ {3, "X/B/C/D", "normal", 1, "C/D", MOVED_HERE},
+ {3, "X/B/C/D/E", "normal", 1, "C/D/E", FALSE, "E2", TRUE},
+ {5, "X/B/C/D/E", "base-deleted", NO_COPY_FROM, "E3"},
+ {1, "E2", "normal", 2, "A/B/C/D/E", MOVED_HERE},
+ {1, "E3", "normal", 1, "C/D/E", MOVED_HERE},
+ {0}
+ };
+ SVN_ERR(check_db_rows(&b, "", nodes));
+ }
+
+ SVN_ERR(sbox_wc_update(&b, "C", 3));
+ SVN_ERR(sbox_wc_resolve(&b, "C", svn_depth_empty,
+ svn_wc_conflict_choose_mine_conflict));
+ SVN_ERR(sbox_wc_resolve(&b, "X/B/C/D/E", svn_depth_empty,
+ svn_wc_conflict_choose_mine_conflict));
+ {
+ nodes_row_t nodes[] = {
+ {0, "", "normal", 1, ""},
+ {0, "A", "normal", 2, "A"},
+ {0, "A/B", "normal", 2, "A/B"},
+ {0, "A/B/C", "normal", 2, "A/B/C"},
+ {0, "A/B/C/D", "normal", 2, "A/B/C/D"},
+ {0, "A/B/C/D/E", "normal", 2, "A/B/C/D/E"},
+ {0, "C", "normal", 3, "C"},
+ {0, "C/D", "normal", 3, "C/D"},
+ {0, "C/D/E", "normal", 3, "C/D/E"},
+ {1, "A", "base-deleted", NO_COPY_FROM, "X"},
+ {1, "A/B", "base-deleted", NO_COPY_FROM},
+ {1, "A/B/C", "base-deleted", NO_COPY_FROM},
+ {1, "A/B/C/D", "base-deleted", NO_COPY_FROM},
+ {1, "A/B/C/D/E", "base-deleted", NO_COPY_FROM},
+ {1, "C", "base-deleted", NO_COPY_FROM, "X/B/C"},
+ {1, "C/D", "base-deleted", NO_COPY_FROM},
+ {1, "C/D/E", "base-deleted", NO_COPY_FROM},
+ {1, "X", "normal", 2, "A", MOVED_HERE},
+ {1, "X/B", "normal", 2, "A/B", MOVED_HERE},
+ {1, "X/B/C", "normal", 2, "A/B/C", MOVED_HERE},
+ {1, "X/B/C/D", "normal", 2, "A/B/C/D", MOVED_HERE},
+ {1, "X/B/C/D/E", "normal", 2, "A/B/C/D/E", MOVED_HERE},
+ {3, "X/B/C", "normal", 3, "C", MOVED_HERE},
+ {3, "X/B/C/D", "normal", 3, "C/D", MOVED_HERE},
+ {3, "X/B/C/D/E", "normal", 3, "C/D/E", FALSE, "E2", TRUE},
+ {5, "X/B/C/D/E", "base-deleted", NO_COPY_FROM, "E3"},
+ {1, "E2", "normal", 2, "A/B/C/D/E", MOVED_HERE},
+ {1, "E3", "normal", 3, "C/D/E", MOVED_HERE},
+ {0}
+ };
+ SVN_ERR(check_db_rows(&b, "", nodes));
+ }
+
+ /* An update with no text/property/tree changes in A, just a revision bump. */
+ SVN_ERR(sbox_wc_update(&b, "A", 4));
+ {
+ nodes_row_t nodes[] = {
+ {0, "", "normal", 1, ""},
+ {0, "A", "normal", 4, "A"},
+ {0, "A/B", "normal", 4, "A/B"},
+ {0, "A/B/C", "normal", 4, "A/B/C"},
+ {0, "A/B/C/D", "normal", 4, "A/B/C/D"},
+ {0, "A/B/C/D/E", "normal", 4, "A/B/C/D/E"},
+ {0, "C", "normal", 3, "C"},
+ {0, "C/D", "normal", 3, "C/D"},
+ {0, "C/D/E", "normal", 3, "C/D/E"},
+ {1, "A", "base-deleted", NO_COPY_FROM, "X"},
+ {1, "A/B", "base-deleted", NO_COPY_FROM},
+ {1, "A/B/C", "base-deleted", NO_COPY_FROM},
+ {1, "A/B/C/D", "base-deleted", NO_COPY_FROM},
+ {1, "A/B/C/D/E", "base-deleted", NO_COPY_FROM},
+ {1, "C", "base-deleted", NO_COPY_FROM, "X/B/C"},
+ {1, "C/D", "base-deleted", NO_COPY_FROM},
+ {1, "C/D/E", "base-deleted", NO_COPY_FROM},
+ {1, "X", "normal", 4, "A", MOVED_HERE},
+ {1, "X/B", "normal", 4, "A/B", MOVED_HERE},
+ {1, "X/B/C", "normal", 4, "A/B/C", MOVED_HERE},
+ {1, "X/B/C/D", "normal", 4, "A/B/C/D", MOVED_HERE},
+ {1, "X/B/C/D/E", "normal", 4, "A/B/C/D/E", MOVED_HERE},
+ {3, "X/B/C", "normal", 3, "C", MOVED_HERE},
+ {3, "X/B/C/D", "normal", 3, "C/D", MOVED_HERE},
+ {3, "X/B/C/D/E", "normal", 3, "C/D/E", FALSE, "E2", TRUE},
+ {5, "X/B/C/D/E", "base-deleted", NO_COPY_FROM, "E3"},
+ {1, "E2", "normal", 4, "A/B/C/D/E", MOVED_HERE},
+ {1, "E3", "normal", 3, "C/D/E", MOVED_HERE},
+ {0}
+ };
+ SVN_ERR(check_db_rows(&b, "", nodes));
+ }
+
+ /* Update for conflicts on A and C */
+ SVN_ERR(sbox_wc_update(&b, "", 5));
+ {
+ nodes_row_t nodes[] = {
+ {0, "", "normal", 5, ""},
+ {0, "A", "normal", 5, "A"},
+ {0, "A/B", "normal", 5, "A/B"},
+ {0, "A/B/C", "normal", 5, "A/B/C"},
+ {0, "A/B/C/D", "normal", 5, "A/B/C/D"},
+ {0, "A/B/C/D/E", "normal", 5, "A/B/C/D/E"},
+ {0, "P", "normal", 5, "P"},
+ {0, "C", "normal", 5, "C"},
+ {0, "C/D", "normal", 5, "C/D"},
+ {0, "C/D/E", "normal", 5, "C/D/E"},
+ {1, "A", "base-deleted", NO_COPY_FROM, "X"},
+ {1, "A/B", "base-deleted", NO_COPY_FROM},
+ {1, "A/B/C", "base-deleted", NO_COPY_FROM},
+ {1, "A/B/C/D", "base-deleted", NO_COPY_FROM},
+ {1, "A/B/C/D/E", "base-deleted", NO_COPY_FROM},
+ {1, "C", "base-deleted", NO_COPY_FROM, "X/B/C"},
+ {1, "C/D", "base-deleted", NO_COPY_FROM},
+ {1, "C/D/E", "base-deleted", NO_COPY_FROM},
+ {1, "X", "normal", 4, "A", MOVED_HERE},
+ {1, "X/B", "normal", 4, "A/B", MOVED_HERE},
+ {1, "X/B/C", "normal", 4, "A/B/C", MOVED_HERE},
+ {1, "X/B/C/D", "normal", 4, "A/B/C/D", MOVED_HERE},
+ {1, "X/B/C/D/E", "normal", 4, "A/B/C/D/E", MOVED_HERE},
+ {3, "X/B/C", "normal", 3, "C", MOVED_HERE},
+ {3, "X/B/C/D", "normal", 3, "C/D", MOVED_HERE},
+ {3, "X/B/C/D/E", "normal", 3, "C/D/E", FALSE, "E2", TRUE},
+ {5, "X/B/C/D/E", "base-deleted", NO_COPY_FROM, "E3"},
+ {1, "E2", "normal", 4, "A/B/C/D/E", MOVED_HERE},
+ {1, "E3", "normal", 3, "C/D/E", MOVED_HERE},
+ {0}
+ };
+ SVN_ERR(check_db_rows(&b, "", nodes));
+ }
+
+ /* Partially resolve A */
+ SVN_ERR(sbox_wc_resolve(&b, "A", svn_depth_empty,
+ svn_wc_conflict_choose_mine_conflict));
+ SVN_ERR(sbox_wc_resolve(&b, "X/B/C", svn_depth_empty,
+ svn_wc_conflict_choose_mine_conflict));
+
+ /* Cannot resolve C */
+ err = sbox_wc_resolve(&b, "C", svn_depth_empty,
+ svn_wc_conflict_choose_mine_conflict);
+ SVN_TEST_ASSERT_ERROR(err, SVN_ERR_WC_CONFLICT_RESOLVER_FAILURE);
+
+ /* Complete resolving A and then resolve C */
+ SVN_ERR(sbox_wc_resolve(&b, "X/B/C/D/E", svn_depth_empty,
+ svn_wc_conflict_choose_mine_conflict));
+ SVN_ERR(sbox_wc_resolve(&b, "C", svn_depth_empty,
+ svn_wc_conflict_choose_mine_conflict));
+
+ {
+ nodes_row_t nodes[] = {
+ {0, "", "normal", 5, ""},
+ {0, "A", "normal", 5, "A"},
+ {0, "A/B", "normal", 5, "A/B"},
+ {0, "A/B/C", "normal", 5, "A/B/C"},
+ {0, "A/B/C/D", "normal", 5, "A/B/C/D"},
+ {0, "A/B/C/D/E", "normal", 5, "A/B/C/D/E"},
+ {0, "P", "normal", 5, "P"},
+ {0, "C", "normal", 5, "C"},
+ {0, "C/D", "normal", 5, "C/D"},
+ {0, "C/D/E", "normal", 5, "C/D/E"},
+ {1, "A", "base-deleted", NO_COPY_FROM, "X"},
+ {1, "A/B", "base-deleted", NO_COPY_FROM},
+ {1, "A/B/C", "base-deleted", NO_COPY_FROM},
+ {1, "A/B/C/D", "base-deleted", NO_COPY_FROM},
+ {1, "A/B/C/D/E", "base-deleted", NO_COPY_FROM},
+ {1, "C", "base-deleted", NO_COPY_FROM, "X/B/C"},
+ {1, "C/D", "base-deleted", NO_COPY_FROM},
+ {1, "C/D/E", "base-deleted", NO_COPY_FROM},
+ {1, "X", "normal", 5, "A", MOVED_HERE},
+ {1, "X/B", "normal", 5, "A/B", MOVED_HERE},
+ {1, "X/B/C", "normal", 5, "A/B/C", MOVED_HERE},
+ {1, "X/B/C/D", "normal", 5, "A/B/C/D", MOVED_HERE},
+ {1, "X/B/C/D/E", "normal", 5, "A/B/C/D/E", MOVED_HERE},
+ {3, "X/B/C", "normal", 5, "C", MOVED_HERE},
+ {3, "X/B/C/D", "normal", 5, "C/D", MOVED_HERE},
+ {3, "X/B/C/D/E", "normal", 5, "C/D/E", FALSE, "E2", TRUE},
+ {5, "X/B/C/D/E", "base-deleted", NO_COPY_FROM, "E3"},
+ {1, "E2", "normal", 5, "A/B/C/D/E", MOVED_HERE},
+ {1, "E3", "normal", 3, "C/D/E", MOVED_HERE},
+ {0}
+ };
+ SVN_ERR(check_db_rows(&b, "", nodes));
+ }
+
+ return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+update_within_move(const svn_test_opts_t *opts, apr_pool_t *pool)
+{
+ svn_test__sandbox_t b;
+ svn_error_t *err;
+
+ SVN_ERR(svn_test__sandbox_create(&b, "update_within_move", opts, pool));
+
+ SVN_ERR(sbox_wc_mkdir(&b, "A"));
+ SVN_ERR(sbox_wc_mkdir(&b, "A/B"));
+ SVN_ERR(sbox_wc_mkdir(&b, "A/B/C"));
+ SVN_ERR(sbox_wc_commit(&b, ""));
+ SVN_ERR(sbox_wc_mkdir(&b, "A/B/C/D"));
+ SVN_ERR(sbox_wc_commit(&b, ""));
+ SVN_ERR(sbox_wc_update(&b, "", 1));
+
+ SVN_ERR(sbox_wc_move(&b, "A", "X"));
+ SVN_ERR(sbox_wc_update(&b, "A/B/C", 2));
+ {
+ nodes_row_t nodes[] = {
+ {0, "", "normal", 1, ""},
+ {0, "A", "normal", 1, "A"},
+ {0, "A/B", "normal", 1, "A/B"},
+ {0, "A/B/C", "normal", 2, "A/B/C"},
+ {0, "A/B/C/D", "normal", 2, "A/B/C/D"},
+ {1, "A", "base-deleted", NO_COPY_FROM, "X"},
+ {1, "A/B", "base-deleted", NO_COPY_FROM},
+ {1, "A/B/C", "base-deleted", NO_COPY_FROM},
+ {1, "A/B/C/D", "base-deleted", NO_COPY_FROM},
+ {1, "X", "normal", 1, "A", MOVED_HERE},
+ {1, "X/B", "normal", 1, "A/B", MOVED_HERE},
+ {1, "X/B/C", "normal", 1, "A/B/C", MOVED_HERE},
+ {0}
+ };
+ SVN_ERR(check_db_rows(&b, "", nodes));
+ }
+
+ /* Can't resolve mixed-revision source to mine-conflict. */
+ err = sbox_wc_resolve(&b, "A", svn_depth_empty,
+ svn_wc_conflict_choose_mine_conflict);
+ SVN_TEST_ASSERT_ERROR(err, SVN_ERR_WC_CONFLICT_RESOLVER_FAILURE);
+
+ SVN_ERR(sbox_wc_resolve(&b, "A", svn_depth_empty,
+ svn_wc_conflict_choose_merged));
+ {
+ nodes_row_t nodes[] = {
+ {0, "", "normal", 1, ""},
+ {0, "A", "normal", 1, "A"},
+ {0, "A/B", "normal", 1, "A/B"},
+ {0, "A/B/C", "normal", 2, "A/B/C"},
+ {0, "A/B/C/D", "normal", 2, "A/B/C/D"},
+ {1, "A", "base-deleted", NO_COPY_FROM},
+ {1, "A/B", "base-deleted", NO_COPY_FROM},
+ {1, "A/B/C", "base-deleted", NO_COPY_FROM},
+ {1, "A/B/C/D", "base-deleted", NO_COPY_FROM},
+ {1, "X", "normal", 1, "A"},
+ {1, "X/B", "normal", 1, "A/B"},
+ {1, "X/B/C", "normal", 1, "A/B/C"},
+ {0}
+ };
+ SVN_ERR(check_db_rows(&b, "", nodes));
+ }
+
+
+ return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+commit_moved_descendant(const svn_test_opts_t *opts, apr_pool_t *pool)
+{
+ svn_test__sandbox_t b;
+ SVN_ERR(svn_test__sandbox_create(&b, "commit_moved_descendant", opts, pool));
+
+ SVN_ERR(sbox_wc_mkdir(&b, "A"));
+ SVN_ERR(sbox_wc_mkdir(&b, "A/A"));
+ SVN_ERR(sbox_wc_mkdir(&b, "A/A/A"));
+ SVN_ERR(sbox_wc_mkdir(&b, "A/A/A/A"));
+ SVN_ERR(sbox_wc_mkdir(&b, "A/A/A/A/A"));
+ SVN_ERR(sbox_wc_mkdir(&b, "A/A/A/A/A/A"));
+ SVN_ERR(sbox_wc_commit(&b, ""));
+ SVN_ERR(sbox_wc_copy(&b, "A", "A_copied"));
+ SVN_ERR(sbox_wc_move(&b, "A/A/A", "AAA_moved"));
+ SVN_ERR(sbox_wc_delete(&b, "A/A"));
+ SVN_ERR(sbox_wc_copy(&b, "A_copied/A", "A/A"));
+
+ /* And now I want to commit AAA_moved (the entire move), but not
+ the replacement of A/A */
+
+ /* For now, just start committing directly */
+ /* ### This fails, because A/A/A is not collected by the commit
+ harvester (it doesn't need committing, but our move filter
+ blocks on it) */
+ SVN_ERR(sbox_wc_commit(&b, ""));
+
+ /* It would be nicer if we could just do a: */
+ /* SVN_ERR(sbox_wc_commit(&b, "AAA_moved")); */
+ /* Which then includes the delete half of the move, when it is
+ shadowed, like in this case. The commit processing doesn't
+ support this yet though*/
+
+ return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+commit_moved_away_descendant(const svn_test_opts_t *opts, apr_pool_t *pool)
+{
+ svn_test__sandbox_t b;
+ SVN_ERR(svn_test__sandbox_create(&b, "commit_moved_away_descendant",
+ opts, pool));
+
+ SVN_ERR(sbox_wc_mkdir(&b, "A"));
+ SVN_ERR(sbox_wc_mkdir(&b, "A/A"));
+ SVN_ERR(sbox_wc_mkdir(&b, "A/A/A"));
+ SVN_ERR(sbox_wc_mkdir(&b, "A/A/A/A"));
+ SVN_ERR(sbox_wc_mkdir(&b, "A/A/A/A/A"));
+ SVN_ERR(sbox_wc_mkdir(&b, "A/A/A/A/A/A"));
+ SVN_ERR(sbox_wc_commit(&b, ""));
+ SVN_ERR(sbox_wc_copy(&b, "A", "A_copied"));
+ SVN_ERR(sbox_wc_move(&b, "A/A/A", "AAA_moved"));
+ SVN_ERR(sbox_wc_delete(&b, "A/A"));
+ SVN_ERR(sbox_wc_copy(&b, "A_copied/A", "A/A"));
+
+ /* And now I want to make sure that I can't commit A, without also
+ committing AAA_moved, as that would break the move*/
+ SVN_ERR(sbox_wc_commit(&b, "A"));
+
+ return svn_error_create(SVN_ERR_TEST_FAILED, NULL,
+ "The commit should have failed");
+
+ /*return SVN_NO_ERROR;*/
+}
+
+static svn_error_t *
+finite_move_update_bump(const svn_test_opts_t *opts, apr_pool_t *pool)
+{
+ svn_test__sandbox_t b;
+ svn_error_t *err;
+ SVN_ERR(svn_test__sandbox_create(&b, "finite_move_update_bump",
+ opts, pool));
+
+ SVN_ERR(sbox_wc_mkdir(&b, "A"));
+ SVN_ERR(sbox_wc_mkdir(&b, "A/B"));
+ SVN_ERR(sbox_wc_mkdir(&b, "A/B/C"));
+ SVN_ERR(sbox_wc_mkdir(&b, "P"));
+ SVN_ERR(sbox_wc_mkdir(&b, "P/Q"));
+ sbox_file_write(&b, "P/Q/f", "r1 content\n");
+ SVN_ERR(sbox_wc_add(&b, "P/Q/f"));
+ SVN_ERR(sbox_wc_commit(&b, ""));
+ SVN_ERR(sbox_wc_mkdir(&b, "X"));
+ SVN_ERR(sbox_wc_commit(&b, ""));
+ SVN_ERR(sbox_wc_update(&b, "", 1));
+
+ SVN_ERR(sbox_wc_move(&b, "A/B", "B2"));
+ SVN_ERR(sbox_wc_update(&b, "A/B/C", 2));
+ SVN_ERR(check_tree_conflict_repos_path(&b, "A/B", NULL, NULL));
+ err = sbox_wc_resolve(&b, "A/B", svn_depth_empty,
+ svn_wc_conflict_choose_mine_conflict);
+ SVN_TEST_ASSERT_ERROR(err, SVN_ERR_WC_CONFLICT_RESOLVER_FAILURE);
+ {
+ nodes_row_t nodes[] = {
+ {0, "", "normal", 1, ""},
+ {0, "A", "normal", 1, "A"},
+ {0, "A/B", "normal", 1, "A/B"},
+ {0, "A/B/C", "normal", 2, "A/B/C"},
+ {0, "P", "normal", 1, "P"},
+ {0, "P/Q", "normal", 1, "P/Q"},
+ {0, "P/Q/f", "normal", 1, "P/Q/f"},
+ {2, "A/B", "base-deleted", NO_COPY_FROM, "B2"},
+ {2, "A/B/C", "base-deleted", NO_COPY_FROM},
+ {1, "B2", "normal", 1, "A/B", MOVED_HERE},
+ {1, "B2/C", "normal", 1, "A/B/C", MOVED_HERE},
+ {0}
+ };
+ SVN_ERR(check_db_rows(&b, "", nodes));
+ }
+
+ SVN_ERR(sbox_wc_revert(&b, "", svn_depth_infinity));
+ SVN_ERR(sbox_wc_update(&b, "", 1));
+ SVN_ERR(sbox_wc_move(&b, "A/B", "B2"));
+ SVN_ERR(sbox_wc_move(&b, "P/Q", "Q2"));
+ SVN_ERR(sbox_wc_update_depth(&b, "A/B", 2, svn_depth_files, FALSE));
+ SVN_ERR(sbox_wc_update_depth(&b, "P/Q", 2, svn_depth_files, FALSE));
+ SVN_ERR(check_tree_conflict_repos_path(&b, "A/B", NULL, NULL));
+ err = sbox_wc_resolve(&b, "A/B", svn_depth_empty,
+ svn_wc_conflict_choose_mine_conflict);
+ SVN_TEST_ASSERT_ERROR(err, SVN_ERR_WC_CONFLICT_RESOLVER_FAILURE);
+ {
+ nodes_row_t nodes[] = {
+ {0, "", "normal", 1, ""},
+ {0, "A", "normal", 1, "A"},
+ {0, "A/B", "normal", 2, "A/B"},
+ {0, "A/B/C", "normal", 1, "A/B/C"},
+ {0, "P", "normal", 1, "P"},
+ {0, "P/Q", "normal", 2, "P/Q"},
+ {0, "P/Q/f", "normal", 2, "P/Q/f"},
+ {2, "A/B", "base-deleted", NO_COPY_FROM, "B2"},
+ {2, "A/B/C", "base-deleted", NO_COPY_FROM},
+ {2, "P/Q", "base-deleted", NO_COPY_FROM, "Q2"},
+ {2, "P/Q/f", "base-deleted", NO_COPY_FROM},
+ {1, "B2", "normal", 1, "A/B", MOVED_HERE},
+ {1, "B2/C", "normal", 1, "A/B/C", MOVED_HERE},
+ {1, "Q2", "normal", 2, "P/Q", MOVED_HERE},
+ {1, "Q2/f", "normal", 2, "P/Q/f", MOVED_HERE},
+ {0}
+ };
+ SVN_ERR(check_db_rows(&b, "", nodes));
+ }
+
+ SVN_ERR(sbox_wc_revert(&b, "", svn_depth_infinity));
+ SVN_ERR(sbox_wc_update(&b, "", 1));
+ SVN_ERR(sbox_wc_move(&b, "A/B", "B2"));
+ SVN_ERR(sbox_wc_move(&b, "P", "P2"));
+ SVN_ERR(sbox_wc_update_depth(&b, "A/B", 2, svn_depth_immediates, FALSE));
+ SVN_ERR(sbox_wc_update_depth(&b, "P", 2, svn_depth_immediates, FALSE));
+ SVN_ERR(check_tree_conflict_repos_path(&b, "P", NULL, NULL));
+ err = sbox_wc_resolve(&b, "P", svn_depth_empty,
+ svn_wc_conflict_choose_mine_conflict);
+ SVN_TEST_ASSERT_ERROR(err, SVN_ERR_WC_CONFLICT_RESOLVER_FAILURE);
+ {
+ nodes_row_t nodes[] = {
+ {0, "", "normal", 1, ""},
+ {0, "A", "normal", 1, "A"},
+ {0, "A/B", "normal", 2, "A/B"},
+ {0, "A/B/C", "normal", 2, "A/B/C"},
+ {0, "P", "normal", 2, "P"},
+ {0, "P/Q", "normal", 2, "P/Q"},
+ {0, "P/Q/f", "normal", 1, "P/Q/f"},
+ {2, "A/B", "base-deleted", NO_COPY_FROM, "B2"},
+ {2, "A/B/C", "base-deleted", NO_COPY_FROM},
+ {1, "P", "base-deleted", NO_COPY_FROM, "P2"},
+ {1, "P/Q", "base-deleted", NO_COPY_FROM},
+ {1, "P/Q/f", "base-deleted", NO_COPY_FROM},
+ {1, "B2", "normal", 2, "A/B", MOVED_HERE},
+ {1, "B2/C", "normal", 2, "A/B/C", MOVED_HERE},
+ {1, "P2", "normal", 1, "P", MOVED_HERE},
+ {1, "P2/Q", "normal", 1, "P/Q", MOVED_HERE},
+ {1, "P2/Q/f", "normal", 1, "P/Q/f", MOVED_HERE},
+ {0}
+ };
+ SVN_ERR(check_db_rows(&b, "", nodes));
+ }
+
+ SVN_ERR(sbox_wc_revert(&b, "", svn_depth_infinity));
+ SVN_ERR(sbox_wc_update(&b, "", 1));
+ SVN_ERR(sbox_wc_move(&b, "A/B/C", "C2"));
+ SVN_ERR(sbox_wc_move(&b, "P/Q", "Q2"));
+ SVN_ERR(sbox_wc_update_depth(&b, "A/B/C", 2, svn_depth_empty, FALSE));
+ SVN_ERR(sbox_wc_update_depth(&b, "P/Q", 2, svn_depth_empty, FALSE));
+ SVN_ERR(check_tree_conflict_repos_path(&b, "P/Q", NULL, NULL));
+ err = sbox_wc_resolve(&b, "P/Q", svn_depth_empty,
+ svn_wc_conflict_choose_mine_conflict);
+ SVN_TEST_ASSERT_ERROR(err, SVN_ERR_WC_CONFLICT_RESOLVER_FAILURE);
+ {
+ nodes_row_t nodes[] = {
+ {0, "", "normal", 1, ""},
+ {0, "A", "normal", 1, "A"},
+ {0, "A/B", "normal", 1, "A/B"},
+ {0, "A/B/C", "normal", 2, "A/B/C"},
+ {0, "P", "normal", 1, "P"},
+ {0, "P/Q", "normal", 2, "P/Q"},
+ {0, "P/Q/f", "normal", 1, "P/Q/f"},
+ {3, "A/B/C", "base-deleted", NO_COPY_FROM, "C2"},
+ {2, "P/Q", "base-deleted", NO_COPY_FROM, "Q2"},
+ {2, "P/Q/f", "base-deleted", NO_COPY_FROM},
+ {1, "C2", "normal", 2, "A/B/C", MOVED_HERE},
+ {1, "Q2", "normal", 1, "P/Q", MOVED_HERE},
+ {1, "Q2/f", "normal", 1, "P/Q/f", MOVED_HERE},
+ {0}
+ };
+ SVN_ERR(check_db_rows(&b, "", nodes));
+ }
+
+ return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+move_away_delete_update(const svn_test_opts_t *opts, apr_pool_t *pool)
+{
+ svn_test__sandbox_t b;
+ SVN_ERR(svn_test__sandbox_create(&b, "move_away_delete_update",
+ opts, pool));
+
+ SVN_ERR(sbox_wc_mkdir(&b, "A"));
+ SVN_ERR(sbox_wc_mkdir(&b, "A/B"));
+ SVN_ERR(sbox_wc_mkdir(&b, "A/B/C"));
+ SVN_ERR(sbox_wc_mkdir(&b, "P"));
+ SVN_ERR(sbox_wc_mkdir(&b, "P/Q"));
+ SVN_ERR(sbox_wc_commit(&b, ""));
+ SVN_ERR(sbox_wc_delete(&b, "A/B"));
+ SVN_ERR(sbox_wc_delete(&b, "P/Q"));
+ SVN_ERR(sbox_wc_commit(&b, ""));
+
+ SVN_ERR(sbox_wc_update(&b, "", 1));
+ SVN_ERR(sbox_wc_move(&b, "A/B/C", "C2"));
+ SVN_ERR(sbox_wc_move(&b, "P/Q", "Q2"));
+
+ /* Update to r2 removes the move sources and clears moved_here from
+ the move destinations. */
+ SVN_ERR(sbox_wc_update(&b, "", 2));
+ {
+ nodes_row_t nodes[] = {
+ {0, "", "normal", 2, ""},
+ {0, "A", "normal", 2, "A"},
+ {0, "P", "normal", 2, "P"},
+ {1, "C2", "normal", 1, "A/B/C"},
+ {1, "Q2", "normal", 1, "P/Q"},
+ {0}
+ };
+ SVN_ERR(check_db_rows(&b, "", nodes));
+ }
+
+ return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+move_not_present_variants(const svn_test_opts_t *opts, apr_pool_t *pool)
+{
+ svn_test__sandbox_t b;
+ SVN_ERR(svn_test__sandbox_create(&b, "move_not_present_variants",
+ opts, pool));
+
+ SVN_ERR(sbox_wc_mkdir(&b, "A"));
+ SVN_ERR(sbox_wc_mkdir(&b, "A/B"));
+ SVN_ERR(sbox_wc_mkdir(&b, "B"));
+ SVN_ERR(sbox_wc_mkdir(&b, "B/B"));
+ SVN_ERR(sbox_wc_mkdir(&b, "C"));
+ SVN_ERR(sbox_wc_mkdir(&b, "C/B"));
+ SVN_ERR(sbox_wc_mkdir(&b, "D"));
+ SVN_ERR(sbox_wc_mkdir(&b, "D/B"));
+ SVN_ERR(sbox_wc_commit(&b, ""));
+ SVN_ERR(sbox_wc_update(&b, "", 1));
+
+ SVN_ERR(sbox_wc_delete(&b, "A/B"));
+ SVN_ERR(sbox_wc_commit(&b, ""));
+
+ SVN_ERR(sbox_wc_delete(&b, "B/B"));
+ SVN_ERR(sbox_wc_update(&b, "C/B", 0));
+ SVN_ERR(sbox_wc_exclude(&b, "D/B"));
+
+ SVN_ERR(sbox_wc_copy(&b, "A", "cA"));
+ SVN_ERR(sbox_wc_copy(&b, "B", "cB"));
+ SVN_ERR(sbox_wc_copy(&b, "C", "cC"));
+ SVN_ERR(sbox_wc_copy(&b, "D", "cD"));
+
+ SVN_ERR(sbox_wc_copy(&b, "cA", "ccA"));
+ SVN_ERR(sbox_wc_copy(&b, "cB", "ccB"));
+ SVN_ERR(sbox_wc_copy(&b, "cC", "ccC"));
+ SVN_ERR(sbox_wc_copy(&b, "cD", "ccD"));
+
+ {
+ nodes_row_t nodes[] = {
+ {0, "", "normal", 1, ""},
+
+ /* Copy of a deleted + committed node */
+ {0, "A", "normal", 1, "A"},
+ {0, "A/B", "not-present", 2, "A/B"},
+
+ {1, "cA", "normal", 1, "A"},
+ {1, "cA/B", "not-present", 2, "A/B"},
+
+ {1, "ccA", "normal", 1, "A"},
+ {1, "ccA/B", "not-present", 2, "A/B"},
+
+ /* Copy of a local deleted node */
+ {0, "B", "normal", 1, "B"},
+ {0, "B/B", "normal", 1, "B/B"},
+ {2, "B/B", "base-deleted", NO_COPY_FROM},
+
+ {1, "cB", "normal", 1, "B",},
+ {1, "cB/B", "normal", 1, "B/B"},
+ {2, "cB/B", "base-deleted", NO_COPY_FROM},
+
+ {1, "ccB", "normal", 1, "B"},
+ {1, "ccB/B", "normal", 1, "B/B"},
+ {2, "ccB/B", "base-deleted", NO_COPY_FROM},
+
+ /* Copy of a to r0 updated node */
+ {0, "C", "normal", 1, "C"},
+ {0, "C/B", "not-present", 0, "C/B"},
+
+ {1, "cC", "normal", 1, "C"},
+ {1, "cC/B", "not-present", 0, "C/B"},
+
+ {1, "ccC", "normal", 1, "C"},
+ {1, "ccC/B", "not-present", 0, "C/B"},
+
+ /* Copy of an excluded node */
+ {0, "D", "normal", 1, "D"},
+ {0, "D/B", "excluded", 1, "D/B"},
+
+ {1, "cD", "normal", 1, "D"},
+ {1, "cD/B", "excluded", 1, "D/B"},
+
+ {1, "ccD", "normal", 1, "D"},
+ {1, "ccD/B", "excluded", 1, "D/B"},
+
+ {0}
+ };
+ SVN_ERR(check_db_rows(&b, "", nodes));
+ }
+
+ SVN_ERR(sbox_wc_revert(&b, "", svn_depth_infinity));
+ SVN_ERR(sbox_wc_delete(&b, "B/B"));
+
+ /* And now do the same thing with moves */
+
+ SVN_ERR(sbox_wc_move(&b, "A", "mA"));
+ SVN_ERR(sbox_wc_move(&b, "B", "mB"));
+ SVN_ERR(sbox_wc_move(&b, "C", "mC"));
+ SVN_ERR(sbox_wc_move(&b, "D", "mD"));
+
+ SVN_ERR(sbox_wc_move(&b, "mA", "mmA"));
+ SVN_ERR(sbox_wc_move(&b, "mB", "mmB"));
+ SVN_ERR(sbox_wc_move(&b, "mC", "mmC"));
+ SVN_ERR(sbox_wc_move(&b, "mD", "mmD"));
+
+ {
+ nodes_row_t nodes[] = {
+ {0, "", "normal", 1, ""},
+
+ /* Move of a deleted + committed node */
+ {0, "A", "normal", 1, "A"},
+ {0, "A/B", "not-present", 2, "A/B"},
+ {1, "A", "base-deleted", NO_COPY_FROM, "mmA"},
+
+ {1, "mmA", "normal", 1, "A", MOVED_HERE},
+ {1, "mmA/B", "not-present", 2, "A/B", MOVED_HERE},
+
+
+ /* Move of a local deleted node */
+ {0, "B", "normal", 1, "B"},
+ {0, "B/B", "normal", 1, "B/B"},
+ {1, "B", "base-deleted", NO_COPY_FROM, "mmB"},
+ {1, "B/B", "base-deleted", NO_COPY_FROM},
+
+ {1, "mmB", "normal", 1, "B", MOVED_HERE},
+ {1, "mmB/B", "normal", 1, "B/B", MOVED_HERE},
+ {2, "mmB/B", "base-deleted", NO_COPY_FROM},
+
+ /* Move of a to r0 updated node */
+ {0, "C", "normal", 1, "C"},
+ {0, "C/B", "not-present", 0, "C/B"},
+ {1, "C", "base-deleted", NO_COPY_FROM, "mmC"},
+
+ {1, "mmC", "normal", 1, "C", MOVED_HERE},
+ {1, "mmC/B", "not-present", 0, "C/B", MOVED_HERE},
+
+ /* Move of an excluded node */
+ {0, "D", "normal", 1, "D",},
+ {0, "D/B", "excluded", 1, "D/B", },
+ {1, "D", "base-deleted", NO_COPY_FROM, "mmD"},
+
+ {1, "mmD", "normal", 1, "D", MOVED_HERE},
+ {1, "mmD/B", "excluded", 1, "D/B", MOVED_HERE},
+
+ {0}
+ };
+ SVN_ERR(check_db_rows(&b, "", nodes));
+ }
+
+ /* And move everything back */
+ SVN_ERR(sbox_wc_move(&b, "mmA", "A"));
+ SVN_ERR(sbox_wc_move(&b, "mmB", "B"));
+ SVN_ERR(sbox_wc_move(&b, "mmC", "C"));
+ SVN_ERR(sbox_wc_move(&b, "mmD", "D"));
+
+ {
+ nodes_row_t nodes[] = {
+ {0, "", "normal", 1, ""},
+
+ /* deleted + committed node */
+ {0, "A", "normal", 1, "A"},
+ {0, "A/B", "not-present", 2, "A/B"},
+
+ /* local deleted node */
+ {0, "B", "normal", 1, "B"},
+ {0, "B/B", "normal", 1, "B/B"},
+ {2, "B/B", "base-deleted", NO_COPY_FROM},
+
+ /* To r0 updated node */
+ {0, "C", "normal", 1, "C"},
+ {0, "C/B", "not-present", 0, "C/B"},
+
+ /* Move of an excluded node */
+ {0, "D", "normal", 1, "D",},
+ {0, "D/B", "excluded", 1, "D/B", },
+
+ {0}
+ };
+ SVN_ERR(check_db_rows(&b, "", nodes));
+ }
+
+ return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+update_child_under_add(const svn_test_opts_t *opts, apr_pool_t *pool)
+{
+ svn_test__sandbox_t b;
+ svn_error_t *err;
+ nodes_row_t nodes[] = {
+ {0, "", "normal", 1, ""},
+ {0, "A", "normal", 1, "A"},
+ {0, "A/B", "not-present", 0, "A/B"},
+ {2, "A/B", "normal", NO_COPY_FROM},
+ {3, "A/B/C", "normal", NO_COPY_FROM},
+ {4, "A/B/C/D", "normal", NO_COPY_FROM},
+ {0}
+ };
+
+ SVN_ERR(svn_test__sandbox_create(&b, "update_child_under_add",
+ opts, pool));
+
+ SVN_ERR(sbox_wc_mkdir(&b, "A"));
+ SVN_ERR(sbox_wc_mkdir(&b, "A/B"));
+ SVN_ERR(sbox_wc_mkdir(&b, "A/B/C"));
+ SVN_ERR(sbox_wc_mkdir(&b, "A/B/C/D"));
+ SVN_ERR(sbox_wc_commit(&b, ""));
+ SVN_ERR(sbox_wc_update(&b, "", 1));
+ SVN_ERR(sbox_wc_update(&b, "A/B", 0));
+ SVN_ERR(sbox_wc_mkdir(&b, "A/B"));
+ SVN_ERR(sbox_wc_mkdir(&b, "A/B/C"));
+ SVN_ERR(sbox_wc_mkdir(&b, "A/B/C/D"));
+ SVN_ERR(check_db_rows(&b, "", nodes));
+
+ /* A/B/C/D is skipped as it has no base node parent */
+ SVN_ERR(sbox_wc_update(&b, "A/B/C/D", 1));
+ SVN_ERR(check_db_rows(&b, "", nodes));
+
+ /* A/B/C should be skipped as it has a not-present base node parent */
+ err = sbox_wc_update(&b, "A/B/C", 1);
+ svn_error_clear(err); /* Allow any error and always check NODES. */
+ SVN_ERR(check_db_rows(&b, "", nodes));
+
+ return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+delete_over_moved_away(const svn_test_opts_t *opts, apr_pool_t *pool)
+{
+ svn_test__sandbox_t b;
+
+ SVN_ERR(svn_test__sandbox_create(&b, "delete_over_moved_away",
+ opts, pool));
+
+ SVN_ERR(sbox_wc_mkdir(&b, "A"));
+ SVN_ERR(sbox_wc_mkdir(&b, "A/B"));
+ SVN_ERR(sbox_wc_mkdir(&b, "A/B/C"));
+
+ SVN_ERR(sbox_wc_commit(&b, ""));
+ SVN_ERR(sbox_wc_update(&b, "", 1));
+
+ SVN_ERR(sbox_wc_move(&b, "A/B", "B"));
+ SVN_ERR(sbox_wc_delete(&b, "A"));
+
+ {
+ nodes_row_t nodes[] = {
+ {0, "", "normal", 1, ""},
+
+ {0, "A", "normal", 1, "A"},
+ {1, "A", "base-deleted", NO_COPY_FROM},
+ {0, "A/B", "normal", 1, "A/B"},
+ {1, "A/B", "base-deleted", NO_COPY_FROM, "B"},
+ {0, "A/B/C", "normal", 1, "A/B/C"},
+ {1, "A/B/C", "base-deleted", NO_COPY_FROM},
+
+ {1, "B", "normal", 1, "A/B", MOVED_HERE},
+ {1, "B/C", "normal", 1, "A/B/C", MOVED_HERE},
+ {0}
+ };
+ SVN_ERR(check_db_rows(&b, "", nodes));
+ }
+
+ /* Now replace A with a similar tree */
+ SVN_ERR(sbox_wc_mkdir(&b, "A"));
+ SVN_ERR(sbox_wc_mkdir(&b, "A/B"));
+ SVN_ERR(sbox_wc_mkdir(&b, "A/B/C"));
+
+ {
+ nodes_row_t nodes[] = {
+ {0, "", "normal", 1, ""},
+
+ {0, "A", "normal", 1, "A"},
+ {1, "A", "normal", NO_COPY_FROM},
+ {0, "A/B", "normal", 1, "A/B"},
+ {1, "A/B", "base-deleted", NO_COPY_FROM, "B"},
+ {2, "A/B", "normal", NO_COPY_FROM},
+ {0, "A/B/C", "normal", 1, "A/B/C"},
+ {1, "A/B/C", "base-deleted", NO_COPY_FROM},
+ {3, "A/B/C", "normal", NO_COPY_FROM},
+
+ {1, "B", "normal", 1, "A/B", MOVED_HERE},
+ {1, "B/C", "normal", 1, "A/B/C", MOVED_HERE},
+ {0}
+ };
+ SVN_ERR(check_db_rows(&b, "", nodes));
+ }
+
+ /* And delete the new A */
+ SVN_ERR(sbox_wc_delete(&b, "A"));
+
+ {
+ nodes_row_t nodes[] = {
+ {0, "", "normal", 1, ""},
+
+ {0, "A", "normal", 1, "A"},
+ {1, "A", "base-deleted", NO_COPY_FROM},
+ {0, "A/B", "normal", 1, "A/B"},
+ /* And here the moved-to information is lost */
+ {1, "A/B", "base-deleted", NO_COPY_FROM, "B"},
+ {0, "A/B/C", "normal", 1, "A/B/C"},
+ {1, "A/B/C", "base-deleted", NO_COPY_FROM},
+
+ /* But the moved-here is still there */
+ {1, "B", "normal", 1, "A/B", MOVED_HERE},
+ {1, "B/C", "normal", 1, "A/B/C", MOVED_HERE},
+ {0}
+ };
+ SVN_ERR(check_db_rows(&b, "", nodes));
+ }
+
+ return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+movedto_opdepth(const svn_test_opts_t *opts, apr_pool_t *pool)
+{
+ svn_test__sandbox_t b;
+
+ SVN_ERR(svn_test__sandbox_create(&b, "moved_to_op_depth",
+ opts, pool));
+
+ SVN_ERR(sbox_wc_mkdir(&b, "A"));
+ SVN_ERR(sbox_wc_mkdir(&b, "A/B"));
+ SVN_ERR(sbox_wc_mkdir(&b, "A/B/C"));
+ SVN_ERR(sbox_wc_commit(&b, ""));
+ SVN_ERR(sbox_wc_update(&b, "", 1));
+
+ SVN_ERR(sbox_wc_move(&b, "A/B/C", "C"));
+
+ {
+ nodes_row_t nodes[] = {
+ {0, "", "normal", 1, ""},
+
+ {0, "A", "normal", 1, "A"},
+ {0, "A/B", "normal", 1, "A/B"},
+ {0, "A/B/C", "normal", 1, "A/B/C"},
+ {3, "A/B/C", "base-deleted", NO_COPY_FROM, "C"},
+
+ {1, "C", "normal", 1, "A/B/C", MOVED_HERE},
+ {0}
+ };
+ SVN_ERR(check_db_rows(&b, "", nodes));
+ }
+
+ /* And now the moved_to information has to switch op-depths */
+ SVN_ERR(sbox_wc_delete(&b, "A/B"));
+ {
+ nodes_row_t nodes[] = {
+ {0, "", "normal", 1, ""},
+
+ {0, "A", "normal", 1, "A"},
+ {0, "A/B", "normal", 1, "A/B"},
+ {0, "A/B/C", "normal", 1, "A/B/C"},
+
+ {2, "A/B", "base-deleted", NO_COPY_FROM},
+ {2, "A/B/C", "base-deleted", NO_COPY_FROM, "C"},
+
+ {1, "C", "normal", 1, "A/B/C", MOVED_HERE},
+ {0}
+ };
+ SVN_ERR(check_db_rows(&b, "", nodes));
+ }
+
+ /* And again */
+ SVN_ERR(sbox_wc_delete(&b, "A"));
+ {
+ nodes_row_t nodes[] = {
+ {0, "", "normal", 1, ""},
+
+ {0, "A", "normal", 1, "A"},
+ {0, "A/B", "normal", 1, "A/B"},
+ {0, "A/B/C", "normal", 1, "A/B/C"},
+
+ {1, "A", "base-deleted", NO_COPY_FROM},
+ {1, "A/B", "base-deleted", NO_COPY_FROM},
+ {1, "A/B/C", "base-deleted", NO_COPY_FROM, "C"},
+
+ {1, "C", "normal", 1, "A/B/C", MOVED_HERE},
+ {0}
+ };
+ SVN_ERR(check_db_rows(&b, "", nodes));
+ }
+
+ /* And now stay at the depth of A */
+ SVN_ERR(sbox_wc_mkdir(&b, "A"));
+ SVN_ERR(sbox_wc_mkdir(&b, "A/B"));
+
+ {
+ nodes_row_t nodes[] = {
+ {0, "", "normal", 1, ""},
+
+ {0, "A", "normal", 1, "A"},
+ {0, "A/B", "normal", 1, "A/B"},
+ {0, "A/B/C", "normal", 1, "A/B/C"},
+
+ {1, "A", "normal", NO_COPY_FROM},
+ {1, "A/B", "base-deleted", NO_COPY_FROM},
+ {1, "A/B/C", "base-deleted", NO_COPY_FROM, "C"},
+
+ {2, "A/B", "normal", NO_COPY_FROM},
+
+ {1, "C", "normal", 1, "A/B/C", MOVED_HERE},
+ {0}
+ };
+ SVN_ERR(check_db_rows(&b, "", nodes));
+ }
+
+ /* And see if it can jump back to B again? */
+ SVN_ERR(sbox_wc_delete(&b, "A"));
+ SVN_ERR(sbox_wc_revert(&b, "A", svn_depth_empty));
+
+ {
+ nodes_row_t nodes[] = {
+ {0, "", "normal", 1, ""},
+
+ {0, "A", "normal", 1, "A"},
+ {0, "A/B", "normal", 1, "A/B"},
+ {0, "A/B/C", "normal", 1, "A/B/C"},
+
+ {2, "A/B", "base-deleted", NO_COPY_FROM},
+ {2, "A/B/C", "base-deleted", NO_COPY_FROM, "C"},
+
+ {1, "C", "normal", 1, "A/B/C", MOVED_HERE},
+ {0}
+ };
+ SVN_ERR(check_db_rows(&b, "", nodes));
+ }
+
+ /* And can we bump it back to C itself? */
+ SVN_ERR(sbox_wc_revert(&b, "A", svn_depth_immediates));
+ {
+ nodes_row_t nodes[] = {
+ {0, "", "normal", 1, ""},
+
+ {0, "A", "normal", 1, "A"},
+ {0, "A/B", "normal", 1, "A/B"},
+ {0, "A/B/C", "normal", 1, "A/B/C"},
+
+ {3, "A/B/C", "base-deleted", NO_COPY_FROM, "C"},
+
+ {1, "C", "normal", 1, "A/B/C", MOVED_HERE},
+ {0}
+ };
+ SVN_ERR(check_db_rows(&b, "", nodes));
+ }
+
+ return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+new_basemove(const svn_test_opts_t *opts, apr_pool_t *pool)
+{
+ svn_test__sandbox_t b;
+
+ SVN_ERR(svn_test__sandbox_create(&b, "new_basemove",
+ opts, pool));
+
+ SVN_ERR(sbox_wc_mkdir(&b, "A"));
+ SVN_ERR(sbox_wc_mkdir(&b, "A/B"));
+ SVN_ERR(sbox_wc_mkdir(&b, "A/B/C"));
+ SVN_ERR(sbox_wc_commit(&b, ""));
+ SVN_ERR(sbox_wc_update(&b, "", 1));
+
+ /* We keep track of moved children of copies */
+ SVN_ERR(sbox_wc_copy(&b, "A", "Copy"));
+ SVN_ERR(sbox_wc_move(&b, "Copy/B/C", "C"));
+
+ {
+ nodes_row_t nodes[] = {
+ {0, "", "normal", 1, ""},
+
+ {0, "A", "normal", 1, "A"},
+ {0, "A/B", "normal", 1, "A/B"},
+ {0, "A/B/C", "normal", 1, "A/B/C"},
+
+ {1, "Copy", "normal", 1, "A"},
+ {1, "Copy/B", "normal", 1, "A/B"},
+ {1, "Copy/B/C", "normal", 1, "A/B/C"},
+
+ {3, "Copy/B/C", "base-deleted", NO_COPY_FROM, "C"},
+
+ /* C is a copy of A/B/C */
+ {1, "C", "normal", 1, "A/B/C", MOVED_HERE},
+ {0}
+ };
+ SVN_ERR(check_db_rows(&b, "", nodes));
+ }
+
+ {
+ apr_array_header_t *targets = apr_array_make(pool, 1, sizeof(char *));
+ APR_ARRAY_PUSH(targets, const char*) = sbox_wc_path(&b, "Copy");
+
+ SVN_ERR(sbox_wc_commit_ex(&b, targets, svn_depth_empty));
+ }
+
+ {
+ nodes_row_t nodes[] = {
+ {0, "", "normal", 1, ""},
+
+ {0, "A", "normal", 1, "A"},
+ {0, "A/B", "normal", 1, "A/B"},
+ {0, "A/B/C", "normal", 1, "A/B/C"},
+
+ {0, "Copy", "normal", 2, "Copy"},
+ {0, "Copy/B", "normal", 2, "Copy/B"},
+ {0, "Copy/B/C", "normal", 2, "Copy/B/C"},
+
+ {3, "Copy/B/C", "base-deleted", NO_COPY_FROM, "C"},
+
+ /* And this node is now a copy of Copy/B/C at r2 */
+ {1, "C", "normal", 2, "Copy/B/C", MOVED_HERE},
+ {0}
+ };
+ SVN_ERR(check_db_rows(&b, "", nodes));
+ }
+
+ return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+move_back(const svn_test_opts_t *opts, apr_pool_t *pool)
+{
+ svn_test__sandbox_t b;
+
+ SVN_ERR(svn_test__sandbox_create(&b, "move_back", opts, pool));
+
+ /* X just so we don't always test with local_relpath == repos_path */
+ SVN_ERR(sbox_wc_mkdir(&b, "X"));
+ SVN_ERR(sbox_wc_mkdir(&b, "X/A"));
+ SVN_ERR(sbox_wc_mkdir(&b, "X/A/B"));
+ SVN_ERR(sbox_wc_mkdir(&b, "X/A/B/C"));
+ SVN_ERR(sbox_wc_mkdir(&b, "X/A/B/D"));
+ SVN_ERR(sbox_wc_mkdir(&b, "X/E"));
+ SVN_ERR(sbox_wc_commit(&b, ""));
+ SVN_ERR(sbox_wc_switch(&b, "", "/X", svn_depth_infinity));
+
+ SVN_ERR(sbox_wc_move(&b, "A/B", "A/B2"));
+ {
+ nodes_row_t nodes[] = {
+ {0, "", "normal", 1, "X"},
+ {0, "A", "normal", 1, "X/A"},
+ {0, "A/B", "normal", 1, "X/A/B"},
+ {0, "A/B/C", "normal", 1, "X/A/B/C"},
+ {0, "A/B/D", "normal", 1, "X/A/B/D"},
+ {0, "E", "normal", 1, "X/E"},
+ {2, "A/B", "base-deleted", NO_COPY_FROM, "A/B2"},
+ {2, "A/B/C", "base-deleted", NO_COPY_FROM},
+ {2, "A/B/D", "base-deleted", NO_COPY_FROM},
+ {2, "A/B2", "normal", 1, "X/A/B", MOVED_HERE},
+ {2, "A/B2/C", "normal", 1, "X/A/B/C", MOVED_HERE},
+ {2, "A/B2/D", "normal", 1, "X/A/B/D", MOVED_HERE},
+ {0}
+ };
+ SVN_ERR(check_db_rows(&b, "", nodes));
+ }
+ SVN_ERR(sbox_wc_move(&b, "A/B2", "A/B"));
+ {
+ nodes_row_t nodes[] = {
+ {0, "", "normal", 1, "X"},
+ {0, "A", "normal", 1, "X/A"},
+ {0, "A/B", "normal", 1, "X/A/B"},
+ {0, "A/B/C", "normal", 1, "X/A/B/C"},
+ {0, "A/B/D", "normal", 1, "X/A/B/D"},
+ {0, "E", "normal", 1, "X/E"},
+ {0}
+ };
+ SVN_ERR(check_db_rows(&b, "", nodes));
+ }
+
+ SVN_ERR(sbox_wc_move(&b, "A/B", "A/B2"));
+ SVN_ERR(sbox_wc_move(&b, "A/B2/C", "A/B2/C2"));
+ SVN_ERR(sbox_wc_move(&b, "A/B2/D", "D2"));
+ SVN_ERR(sbox_wc_move(&b, "E", "A/B2/E2"));
+ {
+ nodes_row_t nodes[] = {
+ {0, "", "normal", 1, "X"},
+ {0, "A", "normal", 1, "X/A"},
+ {0, "A/B", "normal", 1, "X/A/B"},
+ {0, "A/B/C", "normal", 1, "X/A/B/C"},
+ {0, "A/B/D", "normal", 1, "X/A/B/D"},
+ {0, "E", "normal", 1, "X/E"},
+ {1, "D2", "normal", 1, "X/A/B/D", MOVED_HERE},
+ {1, "E", "base-deleted", NO_COPY_FROM, "A/B2/E2"},
+ {2, "A/B", "base-deleted", NO_COPY_FROM, "A/B2"},
+ {2, "A/B/C", "base-deleted", NO_COPY_FROM},
+ {2, "A/B/D", "base-deleted", NO_COPY_FROM},
+ {2, "A/B2", "normal", 1, "X/A/B", MOVED_HERE},
+ {2, "A/B2/C", "normal", 1, "X/A/B/C", MOVED_HERE},
+ {2, "A/B2/D", "normal", 1, "X/A/B/D", MOVED_HERE},
+ {3, "A/B2/C", "base-deleted", NO_COPY_FROM, "A/B2/C2"},
+ {3, "A/B2/D", "base-deleted", NO_COPY_FROM, "D2"},
+ {3, "A/B2/C2", "normal", 1, "X/A/B/C", MOVED_HERE},
+ {3, "A/B2/E2", "normal", 1, "X/E", MOVED_HERE},
+ {0}
+ };
+ SVN_ERR(check_db_rows(&b, "", nodes));
+ }
+ SVN_ERR(sbox_wc_move(&b, "A/B2", "A/B"));
+ {
+ nodes_row_t nodes[] = {
+ {0, "", "normal", 1, "X"},
+ {0, "A", "normal", 1, "X/A"},
+ {0, "A/B", "normal", 1, "X/A/B"},
+ {0, "A/B/C", "normal", 1, "X/A/B/C"},
+ {0, "A/B/D", "normal", 1, "X/A/B/D"},
+ {0, "E", "normal", 1, "X/E"},
+ {1, "D2", "normal", 1, "X/A/B/D", MOVED_HERE},
+ {1, "E", "base-deleted", NO_COPY_FROM, "A/B/E2"},
+ {3, "A/B/C", "base-deleted", NO_COPY_FROM, "A/B/C2"},
+ {3, "A/B/D", "base-deleted", NO_COPY_FROM, "D2"},
+ {3, "A/B/C2", "normal", 1, "X/A/B/C", MOVED_HERE},
+ {3, "A/B/E2", "normal", 1, "X/E", MOVED_HERE},
+ {0}
+ };
+ SVN_ERR(check_db_rows(&b, "", nodes));
+ }
+
+ return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+move_update_subtree(const svn_test_opts_t *opts, apr_pool_t *pool)
+{
+ svn_test__sandbox_t b;
+ svn_error_t *err;
+
+ SVN_ERR(svn_test__sandbox_create(&b, "move_update_subtree", opts, pool));
+
+ SVN_ERR(sbox_wc_mkdir(&b, "A"));
+ SVN_ERR(sbox_wc_mkdir(&b, "A/B"));
+ SVN_ERR(sbox_wc_mkdir(&b, "A/B/C"));
+ SVN_ERR(sbox_wc_commit(&b, ""));
+ SVN_ERR(sbox_wc_mkdir(&b, "A/B/C/D"));
+ SVN_ERR(sbox_wc_commit(&b, ""));
+ SVN_ERR(sbox_wc_mkdir(&b, "X"));
+ SVN_ERR(sbox_wc_commit(&b, ""));
+ SVN_ERR(sbox_wc_update(&b, "", 3));
+ SVN_ERR(sbox_wc_copy(&b, "A", "P"));
+ SVN_ERR(sbox_wc_commit(&b, ""));
+ SVN_ERR(sbox_wc_update(&b, "", 1));
+
+ /* Subtree update is like an interrupted update, it leaves a
+ mixed-revision move source. */
+ SVN_ERR(sbox_wc_move(&b, "A/B", "A/B2"));
+ SVN_ERR(sbox_wc_update(&b, "A/B/C", 2));
+ {
+ nodes_row_t nodes[] = {
+ {0, "", "normal", 1, ""},
+ {0, "A", "normal", 1, "A"},
+ {0, "A/B", "normal", 1, "A/B"},
+ {0, "A/B/C", "normal", 2, "A/B/C"},
+ {0, "A/B/C/D", "normal", 2, "A/B/C/D"},
+ {2, "A/B", "base-deleted", NO_COPY_FROM, "A/B2"},
+ {2, "A/B/C", "base-deleted", NO_COPY_FROM},
+ {2, "A/B/C/D", "base-deleted", NO_COPY_FROM},
+ {2, "A/B2", "normal", 1, "A/B", MOVED_HERE},
+ {2, "A/B2/C", "normal", 1, "A/B/C", MOVED_HERE},
+ {0}
+ };
+ SVN_ERR(check_db_rows(&b, "", nodes));
+ }
+
+ /* Resolve fails because of the mixed-revision. */
+ err = sbox_wc_resolve(&b, "A/B", svn_depth_empty,
+ svn_wc_conflict_choose_mine_conflict);
+ SVN_TEST_ASSERT_ERROR(err, SVN_ERR_WC_CONFLICT_RESOLVER_FAILURE);
+
+ /* Update to single-revision to allow resolve; this requires update
+ while the tree-conflict on A/B is present. */
+ SVN_ERR(sbox_wc_update(&b, "A/B", 2));
+ {
+ nodes_row_t nodes[] = {
+ {0, "", "normal", 1, ""},
+ {0, "A", "normal", 1, "A"},
+ {0, "A/B", "normal", 2, "A/B"},
+ {0, "A/B/C", "normal", 2, "A/B/C"},
+ {0, "A/B/C/D", "normal", 2, "A/B/C/D"},
+ {2, "A/B", "base-deleted", NO_COPY_FROM, "A/B2"},
+ {2, "A/B/C", "base-deleted", NO_COPY_FROM},
+ {2, "A/B/C/D", "base-deleted", NO_COPY_FROM},
+ {2, "A/B2", "normal", 1, "A/B", MOVED_HERE},
+ {2, "A/B2/C", "normal", 1, "A/B/C", MOVED_HERE},
+ {0}
+ };
+ SVN_ERR(check_db_rows(&b, "", nodes));
+ }
+
+ /* Now resolve is possible. */
+ SVN_ERR(sbox_wc_resolve(&b, "A/B", svn_depth_empty,
+ svn_wc_conflict_choose_mine_conflict));
+ {
+ nodes_row_t nodes[] = {
+ {0, "", "normal", 1, ""},
+ {0, "A", "normal", 1, "A"},
+ {0, "A/B", "normal", 2, "A/B"},
+ {0, "A/B/C", "normal", 2, "A/B/C"},
+ {0, "A/B/C/D", "normal", 2, "A/B/C/D"},
+ {2, "A/B", "base-deleted", NO_COPY_FROM, "A/B2"},
+ {2, "A/B/C", "base-deleted", NO_COPY_FROM},
+ {2, "A/B/C/D", "base-deleted", NO_COPY_FROM},
+ {2, "A/B2", "normal", 2, "A/B", MOVED_HERE},
+ {2, "A/B2/C", "normal", 2, "A/B/C", MOVED_HERE},
+ {2, "A/B2/C/D", "normal", 2, "A/B/C/D", MOVED_HERE},
+ {0}
+ };
+ SVN_ERR(check_db_rows(&b, "", nodes));
+ }
+
+ /* Subtree update that only bumps. */
+ SVN_ERR(sbox_wc_update(&b, "A/B/C", 3));
+ {
+ nodes_row_t nodes[] = {
+ {0, "", "normal", 1, ""},
+ {0, "A", "normal", 1, "A"},
+ {0, "A/B", "normal", 2, "A/B"},
+ {0, "A/B/C", "normal", 3, "A/B/C"},
+ {0, "A/B/C/D", "normal", 3, "A/B/C/D"},
+ {2, "A/B", "base-deleted", NO_COPY_FROM, "A/B2"},
+ {2, "A/B/C", "base-deleted", NO_COPY_FROM},
+ {2, "A/B/C/D", "base-deleted", NO_COPY_FROM},
+ {2, "A/B2", "normal", 2, "A/B", MOVED_HERE},
+ {2, "A/B2/C", "normal", 2, "A/B/C", MOVED_HERE},
+ {2, "A/B2/C/D", "normal", 2, "A/B/C/D", MOVED_HERE},
+ {0}
+ };
+ SVN_ERR(check_db_rows(&b, "", nodes));
+ }
+
+ /* Resolve fails because of the mixed-revision. */
+ err = sbox_wc_resolve(&b, "A/B", svn_depth_empty,
+ svn_wc_conflict_choose_mine_conflict);
+ SVN_TEST_ASSERT_ERROR(err, SVN_ERR_WC_CONFLICT_RESOLVER_FAILURE);
+
+ /* Update allowed while tree-conflict is present. */
+ SVN_ERR(sbox_wc_update(&b, "A/B", 3));
+ {
+ nodes_row_t nodes[] = {
+ {0, "", "normal", 1, ""},
+ {0, "A", "normal", 1, "A"},
+ {0, "A/B", "normal", 3, "A/B"},
+ {0, "A/B/C", "normal", 3, "A/B/C"},
+ {0, "A/B/C/D", "normal", 3, "A/B/C/D"},
+ {2, "A/B", "base-deleted", NO_COPY_FROM, "A/B2"},
+ {2, "A/B/C", "base-deleted", NO_COPY_FROM},
+ {2, "A/B/C/D", "base-deleted", NO_COPY_FROM},
+ {2, "A/B2", "normal", 2, "A/B", MOVED_HERE},
+ {2, "A/B2/C", "normal", 2, "A/B/C", MOVED_HERE},
+ {2, "A/B2/C/D", "normal", 2, "A/B/C/D", MOVED_HERE},
+ {0}
+ };
+ SVN_ERR(check_db_rows(&b, "", nodes));
+ }
+
+ /* Now resolve works. */
+ SVN_ERR(sbox_wc_resolve(&b, "A/B", svn_depth_empty,
+ svn_wc_conflict_choose_mine_conflict));
+ {
+ nodes_row_t nodes[] = {
+ {0, "", "normal", 1, ""},
+ {0, "A", "normal", 1, "A"},
+ {0, "A/B", "normal", 3, "A/B"},
+ {0, "A/B/C", "normal", 3, "A/B/C"},
+ {0, "A/B/C/D", "normal", 3, "A/B/C/D"},
+ {2, "A/B", "base-deleted", NO_COPY_FROM, "A/B2"},
+ {2, "A/B/C", "base-deleted", NO_COPY_FROM},
+ {2, "A/B/C/D", "base-deleted", NO_COPY_FROM},
+ {2, "A/B2", "normal", 3, "A/B", MOVED_HERE},
+ {2, "A/B2/C", "normal", 3, "A/B/C", MOVED_HERE},
+ {2, "A/B2/C/D", "normal", 3, "A/B/C/D", MOVED_HERE},
+ {0}
+ };
+ SVN_ERR(check_db_rows(&b, "", nodes));
+ }
+
+ /* Partial switch of source. */
+ SVN_ERR(sbox_wc_switch(&b, "A", "/P", svn_depth_immediates));
+ {
+ nodes_row_t nodes[] = {
+ {0, "", "normal", 1, ""},
+ {0, "A", "normal", 4, "P"},
+ {0, "A/B", "normal", 4, "P/B"},
+ {0, "A/B/C", "normal", 3, "A/B/C"},
+ {0, "A/B/C/D", "normal", 3, "A/B/C/D"},
+ {2, "A/B", "base-deleted", NO_COPY_FROM, "A/B2"},
+ {2, "A/B/C", "base-deleted", NO_COPY_FROM},
+ {2, "A/B/C/D", "base-deleted", NO_COPY_FROM},
+ {2, "A/B2", "normal", 3, "A/B", MOVED_HERE},
+ {2, "A/B2/C", "normal", 3, "A/B/C", MOVED_HERE},
+ {2, "A/B2/C/D", "normal", 3, "A/B/C/D", MOVED_HERE},
+ {0}
+ };
+ SVN_ERR(check_db_rows(&b, "", nodes));
+ }
+
+ /* Resolve fails because of the subtree-switch. */
+ err = sbox_wc_resolve(&b, "A/B", svn_depth_empty,
+ svn_wc_conflict_choose_mine_conflict);
+ SVN_TEST_ASSERT_ERROR(err, SVN_ERR_WC_CONFLICT_RESOLVER_FAILURE);
+
+ /* Switch works while tree-conflict is present. */
+ SVN_ERR(sbox_wc_switch(&b, "A", "/P", svn_depth_infinity));
+ {
+ nodes_row_t nodes[] = {
+ {0, "", "normal", 1, ""},
+ {0, "A", "normal", 4, "P"},
+ {0, "A/B", "normal", 4, "P/B"},
+ {0, "A/B/C", "normal", 4, "P/B/C"},
+ {0, "A/B/C/D", "normal", 4, "P/B/C/D"},
+ {2, "A/B", "base-deleted", NO_COPY_FROM, "A/B2"},
+ {2, "A/B/C", "base-deleted", NO_COPY_FROM},
+ {2, "A/B/C/D", "base-deleted", NO_COPY_FROM},
+ {2, "A/B2", "normal", 3, "A/B", MOVED_HERE},
+ {2, "A/B2/C", "normal", 3, "A/B/C", MOVED_HERE},
+ {2, "A/B2/C/D", "normal", 3, "A/B/C/D", MOVED_HERE},
+ {0}
+ };
+ SVN_ERR(check_db_rows(&b, "", nodes));
+ }
+
+ /* Now resolve works. */
+ SVN_ERR(sbox_wc_resolve(&b, "A/B", svn_depth_empty,
+ svn_wc_conflict_choose_mine_conflict));
+ {
+ nodes_row_t nodes[] = {
+ {0, "", "normal", 1, ""},
+ {0, "A", "normal", 4, "P"},
+ {0, "A/B", "normal", 4, "P/B"},
+ {0, "A/B/C", "normal", 4, "P/B/C"},
+ {0, "A/B/C/D", "normal", 4, "P/B/C/D"},
+ {2, "A/B", "base-deleted", NO_COPY_FROM, "A/B2"},
+ {2, "A/B/C", "base-deleted", NO_COPY_FROM},
+ {2, "A/B/C/D", "base-deleted", NO_COPY_FROM},
+ {2, "A/B2", "normal", 4, "P/B", MOVED_HERE},
+ {2, "A/B2/C", "normal", 4, "P/B/C", MOVED_HERE},
+ {2, "A/B2/C/D", "normal", 4, "P/B/C/D", MOVED_HERE},
+ {0}
+ };
+ SVN_ERR(check_db_rows(&b, "", nodes));
+ }
+
+ return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+move_parent_into_child(const svn_test_opts_t *opts, apr_pool_t *pool)
+{
+ svn_test__sandbox_t b;
+
+ SVN_ERR(svn_test__sandbox_create(&b, "move_parent_into_child", opts, pool));
+ SVN_ERR(sbox_wc_mkdir(&b, "A"));
+ SVN_ERR(sbox_wc_mkdir(&b, "A/B"));
+ SVN_ERR(sbox_wc_commit(&b, ""));
+ SVN_ERR(sbox_wc_update(&b, "", 1));
+
+ SVN_ERR(sbox_wc_move(&b, "A/B", "B2"));
+ SVN_ERR(sbox_wc_move(&b, "A", "B2/A"));
+ {
+ nodes_row_t nodes[] = {
+ {0, "", "normal", 1, ""},
+ {0, "A", "normal", 1, "A"},
+ {0, "A/B", "normal", 1, "A/B"},
+ {1, "A", "base-deleted", NO_COPY_FROM, "B2/A"},
+ {1, "A/B", "base-deleted", NO_COPY_FROM},
+ {1, "B2", "normal", 1, "A/B", MOVED_HERE},
+ {2, "B2/A", "normal", 1, "A", MOVED_HERE},
+ {2, "B2/A/B", "normal", 1, "A/B", MOVED_HERE},
+ {3, "B2/A/B", "base-deleted", NO_COPY_FROM, "B2"},
+ {0}
+ };
+ SVN_ERR(check_db_rows(&b, "", nodes));
+ }
+
+ SVN_ERR(sbox_wc_move(&b, "B2", "A"));
+ {
+ nodes_row_t nodes[] = {
+ {0, "", "normal", 1, ""},
+ {0, "A", "normal", 1, "A"},
+ {0, "A/B", "normal", 1, "A/B"},
+ {1, "A", "normal", 1, "A/B", FALSE, "A/A", TRUE},
+ {1, "A/B", "base-deleted", NO_COPY_FROM},
+ {2, "A/A", "normal", 1, "A", MOVED_HERE},
+ {2, "A/A/B", "normal", 1, "A/B", MOVED_HERE},
+ {3, "A/A/B", "base-deleted", NO_COPY_FROM, "A"},
+ {0}
+ };
+ SVN_ERR(check_db_rows(&b, "", nodes));
+ }
+
+ SVN_ERR(sbox_wc_move(&b, "A/A", "A/B"));
+ {
+ nodes_row_t nodes[] = {
+ {0, "", "normal", 1, ""},
+ {0, "A", "normal", 1, "A"},
+ {0, "A/B", "normal", 1, "A/B"},
+ {1, "A", "normal", 1, "A/B", FALSE, "A/B", TRUE},
+ {1, "A/B", "base-deleted", NO_COPY_FROM},
+ {2, "A/B", "normal", 1, "A", MOVED_HERE},
+ {2, "A/B/B", "normal", 1, "A/B", MOVED_HERE},
+ {3, "A/B/B", "base-deleted", NO_COPY_FROM, "A"},
+ {0}
+ };
+ SVN_ERR(check_db_rows(&b, "", nodes));
+ }
+
+ return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+move_depth_expand(const svn_test_opts_t *opts, apr_pool_t *pool)
+{
+ svn_test__sandbox_t b;
+
+ SVN_ERR(svn_test__sandbox_create(&b, "move_depth_expand", opts, pool));
+ SVN_ERR(sbox_wc_mkdir(&b, "A"));
+ SVN_ERR(sbox_wc_mkdir(&b, "A/A"));
+ SVN_ERR(sbox_wc_mkdir(&b, "A/A/A"));
+ SVN_ERR(sbox_wc_mkdir(&b, "A/A/A/A"));
+ SVN_ERR(sbox_wc_mkdir(&b, "A/B"));
+ SVN_ERR(sbox_wc_mkdir(&b, "A/B/A"));
+ SVN_ERR(sbox_wc_mkdir(&b, "A/B/A/A"));
+ SVN_ERR(sbox_wc_commit(&b, ""));
+ SVN_ERR(sbox_wc_update(&b, "", 0));
+
+ SVN_ERR(sbox_wc_update_depth(&b, "", 1, svn_depth_immediates, TRUE));
+ SVN_ERR(sbox_wc_update_depth(&b, "A", 1, svn_depth_immediates, TRUE));
+ /* Make A/B not present */
+ SVN_ERR(sbox_wc_update_depth(&b, "A/B", 0, svn_depth_immediates, TRUE));
+
+ SVN_ERR(sbox_wc_move(&b, "A", "C"));
+ SVN_ERR(sbox_wc_mkdir(&b, "C/A/A")); /* Local addition obstruction */
+ SVN_ERR(sbox_wc_copy(&b, "C/A", "C/B")); /* Copied obstruction */
+
+ {
+ nodes_row_t nodes[] = {
+ {0, "", "normal", 1, "" },
+
+ {0, "A", "normal", 1, "A" },
+ {1, "A", "base-deleted", NO_COPY_FROM, "C" },
+ {0, "A/A", "normal", 1, "A/A" },
+ {1, "A/A", "base-deleted", NO_COPY_FROM },
+ {0, "A/B", "not-present", 0, "A/B" },
+
+ {1, "C", "normal", 1, "A", MOVED_HERE },
+
+ {1, "C/A", "normal", 1, "A/A", MOVED_HERE },
+ {3, "C/A/A", "normal", NO_COPY_FROM },
+
+ {1, "C/B", "not-present", 0, "A/B", MOVED_HERE},
+ {2, "C/B", "normal", 1, "A/A" },
+ {3, "C/B/A", "normal", NO_COPY_FROM },
+ {0}
+ };
+ SVN_ERR(check_db_rows(&b, "", nodes));
+ }
+
+ SVN_ERR(sbox_wc_update_depth(&b, "", 1, svn_depth_infinity, TRUE));
+
+ /* This used to cause a segfault. Then it asserted in a different place */
+ SVN_ERR(sbox_wc_resolve(&b, "A", svn_depth_empty,
+ svn_wc_conflict_choose_mine_conflict));
+
+ /* And now verify that there are no not-present nodes left and a
+ consistent working copy */
+ {
+ nodes_row_t nodes[] = {
+ {0, "", "normal", 1, "" },
+
+ {0, "A", "normal", 1, "A" },
+ {0, "A/A", "normal", 1, "A/A" },
+ {0, "A/A/A", "normal", 1, "A/A/A" },
+ {0, "A/A/A/A", "normal", 1, "A/A/A/A" },
+ {0, "A/B", "normal", 1, "A/B" },
+ {0, "A/B/A", "normal", 1, "A/B/A" },
+ {0, "A/B/A/A", "normal", 1, "A/B/A/A" },
+
+ {1, "A", "base-deleted", NO_COPY_FROM, "C" },
+ {1, "A/A", "base-deleted", NO_COPY_FROM },
+ {1, "A/A/A", "base-deleted", NO_COPY_FROM },
+ {1, "A/B", "base-deleted", NO_COPY_FROM },
+ {1, "A/B/A", "base-deleted", NO_COPY_FROM },
+ {1, "A/B/A/A", "base-deleted", NO_COPY_FROM },
+ {1, "A/A/A/A", "base-deleted", NO_COPY_FROM },
+
+
+ {1, "C", "normal", 1, "A", MOVED_HERE },
+ {1, "C/A", "normal", 1, "A/A", MOVED_HERE },
+ {1, "C/A/A", "normal", 1, "A/A/A", MOVED_HERE },
+ {1, "C/A/A/A", "normal", 1, "A/A/A/A", MOVED_HERE },
+
+ {3, "C/A/A", "normal", NO_COPY_FROM },
+ {3, "C/A/A/A", "base-deleted", NO_COPY_FROM },
+
+ {1, "C/B", "normal", 1, "A/B", MOVED_HERE },
+ {1, "C/B/A", "normal", 1, "A/B/A", MOVED_HERE },
+ {1, "C/B/A/A", "normal", 1, "A/B/A/A", MOVED_HERE },
+
+ {2, "C/B", "normal", 1, "A/A" },
+ {2, "C/B/A", "base-deleted", NO_COPY_FROM },
+ {2, "C/B/A/A", "base-deleted", NO_COPY_FROM },
+
+ {3, "C/B/A", "normal", NO_COPY_FROM },
+
+ {0}
+ };
+ SVN_ERR(check_db_rows(&b, "", nodes));
+ }
+
+ return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+move_retract(const svn_test_opts_t *opts, apr_pool_t *pool)
+{
+ svn_test__sandbox_t b;
+
+ SVN_ERR(svn_test__sandbox_create(&b, "move_retract", opts, pool));
+
+ SVN_ERR(sbox_wc_mkdir(&b, "A"));
+ SVN_ERR(sbox_wc_mkdir(&b, "A/A"));
+ SVN_ERR(sbox_wc_mkdir(&b, "A/A/A"));
+ SVN_ERR(sbox_wc_mkdir(&b, "A/A/A/A"));
+ SVN_ERR(sbox_wc_mkdir(&b, "A/A/A/C"));
+ SVN_ERR(sbox_wc_mkdir(&b, "A/A/A/D"));
+ SVN_ERR(sbox_wc_mkdir(&b, "A/B"));
+ SVN_ERR(sbox_wc_mkdir(&b, "A/B/A"));
+ SVN_ERR(sbox_wc_mkdir(&b, "A/B/A/A"));
+ SVN_ERR(sbox_wc_mkdir(&b, "A/B/A/C"));
+ SVN_ERR(sbox_wc_mkdir(&b, "A/B/A/D"));
+ SVN_ERR(sbox_wc_commit(&b, ""));
+ SVN_ERR(sbox_wc_delete(&b, "A/A/A/A"));
+ SVN_ERR(sbox_wc_delete(&b, "A/A/A/C"));
+ SVN_ERR(sbox_wc_delete(&b, "A/A/A/D"));
+ SVN_ERR(sbox_wc_delete(&b, "A/B/A/C"));
+ SVN_ERR(sbox_wc_commit(&b, ""));
+
+ SVN_ERR(sbox_wc_update(&b, "", 1));
+ SVN_ERR(sbox_wc_move(&b, "A/B/A/D", "D"));
+ SVN_ERR(sbox_wc_delete(&b, "A/B"));
+ SVN_ERR(sbox_wc_move(&b, "A/A", "A/B"));
+
+ {
+ nodes_row_t nodes[] = {
+ {0, "", "normal", 1, "" },
+
+ {0, "A", "normal", 1, "A" },
+ {0, "A/A", "normal", 1, "A/A" },
+ {0, "A/A/A", "normal", 1, "A/A/A" },
+ {0, "A/A/A/A", "normal", 1, "A/A/A/A" },
+ {0, "A/A/A/C", "normal", 1, "A/A/A/C" },
+ {0, "A/A/A/D", "normal", 1, "A/A/A/D" },
+
+ {2, "A/A", "base-deleted", NO_COPY_FROM, "A/B"},
+ {2, "A/A/A", "base-deleted", NO_COPY_FROM },
+ {2, "A/A/A/A", "base-deleted", NO_COPY_FROM },
+ {2, "A/A/A/C", "base-deleted", NO_COPY_FROM },
+ {2, "A/A/A/D", "base-deleted", NO_COPY_FROM },
+
+ {0, "A/B", "normal", 1, "A/B" },
+ {0, "A/B/A", "normal", 1, "A/B/A" },
+ {0, "A/B/A/A", "normal", 1, "A/B/A/A" },
+ {0, "A/B/A/C", "normal", 1, "A/B/A/C" },
+ {0, "A/B/A/D", "normal", 1, "A/B/A/D" },
+
+ {2, "A/B", "normal", 1, "A/A", MOVED_HERE },
+ {2, "A/B/A", "normal", 1, "A/A/A", MOVED_HERE },
+ {2, "A/B/A/A", "normal", 1, "A/A/A/A", MOVED_HERE },
+ {2, "A/B/A/C", "normal", 1, "A/A/A/C", MOVED_HERE },
+ {2, "A/B/A/D", "normal", 1, "A/A/A/D", FALSE, "D", TRUE },
+
+ {1, "D", "normal", 1, "A/B/A/D", MOVED_HERE },
+
+ {0}
+ };
+ SVN_ERR(check_db_rows(&b, "", nodes));
+ }
+
+ SVN_ERR(sbox_wc_update(&b, "", 2));
+
+ {
+ nodes_row_t nodes[] = {
+ {0, "", "normal", 2, "" },
+
+ {0, "A", "normal", 2, "A" },
+ {0, "A/A", "normal", 2, "A/A" },
+ {0, "A/A/A", "normal", 2, "A/A/A" },
+
+ {2, "A/A", "base-deleted", NO_COPY_FROM, "A/B"},
+ {2, "A/A/A", "base-deleted", NO_COPY_FROM },
+
+ {0, "A/B", "normal", 2, "A/B" },
+ {0, "A/B/A", "normal", 2, "A/B/A" },
+ {0, "A/B/A/A", "normal", 2, "A/B/A/A" },
+ {0, "A/B/A/D", "normal", 2, "A/B/A/D" },
+
+ {2, "A/B", "normal", 1, "A/A", MOVED_HERE },
+ {2, "A/B/A", "normal", 1, "A/A/A", MOVED_HERE },
+ {2, "A/B/A/A", "normal", 1, "A/A/A/A", MOVED_HERE },
+ {2, "A/B/A/C", "normal", 1, "A/A/A/C", MOVED_HERE },
+ {2, "A/B/A/D", "normal", 1, "A/A/A/D", FALSE, "D", TRUE },
+
+ {1, "D", "normal", 1, "A/B/A/D", MOVED_HERE },
+
+ {0}
+ };
+ SVN_ERR(check_db_rows(&b, "", nodes));
+ }
+
+
+ SVN_ERR(sbox_wc_resolve(&b, "A/A", svn_depth_empty,
+ svn_wc_conflict_choose_mine_conflict));
+
+ {
+ nodes_row_t nodes[] = {
+ {0, "", "normal", 2, "" },
+
+ {0, "A", "normal", 2, "A" },
+ {0, "A/A", "normal", 2, "A/A" },
+ {0, "A/A/A", "normal", 2, "A/A/A" },
+
+ {0, "A/B", "normal", 2, "A/B" },
+ {0, "A/B/A", "normal", 2, "A/B/A" },
+ {0, "A/B/A/A", "normal", 2, "A/B/A/A" },
+ {0, "A/B/A/D", "normal", 2, "A/B/A/D" },
+
+ {2, "A/A", "base-deleted", NO_COPY_FROM, "A/B"},
+ {2, "A/A/A", "base-deleted", NO_COPY_FROM },
+
+ {2, "A/B", "normal", 2, "A/A", MOVED_HERE },
+ {2, "A/B/A", "normal", 2, "A/A/A", MOVED_HERE },
+ {2, "A/B/A/A", "base-deleted", NO_COPY_FROM }, /* ### MISSING! */
+ {2, "A/B/A/D", "base-deleted", NO_COPY_FROM, "D" }, /* ### MISSING! */
+
+ /* Still conflicted */
+ {1, "D", "normal", 1, "A/B/A/D", MOVED_HERE },
+
+ {0}
+ };
+ SVN_ERR(check_db_rows(&b, "", nodes));
+ }
+
+ /* ### TODO: Resolve via which specific target? */
+ SVN_ERR(sbox_wc_resolve(&b, "", svn_depth_infinity,
+ svn_wc_conflict_choose_mine_conflict));
+
+ {
+ nodes_row_t nodes[] = {
+
+ {1, "D", "normal", 2, "A/B/A/D", MOVED_HERE },
+
+ {0}
+ };
+ SVN_ERR(check_db_rows(&b, "D", nodes));
+ }
+
+ return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+move_delete_file_externals(const svn_test_opts_t *opts, apr_pool_t *pool)
+{
+ svn_test__sandbox_t b;
+
+ SVN_ERR(svn_test__sandbox_create(&b, "move_delete_file_externals", opts,
+ pool));
+
+ SVN_ERR(sbox_wc_mkdir(&b, "A"));
+ SVN_ERR(sbox_wc_mkdir(&b, "A/B"));
+ sbox_file_write(&b, "f", "New file");
+ SVN_ERR(sbox_wc_add(&b, "f"));
+ SVN_ERR(sbox_wc_propset(&b, "svn:externals", "^/f B/P/g", "A"));
+ SVN_ERR(sbox_wc_propset(&b, "svn:externals", "^/f Q/g\n^/f g", "A/B"));
+ SVN_ERR(sbox_wc_commit(&b, ""));
+ SVN_ERR(sbox_wc_update(&b, "", 1));
+
+ {
+ nodes_row_t nodes[] = {
+ {0, "", "normal", 1, ""},
+ {0, "A", "normal", 1, "A"},
+ {0, "A/B", "normal", 1, "A/B"},
+ {0, "f", "normal", 1, "f"},
+ {0, "A/B/g", "normal", 1, "f", TRUE},
+ {0, "A/B/P/g", "normal", 1, "f", TRUE},
+ {0, "A/B/Q/g", "normal", 1, "f", TRUE},
+ {0}
+ };
+ SVN_ERR(check_db_rows(&b, "", nodes));
+ }
+
+ /* Delete removes the file external rows. */
+ SVN_ERR(sbox_wc_delete(&b, "A"));
+ {
+ nodes_row_t nodes[] = {
+ {0, "", "normal", 1, ""},
+ {0, "A", "normal", 1, "A"},
+ {0, "A/B", "normal", 1, "A/B"},
+ {0, "f", "normal", 1, "f"},
+ {1, "A", "base-deleted", NO_COPY_FROM},
+ {1, "A/B", "base-deleted", NO_COPY_FROM},
+ {0}
+ };
+ SVN_ERR(check_db_rows(&b, "", nodes));
+ }
+
+ /* Revert doesn't restore the file external rows... */
+ SVN_ERR(sbox_wc_revert(&b, "A", svn_depth_infinity));
+ {
+ nodes_row_t nodes[] = {
+ {0, "", "normal", 1, ""},
+ {0, "A", "normal", 1, "A"},
+ {0, "A/B", "normal", 1, "A/B"},
+ {0, "f", "normal", 1, "f"},
+ {0}
+ };
+ SVN_ERR(check_db_rows(&b, "", nodes));
+ }
+ /* ... but update does. */
+ SVN_ERR(sbox_wc_update(&b, "", 1));
+ {
+ nodes_row_t nodes[] = {
+ {0, "", "normal", 1, ""},
+ {0, "A", "normal", 1, "A"},
+ {0, "A/B", "normal", 1, "A/B"},
+ {0, "f", "normal", 1, "f"},
+ {0, "A/B/g", "normal", 1, "f", TRUE},
+ {0, "A/B/P/g", "normal", 1, "f", TRUE},
+ {0, "A/B/Q/g", "normal", 1, "f", TRUE},
+ {0}
+ };
+ SVN_ERR(check_db_rows(&b, "", nodes));
+ }
+
+ /* Move removes the file external rows. */
+ SVN_ERR(sbox_wc_move(&b, "A", "A2"));
+ {
+ nodes_row_t nodes[] = {
+ {0, "", "normal", 1, ""},
+ {0, "A", "normal", 1, "A"},
+ {0, "A/B", "normal", 1, "A/B"},
+ {0, "f", "normal", 1, "f"},
+ {1, "A", "base-deleted", NO_COPY_FROM, "A2"},
+ {1, "A/B", "base-deleted", NO_COPY_FROM},
+ {1, "A2", "normal", 1, "A", MOVED_HERE},
+ {1, "A2/B", "normal", 1, "A/B", MOVED_HERE},
+ {0}
+ };
+ SVN_ERR(check_db_rows(&b, "", nodes));
+ }
+ /* Update adds file external rows to the copy. */
+ SVN_ERR(sbox_wc_update(&b, "", 1));
+ {
+ nodes_row_t nodes[] = {
+ {0, "", "normal", 1, ""},
+ {0, "A", "normal", 1, "A"},
+ {0, "A/B", "normal", 1, "A/B"},
+ {0, "f", "normal", 1, "f"},
+ {1, "A", "base-deleted", NO_COPY_FROM, "A2"},
+ {1, "A/B", "base-deleted", NO_COPY_FROM},
+ {1, "A2", "normal", 1, "A", MOVED_HERE},
+ {1, "A2/B", "normal", 1, "A/B", MOVED_HERE},
+ {0, "A2/B/g", "normal", 1, "f", TRUE},
+ {0, "A2/B/P/g", "normal", 1, "f", TRUE},
+ {0, "A2/B/Q/g", "normal", 1, "f", TRUE},
+ {0}
+ };
+ SVN_ERR(check_db_rows(&b, "", nodes));
+ }
+
+ return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+update_with_tree_conflict(const svn_test_opts_t *opts, apr_pool_t *pool)
+{
+ svn_test__sandbox_t b;
+
+ SVN_ERR(svn_test__sandbox_create(&b, "update_with_tree_conflict", opts,
+ pool));
+
+ SVN_ERR(sbox_wc_mkdir(&b, "A"));
+ SVN_ERR(sbox_wc_mkdir(&b, "A/B"));
+ SVN_ERR(sbox_wc_commit(&b, ""));
+ SVN_ERR(sbox_wc_mkdir(&b, "A/B/C"));
+ SVN_ERR(sbox_wc_commit(&b, ""));
+ SVN_ERR(sbox_wc_update(&b, "", 1));
+ SVN_ERR(sbox_wc_move(&b, "A", "A2"));
+
+ SVN_ERR(sbox_wc_update_depth(&b, "A", 2, svn_depth_empty, FALSE));
+ {
+ nodes_row_t nodes[] = {
+ {0, "", "normal", 1, ""},
+ {0, "A", "normal", 2, "A"},
+ {0, "A/B", "normal", 1, "A/B"},
+ {1, "A", "base-deleted", NO_COPY_FROM, "A2"},
+ {1, "A/B", "base-deleted", NO_COPY_FROM},
+ {1, "A2", "normal", 1, "A", MOVED_HERE},
+ {1, "A2/B", "normal", 1, "A/B", MOVED_HERE},
+ {0}
+ };
+ SVN_ERR(check_db_rows(&b, "", nodes));
+ }
+
+ SVN_ERR(sbox_wc_update(&b, "A", 2));
+ {
+ nodes_row_t nodes[] = {
+ {0, "", "normal", 1, ""},
+ {0, "A", "normal", 2, "A"},
+ {0, "A/B", "normal", 2, "A/B"},
+ {0, "A/B/C", "normal", 2, "A/B/C"},
+ {1, "A", "base-deleted", NO_COPY_FROM, "A2"},
+ {1, "A/B", "base-deleted", NO_COPY_FROM},
+ {1, "A/B/C", "base-deleted", NO_COPY_FROM},
+ {1, "A2", "normal", 1, "A", MOVED_HERE},
+ {1, "A2/B", "normal", 1, "A/B", MOVED_HERE},
+ {0}
+ };
+ SVN_ERR(check_db_rows(&b, "", nodes));
+ }
+
+ /* Second update overwrote the existing tree-conflict and that
+ causes the move-update to assert. */
+ SVN_ERR(sbox_wc_resolve(&b, "A", svn_depth_infinity,
+ svn_wc_conflict_choose_mine_conflict));
+ {
+ nodes_row_t nodes[] = {
+ {0, "", "normal", 1, ""},
+ {0, "A", "normal", 2, "A"},
+ {0, "A/B", "normal", 2, "A/B"},
+ {0, "A/B/C", "normal", 2, "A/B/C"},
+ {1, "A", "base-deleted", NO_COPY_FROM, "A2"},
+ {1, "A/B", "base-deleted", NO_COPY_FROM},
+ {1, "A/B/C", "base-deleted", NO_COPY_FROM},
+ {1, "A2", "normal", 2, "A", MOVED_HERE},
+ {1, "A2/B", "normal", 2, "A/B", MOVED_HERE},
+ {1, "A2/B/C", "normal", 2, "A/B/C", MOVED_HERE},
+ {0}
+ };
+ SVN_ERR(check_db_rows(&b, "", nodes));
+ }
+
+ /* Same again but second update is A/B rather than A which triggers
+ the problem through open_root rather than open_directory. */
+ SVN_ERR(sbox_wc_revert(&b, "", svn_depth_infinity));
+ SVN_ERR(sbox_wc_update(&b, "", 1));
+ SVN_ERR(sbox_wc_move(&b, "A", "A2"));
+ SVN_ERR(sbox_wc_update_depth(&b, "A", 2, svn_depth_empty, FALSE));
+ SVN_ERR(sbox_wc_update(&b, "A/B", 2));
+ {
+ nodes_row_t nodes[] = {
+ {0, "", "normal", 1, ""},
+ {0, "A", "normal", 2, "A"},
+ {0, "A/B", "normal", 2, "A/B"},
+ {0, "A/B/C", "normal", 2, "A/B/C"},
+ {1, "A", "base-deleted", NO_COPY_FROM, "A2"},
+ {1, "A/B", "base-deleted", NO_COPY_FROM},
+ {1, "A/B/C", "base-deleted", NO_COPY_FROM},
+ {1, "A2", "normal", 1, "A", MOVED_HERE},
+ {1, "A2/B", "normal", 1, "A/B", MOVED_HERE},
+ {0}
+ };
+ SVN_ERR(check_db_rows(&b, "", nodes));
+ }
+ SVN_ERR(sbox_wc_resolve(&b, "A", svn_depth_infinity,
+ svn_wc_conflict_choose_mine_conflict));
+ {
+ nodes_row_t nodes[] = {
+ {0, "", "normal", 1, ""},
+ {0, "A", "normal", 2, "A"},
+ {0, "A/B", "normal", 2, "A/B"},
+ {0, "A/B/C", "normal", 2, "A/B/C"},
+ {1, "A", "base-deleted", NO_COPY_FROM, "A2"},
+ {1, "A/B", "base-deleted", NO_COPY_FROM},
+ {1, "A/B/C", "base-deleted", NO_COPY_FROM},
+ {1, "A2", "normal", 2, "A", MOVED_HERE},
+ {1, "A2/B", "normal", 2, "A/B", MOVED_HERE},
+ {1, "A2/B/C", "normal", 2, "A/B/C", MOVED_HERE},
+ {0}
+ };
+ SVN_ERR(check_db_rows(&b, "", nodes));
+ }
+
+ return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+move_child_to_parent_revert(const svn_test_opts_t *opts, apr_pool_t *pool)
+{
+ svn_test__sandbox_t b;
+
+ SVN_ERR(svn_test__sandbox_create(&b, "move_child_to_parent_revert", opts,
+ pool));
+
+ SVN_ERR(sbox_wc_mkdir(&b, "A"));
+ SVN_ERR(sbox_wc_mkdir(&b, "A/B"));
+ SVN_ERR(sbox_wc_commit(&b, ""));
+
+
+ SVN_ERR(sbox_wc_move(&b, "A/B", "B"));
+ SVN_ERR(sbox_wc_delete(&b, "A"));
+
+ /* Verify that the move is still recorded correctly */
+ {
+ nodes_row_t nodes[] = {
+ {0, "", "normal", 0, ""},
+ {0, "A", "normal", 1, "A"},
+ {0, "A/B", "normal", 1, "A/B"},
+
+ {1, "A", "base-deleted", NO_COPY_FROM},
+ {1, "A/B", "base-deleted", NO_COPY_FROM, "B"},
+
+ {1, "B", "normal", 1, "A/B", MOVED_HERE},
+ {0}
+ };
+ SVN_ERR(check_db_rows(&b, "", nodes));
+ }
+
+ SVN_ERR(sbox_wc_revert(&b, "A", svn_depth_infinity));
+
+ /* Verify that the move is now just a copy */
+ {
+ nodes_row_t nodes[] = {
+ {0, "", "normal", 0, ""},
+ {0, "A", "normal", 1, "A"},
+ {0, "A/B", "normal", 1, "A/B"},
+
+ {1, "B", "normal", 1, "A/B"},
+ {0}
+ };
+ SVN_ERR(check_db_rows(&b, "", nodes));
+ }
+
+
+ return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+move_delete_intermediate(const svn_test_opts_t *opts, apr_pool_t *pool)
+{
+ svn_test__sandbox_t b;
+
+ SVN_ERR(svn_test__sandbox_create(&b, "move_delete_intermediate", opts,
+ pool));
+
+ SVN_ERR(sbox_wc_mkdir(&b, "A"));
+ SVN_ERR(sbox_wc_mkdir(&b, "A/A"));
+ SVN_ERR(sbox_wc_mkdir(&b, "A/A/A"));
+ SVN_ERR(sbox_wc_mkdir(&b, "A/A/A/A"));
+ SVN_ERR(sbox_wc_mkdir(&b, "B"));
+ SVN_ERR(sbox_wc_mkdir(&b, "B/A"));
+ SVN_ERR(sbox_wc_mkdir(&b, "B/A/A"));
+ SVN_ERR(sbox_wc_mkdir(&b, "B/A/A/A"));
+ SVN_ERR(sbox_wc_mkdir(&b, "C"));
+ SVN_ERR(sbox_wc_mkdir(&b, "C/A"));
+ SVN_ERR(sbox_wc_mkdir(&b, "C/A/A"));
+ SVN_ERR(sbox_wc_mkdir(&b, "C/A/A/A"));
+ SVN_ERR(sbox_wc_commit(&b, ""));
+
+ SVN_ERR(sbox_wc_move(&b, "A/A/A", "AAA_1"));
+
+ SVN_ERR(sbox_wc_delete(&b, "A"));
+ SVN_ERR(sbox_wc_move(&b, "B", "A"));
+
+ SVN_ERR(sbox_wc_move(&b, "A/A/A", "AAA_2"));
+
+ SVN_ERR(sbox_wc_delete(&b, "A/A"));
+ SVN_ERR(sbox_wc_move(&b, "C/A", "A/A"));
+
+ SVN_ERR(sbox_wc_move(&b, "A/A/A", "AAA_3"));
+
+ /* Verify that the move is still recorded correctly */
+ {
+ nodes_row_t nodes[] = {
+
+ {0, "", "normal", 0, ""},
+
+ {1, "AAA_1", "normal", 1, "A/A/A", MOVED_HERE},
+ {1, "AAA_1/A", "normal", 1, "A/A/A/A", MOVED_HERE},
+ {1, "AAA_2", "normal", 1, "B/A/A", MOVED_HERE},
+ {1, "AAA_2/A", "normal", 1, "B/A/A/A", MOVED_HERE},
+ {1, "AAA_3", "normal", 1, "C/A/A", MOVED_HERE},
+ {1, "AAA_3/A", "normal", 1, "C/A/A/A", MOVED_HERE},
+
+ {0, "A", "normal", 1, "A"},
+ {0, "A/A", "normal", 1, "A/A"},
+ {0, "A/A/A", "normal", 1, "A/A/A"},
+ {0, "A/A/A/A", "normal", 1, "A/A/A/A"},
+
+ {1, "A", "normal", 1, "B", MOVED_HERE},
+ {1, "A/A", "normal", 1, "B/A", MOVED_HERE},
+ {1, "A/A/A", "normal", 1, "B/A/A", FALSE, "AAA_1", TRUE},
+ {1, "A/A/A/A", "normal", 1, "B/A/A/A", MOVED_HERE},
+
+ {2, "A/A", "normal", 1, "C/A", MOVED_HERE},
+ {2, "A/A/A", "normal", 1, "C/A/A", FALSE, "AAA_2", TRUE},
+ {2, "A/A/A/A", "normal", 1, "C/A/A/A", MOVED_HERE},
+
+ {3, "A/A/A", "base-deleted", NO_COPY_FROM, "AAA_3"},
+ {3, "A/A/A/A", "base-deleted", NO_COPY_FROM},
+
+ {0, "B", "normal", 1, "B"},
+ {0, "B/A", "normal", 1, "B/A"},
+ {0, "B/A/A", "normal", 1, "B/A/A"},
+ {0, "B/A/A/A", "normal", 1, "B/A/A/A"},
+
+ {1, "B", "base-deleted", NO_COPY_FROM, "A"},
+ {1, "B/A", "base-deleted", NO_COPY_FROM},
+ {1, "B/A/A", "base-deleted", NO_COPY_FROM},
+ {1, "B/A/A/A", "base-deleted", NO_COPY_FROM},
+
+ {0, "C", "normal", 1, "C"},
+ {0, "C/A", "normal", 1, "C/A"},
+ {0, "C/A/A", "normal", 1, "C/A/A"},
+ {0, "C/A/A/A", "normal", 1, "C/A/A/A"},
+
+ {2, "C/A", "base-deleted", NO_COPY_FROM, "A/A"},
+ {2, "C/A/A", "base-deleted", NO_COPY_FROM},
+ {2, "C/A/A/A", "base-deleted", NO_COPY_FROM},
+
+ {0},
+ };
+ SVN_ERR(check_db_rows(&b, "", nodes));
+ }
+
+ /* Ok, now we are in the very ugly case where A/A/A is moved away 3 times */
+
+ /* Let's delete A */
+ SVN_ERR(sbox_wc_delete(&b, "A"));
+
+ /* AAA_1, AAA_2 and AAA_3 should still be moves after deleting A */
+ {
+ nodes_row_t nodes[] = {
+
+ {0, "", "normal", 0, ""},
+
+ {1, "AAA_1", "normal", 1, "A/A/A", MOVED_HERE},
+ {1, "AAA_1/A", "normal", 1, "A/A/A/A", MOVED_HERE},
+
+ {1, "AAA_2", "normal", 1, "B/A/A", MOVED_HERE},
+ {1, "AAA_2/A", "normal", 1, "B/A/A/A", MOVED_HERE},
+
+ {1, "AAA_3", "normal", 1, "C/A/A", MOVED_HERE},
+ {1, "AAA_3/A", "normal", 1, "C/A/A/A", MOVED_HERE},
+
+ {0, "A", "normal", 1, "A"},
+ {0, "A/A", "normal", 1, "A/A"},
+ {0, "A/A/A", "normal", 1, "A/A/A"},
+ {0, "A/A/A/A", "normal", 1, "A/A/A/A"},
+
+ {1, "A", "base-deleted", NO_COPY_FROM},
+ {1, "A/A", "base-deleted", NO_COPY_FROM},
+ {1, "A/A/A", "base-deleted", NO_COPY_FROM, "AAA_1"},
+ {1, "A/A/A/A", "base-deleted", NO_COPY_FROM},
+
+ {0, "B", "normal", 1, "B"},
+ {0, "B/A", "normal", 1, "B/A"},
+ {0, "B/A/A", "normal", 1, "B/A/A"},
+ {0, "B/A/A/A", "normal", 1, "B/A/A/A"},
+
+ {1, "B", "base-deleted", NO_COPY_FROM},
+ {1, "B/A", "base-deleted", NO_COPY_FROM},
+ {1, "B/A/A", "base-deleted", NO_COPY_FROM, "AAA_2"},
+ {1, "B/A/A/A", "base-deleted", NO_COPY_FROM},
+
+ {0, "C", "normal", 1, "C"},
+ {0, "C/A", "normal", 1, "C/A"},
+ {0, "C/A/A", "normal", 1, "C/A/A"},
+ {0, "C/A/A/A", "normal", 1, "C/A/A/A"},
+
+ {2, "C/A", "base-deleted", NO_COPY_FROM},
+ {2, "C/A/A", "base-deleted", NO_COPY_FROM, "AAA_3"},
+ {2, "C/A/A/A", "base-deleted", NO_COPY_FROM},
+
+ {0},
+ };
+ SVN_ERR(check_db_rows(&b, "", nodes));
+ }
+
+ return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+move_revert_intermediate(const svn_test_opts_t *opts, apr_pool_t *pool)
+{
+ svn_test__sandbox_t b;
+
+ SVN_ERR(svn_test__sandbox_create(&b, "move_revert_intermediate", opts,
+ pool));
+
+ SVN_ERR(sbox_wc_mkdir(&b, "A"));
+ SVN_ERR(sbox_wc_mkdir(&b, "A/A"));
+ SVN_ERR(sbox_wc_mkdir(&b, "A/A/A"));
+ SVN_ERR(sbox_wc_mkdir(&b, "A/A/A/A"));
+ SVN_ERR(sbox_wc_mkdir(&b, "B"));
+ SVN_ERR(sbox_wc_mkdir(&b, "B/A"));
+ SVN_ERR(sbox_wc_mkdir(&b, "B/A/A"));
+ SVN_ERR(sbox_wc_mkdir(&b, "B/A/A/A"));
+ SVN_ERR(sbox_wc_mkdir(&b, "C"));
+ SVN_ERR(sbox_wc_mkdir(&b, "C/A"));
+ SVN_ERR(sbox_wc_mkdir(&b, "C/A/A"));
+ SVN_ERR(sbox_wc_mkdir(&b, "C/A/A/A"));
+ SVN_ERR(sbox_wc_commit(&b, ""));
+
+ SVN_ERR(sbox_wc_move(&b, "A/A/A", "AAA_1"));
+
+ SVN_ERR(sbox_wc_delete(&b, "A"));
+ SVN_ERR(sbox_wc_move(&b, "B", "A"));
+
+ SVN_ERR(sbox_wc_move(&b, "A/A/A", "AAA_2"));
+
+ SVN_ERR(sbox_wc_delete(&b, "A/A"));
+ SVN_ERR(sbox_wc_move(&b, "C/A", "A/A"));
+
+ SVN_ERR(sbox_wc_move(&b, "A/A/A", "AAA_3"));
+
+ /* Verify that the move is still recorded correctly */
+ {
+ nodes_row_t nodes[] = {
+
+ {0, "", "normal", 0, ""},
+
+ {1, "AAA_1", "normal", 1, "A/A/A", MOVED_HERE},
+ {1, "AAA_1/A", "normal", 1, "A/A/A/A", MOVED_HERE},
+ {1, "AAA_2", "normal", 1, "B/A/A", MOVED_HERE},
+ {1, "AAA_2/A", "normal", 1, "B/A/A/A", MOVED_HERE},
+ {1, "AAA_3", "normal", 1, "C/A/A", MOVED_HERE},
+ {1, "AAA_3/A", "normal", 1, "C/A/A/A", MOVED_HERE},
+
+ {0, "A", "normal", 1, "A"},
+ {0, "A/A", "normal", 1, "A/A"},
+ {0, "A/A/A", "normal", 1, "A/A/A"},
+ {0, "A/A/A/A", "normal", 1, "A/A/A/A"},
+
+ {1, "A", "normal", 1, "B", MOVED_HERE},
+ {1, "A/A", "normal", 1, "B/A", MOVED_HERE},
+ {1, "A/A/A", "normal", 1, "B/A/A", FALSE, "AAA_1", TRUE},
+ {1, "A/A/A/A", "normal", 1, "B/A/A/A", MOVED_HERE},
+
+ {2, "A/A", "normal", 1, "C/A", MOVED_HERE},
+ {2, "A/A/A", "normal", 1, "C/A/A", FALSE, "AAA_2", TRUE},
+ {2, "A/A/A/A", "normal", 1, "C/A/A/A", MOVED_HERE},
+
+ {3, "A/A/A", "base-deleted", NO_COPY_FROM, "AAA_3"},
+ {3, "A/A/A/A", "base-deleted", NO_COPY_FROM},
+
+ {0, "B", "normal", 1, "B"},
+ {0, "B/A", "normal", 1, "B/A"},
+ {0, "B/A/A", "normal", 1, "B/A/A"},
+ {0, "B/A/A/A", "normal", 1, "B/A/A/A"},
+
+ {1, "B", "base-deleted", NO_COPY_FROM, "A"},
+ {1, "B/A", "base-deleted", NO_COPY_FROM},
+ {1, "B/A/A", "base-deleted", NO_COPY_FROM},
+ {1, "B/A/A/A", "base-deleted", NO_COPY_FROM},
+
+ {0, "C", "normal", 1, "C"},
+ {0, "C/A", "normal", 1, "C/A"},
+ {0, "C/A/A", "normal", 1, "C/A/A"},
+ {0, "C/A/A/A", "normal", 1, "C/A/A/A"},
+
+ {2, "C/A", "base-deleted", NO_COPY_FROM, "A/A"},
+ {2, "C/A/A", "base-deleted", NO_COPY_FROM},
+ {2, "C/A/A/A", "base-deleted", NO_COPY_FROM},
+
+ {0},
+ };
+ SVN_ERR(check_db_rows(&b, "", nodes));
+ }
+
+ /* Ok, now we are in the very ugly case where A/A/A is moved away 3 times */
+
+ /* Let's revert A */
+ SVN_ERR(sbox_wc_revert(&b, "A", svn_depth_infinity));
+
+ /* AAA_1 should now be a copy, but AAA_2 and AAA_3 should still be moves,
+ but now from the original location instead of from "A/A/A" */
+ {
+ nodes_row_t nodes[] = {
+
+ {0, "", "normal", 0, ""},
+
+ {1, "AAA_1", "normal", 1, "A/A/A",},
+ {1, "AAA_1/A", "normal", 1, "A/A/A/A"},
+ {1, "AAA_2", "normal", 1, "B/A/A", MOVED_HERE},
+ {1, "AAA_2/A", "normal", 1, "B/A/A/A", MOVED_HERE},
+ {1, "AAA_3", "normal", 1, "C/A/A", MOVED_HERE},
+ {1, "AAA_3/A", "normal", 1, "C/A/A/A", MOVED_HERE},
+
+ {0, "A", "normal", 1, "A"},
+ {0, "A/A", "normal", 1, "A/A"},
+ {0, "A/A/A", "normal", 1, "A/A/A"},
+ {0, "A/A/A/A", "normal", 1, "A/A/A/A"},
+
+ {0, "B", "normal", 1, "B"},
+ {0, "B/A", "normal", 1, "B/A"},
+ {0, "B/A/A", "normal", 1, "B/A/A"},
+ {0, "B/A/A/A", "normal", 1, "B/A/A/A"},
+
+ {1, "B", "base-deleted", NO_COPY_FROM},
+ {1, "B/A", "base-deleted", NO_COPY_FROM},
+ {1, "B/A/A", "base-deleted", NO_COPY_FROM, "AAA_2"},
+ {1, "B/A/A/A", "base-deleted", NO_COPY_FROM},
+
+ {0, "C", "normal", 1, "C"},
+ {0, "C/A", "normal", 1, "C/A"},
+ {0, "C/A/A", "normal", 1, "C/A/A"},
+ {0, "C/A/A/A", "normal", 1, "C/A/A/A"},
+
+ {2, "C/A", "base-deleted", NO_COPY_FROM},
+ {2, "C/A/A", "base-deleted", NO_COPY_FROM, "AAA_3"},
+ {2, "C/A/A/A", "base-deleted", NO_COPY_FROM},
+
+ {0},
+ };
+ SVN_ERR(check_db_rows(&b, "", nodes));
+ }
+
+ return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+copy_mixed_rev_mods(const svn_test_opts_t *opts, apr_pool_t *pool)
+{
+ svn_test__sandbox_t b;
+
+ SVN_ERR(svn_test__sandbox_create(&b, "copy_mixed_rev_mods", opts,
+ pool));
+
+ SVN_ERR(sbox_wc_mkdir(&b, "A"));
+ SVN_ERR(sbox_wc_mkdir(&b, "A/B"));
+ SVN_ERR(sbox_wc_commit(&b, ""));
+ SVN_ERR(sbox_wc_mkdir(&b, "A/B/C"));
+ SVN_ERR(sbox_wc_commit(&b, ""));
+ SVN_ERR(sbox_wc_update(&b, "", 1));
+ SVN_ERR(sbox_wc_update(&b, "A/B", 2));
+ SVN_ERR(sbox_wc_delete(&b, "A/B"));
+ SVN_ERR(sbox_wc_mkdir(&b, "A/B"));
+
+ {
+ nodes_row_t nodes[] = {
+ {0, "", "normal", 1, ""},
+ {0, "A", "normal", 1, "A"},
+ {0, "A/B", "normal", 2, "A/B"},
+ {0, "A/B/C", "normal", 2, "A/B/C"},
+ {2, "A/B", "normal", NO_COPY_FROM},
+ {2, "A/B/C", "base-deleted", NO_COPY_FROM},
+ {0}
+ };
+ SVN_ERR(check_db_rows(&b, "", nodes));
+ }
+
+ SVN_ERR(sbox_wc_copy(&b, "A", "X"));
+ {
+ nodes_row_t nodes[] = {
+ {1, "X", "normal", 1, "A"},
+ {1, "X/B", "not-present", 2, "A/B"},
+ {2, "X/B", "normal", NO_COPY_FROM},
+ {0}
+ };
+ SVN_ERR(check_db_rows(&b, "X", nodes));
+ }
+
+ SVN_ERR(sbox_wc_commit(&b, "X"));
+ {
+ nodes_row_t nodes[] = {
+ {0, "X", "normal", 3, "X"},
+ {0, "X/B", "normal", 3, "X/B"},
+ {0}
+ };
+ SVN_ERR(check_db_rows(&b, "X", nodes));
+ }
+
+ return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+move_replace_ancestor_with_child(const svn_test_opts_t *opts, apr_pool_t *pool)
+{
+ svn_test__sandbox_t b;
+
+ SVN_ERR(svn_test__sandbox_create(&b, "move_replace_ancestor_with_child", opts,
+ pool));
+
+ SVN_ERR(sbox_wc_mkdir(&b, "A"));
+ SVN_ERR(sbox_wc_mkdir(&b, "A/A"));
+
+ SVN_ERR(sbox_wc_commit(&b, ""));
+ SVN_ERR(sbox_wc_update(&b, "", 1));
+
+ SVN_ERR(sbox_wc_move(&b, "A", "A2"));
+
+ {
+ nodes_row_t nodes[] = {
+
+ { 0, "", "normal", 1, "" },
+
+ { 0, "A", "normal", 1, "A"},
+ { 0, "A/A", "normal", 1, "A/A" },
+
+ { 1, "A", "base-deleted", NO_COPY_FROM , "A2"},
+ { 1, "A/A", "base-deleted", NO_COPY_FROM },
+
+ { 1, "A2", "normal", 1, "A", MOVED_HERE },
+ { 1, "A2/A", "normal", 1, "A/A", MOVED_HERE },
+
+ { 0 },
+ };
+ SVN_ERR(check_db_rows(&b, "", nodes));
+ }
+
+ SVN_ERR(sbox_wc_move(&b, "A2/A", "A"));
+
+ {
+ nodes_row_t nodes[] = {
+ { 0, "", "normal", 1, "" },
+
+ { 0, "A", "normal", 1, "A"},
+ { 0, "A/A", "normal", 1, "A/A" },
+
+ { 1, "A", "normal", 1, "A/A", FALSE, "A2", TRUE },
+ { 1, "A/A", "base-deleted", NO_COPY_FROM },
+
+ { 1, "A2", "normal", 1, "A", MOVED_HERE },
+ { 1, "A2/A", "normal", 1, "A/A", MOVED_HERE },
+
+ { 2, "A2/A", "base-deleted", NO_COPY_FROM, "A" },
+ { 0 },
+ };
+ SVN_ERR(check_db_rows(&b, "", nodes));
+ }
+
+ /* ### This currently fails with an assertion in maintainer mode */
+ SVN_ERR(sbox_wc_delete(&b, "A2"));
+
+ {
+ nodes_row_t nodes[] = {
+ { 0, "", "normal", 1, "" },
+
+ { 0, "A", "normal", 1, "A"},
+ { 0, "A/A", "normal", 1, "A/A" },
+
+ { 1, "A", "normal", 1, "A/A", MOVED_HERE },
+ { 1, "A/A", "base-deleted", NO_COPY_FROM, "A" },
+
+ { 0 },
+ };
+ SVN_ERR(check_db_rows(&b, "", nodes));
+ }
+
+ SVN_ERR(sbox_wc_commit(&b, "A"));
+
+ return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+move_twice_within_delete(const svn_test_opts_t *opts, apr_pool_t *pool)
+{
+ svn_test__sandbox_t b;
+
+ SVN_ERR(svn_test__sandbox_create(&b, "move_twice_within_delete", opts,
+ pool));
+
+ SVN_ERR(sbox_wc_mkdir(&b, "A"));
+ SVN_ERR(sbox_wc_mkdir(&b, "A/A"));
+ SVN_ERR(sbox_wc_mkdir(&b, "A/A/A"));
+
+ SVN_ERR(sbox_wc_commit(&b, ""));
+ SVN_ERR(sbox_wc_update(&b, "", 1));
+
+ SVN_ERR(sbox_wc_mkdir(&b, "B"));
+ SVN_ERR(sbox_wc_move(&b, "A", "B/A"));
+ SVN_ERR(sbox_wc_move(&b, "B/A/A", "B/AA"));
+ SVN_ERR(sbox_wc_move(&b, "B/AA/A", "AA"));
+
+ {
+ nodes_row_t nodes[] = {
+
+ { 0, "", "normal", 1, "" },
+
+ { 0, "A", "normal", 1, "A" },
+ { 0, "A/A", "normal", 1, "A/A" },
+ { 0, "A/A/A", "normal", 1, "A/A/A" },
+
+ { 1, "A", "base-deleted", NO_COPY_FROM, "B/A" },
+ { 1, "A/A", "base-deleted", NO_COPY_FROM },
+ { 1, "A/A/A", "base-deleted", NO_COPY_FROM },
+
+ { 1, "AA", "normal", 1, "A/A/A", MOVED_HERE },
+
+ { 1, "B", "normal", NO_COPY_FROM },
+ { 2, "B/A", "normal", 1, "A", MOVED_HERE },
+ { 2, "B/A/A", "normal", 1, "A/A", MOVED_HERE },
+ { 2, "B/A/A/A", "normal", 1, "A/A/A", MOVED_HERE },
+
+ { 3, "B/A/A", "base-deleted", NO_COPY_FROM, "B/AA" },
+ { 3, "B/A/A/A", "base-deleted", NO_COPY_FROM },
+
+ { 2, "B/AA", "normal", 1, "A/A", MOVED_HERE},
+ { 2, "B/AA/A", "normal", 1, "A/A/A", MOVED_HERE },
+
+ { 3, "B/AA/A", "base-deleted", NO_COPY_FROM, "AA" },
+
+ { 0 },
+ };
+ SVN_ERR(check_db_rows(&b, "", nodes));
+ }
+
+ SVN_ERR(sbox_wc_delete(&b, "B"));
+
+ {
+ nodes_row_t nodes[] = {
+ { 0, "", "normal", 1, "" },
+
+ { 0, "A", "normal", 1, "A" },
+ { 0, "A/A", "normal", 1, "A/A" },
+ { 0, "A/A/A", "normal", 1, "A/A/A" },
+
+ { 1, "A", "base-deleted", NO_COPY_FROM },
+ { 1, "A/A", "base-deleted", NO_COPY_FROM },
+ { 1, "A/A/A", "base-deleted", NO_COPY_FROM, "AA" },
+
+ { 1, "AA", "normal", 1, "A/A/A", MOVED_HERE },
+
+ { 0 },
+ };
+ SVN_ERR(check_db_rows(&b, "", nodes));
+ }
+
+ return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+repo_wc_copy(const svn_test_opts_t *opts, apr_pool_t *pool)
+{
+ svn_test__sandbox_t b;
+ const char *repos_dir;
+ const char *new_repos_dir;
+ const char *new_repos_url;
+
+ SVN_ERR(svn_test__sandbox_create(&b, "repo_wc_copy",
+ opts, pool));
+ SVN_ERR(sbox_add_and_commit_greek_tree(&b));
+
+ SVN_ERR(sbox_wc_copy_url(&b,
+ svn_path_url_add_component2(b.repos_url, "A/B",
+ pool),
+ -1, "AA"));
+
+ {
+ nodes_row_t nodes[] = {
+
+ {1, "AA/lambda", "normal", 1, "A/B/lambda"},
+ {1, "AA", "normal", 1, "A/B"},
+ {1, "AA/E/beta", "normal", 1, "A/B/E/beta"},
+ {1, "AA/E/alpha", "normal", 1, "A/B/E/alpha"},
+ {1, "AA/F", "normal", 1, "A/B/F"},
+ {1, "AA/E", "normal", 1, "A/B/E"},
+
+ { 0 },
+ };
+ SVN_ERR(check_db_rows(&b, "AA", nodes));
+ }
+
+ SVN_ERR(svn_uri_get_dirent_from_file_url(&repos_dir, b.repos_url,
+ pool));
+ new_repos_dir = apr_pstrcat(pool, repos_dir, "-2", SVN_VA_NULL);
+ new_repos_url = apr_pstrcat(pool, b.repos_url, "-2", SVN_VA_NULL);
+
+ svn_test_add_dir_cleanup(new_repos_dir);
+
+ SVN_ERR(svn_io_remove_dir2(new_repos_dir, TRUE, NULL, NULL, pool));
+ SVN_ERR(svn_io_copy_dir_recursively(repos_dir,
+ svn_dirent_dirname(new_repos_dir, pool),
+ svn_dirent_basename(new_repos_dir, pool),
+ FALSE, NULL, NULL, pool));
+
+ SVN_ERR(sbox_wc_relocate(&b, new_repos_url));
+
+ /* This produced an invalid copy in Subversion <= 1.8.8.
+ Status would show all descendants as incomplete */
+ SVN_ERR(sbox_wc_copy_url(&b,
+ svn_path_url_add_component2(b.repos_url, "A/B",
+ pool),
+ -1, "BB"));
+
+ {
+ nodes_row_t nodes[] = {
+
+ {1, "BB/lambda", "normal", 1, "A/B/lambda"},
+ {1, "BB", "normal", 1, "A/B"},
+ {1, "BB/E/beta", "normal", 1, "A/B/E/beta"},
+ {1, "BB/E/alpha", "normal", 1, "A/B/E/alpha"},
+ {1, "BB/F", "normal", 1, "A/B/F"},
+ {1, "BB/E", "normal", 1, "A/B/E"},
+
+ { 0 },
+ };
+ SVN_ERR(check_db_rows(&b, "BB", nodes));
+ }
+
+ return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+movedhere_extract_retract(const svn_test_opts_t *opts, apr_pool_t *pool)
+{
+ svn_test__sandbox_t b;
+
+ SVN_ERR(svn_test__sandbox_create(&b, "movedhere_extract_retract",
+ opts, pool));
+
+ SVN_ERR(sbox_wc_mkdir(&b, "A"));
+ SVN_ERR(sbox_wc_mkdir(&b, "A/B1"));
+ SVN_ERR(sbox_wc_mkdir(&b, "A/B2"));
+ SVN_ERR(sbox_wc_mkdir(&b, "A/B3"));
+ SVN_ERR(sbox_wc_mkdir(&b, "A/C1"));
+ SVN_ERR(sbox_wc_mkdir(&b, "A/C2"));
+ SVN_ERR(sbox_wc_mkdir(&b, "A/C3"));
+ SVN_ERR(sbox_wc_mkdir(&b, "A/D1"));
+ SVN_ERR(sbox_wc_mkdir(&b, "A/D2"));
+ SVN_ERR(sbox_wc_mkdir(&b, "A/D3"));
+
+ SVN_ERR(sbox_wc_commit(&b, ""));
+
+ SVN_ERR(sbox_wc_propset(&b, "k", "v", "A/B1"));
+ SVN_ERR(sbox_wc_propset(&b, "k", "v", "A/B2"));
+ SVN_ERR(sbox_wc_propset(&b, "k", "v", "A/B3"));
+ SVN_ERR(sbox_wc_delete(&b, "A/C1"));
+ SVN_ERR(sbox_wc_delete(&b, "A/C2"));
+ SVN_ERR(sbox_wc_delete(&b, "A/C3"));
+ SVN_ERR(sbox_wc_mkdir(&b, "A/E1"));
+ SVN_ERR(sbox_wc_mkdir(&b, "A/E2"));
+ SVN_ERR(sbox_wc_mkdir(&b, "A/E3"));
+
+ SVN_ERR(sbox_wc_commit(&b, ""));
+
+ SVN_ERR(sbox_wc_update(&b, "", 1));
+
+ SVN_ERR(sbox_wc_move(&b, "A", "Z"));
+
+ SVN_ERR(sbox_wc_delete(&b, "Z/B1"));
+ SVN_ERR(sbox_wc_delete(&b, "Z/C1"));
+ SVN_ERR(sbox_wc_delete(&b, "Z/D1"));
+
+ SVN_ERR(sbox_wc_move(&b, "Z/B2", "B2"));
+ SVN_ERR(sbox_wc_move(&b, "Z/C2", "C2"));
+ SVN_ERR(sbox_wc_move(&b, "Z/D2", "D2"));
+
+ SVN_ERR(sbox_wc_mkdir(&b, "Z/B2"));
+ SVN_ERR(sbox_wc_mkdir(&b, "Z/C2"));
+ SVN_ERR(sbox_wc_mkdir(&b, "Z/D2"));
+ SVN_ERR(sbox_wc_mkdir(&b, "Z/E2"));
+
+ SVN_ERR(sbox_wc_update(&b, "", 2));
+ SVN_ERR(sbox_wc_resolve(&b, "A", svn_depth_empty,
+ svn_wc_conflict_choose_mine_conflict));
+ SVN_ERR(sbox_wc_resolve(&b, "Z/B1", svn_depth_empty,
+ svn_wc_conflict_choose_mine_conflict));
+ SVN_ERR(sbox_wc_resolve(&b, "Z/B2", svn_depth_empty,
+ svn_wc_conflict_choose_mine_conflict));
+
+ SVN_ERR(sbox_wc_resolve(&b, "Z/C1", svn_depth_empty,
+ svn_wc_conflict_choose_merged));
+ SVN_ERR(sbox_wc_resolve(&b, "Z/C2", svn_depth_empty,
+ svn_wc_conflict_choose_merged));
+
+ SVN_ERR(sbox_wc_resolve(&b, "", svn_depth_infinity,
+ svn_wc_conflict_choose_mine_conflict));
+ {
+ nodes_row_t nodes[] = {
+
+ {0, "", "normal", 2, ""},
+ {0, "A", "normal", 2, "A"},
+ {0, "A/B1", "normal", 2, "A/B1", FALSE, NULL, FALSE, "k"},
+ {0, "A/B2", "normal", 2, "A/B2", FALSE, NULL, FALSE, "k"},
+ {0, "A/B3", "normal", 2, "A/B3", FALSE, NULL, FALSE, "k"},
+ {0, "A/D1", "normal", 2, "A/D1"},
+ {0, "A/D2", "normal", 2, "A/D2"},
+ {0, "A/D3", "normal", 2, "A/D3"},
+ {0, "A/E1", "normal", 2, "A/E1"},
+ {0, "A/E2", "normal", 2, "A/E2"},
+ {0, "A/E3", "normal", 2, "A/E3"},
+
+ {1, "A", "base-deleted", NO_COPY_FROM, "Z"},
+ {1, "A/B1", "base-deleted", NO_COPY_FROM},
+ {1, "A/B2", "base-deleted", NO_COPY_FROM},
+ {1, "A/B3", "base-deleted", NO_COPY_FROM},
+
+ {1, "A/D1", "base-deleted", NO_COPY_FROM},
+ {1, "A/D2", "base-deleted", NO_COPY_FROM},
+ {1, "A/D3", "base-deleted", NO_COPY_FROM},
+
+ {1, "A/E1", "base-deleted", NO_COPY_FROM},
+ {1, "A/E2", "base-deleted", NO_COPY_FROM},
+ {1, "A/E3", "base-deleted", NO_COPY_FROM},
+
+ {1, "B2", "normal", 2, "A/B2", MOVED_HERE, "k"},
+ {1, "C2", "normal", 1, "A/C2"},
+ {1, "D2", "normal", 1, "A/D2", MOVED_HERE},
+
+ {1, "Z", "normal", 2, "A", MOVED_HERE},
+ {1, "Z/B1", "normal", 2, "A/B1", MOVED_HERE, "k"},
+ {1, "Z/B2", "normal", 2, "A/B2", MOVED_HERE, "k"},
+ {1, "Z/B3", "normal", 2, "A/B3", MOVED_HERE, "k"},
+ {1, "Z/D1", "normal", 2, "A/D1", MOVED_HERE},
+ {1, "Z/D2", "normal", 2, "A/D2", MOVED_HERE},
+ {1, "Z/D3", "normal", 2, "A/D3", MOVED_HERE},
+ {1, "Z/E1", "normal", 2, "A/E1", MOVED_HERE},
+ {1, "Z/E2", "normal", 2, "A/E2", MOVED_HERE},
+ {1, "Z/E3", "normal", 2, "A/E3", MOVED_HERE},
+
+ {2, "Z/B2", "normal", NO_COPY_FROM, "B2"},
+ {2, "Z/C2", "normal", NO_COPY_FROM},
+ {2, "Z/D2", "normal", NO_COPY_FROM, "D2"},
+ {2, "Z/E2", "normal", NO_COPY_FROM},
+
+ {2, "Z/B1", "base-deleted", NO_COPY_FROM},
+ {2, "Z/D1", "base-deleted", NO_COPY_FROM},
+
+ { 0 },
+ };
+ SVN_ERR(check_db_rows(&b, "", nodes));
+ }
+
+ return SVN_NO_ERROR;
+}
+
+
+static svn_error_t *
+nested_move_delete(const svn_test_opts_t *opts, apr_pool_t *pool)
+{
+ svn_test__sandbox_t b;
+
+ SVN_ERR(svn_test__sandbox_create(&b, "nested_move_delete", opts, pool));
+
+ SVN_ERR(sbox_add_and_commit_greek_tree(&b));
+
+ SVN_ERR(sbox_wc_mkdir(&b, "A/Z"));
+ SVN_ERR(sbox_wc_move(&b, "A/B/lambda", "A/Z/lambda"));
+
+ SVN_ERR(sbox_wc_delete(&b, "A/B"));
+
+ {
+ nodes_row_t nodes_AB[] = {
+ {0, "A/B", "normal", 1, "A/B"},
+ {2, "A/B", "base-deleted", NO_COPY_FROM},
+ {0, "A/B/E", "normal", 1, "A/B/E"},
+ {2, "A/B/E", "base-deleted", NO_COPY_FROM},
+ {0, "A/B/E/alpha", "normal", 1, "A/B/E/alpha"},
+ {2, "A/B/E/alpha", "base-deleted", NO_COPY_FROM},
+ {0, "A/B/E/beta", "normal", 1, "A/B/E/beta"},
+ {2, "A/B/E/beta", "base-deleted", NO_COPY_FROM},
+ {0, "A/B/F", "normal", 1, "A/B/F"},
+ {2, "A/B/F", "base-deleted", NO_COPY_FROM},
+ {0, "A/B/lambda", "normal", 1, "A/B/lambda"},
+ {2, "A/B/lambda", "base-deleted", NO_COPY_FROM, "A/Z/lambda"},
+ {0}
+ };
+ nodes_row_t nodes_AZ[] = {
+ {2, "A/Z", "normal", NO_COPY_FROM},
+ {3, "A/Z/lambda", "normal", 1, "A/B/lambda", MOVED_HERE },
+ {0}
+ };
+
+ SVN_ERR(check_db_rows(&b, "A/B", nodes_AB));
+ SVN_ERR(check_db_rows(&b, "A/Z", nodes_AZ));
+ }
+
+ SVN_ERR(sbox_wc_move(&b, "A", "A_moved"));
+
+ {
+ nodes_row_t nodes[] = {
+ {0, "", "normal", 0, ""},
+ {0, "A", "normal", 1, "A"},
+ {1, "A", "base-deleted", NO_COPY_FROM, "A_moved"},
+ {0, "A/B", "normal", 1, "A/B"},
+ {1, "A/B", "base-deleted", NO_COPY_FROM},
+ {0, "A/B/E", "normal", 1, "A/B/E"},
+ {1, "A/B/E", "base-deleted", NO_COPY_FROM},
+ {0, "A/B/E/alpha", "normal", 1, "A/B/E/alpha"},
+ {1, "A/B/E/alpha", "base-deleted", NO_COPY_FROM},
+ {0, "A/B/E/beta", "normal", 1, "A/B/E/beta"},
+ {1, "A/B/E/beta", "base-deleted", NO_COPY_FROM},
+ {0, "A/B/F", "normal", 1, "A/B/F"},
+ {1, "A/B/F", "base-deleted", NO_COPY_FROM},
+ {0, "A/B/lambda", "normal", 1, "A/B/lambda"},
+ {1, "A/B/lambda", "base-deleted", NO_COPY_FROM},
+ {0, "A/C", "normal", 1, "A/C"},
+ {1, "A/C", "base-deleted", NO_COPY_FROM},
+ {0, "A/D", "normal", 1, "A/D"},
+ {1, "A/D", "base-deleted", NO_COPY_FROM},
+ {0, "A/D/G", "normal", 1, "A/D/G"},
+ {1, "A/D/G", "base-deleted", NO_COPY_FROM},
+ {0, "A/D/G/pi", "normal", 1, "A/D/G/pi"},
+ {1, "A/D/G/pi", "base-deleted", NO_COPY_FROM},
+ {0, "A/D/G/rho", "normal", 1, "A/D/G/rho"},
+ {1, "A/D/G/rho", "base-deleted", NO_COPY_FROM},
+ {0, "A/D/G/tau", "normal", 1, "A/D/G/tau"},
+ {1, "A/D/G/tau", "base-deleted", NO_COPY_FROM},
+ {0, "A/D/H", "normal", 1, "A/D/H"},
+ {1, "A/D/H", "base-deleted", NO_COPY_FROM},
+ {0, "A/D/H/chi", "normal", 1, "A/D/H/chi"},
+ {1, "A/D/H/chi", "base-deleted", NO_COPY_FROM},
+ {0, "A/D/H/omega", "normal", 1, "A/D/H/omega"},
+ {1, "A/D/H/omega", "base-deleted", NO_COPY_FROM},
+ {0, "A/D/H/psi", "normal", 1, "A/D/H/psi"},
+ {1, "A/D/H/psi", "base-deleted", NO_COPY_FROM},
+ {0, "A/D/gamma", "normal", 1, "A/D/gamma"},
+ {1, "A/D/gamma", "base-deleted", NO_COPY_FROM},
+ {0, "A/mu", "normal", 1, "A/mu"},
+ {1, "A/mu", "base-deleted", NO_COPY_FROM},
+ {1, "A_moved", "normal", 1, "A", MOVED_HERE},
+ {1, "A_moved/B", "normal", 1, "A/B", MOVED_HERE},
+ {2, "A_moved/B", "base-deleted", NO_COPY_FROM},
+ {2, "A_moved/B/E", "base-deleted", NO_COPY_FROM},
+ {1, "A_moved/B/E", "normal", 1, "A/B/E", MOVED_HERE},
+ {1, "A_moved/B/E/alpha", "normal", 1, "A/B/E/alpha", MOVED_HERE},
+ {2, "A_moved/B/E/alpha", "base-deleted", NO_COPY_FROM},
+ {1, "A_moved/B/E/beta", "normal", 1, "A/B/E/beta", MOVED_HERE},
+ {2, "A_moved/B/E/beta", "base-deleted", NO_COPY_FROM},
+ {1, "A_moved/B/F", "normal", 1, "A/B/F", MOVED_HERE},
+ {2, "A_moved/B/F", "base-deleted", NO_COPY_FROM},
+ {1, "A_moved/B/lambda", "normal", 1, "A/B/lambda", MOVED_HERE},
+ {2, "A_moved/B/lambda", "base-deleted", NO_COPY_FROM, "A_moved/Z/lambda"},
+ {1, "A_moved/C", "normal", 1, "A/C", MOVED_HERE},
+ {1, "A_moved/D", "normal", 1, "A/D", MOVED_HERE},
+ {1, "A_moved/D/G", "normal", 1, "A/D/G", MOVED_HERE},
+ {1, "A_moved/D/G/pi", "normal", 1, "A/D/G/pi", MOVED_HERE},
+ {1, "A_moved/D/G/rho", "normal", 1, "A/D/G/rho", MOVED_HERE},
+ {1, "A_moved/D/G/tau", "normal", 1, "A/D/G/tau", MOVED_HERE},
+ {1, "A_moved/D/H", "normal", 1, "A/D/H", MOVED_HERE},
+ {1, "A_moved/D/H/chi", "normal", 1, "A/D/H/chi", MOVED_HERE},
+ {1, "A_moved/D/H/omega", "normal", 1, "A/D/H/omega", MOVED_HERE},
+ {1, "A_moved/D/H/psi", "normal", 1, "A/D/H/psi", MOVED_HERE},
+ {1, "A_moved/D/gamma", "normal", 1, "A/D/gamma", MOVED_HERE},
+ {2, "A_moved/Z", "normal", NO_COPY_FROM},
+ {3, "A_moved/Z/lambda", "normal", 1, "A/B/lambda", MOVED_HERE},
+ {1, "A_moved/mu", "normal", 1, "A/mu", MOVED_HERE},
+ {0, "iota", "normal", 1, "iota"},
+
+ {0}
+ };
+
+ SVN_ERR(check_db_rows(&b, "", nodes));
+ }
+
+ return SVN_NO_ERROR;
+}
+
/* ---------------------------------------------------------------------- */
/* The list of test functions */
@@ -3606,7 +9081,116 @@ struct svn_test_descriptor_t test_funcs[] =
#endif
SVN_TEST_OPTS_PASS(commit_file_external,
"commit_file_external (issue #4002)"),
+ SVN_TEST_OPTS_PASS(revert_file_externals,
+ "revert_file_externals"),
+ SVN_TEST_OPTS_PASS(copy_file_externals,
+ "copy_file_externals"),
+ SVN_TEST_OPTS_PASS(copy_wc_wc_server_excluded,
+ "test_wc_wc_copy_server_excluded"),
SVN_TEST_OPTS_PASS(incomplete_switch,
"incomplete_switch (issue 4040)"),
+ SVN_TEST_OPTS_PASS(nested_moves_child_first,
+ "nested_moves_child_first"),
+ SVN_TEST_OPTS_PASS(nested_moves_child_last,
+ "nested_moves_child_last"),
+ SVN_TEST_OPTS_PASS(move_in_copy,
+ "move_in_copy"),
+ SVN_TEST_OPTS_PASS(move_in_replace,
+ "move_in_replace"),
+ SVN_TEST_OPTS_PASS(copy_a_move,
+ "copy_a_move"),
+ SVN_TEST_OPTS_PASS(move_to_swap,
+ "move_to_swap"),
+ SVN_TEST_OPTS_PASS(revert_nested_move,
+ "revert_nested_move"),
+ SVN_TEST_OPTS_PASS(move_on_move,
+ "move_on_move"),
+ SVN_TEST_OPTS_PASS(move_on_move2,
+ "move_on_move2"),
+ SVN_TEST_OPTS_PASS(move_added,
+ "move_added"),
+ SVN_TEST_OPTS_PASS(move_update,
+ "move_update"),
+ SVN_TEST_OPTS_PASS(test_scan_delete,
+ "scan_delete"),
+ SVN_TEST_OPTS_PASS(test_follow_moved_to,
+ "follow_moved_to"),
+ SVN_TEST_OPTS_WIMP(mixed_rev_move,
+ "mixed_rev_move",
+ "needs different libsvn_wc entry point"),
+ SVN_TEST_OPTS_PASS(update_prop_mod_into_moved,
+ "update_prop_mod_into_moved"),
+ SVN_TEST_OPTS_PASS(nested_move_update,
+ "nested_move_update"),
+ SVN_TEST_OPTS_PASS(nested_move_commit,
+ "nested_move_commit (issue 4291)"),
+ SVN_TEST_OPTS_PASS(nested_move_update2,
+ "nested_move_update2"),
+ SVN_TEST_OPTS_PASS(move_update_conflicts,
+ "move_update_conflicts"),
+ SVN_TEST_OPTS_PASS(move_update_delete_mods,
+ "move_update_delete_mods"),
+ SVN_TEST_OPTS_PASS(nested_moves2,
+ "nested_moves2"),
+ SVN_TEST_OPTS_PASS(move_in_delete,
+ "move_in_delete (issue 4303)"),
+ SVN_TEST_OPTS_PASS(switch_move,
+ "switch_move"),
+ SVN_TEST_OPTS_PASS(move_replace,
+ "move_replace"),
+ SVN_TEST_OPTS_PASS(layered_moved_to,
+ "layered_moved_to"),
+ SVN_TEST_OPTS_PASS(update_within_move,
+ "update_within_move"),
+ SVN_TEST_OPTS_PASS(commit_moved_descendant,
+ "commit_moved_descendant"),
+ SVN_TEST_OPTS_XFAIL(commit_moved_away_descendant,
+ "commit_moved_away_descendant"),
+ SVN_TEST_OPTS_PASS(finite_move_update_bump,
+ "finite_move_update_bump"),
+ SVN_TEST_OPTS_PASS(move_away_delete_update,
+ "move_away_delete_update"),
+ SVN_TEST_OPTS_PASS(move_not_present_variants,
+ "move_not_present_variants"),
+ SVN_TEST_OPTS_PASS(update_child_under_add,
+ "update_child_under_add (issue 4111)"),
+ SVN_TEST_OPTS_PASS(delete_over_moved_away,
+ "delete_over_moved_away"),
+ SVN_TEST_OPTS_PASS(movedto_opdepth,
+ "moved_to op_depth"),
+ SVN_TEST_OPTS_PASS(new_basemove,
+ "new_basemove"),
+ SVN_TEST_OPTS_PASS(move_back,
+ "move_back (issue 4302)"),
+ SVN_TEST_OPTS_PASS(move_update_subtree,
+ "move_update_subtree (issue 4232)"),
+ SVN_TEST_OPTS_PASS(move_parent_into_child,
+ "move_parent_into_child (issue 4333)"),
+ SVN_TEST_OPTS_PASS(move_depth_expand,
+ "move depth expansion"),
+ SVN_TEST_OPTS_PASS(move_retract,
+ "move retract (issue 4336)"),
+ SVN_TEST_OPTS_PASS(move_delete_file_externals,
+ "move/delete file externals (issue 4293)"),
+ SVN_TEST_OPTS_PASS(update_with_tree_conflict,
+ "update with tree conflict (issue 4347)"),
+ SVN_TEST_OPTS_PASS(move_child_to_parent_revert,
+ "move child to parent and revert (issue 4436)"),
+ SVN_TEST_OPTS_PASS(move_delete_intermediate,
+ "move more than once, delete intermediate"),
+ SVN_TEST_OPTS_XFAIL(move_revert_intermediate,
+ "move more than once, revert intermediate"),
+ SVN_TEST_OPTS_PASS(move_replace_ancestor_with_child,
+ "move replace ancestor with child"),
+ SVN_TEST_OPTS_PASS(move_twice_within_delete,
+ "move twice and then delete"),
+ SVN_TEST_OPTS_PASS(repo_wc_copy,
+ "repo_wc_copy"),
+ SVN_TEST_OPTS_PASS(copy_mixed_rev_mods,
+ "copy mixed-rev with mods"),
+ SVN_TEST_OPTS_PASS(movedhere_extract_retract,
+ "movedhere extract retract"),
+ SVN_TEST_OPTS_PASS(nested_move_delete,
+ "nested move delete"),
SVN_TEST_NULL
};
diff --git a/subversion/tests/libsvn_wc/pristine-store-test.c b/subversion/tests/libsvn_wc/pristine-store-test.c
index 4227026..6df96fc 100644
--- a/subversion/tests/libsvn_wc/pristine-store-test.c
+++ b/subversion/tests/libsvn_wc/pristine-store-test.c
@@ -187,8 +187,7 @@ pristine_write_read(const svn_test_opts_t *opts,
SVN_ERR(svn_wc__db_pristine_remove(db, wc_abspath, data_sha1, pool));
err = svn_wc__db_pristine_read(&data_read_back, NULL, db, wc_abspath,
data_sha1, pool, pool);
- SVN_TEST_ASSERT(err != NULL);
- svn_error_clear(err);
+ SVN_TEST_ASSERT_ERROR(err, SVN_ERR_WC_PATH_NOT_FOUND);
}
/* Ensure it's no longer found in the store. */
@@ -308,9 +307,7 @@ reject_mismatching_text(const svn_test_opts_t *opts,
SVN_ERR(write_and_checksum_temp_file(&path, NULL, NULL,
data2, pristine_tmp_dir, pool));
err = svn_wc__db_pristine_install(db, path, data_sha1, data_md5, pool);
- SVN_TEST_ASSERT(err != NULL);
- SVN_TEST_ASSERT(err->apr_err == SVN_ERR_WC_CORRUPT_TEXT_BASE);
- svn_error_clear(err);
+ SVN_TEST_ASSERT_ERROR(err, SVN_ERR_WC_CORRUPT_TEXT_BASE);
}
return SVN_NO_ERROR;
diff --git a/subversion/tests/libsvn_wc/tree-conflict-data-test.c b/subversion/tests/libsvn_wc/tree-conflict-data-test.c
deleted file mode 100644
index 40d42ac..0000000
--- a/subversion/tests/libsvn_wc/tree-conflict-data-test.c
+++ /dev/null
@@ -1,307 +0,0 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-
-/*
- * tree-conflict-data-test.c -- test the storage of tree conflict data
- */
-
-#include <stdio.h>
-#include <string.h>
-#include <apr_hash.h>
-#include <apr_tables.h>
-
-#include "svn_pools.h"
-#include "svn_hash.h"
-#include "svn_types.h"
-#include "svn_wc.h"
-#include "private/svn_wc_private.h"
-#include "utils.h"
-#include "../svn_test.h"
-#include "../../libsvn_wc/tree_conflicts.h"
-#include "../../libsvn_wc/wc.h"
-#include "../../libsvn_wc/wc_db.h"
-
-/* A quick way to create error messages. */
-static svn_error_t *
-fail(apr_pool_t *pool, const char *fmt, ...)
-{
- va_list ap;
- char *msg;
-
- va_start(ap, fmt);
- msg = apr_pvsprintf(pool, fmt, ap);
- va_end(ap);
-
- return svn_error_create(SVN_ERR_TEST_FAILED, 0, msg);
-}
-
-/* Raise a test error if EXPECTED and ACTUAL differ. */
-static svn_error_t *
-compare_version(const svn_wc_conflict_version_t *expected,
- const svn_wc_conflict_version_t *actual)
-{
- SVN_TEST_STRING_ASSERT(expected->repos_url, actual->repos_url);
- SVN_TEST_ASSERT(expected->peg_rev == actual->peg_rev);
- SVN_TEST_STRING_ASSERT(expected->path_in_repos, actual->path_in_repos);
- SVN_TEST_ASSERT(expected->node_kind == actual->node_kind);
- return SVN_NO_ERROR;
-}
-
-/* Raise a test error if EXPECTED and ACTUAL differ or if ACTUAL is NULL. */
-static svn_error_t *
-compare_conflict(const svn_wc_conflict_description2_t *expected,
- const svn_wc_conflict_description2_t *actual)
-{
- SVN_TEST_ASSERT(actual != NULL);
-
- SVN_TEST_STRING_ASSERT(expected->local_abspath, actual->local_abspath);
- SVN_TEST_ASSERT(expected->node_kind == actual->node_kind);
- SVN_TEST_ASSERT(expected->kind == actual->kind);
- SVN_TEST_STRING_ASSERT(expected->property_name, actual->property_name);
- SVN_TEST_ASSERT(expected->is_binary == actual->is_binary);
- SVN_TEST_STRING_ASSERT(expected->mime_type, actual->mime_type);
- SVN_TEST_ASSERT(expected->action == actual->action);
- SVN_TEST_ASSERT(expected->reason == actual->reason);
- SVN_TEST_STRING_ASSERT(expected->base_abspath, actual->base_abspath);
- SVN_TEST_STRING_ASSERT(expected->their_abspath, actual->their_abspath);
- SVN_TEST_STRING_ASSERT(expected->my_abspath, actual->my_abspath);
- SVN_TEST_STRING_ASSERT(expected->merged_file, actual->merged_file);
- SVN_TEST_ASSERT(expected->operation == actual->operation);
- compare_version(expected->src_left_version, actual->src_left_version);
- compare_version(expected->src_right_version, actual->src_right_version);
- return SVN_NO_ERROR;
-}
-
-/* Create and return a tree conflict description */
-static svn_wc_conflict_description2_t *
-tree_conflict_create(const char *local_abspath,
- svn_node_kind_t node_kind,
- svn_wc_operation_t operation,
- svn_wc_conflict_action_t action,
- svn_wc_conflict_reason_t reason,
- const char *left_repo,
- const char *left_path,
- svn_revnum_t left_revnum,
- svn_node_kind_t left_kind,
- const char *right_repo,
- const char *right_path,
- svn_revnum_t right_revnum,
- svn_node_kind_t right_kind,
- apr_pool_t *result_pool)
-{
- svn_wc_conflict_version_t *left, *right;
- svn_wc_conflict_description2_t *conflict;
-
- left = svn_wc_conflict_version_create(left_repo, left_path, left_revnum,
- left_kind, result_pool);
- right = svn_wc_conflict_version_create(right_repo, right_path, right_revnum,
- right_kind, result_pool);
- conflict = svn_wc_conflict_description_create_tree2(
- local_abspath, node_kind, operation,
- left, right, result_pool);
- conflict->action = action;
- conflict->reason = reason;
- return conflict;
-}
-
-static svn_error_t *
-test_deserialize_tree_conflict(apr_pool_t *pool)
-{
- const svn_wc_conflict_description2_t *conflict;
- svn_wc_conflict_description2_t *exp_conflict;
- const char *tree_conflict_data;
- const char *local_abspath;
- const svn_skel_t *skel;
-
- tree_conflict_data = "(conflict Foo.c file update deleted edited "
- "(version 0 2 -1 0 0 ) (version 0 2 -1 0 0 ))";
-
- SVN_ERR(svn_dirent_get_absolute(&local_abspath, "Foo.c", pool));
- exp_conflict = svn_wc_conflict_description_create_tree2(
- local_abspath, svn_node_file, svn_wc_operation_update,
- NULL, NULL, pool);
- exp_conflict->action = svn_wc_conflict_action_delete;
- exp_conflict->reason = svn_wc_conflict_reason_edited;
-
- skel = svn_skel__parse(tree_conflict_data, strlen(tree_conflict_data), pool);
- SVN_ERR(svn_wc__deserialize_conflict(&conflict, skel, "", pool, pool));
-
- if ((conflict->node_kind != exp_conflict->node_kind) ||
- (conflict->action != exp_conflict->action) ||
- (conflict->reason != exp_conflict->reason) ||
- (conflict->operation != exp_conflict->operation) ||
- (strcmp(conflict->local_abspath, exp_conflict->local_abspath) != 0))
- return fail(pool, "Unexpected tree conflict");
-
- return SVN_NO_ERROR;
-}
-
-static svn_error_t *
-test_serialize_tree_conflict(apr_pool_t *pool)
-{
- svn_wc_conflict_description2_t *conflict;
- const char *tree_conflict_data;
- const char *expected;
- const char *local_abspath;
- svn_skel_t *skel;
-
- SVN_ERR(svn_dirent_get_absolute(&local_abspath, "Foo.c", pool));
-
- conflict = svn_wc_conflict_description_create_tree2(
- local_abspath, svn_node_file, svn_wc_operation_update,
- NULL, NULL, pool);
- conflict->action = svn_wc_conflict_action_delete;
- conflict->reason = svn_wc_conflict_reason_edited;
-
- SVN_ERR(svn_wc__serialize_conflict(&skel, conflict, pool, pool));
- tree_conflict_data = svn_skel__unparse(skel, pool)->data;
-
- expected = "(conflict Foo.c file update deleted edited "
- "(version 0 2 -1 0 0 ) (version 0 2 -1 0 0 ))";
-
- if (strcmp(expected, tree_conflict_data) != 0)
- return fail(pool, "Unexpected text from tree conflict\n"
- " Expected: %s\n"
- " Actual: %s\n", expected, tree_conflict_data);
-
- return SVN_NO_ERROR;
-}
-
-/* Test WC-DB-level conflict APIs. Especially tree conflicts. */
-static svn_error_t *
-test_read_write_tree_conflicts(const svn_test_opts_t *opts,
- apr_pool_t *pool)
-{
- svn_test__sandbox_t sbox;
-
- const char *parent_abspath;
- const char *child1_abspath, *child2_abspath;
- svn_wc_conflict_description2_t *conflict1, *conflict2;
-
- SVN_ERR(svn_test__sandbox_create(&sbox, "read_write_tree_conflicts", opts, pool));
- parent_abspath = svn_dirent_join(sbox.wc_abspath, "A", pool);
- SVN_ERR(svn_wc__db_op_add_directory(sbox.wc_ctx->db, parent_abspath, NULL,
- pool));
- child1_abspath = svn_dirent_join(parent_abspath, "foo", pool);
- child2_abspath = svn_dirent_join(parent_abspath, "bar", pool);
-
- conflict1 = tree_conflict_create(child1_abspath, svn_node_file,
- svn_wc_operation_update,
- svn_wc_conflict_action_delete,
- svn_wc_conflict_reason_edited,
- "dummy://localhost", "path/to/foo",
- 51, svn_node_file,
- "dummy://localhost", "path/to/foo",
- 52, svn_node_none,
- pool);
-
- conflict2 = tree_conflict_create(child2_abspath, svn_node_dir,
- svn_wc_operation_merge,
- svn_wc_conflict_action_replace,
- svn_wc_conflict_reason_edited,
- "dummy://localhost", "path/to/bar",
- 51, svn_node_dir,
- "dummy://localhost", "path/to/bar",
- 52, svn_node_file,
- pool);
-
- /* Write (conflict1 through WC-DB API, conflict2 through WC API) */
- SVN_ERR(svn_wc__db_op_set_tree_conflict(sbox.wc_ctx->db, child1_abspath,
- conflict1, pool));
- SVN_ERR(svn_wc__add_tree_conflict(sbox.wc_ctx, /*child2_abspath,*/
- conflict2, pool));
-
- /* Query (conflict1 through WC-DB API, conflict2 through WC API) */
- {
- svn_boolean_t text_c, prop_c, tree_c;
-
- SVN_ERR(svn_wc__internal_conflicted_p(&text_c, &prop_c, &tree_c,
- sbox.wc_ctx->db, child1_abspath, pool));
- SVN_TEST_ASSERT(tree_c);
- SVN_TEST_ASSERT(! text_c && ! prop_c);
-
- SVN_ERR(svn_wc_conflicted_p3(&text_c, &prop_c, &tree_c,
- sbox.wc_ctx, child2_abspath, pool));
- SVN_TEST_ASSERT(tree_c);
- SVN_TEST_ASSERT(! text_c && ! prop_c);
- }
-
- /* Read one (conflict1 through WC-DB API, conflict2 through WC API) */
- {
- const svn_wc_conflict_description2_t *read_conflict;
-
- SVN_ERR(svn_wc__db_op_read_tree_conflict(&read_conflict, sbox.wc_ctx->db,
- child1_abspath, pool, pool));
- SVN_ERR(compare_conflict(conflict1, read_conflict));
-
- SVN_ERR(svn_wc__get_tree_conflict(&read_conflict, sbox.wc_ctx,
- child2_abspath, pool, pool));
- SVN_ERR(compare_conflict(conflict2, read_conflict));
- }
-
- /* Read many (both through WC-DB API, both through WC API) */
- {
- apr_hash_t *all_conflicts;
- const svn_wc_conflict_description2_t *read_conflict;
-
- SVN_ERR(svn_wc__db_op_read_all_tree_conflicts(
- &all_conflicts, sbox.wc_ctx->db, parent_abspath, pool, pool));
- SVN_TEST_ASSERT(apr_hash_count(all_conflicts) == 2);
- read_conflict = apr_hash_get(all_conflicts, "foo", APR_HASH_KEY_STRING);
- SVN_ERR(compare_conflict(conflict1, read_conflict));
- read_conflict = apr_hash_get(all_conflicts, "bar", APR_HASH_KEY_STRING);
- SVN_ERR(compare_conflict(conflict2, read_conflict));
-
- SVN_ERR(svn_wc__get_all_tree_conflicts(
- &all_conflicts, sbox.wc_ctx, parent_abspath, pool, pool));
- SVN_TEST_ASSERT(apr_hash_count(all_conflicts) == 2);
- read_conflict = apr_hash_get(all_conflicts, child1_abspath,
- APR_HASH_KEY_STRING);
- SVN_ERR(compare_conflict(conflict1, read_conflict));
- read_conflict = apr_hash_get(all_conflicts, child2_abspath,
- APR_HASH_KEY_STRING);
- SVN_ERR(compare_conflict(conflict2, read_conflict));
- }
-
- /* ### TODO: to test...
- * svn_wc__db_read_conflict_victims
- * svn_wc__db_read_conflicts
- * svn_wc__node_get_conflict_info
- * svn_wc__del_tree_conflict
- */
-
- return SVN_NO_ERROR;
-}
-
-/* The test table. */
-
-struct svn_test_descriptor_t test_funcs[] =
- {
- SVN_TEST_NULL,
- SVN_TEST_PASS2(test_deserialize_tree_conflict,
- "deserialize tree conflict"),
- SVN_TEST_PASS2(test_serialize_tree_conflict,
- "serialize tree conflict"),
- SVN_TEST_OPTS_PASS(test_read_write_tree_conflicts,
- "read and write tree conflicts"),
- SVN_TEST_NULL
- };
-
diff --git a/subversion/tests/libsvn_wc/utils.c b/subversion/tests/libsvn_wc/utils.c
index 49d3303..1682b98 100644
--- a/subversion/tests/libsvn_wc/utils.c
+++ b/subversion/tests/libsvn_wc/utils.c
@@ -23,6 +23,7 @@
#include "svn_error.h"
#include "svn_client.h"
#include "svn_pools.h"
+#include "private/svn_dep_compat.h"
#include "utils.h"
@@ -81,17 +82,18 @@ create_repos_and_wc(const char **repos_url,
/* Create a WC. Set *WC_ABSPATH to its path. */
{
+ apr_pool_t *subpool = svn_pool_create(pool); /* To cleanup CTX */
svn_client_ctx_t *ctx;
svn_opt_revision_t head_rev = { svn_opt_revision_head, {0} };
- SVN_ERR(svn_client_create_context(&ctx, pool));
- /* SVN_ERR(svn_config_get_config(&ctx->config, config_dir, pool)); */
+ SVN_ERR(svn_client_create_context2(&ctx, NULL, subpool));
SVN_ERR(svn_dirent_get_absolute(wc_abspath, wc_path, pool));
SVN_ERR(svn_client_checkout3(NULL, *repos_url, *wc_abspath,
&head_rev, &head_rev, svn_depth_infinity,
FALSE /* ignore_externals */,
FALSE /* allow_unver_obstructions */,
- ctx, pool));
+ ctx, subpool));
+ svn_pool_destroy(subpool);
}
/* Register this WC for cleanup. */
@@ -132,7 +134,8 @@ svn_test__create_fake_wc(const char *wc_abspath,
svn_error_clear(svn_io_remove_file2(db_abspath, FALSE, scratch_pool));
SVN_ERR(svn_wc__db_util_open_db(&sdb, wc_abspath, "wc.db",
- svn_sqlite__mode_rwcreate, my_statements,
+ svn_sqlite__mode_rwcreate,
+ FALSE /* exclusive */, my_statements,
result_pool, scratch_pool));
for (i = 0; my_statements[i] != NULL; i++)
SVN_ERR(svn_sqlite__exec_statements(sdb, /* my_statements[] */ i));
@@ -153,3 +156,377 @@ svn_test__sandbox_create(svn_test__sandbox_t *sandbox,
SVN_ERR(svn_wc_context_create(&sandbox->wc_ctx, NULL, pool, pool));
return SVN_NO_ERROR;
}
+
+void
+sbox_file_write(svn_test__sandbox_t *b, const char *path, const char *text)
+{
+ FILE *f = fopen(sbox_wc_path(b, path), "w");
+
+ fputs(text, f);
+ fclose(f);
+}
+
+svn_error_t *
+sbox_wc_add(svn_test__sandbox_t *b, const char *path)
+{
+ const char *parent_abspath;
+
+ path = sbox_wc_path(b, path);
+ parent_abspath = svn_dirent_dirname(path, b->pool);
+ SVN_ERR(svn_wc__acquire_write_lock(NULL, b->wc_ctx, parent_abspath, FALSE,
+ b->pool, b->pool));
+ SVN_ERR(svn_wc_add_from_disk2(b->wc_ctx, path, NULL /*props*/,
+ NULL, NULL, b->pool));
+ SVN_ERR(svn_wc__release_write_lock(b->wc_ctx, parent_abspath, b->pool));
+ return SVN_NO_ERROR;
+}
+
+svn_error_t *
+sbox_disk_mkdir(svn_test__sandbox_t *b, const char *path)
+{
+ path = sbox_wc_path(b, path);
+ SVN_ERR(svn_io_dir_make(path, APR_FPROT_OS_DEFAULT, b->pool));
+ return SVN_NO_ERROR;
+}
+
+svn_error_t *
+sbox_wc_mkdir(svn_test__sandbox_t *b, const char *path)
+{
+ SVN_ERR(sbox_disk_mkdir(b, path));
+ SVN_ERR(sbox_wc_add(b, path));
+ return SVN_NO_ERROR;
+}
+
+#if 0 /* not used */
+/* Copy the file or directory tree FROM_PATH to TO_PATH which must not exist
+ * beforehand. */
+svn_error_t *
+sbox_disk_copy(svn_test__sandbox_t *b, const char *from_path, const char *to_path)
+{
+ const char *to_dir, *to_name;
+
+ from_path = sbox_wc_path(b, from_path);
+ to_path = sbox_wc_path(b, to_path);
+ svn_dirent_split(&to_dir, &to_name, to_path, b->pool);
+ return svn_io_copy_dir_recursively(from_path, to_dir, to_name,
+ FALSE, NULL, NULL, b->pool);
+}
+#endif
+
+svn_error_t *
+sbox_wc_copy(svn_test__sandbox_t *b, const char *from_path, const char *to_path)
+{
+ const char *parent_abspath;
+
+ from_path = sbox_wc_path(b, from_path);
+ to_path = sbox_wc_path(b, to_path);
+ parent_abspath = svn_dirent_dirname(to_path, b->pool);
+ SVN_ERR(svn_wc__acquire_write_lock(NULL, b->wc_ctx, parent_abspath, FALSE,
+ b->pool, b->pool));
+ SVN_ERR(svn_wc_copy3(b->wc_ctx, from_path, to_path, FALSE,
+ NULL, NULL, NULL, NULL, b->pool));
+ SVN_ERR(svn_wc__release_write_lock(b->wc_ctx, parent_abspath, b->pool));
+ return SVN_NO_ERROR;
+}
+
+svn_error_t *
+sbox_wc_copy_url(svn_test__sandbox_t *b, const char *from_url,
+ svn_revnum_t revision, const char *to_path)
+{
+ apr_pool_t *scratch_pool = b->pool;
+ svn_client_ctx_t *ctx;
+ svn_opt_revision_t rev = { svn_opt_revision_unspecified, {0} };
+ svn_client_copy_source_t* src;
+ apr_array_header_t *sources = apr_array_make(
+ scratch_pool, 1,
+ sizeof(svn_client_copy_source_t *));
+
+ SVN_ERR(svn_client_create_context2(&ctx, NULL, scratch_pool));
+ ctx->wc_ctx = b->wc_ctx;
+
+ if (SVN_IS_VALID_REVNUM(revision))
+ {
+ rev.kind = svn_opt_revision_number;
+ rev.value.number = revision;
+ }
+
+ src = apr_pcalloc(scratch_pool, sizeof(*src));
+
+ src->path = from_url;
+ src->revision = &rev;
+ src->peg_revision = &rev;
+
+ APR_ARRAY_PUSH(sources, svn_client_copy_source_t *) = src;
+
+ SVN_ERR(svn_client_copy6(sources, sbox_wc_path(b, to_path),
+ FALSE, FALSE, FALSE, NULL, NULL, NULL,
+ ctx, scratch_pool));
+
+ ctx->wc_ctx = NULL;
+
+ return SVN_NO_ERROR;
+}
+
+
+svn_error_t *
+sbox_wc_revert(svn_test__sandbox_t *b, const char *path, svn_depth_t depth)
+{
+ const char *abspath = sbox_wc_path(b, path);
+ const char *dir_abspath;
+ const char *lock_root_abspath;
+
+ if (strcmp(abspath, b->wc_abspath))
+ dir_abspath = svn_dirent_dirname(abspath, b->pool);
+ else
+ dir_abspath = abspath;
+
+ SVN_ERR(svn_wc__acquire_write_lock(&lock_root_abspath, b->wc_ctx,
+ dir_abspath, FALSE /* lock_anchor */,
+ b->pool, b->pool));
+ SVN_ERR(svn_wc_revert4(b->wc_ctx, abspath, depth, FALSE, NULL,
+ NULL, NULL, /* cancel baton + func */
+ NULL, NULL, /* notify baton + func */
+ b->pool));
+ SVN_ERR(svn_wc__release_write_lock(b->wc_ctx, lock_root_abspath, b->pool));
+ return SVN_NO_ERROR;
+}
+
+svn_error_t *
+sbox_wc_delete(svn_test__sandbox_t *b, const char *path)
+{
+ const char *abspath = sbox_wc_path(b, path);
+ const char *dir_abspath = svn_dirent_dirname(abspath, b->pool);
+ const char *lock_root_abspath;
+
+ SVN_ERR(svn_wc__acquire_write_lock(&lock_root_abspath, b->wc_ctx,
+ dir_abspath, FALSE,
+ b->pool, b->pool));
+ SVN_ERR(svn_wc_delete4(b->wc_ctx, abspath, FALSE, TRUE,
+ NULL, NULL, /* cancel baton + func */
+ NULL, NULL, /* notify baton + func */
+ b->pool));
+ SVN_ERR(svn_wc__release_write_lock(b->wc_ctx, lock_root_abspath, b->pool));
+ return SVN_NO_ERROR;
+}
+
+svn_error_t *
+sbox_wc_exclude(svn_test__sandbox_t *b, const char *path)
+{
+ const char *abspath = sbox_wc_path(b, path);
+ const char *lock_root_abspath;
+
+ SVN_ERR(svn_wc__acquire_write_lock(&lock_root_abspath, b->wc_ctx,
+ abspath, TRUE,
+ b->pool, b->pool));
+ SVN_ERR(svn_wc_exclude(b->wc_ctx, abspath,
+ NULL, NULL, /* cancel baton + func */
+ NULL, NULL, /* notify baton + func */
+ b->pool));
+ SVN_ERR(svn_wc__release_write_lock(b->wc_ctx, lock_root_abspath, b->pool));
+ return SVN_NO_ERROR;
+}
+
+svn_error_t *
+sbox_wc_commit_ex(svn_test__sandbox_t *b,
+ apr_array_header_t *targets,
+ svn_depth_t depth)
+{
+ svn_client_ctx_t *ctx;
+ apr_pool_t *scratch_pool = svn_pool_create(b->pool);
+ svn_error_t *err;
+
+ SVN_ERR(svn_client_create_context2(&ctx, NULL, scratch_pool));
+ ctx->wc_ctx = b->wc_ctx;
+
+ /* A successfull commit doesn't close the ra session, but leaves that
+ to the caller. This leaves the BDB handle open, which might cause
+ problems in further test code. (op_depth_tests.c's repo_wc_copy) */
+ err = svn_client_commit6(targets, depth,
+ FALSE /* keep_locks */,
+ FALSE /* keep_changelist */,
+ TRUE /* commit_as_operations */,
+ TRUE /* include_file_externals */,
+ FALSE /* include_dir_externals */,
+ NULL, NULL, NULL, NULL, ctx, scratch_pool);
+
+ svn_pool_destroy(scratch_pool);
+
+ return svn_error_trace(err);
+}
+
+svn_error_t *
+sbox_wc_commit(svn_test__sandbox_t *b, const char *path)
+{
+ apr_array_header_t *targets = apr_array_make(b->pool, 1,
+ sizeof(const char *));
+
+ APR_ARRAY_PUSH(targets, const char *) = sbox_wc_path(b, path);
+ return sbox_wc_commit_ex(b, targets, svn_depth_infinity);
+}
+
+svn_error_t *
+sbox_wc_update_depth(svn_test__sandbox_t *b,
+ const char *path,
+ svn_revnum_t revnum,
+ svn_depth_t depth,
+ svn_boolean_t sticky)
+{
+ svn_client_ctx_t *ctx;
+ apr_array_header_t *result_revs;
+ apr_array_header_t *paths = apr_array_make(b->pool, 1,
+ sizeof(const char *));
+ svn_opt_revision_t revision;
+
+ revision.kind = svn_opt_revision_number;
+ revision.value.number = revnum;
+
+ APR_ARRAY_PUSH(paths, const char *) = sbox_wc_path(b, path);
+ SVN_ERR(svn_client_create_context2(&ctx, NULL, b->pool));
+ ctx->wc_ctx = b->wc_ctx;
+ return svn_client_update4(&result_revs, paths, &revision, depth,
+ sticky, FALSE, FALSE, FALSE, FALSE,
+ ctx, b->pool);
+}
+
+svn_error_t *
+sbox_wc_update(svn_test__sandbox_t *b, const char *path, svn_revnum_t revnum)
+{
+ SVN_ERR(sbox_wc_update_depth(b, path, revnum, svn_depth_unknown, FALSE));
+ return SVN_NO_ERROR;
+}
+
+svn_error_t *
+sbox_wc_switch(svn_test__sandbox_t *b,
+ const char *path,
+ const char *url,
+ svn_depth_t depth)
+{
+ svn_client_ctx_t *ctx;
+ svn_revnum_t result_rev;
+ svn_opt_revision_t head_rev = { svn_opt_revision_head, {0} };
+
+ url = apr_pstrcat(b->pool, b->repos_url, url, (char*)NULL);
+ SVN_ERR(svn_client_create_context2(&ctx, NULL, b->pool));
+ ctx->wc_ctx = b->wc_ctx;
+ return svn_client_switch3(&result_rev, sbox_wc_path(b, path), url,
+ &head_rev, &head_rev, depth,
+ FALSE /* depth_is_sticky */,
+ TRUE /* ignore_externals */,
+ FALSE /* allow_unver_obstructions */,
+ TRUE /* ignore_ancestry */,
+ ctx, b->pool);
+}
+
+svn_error_t *
+sbox_wc_resolved(svn_test__sandbox_t *b, const char *path)
+{
+ return sbox_wc_resolve(b, path, svn_depth_infinity,
+ svn_wc_conflict_choose_merged);
+}
+
+svn_error_t *
+sbox_wc_resolve(svn_test__sandbox_t *b, const char *path, svn_depth_t depth,
+ svn_wc_conflict_choice_t conflict_choice)
+{
+ const char *lock_abspath;
+ svn_error_t *err;
+
+ SVN_ERR(svn_wc__acquire_write_lock_for_resolve(&lock_abspath, b->wc_ctx,
+ sbox_wc_path(b, path),
+ b->pool, b->pool));
+ err = svn_wc__resolve_conflicts(b->wc_ctx, sbox_wc_path(b, path),
+ depth,
+ TRUE /* resolve_text */,
+ "" /* resolve_prop (ALL props) */,
+ TRUE /* resolve_tree */,
+ conflict_choice,
+ NULL, NULL, /* conflict func */
+ NULL, NULL, /* cancellation */
+ NULL, NULL, /* notification */
+ b->pool);
+
+ err = svn_error_compose_create(err, svn_wc__release_write_lock(b->wc_ctx,
+ lock_abspath,
+ b->pool));
+ return err;
+}
+
+svn_error_t *
+sbox_wc_move(svn_test__sandbox_t *b, const char *src, const char *dst)
+{
+ svn_client_ctx_t *ctx;
+ apr_array_header_t *paths = apr_array_make(b->pool, 1,
+ sizeof(const char *));
+
+ SVN_ERR(svn_client_create_context2(&ctx, NULL, b->pool));
+ ctx->wc_ctx = b->wc_ctx;
+ APR_ARRAY_PUSH(paths, const char *) = sbox_wc_path(b, src);
+ return svn_client_move7(paths, sbox_wc_path(b, dst),
+ FALSE /* move_as_child */,
+ FALSE /* make_parents */,
+ TRUE /* allow_mixed_revisions */,
+ FALSE /* metadata_only */,
+ NULL /* revprop_table */,
+ NULL, NULL, /* commit callback */
+ ctx, b->pool);
+}
+
+svn_error_t *
+sbox_wc_propset(svn_test__sandbox_t *b,
+ const char *name,
+ const char *value,
+ const char *path)
+{
+ svn_client_ctx_t *ctx;
+ apr_array_header_t *paths = apr_array_make(b->pool, 1,
+ sizeof(const char *));
+ svn_string_t *pval = value ? svn_string_create(value, b->pool) : NULL;
+
+ SVN_ERR(svn_client_create_context2(&ctx, NULL, b->pool));
+ ctx->wc_ctx = b->wc_ctx;
+ APR_ARRAY_PUSH(paths, const char *) = sbox_wc_path(b, path);
+ return svn_client_propset_local(name, pval, paths, svn_depth_empty,
+ TRUE /* skip_checks */,
+ NULL, ctx, b->pool);
+}
+
+svn_error_t *
+sbox_wc_relocate(svn_test__sandbox_t *b,
+ const char *new_repos_url)
+{
+ apr_pool_t *scratch_pool = b->pool;
+ svn_client_ctx_t *ctx;
+
+ SVN_ERR(svn_client_create_context2(&ctx, NULL, scratch_pool));
+ ctx->wc_ctx = b->wc_ctx;
+
+ SVN_ERR(svn_client_relocate2(b->wc_abspath, b->repos_url,
+ new_repos_url, FALSE, ctx,scratch_pool));
+
+ b->repos_url = apr_pstrdup(b->pool, new_repos_url);
+
+ return SVN_NO_ERROR;
+}
+
+svn_error_t *
+sbox_add_and_commit_greek_tree(svn_test__sandbox_t *b)
+{
+ const struct svn_test__tree_entry_t *node;
+
+ for (node = svn_test__greek_tree_nodes; node->path; node++)
+ {
+ if (node->contents)
+ {
+ sbox_file_write(b, node->path, node->contents);
+ SVN_ERR(sbox_wc_add(b, node->path));
+ }
+ else
+ {
+ SVN_ERR(sbox_wc_mkdir(b, node->path));
+ }
+ }
+
+ SVN_ERR(sbox_wc_commit(b, ""));
+
+ return SVN_NO_ERROR;
+}
diff --git a/subversion/tests/libsvn_wc/utils.h b/subversion/tests/libsvn_wc/utils.h
index 83114e2..3004634 100644
--- a/subversion/tests/libsvn_wc/utils.h
+++ b/subversion/tests/libsvn_wc/utils.h
@@ -74,6 +74,107 @@ svn_test__sandbox_create(svn_test__sandbox_t *sandbox,
const svn_test_opts_t *opts,
apr_pool_t *pool);
+/* ---------------------------------------------------------------------- */
+/* Functions for easy manipulation of a WC. Paths given to these functions
+ * can be relative to the WC root as stored in the WC baton. */
+
+/* Return the abspath of PATH which is absolute or relative to the WC in B. */
+#define sbox_wc_path(b, path) \
+ (svn_dirent_join((b)->wc_abspath, (path), (b)->pool))
+
+/* Create a file on disk at PATH, with TEXT as its content. */
+void
+sbox_file_write(svn_test__sandbox_t *b, const char *path, const char *text);
+
+/* Schedule for addition the single node that exists on disk at PATH,
+ * non-recursively. */
+svn_error_t *
+sbox_wc_add(svn_test__sandbox_t *b, const char *path);
+
+/* Create a single directory on disk. */
+svn_error_t *
+sbox_disk_mkdir(svn_test__sandbox_t *b, const char *path);
+
+/* Create a single directory on disk and schedule it for addition. */
+svn_error_t *
+sbox_wc_mkdir(svn_test__sandbox_t *b, const char *path);
+
+/* Copy the WC file or directory tree FROM_PATH to TO_PATH which must not
+ * exist beforehand. */
+svn_error_t *
+sbox_wc_copy(svn_test__sandbox_t *b, const char *from_path, const char *to_path);
+
+svn_error_t *
+sbox_wc_copy_url(svn_test__sandbox_t *b, const char *from_url,
+ svn_revnum_t revision, const char *to_path);
+
+svn_error_t *
+sbox_wc_relocate(svn_test__sandbox_t *b,
+ const char *new_repos_url);
+
+/* Revert a WC file or directory tree at PATH */
+svn_error_t *
+sbox_wc_revert(svn_test__sandbox_t *b, const char *path, svn_depth_t depth);
+
+/* */
+svn_error_t *
+sbox_wc_delete(svn_test__sandbox_t *b, const char *path);
+
+/* */
+svn_error_t *
+sbox_wc_exclude(svn_test__sandbox_t *b, const char *path);
+
+/* */
+svn_error_t *
+sbox_wc_commit(svn_test__sandbox_t *b, const char *path);
+
+/* */
+svn_error_t *
+sbox_wc_commit_ex(svn_test__sandbox_t *b,
+ apr_array_header_t *targets,
+ svn_depth_t depth);
+
+/* */
+svn_error_t *
+sbox_wc_update(svn_test__sandbox_t *b, const char *path, svn_revnum_t revnum);
+
+svn_error_t *
+sbox_wc_update_depth(svn_test__sandbox_t *b,
+ const char *path,
+ svn_revnum_t revnum,
+ svn_depth_t depth,
+ svn_boolean_t sticky);
+
+svn_error_t *
+sbox_wc_switch(svn_test__sandbox_t *b,
+ const char *path,
+ const char *url,
+ svn_depth_t depth);
+
+/* */
+svn_error_t *
+sbox_wc_resolved(svn_test__sandbox_t *b, const char *path);
+
+/* */
+svn_error_t *
+sbox_wc_resolve(svn_test__sandbox_t *b, const char *path, svn_depth_t depth,
+ svn_wc_conflict_choice_t conflict_choice);
+
+/* */
+svn_error_t *
+sbox_wc_move(svn_test__sandbox_t *b, const char *src, const char *dst);
+
+/* Set property NAME to VALUE on PATH. If VALUE=NULL, delete the property. */
+svn_error_t *
+sbox_wc_propset(svn_test__sandbox_t *b,
+ const char *name,
+ const char *value,
+ const char *path);
+
+/* Create the Greek tree on disk in the WC, and commit it. */
+svn_error_t *
+sbox_add_and_commit_greek_tree(svn_test__sandbox_t *b);
+
/* Create a WC directory at WC_ABSPATH containing a fake WC DB, generated by
* executing the SQL statements EXTRA_STATEMENTS in addition to the standard
diff --git a/subversion/tests/libsvn_wc/wc-incomplete-tester.c b/subversion/tests/libsvn_wc/wc-incomplete-tester.c
index bd66641..2aac605 100644
--- a/subversion/tests/libsvn_wc/wc-incomplete-tester.c
+++ b/subversion/tests/libsvn_wc/wc-incomplete-tester.c
@@ -78,7 +78,7 @@ int main(int argc, const char *argv[])
"Mark WCPATH incomplete at REVISION [and REPOS_RELPATH]\n");
exit(EXIT_FAILURE);
}
-
+
if (apr_initialize())
{
fprintf(stderr, "apr_initialize failed\n");
diff --git a/subversion/tests/libsvn_wc/wc-queries-test.c b/subversion/tests/libsvn_wc/wc-queries-test.c
new file mode 100644
index 0000000..0621720
--- /dev/null
+++ b/subversion/tests/libsvn_wc/wc-queries-test.c
@@ -0,0 +1,897 @@
+/*
+ * wc-queries-test.c -- test the evaluation of the wc Sqlite queries
+ *
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ */
+
+#include "svn_pools.h"
+#include "svn_ctype.h"
+#include "private/svn_dep_compat.h"
+
+#include "svn_private_config.h"
+
+#include "../svn_test.h"
+
+#ifdef SVN_SQLITE_INLINE
+/* Include sqlite3 inline, making all symbols private. */
+ #define SQLITE_API static
+ #ifdef __APPLE__
+ #include <Availability.h>
+ #if __MAC_OS_X_VERSION_MIN_REQUIRED < 1060
+ /* <libkern/OSAtomic.h> is included on OS X by sqlite3.c, and
+ on old systems (Leopard or older), it cannot be compiled
+ with -std=c89 because it uses inline. This is a work-around. */
+ #define inline __inline__
+ #include <libkern/OSAtomic.h>
+ #undef inline
+ #endif
+ #endif
+ #include <sqlite3.c>
+#else
+ #include <sqlite3.h>
+#endif
+
+#include "../../libsvn_wc/wc-queries.h"
+
+WC_QUERIES_SQL_DECLARE_STATEMENTS(wc_queries);
+WC_QUERIES_SQL_DECLARE_STATEMENT_INFO(wc_query_info);
+
+/* The first query after the normal wc queries */
+#define STMT_SCHEMA_FIRST STMT_CREATE_SCHEMA
+
+#define SQLITE_ERR(x) \
+{ \
+ int sqlite_err__temp = (x); \
+ if (sqlite_err__temp != SQLITE_OK) \
+ return svn_error_createf(SVN_ERR_SQLITE_ERROR, \
+ NULL, "sqlite: %s", \
+ sqlite3_errmsg(sdb)); \
+} while (0)
+
+/* Schema creation statements fail during preparing when the table
+ already exists, and must be evaluated before testing the
+ queries. Statements above STMT_SCHEMA_FIRST only need to be
+ included here when they need to be evaluated before testing the
+ statements */
+static const int schema_statements[] =
+{
+ /* Usual tables */
+ STMT_CREATE_SCHEMA,
+ STMT_CREATE_NODES,
+ STMT_CREATE_NODES_TRIGGERS,
+ STMT_CREATE_EXTERNALS,
+ STMT_INSTALL_SCHEMA_STATISTICS,
+ /* Memory tables */
+ STMT_CREATE_TARGETS_LIST,
+ STMT_CREATE_CHANGELIST_LIST,
+ STMT_CREATE_CHANGELIST_TRIGGER,
+ STMT_CREATE_TARGET_PROP_CACHE,
+ STMT_CREATE_REVERT_LIST,
+ STMT_CREATE_DELETE_LIST,
+ STMT_CREATE_UPDATE_MOVE_LIST,
+ -1 /* final marker */
+};
+
+/* These statements currently trigger warnings. It would be nice if
+ we could annotate these in wc-queries.sql */
+static const int slow_statements[] =
+{
+ /* Operate on the entire WC */
+ STMT_SELECT_ALL_NODES, /* schema validation code */
+
+ /* Updates all records for a repository (designed slow) */
+ STMT_UPDATE_LOCK_REPOS_ID,
+
+ /* Full temporary table read */
+ STMT_INSERT_ACTUAL_EMPTIES,
+ STMT_SELECT_REVERT_LIST_RECURSIVE,
+ STMT_SELECT_DELETE_LIST,
+ STMT_SELECT_UPDATE_MOVE_LIST,
+
+ /* Designed as slow to avoid penalty on other queries */
+ STMT_SELECT_UNREFERENCED_PRISTINES,
+
+ /* Slow, but just if foreign keys are enabled:
+ * STMT_DELETE_PRISTINE_IF_UNREFERENCED,
+ */
+ STMT_HAVE_STAT1_TABLE, /* Queries sqlite_master which has no index */
+
+ -1 /* final marker */
+};
+
+/* Statements that just read the first record from a table,
+ using the primary key. Specialized as different sqlite
+ versions produce different results */
+static const int primary_key_statements[] =
+{
+ /* Is there a record? ### Can we somehow check for LIMIT 1,
+ and primary key instead of adding a list? */
+ STMT_LOOK_FOR_WORK,
+ STMT_SELECT_WORK_ITEM,
+
+ -1 /* final marker */
+};
+
+/* Helper function to determine if a statement is in a list */
+static svn_boolean_t
+in_list(const int list[], int stmt_idx)
+{
+ int i;
+
+ for (i = 0; list[i] != -1; i++)
+ {
+ if (list[i] == stmt_idx)
+ return TRUE;
+ }
+ return FALSE;
+}
+
+/* Helpers to determine if a statement is in a common list */
+#define is_slow_statement(stmt_idx) in_list(slow_statements, stmt_idx)
+#define is_schema_statement(stmt_idx) \
+ ((stmt_idx >= STMT_SCHEMA_FIRST) || in_list(schema_statements, stmt_idx))
+
+
+/* Create an in-memory db for evaluating queries */
+static svn_error_t *
+create_memory_db(sqlite3 **db,
+ apr_pool_t *pool)
+{
+ sqlite3 *sdb;
+ int i;
+
+ /* Create an in-memory raw database */
+ SVN_TEST_ASSERT(sqlite3_initialize() == SQLITE_OK);
+ SQLITE_ERR(sqlite3_open_v2("", &sdb,
+ SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE,
+ NULL));
+
+ /* Create schema */
+ for (i = 0; schema_statements[i] != -1; i++)
+ {
+ SQLITE_ERR(sqlite3_exec(sdb, wc_queries[schema_statements[i]], NULL, NULL, NULL));
+ }
+
+ *db = sdb;
+ return SVN_NO_ERROR;
+}
+
+/* Verify sqlite3 runtime version */
+static svn_error_t *
+test_sqlite_version(apr_pool_t *scratch_pool)
+{
+ printf("DBG: Using Sqlite %s\n", sqlite3_version);
+
+ if (sqlite3_libversion_number() != SQLITE_VERSION_NUMBER)
+ printf("DBG: Compiled against Sqlite %s", SQLITE_VERSION);
+
+ if (sqlite3_libversion_number() < SQLITE_VERSION_NUMBER)
+ return svn_error_createf(SVN_ERR_TEST_FAILED, NULL,
+ "Compiled against Sqlite %s (at runtime we have Sqlite %s)",
+ SQLITE_VERSION, sqlite3_version);
+
+#if !SQLITE_VERSION_AT_LEAST(3, 7, 9)
+ return svn_error_create(SVN_ERR_TEST_FAILED, NULL,
+ "Sqlite upgrade recommended:\n"
+ "****************************************************************\n"
+ "* Subversion needs at least SQLite 3.7.9 to work optimally *\n"
+ "* *\n"
+ "* With older versions, at least some queries that are expected *\n"
+ "* to be using an index are not. This makes some operations use *\n"
+ "* every node in the working copy instead of just one. *\n"
+ "* *\n"
+ "* While Subversion works correctly in this case, you may see *\n"
+ "* slowdowns of WELL MORE THAN 1000* in some cases! *\n"
+ "* *\n"
+ "* *\n"
+ "* SQLITE UPGRADE RECOMMENDED *\n"
+ "****************************************************************\n");
+#else
+ return SVN_NO_ERROR;
+#endif
+}
+
+/* Parse all normal queries */
+static svn_error_t *
+test_parsable(apr_pool_t *scratch_pool)
+{
+ sqlite3 *sdb;
+ int i;
+
+ SVN_ERR(create_memory_db(&sdb, scratch_pool));
+
+ for (i=0; i < STMT_SCHEMA_FIRST; i++)
+ {
+ sqlite3_stmt *stmt;
+ const char *text = wc_queries[i];
+
+ if (is_schema_statement(i))
+ continue;
+
+ /* Some of our statement texts contain multiple queries. We prepare
+ them all. */
+ while (*text != '\0')
+ {
+ const char *tail;
+ int r = sqlite3_prepare_v2(sdb, text, -1, &stmt, &tail);
+
+ if (r != SQLITE_OK)
+ return svn_error_createf(SVN_ERR_SQLITE_ERROR, NULL,
+ "Preparing %s failed: %s\n%s",
+ wc_query_info[i][0],
+ sqlite3_errmsg(sdb),
+ text);
+
+ SQLITE_ERR(sqlite3_finalize(stmt));
+
+ /* Continue after the current statement */
+ text = tail;
+ }
+ }
+
+ SQLITE_ERR(sqlite3_close(sdb)); /* Close the DB if ok; otherwise leaked */
+
+ return SVN_NO_ERROR;
+}
+
+/* Contains a parsed record from EXPLAIN QUERY PLAN */
+struct explanation_item
+{
+ const char *operation;
+ const char *table;
+ const char *alias;
+ svn_boolean_t scan;
+ svn_boolean_t search;
+ svn_boolean_t covered_by_index;
+ svn_boolean_t primary_key;
+ svn_boolean_t automatic_index;
+ const char *index;
+ const char *expressions;
+ const char *expected;
+
+ const char *compound_left;
+ const char *compound_right;
+ svn_boolean_t create_btree;
+
+ int expression_vars;
+ int expected_rows;
+};
+
+#define MATCH_TOKEN(x, y) (x && (strcmp(x, y) == 0))
+
+/* Simple parser for the Sqlite textual explanation into an explanation_item.
+ Writes "DBG:" lines when sqlite produces unexpected results. When no
+ valid explanation_item can be parsed sets *PARSED_ITEM to NULL, otherwise
+ to a valid result. */
+static svn_error_t *
+parse_explanation_item(struct explanation_item **parsed_item,
+ const char *text,
+ apr_pool_t *result_pool)
+{
+ struct explanation_item *item = apr_pcalloc(result_pool, sizeof(*item));
+ char *token;
+ char *last;
+ char *tmp = apr_pstrdup(result_pool, text);
+ const char *tmp_end = &tmp[strlen(tmp)];
+
+ *parsed_item = NULL;
+
+ item->operation = apr_strtok(tmp, " ", &last);
+
+ if (!item->operation)
+ {
+ return SVN_NO_ERROR;
+ }
+
+ item->scan = MATCH_TOKEN(item->operation, "SCAN");
+
+ if (item->scan || MATCH_TOKEN(item->operation, "SEARCH"))
+ {
+ item->search = TRUE; /* Search or scan */
+ token = apr_strtok(NULL, " ", &last);
+
+ if (!MATCH_TOKEN(token, "TABLE"))
+ {
+ printf("DBG: Expected 'TABLE', got '%s' in '%s'\n", token, text);
+ return SVN_NO_ERROR; /* Nothing to parse */
+ }
+
+ item->table = apr_strtok(NULL, " ", &last);
+
+ token = apr_strtok(NULL, " ", &last);
+
+ /* Skip alias */
+ if (MATCH_TOKEN(token, "AS"))
+ {
+ item->alias = apr_strtok(NULL, " ", &last);
+ token = apr_strtok(NULL, " ", &last);
+ }
+
+ if (MATCH_TOKEN(token, "USING"))
+ {
+ token = apr_strtok(NULL, " ", &last);
+
+ if (MATCH_TOKEN(token, "AUTOMATIC"))
+ {
+ /* Pain: A temporary index is created */
+ item->automatic_index = TRUE;
+ token = apr_strtok(NULL, " ", &last);
+ }
+
+ /* Handle COVERING */
+ if (MATCH_TOKEN(token, "COVERING"))
+ {
+ /* Bonus: Query will be answered by just using the index */
+ item->covered_by_index = TRUE;
+ token = apr_strtok(NULL, " ", &last);
+ }
+
+ if (MATCH_TOKEN(token, "INDEX"))
+ {
+ item->index = apr_strtok(NULL, " ", &last);
+ }
+ else if (MATCH_TOKEN(token, "INTEGER"))
+ {
+ token = apr_strtok(NULL, " ", &last);
+ if (!MATCH_TOKEN(token, "PRIMARY"))
+ {
+ printf("DBG: Expected 'PRIMARY', got '%s' in '%s'\n",
+ token, text);
+ return SVN_NO_ERROR;
+ }
+
+ token = apr_strtok(NULL, " ", &last);
+ if (!MATCH_TOKEN(token, "KEY"))
+ {
+ printf("DBG: Expected 'KEY', got '%s' in '%s'\n",
+ token, text);
+ return SVN_NO_ERROR;
+ }
+
+ item->primary_key = TRUE;
+ }
+ else
+ {
+ printf("DBG: Expected 'INDEX' or 'PRIMARY', got '%s' in '%s'\n",
+ token, text);
+ return SVN_NO_ERROR;
+ }
+
+ token = apr_strtok(NULL, " ", &last);
+ }
+
+ if (token && token[0] == '(' && token[1] != '~')
+ {
+ /* Undo the tokenization to switch parser rules */
+ size_t token_len = strlen(token);
+
+ if (token + token_len < tmp_end)
+ token[token_len] = ' ';
+
+ if (token[token_len] == '\0')
+ last[-1] = ' ';
+
+ token++; /* Skip the '(' */
+
+ item->expressions = apr_strtok(token, ")", &last);
+ token = apr_strtok(NULL, " ", &last);
+ }
+
+ if (token && *token == '(' && token[1] == '~')
+ {
+ /* Undo the tokenization to switch parser rules */
+ size_t token_len = strlen(token);
+
+ if (token + token_len < tmp_end)
+ token[token_len] = ' ';
+
+ if (token[token_len] == '\0')
+ last[-1] = ' ';
+
+ token += 2; /* Skip "(~" */
+
+ item->expected = apr_strtok(token, ")", &last);
+ token = apr_strtok(NULL, " ", &last);
+ }
+
+ if (token)
+ {
+ printf("DBG: Unexpected token '%s' in '%s'\n",
+ token, text);
+ return SVN_NO_ERROR;
+ }
+
+ /* Parsing successfull */
+ }
+ else if (MATCH_TOKEN(item->operation, "EXECUTE"))
+ {
+ /* Subquery handling */
+ return SVN_NO_ERROR;
+ }
+ else if (MATCH_TOKEN(item->operation, "COMPOUND"))
+ {
+ /* Handling temporary table (E.g. UNION) */
+
+ token = apr_strtok(NULL, " ", &last);
+ if (!MATCH_TOKEN(token, "SUBQUERIES"))
+ {
+ printf("DBG: Expected 'SUBQUERIES', got '%s' in '%s'\n", token,
+ text);
+ return SVN_NO_ERROR;
+ }
+
+ item->compound_left = apr_strtok(NULL, " ", &last);
+ token = apr_strtok(NULL, " ", &last);
+
+ if (!MATCH_TOKEN(token, "AND"))
+ {
+ printf("DBG: Expected 'AND', got '%s' in '%s'\n", token, text);
+ return SVN_NO_ERROR;
+ }
+
+ item->compound_right = apr_strtok(NULL, " ", &last);
+
+ token = apr_strtok(NULL, " ", &last);
+ if (MATCH_TOKEN(token, "USING"))
+ {
+ token = apr_strtok(NULL, " ", &last);
+ if (!MATCH_TOKEN(token, "TEMP"))
+ {
+ printf("DBG: Expected 'TEMP', got '%s' in '%s'\n", token, text);
+ }
+ token = apr_strtok(NULL, " ", &last);
+ if (!MATCH_TOKEN(token, "B-TREE"))
+ {
+ printf("DBG: Expected 'B-TREE', got '%s' in '%s'\n", token,
+ text);
+ }
+ item->create_btree = TRUE;
+ }
+ }
+ else if (MATCH_TOKEN(item->operation, "USE"))
+ {
+ /* Using a temporary table for ordering results */
+ /* ### Need parsing */
+ item->create_btree = TRUE;
+ }
+ else
+ {
+ printf("DBG: Unhandled sqlite operation '%s' in explanation\n", item->operation);
+ return SVN_NO_ERROR;
+ }
+
+ if (item->expressions)
+ {
+ const char *p;
+
+ for (p = item->expressions; *p; p++)
+ {
+ if (*p == '?')
+ item->expression_vars++;
+ }
+ }
+ if (item->expected)
+ {
+ item->expected_rows = atoi(item->expected);
+ }
+
+ *parsed_item = item;
+ return SVN_NO_ERROR;
+}
+
+/* Sqlite has an SQLITE_OMIT_EXPLAIN compilation flag, which may make
+ explain query just evaluate the query. Some older versions use a
+ different number of columns (and different texts) for
+ EXPLAIN query plan.
+
+ If none of this is true set *SUPPORTED to TRUE, otherwise to FALSE */
+static svn_error_t *
+supported_explain_query_plan(svn_boolean_t *supported,
+ sqlite3 *sdb,
+ apr_pool_t *scratch_pool)
+{
+ sqlite3_stmt *stmt;
+ int r;
+
+ *supported = TRUE;
+
+ r = sqlite3_prepare(sdb, "EXPLAIN QUERY PLAN SELECT 1",
+ -1, &stmt, NULL);
+
+ if (r != SQLITE_OK)
+ {
+ *supported = FALSE;
+ return SVN_NO_ERROR;
+ }
+
+ if (sqlite3_step(stmt) == SQLITE_ROW)
+ {
+ if (sqlite3_column_count(stmt) < 4)
+ {
+ *supported = FALSE;
+ /* Fall through */
+ }
+ }
+
+ SQLITE_ERR(sqlite3_reset(stmt));
+ SQLITE_ERR(sqlite3_finalize(stmt));
+ return SVN_NO_ERROR;
+}
+
+
+/* Returns TRUE if TABLE_NAME specifies a nodes table, which should be indexed
+ by wc_id and either local_relpath or parent_relpath */
+static svn_boolean_t
+is_node_table(const char *table_name)
+{
+ return (apr_strnatcasecmp(table_name, "nodes") == 0
+ || apr_strnatcasecmp(table_name, "actual_node") == 0
+ || apr_strnatcasecmp(table_name, "externals") == 0
+ || apr_strnatcasecmp(table_name, "lock") == 0
+ || apr_strnatcasecmp(table_name, "wc_lock") == 0
+ || FALSE);
+}
+
+/* Returns TRUE if TABLE specifies an intermediate result table, which is
+ allowed to have table scans, etc. */
+static svn_boolean_t
+is_result_table(const char *table_name)
+{
+ return (apr_strnatcasecmp(table_name, "target_prop_cache") == 0
+ || apr_strnatcasecmp(table_name, "changelist_list") == 0
+ || FALSE);
+}
+
+static svn_error_t *
+test_query_expectations(apr_pool_t *scratch_pool)
+{
+ sqlite3 *sdb;
+ int i;
+ apr_pool_t *iterpool = svn_pool_create(scratch_pool);
+ svn_error_t *warnings = NULL;
+ svn_boolean_t supports_query_info;
+
+ SVN_ERR(create_memory_db(&sdb, scratch_pool));
+
+ SVN_ERR(supported_explain_query_plan(&supports_query_info, sdb,
+ scratch_pool));
+ if (!supports_query_info)
+ {
+ SQLITE_ERR(sqlite3_close(sdb));
+ return svn_error_create(SVN_ERR_TEST_SKIPPED, NULL,
+ "Sqlite doesn't support EXPLAIN QUERY PLAN");
+ }
+
+ for (i=0; i < STMT_SCHEMA_FIRST; i++)
+ {
+ sqlite3_stmt *stmt;
+ const char *tail;
+ int r;
+ svn_boolean_t warned = FALSE;
+ apr_array_header_t *rows = NULL;
+
+ if (is_schema_statement(i))
+ continue;
+
+ /* Prepare statement to find if it is a single statement. */
+ r = sqlite3_prepare_v2(sdb, wc_queries[i], -1, &stmt, &tail);
+
+ if (r != SQLITE_OK)
+ continue; /* Parse failure is already reported by 'test_parable' */
+
+ SQLITE_ERR(sqlite3_finalize(stmt));
+ if (tail[0] != '\0')
+ continue; /* Multi-queries are currently not testable */
+
+ svn_pool_clear(iterpool);
+
+ r = sqlite3_prepare_v2(sdb,
+ apr_pstrcat(iterpool,
+ "EXPLAIN QUERY PLAN ",
+ wc_queries[i],
+ NULL),
+ -1, &stmt, &tail);
+
+ if (r != SQLITE_OK)
+ continue; /* EXPLAIN not enabled or doesn't support this query */
+
+ while (SQLITE_ROW == (r = sqlite3_step(stmt)))
+ {
+ /*int iSelectid;
+ int iOrder;
+ int iFrom;*/
+ const unsigned char *zDetail;
+ char *detail;
+ struct explanation_item *item;
+
+ /* ### The following code is correct for current Sqlite versions
+ ### (tested with 3.7.x), but the EXPLAIN QUERY PLAN output
+ ### is not guaranteed to be stable for future versions. */
+
+ /* Names as in Sqlite documentation */
+ /*iSelectid = sqlite3_column_int(stmt, 0);
+ iOrder = sqlite3_column_int(stmt, 1);
+ iFrom = sqlite3_column_int(stmt, 2);*/
+ zDetail = sqlite3_column_text(stmt, 3);
+
+ if (! zDetail)
+ continue;
+
+ if (!rows)
+ rows = apr_array_make(iterpool, 10, sizeof(const char*));
+
+ detail = apr_pstrdup(iterpool, (const char*)zDetail);
+
+ APR_ARRAY_PUSH(rows, const char *) = detail;
+
+ SVN_ERR(parse_explanation_item(&item, detail, iterpool));
+
+ if (!item)
+ continue; /* Not parsable or not interesting */
+
+ if (item->search
+ && item->automatic_index)
+ {
+ warned = TRUE;
+ if (!is_slow_statement(i))
+ {
+ warnings = svn_error_createf(SVN_ERR_TEST_FAILED, warnings,
+ "%s: "
+ "Creates a temporary index: %s\n",
+ wc_query_info[i][0], wc_queries[i]);
+ }
+ }
+ else if (item->search && item->primary_key)
+ {
+ /* Nice */
+ }
+ else if (item->search
+ && ((item->expression_vars < 2 && is_node_table(item->table))
+ || (item->expression_vars < 1))
+ && !is_result_table(item->table))
+ {
+ if (in_list(primary_key_statements, i))
+ {
+ /* Reported as primary key index usage in Sqlite 3.7,
+ as table scan in 3.8+, while the execution plan is
+ identical: read first record from table */
+ }
+ else if (!is_slow_statement(i))
+ {
+ warned = TRUE;
+ warnings = svn_error_createf(SVN_ERR_TEST_FAILED, warnings,
+ "%s: "
+ "Uses %s with only %d index component: (%s)\n%s",
+ wc_query_info[i][0], item->table,
+ item->expression_vars, item->expressions,
+ wc_queries[i]);
+ }
+ else
+ warned = TRUE;
+ }
+ else if (item->search && !item->index)
+ {
+ warned = TRUE;
+ if (!is_slow_statement(i))
+ warnings = svn_error_createf(SVN_ERR_TEST_FAILED, warnings,
+ "%s: "
+ "Query on %s doesn't use an index:\n%s",
+ wc_query_info[i][0], item->table, wc_queries[i]);
+ }
+ else if (item->scan && !is_result_table(item->table))
+ {
+ warned = TRUE;
+ if (!is_slow_statement(i))
+ warnings = svn_error_createf(SVN_ERR_TEST_FAILED, warnings,
+ "Query %s: "
+ "Performs scan on %s:\n%s",
+ wc_query_info[i][0], item->table, wc_queries[i]);
+ }
+ else if (item->create_btree)
+ {
+ warned = TRUE;
+ if (!is_slow_statement(i))
+ warnings = svn_error_createf(SVN_ERR_TEST_FAILED, warnings,
+ "Query %s: Creates a temporary B-TREE:\n%s",
+ wc_query_info[i][0], wc_queries[i]);
+ }
+ }
+ SQLITE_ERR(sqlite3_reset(stmt));
+ SQLITE_ERR(sqlite3_finalize(stmt));
+
+ if (!warned && is_slow_statement(i))
+ {
+ printf("DBG: Expected %s to be reported as slow, but it wasn't\n",
+ wc_query_info[i][0]);
+ }
+
+ if (rows && warned != is_slow_statement(i))
+ {
+ int w;
+ svn_error_t *info = NULL;
+ for (w = rows->nelts-1; w >= 0; w--)
+ {
+ if (warned)
+ info = svn_error_createf(SVN_ERR_SQLITE_CONSTRAINT, info,
+ "|%s", APR_ARRAY_IDX(rows, w,
+ const char*));
+ else
+ printf("|%s\n", APR_ARRAY_IDX(rows, w, const char*));
+ }
+
+ warnings = svn_error_compose_create(warnings, info);
+ }
+ }
+ SQLITE_ERR(sqlite3_close(sdb)); /* Close the DB if ok; otherwise leaked */
+
+ return warnings;
+}
+
+/* Helper to verify a bit of data in the sqlite3 statistics */
+static int
+parse_stat_data(const char *stat)
+{
+ int n = 0;
+ apr_int64_t last = APR_INT64_MAX;
+ while (*stat)
+ {
+ apr_int64_t v;
+ char *next;
+
+ if (*stat < '0' || *stat > '9')
+ return -2;
+
+ errno = 0;
+ v = apr_strtoi64(stat, &next, 10);
+
+ /* All numbers specify the average number of rows
+ with the same values in all columns left of it,
+ so the value must be >= 1 and lower than or equal
+ to all previous seen numbers */
+ if (v <= 0 || (v > last) || (errno != 0))
+ return -1;
+
+ last = v;
+
+ n++;
+ stat = next;
+
+ if (*stat == ' ')
+ stat++;
+ }
+
+ return n;
+}
+
+static svn_error_t *
+test_schema_statistics(apr_pool_t *scratch_pool)
+{
+ sqlite3 *sdb;
+ sqlite3_stmt *stmt;
+
+ SVN_ERR(create_memory_db(&sdb, scratch_pool));
+
+ SQLITE_ERR(
+ sqlite3_exec(sdb,
+ "CREATE TABLE shadow_stat1(tbl TEXT, idx TEXT, stat TEXT)",
+ NULL, NULL, NULL));
+
+ SQLITE_ERR(
+ sqlite3_exec(sdb,
+ "INSERT INTO shadow_stat1 (tbl, idx, stat) "
+ "SELECT tbl, idx, stat FROM sqlite_stat1",
+ NULL, NULL, NULL));
+
+ SQLITE_ERR(
+ sqlite3_exec(sdb,
+ "DROP TABLE sqlite_stat1",
+ NULL, NULL, NULL));
+
+ /* Insert statement to give index at least 1 record */
+ SQLITE_ERR(
+ sqlite3_exec(sdb,
+ "INSERT INTO nodes (wc_id, local_relpath, op_depth,"
+ " presence, kind) "
+ "VALUES (1, '', 0, 'normal', 'dir')",
+ NULL, NULL, NULL));
+
+ SQLITE_ERR(
+ sqlite3_exec(sdb,
+ "INSERT INTO actual_node (wc_id, local_relpath) "
+ "VALUES (1, '')",
+ NULL, NULL, NULL));
+
+ SQLITE_ERR(
+ sqlite3_exec(sdb,
+ "INSERT INTO lock (repos_id, repos_relpath, lock_token) "
+ "VALUES (1, '', '')",
+ NULL, NULL, NULL));
+
+ /* These are currently not necessary for query optimization, but it's better
+ to tell Sqlite how we intend to use this table anyway */
+ SQLITE_ERR(
+ sqlite3_exec(sdb,
+ "INSERT INTO wc_lock (wc_id, local_dir_relpath) "
+ "VALUES (1, '')",
+ NULL, NULL, NULL));
+
+ SQLITE_ERR(
+ sqlite3_exec(sdb,
+ "INSERT INTO WORK_QUEUE (work) "
+ "VALUES ('')",
+ NULL, NULL, NULL));
+
+ SQLITE_ERR(
+ sqlite3_exec(sdb,
+ "ANALYZE",
+ NULL, NULL, NULL));
+
+ SQLITE_ERR(
+ sqlite3_prepare(sdb, "SELECT s.tbl, s.idx, s.stat, r.stat "
+ "FROM shadow_stat1 s "
+ "LEFT JOIN sqlite_stat1 r ON "
+ "s.tbl=r.tbl and s.idx=r.idx",
+ -1, &stmt, NULL));
+
+ while (sqlite3_step(stmt) == SQLITE_ROW)
+ {
+ const char *wc_stat = (const char*)sqlite3_column_text(stmt, 2);
+ const char *sqlite_stat = (const char*)sqlite3_column_text(stmt, 3);
+
+ if (! sqlite_stat)
+ {
+ return svn_error_createf(SVN_ERR_TEST_FAILED, NULL,
+ "Schema statistic failure:"
+ " Refering to unknown index '%s' on '%s'",
+ sqlite3_column_text(stmt, 1),
+ sqlite3_column_text(stmt, 0));
+ }
+
+ if (parse_stat_data(wc_stat) != parse_stat_data(sqlite_stat))
+ {
+ return svn_error_createf(SVN_ERR_TEST_FAILED, NULL,
+ "Schema statistic failure:"
+ " Column mismatch for '%s' on '%s'",
+ sqlite3_column_text(stmt, 1),
+ sqlite3_column_text(stmt, 0));
+ }
+ }
+
+ SQLITE_ERR(sqlite3_reset(stmt));
+ SQLITE_ERR(sqlite3_finalize(stmt));
+
+ SQLITE_ERR(sqlite3_close(sdb)); /* Close the DB if ok; otherwise leaked */
+
+ return SVN_NO_ERROR;
+}
+
+struct svn_test_descriptor_t test_funcs[] =
+ {
+ SVN_TEST_NULL,
+ SVN_TEST_PASS2(test_sqlite_version,
+ "sqlite up-to-date"),
+ SVN_TEST_PASS2(test_parsable,
+ "queries are parsable"),
+ SVN_TEST_PASS2(test_query_expectations,
+ "test query expectations"),
+ SVN_TEST_PASS2(test_schema_statistics,
+ "test schema statistics"),
+ SVN_TEST_NULL
+ };
diff --git a/subversion/tests/libsvn_wc/wc-test.c b/subversion/tests/libsvn_wc/wc-test.c
new file mode 100644
index 0000000..30eb18a
--- /dev/null
+++ b/subversion/tests/libsvn_wc/wc-test.c
@@ -0,0 +1,323 @@
+/*
+ * wc-test.c : test WC APIs
+ *
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ */
+
+#include <apr_pools.h>
+#include <apr_general.h>
+
+#include "svn_types.h"
+#include "svn_io.h"
+#include "svn_dirent_uri.h"
+#include "svn_pools.h"
+#include "svn_repos.h"
+#include "svn_wc.h"
+#include "svn_client.h"
+#include "svn_hash.h"
+
+#include "utils.h"
+
+#include "private/svn_wc_private.h"
+#include "private/svn_sqlite.h"
+#include "private/svn_dep_compat.h"
+#include "../../libsvn_wc/wc.h"
+#include "../../libsvn_wc/wc_db.h"
+#define SVN_WC__I_AM_WC_DB
+#include "../../libsvn_wc/wc_db_private.h"
+
+#include "../svn_test.h"
+
+#ifdef _MSC_VER
+#pragma warning(disable: 4221) /* nonstandard extension used */
+#endif
+
+
+/* ---------------------------------------------------------------------- */
+/* The test functions */
+
+/* Structure for testing node_get_base and node_get_origin. */
+struct base_origin_t
+{
+ /* Path to create and test, WC-relative */
+ const char *path;
+ /* Expected base rev. "-1" means no base. (Expected base path
+ * == base_rev valid ? path : NULL) */
+ svn_revnum_t base_rev;
+ /* Path to copy from, WC-relative */
+ const char *src_path;
+ /* Expected "origin" */
+ struct {
+ const char *path;
+ svn_revnum_t rev;
+ } origin;
+};
+
+/* Data for testing node_get_base and node_get_origin. */
+struct base_origin_t base_origin_subtests[] =
+ {
+ /* file copied onto nothing */
+ { "A/C/copy1", -1, "iota", {"iota", 1} },
+
+ /* dir copied onto nothing */
+ { "A/C/copy2", -1, "A/B/E", {"A/B/E", 1} },
+
+ /* replacement: file copied over a schedule-delete file */
+ { "A/B/lambda", 1, "iota", {"iota", 1} },
+
+ /* replacement: dir copied over a schedule-delete dir */
+ { "A/D/G", 1, "A/B/E", {"A/B/E", 1} },
+
+ /* replacement: dir copied over a schedule-delete file */
+ { "A/D/gamma", 1, "A/B/E", {"A/B/E", 1} },
+
+ /* replacement: file copied over a schedule-delete dir */
+ { "A/D/H", 1, "iota", {"iota", 1} },
+
+ { 0 }
+ };
+
+/* Create a WC containing lots of different node states, in the sandbox B. */
+static svn_error_t *
+create_wc_for_base_and_origin_tests(svn_test__sandbox_t *b)
+{
+ struct base_origin_t *copy;
+
+ SVN_ERR(sbox_add_and_commit_greek_tree(b));
+
+ /* Copy various things */
+ for (copy = base_origin_subtests; copy->src_path; copy++)
+ {
+ if (SVN_IS_VALID_REVNUM(copy->base_rev))
+ SVN_ERR(sbox_wc_delete(b, copy->path));
+ SVN_ERR(sbox_wc_copy(b, copy->src_path, copy->path));
+ }
+
+ return SVN_NO_ERROR;
+}
+
+/* Test svn_wc__node_get_base(). */
+static svn_error_t *
+test_node_get_base(const svn_test_opts_t *opts, apr_pool_t *pool)
+{
+ svn_test__sandbox_t *b = apr_palloc(pool, sizeof(*b));
+
+ SVN_ERR(svn_test__sandbox_create(b, "node_get_base", opts, pool));
+
+ SVN_ERR(create_wc_for_base_and_origin_tests(b));
+
+ {
+ struct base_origin_t *subtest;
+
+ for (subtest = base_origin_subtests; subtest->path; subtest++)
+ {
+ const char *local_abspath
+ = svn_dirent_join(b->wc_abspath, subtest->path, b->pool);
+ svn_revnum_t revision;
+ const char *repos_relpath, *repos_root_url, *repos_uuid;
+
+ SVN_ERR(svn_wc__node_get_base(NULL, &revision, &repos_relpath,
+ &repos_root_url, &repos_uuid,
+ NULL,
+ b->wc_ctx, local_abspath,
+ TRUE /* ignore_enoent */,
+ FALSE /* show_hidden */,
+ b->pool, b->pool));
+ SVN_TEST_ASSERT(revision == subtest->base_rev);
+ if (SVN_IS_VALID_REVNUM(subtest->base_rev))
+ {
+ SVN_TEST_STRING_ASSERT(repos_relpath, subtest->path);
+ SVN_TEST_STRING_ASSERT(repos_root_url, b->repos_url);
+ SVN_TEST_ASSERT(repos_uuid != NULL);
+ }
+ else
+ {
+ SVN_TEST_STRING_ASSERT(repos_relpath, NULL);
+ SVN_TEST_STRING_ASSERT(repos_root_url, NULL);
+ SVN_TEST_STRING_ASSERT(repos_uuid, NULL);
+ }
+ }
+ }
+
+ return SVN_NO_ERROR;
+}
+
+/* Test svn_wc__node_get_origin(). */
+static svn_error_t *
+test_node_get_origin(const svn_test_opts_t *opts, apr_pool_t *pool)
+{
+ svn_test__sandbox_t *b = apr_palloc(pool, sizeof(*b));
+
+ SVN_ERR(svn_test__sandbox_create(b, "node_get_origin", opts, pool));
+
+ SVN_ERR(create_wc_for_base_and_origin_tests(b));
+
+ {
+ struct base_origin_t *subtest;
+
+ for (subtest = base_origin_subtests; subtest->path; subtest++)
+ {
+ const char *local_abspath
+ = svn_dirent_join(b->wc_abspath, subtest->path, b->pool);
+ svn_revnum_t revision;
+ const char *repos_relpath, *repos_root_url, *repos_uuid;
+
+ SVN_ERR(svn_wc__node_get_origin(NULL, &revision, &repos_relpath,
+ &repos_root_url, &repos_uuid, NULL,
+ b->wc_ctx, local_abspath, FALSE,
+ b->pool, b->pool));
+ SVN_TEST_ASSERT(revision == subtest->origin.rev);
+ if (SVN_IS_VALID_REVNUM(subtest->origin.rev))
+ {
+ SVN_TEST_STRING_ASSERT(repos_relpath, subtest->origin.path);
+ SVN_TEST_STRING_ASSERT(repos_root_url, b->repos_url);
+ SVN_TEST_ASSERT(repos_uuid != NULL);
+ }
+ else
+ {
+ SVN_TEST_STRING_ASSERT(repos_relpath, NULL);
+ SVN_TEST_STRING_ASSERT(repos_root_url, NULL);
+ SVN_TEST_STRING_ASSERT(repos_uuid, NULL);
+ }
+ }
+ }
+
+ return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+test_externals_parse(const svn_test_opts_t *opts, apr_pool_t *pool)
+{
+ int i;
+ struct external_info
+ {
+ const char *line;
+ const char *url;
+ const char *local_path;
+ svn_revnum_t peg_rev;
+ svn_revnum_t rev;
+
+ } items[] = {
+ {
+ "dir http://server/svn/a",
+ "http://server/svn/a",
+ "dir"
+ },
+ {
+ "/svn/home dir",
+ "u://svr/svn/home",
+ "dir"
+ },
+ {
+ "//server/home dir",
+ "u://server/home",
+ "dir"
+ },
+ {
+ "../../../../home dir",
+ "u://svr/svn/home",
+ "dir",
+ },
+ {
+ "^/../repB/tools/scripts scripts",
+ "u://svr/svn/cur/repB/tools/scripts",
+ "scripts"
+ },
+ {
+ "^/../repB/tools/README.txt scripts/README.txt",
+ "u://svr/svn/cur/repB/tools/README.txt",
+ "scripts/README.txt"
+ },
+ };
+
+ for (i = 0; i < sizeof(items) / sizeof(items[0]); i++)
+ {
+ apr_array_header_t *results;
+ svn_wc_external_item2_t *external_item;
+ const char *resolved_url;
+ SVN_ERR(svn_wc_parse_externals_description3(&results, "/my/current/dir",
+ items[i].line, FALSE, pool));
+
+ SVN_TEST_ASSERT(results && results->nelts == 1);
+
+ external_item = APR_ARRAY_IDX(results, 0, svn_wc_external_item2_t *);
+
+ SVN_ERR(svn_wc__resolve_relative_external_url(&resolved_url,
+ external_item,
+ "u://svr/svn/cur/dir",
+ "u://svr/svn/cur/dir/sd/fl",
+ pool, pool));
+
+ SVN_TEST_STRING_ASSERT(resolved_url, items[i].url);
+ SVN_TEST_STRING_ASSERT(external_item->target_dir, items[i].local_path);
+
+ if (items[i].peg_rev != 0)
+ SVN_TEST_ASSERT(external_item->peg_revision.value.number
+ == items[i].peg_rev);
+ if (items[i].rev != 0)
+ SVN_TEST_ASSERT(external_item->revision.value.number == items[i].rev);
+ SVN_TEST_ASSERT(svn_uri_is_canonical(resolved_url, pool));
+ }
+
+
+ return SVN_NO_ERROR;
+
+}
+
+static svn_error_t *
+test_externals_parse_erratic(apr_pool_t *pool)
+{
+ svn_error_t *err;
+ apr_array_header_t *list = NULL;
+
+ err = svn_wc_parse_externals_description3(
+ &list, "parent_dir",
+ "^/valid/but/should/not/be/on/record wc_target\n"
+ "because_this_is_an_error",
+ FALSE, pool);
+
+ /* DESC above has an error, so expect one. */
+ SVN_TEST_ASSERT(err != NULL);
+ svn_error_clear(err);
+
+ /* svn_wc_parse_externals_description3() should not
+ touch LIST when DESC had an error.*/
+ SVN_TEST_ASSERT(list == NULL);
+
+ return SVN_NO_ERROR;
+}
+
+
+/* ---------------------------------------------------------------------- */
+/* The list of test functions */
+
+struct svn_test_descriptor_t test_funcs[] =
+ {
+ SVN_TEST_NULL,
+ SVN_TEST_OPTS_PASS(test_node_get_base,
+ "test_node_get_base"),
+ SVN_TEST_OPTS_PASS(test_node_get_origin,
+ "test_node_get_origin"),
+ SVN_TEST_OPTS_PASS(test_externals_parse,
+ "test svn_wc_parse_externals_description3"),
+ SVN_TEST_PASS2(test_externals_parse_erratic,
+ "parse erratic externals definition"),
+ SVN_TEST_NULL
+ };