You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by pb...@apache.org on 2012/06/12 12:16:47 UTC

svn commit: r1349228 - /subversion/trunk/subversion/tests/cmdline/merge_symmetric_tests.py

Author: pburba
Date: Tue Jun 12 10:16:46 2012
New Revision: 1349228

URL: http://svn.apache.org/viewvc?rev=1349228&view=rev
Log:
New symmetric merge tests which cover some failing subtree merge use cases.

* subversion/tests/cmdline/merge_symmetric_tests.py
  (set_up_branch): Import.

  (Merging scenarios to test): Add some new diagrams to the global comments.
 
  (subtree_to_and_fro,
   merge_to_reverse_cherry_subtree_to_merge_to): New.

  (test_list): Add subtree_to_and_fro and
   merge_to_reverse_cherry_subtree_to_merge_to.

Modified:
    subversion/trunk/subversion/tests/cmdline/merge_symmetric_tests.py

Modified: subversion/trunk/subversion/tests/cmdline/merge_symmetric_tests.py
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/tests/cmdline/merge_symmetric_tests.py?rev=1349228&r1=1349227&r2=1349228&view=diff
==============================================================================
--- subversion/trunk/subversion/tests/cmdline/merge_symmetric_tests.py (original)
+++ subversion/trunk/subversion/tests/cmdline/merge_symmetric_tests.py Tue Jun 12 10:16:46 2012
@@ -46,6 +46,7 @@ from svntest.main import server_has_merg
 from merge_tests import local_path
 from merge_tests import expected_merge_output
 from merge_tests import svn_merge
+from merge_tests import set_up_branch
 
 #----------------------------------------------------------------------
 
@@ -127,7 +128,17 @@ from merge_tests import svn_merge
 #
 #   Subtree mergeinfo
 #
-#     ...
+#     subtree to, fro
+#     A (--o-o-o-o---------x
+#       ( \         \     /
+#       (  \         \   /
+#     B (   o--o------s--
+#
+#     merge to, reverse cherry subtree to, merge to
+#     A (--o-o-o-o------------------
+#       ( \         \        \     \
+#       (  \         \        \     \
+#     B (   o--o------x-------rcs----x
 #
 #   Sparse WC
 #
@@ -142,9 +153,11 @@ from merge_tests import svn_merge
 #
 #   o   - an original change
 #   ?   - an original change or no-op (test both)
-#   x   - a merge
+#   x   - a branch root merge
 #   c   - a cherry-pick merge
 #   [o] - source range of a cherry-pick merge
+#   s   - a subtree merge
+#   r   - reverse merge
 
 
 ########################################################################
@@ -737,6 +750,241 @@ def cherry3_fwd(sbox):
                   expect_mi=[7, 8, 9],
                   expect_3ways=[three_way_merge('A8', 'A9')])
 
