You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by br...@apache.org on 2013/10/22 19:01:43 UTC
svn commit: r1534703 - in /subversion/branches/1.8.x: ./
subversion/libsvn_wc/ subversion/tests/cmdline/ subversion/tests/libsvn_wc/
Author: breser
Date: Tue Oct 22 17:01:42 2013
New Revision: 1534703
URL: http://svn.apache.org/r1534703
Log:
Merge the r1530763 group from trunk:
* r1530763, r1530768, r1530922, r1530872, r1531002, r1531004, r1531938, r1532098, r1530967
Resolve issue #4436, reverting a move leaves some move data.
Justification:
Reverting a move shouldn't break the wc.db state.
Notes:
breser: Added r1530967 because the comment in wc_db.h mentions the test
added by that revision.
Votes:
+1: breser, rhuijben, philip
Modified:
subversion/branches/1.8.x/ (props changed)
subversion/branches/1.8.x/STATUS
subversion/branches/1.8.x/subversion/libsvn_wc/wc-queries.sql
subversion/branches/1.8.x/subversion/libsvn_wc/wc_db.c
subversion/branches/1.8.x/subversion/libsvn_wc/wc_db.h
subversion/branches/1.8.x/subversion/libsvn_wc/wc_db_private.h
subversion/branches/1.8.x/subversion/libsvn_wc/wc_db_update_move.c
subversion/branches/1.8.x/subversion/tests/cmdline/move_tests.py
subversion/branches/1.8.x/subversion/tests/cmdline/revert_tests.py
subversion/branches/1.8.x/subversion/tests/libsvn_wc/op-depth-test.c
Propchange: subversion/branches/1.8.x/
------------------------------------------------------------------------------
Merged /subversion/trunk:r1530763,1530768,1530872,1530922,1530967,1531002,1531004,1531938,1532098
Modified: subversion/branches/1.8.x/STATUS
URL: http://svn.apache.org/viewvc/subversion/branches/1.8.x/STATUS?rev=1534703&r1=1534702&r2=1534703&view=diff
==============================================================================
--- subversion/branches/1.8.x/STATUS (original)
+++ subversion/branches/1.8.x/STATUS Tue Oct 22 17:01:42 2013
@@ -107,16 +107,6 @@ Veto-blocked changes:
Approved changes:
=================
- * r1530763, r1530768, r1530922, r1530872, r1531002, r1531004, r1531938, r1532098, r1530967
- Resolve issue #4436, reverting a move leaves some move data.
- Justification:
- Reverting a move shouldn't break the wc.db state.
- Notes:
- breser: Added r1530967 because the comment in wc_db.h mentions the test
- added by that revision.
- Votes:
- +1: breser, rhuijben, philip
-
* r1520065, r1520745
Resolve a user triggerable assertion when during an update a file external
is being replaced by a server excluded (aka absent) node. Issue 4422.
Modified: subversion/branches/1.8.x/subversion/libsvn_wc/wc-queries.sql
URL: http://svn.apache.org/viewvc/subversion/branches/1.8.x/subversion/libsvn_wc/wc-queries.sql?rev=1534703&r1=1534702&r2=1534703&view=diff
==============================================================================
--- subversion/branches/1.8.x/subversion/libsvn_wc/wc-queries.sql (original)
+++ subversion/branches/1.8.x/subversion/libsvn_wc/wc-queries.sql Tue Oct 22 17:01:42 2013
@@ -1571,7 +1571,7 @@ WHERE wc_id = ?1
AND moved_to IS NOT NULL
-- STMT_SELECT_MOVED_OUTSIDE
-SELECT local_relpath, moved_to FROM nodes
+SELECT local_relpath, moved_to, op_depth FROM nodes
WHERE wc_id = ?1
AND (local_relpath = ?2 OR IS_STRICT_DESCENDANT_OF(local_relpath, ?2))
AND op_depth >= ?3
Modified: subversion/branches/1.8.x/subversion/libsvn_wc/wc_db.c
URL: http://svn.apache.org/viewvc/subversion/branches/1.8.x/subversion/libsvn_wc/wc_db.c?rev=1534703&r1=1534702&r2=1534703&view=diff
==============================================================================
--- subversion/branches/1.8.x/subversion/libsvn_wc/wc_db.c (original)
+++ subversion/branches/1.8.x/subversion/libsvn_wc/wc_db.c Tue Oct 22 17:01:42 2013
@@ -2248,6 +2248,12 @@ db_base_remove(svn_wc__db_wcroot_t *wcro
* might introduce actual-only nodes without direct parents,
* and we're not yet sure if other existing code is prepared
* to handle such nodes. To be revisited post-1.8.
+ *
+ * ### In case of a conflict we are most likely creating WORKING nodes
+ * describing a copy of what was in BASE. The move information
+ * should be updated to describe a move from the WORKING layer.
+ * When stored that way the resolver of the tree conflict still has
+ * the knowledge of what was moved.
*/
SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
STMT_SELECT_MOVED_OUTSIDE));
@@ -6388,6 +6394,7 @@ op_revert_txn(void *baton,
{
SVN_ERR(svn_wc__db_resolve_break_moved_away_internal(wcroot,
local_relpath,
+ op_depth,
scratch_pool));
}
else
@@ -6554,10 +6561,12 @@ op_revert_recursive_txn(void *baton,
while (have_row)
{
const char *move_src_relpath = svn_sqlite__column_text(stmt, 0, NULL);
+ int move_op_depth = svn_sqlite__column_int(stmt, 2);
svn_error_t *err;
err = svn_wc__db_resolve_break_moved_away_internal(wcroot,
move_src_relpath,
+ move_op_depth,
scratch_pool);
if (err)
return svn_error_compose_create(err, svn_sqlite__reset(stmt));
Modified: subversion/branches/1.8.x/subversion/libsvn_wc/wc_db.h
URL: http://svn.apache.org/viewvc/subversion/branches/1.8.x/subversion/libsvn_wc/wc_db.h?rev=1534703&r1=1534702&r2=1534703&view=diff
==============================================================================
--- subversion/branches/1.8.x/subversion/libsvn_wc/wc_db.h (original)
+++ subversion/branches/1.8.x/subversion/libsvn_wc/wc_db.h Tue Oct 22 17:01:42 2013
@@ -3382,7 +3382,14 @@ svn_wc__db_resolve_delete_raise_moved_aw
apr_pool_t *scratch_pool);
/* Like svn_wc__db_resolve_delete_raise_moved_away this should be
- combined. */
+ combined.
+
+ ### LOCAL_ABSPATH specifies the move origin, but the move origin
+ ### is not necessary unique enough. This function needs an op_root_abspath
+ ### argument to differentiate between different origins.
+
+ ### See move_tests.py: move_many_update_delete for an example case.
+ */
svn_error_t *
svn_wc__db_resolve_break_moved_away(svn_wc__db_t *db,
const char *local_abspath,
Modified: subversion/branches/1.8.x/subversion/libsvn_wc/wc_db_private.h
URL: http://svn.apache.org/viewvc/subversion/branches/1.8.x/subversion/libsvn_wc/wc_db_private.h?rev=1534703&r1=1534702&r2=1534703&view=diff
==============================================================================
--- subversion/branches/1.8.x/subversion/libsvn_wc/wc_db_private.h (original)
+++ subversion/branches/1.8.x/subversion/libsvn_wc/wc_db_private.h Tue Oct 22 17:01:42 2013
@@ -442,9 +442,12 @@ svn_wc__db_bump_moved_away(svn_wc__db_wc
svn_wc__db_t *db,
apr_pool_t *scratch_pool);
+/* Unbreak the move from LOCAL_RELPATH on op-depth in WCROOT, by making
+ the destination a normal copy */
svn_error_t *
svn_wc__db_resolve_break_moved_away_internal(svn_wc__db_wcroot_t *wcroot,
const char *local_relpath,
+ int op_depth,
apr_pool_t *scratch_pool);
svn_error_t *
Modified: subversion/branches/1.8.x/subversion/libsvn_wc/wc_db_update_move.c
URL: http://svn.apache.org/viewvc/subversion/branches/1.8.x/subversion/libsvn_wc/wc_db_update_move.c?rev=1534703&r1=1534702&r2=1534703&view=diff
==============================================================================
--- subversion/branches/1.8.x/subversion/libsvn_wc/wc_db_update_move.c (original)
+++ subversion/branches/1.8.x/subversion/libsvn_wc/wc_db_update_move.c Tue Oct 22 17:01:42 2013
@@ -2284,30 +2284,34 @@ svn_wc__db_bump_moved_away(svn_wc__db_wc
svn_wc__db_t *db,
apr_pool_t *scratch_pool)
{
- const char *dummy1, *move_dst_op_root_relpath;
- const char *move_src_root_relpath, *move_src_op_root_relpath;
apr_hash_t *src_done;
SVN_ERR(svn_sqlite__exec_statements(wcroot->sdb,
STMT_CREATE_UPDATE_MOVE_LIST));
- SVN_ERR(svn_wc__db_op_depth_moved_to(&dummy1, &move_dst_op_root_relpath,
- &move_src_root_relpath,
- &move_src_op_root_relpath, 0,
- wcroot, local_relpath,
- scratch_pool, scratch_pool));
-
- if (move_src_root_relpath)
+ if (local_relpath[0] != '\0')
{
- if (strcmp(move_src_root_relpath, local_relpath))
+ const char *dummy1, *move_dst_op_root_relpath;
+ const char *move_src_root_relpath, *move_src_op_root_relpath;
+
+ /* Is the root of the update moved away? (Impossible for the wcroot) */
+ SVN_ERR(svn_wc__db_op_depth_moved_to(&dummy1, &move_dst_op_root_relpath,
+ &move_src_root_relpath,
+ &move_src_op_root_relpath, 0,
+ wcroot, local_relpath,
+ scratch_pool, scratch_pool));
+
+ if (move_src_root_relpath)
{
- SVN_ERR(bump_mark_tree_conflict(wcroot, move_src_root_relpath,
- move_src_op_root_relpath,
- move_dst_op_root_relpath,
- db, scratch_pool));
- return SVN_NO_ERROR;
+ if (strcmp(move_src_root_relpath, local_relpath))
+ {
+ SVN_ERR(bump_mark_tree_conflict(wcroot, move_src_root_relpath,
+ move_src_op_root_relpath,
+ move_dst_op_root_relpath,
+ db, scratch_pool));
+ return SVN_NO_ERROR;
+ }
}
-
}
src_done = apr_hash_make(scratch_pool);
@@ -2440,17 +2444,23 @@ break_move(svn_wc__db_wcroot_t *wcroot,
svn_error_t *
svn_wc__db_resolve_break_moved_away_internal(svn_wc__db_wcroot_t *wcroot,
const char *local_relpath,
+ int op_depth,
apr_pool_t *scratch_pool)
{
const char *dummy1, *move_dst_op_root_relpath;
const char *dummy2, *move_src_op_root_relpath;
+ /* We want to include the passed op-depth, but the function does a > check */
SVN_ERR(svn_wc__db_op_depth_moved_to(&dummy1, &move_dst_op_root_relpath,
&dummy2,
&move_src_op_root_relpath,
- relpath_depth(local_relpath) - 1,
+ op_depth - 1,
wcroot, local_relpath,
scratch_pool, scratch_pool));
+
+ SVN_ERR_ASSERT(move_src_op_root_relpath != NULL
+ && move_dst_op_root_relpath != NULL);
+
SVN_ERR(break_move(wcroot, local_relpath,
relpath_depth(move_src_op_root_relpath),
move_dst_op_root_relpath,
@@ -2519,6 +2529,7 @@ svn_wc__db_resolve_break_moved_away(svn_
SVN_WC__DB_WITH_TXN(
svn_wc__db_resolve_break_moved_away_internal(wcroot, local_relpath,
+ relpath_depth(local_relpath),
scratch_pool),
wcroot);
Modified: subversion/branches/1.8.x/subversion/tests/cmdline/move_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/1.8.x/subversion/tests/cmdline/move_tests.py?rev=1534703&r1=1534702&r2=1534703&view=diff
==============================================================================
--- subversion/branches/1.8.x/subversion/tests/cmdline/move_tests.py (original)
+++ subversion/branches/1.8.x/subversion/tests/cmdline/move_tests.py Tue Oct 22 17:01:42 2013
@@ -1234,6 +1234,169 @@ def move_missing(sbox):
svntest.actions.run_and_verify_status(wc_dir, expected_status)
+def setup_move_many(sbox):
+ "helper function which creates a wc with node A/A/A which is moved 3 times"
+
+ sbox.simple_rm('A', 'iota')
+ sbox.simple_mkdir('A',
+ 'A/A',
+ 'A/A/A',
+ 'A/A/A/A',
+ 'B',
+ 'B/A',
+ 'B/A/A',
+ 'B/A/A/A',
+ 'C',
+ 'C/A',
+ 'C/A/A',
+ 'C/A/A/A')
+ sbox.simple_commit()
+ sbox.simple_update()
+
+ sbox.simple_move('A/A/A', 'AAA_1')
+
+ sbox.simple_rm('A')
+ sbox.simple_move('B', 'A')
+
+ sbox.simple_move('A/A/A', 'AAA_2')
+
+ sbox.simple_rm('A/A')
+ sbox.simple_move('C/A', 'A/A')
+
+ sbox.simple_move('A/A/A', 'AAA_3')
+
+def move_many_status(wc_dir):
+ "obtain standard status after setup_move_many"
+
+ return svntest.wc.State(wc_dir, {
+ '' : Item(status=' ', wc_rev='2'),
+
+ 'AAA_1' : Item(status='A ', copied='+', moved_from='A/A/A', wc_rev='-'),
+ 'AAA_1/A' : Item(status=' ', copied='+', wc_rev='-'),
+
+ 'AAA_2' : Item(status='A ', copied='+', moved_from='A/A/A', wc_rev='-'),
+ 'AAA_2/A' : Item(status=' ', copied='+', wc_rev='-'),
+
+ 'AAA_3' : Item(status='A ', copied='+', moved_from='A/A/A', wc_rev='-'),
+ 'AAA_3/A' : Item(status=' ', copied='+', wc_rev='-'),
+
+ 'A' : Item(status='R ', copied='+', moved_from='B', wc_rev='-'),
+ 'A/A' : Item(status='R ', copied='+', moved_from='C/A', wc_rev='-'),
+ 'A/A/A' : Item(status='D ', copied='+', wc_rev='-', moved_to='AAA_3'),
+ 'A/A/A/A' : Item(status='D ', copied='+', wc_rev='-'),
+
+ 'B' : Item(status='D ', wc_rev='2', moved_to='A'),
+ 'B/A' : Item(status='D ', wc_rev='2'),
+ 'B/A/A' : Item(status='D ', wc_rev='2'),
+ 'B/A/A/A' : Item(status='D ', wc_rev='2'),
+
+ 'C' : Item(status=' ', wc_rev='2'),
+ 'C/A' : Item(status='D ', wc_rev='2', moved_to='A/A'),
+ 'C/A/A' : Item(status='D ', wc_rev='2'),
+ 'C/A/A/A' : Item(status='D ', wc_rev='2'),
+ })
+
+def move_many_update_delete(sbox):
+ "move many and delete-on-update"
+
+ sbox.build()
+ setup_move_many(sbox)
+
+ wc_dir = sbox.wc_dir
+
+ # Verify start situation
+ expected_status = move_many_status(wc_dir)
+ svntest.actions.run_and_verify_status(wc_dir, expected_status)
+
+ # And now create a tree conflict
+ svntest.actions.run_and_verify_svn(None, None, [],
+ 'rm', sbox.repo_url + '/B',
+ '-m', '')
+
+ expected_output = svntest.wc.State(wc_dir, {
+ 'B' : Item(status=' ', treeconflict='C'),
+ })
+
+
+ expected_status.tweak('', 'C', 'C/A', 'C/A/A', 'C/A/A/A', wc_rev='3')
+ expected_status.tweak('A', moved_from=None)
+ expected_status.remove('B/A', 'B/A/A', 'B/A/A/A')
+ expected_status.tweak('B', status='! ', treeconflict='C', wc_rev=None, moved_to=None)
+
+ svntest.actions.run_and_verify_update(wc_dir, expected_output, None,
+ expected_status)
+
+ # Would be nice if we could run the resolver as a separate step,
+ # but 'svn resolve' just fails for any value but working
+
+@XFail()
+def move_many_update_add(sbox):
+ "move many and add-on-update"
+
+ sbox.build()
+ setup_move_many(sbox)
+
+ wc_dir = sbox.wc_dir
+
+ # Verify start situation
+ expected_status = move_many_status(wc_dir)
+ #svntest.actions.run_and_verify_status(wc_dir, expected_status)
+
+ # And now create a tree conflict
+ svntest.actions.run_and_verify_svn(None, None, [],
+ 'mkdir', sbox.repo_url + '/B/A/A/BB',
+ '-m', '')
+
+ expected_output = svntest.wc.State(wc_dir, {
+ 'B' : Item(status=' ', treeconflict='C'),
+ 'B/A' : Item(status=' ', treeconflict='U'),
+ 'B/A/A' : Item(status=' ', treeconflict='U'),
+ 'B/A/A/BB' : Item(status=' ', treeconflict='A'),
+ # And while resolving
+ 'A/A/' : Item(status=' ', treeconflict='C')
+ })
+
+ expected_status.tweak('',
+ 'B', 'B/A', 'B/A/A', 'B/A/A/A',
+ 'C', 'C/A', 'C/A/A', 'C/A/A/A',
+ wc_rev='3')
+
+ expected_status.tweak('A/A', treeconflict='C')
+ expected_status.add({
+ 'A/A/A/BB' : Item(status='D ', copied='+', wc_rev='-'),
+ 'B/A/A/BB' : Item(status='D ', wc_rev='3'),
+ })
+
+ svntest.actions.run_and_verify_update(wc_dir, expected_output, None,
+ expected_status,
+ None, None, None,
+ None, None, None,
+ wc_dir, '--accept', 'mine-conflict')
+
+ # And another one
+ svntest.actions.run_and_verify_svn(None, None, [],
+ 'mkdir', sbox.repo_url + '/C/A/A/BB',
+ '-m', '')
+
+ expected_status.tweak('',
+ 'B', 'B/A', 'B/A/A', 'B/A/A/A',
+ 'C', 'C/A', 'C/A/A', 'C/A/A/A',
+ wc_rev='4')
+
+ expected_output = svntest.wc.State(wc_dir, {
+ 'C/A' : Item(status=' ', treeconflict='C'),
+ 'C/A/A' : Item(status=' ', treeconflict='U'),
+ 'C/A/A/BB' : Item(status=' ', treeconflict='A'),
+ })
+
+ # This currently triggers an assertion failure
+ svntest.actions.run_and_verify_update(wc_dir, expected_output, None,
+ expected_status,
+ None, None, None,
+ None, None, None,
+ wc_dir, '--accept', 'mine-conflict')
+
+
#######################################################################
# Run the tests
@@ -1245,6 +1408,8 @@ test_list = [ None,
deeper_move_file_test,
property_merge,
move_missing,
+ move_many_update_delete,
+ move_many_update_add,
]
if __name__ == '__main__':
Modified: subversion/branches/1.8.x/subversion/tests/cmdline/revert_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/1.8.x/subversion/tests/cmdline/revert_tests.py?rev=1534703&r1=1534702&r2=1534703&view=diff
==============================================================================
--- subversion/branches/1.8.x/subversion/tests/cmdline/revert_tests.py (original)
+++ subversion/branches/1.8.x/subversion/tests/cmdline/revert_tests.py Tue Oct 22 17:01:42 2013
@@ -1644,6 +1644,8 @@ def revert_obstructing_wc(sbox):
'revert', '-R', wc_dir)
+
+
########################################################################
# Run the tests
@@ -1683,7 +1685,7 @@ test_list = [ None,
revert_no_text_change_conflict_recursive,
revert_with_unversioned_targets,
revert_nonexistent,
- revert_obstructing_wc
+ revert_obstructing_wc,
]
if __name__ == '__main__':
Modified: subversion/branches/1.8.x/subversion/tests/libsvn_wc/op-depth-test.c
URL: http://svn.apache.org/viewvc/subversion/branches/1.8.x/subversion/tests/libsvn_wc/op-depth-test.c?rev=1534703&r1=1534702&r2=1534703&view=diff
==============================================================================
--- subversion/branches/1.8.x/subversion/tests/libsvn_wc/op-depth-test.c (original)
+++ subversion/branches/1.8.x/subversion/tests/libsvn_wc/op-depth-test.c Tue Oct 22 17:01:42 2013
@@ -8149,6 +8149,197 @@ update_with_tree_conflict(const svn_test
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_abspath_more_than_once(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/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;
+}
+
+
/* ---------------------------------------------------------------------- */
/* The list of test functions */
@@ -8302,5 +8493,9 @@ struct svn_test_descriptor_t test_funcs[
"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_XFAIL(move_abspath_more_than_once,
+ "move one abspath more than once"),
SVN_TEST_NULL
};