You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by hw...@apache.org on 2010/12/10 22:23:13 UTC

svn commit: r1044516 [20/22] - in /subversion/branches/ignore-mergeinfo: ./ build/ac-macros/ build/generator/ contrib/server-side/ notes/ notes/wc-ng/ subversion/bindings/javahl/native/ subversion/bindings/javahl/src/org/apache/subversion/javahl/ subve...

Modified: subversion/branches/ignore-mergeinfo/subversion/tests/cmdline/merge_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/ignore-mergeinfo/subversion/tests/cmdline/merge_tests.py?rev=1044516&r1=1044515&r2=1044516&view=diff
==============================================================================
--- subversion/branches/ignore-mergeinfo/subversion/tests/cmdline/merge_tests.py (original)
+++ subversion/branches/ignore-mergeinfo/subversion/tests/cmdline/merge_tests.py Fri Dec 10 21:23:03 2010
@@ -37,10 +37,10 @@ Item = wc.StateItem
 XFail = svntest.testcase.XFail
 Skip = svntest.testcase.Skip
 SkipUnless = svntest.testcase.SkipUnless
+Wimp = svntest.testcase.Wimp
 
 from svntest.main import SVN_PROP_MERGEINFO
 from svntest.main import server_has_mergeinfo
-from svntest.main import is_fs_case_insensitive
 from svntest.actions import fill_file_with_lines
 from svntest.actions import make_conflict_marker_text
 from svntest.actions import inject_conflict_into_expected_state
@@ -1639,7 +1639,7 @@ def merge_skips_obstructions(sbox):
                                        expected_status.copy(wc_dir),
                                        expected_skip,
                                        None, None, None, None, None,
-                                       1, 0, '--ignore-ancestry')
+                                       1, 0, '--ignore-ancestry', wc_dir)
 
 #----------------------------------------------------------------------
 # At one time, a merge that added items with the same name as missing
@@ -1652,6 +1652,8 @@ def merge_into_missing(sbox):
 
   sbox.build()
   wc_dir = sbox.wc_dir
+  
+  single_db = svntest.main.wc_is_singledb(wc_dir)
 
   F_path = os.path.join(wc_dir, 'A', 'B', 'F')
   F_url = sbox.repo_url + '/A/B/F'
@@ -1715,14 +1717,25 @@ def merge_into_missing(sbox):
     ''      : Item(status='  ', wc_rev=1),
     'foo'   : Item(status='! ', wc_rev=2),
     'Q'     : Item(status='! ', wc_rev='?'),
-# In some intermediate WC-NG state (since r937468) this was:
-#   'Q'     : Item(status='! ', wc_rev='2', entry_rev='?'),
-# but the expected value is now back what it was.
     })
   expected_skip = wc.State(F_path, {
     'Q'   : Item(),
     'foo' : Item(),
     })
+    
+  if single_db:
+    # Revision not lost
+    expected_status.tweak('Q', wc_rev=2)
+    # Missing data still available
+    expected_status.add({
+      'Q/R'      : Item(status='! ', wc_rev='3'),
+      'Q/R/bar'  : Item(status='! ', wc_rev='3'),
+      'Q/baz'    : Item(status='! ', wc_rev='3'),
+    })    
+
+  # Use --ignore-ancestry because merge tracking aware merges raise an
+  # error when the merge target is missing subtrees due to OS-level
+  # deletes.
 
   ### Need to real and dry-run separately since real merge notifies Q
   ### twice!
@@ -1734,20 +1747,26 @@ def merge_into_missing(sbox):
                                        expected_status,
                                        expected_skip,
                                        None, None, None, None, None,
-                                       0, 0, '--dry-run')
+                                       0, 0, '--dry-run',
+                                       '--ignore-ancestry', F_path)
 
   expected_status = wc.State(F_path, {
-    ''      : Item(status=' M', wc_rev=1),
-    'foo'   : Item(status='!M', wc_rev=2),
+    ''      : Item(status='  ', wc_rev=1),
+    'foo'   : Item(status='! ', wc_rev=2),
     'Q'     : Item(status='! ', wc_rev='?'),
-# In some intermediate WC-NG state (since r937468) this was:
-#   'Q'     : Item(status='! ', wc_rev='2', entry_rev='?'),
-# but the expected value is now back what it was.
     })
   expected_mergeinfo_output = wc.State(F_path, {
-    ''    : Item(status=' U'),
-    'foo' : Item(status=' U'), # Mergeinfo is set on missing/obstructed files.
     })
+    
+  if single_db:
+    # Revision is known and we can record mergeinfo
+    expected_status.tweak('Q', wc_rev='2', entry_rev='?')
+    expected_status.add({
+      'Q/R'      : Item(status='! ', wc_rev='3'),
+      'Q/R/bar'  : Item(status='! ', wc_rev='3'),
+      'Q/baz'    : Item(status='! ', wc_rev='3'),
+    })    
+
   svntest.actions.run_and_verify_merge(F_path, '1', '2', F_url, None,
                                        expected_output,
                                        expected_mergeinfo_output,
@@ -1756,7 +1775,8 @@ def merge_into_missing(sbox):
                                        expected_status,
                                        expected_skip,
                                        None, None, None, None, None,
-                                       0, 0)
+                                       0, 0,
+                                       '--ignore-ancestry', F_path)
 
   # This merge fails when it attempts to descend into the missing
   # directory.  That's OK, there is no real need to support merge into
@@ -1771,13 +1791,21 @@ def merge_into_missing(sbox):
   # Check working copy is not locked.
   expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
   expected_status.add({
-    'A/B/F'     : Item(status=' M', wc_rev=1),
-    'A/B/F/foo' : Item(status='!M', wc_rev=2),
+    'A/B/F'     : Item(status='  ', wc_rev=1),
+    'A/B/F/foo' : Item(status='! ', wc_rev=2),
     'A/B/F/Q'   : Item(status='! ', wc_rev='?'),
-# In some intermediate WC-NG state (since r937468) this was:
-#  'A/B/F/Q'   : Item(status='! ', wc_rev='2', entry_rev='?'),
-# but the expected value is now back what it was.
     })
+  if single_db:
+    # Revision known and mergeinfo recorded
+    expected_status.tweak('A/B/F/Q', wc_rev='2')
+    # Missing data still available
+    expected_status.add({
+      'A/B/F/Q'        : Item(status='! ', wc_rev='2'),
+      'A/B/F/Q/baz'    : Item(status='! ', wc_rev='3'),
+      'A/B/F/Q/R'      : Item(status='! ', wc_rev='3'),
+      'A/B/F/Q/R/bar'  : Item(status='! ', wc_rev='3'),
+    })
+
   svntest.actions.run_and_verify_status(wc_dir, expected_status)
 
 #----------------------------------------------------------------------
@@ -2431,11 +2459,11 @@ def merge_dir_replace(sbox):
   expected_status = wc.State(C_path, {
     ''    : Item(status=' M', wc_rev=3),
     'foo' : Item(status='R ', wc_rev='-', copied='+'),
-    'foo/new file 2' : Item(status='D ', wc_rev='-', copied='+'),
-    'foo/file foo'       : Item(status='A ', wc_rev='-', copied='+'),
-    'foo/bar'            : Item(status='A ', wc_rev='-', copied='+'),
-    'foo/bar/new file 3' : Item(status='A ', wc_rev='-', copied='+'),
-    'foo/new file'   : Item(status='D ', wc_rev='-', copied='+'),
+    'foo/new file 2' : Item(status='D ', wc_rev='3'),
+    'foo/file foo'       : Item(status='  ', wc_rev='-', copied='+'),
+    'foo/bar'            : Item(status='  ', wc_rev='-', copied='+'),
+    'foo/bar/new file 3' : Item(status='  ', wc_rev='-', copied='+'),
+    'foo/new file'   : Item(status='D ', wc_rev='3'),
     })
   expected_skip = wc.State(C_path, { })
   svntest.actions.run_and_verify_merge(C_path, '2', '5', F_url, None,
@@ -2454,9 +2482,6 @@ def merge_dir_replace(sbox):
   expected_output = svntest.wc.State(wc_dir, {
     'A/C'                    : Item(verb='Sending'),
     'A/C/foo'                : Item(verb='Replacing'),
-    'A/C/foo/file foo'       : Item(verb='Adding'),
-    'A/C/foo/bar'            : Item(verb='Adding'),
-    'A/C/foo/bar/new file 3' : Item(verb='Adding'),
     })
   expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
   expected_status.add({
@@ -3023,7 +3048,7 @@ def property_merge_undo_redo(sbox):
                                        None, None, # no B singleton handler
                                        1, # check props
                                        0, # dry_run
-                                       '--ignore-ancestry')
+                                       '--ignore-ancestry', wc_dir)
 
 
 
@@ -3407,7 +3432,7 @@ def merge_ignore_whitespace(sbox):
                                        expected_skip,
                                        None, None, None, None, None,
                                        0, 0,
-                                       '-x', '-w')
+                                       '-x', '-w', wc_dir)
 
 #----------------------------------------------------------------------
 # use -x --ignore-eol-style option for ignoring eolstyle during merge
@@ -3489,7 +3514,7 @@ def merge_ignore_eolstyle(sbox):
                                        expected_skip,
                                        None, None, None, None, None,
                                        0, 0,
-                                       '-x', '--ignore-eol-style')
+                                       '-x', '--ignore-eol-style', wc_dir)
 
 #----------------------------------------------------------------------
 # eol-style handling during merge with conflicts, scenario 1:
@@ -4786,6 +4811,11 @@ def mergeinfo_inheritance(sbox):
                                         wc_status,
                                         None,
                                         wc_dir)
+                        
+  # In single-db mode you can't create a disconnected working copy by just
+  # copying a subdir                
+  if svntest.main.wc_is_singledb(wc_dir):
+    return
 
   # Copy the subtree A_COPY/B/E from the working copy, making the
   # disconnected WC E_only.
@@ -5028,7 +5058,8 @@ def mergeinfo_elision(sbox):
                                        expected_status,
                                        expected_skip,
                                        None, None, None, None,
