You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by st...@apache.org on 2011/10/11 21:52:46 UTC

svn commit: r1182053 [27/30] - in /subversion/branches/svn_mutex: ./ build/ build/ac-macros/ build/generator/ build/generator/swig/ build/generator/templates/ contrib/client-side/ contrib/hook-scripts/enforcer/ contrib/server-side/ notes/ notes/merge-t...

Modified: subversion/branches/svn_mutex/subversion/tests/cmdline/merge_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/svn_mutex/subversion/tests/cmdline/merge_tests.py?rev=1182053&r1=1182052&r2=1182053&view=diff
==============================================================================
--- subversion/branches/svn_mutex/subversion/tests/cmdline/merge_tests.py (original)
+++ subversion/branches/svn_mutex/subversion/tests/cmdline/merge_tests.py Tue Oct 11 19:52:34 2011
@@ -2439,7 +2439,7 @@ def set_up_dir_replace(sbox):
 # A merge that replaces a directory
 # Tests for Issue #2144 and Issue #2607
 @SkipUnless(server_has_mergeinfo)
-@Issue(2144)
+@Issue(2144,2607)
 def merge_dir_replace(sbox):
   "merge a replacement of a directory"
 
@@ -7482,7 +7482,6 @@ def merge_away_subtrees_noninheritable_r
   #
   # First revert all local changes and remove A_COPY/C/nu from disk.
   svntest.actions.run_and_verify_svn(None, None, [], 'revert', '-R', wc_dir)
-  os.remove(os.path.join(wc_dir, "A_COPY", "nu"))
 
   # Make a text change to A_COPY_2/mu in r11 and then merge that
   # change to A/mu in r12.  This will create mergeinfo of '/A_COPY_2/mu:11'
@@ -7682,7 +7681,7 @@ def merge_away_subtrees_noninheritable_r
   expected_output = svntest.verify.UnorderedOutput(
       [A_COPY_path  + ' - /A:2-13*\n',
        mu_COPY_path + ' - /A/mu:2-13\n',
-       nu_COPY_path + ' - /A/nu:2-13\n',])
+       nu_COPY_path + ' - /A/nu:10-13\n',])
   svntest.actions.run_and_verify_svn(None,
                                      expected_output,
                                      [], 'pg', SVN_PROP_MERGEINFO,
@@ -9309,6 +9308,7 @@ def ignore_ancestry_and_mergeinfo(sbox):
 
 #----------------------------------------------------------------------
 @SkipUnless(server_has_mergeinfo)
+@Issue(3032)
 def merge_from_renamed_branch_fails_while_avoiding_repeat_merge(sbox):
   "merge from renamed branch"
   #Copy A/C to A/COPY_C results in r2.
@@ -9694,7 +9694,7 @@ def new_subtrees_should_not_break_merge(
     'D/H/psi'   : Item("This is the file 'psi'.\n"),
     'D/H/omega' : Item("New content"),
     'D/H/nu'    : Item("New content",
-                       props={SVN_PROP_MERGEINFO : '/A/D/H/nu:8'}),
+                       props={SVN_PROP_MERGEINFO : '/A/D/H/nu:7-8'}),
     })
   expected_skip = wc.State(A_COPY_path, { })
   svntest.actions.run_and_verify_merge(A_COPY_path, '4', '6',
@@ -9740,7 +9740,7 @@ def new_subtrees_should_not_break_merge(
     'H/psi'   : Item("This is the file 'psi'.\n"),
     'H/omega' : Item("This is the file 'omega'.\n"),
     'H/nu'    : Item("New content",
-                     props={SVN_PROP_MERGEINFO : '/A/D/H/nu:8'}),
+                     props={SVN_PROP_MERGEINFO : '/A/D/H/nu:7-8'}),
     })
   expected_skip = wc.State(D_COPY_path, { })
   svntest.actions.run_and_verify_merge(D_COPY_path, '6', '5',
@@ -9812,7 +9812,7 @@ def new_subtrees_should_not_break_merge(
     'D/H/psi'   : Item("This is the file 'psi'.\n"),
     'D/H/omega' : Item("New content"),
     'D/H/nu'    : Item("New content",
-                       props={SVN_PROP_MERGEINFO : '/A/D/H/nu:8'}),
+                       props={SVN_PROP_MERGEINFO : '/A/D/H/nu:7-8'}),
     })
   expected_skip = wc.State(A_COPY_path, { })
   svntest.actions.run_and_verify_merge(A_COPY_path, '5', '6',
@@ -11583,24 +11583,7 @@ def dont_explicitly_record_implicit_merg
   svntest.actions.run_and_verify_svn(None, None, [], 'up', wc_dir)
   wc_status.tweak(wc_rev=10)
 
-  # Now do a cherry harvest merge to 'A_copy'.  We should pick up the
-  # change to 'A_copy/D/H/nu' from r10, the mergeinfo on 'A_copy' should
-  # reflect the entire eligible revision range from 'A', r2-10.
-  # 'A_copy/D/H/nu' should have get the equivalent mergeinfo to 'A_copy'
-  # which should elide to the latter, leaving no explicit mergeinfo...
-  #
-  # ...or should it?  For the mergeinfo on ' A_copy/D/H/nu' to elide, it
-  # needs mergeinfo '/A/D/H/nu:2-10', but 'A/D/H/nu' doesn't exist prior to
-  # r6...Anyhow, regardless of what the mergeinfo on ' A_copy/D/H/nu' should
-  # be prior to elision, if we have the following conditions:
-  #
-  #   1) A uniform working revision merge target.
-  #
-  #   2) Explicit mergeinfo on the target/subtrees from the same
-  #      source ('A' in this case).
-  #
-  # Then a cherry harvest from the same source should leave explicit
-  # mergeinfo *only* on the merge target no?
+  # Now do a cherry harvest merge to 'A_copy'.
   expected_output = wc.State(A_copy_path, {
     'D/H/nu' : Item(status='U '),
     })
@@ -11609,7 +11592,6 @@ def dont_explicitly_record_implicit_merg
     'D/H/nu' : Item(status=' U'),
     })
   expected_elision_output = wc.State(A_copy_path, {
-    'D/H/nu' : Item(status=' U'),
     })
   expected_A_copy_status = wc.State(A_copy_path, {
     ''          : Item(status=' M', wc_rev=10),
@@ -11653,7 +11635,8 @@ def dont_explicitly_record_implicit_merg
     'D/H/chi'   : Item("This is the file 'chi'.\n"),
     'D/H/psi'   : Item("This is the file 'psi'.\n"),
     'D/H/omega' : Item("This is the file 'omega'.\n"),
-    'D/H/nu'    : Item("Even nuer content"),
+    'D/H/nu'    : Item("Even nuer content",
+                       props={SVN_PROP_MERGEINFO : '/A/D/H/nu:6-10'}),
     })
   expected_A_copy_skip = wc.State(A_copy_path, {})
   svntest.actions.run_and_verify_merge(A_copy_path, None, None,
@@ -12023,7 +12006,7 @@ def subtree_source_missing_in_requested_
   sbox.build()
   wc_dir = sbox.wc_dir
 
-  # Make a branche to merge to.
+  # Make a branch to merge to.
   wc_disk, wc_status = set_up_branch(sbox, False, 1)
 
   # Some paths we'll care about.
@@ -12033,16 +12016,14 @@ def subtree_source_missing_in_requested_
   psi_COPY_path   = os.path.join(wc_dir, "A_COPY", "D", "H", "psi")
   omega_COPY_path = os.path.join(wc_dir, "A_COPY", "D", "H", "omega")
 
-  # r7 Delete a A/D/H/psi.
+  # r7 Delete A/D/H/psi.
   svntest.actions.run_and_verify_svn(None, None, [],
                                      'delete', psi_path)
-  svntest.actions.run_and_verify_svn(None, None, [],
-                                     'ci', '-m', 'delete psi', wc_dir)
+  sbox.simple_commit(message='delete psi')
 
   # r8 - modify A/D/H/omega.
   svntest.main.file_write(os.path.join(omega_path), "Even newer content")
-  svntest.actions.run_and_verify_svn(None, None, [],
-                                     'ci', '-m', 'modify omega', wc_dir)
+  sbox.simple_commit(message='modify omega')
 
   # r9 - Merge r3 to A_COPY/D/H/psi
   expected_output = expected_merge_output(
@@ -12052,9 +12033,7 @@ def subtree_source_missing_in_requested_
                                      'merge', '-c', '3',
                                      sbox.repo_url + '/A/D/H/psi@3',
                                      psi_COPY_path)
-  svntest.actions.run_and_verify_svn(None, None, [],
-                                     'ci', '-m', 'merge r3 to A_COPY/D/H/psi',
-                                     wc_dir)
+  sbox.simple_commit(message='merge r3 to A_COPY/D/H/psi')
 
   # r10 - Merge r6 to A_COPY/D/H/omega.
   expected_output = expected_merge_output(
@@ -12064,9 +12043,7 @@ def subtree_source_missing_in_requested_
                                      'merge', '-c', '6',
                                      sbox.repo_url + '/A/D/H/omega',
                                      omega_COPY_path)
-  svntest.actions.run_and_verify_svn(None, None, [], 'ci', '-m',
-                                     'merge r6 to A_COPY',
-                                     wc_dir)
+  sbox.simple_commit(message='merge r6 to A_COPY')
   svntest.actions.run_and_verify_svn(None, exp_noop_up_out(10), [], 'up',
                                      wc_dir)
 
@@ -12093,17 +12070,14 @@ def subtree_source_missing_in_requested_
                                      'merge', '-c', '8',
                                      sbox.repo_url + '/A',
                                      A_COPY_path, '--record-only')
-  svntest.actions.run_and_verify_svn(None, None, [], 'ci', '-m',
-                                     'merge r8 to A_COPY/D/H/omega',
-                                     wc_dir)
+  sbox.simple_commit(message='merge r8 to A_COPY/D/H/omega')
   svntest.actions.run_and_verify_svn(None, exp_noop_up_out(11), [], 'up',
                                      wc_dir)
 
   # r12 - modify A/D/H/omega yet again.
   svntest.main.file_write(os.path.join(omega_path),
                           "Now with fabulous new content!")
-  svntest.actions.run_and_verify_svn(None, None, [],
-                                     'ci', '-m', 'modify omega', wc_dir)
+  sbox.simple_commit(message='modify omega')
 
   # r13 - Merge all available revs to A_COPY/D/H/omega.
   expected_output = expected_merge_output(
@@ -12113,9 +12087,7 @@ def subtree_source_missing_in_requested_
                                      'merge',
                                      sbox.repo_url + '/A/D/H/omega',
                                      omega_COPY_path)
-  svntest.actions.run_and_verify_svn(None, None, [], 'ci', '-m',
-                                     'cherry harvest to A_COPY/D/H/omega',
-                                     wc_dir)
+  sbox.simple_commit(message='cherry harvest to A_COPY/D/H/omega')
   svntest.actions.run_and_verify_svn(None, exp_noop_up_out(13), [], 'up',
                                      wc_dir)
 
@@ -12276,9 +12248,7 @@ def subtree_source_missing_in_requested_
                                      'merge', '-c', '12',
                                      sbox.repo_url + '/A',
                                      A_COPY_path, '--record-only')
-  svntest.actions.run_and_verify_svn(None, None, [], 'ci', '-m',
-                                     'Merge r12 to A_COPY',
-                                     wc_dir)
+  sbox.simple_commit(message='Merge r12 to A_COPY')
 
   # Update A_COPY/D/H/rho back to r13 so it's mergeinfo doesn't include
   # r12.  Then merge a range, -r6:12 which should delete a subtree
