Author: julianfoad
Date: Thu Apr 16 09:27:18 2015
New Revision: 1674030

URL: http://svn.apache.org/r1674030
Log:
On the 'move-tracking-2' branch: Implement merging of subbranches (just for
edit-vs-edit cases, so far), and add a test that merges subbranches.

* subversion/svnmover/svnmover.c
  (merge_subbranch): New.
  (branch_merge_subtree_r): Merge subbranches. Notify start and end of
    merging this branch. Simplify a bit of notification code.

* subversion/tests/cmdline/svnmover_tests.py
  (subbranches1): New test.
  (test_list): Run it.

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=1674030&r1=1674029&r2=1674030&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/svnmover/svnmover.c 
(original)
+++ subversion/branches/move-tracking-2/subversion/svnmover/svnmover.c Thu Apr 
16 09:27:18 2015
@@ -659,6 +659,80 @@ element_merge(svn_branch_el_rev_content_
   *conflict_p = conflict;
 }
 
+static svn_error_t *
+branch_merge_subtree_r(svn_editor3_t *editor,
+                       const svn_branch_el_rev_id_t *src,
+                       const svn_branch_el_rev_id_t *tgt,
+                       const svn_branch_el_rev_id_t *yca,
+                       apr_pool_t *scratch_pool);
+
+/* Merge the subbranch of {SRC, TGT, YCA} found at EID.
+ */
+static svn_error_t *
+merge_subbranch(svn_editor3_t *editor,
+                const svn_branch_el_rev_id_t *src,
+                const svn_branch_el_rev_id_t *tgt,
+                const svn_branch_el_rev_id_t *yca,
+                int eid,
+                apr_pool_t *scratch_pool)
+{
+  svn_branch_instance_t *src_subbranch
+    = svn_branch_get_subbranch_at_eid(src->branch, eid, scratch_pool);
+  svn_branch_instance_t *tgt_subbranch
+    = svn_branch_get_subbranch_at_eid(tgt->branch, eid, scratch_pool);
+  svn_branch_instance_t *yca_subbranch
+    = svn_branch_get_subbranch_at_eid(yca->branch, eid, scratch_pool);
+  svn_branch_el_rev_id_t *subbr_src = NULL;
+  svn_branch_el_rev_id_t *subbr_tgt = NULL;
+  svn_branch_el_rev_id_t *subbr_yca = NULL;
+
+  if (src_subbranch)
+    subbr_src = svn_branch_el_rev_id_create(
+                  src_subbranch, src_subbranch->sibling_defn->root_eid,
+                  src->rev, scratch_pool);
+  if (tgt_subbranch)
+    subbr_tgt = svn_branch_el_rev_id_create(
+                  tgt_subbranch, tgt_subbranch->sibling_defn->root_eid,
+                  tgt->rev, scratch_pool);
+  if (yca_subbranch)
+    subbr_yca = svn_branch_el_rev_id_create(
+                  yca_subbranch, yca_subbranch->sibling_defn->root_eid,
+                  yca->rev, scratch_pool);
+
+  if (subbr_src && subbr_tgt && subbr_yca)  /* ?edit vs. ?edit */
+    {
+      /* subbranch possibly changed in source => merge */
+      SVN_ERR(branch_merge_subtree_r(editor, subbr_src, subbr_tgt, subbr_yca,
+                                     scratch_pool));
+    }
+  else if (subbr_src && subbr_yca)  /* ?edit vs. delete */
+    {
+      /* ### possible conflict (edit vs. delete) */
+    }
+  else if (subbr_tgt && subbr_yca)  /* delete vs. ?edit */
+    {
+      /* ### possible conflict (delete vs. edit) */
+    }
+  else if (subbr_src && subbr_tgt)  /* double add */
+    {
+      /* ### conflict */
+    }
+  else if (subbr_src)  /* added on source branch */
+    {
+      /* ### add it on target */
+    }
+  else if (subbr_tgt)  /* added on target branch */
+    {
+      /* nothing to do */
+    }
+  else if (subbr_yca)  /* double delete */
+    {
+      /* ### conflict? policy option? */
+    }
+
+  return SVN_NO_ERROR;
+}
+
 /* Merge ...
  *
  * Merge any sub-branches in the same way, recursively.
@@ -688,6 +762,8 @@ branch_merge_subtree_r(svn_editor3_t *ed
            yca->rev,
            yca->branch->sibling_defn->bsid, yca->eid));
 
+  notify("merging into branch %s",
+         svn_branch_instance_get_id(tgt->branch, scratch_pool));
   /*
       for (eid, diff1) in element_differences(YCA, FROM):
         diff2 = element_diff(eid, YCA, TO)
@@ -729,6 +805,9 @@ branch_merge_subtree_r(svn_editor3_t *ed
          TGT, YCA) exists, but we choose to skip it when SRC == YCA. */
       if (! e_yca_src)
         {
+          /* Still may need to merge a subbranch here */
+          SVN_ERR(merge_subbranch(editor, src, tgt, yca, eid, scratch_pool));
+
           continue;
         }
 