-                                       None, 1, 1, '--record-only')
+                                       None, 1, 1, '--record-only',
+                                       A_COPY_path)
 
   # Reverse merge r5 out of A_COPY/B/E/beta.  The mergeinfo on
   # A_COPY/B/E/beta which previously elided will now return,
@@ -7102,7 +7133,7 @@ def merge_with_depth_files(sbox):
                                        expected_disk,
                                        expected_status, expected_skip,
                                        None, None, None, None, None, 1, 1,
-                                       '--depth', 'files')
+                                       '--depth', 'files', Acopy_path)
 
 #----------------------------------------------------------------------
 # Test for issue #2976 Subtrees can lose non-inheritable ranges.
@@ -7197,7 +7228,7 @@ def merge_away_subtrees_noninheritable_r
                                        expected_disk,
                                        expected_status, expected_skip,
                                        None, None, None, None, None, 1, 1,
-                                       '--depth', 'immediates')
+                                       '--depth', 'immediates', D_COPY_path)
 
   # Repeat the previous merge but at default depth of infinity.  The change
   # to A_COPY/D/H/omega should now happen and the non-inheritable ranges on
@@ -7467,7 +7498,7 @@ def merge_away_subtrees_noninheritable_r
                                        expected_disk,
                                        expected_status, expected_skip,
                                        None, None, None, None, None, 1, 1,
-                                       '--depth', 'empty')
+                                       '--depth', 'empty', H_COPY_2_path)
   svntest.actions.run_and_verify_svn(None, None, [], 'commit', '-m',
                                      'log msg', wc_dir);
   svntest.actions.run_and_verify_svn(None, None, [], 'up', wc_dir)
@@ -8697,7 +8728,8 @@ def propchange_of_subdir_raises_conflict
                                        expected_status,
                                        expected_skip,
                                        None, None, None, None, None,
-                                       1, 1, '--depth', 'files')
+                                       1, 1, '--depth', 'files',
+                                       A_COPY_B_path)
 
   # Merge /A/B to /A_COPY/B ie., r1 to r3 with infinite depth
   expected_output = wc.State(A_COPY_B_path, {
@@ -8920,7 +8952,8 @@ def merge_target_with_non_inheritable_me
                                        expected_status,
                                        expected_skip,
                                        None, None, None, None, None,
-                                       1, 1, '--depth', 'immediates')
+                                       1, 1, '--depth', 'immediates',
+                                       A_COPY_B_path)
 
   # Merge /A/B to /A_COPY/B ie., r1 to r3 with infinite depth
   expected_output = wc.State(A_COPY_B_path, {
@@ -9141,7 +9174,7 @@ def ignore_ancestry_and_mergeinfo(sbox):
                                        expected_status,
                                        expected_skip,
                                        None, None, None, None, None, 1, 1,
-                                       '--ignore-ancestry')
+                                       '--ignore-ancestry', A_COPY_B_path)
 
 #----------------------------------------------------------------------
 def merge_from_renamed_branch_fails_while_avoiding_repeat_merge(sbox):
@@ -13593,7 +13626,7 @@ def subtree_gets_changes_even_if_ultimat
                                        expected_disk,
                                        expected_status, expected_skip,
                                        None, None, None, None, None, 1, 0,
-                                       '-c3,7')
+                                       '-c3,7', H_COPY_path)
   svntest.actions.run_and_verify_svn(
     None,
     expected_merge_output([[-7]],
@@ -14737,7 +14770,7 @@ def record_only_merge(sbox):
                                        expected_status,
                                        expected_skip,
                                        None, None, None, None, None, 1, 0,
-                                       '--record-only')
+                                       '--record-only', A2_path)
 
 #----------------------------------------------------------------------
 # Test for issue #3514 'svn merge --accept [ base | theirs-full ]
@@ -14833,7 +14866,8 @@ def merge_automatic_conflict_resolution(
                                        svntest.tree.detect_conflict_files,
                                        list(psi_conflict_support_files),
                                        None, None, 1, 1,
-                                       '--accept', 'postpone')
+                                       '--accept', 'postpone',
+                                       A_COPY_path)
   svntest.actions.run_and_verify_svn(None, None, [],
                                      'revert', '--recursive', wc_dir)
 
@@ -14851,7 +14885,8 @@ def merge_automatic_conflict_resolution(
                                        expected_skip,
                                        None, None, None,
                                        None, None, 1, 0,
-                                       '--accept', 'mine-conflict')
+                                       '--accept', 'mine-conflict',
+                                       A_COPY_path)
   svntest.actions.run_and_verify_svn(None, None, [],
                                      'revert', '--recursive', wc_dir)
   svntest.actions.run_and_verify_merge(A_COPY_path, '2', '3',
@@ -14864,7 +14899,8 @@ def merge_automatic_conflict_resolution(
                                        expected_skip,
                                        None, None, None,
                                        None, None, 1, 0,
-                                       '--accept', 'mine-full')
+                                       '--accept', 'mine-full',
+                                       A_COPY_path)
   svntest.actions.run_and_verify_svn(None, None, [],
                                      'revert', '--recursive', wc_dir)
 
@@ -14882,35 +14918,10 @@ def merge_automatic_conflict_resolution(
                                        expected_skip,
                                        None, None, None,
                                        None, None, 1, 0,
-                                       '--accept', 'theirs-conflict')
+                                       '--accept', 'theirs-conflict',
+                                       A_COPY_path)
   svntest.actions.run_and_verify_svn(None, None, [],
                                      'revert', '--recursive', wc_dir)
-  # Issue #3514 fails here with an error similar to:
-  #
-  # ..\..\..\subversion\svn\util.c:900: (apr_err=125007)
-  #..\..\..\subversion\libsvn_client\merge.c:9408: (apr_err=125007)
-  #..\..\..\subversion\libsvn_client\merge.c:8054: (apr_err=125007)
-  #..\..\..\subversion\libsvn_client\merge.c:7733: (apr_err=125007)
-  #..\..\..\subversion\libsvn_client\merge.c:4870: (apr_err=125007)
-  #..\..\..\subversion\libsvn_repos\reporter.c:1266: (apr_err=125007)
-  #..\..\..\subversion\libsvn_repos\reporter.c:1197: (apr_err=125007)
-  #..\..\..\subversion\libsvn_repos\reporter.c:1135: (apr_err=125007)
-  #..\..\..\subversion\libsvn_repos\reporter.c:854: (apr_err=125007)
-  #..\..\..\subversion\libsvn_repos\reporter.c:1135: (apr_err=125007)
-  #..\..\..\subversion\libsvn_repos\reporter.c:854: (apr_err=125007)
-  #..\..\..\subversion\libsvn_repos\reporter.c:1135: (apr_err=125007)
-  #..\..\..\subversion\libsvn_client\repos_diff.c:861: (apr_err=125007)
-  #..\..\..\subversion\libsvn_client\merge.c:1511: (apr_err=125007)
-  #..\..\..\subversion\libsvn_wc\merge.c:1309: (apr_err=125007)
-  #..\..\..\subversion\libsvn_wc\merge.c:1252: (apr_err=125007)
-  #..\..\..\subversion\libsvn_wc\merge.c:914: (apr_err=125007)
-  #..\..\..\subversion\libsvn_wc\merge.c:794: (apr_err=125007)
-  #..\..\..\subversion\libsvn_wc\merge.c:460: (apr_err=125007)
-  #..\..\..\subversion\libsvn_wc\log.c:921: (apr_err=125007)
-  #..\..\..\subversion\libsvn_wc\log.c:878: (apr_err=125007)
-  #svn: Path 'C:\DOCUME~1\pburba\LOCALS~1\Temp\tempfile.149.tmp' is not a
-  # child of 'C:\SVN\src-trunk\Debug\subversion\tests\cmdline\svn-test-work\
-  # working_copies\merge_tests-137\A_COPY\D\H'
   svntest.actions.run_and_verify_merge(A_COPY_path, '2', '3',
                                        sbox.repo_url + '/A', None,
                                        expected_output,
@@ -14921,20 +14932,16 @@ def merge_automatic_conflict_resolution(
                                        expected_skip,
                                        None, None, None,
                                        None, None, 1, 0,
-                                       '--accept', 'theirs-full')
+                                       '--accept', 'theirs-full',
+                                       A_COPY_path)
   svntest.actions.run_and_verify_svn(None, None, [],
                                      'revert', '--recursive', wc_dir)
   # Test --accept base
-  #
-  # Make a working change to A_COPY/D/H/psi.
-  svntest.main.file_write(psi_COPY_path, "WORKING.\n")
   expected_output = wc.State(A_COPY_path, {'D/H/psi' : Item(status='U ')})
   expected_elision_output = wc.State(A_COPY_path, {
     })
-  expected_disk.tweak('D/H/psi', contents="BASE")
+  expected_disk.tweak('D/H/psi', contents="This is the file 'psi'.\n")
   expected_status.tweak('D/H/psi', status='M ')
-  # Issue #3514 fails here with an error similar to the one above for
-  # --accept theirs-full.
   svntest.actions.run_and_verify_merge(A_COPY_path, '2', '3',
                                        sbox.repo_url + '/A', None,
                                        expected_output,
@@ -14945,7 +14952,8 @@ def merge_automatic_conflict_resolution(
                                        expected_skip,
                                        None, None, None,
                                        None, None, 1, 0,
-                                       '--accept', 'base')
+                                       '--accept', 'base',
+                                       A_COPY_path)
 
 #----------------------------------------------------------------------
 # Test for issue #3440 'Skipped paths get incorrect override mergeinfo
