You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by ju...@apache.org on 2015/03/24 17:32:05 UTC
svn commit: r1668930 - in /subversion/branches/move-tracking-2/subversion:
svnmover/svnmover.c tests/cmdline/svnmover_tests.py
Author: julianfoad
Date: Tue Mar 24 16:32:04 2015
New Revision: 1668930
URL: http://svn.apache.org/r1668930
Log:
On the 'move-tracking-2' branch: Make move-by-branch-and-delete and
move-by-copy-and-delete work with subtrees.
* subversion/svnmover/svnmover.c
(move_by_branch_and_delete,
move_by_copy_and_delete): New.
(do_move): Use them.
* subversion/tests/cmdline/svnmover_tests.py
(move_to_related_branch,
move_to_related_branch_element_already_exists): New tests.
(test_list): Run them.
Modified:
subversion/branches/move-tracking-2/subversion/svnmover/svnmover.c
subversion/branches/move-tracking-2/subversion/tests/cmdline/svnmover_tests.py
Modified: subversion/branches/move-tracking-2/subversion/svnmover/svnmover.c
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/svnmover/svnmover.c?rev=1668930&r1=1668929&r2=1668930&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/svnmover/svnmover.c (original)
+++ subversion/branches/move-tracking-2/subversion/svnmover/svnmover.c Tue Mar 24 16:32:04 2015
@@ -1202,16 +1202,87 @@ svn_branch_diff_r(svn_editor3_t *editor,
return SVN_NO_ERROR;
}
+/* Move by branch-and-delete into an existing target branch.
+ *
+ * The target branch is different from the source branch.
+ *
+ * delete elements from source branch
+ * instantiate (or update) same elements in target branch
+ *
+ * For each element being moved, if the element already exists in TO_BRANCH,
+ * the effect is as if the existing element in TO_BRANCH was first deleted.
+ */
+static svn_error_t *
+move_by_branch_and_delete(svn_editor3_t *editor,
+ svn_branch_el_rev_id_t *el_rev,
+ svn_branch_instance_t *to_branch,
+ int to_parent_eid,
+ const char *to_name,
+ apr_pool_t *scratch_pool)
+{
+ svn_branch_subtree_t subtree
+ = svn_branch_map_get_subtree(el_rev->branch, el_rev->eid, scratch_pool);
+
+ SVN_ERR_ASSERT(BRANCHES_IN_SAME_FAMILY(el_rev->branch, to_branch));
+
+ /* This is supposed to be used for moving to a *different* branch in the
+ same family. In fact, this method would also work for moving within one
+ branch, but we don't currently want to use it for that purpose. */
+ SVN_ERR_ASSERT(! BRANCH_IS_SAME_BRANCH(el_rev->branch, to_branch,
+ scratch_pool));
+
+ SVN_ERR(svn_editor3_delete(editor, el_rev->rev,
+ el_rev->branch, el_rev->eid));
+ SVN_ERR(svn_branch_instantiate_subtree(to_branch,
+ to_parent_eid, to_name, subtree,
+ scratch_pool));
+
+ /* ### We need to move nested branches too. */
+ return SVN_NO_ERROR;
+}
+
+/* Move by copy-and-delete into a different branch family.
+ *
+ * The target branch is different from the source branch.
+ *
+ * copy source elements to target branch
+ * delete elements from source branch
+ *
+ * For each element being moved, if the element already exists in TO_BRANCH,
+ * the effect is as if the existing element in TO_BRANCH was first deleted.
+ */
+static svn_error_t *
+move_by_copy_and_delete(svn_editor3_t *editor,
+ svn_branch_el_rev_id_t *el_rev,
+ svn_branch_instance_t *to_branch,
+ int to_parent_eid,
+ const char *to_name,
+ apr_pool_t *scratch_pool)
+{
+ SVN_ERR_ASSERT(! BRANCHES_IN_SAME_FAMILY(el_rev->branch, to_branch));
+
+ SVN_ERR(svn_editor3_copy_tree(editor, el_rev,
+ to_branch,
+ to_parent_eid, to_name));
+ SVN_ERR(svn_editor3_delete(editor, el_rev->rev,
+ el_rev->branch, el_rev->eid));
+ return SVN_NO_ERROR;
+}
+
/* Move in the 'best' way possible.
*
* if target is in same branch:
* move the element
* else if target is in another branch of same family:
- * delete element from source branch
- * instantiate same element in target branch
+ * delete from source branch
+ * instantiate in target branch
* else:
- * delete element from source branch
- * create a new element in target branch
+ * copy into target branch
+ * delete from source branch
+ *
+ * ### Another available option is a variant of the second case:
+ * if (parent branch of source branch) and (parent element of target) are in
+ * the same family, then make a subtree-branch of the source subtree.
*/
static svn_error_t *
do_move(svn_editor3_t *editor,
@@ -1220,10 +1291,9 @@ do_move(svn_editor3_t *editor,
const char *to_name,
apr_pool_t *scratch_pool)
{
- svn_branch_el_rev_content_t *old_node;
-
/* Simple move/rename within same branch, if possible */
- if (to_parent_el_rev->branch == el_rev->branch)
+ if (BRANCH_IS_SAME_BRANCH(to_parent_el_rev->branch, el_rev->branch,
+ scratch_pool))
{
/* Move within same branch */
SVN_ERR(svn_editor3_alter(editor, el_rev->rev,
@@ -1233,60 +1303,30 @@ do_move(svn_editor3_t *editor,
return SVN_NO_ERROR;
}
- /* Instantiate same element in another branch of same family, if possible */
- if (el_rev->branch->sibling_defn->family->fid
- == to_parent_el_rev->branch->sibling_defn->family->fid)
+ /* Instantiate same elements in another branch of same family, if possible */
+ if (BRANCHES_IN_SAME_FAMILY(el_rev->branch, to_parent_el_rev->branch))
{
- /* Does this element already exist in the target branch? We can't
- use this method if it does. */
- SVN_ERR(svn_editor3_el_rev_get(&old_node,
- editor,
- to_parent_el_rev->branch, el_rev->eid,
- scratch_pool, scratch_pool));
- if (! old_node)
- {
- /* (There is no danger of creating a cyclic directory hierarchy in
- the target branch, as this element doesn't yet exist there.) */
-
- printf("mv: moving by deleting element in source branch and "
- "instantiating same element in target branch\n");
-
- /* Get the old content of the source node (which we know exists) */
- SVN_ERR(svn_editor3_el_rev_get(&old_node,
- editor, el_rev->branch, el_rev->eid,
- scratch_pool, scratch_pool));
- SVN_ERR_ASSERT(old_node);
- SVN_ERR(svn_editor3_delete(editor, el_rev->rev,
- el_rev->branch, el_rev->eid));
- SVN_ERR(svn_editor3_instantiate(editor,
- to_parent_el_rev->branch, el_rev->eid,
- to_parent_el_rev->eid, to_name,
- old_node->content));
- /* ### We need to move nested branches too. */
- return SVN_NO_ERROR;
- }
+ /* Here the elements moved from the source branch will overwrite any
+ corresponding elements that already exist in the target branch.
+ We could instead check and either throw an error or fall back to
+ copy-and-delete in that case. */
+
+ printf("mv: moving by branch-and-delete\n");
+
+ SVN_ERR(move_by_branch_and_delete(editor, el_rev,
+ to_parent_el_rev->branch,
+ to_parent_el_rev->eid, to_name,
+ scratch_pool));
+ return SVN_NO_ERROR;
}
/* Move by copy-and-delete */
- if (el_rev->branch->sibling_defn->family->fid
- != to_parent_el_rev->branch->sibling_defn->family->fid) /* ### always */
- {
- printf("mv: moving by copy-and-delete to a different branch family\n");
- }
- else /* ### never */
- {
- printf("mv: moving by copy-and-delete\n");
- }
- SVN_ERR(svn_editor3_el_rev_get(&old_node,
- editor, el_rev->branch, el_rev->eid,
- scratch_pool, scratch_pool));
- SVN_ERR(svn_editor3_delete(editor, el_rev->rev,
- el_rev->branch, el_rev->eid));
- SVN_ERR(svn_editor3_add(editor, NULL /*new_eid*/,
- old_node->content->kind,
- to_parent_el_rev->branch,
- to_parent_el_rev->eid, to_name,
- old_node->content));
+ printf("mv: moving by copy-and-delete\n");
+
+ SVN_ERR(move_by_copy_and_delete(editor, el_rev,
+ to_parent_el_rev->branch,
+ to_parent_el_rev->eid, to_name,
+ scratch_pool));
return SVN_NO_ERROR;
}
Modified: subversion/branches/move-tracking-2/subversion/tests/cmdline/svnmover_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/tests/cmdline/svnmover_tests.py?rev=1668930&r1=1668929&r2=1668930&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/tests/cmdline/svnmover_tests.py (original)
+++ subversion/branches/move-tracking-2/subversion/tests/cmdline/svnmover_tests.py Tue Mar 24 16:32:04 2015
@@ -548,6 +548,72 @@ def simple_moves_within_a_branch(sbox):
'mv', 'lib/README.txt', 'README'
)
+# Exercise moves from one branch to another in the same family. 'svnmover'
+# executes these by branch-and-delete. In this test, the elements being moved
+# do not already exist in the target branch.
+def move_to_related_branch(sbox):
+ "move to related branch"
+ sbox_build_svnmover(sbox, content=initial_content_in_trunk)
+ repo_url = sbox.repo_url
+
+ # branch
+ test_svnmover(repo_url, None,
+ 'branch', 'trunk', 'branches/br1')
+
+ # remove all elements from branch so we can try moving them there
+ test_svnmover(repo_url, None,
+ 'rm', 'branches/br1/README',
+ 'rm', 'branches/br1/lib')
+
+ # move from trunk to branch 'br1'
+ test_svnmover(repo_url, [
+ 'D /trunk/README',
+ 'D /trunk/lib',
+ 'A /branches/br1/README (from /trunk/README:4)',
+ 'A /branches/br1/subdir',
+ 'A /branches/br1/subdir/lib2 (from /trunk/lib:4)',
+ 'D /branches/br1/subdir/lib2/foo/y',
+ 'A /branches/br1/y2 (from /trunk/lib/foo/y:4)',
+ ],
+ # keeping same relpath
+ 'mv', 'trunk/README', 'branches/br1/README',
+ # with a move-within-branch and rename as well
+ 'mv', 'trunk/lib/foo/y', 'branches/br1/y2',
+ # dir with children, also renaming and moving within branch
+ 'mkdir', 'branches/br1/subdir',
+ 'mv', 'trunk/lib', 'branches/br1/subdir/lib2',
+ )
+
+# Exercise moves from one branch to another in the same family. 'svnmover'
+# executes these by branch-and-delete. In this test, there are existing
+# instances of the same elements in the target branch, which should be
+# overwritten.
+def move_to_related_branch_element_already_exists(sbox):
+ "move to related branch; element already exists"
+ sbox_build_svnmover(sbox, content=initial_content_in_trunk)
+ repo_url = sbox.repo_url
+
+ # branch
+ test_svnmover(repo_url, None,
+ 'branch', 'trunk', 'branches/br1')
+
+ # move to a branch where same element already exists: should overwrite
+ test_svnmover(repo_url, [
+ 'D /trunk/README',
+ 'D /branches/br1/README',
+ 'A /branches/br1/README2 (from /trunk/README:3)',
+ ],
+ # single file: element already exists, at different relpath
+ 'mv', 'trunk/README', 'branches/br1/README2')
+ test_svnmover(repo_url, [
+ 'D /trunk/lib',
+ 'D /branches/br1/lib',
+ 'A /branches/br1/lib2 (from /trunk/lib:4)',
+ ],
+ # dir: child elements already exist (at different relpaths)
+ 'mv', 'branches/br1/lib/foo/x', 'branches/br1/x2',
+ 'mv', 'trunk/lib', 'branches/br1/lib2')
+
######################################################################
@@ -557,6 +623,8 @@ test_list = [ None,
merges,
merge_edits_with_move,
simple_moves_within_a_branch,
+ move_to_related_branch,
+ move_to_related_branch_element_already_exists,
]
if __name__ == '__main__':