@@ -12921,12 +12891,6 @@ def merge_target_and_subtrees_need_nonin
     None, expected_merge_output([[8]], ['U    ' + nu_COPY_path    + '\n',
                                         ' G   ' + nu_COPY_path    + '\n']),
     [], 'merge', '-c8', sbox.repo_url + '/A/D/G/nu', nu_COPY_path)
-  # Replicate pre 1.7 merge behavior where self-referential mergeinfo
-  # could be inherited, this keeps the original intent of this test intact,
-  # see http://subversion.tigris.org/issues/show_bug.cgi?id=3669#desc8
-  svntest.actions.run_and_verify_svn(None, None, [], 'ps',
-                                     SVN_PROP_MERGEINFO, '/A/D/G/nu:2-8',
-                                     nu_COPY_path)
 
   svntest.actions.run_and_verify_svn(
     None, expected_merge_output([[-6]], ['G    ' + omega_COPY_path    + '\n',
@@ -13759,14 +13723,12 @@ def subtree_gets_changes_even_if_ultimat
 
   # r7: Make an additional text mod to A/D/H/psi.
   svntest.main.file_write(psi_path, "Even newer content")
-  svntest.actions.run_and_verify_svn(None, None, [],
-                                     'ci', '-m', 'mod psi', wc_dir)
+  sbox.simple_commit(message='mod psi')
 
   # r8: Delete A/D/H/psi.
   svntest.actions.run_and_verify_svn(None, None, [],
                                      'delete', psi_path)
-  svntest.actions.run_and_verify_svn(None, None, [],
-                                     'ci', '-m', 'delete psi', wc_dir)
+  sbox.simple_commit(message='delete psi')
 
   # Update WC before merging so mergeinfo elision and inheritance
   # occur smoothly.
@@ -13812,11 +13774,8 @@ def subtree_gets_changes_even_if_ultimat
                           ['G    ' + psi_COPY_path + '\n',
                            ' G   ' + psi_COPY_path + '\n',]),
     [], 'merge', '-c-7', sbox.repo_url + '/A/D/H/psi@7', psi_COPY_path)
-  svntest.actions.run_and_verify_svn(None, None, [],
-                                     'ci', '-m',
-                                     'merge -c3,7 from A/D/H,' \
-                                     'reverse merge -c-7 from A/D/H/psi',
-                                     wc_dir)
+  sbox.simple_commit(message='merge -c3,7 from A/D/H,' \
+                             'reverse merge -c-7 from A/D/H/psi')
 
   # Merge all available revisions from A/D/H to A_COPY/D/H.  This merge
   # ultimately tries to delete A_COPY/D/H/psi, but first it should merge
@@ -13976,7 +13935,7 @@ def no_self_referential_filtering_on_add
     'B/E/beta'  : Item("New content"),
     'B/lambda'  : Item("This is the file 'lambda'.\n"),
     'B/F'       : Item(),
-    'C_MOVED'   : Item(props={SVN_PROP_MERGEINFO : '/A/C_MOVED:3-10\n' +
+    'C_MOVED'   : Item(props={SVN_PROP_MERGEINFO : '/A/C_MOVED:10\n' +
                               '/A_COPY/C:8\n' +
                               '/A_COPY/C_MOVED:8',
                               'propname' : 'propval'}),
@@ -16278,7 +16237,8 @@ def merge_with_os_deleted_subtrees(sbox)
 # Test for issue #3668 'inheritance can result in self-referential
 # mergeinfo' and issue #3669 'inheritance can result in mergeinfo
 # describing nonexistent sources'
-@Issue(3668)
+@Issue(3668,3669)
+@XFail()
 def no_self_referential_or_nonexistent_inherited_mergeinfo(sbox):
   "don't inherit bogus mergeinfo"
 
@@ -16339,6 +16299,10 @@ def no_self_referential_or_nonexistent_i
   # Update the WC in preparation for merges.
   svntest.actions.run_and_verify_svn(None, None, [], 'up', wc_dir)
 
+  # This test is marked as XFail because the following two merges
+  # create mergeinfo with both non-existent path-revs and self-referential
+  # mergeinfo.
+  #
   # Merge all available revisions from A/C/nu to A_COPY/C/nu.
   # The target has no explicit mergeinfo of its own but inherits mergeinfo
   # from A_COPY.  A_COPY has the mergeinfo '/A:2-9' so the naive mergeinfo
@@ -16727,6 +16691,426 @@ def foreign_repos_prop_conflict(sbox):
                                      sbox.repo_url,
                                      other_wc_dir)
 
+#----------------------------------------------------------------------
+# Test for issue #3975 'adds with explicit mergeinfo don't get mergeinfo
+# describing merge which added them'
+@Issue(3975)
+@SkipUnless(server_has_mergeinfo)
+def merge_adds_subtree_with_mergeinfo(sbox):
+  "merge adds subtree with mergeinfo"
+
+  sbox.build()
+  wc_dir = sbox.wc_dir
+  wc_disk, wc_status = set_up_branch(sbox, False, 2)
+
+  A_path       = os.path.join(wc_dir, 'A')
+  nu_path      = os.path.join(wc_dir, 'A', 'C', 'nu')
+  nu_COPY_path = os.path.join(wc_dir, 'A_COPY', 'C', 'nu')
+  A_COPY2_path = os.path.join(wc_dir, 'A_COPY_2')
+
+  # r8 - Add the file A_COPY/C/nu.
+  svntest.main.file_write(nu_COPY_path, "This is the file 'nu'.\n")
+  svntest.actions.run_and_verify_svn(None, None, [], 'add', nu_COPY_path)
+  svntest.actions.run_and_verify_svn(None, None, [], 'ci', '-m',
+                                     'Add a file on the A_COPY branch',
+                                     wc_dir)
+
+  # r9 - Cherry pick r8 from A_COPY to A.
+  svntest.actions.run_and_verify_svn(None, None, [], 'up', wc_dir)
+  svntest.actions.run_and_verify_svn(None, None, [], 'merge',
+                                     sbox.repo_url + '/A_COPY',
+                                     A_path, '-c8')
+  svntest.actions.run_and_verify_svn(None, None, [], 'ci', '-m',
+                                     'Merge r8 from A_COPY to A', wc_dir)
+
+  # r10 - Make a modification to A_COPY/C/nu
+  svntest.main.file_append(nu_COPY_path,
+                           "More work on the A_COPY branch.\n")
+  svntest.actions.run_and_verify_svn(None, None, [], 'ci', '-m',
+                                     'Some work on the A_COPY branch', wc_dir)
+
+  # r9 - Cherry pick r10 from A_COPY/C/nu to A/C/nu.  Make some
+  # changes to A/C/nu before committing the merge.
+  svntest.actions.run_and_verify_svn(None, None, [], 'merge',
+                                     sbox.repo_url + '/A_COPY/C/nu',
+                                     nu_path, '-c10')
+  svntest.main.file_append(nu_path, "A faux conflict resolution.\n")
+  svntest.actions.run_and_verify_svn(None, None, [], 'ci', '-m',
+                                     'Merge r8 from A_COPY to A', wc_dir)
+
+  # Sync merge A to A_COPY_2
+  svntest.actions.run_and_verify_svn(None, None, [], 'up', wc_dir)
+  expected_output = wc.State(A_COPY2_path, {
+    'B/E/beta'  : Item(status='U '),
+    'C/nu'      : Item(status='A '),
+    'D/G/rho'   : Item(status='U '),
+    'D/H/omega' : Item(status='U '),
+    'D/H/psi'   : Item(status='U '),
+    ''          : Item(status=' U'),
+    })
+  expected_mergeinfo_output = wc.State(A_COPY2_path, {
+    ''     : Item(status=' G'),
+    'C/nu' : Item(status=' U'),
+    })
+  expected_elision_output = wc.State(A_COPY2_path, {
+    })
+  expected_status = wc.State(A_COPY2_path, {
+    ''          : Item(status=' M'),
+    'B'         : Item(status='  '),
+    '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='  '),
+    'C/nu'      : Item(status='A ', copied='+'),
+    'D'         : Item(status='  '),
+    'D/G'       : Item(status='  '),
+    'D/G/pi'    : Item(status='  '),
+    'D/G/rho'   : Item(status='M '),
+    'D/G/tau'   : Item(status='  '),
+    'D/gamma'   : Item(status='  '),
+    'D/H'       : Item(status='  '),
+    'D/H/chi'   : Item(status='  '),
+    'D/H/psi'   : Item(status='M '),
+    'D/H/omega' : Item(status='M '),
+    })
+  expected_status.tweak(wc_rev=11)
+  expected_status.tweak('C/nu', wc_rev='-')
+  expected_disk = wc.State('', {
+    ''          : Item(props={SVN_PROP_MERGEINFO : '/A:3-11\n/A_COPY:8'}),
+    '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(),
+    # C/nu will pick up the mergeinfo A_COPY/C/nu:8 which is self-referential.
+    # This is issue #3668 'inheritance can result in self-referential
+    # mergeinfo', but we'll allow it in this test since issue #3668 is
+    # tested elsewhere and is not the point of *this* test.
+    'C/nu'      : Item("This is the file 'nu'.\n" \
+                       "More work on the A_COPY branch.\n" \
+                       "A faux conflict resolution.\n",
+                       props={SVN_PROP_MERGEINFO :
+                              '/A/C/nu:9-11\n/A_COPY/C/nu:8,10'}),
+    '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('.', { })
+  svntest.actions.run_and_verify_merge(A_COPY2_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, False)
+
+#----------------------------------------------------------------------
+# A test for issue #3978 'reverse merge which adds subtree fails'.
+@Issue(3978)
+@SkipUnless(server_has_mergeinfo)
+def reverse_merge_adds_subtree(sbox):
+  "reverse merge adds subtree"
+
+  sbox.build()
+  wc_dir = sbox.wc_dir
+  wc_disk, wc_status = set_up_branch(sbox)
+
+  A_path       = os.path.join(wc_dir, 'A')
+  chi_path     = os.path.join(wc_dir, 'A', 'D', 'H', 'chi')
+  A_COPY_path  = os.path.join(wc_dir, 'A_COPY')
+  H_COPY_path  = os.path.join(wc_dir, 'A_COPY', 'D', 'H')
+
+  # r7 - Delete A\D\H\chi
+  svntest.actions.run_and_verify_svn(None, None, [], 'delete', chi_path)
+  svntest.actions.run_and_verify_svn(None, None, [], 'ci', '-m',
+                                     'Delete a file', wc_dir)
+
+  # r8 - Merge r7 from A to A_COPY
+  svntest.actions.run_and_verify_svn(None, None, [], 'merge',
+                                     sbox.repo_url + '/A',
+                                     A_COPY_path, '-c7')
+  svntest.actions.run_and_verify_svn(None, None, [], 'ci', '-m',
+                                     'Cherry-pick r7 from A to A_COPY', wc_dir)
+
+  # r9 - File depth sync merge from A/D/H to A_COPY/D/H/
+  svntest.actions.run_and_verify_svn(None, None, [], 'up', wc_dir)
+  svntest.actions.run_and_verify_svn(None, None, [], 'merge',
+                                     sbox.repo_url + '/A/D/H',
+                                     H_COPY_path, '--depth', 'files')
+  svntest.actions.run_and_verify_svn(None, None, [], 'ci', '-m',
+                                     'Cherry-pick r7 from A to A_COPY', wc_dir)
+
+  # Reverse merge r7 from A to A_COPY
+  #
+  # Prior to the issue #3978 fix this merge failed with an assertion:
+  #
+  # >svn merge ^/A A_COPY -c-7
+  # --- Reverse-merging r7 into 'A_COPY\D\H':
+  # A    A_COPY\D\H\chi
+  # --- Recording mergeinfo for reverse merge of r7 into 'A_COPY':
+  #  U   A_COPY
+  # --- Recording mergeinfo for reverse merge of r7 into 'A_COPY\D\H':
+  #  U   A_COPY\D\H
+  # ..\..\..\subversion\svn\util.c:913: (apr_err=200020)
+  # ..\..\..\subversion\libsvn_client\merge.c:10990: (apr_err=200020)
+  # ..\..\..\subversion\libsvn_client\merge.c:10944: (apr_err=200020)
+  # ..\..\..\subversion\libsvn_client\merge.c:10944: (apr_err=200020)
+  # ..\..\..\subversion\libsvn_client\merge.c:10914: (apr_err=200020)
+  # ..\..\..\subversion\libsvn_client\merge.c:8928: (apr_err=200020)
+  # ..\..\..\subversion\libsvn_client\merge.c:7850: (apr_err=200020)
+  # ..\..\..\subversion\libsvn_client\mergeinfo.c:120: (apr_err=200020)
+  # ..\..\..\subversion\libsvn_wc\props.c:2472: (apr_err=200020)
+  # ..\..\..\subversion\libsvn_wc\props.c:2247: (apr_err=200020)
+  # ..\..\..\subversion\libsvn_wc\props.c:2576: (apr_err=200020)
+  # ..\..\..\subversion\libsvn_subr\mergeinfo.c:705: (apr_err=200020)
+  # svn: E200020: Could not parse mergeinfo string '-7'
+  # ..\..\..\subversion\libsvn_subr\mergeinfo.c:688: (apr_err=200022)
+  # ..\..\..\subversion\libsvn_subr\mergeinfo.c:607: (apr_err=200022)
+  # ..\..\..\subversion\libsvn_subr\mergeinfo.c:504: (apr_err=200022)
+  # ..\..\..\subversion\libsvn_subr\kitchensink.c:57: (apr_err=200022)
+  # svn: E200022: Negative revision number found parsing '-7'
+  svntest.actions.run_and_verify_svn(None, None, [], 'up', wc_dir)
+  svntest.actions.run_and_verify_svn(None, None, [], 'up', wc_dir)
+  expected_output = wc.State(A_COPY_path, {
+    'D/H/chi' : Item(status='A '),
+    })
+  expected_mergeinfo_output = wc.State(A_COPY_path, {
+    ''    : Item(status=' U'),
+    'D/H' : Item(status=' U'),
+    })
+  expected_elision_output = wc.State(A_COPY_path, {
+    '' : Item(status=' U'),
+    })
+  expected_status = wc.State(A_COPY_path, {
+    ''          : Item(status=' M'),
+    'B'         : Item(status='  '),
+    'mu'        : Item(status='  '),
+    'B/E'       : Item(status='  '),
+    'B/E/alpha' : Item(status='  '),
+    'B/E/beta'  : Item(status='  '),
+    '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=' M'),
+    'D/H/chi'   : Item(status='A ', copied='+'),
+    'D/H/psi'   : Item(status='  '),
+    'D/H/omega' : Item(status='  '),
+    })
+  expected_status.tweak(wc_rev=9)
+  expected_status.tweak('D/H/chi', wc_rev='-')
+  expected_disk = wc.State('', {
+    '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("This is the file 'beta'.\n"),
+    '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("This is the file 'rho'.\n"),
+    'D/G/tau'   : Item("This is the file 'tau'.\n"),
+    'D/gamma'   : Item("This is the file 'gamma'.\n"),
+    'D/H'       : Item(props={SVN_PROP_MERGEINFO : '/A/D/H:2-6*,8*'}),
+    'D/H/chi'   : Item("This is the file 'chi'.\n"),
+    'D/H/psi'   : Item("New content",
+                       props={SVN_PROP_MERGEINFO : '/A/D/H/psi:2-8'}),
+    'D/H/omega' : Item("New content",
+                       props={SVN_PROP_MERGEINFO : '/A/D/H/omega:2-8'}),
+    })
+  expected_skip = wc.State('.', { })
+  svntest.actions.run_and_verify_merge(A_COPY_path, 7, 6,
+                                       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, False)
+
+#----------------------------------------------------------------------
+# A test for issue #3989 'merge which deletes file with native eol-style
+# raises spurious tree conflict'.
+@Issue(3989)
+@SkipUnless(server_has_mergeinfo)
+def merged_deletion_causes_tree_conflict(sbox):
+  "merged deletion causes spurious tree conflict"
+
+  sbox.build()
+  wc_dir = sbox.wc_dir
+
+  A_path        = os.path.join(wc_dir, 'A')
+  psi_path      = os.path.join(wc_dir, 'A', 'D', 'H', 'psi')
+  H_branch_path = os.path.join(wc_dir, 'branch', 'D', 'H')
+
+  # r2 - Set svn:eol-style native on A/D/H/psi
+  svntest.actions.run_and_verify_svn(None, None, [], 'ps', 'svn:eol-style',
+                                     'native', psi_path)
+  svntest.actions.run_and_verify_svn(None, None, [], 'ci', '-m',
+                                     'Set eol-style native on a path',
+                                     wc_dir)
+
+  # r3 - Branch ^/A to ^/branch
+  svntest.actions.run_and_verify_svn(None, None, [], 'copy',
+                                     sbox.repo_url + '/A',
+                                     sbox.repo_url + '/branch',
+                                     '-m', 'Copy ^/A to ^/branch')
+  svntest.actions.run_and_verify_svn(None, None, [], 'up', wc_dir)
+
+  # r4 - Delete A/D/H/psi 
+  svntest.actions.run_and_verify_svn(None, None, [], 'delete', psi_path)
+  svntest.actions.run_and_verify_svn(None, None, [], 'ci', '-m',
+                                     'Delete a a path with native eol-style',
+                                     wc_dir)
+
+  # Sync merge ^/A/D/H to branch/D/H.
+  #
+  # branch/D/H/psi is, ignoring differences caused by svn:eol-style, identical
+  # to ^/A/D/H/psi when the latter was deleted, so the deletion should merge
+  # cleanly.
+  svntest.actions.run_and_verify_svn(None, None, [], 'up', wc_dir)
+  expected_output = wc.State(H_branch_path, {
+    'psi' : Item(status='D '),
+    })
+  expected_mergeinfo_output = wc.State(H_branch_path, {
+    ''    : Item(status=' U'),
+    })
+  expected_elision_output = wc.State(H_branch_path, {})
+  expected_status = wc.State(H_branch_path, {
+    ''      : Item(status=' M'),
+    'chi'   : Item(status='  '),
+    'psi'   : Item(status='D '),
+    'omega' : Item(status='  '),
+    })
+  expected_status.tweak(wc_rev=4)
+  expected_disk = wc.State('', {
+    ''      : Item(props={SVN_PROP_MERGEINFO : '/A/D/H:3-4'}),
+    'chi'   : Item("This is the file 'chi'.\n"),
+    'omega' : Item("This is the file 'omega'.\n"),
+    })
+  expected_skip = wc.State('.', { })
+  svntest.actions.run_and_verify_merge(H_branch_path, None, None,
+                                       sbox.repo_url + '/A/D/H', None,
+                                       expected_output,
+                                       expected_mergeinfo_output,
+                                       expected_elision_output,
+                                       expected_disk,
+                                       expected_status,
+                                       expected_skip,
+                                       None, None, None, None,
+                                       None, 1, False)
+
+#----------------------------------------------------------------------
+# A test for issue #3976 'record-only merges which add new subtree mergeinfo
+# don't record mergeinfo describing merge'.
+@Issue(3976)
+@SkipUnless(server_has_mergeinfo)
+def record_only_merge_adds_new_subtree_mergeinfo(sbox):
+  "record only merge adds new subtree mergeinfo"
+
+  sbox.build()
+  wc_dir = sbox.wc_dir
+  wc_disk, wc_status = set_up_branch(sbox)
+
+  psi_path      = os.path.join(wc_dir, 'A', 'D', 'H', 'psi')
+  psi_COPY_path = os.path.join(wc_dir, 'A_COPY', 'D', 'H', 'psi')
+  H_COPY2_path  = os.path.join(wc_dir, 'A_COPY_2', 'D', 'H')
+
+  # r7 - Copy ^/A_COPY to ^/A_COPY_2
+  svntest.actions.run_and_verify_svn(None, None, [],
+                                     'copy', '-m', 'copy A_COPY to A_COPY_2',
+                                     sbox.repo_url + '/A_COPY',
+                                     sbox.repo_url + '/A_COPY_2')
+
+  # r8 - Set a property on A/D/H/psi.  It doesn't matter what property
+  # we use, just as long as we have a change that can be merged independently
+  # of the text change to A/D/H/psi in r3.
+  svntest.main.run_svn(None, 'propset', 'svn:eol-style', 'native', psi_path)
+  svntest.main.run_svn(None, 'commit', '-m', 'set svn:eol-style', wc_dir)
+
+  # r9 - Merge r3 from ^/A/D/H/psi to A_COPY/D/H/psi.
+  svntest.actions.run_and_verify_svn(None, None, [], 'merge',
+                                     sbox.repo_url + '/A/D/H/psi',
+                                     psi_COPY_path, '-c3')
+  svntest.main.run_svn(None, 'commit', '-m', 'Subtree merge', wc_dir)
+
+  # r10 - Merge r8 from ^/A/D/H/psi to A_COPY/D/H/psi.
+  svntest.actions.run_and_verify_svn(None, None, [], 'merge',
+                                     sbox.repo_url + '/A/D/H/psi',
+                                     psi_COPY_path, '-c8')
+  svntest.main.run_svn(None, 'commit', '-m', 'Subtree merge', wc_dir)
+
+  # Merge r10 from ^/A_COPY/D/H to A_COPY_2/D/H.  This should leave
+  # A_COPY_2/D/H/psi with three new property additions:
+  #
+  #   1) The 'svn:eol-style=native' from r10 via r8.
+  #
+  #   2) The mergeinfo '/A/D/H/psi:8' from r10.
+  #
+  #   3) The mergeinfo '/A_COPY/D/H/psi:10' describing the merge itself.
+  svntest.actions.run_and_verify_svn(None, None, [], 'up', wc_dir)
+  expected_output = wc.State(H_COPY2_path, {
+    'psi' : Item(status=' U'),
+    })
+  expected_mergeinfo_output = wc.State(H_COPY2_path, {
+    ''    : Item(status=' U'),
+    'psi' : Item(status=' G'),
+    })
+  expected_elision_output = wc.State(H_COPY2_path, {})
+  expected_status = wc.State(H_COPY2_path, {
+    ''      : Item(status=' M'),
+    'chi'   : Item(status='  '),
+    'psi'   : Item(status=' M'),
+    'omega' : Item(status='  '),
+    })
+  expected_status.tweak(wc_rev=10)
+  expected_disk = wc.State('', {
+    ''      : Item(props={SVN_PROP_MERGEINFO : '/A_COPY/D/H:10'}),
+    'psi'   : Item("This is the file 'psi'.\n",
+                   props={SVN_PROP_MERGEINFO :
+                          '/A/D/H/psi:8\n/A_COPY/D/H/psi:10',
+                          'svn:eol-style' : 'native'}),
+    'chi'   : Item("This is the file 'chi'.\n"),
+    'omega' : Item("This is the file 'omega'.\n"),
+    })
+  expected_skip = wc.State('.', { })
+  svntest.actions.run_and_verify_merge(H_COPY2_path, 9, 10,
+                                       sbox.repo_url + '/A_COPY/D/H', None,
+                                       expected_output,
+                                       expected_mergeinfo_output,
+                                       expected_elision_output,
+                                       expected_disk,
+                                       expected_status,
+                                       expected_skip,
+                                       None, None, None, None,
+                                       None, 1, False)
+
 ########################################################################
 # Run the tests
 
@@ -16851,6 +17235,10 @@ test_list = [ None,
               merge_change_to_file_with_executable,
               dry_run_merge_conflicting_binary,
               foreign_repos_prop_conflict,
+              merge_adds_subtree_with_mergeinfo,
+              reverse_merge_adds_subtree,
+              merged_deletion_causes_tree_conflict,
+              record_only_merge_adds_new_subtree_mergeinfo,
              ]
 
 if __name__ == '__main__':

Modified: subversion/branches/svn_mutex/subversion/tests/cmdline/merge_tree_conflict_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/svn_mutex/subversion/tests/cmdline/merge_tree_conflict_tests.py?rev=1182053&r1=1182052&r2=1182053&view=diff
==============================================================================
--- subversion/branches/svn_mutex/subversion/tests/cmdline/merge_tree_conflict_tests.py (original)
+++ subversion/branches/svn_mutex/subversion/tests/cmdline/merge_tree_conflict_tests.py Tue Oct 11 19:52:34 2011
@@ -1940,6 +1940,82 @@ def merge_replace_causes_tree_conflict2(
     actions.run_and_verify_svn2('OUTPUT', expected_stdout, [], 0, 'st',
                               '--depth=empty', path)
 
+#----------------------------------------------------------------------
+# Test for issue #4011 'merge of replacement on local delete fails'
+@SkipUnless(server_has_mergeinfo)
+@Issue(4011)
+@XFail()
+def merge_replace_on_del_fails(sbox):
+  "merge replace on local delete fails"
+
+  sbox.build()
+  wc_dir = sbox.wc_dir
+
+  C_path        = os.path.join(wc_dir, 'A', 'C')
+  branch_path   = os.path.join(wc_dir, 'branch')
+  C_branch_path = os.path.join(wc_dir, 'branch', 'C')
+
+  # r2 - Copy ^/A to ^/branch
+  svntest.actions.run_and_verify_svn(None, None, [], 'copy',
+                                     sbox.repo_url + '/A',
+                                     sbox.repo_url + '/branch',
+                                     '-m', 'Create a branch')
+
+  # r3 - Replace A/C
+  svntest.actions.run_and_verify_svn(None, None, [], 'del', C_path)
+  svntest.actions.run_and_verify_svn(None, None, [], 'mkdir', C_path)
+  svntest.actions.run_and_verify_svn(None, None, [], 'ci',
+                                     '-m', 'Replace A/C', wc_dir)
+
+  # r4 - Delete branch/C
+  svntest.actions.run_and_verify_svn(None, None, [], 'up', wc_dir)
+  svntest.actions.run_and_verify_svn(None, None, [], 'del', C_branch_path)
+  svntest.actions.run_and_verify_svn(None, None, [], 'ci',
+                                     '-m', 'Delete branch/C', wc_dir)
+
+  # Sync merge ^/A to branch
+  svntest.actions.run_and_verify_svn(None, None, [], 'up', wc_dir)
+  expected_stdout = verify.UnorderedOutput([
+    "--- Merging r2 through r4 into '" + branch_path + "':\n",
+    '   C ' + C_branch_path + '\n',
+    "--- Recording mergeinfo for merge of r2 through r4 into '" \
+    + branch_path + "':\n",
+    ' U   ' + branch_path + '\n',
+    'Summary of conflicts:\n',
+    '  Tree conflicts: 1\n',
+    ])
+  # This currently fails with:
+  #
+  #   >svn merge ^/A branch
+  #   ..\..\..\subversion\svn\util.c:913: (apr_err=155010)
+  #   ..\..\..\subversion\libsvn_client\merge.c:11349: (apr_err=155010)
+  #   ..\..\..\subversion\libsvn_client\merge.c:11303: (apr_err=155010)
+  #   ..\..\..\subversion\libsvn_client\merge.c:11303: (apr_err=155010)
+  #   ..\..\..\subversion\libsvn_client\merge.c:11273: (apr_err=155010)
+  #   ..\..\..\subversion\libsvn_client\merge.c:9287: (apr_err=155010)
+  #   ..\..\..\subversion\libsvn_client\merge.c:8870: (apr_err=155010)
+  #   ..\..\..\subversion\libsvn_client\merge.c:5349: (apr_err=155010)
+  #   ..\..\..\subversion\libsvn_repos\reporter.c:1430: (apr_err=155010)
+  #   ..\..\..\subversion\libsvn_client\ra.c:247: (apr_err=155010)
+  #   ..\..\..\subversion\libsvn_repos\reporter.c:1269: (apr_err=155010)
+  #   ..\..\..\subversion\libsvn_repos\reporter.c:1205: (apr_err=155010)
+  #   ..\..\..\subversion\libsvn_repos\reporter.c:920: (apr_err=155010)
+  #   ..\..\..\subversion\libsvn_delta\cancel.c:120: (apr_err=155010)
+  #   ..\..\..\subversion\libsvn_delta\cancel.c:120: (apr_err=155010)
+  #   ..\..\..\subversion\libsvn_client\repos_diff.c:710: (apr_err=155010)
+  #   ..\..\..\subversion\libsvn_client\merge.c:2234: (apr_err=155010)
+  #   ..\..\..\subversion\libsvn_wc\adm_ops.c:1069: (apr_err=155010)
+  #   ..\..\..\subversion\libsvn_wc\adm_ops.c:956: (apr_err=155010)
+  #   ..\..\..\subversion\libsvn_wc\update_editor.c:5036: (apr_err=155010)
+  #   ..\..\..\subversion\libsvn_wc\wc_db.c:6985: (apr_err=155010)
+  #   ..\..\..\subversion\libsvn_wc\wc_db.c:6929: (apr_err=155010)
+  #   ..\..\..\subversion\libsvn_wc\wc_db.c:6920: (apr_err=155010)
+  #   svn: E155010: The node 'C:\SVN\src-trunk\Debug\subversion\tests\
+  #     cmdline\svn-test-work\working_copies\merge_tree_conflict_tests-24\
+  #     branch\C' was not found.
+  actions.run_and_verify_svn2('OUTPUT', expected_stdout, [], 0, 'merge',
+    sbox.repo_url + '/A', branch_path)
+
 ########################################################################
 # Run the tests
 
@@ -1969,6 +2045,7 @@ test_list = [ None,
               tree_conflicts_merge_del_onto_missing,
               merge_replace_causes_tree_conflict,
               merge_replace_causes_tree_conflict2,
+              merge_replace_on_del_fails,
              ]
 
 if __name__ == '__main__':

Modified: subversion/branches/svn_mutex/subversion/tests/cmdline/mergeinfo_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/svn_mutex/subversion/tests/cmdline/mergeinfo_tests.py?rev=1182053&r1=1182052&r2=1182053&view=diff
==============================================================================
--- subversion/branches/svn_mutex/subversion/tests/cmdline/mergeinfo_tests.py (original)
+++ subversion/branches/svn_mutex/subversion/tests/cmdline/mergeinfo_tests.py Tue Oct 11 19:52:34 2011
@@ -489,6 +489,196 @@ def mergeinfo_on_pegged_wc_path(sbox):
     adjust_error_for_server_version(''),
     ['4', '5'], A_path, A_COPY_path + '@PREV', '--show-revs', 'eligible')
 
+#----------------------------------------------------------------------
+# A test for issue 3986 'svn_client_mergeinfo_log API is broken'.
+@Issue(3986)
+@SkipUnless(server_has_mergeinfo)
+def wc_target_inherits_mergeinfo_from_repos(sbox):
+  "wc target inherits mergeinfo from repos"
+
+  sbox.build()
+  wc_dir = sbox.wc_dir
+  wc_disk, wc_status = set_up_branch(sbox, nbr_of_branches=2)
+
+  A_COPY_path   = os.path.join(wc_dir, 'A_COPY')
+  rho_COPY_path = os.path.join(wc_dir, 'A_COPY', 'D', 'G', 'rho')
+  gamma_2_path  = os.path.join(wc_dir, 'A_COPY_2', 'D', 'gamma')
+  tau_path      = os.path.join(wc_dir, 'A', 'D', 'G', 'tau')
+  D_COPY_path   = os.path.join(wc_dir, 'A_COPY', 'D')
+  
+  # Merge -c5 ^/A/D/G/rho A_COPY\D\G\rho
+  # Merge -c7 ^/A A_COPY
+  # Commit as r8
+  #
+  # This gives us some explicit mergeinfo on the "branch" root and
+  # one of its subtrees:
+  #
+  #   Properties on 'A_COPY\D\G\rho':
+  #     svn:mergeinfo
+  #       /A/D/G/rho:5
+  #   Properties on 'A_COPY':
+  #     svn:mergeinfo
+  #       /A:7
+  svntest.actions.run_and_verify_svn(None, None, [], 'merge',
+                                     sbox.repo_url + '/A/D/G/rho',
+                                     rho_COPY_path, '-c5')
+  svntest.actions.run_and_verify_svn(None, None, [], 'merge',
+                                     sbox.repo_url + '/A',
+                                     A_COPY_path, '-c7')
+  svntest.actions.run_and_verify_svn(None, None, [], 'ci', '-m',
+                                     'Cherrypicks to branch subtree and root',
+                                     wc_dir)
+
+  # Checkout a new wc rooted at ^/A_COPY/D.
+  subtree_wc = sbox.add_wc_path('D_COPY')
+  svntest.actions.run_and_verify_svn(None, None, [], 'co',
+                                     sbox.repo_url + '/A_COPY/D',
+                                     subtree_wc)
+
+  # Check the merged and eligible revisions both recursively and
+  # non-recursively.
+
+  # Eligible : Non-recursive  
+  svntest.actions.run_and_verify_mergeinfo(
+    adjust_error_for_server_version(''),
+    ['4','5'], sbox.repo_url + '/A/D', subtree_wc,
+    '--show-revs', 'eligible')
+
+  # Eligible : Recursive
+  svntest.actions.run_and_verify_mergeinfo(
+    adjust_error_for_server_version(''),
+    ['4'], sbox.repo_url + '/A/D', subtree_wc,
+    '--show-revs', 'eligible', '-R')
+
+  # Merged : Non-recursive
+  svntest.actions.run_and_verify_mergeinfo(
+    adjust_error_for_server_version(''),
+    ['7'], sbox.repo_url + '/A/D', subtree_wc,
+    '--show-revs', 'merged')
+
+  # Merged : Recursive
+  svntest.actions.run_and_verify_mergeinfo(
+    adjust_error_for_server_version(''),
+    ['5','7'], sbox.repo_url + '/A/D', subtree_wc,
+    '--show-revs', 'merged', '-R')
+
+  # Test that intersecting revisions in the 'svn mergeinfo' target
+  # from one source don't show up as merged when asking about a different
+  # source.
+  #
+  # In r9 make a change that effects two branches:
+  svntest.actions.run_and_verify_svn(None, None, [], 'up', wc_dir)
+  svntest.main.file_write(gamma_2_path, "New content.\n")
+  svntest.main.file_write(tau_path, "New content.\n")
+  svntest.actions.run_and_verify_svn(None, None, [], 'ci', '-m',
+                                     'Make changes under both A and A_COPY_2',
+                                     wc_dir)
+
+  # In r10 merge r9 from A_COPY_2 to A_COPY.
+  #
+  # This gives us this mergeinfo:
+  #
+  #   Properties on 'A_COPY':
+  #     svn:mergeinfo
+  #       /A:7
+  #       /A_COPY_2:9
+  #   Properties on 'A_COPY\D\G\rho':
+  #     svn:mergeinfo
+  #       /A/D/G/rho:5
+  svntest.actions.run_and_verify_svn(None, None, [], 'merge',
+                                     sbox.repo_url + '/A_COPY_2',
+                                     A_COPY_path, '-c9')
+  svntest.actions.run_and_verify_svn(None, None, [], 'ci', '-m',
+                                     'Merge r8 from A_COPY_2 to A_COPY',
+                                     wc_dir)
+ 
+  def test_svn_mergeinfo_4_way(wc_target):
+    # Eligible : Non-recursive
+    svntest.actions.run_and_verify_mergeinfo(
+      adjust_error_for_server_version(''),
+      ['4','5','9'], sbox.repo_url + '/A/D', wc_target,
+      '--show-revs', 'eligible')
+
+    # Eligible : Recursive
+    svntest.actions.run_and_verify_mergeinfo(
+      adjust_error_for_server_version(''),
+      ['4','9'], sbox.repo_url + '/A/D', wc_target,
+      '--show-revs', 'eligible', '-R')
+
+    # Merged : Non-recursive
+    svntest.actions.run_and_verify_mergeinfo(
+      adjust_error_for_server_version(''),
+      ['7'], sbox.repo_url + '/A/D', wc_target,
+      '--show-revs', 'merged')
+
+    # Merged : Recursive
+    svntest.actions.run_and_verify_mergeinfo(
+      adjust_error_for_server_version(''),
+      ['5','7'], sbox.repo_url + '/A/D', wc_target,
+      '--show-revs', 'merged', '-R')
+
+  # Test while the target is the full WC and then with the subtree WC:
+  svntest.actions.run_and_verify_svn(None, None, [], 'up', wc_dir)
+  svntest.actions.run_and_verify_svn(None, None, [], 'up', subtree_wc)
+
+  test_svn_mergeinfo_4_way(D_COPY_path)
+  test_svn_mergeinfo_4_way(subtree_wc)
+
+#----------------------------------------------------------------------
+# A test for issue 3791 'svn mergeinfo shows natural history of added
+# subtrees as eligible'.
+@Issue(3791)
+@SkipUnless(server_has_mergeinfo)
+def natural_history_is_not_eligible_nor_merged(sbox):
+  "natural history is not eligible nor merged"
+
+  sbox.build()
+  wc_dir = sbox.wc_dir
+  wc_disk, wc_status = set_up_branch(sbox)
+
+  nu_path      = os.path.join(wc_dir, 'A', 'C', 'nu')
+  A_COPY_path  = os.path.join(wc_dir, 'A_COPY')
+  nu_COPY_path = os.path.join(wc_dir, 'A_COPY', 'C', 'nu')
+
+  # r7 - Add a new file A/C/nu
+  svntest.main.file_write(nu_path, "This is the file 'nu'.\n")
+  svntest.actions.run_and_verify_svn(None, None, [], 'add', nu_path)
+  svntest.actions.run_and_verify_svn(None, None, [], 'ci',
+                                     '-m', 'Add a file', wc_dir)
+
+  # r8 - Sync merge ^/A to A_COPY
+  svntest.actions.run_and_verify_svn(None, None, [], 'merge',
+                                     sbox.repo_url + '/A', A_COPY_path)
+  svntest.actions.run_and_verify_svn(None, None, [], 'ci',
+                                     '-m', 'Add a file', wc_dir)
+
+  # r9 - Modify the file added in r7
+  svntest.main.file_write(nu_path, "Modification to file 'nu'.\n")
+  svntest.actions.run_and_verify_svn(None, None, [], 'ci',
+                                     '-m', 'Modify added file', wc_dir)
+
+  # r10 - Merge ^/A/C/nu to A_COPY/C/nu, creating subtree mergeinfo.
+  svntest.actions.run_and_verify_svn(None, None, [], 'merge',
+                                     sbox.repo_url + '/A/C/nu', nu_COPY_path)
+  svntest.actions.run_and_verify_svn(None, None, [], 'ci',
+                                     '-m', 'Add a file', wc_dir)
+  svntest.actions.run_and_verify_svn(None, None, [], 'up', wc_dir)
+
+  # We've effectively merged everything from ^/A to A_COPY, check
+  # that svn mergeinfo -R agrees.
+  #
+  # First check if there are eligible revisions, there should be none.
+  svntest.actions.run_and_verify_mergeinfo(
+    adjust_error_for_server_version(''),
+    [], sbox.repo_url + '/A',
+    A_COPY_path, '--show-revs', 'eligible', '-R')
+
+  # Now check that all operative revisions show as merged.
+  svntest.actions.run_and_verify_mergeinfo(
+    adjust_error_for_server_version(''),
+    ['3','4','5','6','7','9'], sbox.repo_url + '/A',
+    A_COPY_path, '--show-revs', 'merged', '-R')
+
 ########################################################################
 # Run the tests
 
@@ -503,6 +693,8 @@ test_list = [ None,
               non_inheritable_mergeinfo,
               recursive_mergeinfo,
               mergeinfo_on_pegged_wc_path,
+              wc_target_inherits_mergeinfo_from_repos,
+              natural_history_is_not_eligible_nor_merged,
              ]
 
 if __name__ == '__main__':

Modified: subversion/branches/svn_mutex/subversion/tests/cmdline/patch_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/svn_mutex/subversion/tests/cmdline/patch_tests.py?rev=1182053&r1=1182052&r2=1182053&view=diff
==============================================================================
--- subversion/branches/svn_mutex/subversion/tests/cmdline/patch_tests.py (original)
+++ subversion/branches/svn_mutex/subversion/tests/cmdline/patch_tests.py Tue Oct 11 19:52:34 2011
@@ -3484,6 +3484,379 @@ def patch_add_symlink(sbox):
                                        1, # check-props
                                        1) # dry-run
 
+def patch_moved_away(sbox):
+  "patch a file that was moved away"
+
+  sbox.build()
+  wc_dir = sbox.wc_dir
+
+  patch_file_path = make_patch_path(sbox)
+  mu_path = os.path.join(wc_dir, 'A', 'mu')
+
+  mu_contents = [
+    "Dear internet user,\n",
+    "\n",
+    "We wish to congratulate you over your email success in our computer\n",
+    "Balloting. This is a Millennium Scientific Electronic Computer Draw\n",
+    "in which email addresses were used. All participants were selected\n",
+    "through a computer ballot system drawn from over 100,000 company\n",
+    "and 50,000,000 individual email addresses from all over the world.\n",
+    "\n",
+    "Your email address drew and have won the sum of  750,000 Euros\n",
+    "( Seven Hundred and Fifty Thousand Euros) in cash credited to\n",
+    "file with\n",
+    "    REFERENCE NUMBER: ESP/WIN/008/05/10/MA;\n",
+    "    WINNING NUMBER : 14-17-24-34-37-45-16\n",
+    "    BATCH NUMBERS :\n",
+    "    EULO/1007/444/606/08;\n",
+    "    SERIAL NUMBER: 45327\n",
+    "and PROMOTION DATE: 13th June. 2009\n",
+    "\n",
+    "To claim your winning prize, you are to contact the appointed\n",
+    "agent below as soon as possible for the immediate release of your\n",
+    "winnings with the below details.\n",
+    "\n",
+    "Again, we wish to congratulate you over your email success in our\n"
+    "computer Balloting.\n"
+  ]
+
+  # Set mu contents
+  svntest.main.file_write(mu_path, ''.join(mu_contents))
+  expected_output = svntest.wc.State(wc_dir, {
+    'A/mu'       : Item(verb='Sending'),
+    })
+  expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
+  expected_status.tweak('A/mu', wc_rev=2)
+  svntest.actions.run_and_verify_commit(wc_dir, expected_output,
+                                        expected_status, None, wc_dir)
+
+  # Move mu away
+  sbox.simple_move("A/mu", "A/mu2")
+
+  # Apply patch
+  unidiff_patch = [
+    "--- A/mu.orig	2009-06-24 15:23:55.000000000 +0100\n",
+    "+++ A/mu	2009-06-24 15:21:23.000000000 +0100\n",
+    "@@ -6,6 +6,9 @@\n",
+    " through a computer ballot system drawn from over 100,000 company\n",
+    " and 50,000,000 individual email addresses from all over the world.\n",
+    " \n",
+    "+It is a promotional program aimed at encouraging internet users;\n",
+    "+therefore you do not need to buy ticket to enter for it.\n",
+    "+\n",
+    " Your email address drew and have won the sum of  750,000 Euros\n",
+    " ( Seven Hundred and Fifty Thousand Euros) in cash credited to\n",
+    " file with\n",
+    "@@ -14,11 +17,8 @@\n",
+    "     BATCH NUMBERS :\n",
+    "     EULO/1007/444/606/08;\n",
+    "     SERIAL NUMBER: 45327\n",
+    "-and PROMOTION DATE: 13th June. 2009\n",
+    "+and PROMOTION DATE: 14th June. 2009\n",
+    " \n",
+    " To claim your winning prize, you are to contact the appointed\n",
+    " agent below as soon as possible for the immediate release of your\n",
+    " winnings with the below details.\n",
+    "-\n",
+    "-Again, we wish to congratulate you over your email success in our\n",
+    "-computer Balloting.\n",
+  ]
+
+  svntest.main.file_write(patch_file_path, ''.join(unidiff_patch))
+
+  mu_contents = [
+    "Dear internet user,\n",
+    "\n",
+    "We wish to congratulate you over your email success in our computer\n",
+    "Balloting. This is a Millennium Scientific Electronic Computer Draw\n",
+    "in which email addresses were used. All participants were selected\n",
+    "through a computer ballot system drawn from over 100,000 company\n",
+    "and 50,000,000 individual email addresses from all over the world.\n",
+    "\n",
+    "It is a promotional program aimed at encouraging internet users;\n",
+    "therefore you do not need to buy ticket to enter for it.\n",
+    "\n",
+    "Your email address drew and have won the sum of  750,000 Euros\n",
+    "( Seven Hundred and Fifty Thousand Euros) in cash credited to\n",
+    "file with\n",
+    "    REFERENCE NUMBER: ESP/WIN/008/05/10/MA;\n",
+    "    WINNING NUMBER : 14-17-24-34-37-45-16\n",
+    "    BATCH NUMBERS :\n",
+    "    EULO/1007/444/606/08;\n",
+    "    SERIAL NUMBER: 45327\n",
+    "and PROMOTION DATE: 14th June. 2009\n",
+    "\n",
+    "To claim your winning prize, you are to contact the appointed\n",
+    "agent below as soon as possible for the immediate release of your\n",
+    "winnings with the below details.\n",
+  ]
+
+  expected_output = [
+    'U         %s\n' % os.path.join(wc_dir, 'A', 'mu2'),
+  ]
+
+  expected_disk = svntest.main.greek_state.copy()
+  expected_disk.add({'A/mu2': Item(contents=''.join(mu_contents))})
+  expected_disk.remove('A/mu')
+
+  expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
+  expected_status.add({'A/mu2' : Item(status='A ', copied='+', wc_rev='-')})
+
+  expected_status.tweak('A/mu', status='D ', wc_rev=2)
+
+  expected_skip = wc.State('', { })
+
+  svntest.actions.run_and_verify_patch(wc_dir, os.path.abspath(patch_file_path),
+                                       expected_output,
+                                       expected_disk,
+                                       expected_status,
+                                       expected_skip,
+                                       None, # expected err
+                                       1, # check-props
+                                       1) # dry-run
+
+@XFail()
+@Issue(3991)
+def patch_lacking_trailing_eol(sbox):
+  "patch file lacking trailing eol"
+
+  sbox.build(read_only = True)
+  wc_dir = sbox.wc_dir
+
+  patch_file_path = make_patch_path(sbox)
+  iota_path = os.path.join(wc_dir, 'iota')
+  mu_path = os.path.join(wc_dir, 'A', 'mu')
+
+  # Prepare
+  expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
+
+  # Apply patch
+  unidiff_patch = [
+    "Index: iota\n",
+    "===================================================================\n",
+    "--- iota\t(revision 1)\n",
+    "+++ iota\t(working copy)\n",
+    # TODO: -1 +1
+    "@@ -1 +1,2 @@\n",
+    " This is the file 'iota'.\n",
+    "+Some more bytes", # No trailing \n on this line!
+  ]
+
+  svntest.main.file_write(patch_file_path, ''.join(unidiff_patch))
+
+  gamma_contents = "It is the file 'gamma'.\n"
+  iota_contents = "This is the file 'iota'.\n"
+  new_contents = "new\n"
+
+  expected_output = [
+    'U         %s\n' % os.path.join(wc_dir, 'iota'),
+    'svn: W[0-9]+: .*', # warning about appending a newline to iota's last line
+  ]
+
+  # Expect a newline to be appended
+  expected_disk = svntest.main.greek_state.copy()
+  expected_disk.tweak('iota', contents=iota_contents+"Some more bytes\n")
+
+  expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
+  expected_status.tweak('iota', status='M ')
+
+  expected_skip = wc.State('', { })
+
+  svntest.actions.run_and_verify_patch(wc_dir, os.path.abspath(patch_file_path),
+                                       expected_output,
+                                       expected_disk,
+                                       expected_status,
+                                       expected_skip,
+                                       None, # expected err
+                                       1, # check-props
+                                       1) # dry-run
+
+@Issue(4003)
+def patch_deletes_prop(sbox):
+  "patch deletes prop, directly and via reversed add"
+
+  sbox.build()
+  wc_dir = sbox.wc_dir
+
+  patch_file_path = make_patch_path(sbox)
+  iota_path = os.path.join(wc_dir, 'iota')
+
+  svntest.main.run_svn(None, 'propset', 'propname', 'propvalue',
+                       iota_path)
+  expected_output = svntest.wc.State(wc_dir, {
+    'iota' : Item(verb='Sending'),
+    })
+  expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
+  expected_status.tweak('iota', wc_rev=2)
+  svntest.actions.run_and_verify_commit(wc_dir, expected_output,
+                                        expected_status, None, wc_dir)
+
+  # Apply patch
+  unidiff_patch = [
+    "Index: iota\n",
+    "===================================================================\n",
+    "--- iota\t(revision 1)\n",
+    "+++ iota\t(working copy)\n",
+    "\n",
+    "Property changes on: iota\n",
+    "___________________________________________________________________\n",
+    "Deleted: propname\n",
+    "## -1 +0,0 ##\n",
+    "-propvalue\n",
+    ]
+  svntest.main.file_write(patch_file_path, ''.join(unidiff_patch))
+
+  # Expect the original state of the working copy in r1, exception
+  # that iota is at r2 now.
+  expected_disk = svntest.main.greek_state.copy()
+  expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
+  expected_status.tweak('iota', status=' M')
+  expected_status.tweak('iota', wc_rev=2)
+  expected_skip = wc.State('', { })
+  expected_output = [
+    ' U        %s\n' % os.path.join(wc_dir, 'iota'),
+  ]
+  svntest.actions.run_and_verify_patch(wc_dir, os.path.abspath(patch_file_path),
+                                       expected_output,
+                                       expected_disk,
+                                       expected_status,
+                                       expected_skip,
+                                       None, # expected err
+                                       1, # check-props
+                                       0) # dry-run
+
+  # Revert any local mods, then try to reverse-apply a patch which
+  # *adds* the property.
+  svntest.main.run_svn(None, 'revert', iota_path)
+
+  # Apply patch 
+  unidiff_patch = [
+    "Index: iota\n",
+    "===================================================================\n",
+    "--- iota\t(revision 1)\n",
+    "+++ iota\t(working copy)\n",
+    "\n",
+    "Property changes on: iota\n",
+    "___________________________________________________________________\n",
+    "Added: propname\n",
+    "## -0,0 +1 ##\n",
+    "+propvalue\n",
+    ]
+  svntest.main.file_write(patch_file_path, ''.join(unidiff_patch))
+
+  svntest.actions.run_and_verify_patch(wc_dir, os.path.abspath(patch_file_path),
+                                       expected_output,
+                                       expected_disk,
+                                       expected_status,
+                                       expected_skip,
+                                       None, # expected err
+                                       1, # check-props
+                                       1, # dry-run
+                                       '--reverse-diff') 
+
+@Issue(4004)
+def patch_reversed_add_with_props(sbox):
+  "reverse patch new file+props atop uncommitted"
+
+  sbox.build()
+  wc_dir = sbox.wc_dir
+  patch_file_path = make_patch_path(sbox)
+
+  # Add a new file which also has props set on it.
+  newfile_path = os.path.join(wc_dir, 'newfile')
+  newfile_contents = ["This is the file 'newfile'.\n"]
+  svntest.main.file_write(newfile_path, ''.join(newfile_contents))
+  svntest.main.run_svn(None, 'add', newfile_path)
+  svntest.main.run_svn(None, 'propset', 'propname', 'propvalue',
+                       newfile_path)
+
+  # Generate a patch file from our current diff (rooted at the working
+  # copy root).
+  cwd = os.getcwd()
+  try:
+    os.chdir(wc_dir)
+    exit_code, diff_output, err_output = svntest.main.run_svn(None, 'diff')
+  finally:
+    os.chdir(cwd)
+  svntest.main.file_write(patch_file_path, ''.join(diff_output))
+
+  # Okay, now commit up.
+  expected_output = svntest.wc.State(wc_dir, {
+    'newfile' : Item(verb='Adding'),
+    })
+
+  # Now, we'll try to reverse-apply the very diff we just created.  We
+  # expect the original state of the working copy in r1.
+  expected_disk = svntest.main.greek_state.copy()
+  expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
+  expected_skip = wc.State('', { })
+  expected_output = [
+    'D         %s\n' % newfile_path,
+  ]
+  svntest.actions.run_and_verify_patch(wc_dir, os.path.abspath(patch_file_path),
+                                       expected_output,
+                                       expected_disk,
+                                       expected_status,
+                                       expected_skip,
+                                       None, # expected err
+                                       1, # check-props
+                                       1, # dry-run
+                                       '--reverse-diff') 
+
+@Issue(4004)
+def patch_reversed_add_with_props2(sbox):
+  "reverse patch new file+props"
+
+  sbox.build()
+  wc_dir = sbox.wc_dir
+  patch_file_path = make_patch_path(sbox)
+
+  # Add a new file which also has props set on it.
+  newfile_path = os.path.join(wc_dir, 'newfile')
+  newfile_contents = ["This is the file 'newfile'.\n"]
+  svntest.main.file_write(newfile_path, ''.join(newfile_contents))
+  svntest.main.run_svn(None, 'add', newfile_path)
+  svntest.main.run_svn(None, 'propset', 'propname', 'propvalue',
+                       newfile_path)
+
+  # Generate a patch file from our current diff (rooted at the working
+  # copy root).
+  cwd = os.getcwd()
+  try:
+    os.chdir(wc_dir)
+    exit_code, diff_output, err_output = svntest.main.run_svn(None, 'diff')
+  finally:
+    os.chdir(cwd)
+  svntest.main.file_write(patch_file_path, ''.join(diff_output))
+
+  # Okay, now commit up.
+  expected_output = svntest.wc.State(wc_dir, {
+    'newfile' : Item(verb='Adding'),
+    })
+  expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
+  expected_status.add({'newfile' : Item(wc_rev=2, status='  ')})
+  svntest.actions.run_and_verify_commit(wc_dir, expected_output,
+                                        expected_status, None, wc_dir)
+
+  # Now, we'll try to reverse-apply the very diff we just created.  We
+  # expect the original state of the working copy in r1 plus 'newfile'
+  # scheduled for deletion.
+  expected_disk = svntest.main.greek_state.copy()
+  expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
+  expected_status.add({'newfile' : Item(status='D ', wc_rev=2)})
+  expected_skip = wc.State('', { })
+  expected_output = [
+    'D         %s\n' % newfile_path,
+  ]
+  svntest.actions.run_and_verify_patch(wc_dir, os.path.abspath(patch_file_path),
+                                       expected_output,
+                                       expected_disk,
+                                       expected_status,
+                                       expected_skip,
+                                       None, # expected err
+                                       1, # check-props
+                                       1, # dry-run
+                                       '--reverse-diff') 
 
 ########################################################################
 #Run the tests
@@ -3520,6 +3893,11 @@ test_list = [ None,
               patch_strip_cwd,
               patch_set_prop_no_eol,
               patch_add_symlink,
+              patch_moved_away,
+              patch_lacking_trailing_eol,
+              patch_deletes_prop,
+              patch_reversed_add_with_props,
+              patch_reversed_add_with_props2,
             ]
 
 if __name__ == '__main__':

Modified: subversion/branches/svn_mutex/subversion/tests/cmdline/prop_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/svn_mutex/subversion/tests/cmdline/prop_tests.py?rev=1182053&r1=1182052&r2=1182053&view=diff
==============================================================================
--- subversion/branches/svn_mutex/subversion/tests/cmdline/prop_tests.py (original)
+++ subversion/branches/svn_mutex/subversion/tests/cmdline/prop_tests.py Tue Oct 11 19:52:34 2011
@@ -138,6 +138,7 @@ def commit_props(sbox):
 
 #----------------------------------------------------------------------
 
+@Issue(3951)
 def update_props(sbox):
   "receive properties via update"
 
@@ -1124,7 +1125,7 @@ def recursive_base_wc_ops(sbox):
 #----------------------------------------------------------------------
 
 def url_props_ops(sbox):
-  "property operations on an URL"
+  "property operations on a URL"
 
   # Bootstrap
   sbox.build()

Modified: subversion/branches/svn_mutex/subversion/tests/cmdline/resolve_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/svn_mutex/subversion/tests/cmdline/resolve_tests.py?rev=1182053&r1=1182052&r2=1182053&view=diff
==============================================================================
--- subversion/branches/svn_mutex/subversion/tests/cmdline/resolve_tests.py (original)
+++ subversion/branches/svn_mutex/subversion/tests/cmdline/resolve_tests.py Tue Oct 11 19:52:34 2011
@@ -196,7 +196,7 @@ def prop_conflict_resolution(sbox):
     # Update, postponing all conflict resolution.
     svntest.actions.run_and_verify_svn(None, None, [], 'up',
                                        '--accept=postpone', wc_dir)
-    svntest.actions.run_and_verify_resolve([iota_path, mu_path, gamma_path], '-R',
+    svntest.actions.run_and_verify_resolve([iota_path, mu_path], '-R',
                                            '--accept', resolve_accept, wc_dir)
     svntest.actions.run_and_verify_svn(
       'svn revolve -R --accept=' + resolve_accept + ' of prop conflict '

Modified: subversion/branches/svn_mutex/subversion/tests/cmdline/revert_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/svn_mutex/subversion/tests/cmdline/revert_tests.py?rev=1182053&r1=1182052&r2=1182053&view=diff
==============================================================================
--- subversion/branches/svn_mutex/subversion/tests/cmdline/revert_tests.py (original)
+++ subversion/branches/svn_mutex/subversion/tests/cmdline/revert_tests.py Tue Oct 11 19:52:34 2011
@@ -368,37 +368,52 @@ def revert_replaced_file_without_props(s
   svntest.actions.run_and_verify_status(wc_dir, expected_status)
 
 #----------------------------------------------------------------------
-# Regression test for issue #876:
-# svn revert of an svn move'd file does not revert the file
-@XFail()
+# Note that issue #876 has been rejected. This now basically tests that
+# reverting the delete side of a move does *not* also revert the copy side.
 @Issue(876)
 def revert_moved_file(sbox):
-    "revert a moved file"
+  "revert a moved file"
+
+  # svntest.factory.make(sbox, """svn mv iota iota_moved
+  #                               svn st
+  #                               svn revert iota
+  #                               svn st
+  #                               """)
+
+  sbox.build()
+  wc_dir = sbox.wc_dir
+
+  iota = os.path.join(wc_dir, 'iota')
+  iota_moved = os.path.join(wc_dir, 'iota_moved')
+
+  # svn mv iota iota_moved
+  expected_stdout = svntest.verify.UnorderedOutput([
+    'A         ' + iota_moved + '\n',
+    'D         ' + iota + '\n',
+  ])
+
+  actions.run_and_verify_svn2('OUTPUT', expected_stdout, [], 0, 'mv', iota,
+    iota_moved)
 
-    sbox.build(read_only = True)
-    wc_dir = sbox.wc_dir
-    iota_path = os.path.join(wc_dir, 'iota')
-    iota_path_moved = os.path.join(wc_dir, 'iota_moved')
-
-    svntest.actions.run_and_verify_svn(None, None, [], 'mv', iota_path,
-                                        iota_path_moved)
-    expected_output = svntest.actions.get_virginal_state(wc_dir, 1)
-    expected_output.tweak('iota', status='D ')
-    expected_output.add({
-      'iota_moved' : Item(status='A ', copied='+', wc_rev='-'),
-    })
-    svntest.actions.run_and_verify_status(wc_dir, expected_output)
-
-    # now revert the file iota
-    svntest.actions.run_and_verify_svn(None,
-      ["Reverted '" + iota_path + "'\n"], [], 'revert', iota_path)
-
-    # at this point, svn status on iota_path_moved should return nothing
-    # since it should disappear on reverting the move, and since svn status
-    # on a non-existent file returns nothing.
+  # svn st
+  expected_status = actions.get_virginal_state(wc_dir, 1)
+  expected_status.add({
+    'iota_moved'        : Item(status='A ', copied='+', wc_rev='-'),
+  })
+  expected_status.tweak('iota', status='D ')
+
+  actions.run_and_verify_unquiet_status(wc_dir, expected_status)
+
+  # svn revert iota
+  expected_stdout = ["Reverted '" + iota + "'\n"]
+
+  actions.run_and_verify_svn2('OUTPUT', expected_stdout, [], 0, 'revert',
+    iota)
 
-    svntest.actions.run_and_verify_svn(None, [], [],
-                                      'status', '-v', iota_path_moved)
+  # svn st
+  expected_status.tweak('iota', status='  ')
+
+  actions.run_and_verify_unquiet_status(wc_dir, expected_status)
 
 
 #----------------------------------------------------------------------
@@ -890,13 +905,7 @@ def status_of_missing_dir_after_revert_r
   svntest.actions.run_and_verify_svn(None, expected_output, [], "revert", "-R",
                                      G_path)
 
-
-  # Revert leaves these added nodes as unversioned
-  expected_output = svntest.verify.UnorderedOutput(
-    ["?       " + os.path.join(G_path, "pi") + "\n",
-     "?       " + os.path.join(G_path, "rho") + "\n",
-     "?       " + os.path.join(G_path, "tau") + "\n"])
-  svntest.actions.run_and_verify_svn(None, expected_output, [],
+  svntest.actions.run_and_verify_svn(None, [], [],
                                      "status", wc_dir)
 
   svntest.main.safe_rmtree(G_path)
@@ -977,8 +986,7 @@ def revert_tree_conflicts_in_updated_fil
   expected_status.remove('A/D/G/tau')
 
   expected_disk = svntest.main.greek_state.copy()
-  expected_disk.tweak('A/D/G/rho',
-                      contents="This is the file 'rho'.\nLocal edit.\n")
+  expected_disk.remove('A/D/G/rho')
   expected_disk.tweak('A/D/G/pi',
                       contents="This is the file 'pi'.\nIncoming edit.\n")
   expected_disk.remove('A/D/G/tau')
@@ -1464,8 +1472,6 @@ def revert_tree_conflicts_with_replaceme
 
   # Remove a few unversioned files that revert left behind.
   os.remove(wc('A/B/E/loc_beta'))
-  os.remove(wc('A/D/G/rho'))
-  os.remove(wc('A/D/G/tau'))
   os.remove(wc('A/D/H/loc_psi'))
 
   # The update operation should have put all incoming items in place.

Modified: subversion/branches/svn_mutex/subversion/tests/cmdline/special_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/svn_mutex/subversion/tests/cmdline/special_tests.py?rev=1182053&r1=1182052&r2=1182053&view=diff
==============================================================================
--- subversion/branches/svn_mutex/subversion/tests/cmdline/special_tests.py (original)
+++ subversion/branches/svn_mutex/subversion/tests/cmdline/special_tests.py Tue Oct 11 19:52:34 2011
@@ -711,6 +711,7 @@ def unrelated_changed_special_status(sbo
                                      '-m', 'psi changed special status')
 
 
+@Issue(3972)
 @SkipUnless(svntest.main.is_posix_os)
 def symlink_destination_change(sbox):
   "revert a symlink destination change"
@@ -747,6 +748,10 @@ def symlink_destination_change(sbox):
   expected_status.tweak('newfile', status='  ')
   svntest.actions.run_and_verify_status(wc_dir, expected_status)
 
+  # Issue 3972, repeat revert produces no output
+  svntest.actions.run_and_verify_svn(None, [], [], 'revert', '-R', wc_dir)
+  svntest.actions.run_and_verify_status(wc_dir, expected_status)
+
   # Now replace the symlink with a normal file and try to commit, we
 
 #----------------------------------------------------------------------
@@ -795,6 +800,67 @@ def merge_foreign_symlink(sbox):
   #     'A/zeta' : Item(status='A ', wc_rev='-', props={'svn:special': '*'}),
   #     })
 
+#----------------------------------------------------------------------
+# See also symlink_to_wc_svnversion().
+@Issue(2557,3987)
+@SkipUnless(svntest.main.is_posix_os)
+def symlink_to_wc_basic(sbox):
+  "operate on symlink to wc"
+
+  sbox.build(read_only = True)
+  wc_dir = sbox.wc_dir
+
+  # Create a symlink
+  symlink_path = sbox.add_wc_path('2')
+  assert not os.path.islink(symlink_path)
+  os.symlink(os.path.basename(wc_dir), symlink_path) ### implementation detail
+  symlink_basename = os.path.basename(symlink_path)
+
+  # Some basic tests
+  wc_uuid = svntest.actions.get_wc_uuid(wc_dir)
+  expected_info = [{
+      'Path' : re.escape(os.path.join(symlink_path)),
+      'Working Copy Root Path' : re.escape(os.path.abspath(symlink_path)),
+      'Repository Root' : sbox.repo_url,
+      'Repository UUID' : wc_uuid,
+      'Revision' : '1',
+      'Node Kind' : 'directory',
+      'Schedule' : 'normal',
+  }, {
+      'Name' : 'iota',
+      'Path' : re.escape(os.path.join(symlink_path, 'iota')),
+      'Working Copy Root Path' : re.escape(os.path.abspath(symlink_path)),
+      'Repository Root' : sbox.repo_url,
+      'Repository UUID' : wc_uuid,
+      'Revision' : '1',
+      'Node Kind' : 'file',
+      'Schedule' : 'normal',
+  }]
+  svntest.actions.run_and_verify_info(expected_info,
+                                      symlink_path, symlink_path + '/iota')
+
+#----------------------------------------------------------------------
+# Similar to #2557/#3987; see symlink_to_wc_basic().
+@Issue(2557,3987)
+@SkipUnless(svntest.main.is_posix_os)
+def symlink_to_wc_svnversion(sbox):
+  "svnversion on symlink to wc"
+
+  sbox.build(read_only = True)
+  wc_dir = sbox.wc_dir
+
+  # Create a symlink
+  symlink_path = sbox.add_wc_path('2')
+  assert not os.path.islink(symlink_path)
+  os.symlink(os.path.basename(wc_dir), symlink_path) ### implementation detail
+  symlink_basename = os.path.basename(symlink_path)
+
+  # Some basic tests
+  svntest.actions.run_and_verify_svnversion("Unmodified symlink to wc",
+                                            symlink_path, sbox.repo_url,
+                                            [ "1\n" ], [])
+
+
 ########################################################################
 # Run the tests
 
@@ -819,6 +885,8 @@ test_list = [ None,
               unrelated_changed_special_status,
               symlink_destination_change,
               merge_foreign_symlink,
+              symlink_to_wc_basic,
+              symlink_to_wc_svnversion,
              ]
 
 if __name__ == '__main__':

Modified: subversion/branches/svn_mutex/subversion/tests/cmdline/stat_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/svn_mutex/subversion/tests/cmdline/stat_tests.py?rev=1182053&r1=1182052&r2=1182053&view=diff
==============================================================================
--- subversion/branches/svn_mutex/subversion/tests/cmdline/stat_tests.py (original)
+++ subversion/branches/svn_mutex/subversion/tests/cmdline/stat_tests.py Tue Oct 11 19:52:34 2011
@@ -797,13 +797,14 @@ def status_on_unversioned_dotdot(sbox):
   sbox.build(read_only = True)
   wc_dir = sbox.wc_dir
 
-  new_dir = os.path.join(wc_dir, 'new_dir')
-  new_subdir = os.path.join(new_dir, 'new_subdir')
+  new_dir = sbox.ospath('new')
+  new_sub = sbox.ospath('new/sub')
+  new_subsub = sbox.ospath('new/sub/sub')
   os.mkdir(new_dir)
-  os.mkdir(new_subdir)
-
-  os.chdir(new_subdir)
+  os.mkdir(new_sub)
+  os.mkdir(new_subsub)
 
+  os.chdir(new_subsub)
   exit_code, out, err = svntest.main.run_svn(1, 'st', '..')
   for line in err:
     if line.find('svn: warning: W155007: \'..\' is not a working copy') != -1:

Modified: subversion/branches/svn_mutex/subversion/tests/cmdline/svnadmin_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/svn_mutex/subversion/tests/cmdline/svnadmin_tests.py?rev=1182053&r1=1182052&r2=1182053&view=diff
==============================================================================
--- subversion/branches/svn_mutex/subversion/tests/cmdline/svnadmin_tests.py (original)
+++ subversion/branches/svn_mutex/subversion/tests/cmdline/svnadmin_tests.py Tue Oct 11 19:52:34 2011
@@ -26,6 +26,7 @@
 
 # General modules
 import os
+import re
 import shutil
 import sys
 
@@ -33,6 +34,7 @@ import sys
 import svntest
 from svntest.verify import SVNExpectedStdout, SVNExpectedStderr
 from svntest.verify import SVNUnexpectedStderr
+from svntest.verify import UnorderedOutput
 from svntest.main import SVN_PROP_MERGEINFO
 
 # (abbreviation)
@@ -465,7 +467,7 @@ def fsfs_file(repo_dir, kind, rev):
     if svntest.main.options.fsfs_sharding is None:
       return os.path.join(repo_dir, 'db', kind, '0', rev)
     else:
-      shard = int(rev) // svntest.main.fsfs_sharding
+      shard = int(rev) // svntest.main.options.fsfs_sharding
       path = os.path.join(repo_dir, 'db', kind, str(shard), rev)
 
       if svntest.main.options.fsfs_packing is None or kind == 'revprops':
@@ -970,7 +972,7 @@ def verify_with_invalid_revprops(sbox):
 
   if svntest.verify.verify_outputs(
     "Output of 'svnadmin verify' is unexpected.", None, errput, None,
-    ".*Malformed file"):
+    ".*svnadmin: E200002:.*"):
     raise svntest.Failure
 
 #----------------------------------------------------------------------
@@ -1320,6 +1322,7 @@ text
 # However, the verification triggered by this test is in the repos layer
 # so it will trigger with either backend anyway.
 @SkipUnless(svntest.main.is_fs_type_fsfs)
+@SkipUnless(svntest.main.server_enforces_UTF8_fspaths_in_verify)
 def verify_non_utf8_paths(sbox):
   "svnadmin verify with non-UTF-8 paths"
 
@@ -1380,6 +1383,101 @@ def verify_non_utf8_paths(sbox):
     'STDERR', expected_stderr, errput):
     raise svntest.Failure
 
+def test_lslocks_and_rmlocks(sbox):
+  "test 'svnadmin lslocks' and 'svnadmin rmlocks'"
+  
+  sbox.build(create_wc=False)
+  iota_url = sbox.repo_url + '/iota'
+  lambda_url = sbox.repo_url + '/A/B/lambda'
+
+  exit_code, output, errput = svntest.main.run_svnadmin("lslocks",
+                                                        sbox.repo_dir)
+
+  if exit_code or errput or output:
+    raise svntest.Failure("Error: 'lslocks' failed")
+
+  expected_output = UnorderedOutput(
+    ["'A/B/lambda' locked by user 'jrandom'.\n",
+     "'iota' locked by user 'jrandom'.\n"])
+  
+  # Lock iota and A/B/lambda using svn client
+  svntest.actions.run_and_verify_svn(None, expected_output,
+                                     [], "lock", "-m", "Locking files",
+                                     iota_url, lambda_url)
+
+  expected_output_list = [
+      "Path: /A/B/lambda",
+      "UUID Token: opaquelocktoken",
+      "Owner: jrandom",
+      "Created:",
+      "Expires:",
+      "Comment \(1 line\):",
+      "Locking files",
+      "Path: /iota",
+      "UUID Token: opaquelocktoken.*",      
+      "\n", # empty line    
+      ]
+
+  # List all locks
+  exit_code, output, errput = svntest.main.run_svnadmin("lslocks",
+                                                        sbox.repo_dir)
+  
+  if errput:
+    raise SVNUnexpectedStderr(errput)
+  svntest.verify.verify_exit_code(None, exit_code, 0)
+    
+  try:
+    expected_output = svntest.verify.UnorderedRegexOutput(expected_output_list)
+    svntest.verify.compare_and_display_lines('lslocks output mismatch',
+                                             'output',
+                                             expected_output, output)
+  except:
+    # Usually both locks have the same timestamp but if the clock
+    # ticks between creating the two locks then the timestamps will
+    # differ.  When the output has two identical "Created" lines
+    # UnorderedRegexOutput must have one matching regex, when the
+    # output has two different "Created" lines UnorderedRegexOutput
+    # must have two regex.
+    expected_output_list.append("Created:.*")
+    expected_output = svntest.verify.UnorderedRegexOutput(expected_output_list)
+    svntest.verify.compare_and_display_lines('lslocks output mismatch',
+                                             'output',
+                                             expected_output, output)
+
+  # List lock in path /A
+  exit_code, output, errput = svntest.main.run_svnadmin("lslocks",
+                                                        sbox.repo_dir,
+                                                        "A")
+  if errput:
+    raise SVNUnexpectedStderr(errput)
+
+  expected_output = svntest.verify.UnorderedRegexOutput([
+    "Path: /A/B/lambda",
+    "UUID Token: opaquelocktoken",
+    "Owner: jrandom",
+    "Created:",
+    "Expires:",
+    "Comment \(1 line\):",
+    "Locking files",
+    "\n", # empty line    
+    ])
+
+  svntest.verify.compare_and_display_lines('message', 'label',
+                                           expected_output, output)
+  svntest.verify.verify_exit_code(None, exit_code, 0)
+
+  # Remove locks
+  exit_code, output, errput = svntest.main.run_svnadmin("rmlocks",
+                                                        sbox.repo_dir,
+                                                        "iota",
+                                                        "A/B/lambda")
+  expected_output = UnorderedOutput(["Removed lock on '/iota'.\n",
+                                     "Removed lock on '/A/B/lambda'.\n"])
+  
+  svntest.verify.verify_outputs(
+    "Unexpected output while running 'svnadmin rmlocks'.",
+    output, [], expected_output, None)
+
 ########################################################################
 # Run the tests
 
@@ -1409,6 +1507,7 @@ test_list = [ None,
               hotcopy_symlink,
               load_bad_props,
               verify_non_utf8_paths,
+              test_lslocks_and_rmlocks,
              ]
 
 if __name__ == '__main__':

Modified: subversion/branches/svn_mutex/subversion/tests/cmdline/svndumpfilter_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/svn_mutex/subversion/tests/cmdline/svndumpfilter_tests.py?rev=1182053&r1=1182052&r2=1182053&view=diff
==============================================================================
--- subversion/branches/svn_mutex/subversion/tests/cmdline/svndumpfilter_tests.py (original)
+++ subversion/branches/svn_mutex/subversion/tests/cmdline/svndumpfilter_tests.py Tue Oct 11 19:52:34 2011
@@ -439,7 +439,7 @@ def filter_mergeinfo_revs_outside_of_dum
   # Check that all the blather above really happens.  First does
   # svndumpfilter report what we expect to stderr?
   expected_err = [
-      "Excluding (and dropping empty revisions for) prefix patterns:\n",
+      "Excluding (and dropping empty revisions for) prefixes:\n",
       "   '/branches/B2'\n",
       "\n",
       "Revision 6 committed as 6.\n",

Modified: subversion/branches/svn_mutex/subversion/tests/cmdline/svnsync_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/svn_mutex/subversion/tests/cmdline/svnsync_tests.py?rev=1182053&r1=1182052&r2=1182053&view=diff
==============================================================================
--- subversion/branches/svn_mutex/subversion/tests/cmdline/svnsync_tests.py (original)
+++ subversion/branches/svn_mutex/subversion/tests/cmdline/svnsync_tests.py Tue Oct 11 19:52:34 2011
@@ -28,7 +28,7 @@
 import sys, os
 
 # Test suite-specific modules
-import locale
+import locale, re
 
 # Our testing module
 import svntest
@@ -76,6 +76,9 @@ def run_sync(url, source_url=None, expec
     args.append(source_prop_encoding)
 
   exit_code, output, errput = svntest.main.run_svnsync(*args)
+  for index, line in enumerate(errput[:]):
+    if re.search("warning: W200007", line):
+      del errput[index]
   if errput:
     if expected_error is None:
       raise SVNUnexpectedStderr(errput)
@@ -101,6 +104,9 @@ def run_copy_revprops(url, source_url, e
     args.append(source_prop_encoding)
 
   exit_code, output, errput = svntest.main.run_svnsync(*args)
+  for index, line in enumerate(errput[:]):
+    if re.search("warning: W200007", line):
+      del errput[index]
   if errput:
     if expected_error is None:
       raise SVNUnexpectedStderr(errput)
@@ -126,6 +132,9 @@ def run_init(dst_url, src_url, source_pr
     args.append(source_prop_encoding)
 
   exit_code, output, errput = svntest.main.run_svnsync(*args)
+  for index, line in enumerate(errput[:]):
+    if re.search("warning: W200007", line):
+      del errput[index]
   if errput:
     raise SVNUnexpectedStderr(errput)
   if output != ['Copied properties for revision 0.\n']:

Modified: subversion/branches/svn_mutex/subversion/tests/cmdline/svntest/actions.py
URL: http://svn.apache.org/viewvc/subversion/branches/svn_mutex/subversion/tests/cmdline/svntest/actions.py?rev=1182053&r1=1182052&r2=1182053&view=diff
==============================================================================
--- subversion/branches/svn_mutex/subversion/tests/cmdline/svntest/actions.py (original)
+++ subversion/branches/svn_mutex/subversion/tests/cmdline/svntest/actions.py Tue Oct 11 19:52:34 2011
@@ -350,11 +350,37 @@ def run_and_verify_svnrdump(dumpfile_con
   if sys.platform == 'win32':
     err = map(lambda x : x.replace('\r\n', '\n'), err)
 
+  for index, line in enumerate(err[:]):
+    if re.search("warning: W200007", line):
+      del err[index]
+
   verify.verify_outputs("Unexpected output", output, err,
                         expected_stdout, expected_stderr)
   verify.verify_exit_code("Unexpected return code", exit_code, expected_exit)
   return output
 
+
+def run_and_verify_svnmucc(message, expected_stdout, expected_stderr,
+                           *varargs):
+  """Run svnmucc command and check its output"""
+
+  expected_exit = 0
+  if expected_stderr is not None and expected_stderr != []:
+    expected_exit = 1
+  return run_and_verify_svnmucc2(message, expected_stdout, expected_stderr,
+                                 expected_exit, *varargs)
+
+def run_and_verify_svnmucc2(message, expected_stdout, expected_stderr,
+                            expected_exit, *varargs):
+  """Run svnmucc command and check its output and exit code."""
+
+  exit_code, out, err = main.run_svnmucc(*varargs)
+  verify.verify_outputs("Unexpected output", out, err,
+                        expected_stdout, expected_stderr)
+  verify.verify_exit_code(message, exit_code, expected_exit)
+  return exit_code, out, err
+
+
 def load_repo(sbox, dumpfile_path = None, dump_str = None,
               bypass_prop_validation = False):
   "Loads the dumpfile into sbox"
@@ -921,7 +947,7 @@ def run_and_verify_info(expected_infos, 
         if value is not None and key not in actual:
           raise main.SVNLineUnequal("Expected key '%s' (with value '%s') "
                                     "not found" % (key, value))
-        if value is not None and not re.search(value, actual[key]):
+        if value is not None and not re.match(value, actual[key]):
           raise verify.SVNUnexpectedStdout("Values of key '%s' don't match:\n"
                                            "  Expected: '%s' (regex)\n"
                                            "  Found:    '%s' (string)\n"
@@ -1372,8 +1398,9 @@ def run_and_verify_commit(wc_dir_name, o
     status_tree = status_tree.old_tree()
 
   # Commit.
+  if '-m' not in args and '-F' not in args:
+    args = list(args) + ['-m', 'log msg']
   exit_code, output, errput = main.run_svn(error_re_string, 'ci',
-                                           '-m', 'log msg',
                                            *args)
 
   if error_re_string:
@@ -1796,12 +1823,12 @@ def set_prop(name, value, path, expected
   if value and (value[0] == '-' or '\x00' in value or sys.platform == 'win32'):
     from tempfile import mkstemp
     (fd, value_file_path) = mkstemp()
+    os.close(fd)
     value_file = open(value_file_path, 'wb')
     value_file.write(value)
     value_file.flush()
     value_file.close()
     main.run_svn(expected_err, 'propset', '-F', value_file_path, name, path)
-    os.close(fd)
     os.remove(value_file_path)
   else:
     main.run_svn(expected_err, 'propset', name, value, path)

Modified: subversion/branches/svn_mutex/subversion/tests/cmdline/svntest/factory.py
URL: http://svn.apache.org/viewvc/subversion/branches/svn_mutex/subversion/tests/cmdline/svntest/factory.py?rev=1182053&r1=1182052&r2=1182053&view=diff
==============================================================================
--- subversion/branches/svn_mutex/subversion/tests/cmdline/svntest/factory.py (original)
+++ subversion/branches/svn_mutex/subversion/tests/cmdline/svntest/factory.py Tue Oct 11 19:52:34 2011
@@ -288,7 +288,9 @@ class TestFactory:
     # Any expected_disk still there from a previous verification
     self.prev_disk = None
     if prev_disk:
-      self.prev_disk = [None, prev_disk]      # svntest.wc.State
+      reparented_prev_disk = svntest.wc.State(prev_disk.wc_dir, {});
+      reparented_prev_disk.add_state(sbox.wc_dir, prev_disk);
+      self.prev_disk = [None, reparented_prev_disk]
 
     # Those command line options that expect an argument following
     # which is not a path. (don't expand args following these)