@@ -14958,6 +14966,7 @@ def skipped_files_get_correct_mergeinfo(
 
   # Some paths we'll care about
   A_COPY_path   = os.path.join(wc_dir, "A_COPY")
+  H_COPY_path   = os.path.join(wc_dir, "A_COPY", "D", "H")
   psi_COPY_path = os.path.join(wc_dir, "A_COPY", "D", "H", "psi")
   psi_path      = os.path.join(wc_dir, "A", "D", "H", "psi")
 
@@ -14985,15 +14994,21 @@ def skipped_files_get_correct_mergeinfo(
     [], 'merge', '-c3', sbox.repo_url + '/A', A_COPY_path)
   svntest.main.run_svn(None, 'commit', '-m', 'initial merge', wc_dir)
 
-  # Update WC to uniform revision and then delete, via the OS, A_COPY/D/H/psi
-  # and then merge all available revisions from A to A_COPY.  A_COPY/D/H/psi
-  # should be reported as skipped and get explicit mergeinfo set on it
-  # reflecting what it previously inherited from A_COPY after the first
-  # merge, i.e. '/A/D/H/psi:3'.  Issue #3440 occurred when empty mergeinfo
-  # was set on A_COPY/D/H/psi, making it appear that r3 was never merged.
+  # Update WC to uniform revision and then set the depth on A_COPY/D/H to
+  # empty.  Then merge all available revisions from A to A_COPY.
+  # A_COPY/D/H/psi and A_COPY/D/H/omega are not present due to their
+  # parent's depth and should be reported as skipped.  A_COPY/D/H should
+  # get explicit mergeinfo set on it reflecting what it previously inherited
+  # from A_COPY after the first merge, i.e. '/A/D/H:3', plus non-inheritable
+  # mergeinfo describing what was done during this merge,
+  # i.e. '/A/D/H:2*,4-8*'.
+  #
+  # Issue #3440 occurred when empty mergeinfo was set on A_COPY/D/H, making
+  # it appear that r3 was never merged.
   svntest.actions.run_and_verify_svn(None, ["At revision 8.\n"], [],
                                      'up', wc_dir)
-  os.remove(psi_COPY_path)
+  svntest.actions.run_and_verify_svn(None, None, [],
+                                     'up', '--set-depth=empty', H_COPY_path)
   expected_status = wc.State(A_COPY_path, {
     ''          : Item(status=' M'),
     'B'         : Item(status='  '),
@@ -15010,10 +15025,7 @@ def skipped_files_get_correct_mergeinfo(
     '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 '),
+    'D/H'       : Item(status=' M'),
     })
   expected_status.tweak(wc_rev=8)
   expected_disk = wc.State('', {
@@ -15032,71 +15044,18 @@ def skipped_files_get_correct_mergeinfo(
     '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'  : Nothing here, this file was deleted via the OS.
-    'D/H/omega' : Item("New content"),
+    'D/H'       : Item(props={SVN_PROP_MERGEINFO : '/A/D/H:2*,3,4-8*'}),
     })
   expected_skip = wc.State(A_COPY_path,
-                           {'D/H/psi' : Item()})
+                           {'D/H/psi'   : Item(),
+                            'D/H/omega' : Item()})
   expected_output = wc.State(A_COPY_path,
                              {'B/E/beta'  : Item(status='U '),
-                              'D/G/rho'   : Item(status='U '),
-                              'D/H/omega' : Item(status='U '),})
-  expected_mergeinfo_output = wc.State(A_COPY_path, {
-    ''        : Item(status=' U'),
-    'D/H/psi' : Item(status=' U'),
-    })
-  expected_elision_output = 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, 1)
-  # run_and_verify_merge cannot check the properties on A_COPY/D/H/psi
-  # since that file is not on disk, so we'll check the file's mergeinfo
-  # directly with svn propget.
-  svntest.actions.run_and_verify_svn(
-    'Incorrect override mergeinfo set on skipped path',
-    ["/A/D/H/psi:3\n"], [], 'pg', 'svn:mergeinfo', psi_COPY_path)
-
-  # Now test another aspect of issue #3440, that a skipped path with
-  # explicit mergeinfo doesn't get it's mergeinfo updated.
-  #
-  # First revert all changes to the WC and then merge -r2:6 from A/D/H/psi
-  # to A_COPY/D/H/psi, creating explicit mergeinfo of '/A/D/H/psi:3-6' on
-  # the latter.  Commit this merge as r9 and then update the WC.
-  svntest.actions.run_and_verify_svn(None, None, [],
-                                     'revert', '-R', wc_dir)
-  svntest.actions.run_and_verify_svn(
-    None,
-    expected_merge_output([[3,6]],
-                          [' U   ' + psi_COPY_path + '\n',
-                           ' G   ' + psi_COPY_path + '\n']),
-    [], 'merge', '-r2:6', sbox.repo_url + '/A/D/H/psi', psi_COPY_path)
-  svntest.main.run_svn(None, 'commit', '-m',
-                       'subtree merge to create explicit mergeinfo',
-                       wc_dir)
-  svntest.actions.run_and_verify_svn(None, ["At revision 9.\n"], [],
-                                     'up', wc_dir)
-
-  # Remove A_COPY/D/H/psi again and then merge all available revisions
-  # from A to A_COPY.  The results should be mostly similar to the
-  # previous merge we did above, execept that A_COPY/D/H/psi should not
-  # have it's mergeinfo changed.
-  os.remove(psi_COPY_path)
-  expected_status.tweak(wc_rev=9)
-  expected_status.tweak('D/H/psi', status='! ')
-  expected_disk.tweak('', props={SVN_PROP_MERGEINFO : '/A:2-9'})
+                              'D/G/rho'   : Item(status='U ')})
   expected_mergeinfo_output = wc.State(A_COPY_path, {
-    ''        : Item(status=' U'),
-    'D/H/psi' : Item(status=' U'),
+    ''    : Item(status=' U'),
+    'D/H' : Item(status=' G'), # ' G' because override mergeinfo gets set
+                               # on this, the root of a 'missing' subtree.
     })
   expected_elision_output = wc.State(A_COPY_path, {
     })
@@ -15111,16 +15070,6 @@ def skipped_files_get_correct_mergeinfo(
                                        None, None, None, None, None,
                                        1, 1)
 
-  # run_and_verify_merge cannot check the properties on A_COPY/D/H/psi
-  # since that file is not on disk, so we'll check the file's mergeinfo
-  # directly with svn propget.  Issue #3440 also occurred here, when an
-  # the missing file's mergeinfo was updated, making it appear that r2
-  # and r7-9 were also merged into A_COPY/D/H/psi, which is clearly not
-  # the case since psi isn't present.
-  svntest.actions.run_and_verify_svn(
-    'Mergeinfo on skipped path altered',
-    ["/A/D/H/psi:3-6\n"], [], 'pg', 'svn:mergeinfo', psi_COPY_path)
-
 #----------------------------------------------------------------------
 # Test for issue #3115 'Case only renames resulting from merges don't
 # work or break the WC on case-insensitive file systems'.
@@ -15475,7 +15424,7 @@ def foreign_repos_del_and_props(sbox):
 # Test for issue #3642 'immediate depth merges don't create proper subtree
 # mergeinfo'. See http://subversion.tigris.org/issues/show_bug.cgi?id=3642
 def immediate_depth_merge_creates_minimal_subtree_mergeinfo(sbox):
-  "no spurious mergeinfo from immediate depth merges "
+  "no spurious mergeinfo from immediate depth merges"
 
   sbox.build()
   wc_dir = sbox.wc_dir
@@ -15533,7 +15482,8 @@ def immediate_depth_merge_creates_minima
                                        expected_status,
                                        expected_skip,
                                        None, None, None, None, None,
-                                       1, 1, '--depth', 'immediates')
+                                       1, 1, '--depth', 'immediates',
+                                       B_COPY_path)
 
 #----------------------------------------------------------------------
 # Test for issue #3646 'cyclic --record-only merges create self-referential
@@ -15627,7 +15577,7 @@ def record_only_merge_creates_self_refer
                                        expected_A_status,
                                        expected_A_skip,
                                        None, None, None, None, None, 1, 1,
-                                       '--record-only')
+                                       '--record-only', A_path)
 
 #----------------------------------------------------------------------
 # Test for issue #3657 'phantom svn:eol-style changes cause spurious merge
@@ -15754,6 +15704,194 @@ def copy_causes_phantom_eol_conflict(sbo
                                        expected_skip,
                                        None, None, None, None, None, 1, 1)
   