+#----------------------------------------------------------------------
+# Symmetric merges ignore subtree mergeinfo during reintegrate.
+@SkipUnless(server_has_mergeinfo)
+def subtree_to_and_fro(sbox):
+  "reintegrate ignores source subtree mergeinfo"
+
+#     A (--o-o-o-o---------x
+#       ( \         \     /
+#       (  \         \   /
+#     B (   o--o------s--
+
+  # Some paths we'll care about.
+  A_COPY_gamma_path = sbox.ospath('A_COPY/D/gamma')
+  psi_path = sbox.ospath('A/D/H/psi')
+  A_COPY_D_path = sbox.ospath('A_COPY/D')
+  A_path = sbox.ospath('A')
+
+  sbox.build()
+  wc_dir = sbox.wc_dir
+
+  # Setup a simple 'trunk & branch': Copy ^/A to ^/A_COPY in r2 and then
+  # make a few edits under A in r3-6:
+  wc_disk, wc_status = set_up_branch(sbox)
+
+  # r7 - Edit a file on the branch.
+  svntest.main.file_write(A_COPY_gamma_path, "Branch edit to 'gamma'.\n")
+  svntest.actions.run_and_verify_svn(None, None, [], 'ci', wc_dir,
+                                     '-m', 'Edit a file on our branch')
+
+  # r8 - Do a subtree sync merge from ^/A/D to A_COPY/D.
+  # Note that among other things this changes A_COPY/D/H/psi.
+  svntest.actions.run_and_verify_svn(None, None, [], 'up', wc_dir)
+  svntest.actions.run_and_verify_svn(None, None, [], 'merge', '--symmetric',
+                                     sbox.repo_url + '/A/D', A_COPY_D_path)
+
+  # r9 - Make an edit to A/D/H/psi.
+  svntest.main.file_write(psi_path, "Trunk Edit to 'psi'.\n")
+  svntest.actions.run_and_verify_svn(None, None, [], 'ci', wc_dir,
+                                     '-m', 'Edit a file on our trunk')
+
+  # Now reintegrate ^/A_COPY back to A.  To the symmetric merge code the
+  # subtree merge to A_COPY/D just looks like any other branch edit, it is
+  # not considered a merge.  So the changes which exist on A/D and were
+  # merged to A_COPY/D, are merged *back* to A, resulting in a conflict:
+  #
+  #   C:\SVN\src-trunk\Debug\subversion\tests\cmdline\svn-test-work\
+  #     working_copies\merge_symmetric_tests-18>svn merge ^^/A_COPY A
+  #     --symmetric
+  #   DBG: merge.c:11461: base on source: file:///C:/SVN/src-trunk/Debug/
+  #     subversion/tests/cmdline/svn-test-work/repositories/
+  #     merge_symmetric_tests-18/A@1
+  #   DBG: merge.c:11462: base on target: file:///C:/SVN/src-trunk/Debug/
+  #     subversion/tests/cmdline/svn-test-work/repositories/
+  #     merge_symmetric_tests-18/A@1
+  #   DBG: merge.c:11567: yca   file:///C:/SVN/src-trunk/Debug/subversion/
+  #     tests/cmdline/svn-test-work/repositories/merge_symmetric_tests-18/A@1
+  #   DBG: merge.c:11568: base  file:///C:/SVN/src-trunk/Debug/subversion/
+  #     tests/cmdline/svn-test-work/repositories/merge_symmetric_tests-18/A@1
+  #   DBG: merge.c:11571: right file:///C:/SVN/src-trunk/Debug/subversion/
+  #     tests/cmdline/svn-test-work/repositories/merge_symmetric_tests-18/
+  #     A_COPY@8
+  #   Conflict discovered in file 'A\D\H\psi'.
+  #   Select: (p) postpone, (df) diff-full, (e) edit,
+  #           (mc) mine-conflict, (tc) theirs-conflict,
+  #           (s) show all options: p
+  #   --- Merging r2 through r8 into 'A':
+  #   C    A\D\H\psi
+  #   U    A\D\gamma
+  #   --- Recording mergeinfo for merge of r2 through r8 into 'A':
+  #    U   A
+  #   Summary of conflicts:
+  #     Text conflicts: 1
+  svntest.actions.run_and_verify_svn(None, None, [], 'up', wc_dir)
+  exit_code, out, err = svntest.actions.run_and_verify_svn(
+    None, [], svntest.verify.AnyOutput,
+    'merge', '--reintegrate', sbox.repo_url + '/A_COPY', A_path)
+
+  # The 'old' merge produced a warning that reintegrate could not be used.
+  # Not claiming this is perfect, but it's better(?) than a conflict:
+  svntest.verify.verify_outputs("Symmetric Reintegrate failed, but not "
+                                "in the way expected",
+                                err, None,
+                                "(svn: E195016: Reintegrate can only be used if "
+                                "revisions 2 through 8 were previously "
+                                "merged from .*/A to the reintegrate source, "
+                                "but this is not the case:\n)"
+                                "|(  A_COPY\n)"
+                                "|(    Missing ranges: /A:5\n)"
+                                "|(\n)"
+                                "|(.*apr_err.*)", # In case of debug build
+                                None,
+                                True) # Match *all* lines of stdout  
+
+#----------------------------------------------------------------------
+# Symmetric merges ignore subtree mergeinfo gaps older than the last rev
+# synced to the target root.
+@SkipUnless(server_has_mergeinfo)
+def merge_to_reverse_cherry_subtree_to_merge_to(sbox):
+  "sync merge ignores source subtree mergeinfo"
+
+  #   A (--o-o-o-o------------------
+  #     ( \         \        \     \
+  #     (  \         \        \     \
+  #   B (   o--o------x-------rc-----x
+
+  # Some paths we'll care about.
+  A_COPY_path = sbox.ospath('A_COPY')
+  A_COPY_B_path = sbox.ospath('A_COPY/B')
+  A_COPY_beta_path = sbox.ospath('A_COPY/B/E/beta')
+
+  sbox.build()
+  wc_dir = sbox.wc_dir
+
+  # Setup a simple 'trunk & branch': Copy ^/A to ^/A_COPY in r2 and then
+  # make a few edits under A in r3-6:
+  wc_disk, wc_status = set_up_branch(sbox)
+
+  # Sync merge ^/A to A_COPY, then reverse merge r5 from ^/A/B to A_COPY/B.
+  # This results in mergeinfo on the target which makes it appear that the
+  # branch is synced up to r6, but the subtree mergeinfo on A_COPY/B reveals
+  # that r5 has not been merged to that subtree:
+  #
+  #   Properties on 'A_COPY':
+  #     svn:mergeinfo
+  #       /A:2-6
+  #   Properties on 'A_COPY\B':
+  #     svn:mergeinfo
+  #       /A/B:2-4,6
+  svntest.actions.run_and_verify_svn(None, None, [], 'up', wc_dir)
+  svntest.actions.run_and_verify_svn(None, None, [], 'merge', '--symmetric',
+                                     sbox.repo_url + '/A', A_COPY_path)
+  svntest.actions.run_and_verify_svn(None, None, [], 'merge', '-c-5',
+                                     sbox.repo_url + '/A/B',
+                                     A_COPY_B_path)
+  svntest.actions.run_and_verify_svn(None, None, [], 'ci', wc_dir, '-m',
+                                     'sync merge and reverse subtree merge')
+
+  # Try a symmetric sync merge from ^/A to A_COPY.  Revision 5 should be
+  # merged to A_COPY/B as its subtree mergeinfo reveals that rev is missing,
+  # like so:
+  # 
+  #   >svn merge ^/A A_COPY
+  #   --- Merging r5 into 'A_COPY\B':
+  #   U    A_COPY\B\E\beta
+  #   --- Recording mergeinfo for merge of r5 through r7 into 'A_COPY':
+  #    U   A_COPY
+  #   --- Recording mergeinfo for merge of r5 through r7 into 'A_COPY\B':
+  #    U   A_COPY\B
+  #   --- Eliding mergeinfo from 'A_COPY\B':
+  #    U   A_COPY\B
+  #
+  # But the --symmetric merge ignores the subtree mergeinfo and considers
+  # only the mergeinfo on the target itself (and thus is a no-op but for
+  # the mergeinfo change on the root of the merge target):
+  #
+  #   >svn merge ^/A A_COPY --symmetric
+  #   --- Recording mergeinfo for merge of r7 into 'A_COPY':
+  #    U   A_COPY
+  #
+  #   >svn diff
+  #   Index: A_COPY
+  #   ===================================================================
+  #   --- A_COPY      (revision 7)
+  #   +++ A_COPY      (working copy)
+  #
+  #   Property changes on: A_COPY
+  #   ___________________________________________________________________
+  #   Modified: svn:mergeinfo
+  #      Merged /A:r7
+  svntest.actions.run_and_verify_svn(None, None, [], 'up', wc_dir)
+  expected_output = wc.State(A_COPY_path, {
+    'B/E/beta'   : Item(status='U '),
+    })
+  expected_mergeinfo_output = wc.State(A_COPY_path, {
+    ''  : Item(status=' U'),
+    'B' : Item(status=' U'),
+    })
+  expected_elision_output = wc.State(A_COPY_path, {
+    'B' : Item(status=' U'),
+    })
+  expected_status = wc.State(A_COPY_path, {
+    ''           : Item(status=' M'),
+    'B'          : Item(status=' M'),
+    'mu'         : Item(status='  '),
+    'B/E'        : Item(status='  '),
+    'B/E/alpha'  : Item(status='  '),
+    'B/E/beta'   : Item(status='M '),
+    'B/lambda'   : Item(status='  '),
+    'B/F'        : Item(status='  '),
+    'C'          : Item(status='  '),
+    'D'          : Item(status='  '),
+    'D/G'        : Item(status='  '),
+    'D/G/pi'     : Item(status='  '),
+    'D/G/rho'    : Item(status='  '),
+    'D/G/tau'    : Item(status='  '),
+    'D/gamma'    : Item(status='  '),
+    'D/H'        : Item(status='  '),
+    'D/H/chi'    : Item(status='  '),
+    'D/H/psi'    : Item(status='  '),
+    'D/H/omega'  : Item(status='  '),
+    })
+  expected_status.tweak(wc_rev='7')
+  expected_disk = wc.State('', {
+    ''           : Item(props={SVN_PROP_MERGEINFO : '/A:2-7'}),
+    'B'          : Item(),
+    'mu'         : Item("This is the file 'mu'.\n"),
+    'B/E'        : Item(),
+    'B/E/alpha'  : Item("This is the file 'alpha'.\n"),
+    'B/E/beta'   : Item("New content"),
+    'B/lambda'   : Item("This is the file 'lambda'.\n"),
+    'B/F'        : Item(),
+    'C'          : Item(),
+    'D'          : Item(),
+    'D/G'        : Item(),
+    'D/G/pi'     : Item("This is the file 'pi'.\n"),
+    'D/G/rho'    : Item("New content"),
+    'D/G/tau'    : Item("This is the file 'tau'.\n"),
+    'D/gamma'    : Item("This is the file 'gamma'.\n"),
+    'D/H'        : Item(),
+    'D/H/chi'    : Item("This is the file 'chi'.\n"),
+    'D/H/psi'    : Item("New content"),
+    'D/H/omega'  : Item("New content"),
+    })
+  expected_skip = wc.State(A_COPY_path, { })
+  svntest.actions.run_and_verify_merge(A_COPY_path, None, None,
+                                       sbox.repo_url + '/A', None,
+                                       expected_output,
+                                       expected_mergeinfo_output,
+                                       expected_elision_output,
+                                       expected_disk,
+                                       expected_status,
+                                       expected_skip,
+                                       None, None, None, None,
+                                       None, 1, 0, '--symmetric', A_COPY_path)
+
 ########################################################################
 # Run the tests
 
@@ -760,6 +1008,8 @@ test_list = [ None,
               cherry1_fwd,
               cherry2_fwd,
               cherry3_fwd,
+              subtree_to_and_fro,
+              merge_to_reverse_cherry_subtree_to_merge_to,
              ]
 
 if __name__ == '__main__':