@@ -755,6 +834,8 @@ branch_merge_subtree_r(svn_editor3_t *ed
           SVN_ERR(svn_editor3_alter(editor, tgt->rev, tgt->branch, eid,
                                     result->parent_eid, result->name,
                                     result->content));
+
+          SVN_ERR(merge_subbranch(editor, src, tgt, yca, eid, scratch_pool));
         }
       else if (e_tgt)
         {
@@ -768,12 +849,9 @@ branch_merge_subtree_r(svn_editor3_t *ed
           svn_branch_instance_t *subbranch
             = svn_branch_get_subbranch_at_eid(src->branch, eid, scratch_pool);
 
-          if (subbranch)
-            notify("A    e%d %s%s",
-                   eid, result->name,
-                   subbranch_str(src->branch, eid, scratch_pool));
-          else
-            notify("A    e%d %s", eid, result->name);
+          notify("A    e%d %s%s",
+                 eid, result->name,
+                 subbranch_str(src->branch, eid, scratch_pool));
 
           /* In BRANCH, create an instance of the element EID with new content.
            *
@@ -798,6 +876,9 @@ branch_merge_subtree_r(svn_editor3_t *ed
         }
     }
 
+  notify("merging into branch %s -- finished",
+         svn_branch_instance_get_id(tgt->branch, scratch_pool));
+
   if (had_conflict)
     {
       return svn_error_createf(SVN_ERR_BRANCHING, NULL,
@@ -808,8 +889,6 @@ branch_merge_subtree_r(svn_editor3_t *ed
       SVN_DBG(("merge completed: no conflicts"));
     }
 
-  /* ### TODO: subbranches */
-
   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=1674030&r1=1674029&r2=1674030&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 
Thu Apr 16 09:27:18 2015
@@ -992,6 +992,52 @@ def restructure_repo_projects_ttb_to_ttb
   ### It's all very well to see that the dirs and files now appear at the
   ### right places, but what should we test to ensure the history is intact?
 
+# Brane's example on IRC 2015-04-14
+# "e.g., in our tree, libsvn_fs_x is a branch of libsvn_fs_fs; are we still
+# allowed to merge branches/foo to trunk, and will the merge correctly reflect
+# changes in these two sub-branches, and will a subsequent merge from fs_fs to
+# fs_x produce sane results?"
+def subbranches1(sbox):
+  "subbranches1"
+  sbox_build_svnmover(sbox, content=initial_content_in_trunk)
+  repo_url = sbox.repo_url
+  head = 1
+
+  # create content in a trunk subtree 'libsvn_fs_fs'
+  test_svnmover2(sbox, 'trunk', None,
+                 'mv lib libsvn_fs_fs',
+                 'put', mk_file(sbox, 'file.c'), 'libsvn_fs_fs/file.c')
+  # branch 'trunk/libsvn_fs_fs' to 'trunk/libsvn_fs_x'
+  test_svnmover2(sbox, 'trunk', None,
+                 'branch libsvn_fs_fs libsvn_fs_x')
+  # branch 'trunk' to 'branches/foo'
+  test_svnmover2(sbox, '', None,
+                 'branch trunk branches/foo')
+
+  # make edits in 'branches/foo' and its subbranch
+  test_svnmover2(sbox, 'branches/foo', None,
+                 'mkdir docs',
+                 'mv libsvn_fs_fs/file.c libsvn_fs_fs/file2.c')
+  test_svnmover2(sbox, 'branches/foo/libsvn_fs_x', None,
+                 'mkdir reps',
+                 'mv file.c reps/file.c')
+
+  # merge 'branches/foo' to 'trunk'
+  test_svnmover2(sbox, '',
+                 reported_br_diff('trunk', 'trunk') +
+                 reported_add('docs') +
+                 reported_move('libsvn_fs_fs/file.c', 'libsvn_fs_fs/file2.c') +
+                 reported_br_diff('trunk/libsvn_fs_x', 'trunk/libsvn_fs_x') +
+                 reported_add('reps') +
+                 reported_move('file.c', 'reps/file.c'),
+                 'merge branches/foo trunk trunk@4')
+
+  # merge 'trunk/libsvn_fs_fs' to 'trunk/libsvn_fs_x'
+  test_svnmover2(sbox, '',
+                 reported_br_diff('trunk/libsvn_fs_x', 'trunk/libsvn_fs_x') +
+                 reported_move('reps/file.c', 'reps/file2.c'),
+                 'merge trunk/libsvn_fs_fs trunk/libsvn_fs_x 
trunk/libsvn_fs_fs@4')
+
 
 ######################################################################
 
@@ -1007,6 +1053,7 @@ test_list = [ None,
               move_branch_within_same_parent_branch,
               restructure_repo_ttb_projects_to_projects_ttb,
               restructure_repo_projects_ttb_to_ttb_projects,
+              subbranches1,
             ]
 
 if __name__ == '__main__':


Reply via email to