+
+#----------------------------------------------------------------------
+def merge_into_locally_added_file(sbox):
+  "merge into locally added file"
+
+  sbox.build()
+  wc_dir = sbox.wc_dir
+
+  # Some paths we'll care about
+  pi_path = sbox.ospath("A/D/G/pi")
+  new_path = sbox.ospath("A/D/G/new")
+
+  shutil.copy(pi_path, new_path)
+  svntest.main.file_append(pi_path, "foo\n")
+  sbox.simple_commit(); # r2
+
+  sbox.simple_add(new_path)
+
+  expected_output = wc.State(wc_dir, {
+    'A/D/G/new' : Item(status='G '),
+    })
+  expected_mergeinfo_output = wc.State(wc_dir, {
+    'A/D/G/new'   : Item(status=' U'),
+    })
+  expected_elision_output = wc.State(wc_dir, {})
+  expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
+  expected_status.add({ 'A/D/G/new' : Item(status='A ', wc_rev=0)})
+  expected_status.tweak('A/D/G/pi', wc_rev=2)
+  expected_disk = svntest.main.greek_state.copy()
+  expected_disk.tweak('A/D/G/pi', contents="This is the file 'pi'.\nfoo\n")
+  expected_disk.add({'A/D/G/new' : Item("This is the file 'pi'.\nfoo\n",
+                     props={SVN_PROP_MERGEINFO : '/A/D/G/pi:2'})})
+  expected_skip = wc.State(wc_dir, {})
+
+  svntest.actions.run_and_verify_merge(wc_dir, '1', '2',
+                                       sbox.repo_url + '/A/D/G/pi', None,
+                                       expected_output,
+                                       expected_mergeinfo_output,
+                                       expected_elision_output,
+                                       expected_disk,
+                                       expected_status,
+                                       expected_skip,
+                                       None, None, None, None, None,
+                                       True, True, new_path)
+  sbox.simple_commit()
+
+#----------------------------------------------------------------------
+def merge_into_locally_added_directory(sbox):
+  "merge into locally added directory"
+
+  sbox.build()
+  wc_dir = sbox.wc_dir
+
+  # Some paths we'll care about
+  G_path = sbox.ospath("A/D/G")
+  pi_path = sbox.ospath("A/D/G/pi")
+  new_dir_path = sbox.ospath("A/D/new_dir")
+
+  svntest.main.file_append_binary(pi_path, "foo\n")
+  sbox.simple_commit(); # r2
+
+  os.mkdir(new_dir_path)
+  svntest.main.file_append_binary(os.path.join(new_dir_path, 'pi'),
+                                  "This is the file 'pi'.\n")
+  svntest.main.file_append_binary(os.path.join(new_dir_path, 'rho'),
+                                  "This is the file 'rho'.\n")
+  svntest.main.file_append_binary(os.path.join(new_dir_path, 'tau'),
+                                  "This is the file 'tau'.\n")
+  sbox.simple_add(new_dir_path)
+
+  expected_output = wc.State(wc_dir, {
+    'A/D/new_dir/pi' : Item(status='G '),
+    })
+  expected_mergeinfo_output = wc.State(wc_dir, {
+    'A/D/new_dir'   : Item(status=' U'),
+    })
+  expected_elision_output = wc.State(wc_dir, {})
+  expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
+  expected_status.add({ 'A/D/new_dir' : Item(status='A ', wc_rev=0)})
+  expected_status.add({ 'A/D/new_dir/pi' : Item(status='A ', wc_rev=0)})
+  expected_status.add({ 'A/D/new_dir/rho' : Item(status='A ', wc_rev=0)})
+  expected_status.add({ 'A/D/new_dir/tau' : Item(status='A ', wc_rev=0)})
+  expected_status.tweak('A/D/G/pi', wc_rev=2)
+  expected_disk = svntest.main.greek_state.copy()
+  expected_disk.tweak('A/D/G/pi', contents="This is the file 'pi'.\nfoo\n")
+  expected_disk.add({'A/D/new_dir' :
+                       Item(props={SVN_PROP_MERGEINFO : '/A/D/G:2'})})
+  expected_disk.add({'A/D/new_dir/pi' :
+                     Item(contents="This is the file 'pi'.\nfoo\n")})
+  expected_disk.add({'A/D/new_dir/rho' :
+                     Item(contents="This is the file 'rho'.\n")})
+  expected_disk.add({'A/D/new_dir/tau' :
+                     Item(contents="This is the file 'tau'.\n")})
+  expected_skip = wc.State(wc_dir, {})
+
+  svntest.actions.run_and_verify_merge(wc_dir, '1', '2',
+                                       sbox.repo_url + '/A/D/G', None,
+                                       expected_output,
+                                       expected_mergeinfo_output,
+                                       expected_elision_output,
+                                       expected_disk,
+                                       expected_status,
+                                       expected_skip,
+                                       None, None, None, None, None,
+                                       True, True, new_dir_path)
+  sbox.simple_commit()
+
+#----------------------------------------------------------------------
+# Test for issue #2915 'Handle mergeinfo for subtrees missing due to removal
+# by non-svn command'
+def merge_with_os_deleted_subtrees(sbox):
+  "merge tracking fails if target missing subtrees"
+
+  # r1: Create a greek tree.
+  sbox.build()
+  wc_dir = sbox.wc_dir
+
+  # r2 - r6: Copy A to A_COPY and then make some text changes under A.
+  set_up_branch(sbox)
+
+  # Some paths we'll care about
+  A_COPY_path   = os.path.join(wc_dir, "A_COPY")
+  C_COPY_path   = os.path.join(wc_dir, "A_COPY", "C")
+  psi_COPY_path = os.path.join(wc_dir, "A_COPY", "D", "H", "psi")
+  mu_COPY_path  = os.path.join(wc_dir, "A_COPY", "mu")
+  G_COPY_path   = os.path.join(wc_dir, "A_COPY", "D", "G")
+
+  # Remove several subtrees from disk.
+  svntest.main.safe_rmtree(C_COPY_path)
+  svntest.main.safe_rmtree(G_COPY_path)
+  os.remove(psi_COPY_path)
+  os.remove(mu_COPY_path)
+
+  # Be sure the regex paths are properly escaped on Windows, see the
+  # note about "The Backslash Plague" in expected_merge_output().
+  if sys.platform == 'win32':
+    re_sep = '\\\\'
+  else:
+    re_sep = os.sep
+
+  # Common part of the expected error message for all cases we will test.
+  err_re = "svn: Merge tracking not allowed with missing subtrees; " + \
+           "try restoring these items first:"                        + \
+           "|(\n)"                                                   + \
+           "|(.*apr_err.*\n)" # In case of debug build
+
+  # Case 1: Infinite depth merge into infinite depth WC target.
+  # Every missing subtree under the target should be reported as missing.
+  missing = "|(.*A_COPY" + re_sep + "mu\n)"                                + \
+            "|(.*A_COPY" + re_sep + "D" + re_sep + "G\n)"                  + \
+            "|(.*A_COPY" + re_sep + "C\n)"                                 + \
+            "|(.*A_COPY" + re_sep + "D" + re_sep + "H" + re_sep + "psi\n)"
+  exit_code, out, err = svntest.actions.run_and_verify_svn(
+    "Missing subtrees should raise error", [], svntest.verify.AnyOutput,
+    'merge', sbox.repo_url + '/A', A_COPY_path)
+  svntest.verify.verify_outputs("Merge failed but not in the way expected",
+                                err, None, err_re + missing, None,
+                                True) # Match *all* lines of stderr
+
+  # Case 2: Immediates depth merge into infinite depth WC target.
+  # Only the two immediate children of the merge target should be reported
+  # as missing.
+  missing = "|(.*A_COPY" + re_sep + "mu\n)" + \
+            "|(.*A_COPY" + re_sep + "C\n)"
+  exit_code, out, err = svntest.actions.run_and_verify_svn(
+    "Missing subtrees should raise error", [], svntest.verify.AnyOutput,
+    'merge', sbox.repo_url + '/A', A_COPY_path, '--depth=immediates')
+  svntest.verify.verify_outputs("Merge failed but not in the way expected",
+                                err, None, err_re + missing, None, True)
+
+  # Case 3: Files depth merge into infinite depth WC target.
+  # Only the single file child of the merge target should be reported
+  # as missing.
+  missing = "|(.*A_COPY" + re_sep + "mu\n)"
+  exit_code, out, err = svntest.actions.run_and_verify_svn(
+    "Missing subtrees should raise error", [], svntest.verify.AnyOutput,
+    'merge', sbox.repo_url + '/A', A_COPY_path, '--depth=files')
+  svntest.verify.verify_outputs("Merge failed but not in the way expected",
+                                err, None, err_re + missing, None, True)
+
+  # Case 4: Empty depth merge into infinite depth WC target.
+  # Only the...oh, wait, the target is present and that is as deep
+  # as the merge goes, so this merge should succeed!
+  svntest.actions.run_and_verify_svn(
+    "Depth empty merge should succeed as long at the target is present",
+    svntest.verify.AnyOutput, [], 'merge', sbox.repo_url + '/A',
+    A_COPY_path, '--depth=empty')
+
 ########################################################################
 # Run the tests
 
@@ -15804,8 +15942,8 @@ test_list = [ None,
               SkipUnless(cherry_pick_text_conflict,
                          server_has_mergeinfo),
               merge_file_replace,
-              XFail(SkipUnless(merge_dir_replace,
-                               server_has_mergeinfo)),
+              SkipUnless(merge_dir_replace,
+                         server_has_mergeinfo),
               merge_dir_and_file_replace,
               merge_file_replace_to_mixed_rev_wc,
               SkipUnless(merge_ignore_whitespace,
@@ -15932,15 +16070,17 @@ test_list = [ None,
               copy_then_replace_via_merge,
               SkipUnless(record_only_merge,
                          server_has_mergeinfo),
-              XFail(merge_automatic_conflict_resolution),
+              merge_automatic_conflict_resolution,
               skipped_files_get_correct_mergeinfo,
-              XFail(committed_case_only_move_and_revert,
-                    is_fs_case_insensitive),
+              committed_case_only_move_and_revert,
               merge_into_wc_for_deleted_branch,
               foreign_repos_del_and_props,
               immediate_depth_merge_creates_minimal_subtree_mergeinfo,
               record_only_merge_creates_self_referential_mergeinfo,
               copy_causes_phantom_eol_conflict,
+              merge_into_locally_added_file,
+              merge_into_locally_added_directory,
+              merge_with_os_deleted_subtrees,
              ]
 
 if __name__ == '__main__':

Modified: subversion/branches/ignore-mergeinfo/subversion/tests/cmdline/merge_tree_conflict_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/ignore-mergeinfo/subversion/tests/cmdline/merge_tree_conflict_tests.py?rev=1044516&r1=1044515&r2=1044516&view=diff
==============================================================================
--- subversion/branches/ignore-mergeinfo/subversion/tests/cmdline/merge_tree_conflict_tests.py (original)
+++ subversion/branches/ignore-mergeinfo/subversion/tests/cmdline/merge_tree_conflict_tests.py Fri Dec 10 21:23:03 2010
@@ -623,6 +623,9 @@ def mergeinfo_recording_in_skipped_merge
     'D/H/omega': Item("This is the file 'omega'.\n"),
     'D/H/psi'  : Item("This is the file 'psi'.\n"),
     })
+  if svntest.main.wc_is_singledb(sbox.wc_dir):
+    # Delete removes directories in single-db
+    expected_disk.remove('B/E')
   expected_skip = wc.State(A_COPY_path, {})
   svntest.actions.run_and_verify_merge(A_COPY_path, None, None,
                                        A_url, None,
@@ -796,9 +799,11 @@ leaf_edit = svntest.actions.deep_trees_l
 tree_del = svntest.actions.deep_trees_tree_del
 leaf_del = svntest.actions.deep_trees_leaf_del
 
-state_after_leaf_edit = svntest.actions.deep_trees_after_leaf_edit
-state_after_leaf_del = svntest.actions.deep_trees_after_leaf_del
-state_after_tree_del = svntest.actions.deep_trees_after_tree_del
+disk_after_leaf_edit = svntest.actions.deep_trees_after_leaf_edit
+disk_after_leaf_del = svntest.actions.deep_trees_after_leaf_del
+disk_after_tree_del = svntest.actions.deep_trees_after_tree_del
+disk_after_leaf_del_no_ci = svntest.actions.deep_trees_after_leaf_del_no_ci
+disk_after_tree_del_no_ci = svntest.actions.deep_trees_after_tree_del_no_ci
 
 deep_trees_conflict_output = svntest.actions.deep_trees_conflict_output
 
@@ -821,7 +826,7 @@ def tree_conflicts_on_merge_local_ci_4_1
 
   expected_output = deep_trees_conflict_output
 
-  expected_disk = state_after_tree_del
+  expected_disk = disk_after_tree_del
 
   expected_status = svntest.wc.State('', {
     ''                  : Item(status=' M', wc_rev='3'),
@@ -858,7 +863,7 @@ def tree_conflicts_on_merge_local_ci_4_2
 
   expected_output = deep_trees_conflict_output
 
-  expected_disk = state_after_tree_del
+  expected_disk = disk_after_tree_del
 
   expected_status = svntest.wc.State('', {
     ''                  : Item(status=' M', wc_rev='3'),
@@ -897,7 +902,7 @@ def tree_conflicts_on_merge_local_ci_5_1
 
   expected_output = deep_trees_conflict_output
 
-  expected_disk = state_after_leaf_edit
+  expected_disk = disk_after_leaf_edit
 
   # We should detect 6 tree conflicts, and nothing should be deleted (when
   # we skip tree conflict victims).
@@ -947,14 +952,7 @@ def tree_conflicts_on_merge_local_ci_5_2
 
   expected_output = deep_trees_conflict_output
 
-  expected_disk = svntest.wc.State('', {
-    'F'                 : Item(),
-    'D'                 : Item(),
-    'DF/D1'             : Item(),
-    'DD/D1'             : Item(),
-    'DDF/D1/D2'         : Item(),
-    'DDD/D1/D2'         : Item(),
-    })
+  expected_disk = disk_after_leaf_del
 
   expected_status = svntest.wc.State('', {
     ''                  : Item(status=' M', wc_rev='3'),
@@ -995,7 +993,7 @@ def tree_conflicts_on_merge_local_ci_6(s
 
   expected_output = deep_trees_conflict_output
 
-  expected_disk = state_after_tree_del
+  expected_disk = disk_after_tree_del
 
   expected_status = svntest.wc.State('', {
     ''                  : Item(status=' M', wc_rev='3'),
@@ -1029,19 +1027,14 @@ def tree_conflicts_on_merge_local_ci_6(s
 def tree_conflicts_on_merge_no_local_ci_4_1(sbox):
   "tree conflicts 4.1: tree del (no ci), leaf edit"
 
+  sbox.build()
+
   # use case 4, as in notes/tree-conflicts/use-cases.txt
   # 4.1) local tree delete, incoming leaf edit
 
   expected_output = deep_trees_conflict_output
 
-  expected_disk = svntest.wc.State('', {
-    'F'                 : Item(),
-    'D/D1'              : Item(),
-    'DF/D1'             : Item(),
-    'DD/D1/D2'          : Item(),
-    'DDF/D1/D2'         : Item(),
-    'DDD/D1/D2/D3'      : Item(),
-    })
+  expected_disk = disk_after_tree_del_no_ci(sbox.wc_dir)
 
   expected_status = svntest.wc.State('', {
     ''                  : Item(status=' M', wc_rev='3'),
@@ -1083,18 +1076,13 @@ def tree_conflicts_on_merge_no_local_ci_
 def tree_conflicts_on_merge_no_local_ci_4_2(sbox):
   "tree conflicts 4.2: tree del (no ci), leaf del"
 
+  sbox.build()
+
   # 4.2) local tree delete, incoming leaf delete
 
   expected_output = deep_trees_conflict_output
 
-  expected_disk = svntest.wc.State('', {
-    'F'                 : Item(),
-    'D/D1'              : Item(),
-    'DF/D1'             : Item(),
-    'DD/D1/D2'          : Item(),
-    'DDF/D1/D2'         : Item(),
-    'DDD/D1/D2/D3'      : Item(),
-    })
+  expected_disk = disk_after_tree_del_no_ci(sbox.wc_dir)
 
   expected_status = svntest.wc.State('', {
     ''                  : Item(status=' M', wc_rev='3'),
@@ -1142,7 +1130,7 @@ def tree_conflicts_on_merge_no_local_ci_
 
   expected_output = deep_trees_conflict_output
 
-  expected_disk = state_after_leaf_edit
+  expected_disk = disk_after_leaf_edit
 
   expected_status = svntest.wc.State('', {
     ''                  : Item(status=' M', wc_rev='3'),
@@ -1150,23 +1138,23 @@ def tree_conflicts_on_merge_no_local_ci_
     'D/D1'              : Item(status=' M', treeconflict='C', wc_rev='3'),
     'D/D1/delta'        : Item(status='A ', wc_rev='0'),
     'DD'                : Item(status='  ', wc_rev='3'),
-    'DD/D1'             : Item(status=' M', treeconflict='C', wc_rev='3'),
-    'DD/D1/D2'          : Item(status='  ', wc_rev='3'),
+    'DD/D1'             : Item(status='  ', treeconflict='C', wc_rev='3'),
+    'DD/D1/D2'          : Item(status=' M', wc_rev='3'),
     'DD/D1/D2/epsilon'  : Item(status='A ', wc_rev='0'),
     'DDD'               : Item(status='  ', wc_rev='3'),
-    'DDD/D1'            : Item(status=' M', treeconflict='C', wc_rev='3'),
+    'DDD/D1'            : Item(status='  ', treeconflict='C', wc_rev='3'),
     'DDD/D1/D2'         : Item(status='  ', wc_rev='3'),
-    'DDD/D1/D2/D3'      : Item(status='  ', wc_rev='3'),
+    'DDD/D1/D2/D3'      : Item(status=' M', wc_rev='3'),
     'DDD/D1/D2/D3/zeta' : Item(status='A ', wc_rev='0'),
     'DDF'               : Item(status='  ', wc_rev='3'),
-    'DDF/D1'            : Item(status=' M', treeconflict='C', wc_rev='3'),
+    'DDF/D1'            : Item(status='  ', treeconflict='C', wc_rev='3'),
     'DDF/D1/D2'         : Item(status='  ', wc_rev='3'),
-    'DDF/D1/D2/gamma'   : Item(status='M ', wc_rev='3'),
+    'DDF/D1/D2/gamma'   : Item(status='MM', wc_rev='3'),
     'DF'                : Item(status='  ', wc_rev='3'),
-    'DF/D1'             : Item(status=' M', treeconflict='C', wc_rev='3'),
-    'DF/D1/beta'        : Item(status='M ', wc_rev='3'),
+    'DF/D1'             : Item(status='  ', treeconflict='C', wc_rev='3'),
+    'DF/D1/beta'        : Item(status='MM', wc_rev='3'),
     'F'                 : Item(status='  ', wc_rev='3'),
-    'F/alpha'           : Item(status='M ', treeconflict='C', wc_rev='3'),
+    'F/alpha'           : Item(status='MM', treeconflict='C', wc_rev='3'),
     })
 
   expected_skip = svntest.wc.State('', {
@@ -1191,14 +1179,7 @@ def tree_conflicts_on_merge_no_local_ci_
 
   expected_output = deep_trees_conflict_output
 
-  expected_disk = svntest.wc.State('', {
-    'F'                 : Item(),
-    'D/D1'              : Item(),
-    'DF/D1'             : Item(),
-    'DD/D1/D2'          : Item(),
-    'DDF/D1/D2'         : Item(),
-    'DDD/D1/D2/D3'      : Item(),
-    })
+  expected_disk = disk_after_leaf_del_no_ci(sbox.wc_dir)
 
   expected_status = svntest.wc.State('', {
     ''                  : Item(status=' M', wc_rev='3'),
@@ -1240,19 +1221,14 @@ def tree_conflicts_on_merge_no_local_ci_
 def tree_conflicts_on_merge_no_local_ci_6(sbox):
   "tree conflicts 6: tree del (no ci), tree del"
 
+  sbox.build()
+
   # use case 6, as in notes/tree-conflicts/use-cases.txt
   # local tree delete, incoming tree delete
 
   expected_output = deep_trees_conflict_output
 
-  expected_disk = svntest.wc.State('', {
-    'F'                 : Item(),
-    'D/D1'              : Item(),
-    'DF/D1'             : Item(),
-    'DD/D1/D2'          : Item(),
-    'DDF/D1/D2'         : Item(),
-    'DDD/D1/D2/D3'      : Item(),
-    })
+  expected_disk = disk_after_tree_del_no_ci(sbox.wc_dir)
 
   expected_status = svntest.wc.State('', {
     ''                  : Item(status=' M', wc_rev='3'),
@@ -1296,15 +1272,28 @@ def tree_conflicts_merge_edit_onto_missi
 
   # local tree missing (via shell delete), incoming leaf edit
 
+  # Note: In 1.7 merge tracking aware merges raise an error if the
+  # merge target has subtrees missing due to a shell delete.  To
+  # preserve the original intent of this test we'll run the merge
+  # with the --ignore-ancestry option, which neither considers nor
+  # records mergeinfo.  With this option the merge should "succeed"
+  # while skipping the missing paths.  Of course with no mergeinfo
+  # recorded and everything skipped, there is nothing to commit, so
+  # unlike most of the tree conflict tests we don't bother with the
+  # final commit step.
+
+  sbox.build()
   expected_output = wc.State('', {
   })
 
-  expected_disk = state_after_tree_del
+  expected_disk = disk_after_tree_del
 
+  # Don't expect any mergeinfo property changes because we run
+  # the merge with the --ignore-ancestry option.
   expected_status = svntest.wc.State('', {
-    ''                  : Item(status=' M', wc_rev=3),
+    ''                  : Item(status='  ', wc_rev=3),
     'F'                 : Item(status='  ', wc_rev=3),
-    'F/alpha'           : Item(status='!M', wc_rev=3),
+    'F/alpha'           : Item(status='! ', wc_rev=3),
     'D'                 : Item(status='  ', wc_rev=3),
     'D/D1'              : Item(status='! ', wc_rev='?'),
     'DF'                : Item(status='  ', wc_rev=3),
@@ -1323,6 +1312,19 @@ def tree_conflicts_merge_edit_onto_missi
     'DDD/D1/D2/D3'      : Item(status='  '),
     })
 
+  if svntest.main.wc_is_singledb(sbox.wc_dir):
+    expected_status.tweak('D/D1',            wc_rev=3, entry_rev='?')
+    expected_status.tweak('DF/D1',           wc_rev=3, entry_rev='?')
+    expected_status.tweak('DF/D1/beta',      wc_rev=3, status='! ')
+    expected_status.tweak('DD/D1',           wc_rev=3, entry_rev='?')
+    expected_status.tweak('DD/D1/D2',        wc_rev=3, status='! ')
+    expected_status.tweak('DDF/D1',          wc_rev=3, entry_rev='?')
+    expected_status.tweak('DDF/D1/D2',       wc_rev=3, status='! ')
+    expected_status.tweak('DDF/D1/D2/gamma', wc_rev=3, status='! ')
+    expected_status.tweak('DDD/D1',          wc_rev=3, entry_rev='?')
+    expected_status.tweak('DDD/D1/D2',       wc_rev=3, status='! ')
+    expected_status.tweak('DDD/D1/D2/D3',    wc_rev=3, status='! ')
+
   expected_skip = svntest.wc.State('', {
     'F/alpha'           : Item(),
     })
@@ -1337,18 +1339,7 @@ def tree_conflicts_merge_edit_onto_missi
                expected_disk,
                expected_status,
                expected_skip,
-
-               ### This should not be happening!
-               ### The commit succeeds (it only commits mergeinfo).
-               ### But then the work queue freaks out while trying to install
-               ### F/alpha into the WC, because F/alpha is missing from disk.
-               ### We end up with a working copy that cannot be cleaned up.
-               ### To make this test pass for now we'll expect this error.
-               ### When the problem is fixed this test will start to fail
-               ### and should be adjusted.
-               commit_block_string=".*Error bumping revisions post-commit",
-
-             ) ], False)
+             ) ], False, do_commit_conflicts=False, ignore_ancestry=True)
 
 #----------------------------------------------------------------------
 def tree_conflicts_merge_del_onto_missing(sbox):
@@ -1356,15 +1347,28 @@ def tree_conflicts_merge_del_onto_missin
 
   # local tree missing (via shell delete), incoming leaf edit
 
+  # Note: In 1.7 merge tracking aware merges raise an error if the
+  # merge target has subtrees missing due to a shell delete.  To
+  # preserve the original intent of this test we'll run the merge
+  # with the --ignore-ancestry option, which neither considers nor
+  # records mergeinfo.  With this option the merge should "succeed"
+  # while skipping the missing paths.  Of course with no mergeinfo
+  # recorded and everything skipped, there is nothing to commit, so
+  # unlike most of the tree conflict tests we don't bother with the
+  # final commit step.
+
+  sbox.build()
   expected_output = wc.State('', {
   })
 
-  expected_disk = state_after_tree_del
+  expected_disk = disk_after_tree_del
 
+  # Don't expect any mergeinfo property changes because we run
+  # the merge with the --ignore-ancestry option.
   expected_status = svntest.wc.State('', {
-    ''                  : Item(status=' M', wc_rev=3),
+    ''                  : Item(status='  ', wc_rev=3),
     'F'                 : Item(status='  ', wc_rev=3),
-    'F/alpha'           : Item(status='!M', wc_rev=3),
+    'F/alpha'           : Item(status='! ', wc_rev=3),
     'D'                 : Item(status='  ', wc_rev=3),
     'D/D1'              : Item(status='! ', wc_rev='?'),
     'DF'                : Item(status='  ', wc_rev=3),
@@ -1383,6 +1387,19 @@ def tree_conflicts_merge_del_onto_missin
     'DDD/D1/D2/D3'      : Item(status='  '),
     })
 
+  if svntest.main.wc_is_singledb(sbox.wc_dir):
+    expected_status.tweak('D/D1',            wc_rev=3)
+    expected_status.tweak('DF/D1',           wc_rev=3)
+    expected_status.tweak('DF/D1/beta',      wc_rev=3, status='! ')
+    expected_status.tweak('DD/D1',           wc_rev=3)
+    expected_status.tweak('DD/D1/D2',        wc_rev=3, status='! ')
+    expected_status.tweak('DDF/D1',          wc_rev=3)
+    expected_status.tweak('DDF/D1/D2',       wc_rev=3, status='! ')
+    expected_status.tweak('DDF/D1/D2/gamma', wc_rev=3, status='! ')
+    expected_status.tweak('DDD/D1',          wc_rev=3)
+    expected_status.tweak('DDD/D1/D2',       wc_rev=3, status='! ')
+    expected_status.tweak('DDD/D1/D2/D3',    wc_rev=3, status='! ')
+
   expected_skip = svntest.wc.State('', {
     'F/alpha'           : Item(),
     'D/D1'              : Item(),
@@ -1397,18 +1414,7 @@ def tree_conflicts_merge_del_onto_missin
                expected_disk,
                expected_status,
                expected_skip,
-
-               ### This should not be happening!
-               ### The commit succeeds (it only commits mergeinfo).
-               ### But then the work queue freaks out while trying to install
-               ### F/alpha into the WC, because F/alpha is missing from disk.
-               ### We end up with a working copy that cannot be cleaned up.
-               ### To make this test pass for now we'll expect this error.
-               ### When the problem is fixed this test will start to fail
-               ### and should be adjusted.
-               commit_block_string=".*Error bumping revisions post-commit",
-
-             ) ], False)
+             ) ], False, do_commit_conflicts=False, ignore_ancestry=True)
 
 #----------------------------------------------------------------------
 def merge_replace_setup(sbox):
@@ -1891,7 +1897,7 @@ test_list = [ None,
               tree_conflicts_on_merge_local_ci_6,
               tree_conflicts_on_merge_no_local_ci_4_1,
               tree_conflicts_on_merge_no_local_ci_4_2,
-              XFail(tree_conflicts_on_merge_no_local_ci_5_1),
+              tree_conflicts_on_merge_no_local_ci_5_1,
               XFail(tree_conflicts_on_merge_no_local_ci_5_2),
               tree_conflicts_on_merge_no_local_ci_6,
               tree_conflicts_merge_edit_onto_missing,

Modified: subversion/branches/ignore-mergeinfo/subversion/tests/cmdline/patch_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/ignore-mergeinfo/subversion/tests/cmdline/patch_tests.py?rev=1044516&r1=1044515&r2=1044516&view=diff
==============================================================================
--- subversion/branches/ignore-mergeinfo/subversion/tests/cmdline/patch_tests.py (original)
+++ subversion/branches/ignore-mergeinfo/subversion/tests/cmdline/patch_tests.py Fri Dec 10 21:23:03 2010
@@ -2436,7 +2436,14 @@ def patch_same_twice(sbox):
     'G         %s\n' % os.path.join(wc_dir, 'A', 'D', 'gamma'),
     '>         hunk @@ -1,1 +1,1 @@ already applied\n',
     'G         %s\n' % os.path.join(wc_dir, 'iota'),
-    '>         hunk @@ -1,1 +1,2 @@ already applied\n',
+    # The iota patch inserts a line after the first line in the file,
+    # with no trailing context. Currently, Subversion applies this patch
+    # multiple times, which matches the behaviour of Larry Wall's patch
+    # implementation. A more complicated hunk matching algorithm is needed
+    # to detect the duplicate application in this case. GNU patch does detect
+    # the duplicate application. Should Subversion be taught to detect it,
+    # we need this line here:
+    # '>         hunk @@ -1,1 +1,2 @@ already applied\n',
     'G         %s\n' % os.path.join(wc_dir, 'new'),
     '>         hunk @@ -0,0 +1,1 @@ already applied\n',
     'G         %s\n' % os.path.join(wc_dir, 'A', 'mu'),
@@ -2449,6 +2456,10 @@ def patch_same_twice(sbox):
 
   expected_skip = wc.State('', {beta_path : Item()})
 
+  # See above comment about the iota patch being applied twice.
+  iota_contents += "Some more bytes\n"
+  expected_disk.tweak('iota', contents=iota_contents)
+
   svntest.actions.run_and_verify_patch(wc_dir, os.path.abspath(patch_file_path),
                                        expected_output,
                                        expected_disk,
@@ -2603,7 +2614,8 @@ def patch_add_path_with_props(sbox):
   expected_disk = svntest.main.greek_state.copy()
   expected_disk.add({'new': Item(contents="This is the file 'new'\n", 
                                  props={'added' : added_prop_contents})})
-  expected_disk.add({'X': Item(props={'added' : added_prop_contents})})
+  expected_disk.add({'X': Item(contents="",
+                               props={'added' : added_prop_contents})})
   expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
   expected_status.add({'new': Item(status='A ', wc_rev='0')})
   expected_status.add({'X': Item(status='A ', wc_rev='0')})
@@ -2975,6 +2987,370 @@ def patch_prop_with_fuzz(sbox):
                                        1, # check-props
                                        1) # dry-run
 
+def patch_git_add_file(sbox):
+  "patch that contains empty files"
+
+  sbox.build()
+  wc_dir = sbox.wc_dir
+  patch_file_path = make_patch_path(sbox)
+
+  new_path = os.path.join(wc_dir, 'new')
+
+  unidiff_patch = [
+    "Index: new\n",
+    "===================================================================\n",
+    "diff --git a/new b/new\n",
+    "new file mode 10644\n",
+  ]
+
+  svntest.main.file_write(patch_file_path, ''.join(unidiff_patch))
+
+  expected_output = [
+    'A         %s\n' % os.path.join(wc_dir, 'new'),
+  ]
+  expected_disk = svntest.main.greek_state.copy()
+  expected_disk.add({'new' : Item(contents="")})
+
+  expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
+  expected_status.add({'new' : Item(status='A ', wc_rev=0)})
+
+  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
+
+def patch_old_target_names(sbox):
+  "patch using old target names"
+
+  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)
+
+  # Apply patch
+
+  unidiff_patch = [
+    "--- A/mu	2009-06-24 15:23:55.000000000 +0100\n",
+    "+++ A/mu.new	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', 'mu'),
+  ]
+
+  expected_disk = svntest.main.greek_state.copy()
+  expected_disk.tweak('A/mu', contents=''.join(mu_contents))
+
+  expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
+  expected_status.tweak('A/mu', status='M ', 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
+                                       "--old-patch-target-names")
+
+def patch_reverse_revert(sbox):
+  "revert a patch by reverse patching"
+
+  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_pre_patch = [
+    "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_pre_patch), 'wb')
+  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)
+
+  # Apply patch
+
+  unidiff_patch = [
+    "Index: A/D/gamma\n",
+    "===================================================================\n",
+    "--- A/D/gamma\t(revision 1)\n",
+    "+++ A/D/gamma\t(working copy)\n",
+    "@@ -1 +1 @@\n",
+    "-This is the file 'gamma'.\n",
+    "+It is the file 'gamma'.\n",
+    "Index: iota\n",
+    "===================================================================\n",
+    "--- iota\t(revision 1)\n",
+    "+++ iota\t(working copy)\n",
+    "@@ -1 +1,2 @@\n",
+    " This is the file 'iota'.\n",
+    "+Some more bytes\n",
+    "\n",
+    "Index: new\n",
+    "===================================================================\n",
+    "--- new	(revision 0)\n",
+    "+++ new	(revision 0)\n",
+    "@@ -0,0 +1 @@\n",
+    "+new\n",
+    "\n",
+    "--- 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",
+    "Index: A/B/E/beta\n",
+    "===================================================================\n",
+    "--- A/B/E/beta	(revision 1)\n",
+    "+++ A/B/E/beta	(working copy)\n",
+    "@@ -1 +0,0 @@\n",
+    "-This is the file 'beta'.\n",
+  ]
+
+  svntest.main.file_write(patch_file_path, ''.join(unidiff_patch), 'wb')
+
+  gamma_contents = "It is the file 'gamma'.\n"
+  iota_contents = "This is the file 'iota'.\nSome more bytes\n"
+  new_contents = "new\n"
+  mu_contents_post_patch = [
+    "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', 'D', 'gamma'),
+    'U         %s\n' % os.path.join(wc_dir, 'iota'),
+    'A         %s\n' % os.path.join(wc_dir, 'new'),
+    'U         %s\n' % os.path.join(wc_dir, 'A', 'mu'),
+    'D         %s\n' % os.path.join(wc_dir, 'A', 'B', 'E', 'beta'),
+  ]
+
+  expected_disk = svntest.main.greek_state.copy()
+  expected_disk.tweak('A/D/gamma', contents=gamma_contents)
+  expected_disk.tweak('iota', contents=iota_contents)
+  expected_disk.add({'new' : Item(contents=new_contents)})
+  expected_disk.tweak('A/mu', contents=''.join(mu_contents_post_patch))
+  expected_disk.remove('A/B/E/beta')
+
+  expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
+  expected_status.tweak('A/D/gamma', status='M ')
+  expected_status.tweak('iota', status='M ')
+  expected_status.add({'new' : Item(status='A ', wc_rev=0)})
+  expected_status.tweak('A/mu', status='M ', wc_rev=2)
+  expected_status.tweak('A/B/E/beta', status='D ')
+
+  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
+
+  # Applying the same patch in reverse should undo local mods
+  expected_output = [
+    'G         %s\n' % os.path.join(wc_dir, 'A', 'D', 'gamma'),
+    'G         %s\n' % os.path.join(wc_dir, 'iota'),
+    'D         %s\n' % os.path.join(wc_dir, 'new'),
+    'G         %s\n' % os.path.join(wc_dir, 'A', 'mu'),
+    'A         %s\n' % os.path.join(wc_dir, 'A', 'B', 'E', 'beta'),
+  ]
+  expected_disk = svntest.main.greek_state.copy()
+  expected_disk.tweak('A/mu', contents=''.join(mu_contents_pre_patch))
+
+  expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
+  expected_status.tweak('A/mu', wc_rev=2)
+
+  ### svn patch should check whether the deleted file has the same
+  ### content as the file added by the patch and revert the deletion
+  ### instead of causing a replacement.
+  expected_status.tweak('A/B/E/beta', status='R ')
+
+  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',
+                                       '--old-patch-target-names')
+
 ########################################################################
 #Run the tests
 
@@ -3001,9 +3377,12 @@ test_list = [ None,
               patch_with_properties,
               patch_same_twice,
               XFail(patch_dir_properties),
-              XFail(patch_add_path_with_props),
+              patch_add_path_with_props,
               patch_prop_offset,
               patch_prop_with_fuzz,
+              patch_git_add_file,
+              patch_old_target_names,
+              patch_reverse_revert,
             ]
 
 if __name__ == '__main__':

Modified: subversion/branches/ignore-mergeinfo/subversion/tests/cmdline/resolve_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/ignore-mergeinfo/subversion/tests/cmdline/resolve_tests.py?rev=1044516&r1=1044515&r2=1044516&view=diff
==============================================================================
--- subversion/branches/ignore-mergeinfo/subversion/tests/cmdline/resolve_tests.py (original)
+++ subversion/branches/ignore-mergeinfo/subversion/tests/cmdline/resolve_tests.py Fri Dec 10 21:23:03 2010
@@ -95,17 +95,158 @@ def automatic_conflict_resolution(sbox):
   # Test 'svn resolve -R --accept theirs-full'
   do_text_conflicting_merge()
   svntest.actions.run_and_verify_resolve([psi_COPY_path],
-                                         '-R', '--accept', 'theirs-full',
+                                         '-R', '--accept', 'tf',
                                          A_COPY_path)
   wc_disk.tweak('A_COPY/D/H/psi', contents="New content")
   svntest.actions.verify_disk(wc_dir, wc_disk)
 
+#----------------------------------------------------------------------
+# Test for issue #3707 'property conflicts not handled correctly by
+# svn resolve'.
+def prop_conflict_resolution(sbox):
+  "resolving prop conflicts"
+
+  sbox.build()
+  wc_dir = sbox.wc_dir
+
+  # Some paths we'll care about
+  iota_path  = os.path.join(wc_dir, "iota")
+  mu_path    = os.path.join(wc_dir, "A", "mu")
+  gamma_path = os.path.join(wc_dir, "A", "D", "gamma")
+  psi_path   = os.path.join(wc_dir, "A", "D", "H", "psi")
+  
+  # r2 - Set property 'propname:propval' on iota, A/mu, and A/D/gamma.
+  svntest.actions.run_and_verify_svn(None, None, [],
+                                     'ps', 'propname', 'propval',
+                                     iota_path, mu_path, gamma_path)
+  svntest.actions.run_and_verify_svn(None, None, [], 'commit',
+                                     '-m', 'create some new properties',
+                                     wc_dir)
+
+  # r3 - Make some changes to the props from r2:
+  #
+  #   iota      : Delete property 'propname'
+  #   A/mu      : Change property 'propname' to 'incoming-conflict'
+  #   A/D/gamma : Change property 'propname' to 'incoming-no-conflict'
+  svntest.actions.run_and_verify_svn(None, None, [],
+                                     'pd', 'propname', iota_path)
+  svntest.actions.run_and_verify_svn(None, None, [],
+                                     'ps', 'propname', 'incoming-conflict',
+                                     mu_path)
+  svntest.actions.run_and_verify_svn(None, None, [],
+                                     'ps', 'propname', 'incoming-no-conflict',
+                                     gamma_path)
+  svntest.actions.run_and_verify_svn(None, None, [],
+                                     'commit', '-m', 'delete a property',
+                                     wc_dir)
+
+  def do_prop_conflicting_up_and_resolve(resolve_accept,
+                                         resolved_deleted_prop_val_output,
+                                         resolved_edited_prop_val_output):
+
+    """Revert the WC, update it to r2, and set the following properties:
+
+    itoa      : 'propname' = 'local_edit'
+                'newprop'  = 'new-val-no-incoming' 
+    A/mu      : 'propname' = 'local_edit'
+    A/D/gamma : 'propname' = 'incoming-no-conflict'
+    A/D/H/psi : 'newprop'  = 'new-val-no-incoming'
+
+    Update the WC, postponing conflicts, then run svn resolve -R
+    --accept=RESOLVE_ACCEPT.
+
+    Using svn propget, check that the resolution results in the following
+    properties:
+
+    itoa      : 'propname' = RESOLVED_EDITED_PROP_VAL_OUTPUT
+                'newprop'  = 'new-val-no-incoming' 
+    A/mu      : 'propname' = RESOLVED_DELETED_PROP_VAL_OUTPUT
+    A/D/gamma : 'propname' = 'incoming-no-conflict'
+    A/D/H/psi : 'newprop'  = 'new-val-no-incoming'
+
+    RESOLVED_DELETED_PROP_VAL_OUTPUT and RESOLVED_EDITED_PROP_VAL_OUTPUT
+    both follow the rules for the expected_stdout arg to
+    run_and_verify_svn2()"""
+
+    svntest.actions.run_and_verify_svn(None, None, [],
+                                       'revert', '--recursive', wc_dir)
+    svntest.actions.run_and_verify_svn(None, None, [], 'up', '-r2', wc_dir)
+
+    # Set some properties that will conflict when we update.
+    svntest.actions.run_and_verify_svn(None, None, [], 'ps',
+                                       'propname', 'local_edit',
+                                       iota_path, mu_path)
+
+    # Set a property that should always merge cleanly with the update.
+    svntest.actions.run_and_verify_svn(None, None, [], 'ps',
+                                       'propname', 'incoming-no-conflict',
+                                       gamma_path)
+
+    # Set a property that has no update coming.
+    svntest.actions.run_and_verify_svn(None, None, [], 'ps',
+                                       'newprop', 'new-val-no-incoming',
+                                       psi_path,
+                                       iota_path)
+
+    # 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',
+                                           '--accept', resolve_accept, wc_dir)
+    svntest.actions.run_and_verify_svn(
+      'svn revolve -R --accept=' + resolve_accept + ' of prop conflict '
+      'not resolved as expected;',
+      resolved_deleted_prop_val_output, [], 'pg', 'propname', iota_path)
+    svntest.actions.run_and_verify_svn(
+      'svn revolve -R --accept=' + resolve_accept + ' of prop conflict '
+      'not resolved as expected;',
+      ['new-val-no-incoming\n'], [], 'pg', 'newprop', iota_path)
+    svntest.actions.run_and_verify_svn(
+      'svn revolve -R --accept=' + resolve_accept + ' of prop conflict '
+      'not resolved as expected;',
+      resolved_edited_prop_val_output, [], 'pg', 'propname', mu_path)
+    svntest.actions.run_and_verify_svn(
+      'svn revolve -R --accept=' + resolve_accept + ' modified a '
+      'non-conflicted property',
+      ['incoming-no-conflict\n'], [], 'pg', 'propname', gamma_path)
+    svntest.actions.run_and_verify_svn(
+      'svn revolve -R --accept=' + resolve_accept + ' modified a '
+      'non-conflicted property',
+      ['new-val-no-incoming\n'], [], 'pg', 'newprop', psi_path)
+
+  # Test how svn resolve deals with prop conflicts and other local
+  # prop changes:
+  #
+  #   1) 'iota' - An incoming prop delete on a local prop modification.
+  #   2) 'A/mu' - An incoming prop edit on a local prop modification.
+  #   3) 'A/D/gamma' - An local, non-conflicted prop edit
+  #
+  # This currently fails because svn resolve --accept=[theirs-conflict |
+  # theirs-full] removes the conflicts, but doesn't install 'their' version
+  # of the conflicted properties.
+  do_prop_conflicting_up_and_resolve('mine-full',
+                                     ['local_edit\n'],
+                                     ['local_edit\n'])
+  do_prop_conflicting_up_and_resolve('mine-conflict',
+                                     ['local_edit\n'],
+                                     ['local_edit\n'])
+  do_prop_conflicting_up_and_resolve('working',
+                                    ['local_edit\n'],
+                                     ['local_edit\n'])
+  do_prop_conflicting_up_and_resolve('theirs-conflict',
+                                     [], # Prop deleted
+                                     ['incoming-conflict\n'])
+  do_prop_conflicting_up_and_resolve('theirs-full',
+                                     [], # Prop deleted
+                                     ['incoming-conflict\n'])
+
 ########################################################################
 # Run the tests
 
 # list all tests here, starting with None:
 test_list = [ None,
               automatic_conflict_resolution,
+              XFail(prop_conflict_resolution),
              ]
 
 if __name__ == '__main__':

Modified: subversion/branches/ignore-mergeinfo/subversion/tests/cmdline/resolved_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/ignore-mergeinfo/subversion/tests/cmdline/resolved_tests.py?rev=1044516&r1=1044515&r2=1044516&view=diff
==============================================================================
--- subversion/branches/ignore-mergeinfo/subversion/tests/cmdline/resolved_tests.py (original)
+++ subversion/branches/ignore-mergeinfo/subversion/tests/cmdline/resolved_tests.py Fri Dec 10 21:23:03 2010
@@ -37,8 +37,7 @@ SkipUnless = svntest.testcase.SkipUnless
 XFail = svntest.testcase.XFail
 Item = svntest.wc.StateItem
 
-from svntest.main import SVN_PROP_MERGEINFO, server_sends_copyfrom_on_update, \
-  server_has_mergeinfo
+from svntest.main import SVN_PROP_MERGEINFO, server_has_mergeinfo
 
 ######################################################################
 # Tests

Modified: subversion/branches/ignore-mergeinfo/subversion/tests/cmdline/revert_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/ignore-mergeinfo/subversion/tests/cmdline/revert_tests.py?rev=1044516&r1=1044515&r2=1044516&view=diff
==============================================================================
--- subversion/branches/ignore-mergeinfo/subversion/tests/cmdline/revert_tests.py (original)
+++ subversion/branches/ignore-mergeinfo/subversion/tests/cmdline/revert_tests.py Fri Dec 10 21:23:03 2010
@@ -851,29 +851,37 @@ def status_of_missing_dir_after_revert_r
                   os.path.join(G_path, 'alpha'),
                   os.path.join(G_path, 'beta')]
 
+  if svntest.main.wc_is_singledb(wc_dir):
+    # These nodes are not lost in single-db
+    revert_paths += [ os.path.join(G_path, 'pi'),
+                      os.path.join(G_path, 'rho'),
+                      os.path.join(G_path, 'tau')]
+
   expected_output = svntest.verify.UnorderedOutput([
     "Reverted '%s'\n" % path for path in revert_paths])
 
   svntest.actions.run_and_verify_svn(None, expected_output, [], "revert", "-R",
                                      G_path)
 
-  ### GS (Oct 11): this is stupid. after a revert, there should be
-  ###              *NO* status whatsoever. ugh. this status behavior
-  ###              has been twiddled over the 1.6/1.7 dev cycle, but
-  ###              it "should" just disappear.
 
-  ### Is it a bug that we'd need to run revert twice to finish the job?
+  # Revert leaves these added nodes as unversioned
   expected_output = svntest.verify.UnorderedOutput(
-    ["A       " + os.path.join(G_path, "pi") + "\n",
-     "A       " + os.path.join(G_path, "rho") + "\n",
-     "A       " + os.path.join(G_path, "tau") + "\n"])
+    ["?       " + 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, [],
                                      "status", wc_dir)
 
   svntest.main.safe_rmtree(G_path)
 
-  expected_output = svntest.verify.UnorderedOutput(
-    ["!       " + G_path + "\n"])
+  if svntest.main.wc_is_singledb(wc_dir):
+    expected_output = svntest.verify.UnorderedOutput(
+      ["!       " + G_path + "\n",
+       "!       " + os.path.join(G_path, "alpha") + "\n",
+       "!       " + os.path.join(G_path, "beta") + "\n"])
+  else:
+    expected_output = svntest.verify.UnorderedOutput(
+      ["!       " + G_path + "\n"])
   svntest.actions.run_and_verify_svn(None, expected_output, [], "status",
                                      wc_dir)
 
@@ -989,6 +997,49 @@ def revert_add_over_not_present_dir(sbox
   svntest.actions.run_and_verify_status(wc_dir, expected_status)
 
 
+def revert_added_tree(sbox):
+  "revert an added tree fails"
+
+  sbox.build()
+  wc_dir = sbox.wc_dir
+  svntest.actions.run_and_verify_svn(None, None, [],
+                                     'mkdir', sbox.ospath('X'), sbox.ospath('X/Y'))
+  expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
+  expected_status.add({
+    'X'   : Item(status='A ', wc_rev=0),
+    'X/Y' : Item(status='A ', wc_rev=0),
+    })
+  svntest.actions.run_and_verify_status(wc_dir, expected_status)
+
+  # Revert is non-recursive and fails, status is unchanged
+  expected_error = '.*Try \'svn revert --depth infinity\'.*'
+  svntest.actions.run_and_verify_svn(None, None, expected_error,
+                                     'revert', sbox.ospath('X'))
+  svntest.actions.run_and_verify_status(wc_dir, expected_status)
+
+
+def revert_child_of_copy(sbox):
+  "revert a child of a copied directory does nothing"
+
+  sbox.build()
+  wc_dir = sbox.wc_dir
+  svntest.actions.run_and_verify_svn(None, None, [],
+                                     'cp', sbox.ospath('A/B/E'), sbox.ospath('A/B/E2'))
+
+  expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
+  expected_status.add({
+    'A/B/E2'       : Item(status='A ', copied='+', wc_rev='-'),
+    'A/B/E2/alpha' : Item(status='  ', copied='+', wc_rev='-'),
+    'A/B/E2/beta'  : Item(status='  ', copied='+', wc_rev='-'),
+    })
+  svntest.actions.run_and_verify_status(wc_dir, expected_status)
+
+  # Revert of child of copy does nothing, status is unchanged
+  svntest.actions.run_and_verify_svn(None, None, [],
+                                     'revert', sbox.ospath('A/B/E2/beta'))
+  svntest.actions.run_and_verify_status(wc_dir, expected_status)
+
+
 ########################################################################
 # Run the tests
 
@@ -1011,11 +1062,12 @@ test_list = [ None,
               revert_propdel__file,
               revert_replaced_with_history_file_1,
               status_of_missing_dir_after_revert,
-              Wimp("revert behavior needs better definition",
-                   status_of_missing_dir_after_revert_replaced_with_history_dir),
+              status_of_missing_dir_after_revert_replaced_with_history_dir,
               revert_replaced_with_history_file_2,
               revert_tree_conflicts_in_updated_files,
               revert_add_over_not_present_dir,
+              revert_added_tree,
+              revert_child_of_copy,
              ]
 
 if __name__ == '__main__':

Modified: subversion/branches/ignore-mergeinfo/subversion/tests/cmdline/schedule_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/ignore-mergeinfo/subversion/tests/cmdline/schedule_tests.py?rev=1044516&r1=1044515&r2=1044516&view=diff
==============================================================================
--- subversion/branches/ignore-mergeinfo/subversion/tests/cmdline/schedule_tests.py (original)
+++ subversion/branches/ignore-mergeinfo/subversion/tests/cmdline/schedule_tests.py Fri Dec 10 21:23:03 2010
@@ -706,7 +706,7 @@ test_list = [ None,
               SkipUnless(revert_add_executable, svntest.main.is_posix_os),
               revert_delete_files,
               revert_delete_dirs,
-              Wimp('Needs single-db', unschedule_missing_added),
+              unschedule_missing_added,
               delete_missing,
               revert_inside_newly_added_dir,
               status_add_deleted_directory,